Merge "Add API to support async network scans."

am: 625d5a9dd9

Change-Id: Iac369e26f707e59095ae7a89bfb11324e12634dc
This commit is contained in:
Ying Xu
2017-05-15 17:04:43 +00:00
committed by android-build-merger
9 changed files with 775 additions and 0 deletions

View File

@@ -0,0 +1,83 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.telephony;
import android.content.Context;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.Log;
import com.android.internal.telephony.ITelephony;
/**
* Allows applications to request the system to perform a network scan.
*
* The caller of {@link #requestNetworkScan(NetworkScanRequest, NetworkScanCallback)} will
* receive a NetworkScan which contains the callback method to stop the scan requested.
* @hide
*/
public class NetworkScan {
public static final String TAG = "NetworkScan";
public static final int SUCCESS = 0;
public static final int ERROR_INVALID_SCAN = 1;
public static final int ERROR_UNSUPPORTED = 2;
public static final int ERROR_INTERRUPTED = 3;
public static final int ERROR_CANCELLED = 4;
private final int mScanId;
private final int mSubId;
/**
* Stops the network scan
*
* This is the callback method to stop an ongoing scan. When user requests a new scan,
* a NetworkScan object will be returned, and the user can stop the scan by calling this
* method.
*/
public void stop() throws RemoteException {
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
telephony.stopNetworkScan(mSubId, mScanId);
} else {
throw new RemoteException("Failed to get the ITelephony instance.");
}
} catch (RemoteException ex) {
Rlog.e(TAG, "stopNetworkScan RemoteException", ex);
throw new RemoteException("Failed to stop the network scan with id " + mScanId);
}
}
/**
* Creates a new NetworkScan with scanId
*
* @param scanId The id of the scan
* @param subId the id of the subscription
* @hide
*/
public NetworkScan(int scanId, int subId) {
mScanId = scanId;
mSubId = subId;
}
private ITelephony getITelephony() {
return ITelephony.Stub.asInterface(
ServiceManager.getService(Context.TELEPHONY_SERVICE));
}
}

View File

@@ -0,0 +1,19 @@
/*
* Copyright (c) 2017, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.telephony;
parcelable NetworkScanRequest;

View File

@@ -0,0 +1,115 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.telephony;
import android.os.Parcel;
import android.os.Parcelable;
import java.util.Arrays;
/**
* Defines a request to peform a network scan.
*
* This class defines whether the network scan will be performed only once or periodically until
* cancelled, when the scan is performed periodically, the time interval is not controlled by the
* user but defined by the modem vendor.
* @hide
*/
public final class NetworkScanRequest implements Parcelable {
/** Performs the scan only once */
public static final int SCAN_TYPE_ONE_SHOT = 0;
/**
* Performs the scan periodically until cancelled
*
* The modem will start new scans periodically, and the interval between two scans is usually
* multiple minutes.
* */
public static final int SCAN_TYPE_PERIODIC = 1;
/** Defines the type of the scan. */
public int scanType;
/** Describes the radio access technologies with bands or channels that need to be scanned. */
public RadioAccessSpecifier[] specifiers;
/**
* Creates a new NetworkScanRequest with scanType and network specifiers
*
* @param scanType The type of the scan
* @param specifiers the radio network with bands / channels to be scanned
*/
public NetworkScanRequest(int scanType, RadioAccessSpecifier[] specifiers) {
this.scanType = scanType;
this.specifiers = specifiers;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(scanType);
dest.writeParcelableArray(specifiers, flags);
}
private NetworkScanRequest(Parcel in) {
scanType = in.readInt();
specifiers = (RadioAccessSpecifier[]) in.readParcelableArray(
Object.class.getClassLoader(),
RadioAccessSpecifier.class);
}
@Override
public boolean equals (Object o) {
NetworkScanRequest nsr;
try {
nsr = (NetworkScanRequest) o;
} catch (ClassCastException ex) {
return false;
}
if (o == null) {
return false;
}
return (scanType == nsr.scanType
&& Arrays.equals(specifiers, nsr.specifiers));
}
@Override
public int hashCode () {
return ((scanType * 31)
+ (Arrays.hashCode(specifiers)) * 37);
}
public static final Creator<NetworkScanRequest> CREATOR =
new Creator<NetworkScanRequest>() {
@Override
public NetworkScanRequest createFromParcel(Parcel in) {
return new NetworkScanRequest(in);
}
@Override
public NetworkScanRequest[] newArray(int size) {
return new NetworkScanRequest[size];
}
};
}

