Add API scaffolding for number verification
Add the PhoneNumberRange and NumberVerificationCallback classes. Add a method in TelephonyManager to activate the API, but it does nothing for now. Bug: 119675160 Test: todo Change-Id: I3ccd62b47f02a3aa324b675fdb16c8e7a1e9feec
This commit is contained in:
parent
bfd3237eac
commit
5314036bb1
@ -544,6 +544,7 @@ java_defaults {
|
||||
"telephony/java/com/android/internal/telephony/IApnSourceService.aidl",
|
||||
"telephony/java/com/android/internal/telephony/ICarrierConfigLoader.aidl",
|
||||
"telephony/java/com/android/internal/telephony/IMms.aidl",
|
||||
"telephony/java/com/android/internal/telephony/INumberVerificationCallback.aidl",
|
||||
"telephony/java/com/android/internal/telephony/IOnSubscriptionsChangedListener.aidl",
|
||||
"telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl",
|
||||
"telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl",
|
||||
|
@ -4466,8 +4466,8 @@ package android.service.carrier {
|
||||
|
||||
public abstract class ApnService extends android.app.Service {
|
||||
ctor public ApnService();
|
||||
method public abstract java.util.List<android.content.ContentValues> onRestoreApns(int);
|
||||
method public android.os.IBinder onBind(android.content.Intent);
|
||||
method public abstract java.util.List<android.content.ContentValues> onRestoreApns(int);
|
||||
}
|
||||
|
||||
}
|
||||
@ -5181,6 +5181,26 @@ package android.telephony {
|
||||
field public static final int RESULT_SUCCESS = 0; // 0x0
|
||||
}
|
||||
|
||||
public abstract interface NumberVerificationCallback {
|
||||
method public default void onCallReceived(java.lang.String);
|
||||
method public default void onVerificationFailed(int);
|
||||
field public static final int REASON_CONCURRENT_REQUESTS = 4; // 0x4
|
||||
field public static final int REASON_IN_ECBM = 5; // 0x5
|
||||
field public static final int REASON_IN_EMERGENCY_CALL = 6; // 0x6
|
||||
field public static final int REASON_NETWORK_NOT_AVAILABLE = 2; // 0x2
|
||||
field public static final int REASON_TIMED_OUT = 1; // 0x1
|
||||
field public static final int REASON_TOO_MANY_CALLS = 3; // 0x3
|
||||
field public static final int REASON_UNSPECIFIED = 0; // 0x0
|
||||
}
|
||||
|
||||
public final class PhoneNumberRange implements android.os.Parcelable {
|
||||
ctor public PhoneNumberRange(java.lang.String, java.lang.String, java.lang.String, java.lang.String);
|
||||
method public int describeContents();
|
||||
method public boolean matches(java.lang.String);
|
||||
method public void writeToParcel(android.os.Parcel, int);
|
||||
field public static final android.os.Parcelable.Creator<android.telephony.PhoneNumberRange> CREATOR;
|
||||
}
|
||||
|
||||
public class PhoneStateListener {
|
||||
method public void onRadioPowerStateChanged(int);
|
||||
method public void onSrvccStateChanged(int);
|
||||
@ -5345,6 +5365,7 @@ package android.telephony {
|
||||
method public boolean needsOtaServiceProvisioning();
|
||||
method public boolean rebootRadio();
|
||||
method public void requestCellInfoUpdate(android.os.WorkSource, java.util.concurrent.Executor, android.telephony.TelephonyManager.CellInfoCallback);
|
||||
method public void requestNumberVerification(android.telephony.PhoneNumberRange, long, java.util.concurrent.Executor, android.telephony.NumberVerificationCallback);
|
||||
method public boolean resetRadioConfig();
|
||||
method public int setAllowedCarriers(int, java.util.List<android.service.carrier.CarrierIdentifier>);
|
||||
method public void setCarrierDataEnabled(boolean);
|
||||
@ -5374,6 +5395,7 @@ package android.telephony {
|
||||
field public static final java.lang.String EXTRA_SIM_STATE = "android.telephony.extra.SIM_STATE";
|
||||
field public static final java.lang.String EXTRA_VISUAL_VOICEMAIL_ENABLED_BY_USER_BOOL = "android.telephony.extra.VISUAL_VOICEMAIL_ENABLED_BY_USER_BOOL";
|
||||
field public static final java.lang.String EXTRA_VOICEMAIL_SCRAMBLED_PIN_STRING = "android.telephony.extra.VOICEMAIL_SCRAMBLED_PIN_STRING";
|
||||
field public static final long MAX_NUMBER_VERIFICATION_TIMEOUT_MILLIS = 60000L; // 0xea60L
|
||||
field public static final int NETWORK_MODE_CDMA_EVDO = 4; // 0x4
|
||||
field public static final int NETWORK_MODE_CDMA_NO_EVDO = 5; // 0x5
|
||||
field public static final int NETWORK_MODE_EVDO_NO_CDMA = 6; // 0x6
|
||||
|
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.telephony;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.SystemApi;
|
||||
|
||||
/**
|
||||
* A callback for number verification. After a request for number verification is received,
|
||||
* the system will call {@link #onCallReceived(String)} if a phone call was received from a number
|
||||
* matching the provided {@link PhoneNumberRange} or it will call {@link #onVerificationFailed(int)}
|
||||
* if an error occurs.
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi
|
||||
public interface NumberVerificationCallback {
|
||||
/** @hide */
|
||||
@IntDef(value = {REASON_UNSPECIFIED, REASON_TIMED_OUT, REASON_NETWORK_NOT_AVAILABLE,
|
||||
REASON_TOO_MANY_CALLS, REASON_CONCURRENT_REQUESTS, REASON_IN_ECBM,
|
||||
REASON_IN_EMERGENCY_CALL},
|
||||
prefix = {"REASON_"})
|
||||
@interface NumberVerificationFailureReason {}
|
||||
|
||||
/**
|
||||
* Verification failed for an unspecified reason.
|
||||
*/
|
||||
int REASON_UNSPECIFIED = 0;
|
||||
|
||||
/**
|
||||
* Verification failed because no phone call was received from a matching number within the
|
||||
* provided timeout.
|
||||
*/
|
||||
int REASON_TIMED_OUT = 1;
|
||||
|
||||
/**
|
||||
* Verification failed because no cellular voice network is available.
|
||||
*/
|
||||
int REASON_NETWORK_NOT_AVAILABLE = 2;
|
||||
|
||||
/**
|
||||
* Verification failed because there are currently too many ongoing phone calls for a new
|
||||
* incoming phone call to be received.
|
||||
*/
|
||||
int REASON_TOO_MANY_CALLS = 3;
|
||||
|
||||
/**
|
||||
* Verification failed because a previous request for verification has not yet completed.
|
||||
*/
|
||||
int REASON_CONCURRENT_REQUESTS = 4;
|
||||
|
||||
/**
|
||||
* Verification failed because the phone is in emergency callback mode.
|
||||
*/
|
||||
int REASON_IN_ECBM = 5;
|
||||
|
||||
/**
|
||||
* Verification failed because the phone is currently in an emergency call.
|
||||
*/
|
||||
int REASON_IN_EMERGENCY_CALL = 6;
|
||||
|
||||
/**
|
||||
* Called when the device receives a phone call from the provided {@link PhoneNumberRange}.
|
||||
* @param phoneNumber The phone number within the range that called. May or may not contain the
|
||||
* country code, but will be entirely numeric.
|
||||
*/
|
||||
default void onCallReceived(@NonNull String phoneNumber) { }
|
||||
|
||||
/**
|
||||
* Called when verification fails for some reason.
|
||||
* @param reason The reason for failure.
|
||||
*/
|
||||
default void onVerificationFailed(@NumberVerificationFailureReason int reason) { }
|
||||
}
|
19
telephony/java/android/telephony/PhoneNumberRange.aidl
Normal file
19
telephony/java/android/telephony/PhoneNumberRange.aidl
Normal file
@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.telephony;
|
||||
|
||||
parcelable PhoneNumberRange;
|
176
telephony/java/android/telephony/PhoneNumberRange.java
Normal file
176
telephony/java/android/telephony/PhoneNumberRange.java
Normal file
@ -0,0 +1,176 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.telephony;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.SystemApi;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* This class is used to represent a range of phone numbers. Each range corresponds to a contiguous
|
||||
* block of phone numbers.
|
||||
*
|
||||
* Example:
|
||||
* {@code
|
||||
* {
|
||||
* mCountryCode = "1"
|
||||
* mPrefix = "650555"
|
||||
* mLowerBound = "0055"
|
||||
* mUpperBound = "0899"
|
||||
* }
|
||||
* }
|
||||
* would match 16505550089 and 6505550472, but not 63827593759 or 16505550900
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi
|
||||
public final class PhoneNumberRange implements Parcelable {
|
||||
public static final Creator<PhoneNumberRange> CREATOR = new Creator<PhoneNumberRange>() {
|
||||
@Override
|
||||
public PhoneNumberRange createFromParcel(Parcel in) {
|
||||
return new PhoneNumberRange(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PhoneNumberRange[] newArray(int size) {
|
||||
return new PhoneNumberRange[size];
|
||||
}
|
||||
};
|
||||
|
||||
private final String mCountryCode;
|
||||
private final String mPrefix;
|
||||
private final String mLowerBound;
|
||||
private final String mUpperBound;
|
||||
|
||||
/**
|
||||
* @param countryCode The country code, omitting the leading "+"
|
||||
* @param prefix A prefix that all numbers matching the range must have.
|
||||
* @param lowerBound When concatenated with the prefix, represents the lower bound of phone
|
||||
* numbers that match this range.
|
||||
* @param upperBound When concatenated with the prefix, represents the upper bound of phone
|
||||
* numbers that match this range.
|
||||
*/
|
||||
public PhoneNumberRange(@NonNull String countryCode, @NonNull String prefix,
|
||||
@NonNull String lowerBound, @NonNull String upperBound) {
|
||||
validateLowerAndUpperBounds(lowerBound, upperBound);
|
||||
if (!Pattern.matches("[0-9]+", countryCode)) {
|
||||
throw new IllegalArgumentException("Country code must be all numeric");
|
||||
}
|
||||
if (!Pattern.matches("[0-9]+", prefix)) {
|
||||
throw new IllegalArgumentException("Prefix must be all numeric");
|
||||
}
|
||||
mCountryCode = countryCode;
|
||||
mPrefix = prefix;
|
||||
mLowerBound = lowerBound;
|
||||
mUpperBound = upperBound;
|
||||
}
|
||||
|
||||
private PhoneNumberRange(Parcel in) {
|
||||
mCountryCode = in.readStringNoHelper();
|
||||
mPrefix = in.readStringNoHelper();
|
||||
mLowerBound = in.readStringNoHelper();
|
||||
mUpperBound = in.readStringNoHelper();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeStringNoHelper(mCountryCode);
|
||||
dest.writeStringNoHelper(mPrefix);
|
||||
dest.writeStringNoHelper(mLowerBound);
|
||||
dest.writeStringNoHelper(mUpperBound);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
PhoneNumberRange that = (PhoneNumberRange) o;
|
||||
return Objects.equals(mCountryCode, that.mCountryCode)
|
||||
&& Objects.equals(mPrefix, that.mPrefix)
|
||||
&& Objects.equals(mLowerBound, that.mLowerBound)
|
||||
&& Objects.equals(mUpperBound, that.mUpperBound);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(mCountryCode, mPrefix, mLowerBound, mUpperBound);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PhoneNumberRange{"
|
||||
+ "mCountryCode='" + mCountryCode + '\''
|
||||
+ ", mPrefix='" + mPrefix + '\''
|
||||
+ ", mLowerBound='" + mLowerBound + '\''
|
||||
+ ", mUpperBound='" + mUpperBound + '\''
|
||||
+ '}';
|
||||
}
|
||||
|
||||
private void validateLowerAndUpperBounds(String lowerBound, String upperBound) {
|
||||
if (lowerBound.length() != upperBound.length()) {
|
||||
throw new IllegalArgumentException("Lower and upper bounds must have the same length");
|
||||
}
|
||||
if (!Pattern.matches("[0-9]+", lowerBound)) {
|
||||
throw new IllegalArgumentException("Lower bound must be all numeric");
|
||||
}
|
||||
if (!Pattern.matches("[0-9]+", upperBound)) {
|
||||
throw new IllegalArgumentException("Upper bound must be all numeric");
|
||||
}
|
||||
if (Integer.parseInt(lowerBound) > Integer.parseInt(upperBound)) {
|
||||
throw new IllegalArgumentException("Lower bound must be lower than upper bound");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if the provided phone number matches this range.
|
||||
* @param number A phone number, with or without separators or a country code.
|
||||
* @return {@code true} if the number matches, {@code false} otherwise.
|
||||
*/
|
||||
public boolean matches(String number) {
|
||||
// Check the prefix, make sure it matches either with or without the country code.
|
||||
String normalizedNumber = number.replaceAll("[^0-9]", "");
|
||||
String prefixWithCountryCode = mCountryCode + mPrefix;
|
||||
String numberPostfix;
|
||||
if (normalizedNumber.startsWith(prefixWithCountryCode)) {
|
||||
numberPostfix = normalizedNumber.substring(prefixWithCountryCode.length());
|
||||
} else if (normalizedNumber.startsWith(mPrefix)) {
|
||||
numberPostfix = normalizedNumber.substring(mPrefix.length());
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Next check the postfix to make sure it lies within the bounds.
|
||||
try {
|
||||
int lower = Integer.parseInt(mLowerBound);
|
||||
int upper = Integer.parseInt(mUpperBound);
|
||||
int numberToCheck = Integer.parseInt(numberPostfix);
|
||||
return numberToCheck <= upper && numberToCheck >= lower;
|
||||
} catch (NumberFormatException e) {
|
||||
Log.e(PhoneNumberRange.class.getSimpleName(), "Invalid bounds or number.", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@ -77,6 +77,7 @@ import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.telecom.ITelecomService;
|
||||
import com.android.internal.telephony.CellNetworkScanResult;
|
||||
import com.android.internal.telephony.IAns;
|
||||
import com.android.internal.telephony.INumberVerificationCallback;
|
||||
import com.android.internal.telephony.IPhoneSubInfo;
|
||||
import com.android.internal.telephony.ITelephony;
|
||||
import com.android.internal.telephony.ITelephonyRegistry;
|
||||
@ -1332,6 +1333,13 @@ public class TelephonyManager {
|
||||
*/
|
||||
public static final String EXTRA_RECOVERY_ACTION = "recoveryAction";
|
||||
|
||||
/**
|
||||
* The max value for the timeout passed in {@link #requestNumberVerification}.
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi
|
||||
public static final long MAX_NUMBER_VERIFICATION_TIMEOUT_MILLIS = 60000;
|
||||
|
||||
//
|
||||
//
|
||||
// Device Info
|
||||
@ -5476,6 +5484,52 @@ public class TelephonyManager {
|
||||
return slotIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Request that the next incoming call from a number matching {@code range} be intercepted.
|
||||
*
|
||||
* This API is intended for OEMs to provide a service for apps to verify the device's phone
|
||||
* number. When called, the Telephony stack will store the provided {@link PhoneNumberRange} and
|
||||
* intercept the next incoming call from a number that lies within the range, within a timeout
|
||||
* specified by {@code timeoutMillis}.
|
||||
*
|
||||
* If such a phone call is received, the caller will be notified via
|
||||
* {@link NumberVerificationCallback#onCallReceived(String)} on the provided {@link Executor}.
|
||||
* If verification fails for any reason, the caller will be notified via
|
||||
* {@link NumberVerificationCallback#onVerificationFailed(int)}
|
||||
* on the provided {@link Executor}.
|
||||
*
|
||||
* In addition to the {@link Manifest.permission#MODIFY_PHONE_STATE} permission, callers of this
|
||||
* API must also be listed in the device configuration as an authorized app in
|
||||
* {@code packages/services/Telephony/res/values/config.xml} under the
|
||||
* {@code config_number_verification_package_name} key.
|
||||
*
|
||||
* @hide
|
||||
* @param range The range of phone numbers the caller expects a phone call from.
|
||||
* @param timeoutMillis The amount of time to wait for such a call, or
|
||||
* {@link #MAX_NUMBER_VERIFICATION_TIMEOUT_MILLIS}, whichever is lesser.
|
||||
* @param executor The {@link Executor} that callbacks should be executed on.
|
||||
* @param callback The callback to use for delivering results.
|
||||
*/
|
||||
@SystemApi
|
||||
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
|
||||
public void requestNumberVerification(@NonNull PhoneNumberRange range, long timeoutMillis,
|
||||
@NonNull @CallbackExecutor Executor executor,
|
||||
@NonNull NumberVerificationCallback callback) {
|
||||
INumberVerificationCallback internalCallback = new INumberVerificationCallback.Stub() {
|
||||
@Override
|
||||
public void onCallReceived(String phoneNumber) throws RemoteException {
|
||||
Binder.withCleanCallingIdentity(() -> callback.onCallReceived(phoneNumber));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onVerificationFailed(int reason) throws RemoteException {
|
||||
Binder.withCleanCallingIdentity(() -> callback.onVerificationFailed(reason));
|
||||
}
|
||||
};
|
||||
|
||||
// TODO -- call the aidl method
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a per-phone telephony property with the value specified.
|
||||
*
|
||||
|
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.internal.telephony;
|
||||
|
||||
oneway interface INumberVerificationCallback {
|
||||
void onCallReceived(String phoneNumber);
|
||||
void onVerificationFailed(int reason);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user