View File

@@ -0,0 +1,19 @@
/*
* Copyright (c) 2017, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.telephony;
parcelable RadioAccessSpecifier;

View File

@@ -0,0 +1,129 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.telephony;
import android.os.Parcel;
import android.os.Parcelable;
import java.util.Arrays;
/**
* Describes a particular radio access network to be scanned.
*
* The scan can be performed on either bands or channels for a specific radio access network type.
* @hide
*/
public final class RadioAccessSpecifier implements Parcelable {
/**
* The radio access network that needs to be scanned
*
* See {@link RadioNetworkConstants.RadioAccessNetworks} for details.
*/
public int radioAccessNetwork;
/**
* The frequency bands that need to be scanned
*
* bands must be used together with radioAccessNetwork
*
* See {@link RadioNetworkConstants} for details.
*/
public int[] bands;
/**
* The frequency channels that need to be scanned
*
* channels must be used together with radioAccessNetwork
*
* See {@link RadioNetworkConstants.RadioAccessNetworks} for details.
*/
public int[] channels;
/**
* Creates a new RadioAccessSpecifier with radio network, bands and channels
*
* The user must specify the radio network type, and at least specify either of frequency
* bands or channels.
*
* @param ran The type of the radio access network
* @param bands the frequency bands to be scanned
* @param channels the frequency bands to be scanned
*/
public RadioAccessSpecifier(int ran, int[] bands, int[] channels) {
this.radioAccessNetwork = ran;
this.bands = bands;
this.channels = channels;
}
public static final Parcelable.Creator<RadioAccessSpecifier> CREATOR =
new Parcelable.Creator<RadioAccessSpecifier> (){
@Override
public RadioAccessSpecifier createFromParcel(Parcel in) {
return new RadioAccessSpecifier(in);
}
@Override
public RadioAccessSpecifier[] newArray(int size) {
return new RadioAccessSpecifier[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(radioAccessNetwork);
dest.writeIntArray(bands);
dest.writeIntArray(channels);
}
private RadioAccessSpecifier(Parcel in) {
radioAccessNetwork = in.readInt();
bands = in.createIntArray();
channels = in.createIntArray();
}
@Override
public boolean equals (Object o) {
RadioAccessSpecifier ras;
try {
ras = (RadioAccessSpecifier) o;
} catch (ClassCastException ex) {
return false;
}
if (o == null) {
return false;
}
return (radioAccessNetwork == ras.radioAccessNetwork
&& Arrays.equals(bands, ras.bands)
&& Arrays.equals(channels, ras.channels));
}
@Override
public int hashCode () {
return ((radioAccessNetwork * 31)
+ (Arrays.hashCode(bands) * 37)
+ (Arrays.hashCode(channels)) * 39);
}
}

View File

@@ -0,0 +1,169 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.telephony;
/**
* Contains radio access network related constants.
* @hide
*/
public final class RadioNetworkConstants {
public static final class RadioAccessNetworks {
public static final int GERAN = 1;
public static final int UTRAN = 2;
public static final int EUTRAN = 3;
/** @hide */
public static final int CDMA2000 = 4;
}
/**
* Frenquency bands for GERAN.
* http://www.etsi.org/deliver/etsi_ts/145000_145099/145005/14.00.00_60/ts_145005v140000p.pdf
*/
public static final class GeranBands {
public static final int BAND_T380 = 1;
public static final int BAND_T410 = 2;
public static final int BAND_450 = 3;
public static final int BAND_480 = 4;
public static final int BAND_710 = 5;
public static final int BAND_750 = 6;
public static final int BAND_T810 = 7;
public static final int BAND_850 = 8;
public static final int BAND_P900 = 9;
public static final int BAND_E900 = 10;
public static final int BAND_R900 = 11;
public static final int BAND_DCS1800 = 12;
public static final int BAND_PCS1900 = 13;
public static final int BAND_ER900 = 14;
}
/**
* Frenquency bands for UTRAN.
* http://www.etsi.org/deliver/etsi_ts/125100_125199/125104/13.03.00_60/ts_125104v130p.pdf
*/
public static final class UtranBands {
public static final int BAND_1 = 1;
public static final int BAND_2 = 2;
public static final int BAND_3 = 3;
public static final int BAND_4 = 4;
public static final int BAND_5 = 5;
public static final int BAND_6 = 6;
public static final int BAND_7 = 7;
public static final int BAND_8 = 8;
public static final int BAND_9 = 9;
public static final int BAND_10 = 10;
public static final int BAND_11 = 11;
public static final int BAND_12 = 12;
public static final int BAND_13 = 13;
public static final int BAND_14 = 14;
/** band 15, 16, 17, 18 are reserved */
public static final int BAND_19 = 19;
public static final int BAND_20 = 20;
public static final int BAND_21 = 21;
public static final int BAND_22 = 22;
/** band 23, 24 are reserved */
public static final int BAND_25 = 25;
public static final int BAND_26 = 26;
}
/**
* Frenquency bands for EUTRAN.
* http://www.etsi.org/deliver/etsi_ts/136100_136199/136101/14.03.00_60/ts_136101v140p.pdf
*/
public static final class EutranBands {
public static final int BAND_1 = 1;
public static final int BAND_2 = 2;
public static final int BAND_3 = 3;
public static final int BAND_4 = 4;
public static final int BAND_5 = 5;
public static final int BAND_6 = 6;
public static final int BAND_7 = 7;
public static final int BAND_8 = 8;
public static final int BAND_9 = 9;
public static final int BAND_10 = 10;
public static final int BAND_11 = 11;
public static final int BAND_12 = 12;
public static final int BAND_13 = 13;
public static final int BAND_14 = 14;
public static final int BAND_17 = 17;
public static final int BAND_18 = 18;
public static final int BAND_19 = 19;
public static final int BAND_20 = 20;
public static final int BAND_21 = 21;
public static final int BAND_22 = 22;
public static final int BAND_23 = 23;
public static final int BAND_24 = 24;
public static final int BAND_25 = 25;
public static final int BAND_26 = 26;
public static final int BAND_27 = 27;
public static final int BAND_28 = 28;
public static final int BAND_30 = 30;
public static final int BAND_31 = 31;
public static final int BAND_33 = 33;
public static final int BAND_34 = 34;
public static final int BAND_35 = 35;
public static final int BAND_36 = 36;
public static final int BAND_37 = 37;
public static final int BAND_38 = 38;
public static final int BAND_39 = 39;
public static final int BAND_40 = 40;
public static final int BAND_41 = 41;
public static final int BAND_42 = 42;
public static final int BAND_43 = 43;
public static final int BAND_44 = 44;
public static final int BAND_45 = 45;
public static final int BAND_46 = 46;
public static final int BAND_47 = 47;
public static final int BAND_48 = 48;
public static final int BAND_65 = 65;
public static final int BAND_66 = 66;
public static final int BAND_68 = 68;
public static final int BAND_70 = 70;
}
/**
* Frenquency bands for CDMA2000.
* http://www.3gpp2.org/Public_html/Specs/C.S0057-E_v1.0_Bandclass_Specification.pdf
* @hide
*
* TODO(yinxu): Check with the nexus team about the definition of CDMA bands.
*/
public static final class CdmaBands {
public static final int BAND_0 = 1;
public static final int BAND_1 = 2;
public static final int BAND_2 = 3;
public static final int BAND_3 = 4;
public static final int BAND_4 = 5;
public static final int BAND_5 = 6;
public static final int BAND_6 = 7;
public static final int BAND_7 = 8;
public static final int BAND_8 = 9;
public static final int BAND_9 = 10;
public static final int BAND_10 = 11;
public static final int BAND_11 = 12;
public static final int BAND_12 = 13;
public static final int BAND_13 = 14;
public static final int BAND_14 = 15;
public static final int BAND_15 = 16;
public static final int BAND_16 = 17;
public static final int BAND_17 = 18;
public static final int BAND_18 = 19;
public static final int BAND_19 = 20;
public static final int BAND_20 = 21;
public static final int BAND_21 = 22;
}
}

View File

@@ -39,6 +39,11 @@ import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.os.Messenger;
import android.os.Parcelable;
import android.os.PersistableBundle;
import android.os.RemoteException;
import android.os.ResultReceiver;
@@ -144,6 +149,7 @@ public class TelephonyManager {
private final Context mContext;
private final int mSubId;
private SubscriptionManager mSubscriptionManager;
private TelephonyScanManager mTelephonyScanManager;
private static String multiSimConfig =
SystemProperties.get(TelephonyProperties.PROPERTY_MULTI_SIM_CONFIG);
@@ -4572,6 +4578,32 @@ public class TelephonyManager {
return null;
}
/**
* Request a network scan.
*
* This method is asynchronous, so the network scan results will be returned by callback.
* The returned NetworkScan will contain a callback method which can be used to stop the scan.
*
* <p>
* Requires Permission:
* {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
* Or the calling app has carrier privileges. @see #hasCarrierPrivileges
*
* @param request Contains all the RAT with bands/channels that need to be scanned.
* @param callback Returns network scan results or errors.
* @return A NetworkScan obj which contains a callback which can stop the scan.
* @hide
*/
public NetworkScan requestNetworkScan(
NetworkScanRequest request, TelephonyScanManager.NetworkScanCallback callback) {
synchronized (this) {
if (mTelephonyScanManager == null) {
mTelephonyScanManager = new TelephonyScanManager();
}
}
return mTelephonyScanManager.requestNetworkScan(getSubId(), request, callback);
}
/**
* Ask the radio to connect to the input network and change selection mode to manual.
*

View File

@@ -0,0 +1,186 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.telephony;
import static com.android.internal.util.Preconditions.checkNotNull;
import android.content.Context;
import android.os.Binder;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.Log;
import android.util.SparseArray;
import java.util.List;
import com.android.internal.telephony.ITelephony;
/**
* Manages the radio access network scan requests and callbacks.
* @hide
*/
public final class TelephonyScanManager {
private static final String TAG = "TelephonyScanManager";
/** @hide */
public static final int CALLBACK_SCAN_RESULTS = 1;
/** @hide */
public static final int CALLBACK_SCAN_ERROR = 2;
/** @hide */
public static final int CALLBACK_SCAN_COMPLETE = 3;
/**
* The caller of {@link #requestNetworkScan(NetworkScanRequest, NetworkScanCallback)} should
* implement and provide this callback so that the scan results or errors can be returned.
*/
public static abstract class NetworkScanCallback {
/** Returns the scan results to the user, this callback will be called multiple times. */
public void onResults(List<CellInfo> results) {}
/**
* Informs the user that the scan has stopped.
*
* This callback will be called when the scan is finished or cancelled by the user.
* The related NetworkScanRequest will be deleted after this callback.
*/
public void onComplete() {}
/**
* Informs the user that there is some error about the scan.
*
* This callback will be called whenever there is any error about the scan, but the scan
* won't stop unless the onComplete() callback is called.
*/
public void onError(int error) {}
}
private static class NetworkScanInfo {
private final NetworkScanRequest mRequest;
private final NetworkScanCallback mCallback;
NetworkScanInfo(NetworkScanRequest request, NetworkScanCallback callback) {
mRequest = request;
mCallback = callback;
}
}
private final Looper mLooper;
private final Messenger mMessenger;
private SparseArray<NetworkScanInfo> mScanInfo = new SparseArray<NetworkScanInfo>();
public TelephonyScanManager() {
HandlerThread thread = new HandlerThread(TAG);
thread.start();
mLooper = thread.getLooper();
mMessenger = new Messenger(new Handler(mLooper) {
@Override
public void handleMessage(Message message) {
checkNotNull(message, "message cannot be null");
NetworkScanInfo nsi;
synchronized (mScanInfo) {
nsi = mScanInfo.get(message.arg2);
}
if (nsi == null) {
throw new RuntimeException(
"Failed to find NetworkScanInfo with id " + message.arg2);
}
NetworkScanCallback callback = nsi.mCallback;
if (callback == null) {
throw new RuntimeException(
"Failed to find NetworkScanCallback with id " + message.arg2);
}
switch (message.what) {
case CALLBACK_SCAN_RESULTS:
try {
callback.onResults((List<CellInfo>) message.obj);
} catch (Exception e) {
Rlog.e(TAG, "Exception in networkscan callback onResults", e);
}
break;
case CALLBACK_SCAN_ERROR:
try {
callback.onError(message.arg1);
} catch (Exception e) {
Rlog.e(TAG, "Exception in networkscan callback onError", e);
}
break;
case CALLBACK_SCAN_COMPLETE:
try {
callback.onComplete();
mScanInfo.remove(message.arg2);
} catch (Exception e) {
Rlog.e(TAG, "Exception in networkscan callback onComplete", e);
}
break;
default:
Rlog.e(TAG, "Unhandled message " + Integer.toHexString(message.what));
break;
}
}
});
}
/**
* Request a network scan.
*
* This method is asynchronous, so the network scan results will be returned by callback.
* The returned NetworkScan will contain a callback method which can be used to stop the scan.
*
* <p>
* Requires Permission:
* {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
* Or the calling app has carrier privileges. @see #hasCarrierPrivileges
*
* @param request Contains all the RAT with bands/channels that need to be scanned.
* @param callback Returns network scan results or errors.
* @return A NetworkScan obj which contains a callback which can stop the scan.
* @hide
*/
public NetworkScan requestNetworkScan(int subId,
NetworkScanRequest request, NetworkScanCallback callback) {
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
int scanId = telephony.requestNetworkScan(subId, request, mMessenger, new Binder());
saveScanInfo(scanId, request, callback);
return new NetworkScan(scanId, subId);
}
} catch (RemoteException ex) {
Rlog.e(TAG, "requestNetworkScan RemoteException", ex);
} catch (NullPointerException ex) {
Rlog.e(TAG, "requestNetworkScan NPE", ex);
}
return null;
}
private void saveScanInfo(int id, NetworkScanRequest request, NetworkScanCallback callback) {
synchronized (mScanInfo) {
mScanInfo.put(id, new NetworkScanInfo(request, callback));
}
}
private ITelephony getITelephony() {
return ITelephony.Stub.asInterface(
ServiceManager.getService(Context.TELEPHONY_SERVICE));
}
}

View File

@@ -19,6 +19,8 @@ package com.android.internal.telephony;
import android.app.PendingIntent;
import android.content.Intent;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Messenger;
import android.os.ResultReceiver;
import android.net.Uri;
import android.service.carrier.CarrierIdentifier;
@@ -29,6 +31,7 @@ import android.telephony.ClientRequestStats;
import android.telephony.IccOpenLogicalChannelResponse;
import android.telephony.ModemActivityInfo;
import android.telephony.NeighboringCellInfo;
import android.telephony.NetworkScanRequest;
import android.telephony.RadioAccessFamily;
import android.telephony.ServiceState;
import android.telephony.SignalStrength;
@@ -794,6 +797,26 @@ interface ITelephony {
*/
CellNetworkScanResult getCellNetworkScanResults(int subId);
/**
* Perform a radio network scan and return the id of this scan.
*
* @param subId the id of the subscription.
* @param request Defines all the configs for network scan.
* @param messenger Callback messages will be sent using this messenger.
* @param binder the binder object instantiated in TelephonyManager.
* @return An id for this scan.
*/
int requestNetworkScan(int subId, in NetworkScanRequest request, in Messenger messenger,
in IBinder binder);
/**
* Stop an existing radio network scan.
*
* @param subId the id of the subscription.
* @param scanId The id of the scan that is going to be stopped.
*/
void stopNetworkScan(int subId, int scanId);
/**
* Ask the radio to connect to the input network and change selection mode to manual.
*