Merge "Fill in methods in EuiccCardController."
diff --git a/Android.mk b/Android.mk
index 5dfa81c..0e7c087 100644
--- a/Android.mk
+++ b/Android.mk
@@ -697,6 +697,28 @@
include $(BUILD_HOST_JAVA_LIBRARY)
+# ==== hiddenapi lists =======================================
+
+# Generate light greylist as private API minus (blacklist plus dark greylist).
+
+$(INTERNAL_PLATFORM_HIDDENAPI_LIGHT_GREYLIST): PRIVATE_API := $(INTERNAL_PLATFORM_PRIVATE_DEX_API_FILE)
+$(INTERNAL_PLATFORM_HIDDENAPI_LIGHT_GREYLIST): BLACKLIST := $(INTERNAL_PLATFORM_HIDDENAPI_BLACKLIST)
+$(INTERNAL_PLATFORM_HIDDENAPI_LIGHT_GREYLIST): DARK_GREYLIST := $(INTERNAL_PLATFORM_HIDDENAPI_DARK_GREYLIST)
+$(INTERNAL_PLATFORM_HIDDENAPI_LIGHT_GREYLIST): $(INTERNAL_PLATFORM_PRIVATE_DEX_API_FILE) \
+ $(INTERNAL_PLATFORM_HIDDENAPI_BLACKLIST) \
+ $(INTERNAL_PLATFORM_HIDDENAPI_DARK_GREYLIST)
+ if [ ! -z "`comm -12 <(sort $(BLACKLIST)) <(sort $(DARK_GREYLIST))`" ]; then \
+ echo "There should be no overlap between $(BLACKLIST) and $(DARK_GREYLIST)" 1>&2; \
+ exit 1; \
+ elif [ ! -z "`comm -13 <(sort $(PRIVATE_API)) <(sort $(BLACKLIST))`" ]; then \
+ echo "$(BLACKLIST) must be a subset of $(PRIVATE_API)" 1>&2; \
+ exit 2; \
+ elif [ ! -z "`comm -13 <(sort $(PRIVATE_API)) <(sort $(DARK_GREYLIST))`" ]; then \
+ echo "$(DARK_GREYLIST) must be a subset of $(PRIVATE_API)" 1>&2; \
+ exit 3; \
+ fi
+ comm -23 <(sort $(PRIVATE_API)) <(sort $(BLACKLIST) $(DARK_GREYLIST)) > $@
+
# Include subdirectory makefiles
# ============================================================
diff --git a/api/current.txt b/api/current.txt
index 7954bf5..bc79db9 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -39995,6 +39995,8 @@
method public void notifyConfigChangedForSubId(int);
field public static final java.lang.String ACTION_CARRIER_CONFIG_CHANGED = "android.telephony.action.CARRIER_CONFIG_CHANGED";
field public static final int DATA_CYCLE_THRESHOLD_DISABLED = -2; // 0xfffffffe
+ field public static final java.lang.String EXTRA_SLOT_INDEX = "android.telephony.extra.SLOT_INDEX";
+ field public static final java.lang.String EXTRA_SUBSCRIPTION_INDEX = "android.telephony.extra.SUBSCRIPTION_INDEX";
field public static final java.lang.String KEY_ADDITIONAL_CALL_SETTING_BOOL = "additional_call_setting_bool";
field public static final java.lang.String KEY_ALLOW_ADDING_APNS_BOOL = "allow_adding_apns_bool";
field public static final java.lang.String KEY_ALLOW_ADD_CALL_DURING_VIDEO_CALL_BOOL = "allow_add_call_during_video_call";
@@ -40172,6 +40174,7 @@
}
public final class CellIdentityLte extends android.telephony.CellIdentity {
+ method public int getBandwidth();
method public int getCi();
method public int getEarfcn();
method public deprecated int getMcc();
@@ -40215,8 +40218,13 @@
public abstract class CellInfo implements android.os.Parcelable {
method public int describeContents();
+ method public int getCellConnectionStatus();
method public long getTimeStamp();
method public boolean isRegistered();
+ field public static final int CONNECTION_NONE = 0; // 0x0
+ field public static final int CONNECTION_PRIMARY_SERVING = 1; // 0x1
+ field public static final int CONNECTION_SECONDARY_SERVING = 2; // 0x2
+ field public static final int CONNECTION_UNKNOWN = 2147483647; // 0x7fffffff
field public static final android.os.Parcelable.Creator<android.telephony.CellInfo> CREATOR;
}
@@ -40529,6 +40537,9 @@
ctor public ServiceState(android.os.Parcel);
method protected void copyFrom(android.telephony.ServiceState);
method public int describeContents();
+ method public int[] getCellBandwidths();
+ method public int getChannelNumber();
+ method public int getDuplexMode();
method public boolean getIsManualSelection();
method public int getNetworkId();
method public java.lang.String getOperatorAlphaLong();
@@ -40545,6 +40556,9 @@
method public void setStateOutOfService();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.telephony.ServiceState> CREATOR;
+ field public static final int DUPLEX_MODE_FDD = 1; // 0x1
+ field public static final int DUPLEX_MODE_TDD = 2; // 0x2
+ field public static final int DUPLEX_MODE_UNKNOWN = 0; // 0x0
field public static final int STATE_EMERGENCY_ONLY = 2; // 0x2
field public static final int STATE_IN_SERVICE = 0; // 0x0
field public static final int STATE_OUT_OF_SERVICE = 1; // 0x1
diff --git a/api/system-current.txt b/api/system-current.txt
index 545438c..2e39bb7f 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -2587,9 +2587,23 @@
method public java.lang.String getInterfaceName();
}
+ public final class IpSecTransform implements java.lang.AutoCloseable {
+ method public void startNattKeepalive(android.net.IpSecTransform.NattKeepaliveCallback, int, android.os.Handler) throws java.io.IOException;
+ method public void stopNattKeepalive();
+ }
+
public static class IpSecTransform.Builder {
method public android.net.IpSecTransform buildTunnelModeTransform(java.net.InetAddress, android.net.IpSecManager.SecurityParameterIndex) throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException, android.net.IpSecManager.SpiUnavailableException;
- method public android.net.IpSecTransform.Builder setNattKeepalive(int);
+ }
+
+ public static class IpSecTransform.NattKeepaliveCallback {
+ ctor public IpSecTransform.NattKeepaliveCallback();
+ method public void onError(int);
+ method public void onStarted();
+ method public void onStopped();
+ field public static final int ERROR_HARDWARE_ERROR = 3; // 0x3
+ field public static final int ERROR_HARDWARE_UNSUPPORTED = 2; // 0x2
+ field public static final int ERROR_INVALID_NETWORK = 1; // 0x1
}
public class NetworkKey implements android.os.Parcelable {
diff --git a/config/hiddenapi-blacklist.txt b/config/hiddenapi-blacklist.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/config/hiddenapi-blacklist.txt
diff --git a/config/hiddenapi-dark-greylist.txt b/config/hiddenapi-dark-greylist.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/config/hiddenapi-dark-greylist.txt
diff --git a/core/java/android/net/IpSecTransform.java b/core/java/android/net/IpSecTransform.java
index 37e2c4f..9ccdbe2 100644
--- a/core/java/android/net/IpSecTransform.java
+++ b/core/java/android/net/IpSecTransform.java
@@ -17,11 +17,14 @@
import static android.net.IpSecManager.INVALID_RESOURCE_ID;
+import static com.android.internal.util.Preconditions.checkNotNull;
+
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.content.Context;
import android.os.Binder;
+import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -128,13 +131,6 @@
int status = result.status;
checkResultStatus(status);
mResourceId = result.resourceId;
-
- /* Keepalive will silently fail if not needed by the config; but, if needed and
- * it fails to start, we need to bail because a transform will not be reliable
- * to use if keepalive is expected to offload and fails.
- */
- // FIXME: if keepalive fails, we need to fail spectacularly
- startKeepalive(mContext);
Log.d(TAG, "Added Transform with Id " + mResourceId);
mCloseGuard.open("build");
} catch (RemoteException e) {
@@ -164,13 +160,9 @@
return;
}
try {
- /* Order matters here because the keepalive is best-effort but could fail in some
- * horrible way to be removed if the wifi (or cell) subsystem has crashed, and we
- * still want to clear out the transform.
- */
IIpSecService svc = getIpSecService();
svc.deleteTransform(mResourceId);
- stopKeepalive();
+ stopNattKeepalive();
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
} finally {
@@ -198,42 +190,35 @@
private final Context mContext;
private final CloseGuard mCloseGuard = CloseGuard.get();
private ConnectivityManager.PacketKeepalive mKeepalive;
- private int mKeepaliveStatus = ConnectivityManager.PacketKeepalive.NO_KEEPALIVE;
- private Object mKeepaliveSyncLock = new Object();
- private ConnectivityManager.PacketKeepaliveCallback mKeepaliveCallback =
+ private Handler mCallbackHandler;
+ private final ConnectivityManager.PacketKeepaliveCallback mKeepaliveCallback =
new ConnectivityManager.PacketKeepaliveCallback() {
@Override
public void onStarted() {
- synchronized (mKeepaliveSyncLock) {
- mKeepaliveStatus = ConnectivityManager.PacketKeepalive.SUCCESS;
- mKeepaliveSyncLock.notifyAll();
+ synchronized (this) {
+ mCallbackHandler.post(() -> mUserKeepaliveCallback.onStarted());
}
}
@Override
public void onStopped() {
- synchronized (mKeepaliveSyncLock) {
- mKeepaliveStatus = ConnectivityManager.PacketKeepalive.NO_KEEPALIVE;
- mKeepaliveSyncLock.notifyAll();
+ synchronized (this) {
+ mKeepalive = null;
+ mCallbackHandler.post(() -> mUserKeepaliveCallback.onStopped());
}
}
@Override
public void onError(int error) {
- synchronized (mKeepaliveSyncLock) {
- mKeepaliveStatus = error;
- mKeepaliveSyncLock.notifyAll();
+ synchronized (this) {
+ mKeepalive = null;
+ mCallbackHandler.post(() -> mUserKeepaliveCallback.onError(error));
}
}
};
- /* Package */
- void startKeepalive(Context c) {
- if (mConfig.getNattKeepaliveInterval() != 0) {
- Log.wtf(TAG, "Keepalive not yet supported.");
- }
- }
+ private NattKeepaliveCallback mUserKeepaliveCallback;
/** @hide */
@VisibleForTesting
@@ -241,9 +226,93 @@
return mResourceId;
}
- /* Package */
- void stopKeepalive() {
- return;
+ /**
+ * A callback class to provide status information regarding a NAT-T keepalive session
+ *
+ * <p>Use this callback to receive status information regarding a NAT-T keepalive session
+ * by registering it when calling {@link #startNattKeepalive}.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static class NattKeepaliveCallback {
+ /** The specified {@code Network} is not connected. */
+ public static final int ERROR_INVALID_NETWORK = 1;
+ /** The hardware does not support this request. */
+ public static final int ERROR_HARDWARE_UNSUPPORTED = 2;
+ /** The hardware returned an error. */
+ public static final int ERROR_HARDWARE_ERROR = 3;
+
+ /** The requested keepalive was successfully started. */
+ public void onStarted() {}
+ /** The keepalive was successfully stopped. */
+ public void onStopped() {}
+ /** An error occurred. */
+ public void onError(int error) {}
+ }
+
+ /**
+ * Start a NAT-T keepalive session for the current transform.
+ *
+ * For a transform that is using UDP encapsulated IPv4, NAT-T offloading provides
+ * a power efficient mechanism of sending NAT-T packets at a specified interval.
+ *
+ * @param userCallback a {@link #NattKeepaliveCallback} to receive asynchronous status
+ * information about the requested NAT-T keepalive session.
+ * @param intervalSeconds the interval between NAT-T keepalives being sent. The
+ * the allowed range is between 20 and 3600 seconds.
+ * @param handler a handler on which to post callbacks when received.
+ *
+ * @hide
+ */
+ @SystemApi
+ public void startNattKeepalive(@NonNull NattKeepaliveCallback userCallback,
+ int intervalSeconds, @NonNull Handler handler) throws IOException {
+ checkNotNull(userCallback);
+ if (intervalSeconds < 20 || intervalSeconds > 3600) {
+ throw new IllegalArgumentException("Invalid NAT-T keepalive interval");
+ }
+ checkNotNull(handler);
+ if (mResourceId == INVALID_RESOURCE_ID) {
+ throw new IllegalStateException(
+ "Packet keepalive cannot be started for an inactive transform");
+ }
+
+ synchronized (mKeepaliveCallback) {
+ if (mKeepaliveCallback != null) {
+ throw new IllegalStateException("Keepalive already active");
+ }
+
+ mUserKeepaliveCallback = userCallback;
+ ConnectivityManager cm = (ConnectivityManager) mContext.getSystemService(
+ Context.CONNECTIVITY_SERVICE);
+ mKeepalive = cm.startNattKeepalive(
+ mConfig.getNetwork(), intervalSeconds, mKeepaliveCallback,
+ NetworkUtils.numericToInetAddress(mConfig.getSourceAddress()),
+ 4500, // FIXME urgently, we need to get the port number from the Encap socket
+ NetworkUtils.numericToInetAddress(mConfig.getDestinationAddress()));
+ mCallbackHandler = handler;
+ }
+ }
+
+ /**
+ * Stop an ongoing NAT-T keepalive session.
+ *
+ * Calling this API will request that an ongoing NAT-T keepalive session be terminated.
+ * If this API is not called when a Transform is closed, the underlying NAT-T session will
+ * be terminated automatically.
+ *
+ * @hide
+ */
+ @SystemApi
+ public void stopNattKeepalive() {
+ synchronized (mKeepaliveCallback) {
+ if (mKeepalive == null) {
+ Log.e(TAG, "No active keepalive to stop");
+ return;
+ }
+ mKeepalive.stop();
+ }
}
/** This class is used to build {@link IpSecTransform} objects. */
@@ -323,26 +392,6 @@
return this;
}
- // TODO: Decrease the minimum keepalive to maybe 10?
- // TODO: Probably a better exception to throw for NATTKeepalive failure
- // TODO: Specify the needed NATT keepalive permission.
- /**
- * Set NAT-T keepalives to be sent with a given interval.
- *
- * <p>This will set power-efficient keepalive packets to be sent by the system. If NAT-T
- * keepalive is requested but cannot be activated, then creation of an {@link
- * IpSecTransform} will fail when calling the build method.
- *
- * @param intervalSeconds the maximum number of seconds between keepalive packets. Must be
- * between 20s and 3600s.
- * @hide
- */
- @SystemApi
- public IpSecTransform.Builder setNattKeepalive(int intervalSeconds) {
- mConfig.setNattKeepaliveInterval(intervalSeconds);
- return this;
- }
-
/**
* Build a transport mode {@link IpSecTransform}.
*
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index 31516fd..e81ed9a 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -892,7 +892,7 @@
*
* @hide
*/
- private Set<UidRange> mUids = null;
+ private ArraySet<UidRange> mUids = null;
/**
* Convenience method to set the UIDs this network applies to to a single UID.
@@ -1180,7 +1180,7 @@
dest.writeInt(mLinkDownBandwidthKbps);
dest.writeParcelable((Parcelable) mNetworkSpecifier, flags);
dest.writeInt(mSignalStrength);
- dest.writeArraySet(new ArraySet<>(mUids));
+ dest.writeArraySet(mUids);
}
public static final Creator<NetworkCapabilities> CREATOR =
diff --git a/packages/PrintSpooler/tests/outofprocess/src/com/android/printspooler/outofprocess/tests/WorkflowTest.java b/packages/PrintSpooler/tests/outofprocess/src/com/android/printspooler/outofprocess/tests/WorkflowTest.java
index 184e559..888fedb 100644
--- a/packages/PrintSpooler/tests/outofprocess/src/com/android/printspooler/outofprocess/tests/WorkflowTest.java
+++ b/packages/PrintSpooler/tests/outofprocess/src/com/android/printspooler/outofprocess/tests/WorkflowTest.java
@@ -154,16 +154,16 @@
@AfterClass
public static void enableAnimations() throws Exception {
- if (sWindowAnimationScaleBefore != Float.NaN) {
+ if (!Float.isNaN(sWindowAnimationScaleBefore)) {
runShellCommand(
"settings put global window_animation_scale " + sWindowAnimationScaleBefore);
}
- if (sTransitionAnimationScaleBefore != Float.NaN) {
+ if (!Float.isNaN(sTransitionAnimationScaleBefore)) {
runShellCommand(
"settings put global transition_animation_scale " +
sTransitionAnimationScaleBefore);
}
- if (sAnimatiorDurationScaleBefore != Float.NaN) {
+ if (!Float.isNaN(sAnimatiorDurationScaleBefore)) {
runShellCommand(
"settings put global animator_duration_scale " + sAnimatiorDurationScaleBefore);
}
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index 7b171b3..69dec2d 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -495,6 +495,7 @@
Intent intent = new Intent(Settings.ACTION_TETHER_PROVISIONING);
intent.putExtra(ConnectivityManager.EXTRA_ADD_TETHER_TYPE, type);
intent.putExtra(ConnectivityManager.EXTRA_PROVISION_CALLBACK, receiver);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
final long ident = Binder.clearCallingIdentity();
try {
mContext.startActivityAsUser(intent, UserHandle.CURRENT);
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index f59871b..94ed218 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -39,13 +39,29 @@
private final static String TAG = "CarrierConfigManager";
/**
+ * Extra included in {@link #ACTION_CARRIER_CONFIG_CHANGED} to indicate the slot index that the
+ * broadcast is for.
+ */
+ public static final String EXTRA_SLOT_INDEX = "android.telephony.extra.SLOT_INDEX";
+
+ /**
+ * Optional extra included in {@link #ACTION_CARRIER_CONFIG_CHANGED} to indicate the
+ * subscription index that the broadcast is for, if a valid one is available.
+ */
+ public static final String EXTRA_SUBSCRIPTION_INDEX =
+ SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX;
+
+ /**
* @hide
*/
public CarrierConfigManager() {
}
/**
- * This intent is broadcast by the system when carrier config changes.
+ * This intent is broadcast by the system when carrier config changes. An int is specified in
+ * {@link #EXTRA_SLOT_INDEX} to indicate the slot index that this is for. An optional int extra
+ * {@link #EXTRA_SUBSCRIPTION_INDEX} is included to indicate the subscription index if a valid
+ * one is available for the slot index.
*/
public static final String
ACTION_CARRIER_CONFIG_CHANGED = "android.telephony.action.CARRIER_CONFIG_CHANGED";
diff --git a/telephony/java/android/telephony/CellIdentityLte.java b/telephony/java/android/telephony/CellIdentityLte.java
index 7f20c8a..5f1f448 100644
--- a/telephony/java/android/telephony/CellIdentityLte.java
+++ b/telephony/java/android/telephony/CellIdentityLte.java
@@ -40,6 +40,8 @@
private final String mAlphaLong;
// short alpha Operator Name String or Enhanced Operator Name String
private final String mAlphaShort;
+ // cell bandwidth, in kHz
+ private final int mBandwidth;
/**
* @hide
@@ -50,6 +52,7 @@
mPci = Integer.MAX_VALUE;
mTac = Integer.MAX_VALUE;
mEarfcn = Integer.MAX_VALUE;
+ mBandwidth = Integer.MAX_VALUE;
mAlphaLong = null;
mAlphaShort = null;
}
@@ -65,7 +68,8 @@
* @hide
*/
public CellIdentityLte(int mcc, int mnc, int ci, int pci, int tac) {
- this(ci, pci, tac, Integer.MAX_VALUE, String.valueOf(mcc), String.valueOf(mnc), null, null);
+ this(ci, pci, tac, Integer.MAX_VALUE, Integer.MAX_VALUE, String.valueOf(mcc),
+ String.valueOf(mnc), null, null);
}
/**
@@ -80,7 +84,8 @@
* @hide
*/
public CellIdentityLte(int mcc, int mnc, int ci, int pci, int tac, int earfcn) {
- this(ci, pci, tac, earfcn, String.valueOf(mcc), String.valueOf(mnc), null, null);
+ this(ci, pci, tac, earfcn, Integer.MAX_VALUE, String.valueOf(mcc), String.valueOf(mnc),
+ null, null);
}
/**
@@ -89,6 +94,7 @@
* @param pci Physical Cell Id 0..503
* @param tac 16-bit Tracking Area Code
* @param earfcn 18-bit LTE Absolute RF Channel Number
+ * @param bandwidth cell bandwidth in kHz
* @param mccStr 3-digit Mobile Country Code in string format
* @param mncStr 2 or 3-digit Mobile Network Code in string format
* @param alphal long alpha Operator Name String or Enhanced Operator Name String
@@ -96,19 +102,20 @@
*
* @hide
*/
- public CellIdentityLte(int ci, int pci, int tac, int earfcn, String mccStr,
- String mncStr, String alphal, String alphas) {
+ public CellIdentityLte(int ci, int pci, int tac, int earfcn, int bandwidth, String mccStr,
+ String mncStr, String alphal, String alphas) {
super(TAG, TYPE_LTE, mccStr, mncStr);
mCi = ci;
mPci = pci;
mTac = tac;
mEarfcn = earfcn;
+ mBandwidth = bandwidth;
mAlphaLong = alphal;
mAlphaShort = alphas;
}
private CellIdentityLte(CellIdentityLte cid) {
- this(cid.mCi, cid.mPci, cid.mTac, cid.mEarfcn, cid.mMccStr,
+ this(cid.mCi, cid.mPci, cid.mTac, cid.mEarfcn, cid.mBandwidth, cid.mMccStr,
cid.mMncStr, cid.mAlphaLong, cid.mAlphaShort);
}
@@ -163,6 +170,13 @@
}
/**
+ * @return Cell bandwidth in kHz, Integer.MAX_VALUE if unknown
+ */
+ public int getBandwidth() {
+ return mBandwidth;
+ }
+
+ /**
* @return Mobile Country Code in string format, null if unknown
*/
public String getMccStr() {
@@ -219,6 +233,7 @@
&& mPci == o.mPci
&& mTac == o.mTac
&& mEarfcn == o.mEarfcn
+ && mBandwidth == o.mBandwidth
&& TextUtils.equals(mMccStr, o.mMccStr)
&& TextUtils.equals(mMncStr, o.mMncStr)
&& TextUtils.equals(mAlphaLong, o.mAlphaLong)
@@ -232,6 +247,7 @@
.append(" mPci=").append(mPci)
.append(" mTac=").append(mTac)
.append(" mEarfcn=").append(mEarfcn)
+ .append(" mBandwidth=").append(mBandwidth)
.append(" mMcc=").append(mMccStr)
.append(" mMnc=").append(mMncStr)
.append(" mAlphaLong=").append(mAlphaLong)
@@ -248,6 +264,7 @@
dest.writeInt(mPci);
dest.writeInt(mTac);
dest.writeInt(mEarfcn);
+ dest.writeInt(mBandwidth);
dest.writeString(mAlphaLong);
dest.writeString(mAlphaShort);
}
@@ -259,6 +276,7 @@
mPci = in.readInt();
mTac = in.readInt();
mEarfcn = in.readInt();
+ mBandwidth = in.readInt();
mAlphaLong = in.readString();
mAlphaShort = in.readString();
diff --git a/telephony/java/android/telephony/CellInfo.java b/telephony/java/android/telephony/CellInfo.java
index b5e4eef..9232ed7 100644
--- a/telephony/java/android/telephony/CellInfo.java
+++ b/telephony/java/android/telephony/CellInfo.java
@@ -16,8 +16,11 @@
package android.telephony;
+import android.annotation.IntDef;
import android.os.Parcel;
import android.os.Parcelable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
/**
* Immutable cell information from a point in time.
@@ -47,6 +50,34 @@
/** @hide */
public static final int TIMESTAMP_TYPE_JAVA_RIL = 4;
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({
+ CONNECTION_NONE,
+ CONNECTION_PRIMARY_SERVING,
+ CONNECTION_SECONDARY_SERVING,
+ CONNECTION_UNKNOWN
+ })
+ public @interface CellConnectionStatus {}
+
+ /**
+ * Cell is not a serving cell.
+ *
+ * <p>The cell has been measured but is neither a camped nor serving cell (3GPP 36.304).
+ */
+ public static final int CONNECTION_NONE = 0;
+
+ /** UE is connected to cell for signalling and possibly data (3GPP 36.331, 25.331). */
+ public static final int CONNECTION_PRIMARY_SERVING = 1;
+
+ /** UE is connected to cell for data (3GPP 36.331, 25.331). */
+ public static final int CONNECTION_SECONDARY_SERVING = 2;
+
+ /** Connection status is unknown. */
+ public static final int CONNECTION_UNKNOWN = Integer.MAX_VALUE;
+
+ private int mCellConnectionStatus = CONNECTION_NONE;
+
// True if device is mRegistered to the mobile network
private boolean mRegistered;
@@ -69,6 +100,7 @@
this.mRegistered = ci.mRegistered;
this.mTimeStampType = ci.mTimeStampType;
this.mTimeStamp = ci.mTimeStamp;
+ this.mCellConnectionStatus = ci.mCellConnectionStatus;
}
/** True if this cell is registered to the mobile network */
@@ -90,6 +122,25 @@
}
/**
+ * Gets the connection status of this cell.
+ *
+ * @see #CONNECTION_NONE
+ * @see #CONNECTION_PRIMARY_SERVING
+ * @see #CONNECTION_SECONDARY_SERVING
+ * @see #CONNECTION_UNKNOWN
+ *
+ * @return The connection status of the cell.
+ */
+ @CellConnectionStatus
+ public int getCellConnectionStatus() {
+ return mCellConnectionStatus;
+ }
+ /** @hide */
+ public void setCellConnectionStatus(@CellConnectionStatus int cellConnectionStatus) {
+ mCellConnectionStatus = cellConnectionStatus;
+ }
+
+ /**
* Where time stamp gets recorded.
* @return one of TIMESTAMP_TYPE_XXXX
*
@@ -111,7 +162,7 @@
public int hashCode() {
int primeNum = 31;
return ((mRegistered ? 0 : 1) * primeNum) + ((int)(mTimeStamp / 1000) * primeNum)
- + (mTimeStampType * primeNum);
+ + (mTimeStampType * primeNum) + (mCellConnectionStatus * primeNum);
}
@Override
@@ -125,7 +176,9 @@
try {
CellInfo o = (CellInfo) other;
return mRegistered == o.mRegistered
- && mTimeStamp == o.mTimeStamp && mTimeStampType == o.mTimeStampType;
+ && mTimeStamp == o.mTimeStamp
+ && mTimeStampType == o.mTimeStampType
+ && mCellConnectionStatus == o.mCellConnectionStatus;
} catch (ClassCastException e) {
return false;
}
@@ -155,6 +208,7 @@
timeStampType = timeStampTypeToString(mTimeStampType);
sb.append(" mTimeStampType=").append(timeStampType);
sb.append(" mTimeStamp=").append(mTimeStamp).append("ns");
+ sb.append(" mCellConnectionStatus=").append(mCellConnectionStatus);
return sb.toString();
}
@@ -181,6 +235,7 @@
dest.writeInt(mRegistered ? 1 : 0);
dest.writeInt(mTimeStampType);
dest.writeLong(mTimeStamp);
+ dest.writeInt(mCellConnectionStatus);
}
/**
@@ -192,6 +247,7 @@
mRegistered = (in.readInt() == 1) ? true : false;
mTimeStampType = in.readInt();
mTimeStamp = in.readLong();
+ mCellConnectionStatus = in.readInt();
}
/** Implement the Parcelable interface */
diff --git a/telephony/java/android/telephony/INetworkService.aidl b/telephony/java/android/telephony/INetworkService.aidl
index d810d58..9ef7186 100644
--- a/telephony/java/android/telephony/INetworkService.aidl
+++ b/telephony/java/android/telephony/INetworkService.aidl
@@ -23,7 +23,9 @@
*/
oneway interface INetworkService
{
- void getNetworkRegistrationState(int domain, INetworkServiceCallback callback);
- void registerForNetworkRegistrationStateChanged(INetworkServiceCallback callback);
- void unregisterForNetworkRegistrationStateChanged(INetworkServiceCallback callback);
+ void createNetworkServiceProvider(int slotId);
+ void removeNetworkServiceProvider(int slotId);
+ void getNetworkRegistrationState(int slotId, int domain, INetworkServiceCallback callback);
+ void registerForNetworkRegistrationStateChanged(int slotId, INetworkServiceCallback callback);
+ void unregisterForNetworkRegistrationStateChanged(int slotId, INetworkServiceCallback callback);
}
diff --git a/telephony/java/android/telephony/NetworkService.java b/telephony/java/android/telephony/NetworkService.java
index 6b3584c..94921de 100644
--- a/telephony/java/android/telephony/NetworkService.java
+++ b/telephony/java/android/telephony/NetworkService.java
@@ -53,11 +53,13 @@
public static final String NETWORK_SERVICE_INTERFACE = "android.telephony.NetworkService";
public static final String NETWORK_SERVICE_EXTRA_SLOT_ID = "android.telephony.extra.SLOT_ID";
- private static final int NETWORK_SERVICE_INTERNAL_REQUEST_INITIALIZE_SERVICE = 1;
- private static final int NETWORK_SERVICE_GET_REGISTRATION_STATE = 2;
- private static final int NETWORK_SERVICE_REGISTER_FOR_STATE_CHANGE = 3;
- private static final int NETWORK_SERVICE_UNREGISTER_FOR_STATE_CHANGE = 4;
- private static final int NETWORK_SERVICE_INDICATION_NETWORK_STATE_CHANGED = 5;
+ private static final int NETWORK_SERVICE_CREATE_NETWORK_SERVICE_PROVIDER = 1;
+ private static final int NETWORK_SERVICE_REMOVE_NETWORK_SERVICE_PROVIDER = 2;
+ private static final int NETWORK_SERVICE_REMOVE_ALL_NETWORK_SERVICE_PROVIDERS = 3;
+ private static final int NETWORK_SERVICE_GET_REGISTRATION_STATE = 4;
+ private static final int NETWORK_SERVICE_REGISTER_FOR_STATE_CHANGE = 5;
+ private static final int NETWORK_SERVICE_UNREGISTER_FOR_STATE_CHANGE = 6;
+ private static final int NETWORK_SERVICE_INDICATION_NETWORK_STATE_CHANGED = 7;
private final HandlerThread mHandlerThread;
@@ -66,7 +68,7 @@
private final SparseArray<NetworkServiceProvider> mServiceMap = new SparseArray<>();
- private final SparseArray<INetworkServiceWrapper> mBinderMap = new SparseArray<>();
+ private final INetworkServiceWrapper mBinder = new INetworkServiceWrapper();
/**
* The abstract class of the actual network service implementation. The network service provider
@@ -147,37 +149,50 @@
public void handleMessage(Message message) {
final int slotId = message.arg1;
final INetworkServiceCallback callback = (INetworkServiceCallback) message.obj;
- NetworkServiceProvider service;
- synchronized (mServiceMap) {
- service = mServiceMap.get(slotId);
- }
+ NetworkServiceProvider serviceProvider = mServiceMap.get(slotId);
switch (message.what) {
- case NETWORK_SERVICE_INTERNAL_REQUEST_INITIALIZE_SERVICE:
- service = createNetworkServiceProvider(message.arg1);
- if (service != null) {
- mServiceMap.put(slotId, service);
+ case NETWORK_SERVICE_CREATE_NETWORK_SERVICE_PROVIDER:
+ // If the service provider doesn't exist yet, we try to create it.
+ if (serviceProvider == null) {
+ mServiceMap.put(slotId, createNetworkServiceProvider(slotId));
}
break;
+ case NETWORK_SERVICE_REMOVE_NETWORK_SERVICE_PROVIDER:
+ // If the service provider doesn't exist yet, we try to create it.
+ if (serviceProvider != null) {
+ serviceProvider.onDestroy();
+ mServiceMap.remove(slotId);
+ }
+ break;
+ case NETWORK_SERVICE_REMOVE_ALL_NETWORK_SERVICE_PROVIDERS:
+ for (int i = 0; i < mServiceMap.size(); i++) {
+ serviceProvider = mServiceMap.get(i);
+ if (serviceProvider != null) {
+ serviceProvider.onDestroy();
+ }
+ }
+ mServiceMap.clear();
+ break;
case NETWORK_SERVICE_GET_REGISTRATION_STATE:
- if (service == null) break;
+ if (serviceProvider == null) break;
int domainId = message.arg2;
- service.getNetworkRegistrationState(domainId,
+ serviceProvider.getNetworkRegistrationState(domainId,
new NetworkServiceCallback(callback));
break;
case NETWORK_SERVICE_REGISTER_FOR_STATE_CHANGE:
- if (service == null) break;
- service.registerForStateChanged(callback);
+ if (serviceProvider == null) break;
+ serviceProvider.registerForStateChanged(callback);
break;
case NETWORK_SERVICE_UNREGISTER_FOR_STATE_CHANGE:
- if (service == null) break;
- service.unregisterForStateChanged(callback);
+ if (serviceProvider == null) break;
+ serviceProvider.unregisterForStateChanged(callback);
break;
case NETWORK_SERVICE_INDICATION_NETWORK_STATE_CHANGED:
- if (service == null) break;
- service.notifyStateChangedToCallbacks();
+ if (serviceProvider == null) break;
+ serviceProvider.notifyStateChangedToCallbacks();
break;
default:
break;
@@ -212,47 +227,14 @@
return null;
}
- int slotId = intent.getIntExtra(
- NETWORK_SERVICE_EXTRA_SLOT_ID, SubscriptionManager.INVALID_SIM_SLOT_INDEX);
-
- if (!SubscriptionManager.isValidSlotIndex(slotId)) {
- loge("Invalid slot id " + slotId);
- return null;
- }
-
- log("onBind: slot id=" + slotId);
-
- INetworkServiceWrapper binder = mBinderMap.get(slotId);
- if (binder == null) {
- Message msg = mHandler.obtainMessage(
- NETWORK_SERVICE_INTERNAL_REQUEST_INITIALIZE_SERVICE);
- msg.arg1 = slotId;
- msg.sendToTarget();
-
- binder = new INetworkServiceWrapper(slotId);
- mBinderMap.put(slotId, binder);
- }
-
- return binder;
+ return mBinder;
}
/** @hide */
@Override
public boolean onUnbind(Intent intent) {
- int slotId = intent.getIntExtra(NETWORK_SERVICE_EXTRA_SLOT_ID,
- SubscriptionManager.INVALID_SIM_SLOT_INDEX);
- if (mBinderMap.get(slotId) != null) {
- NetworkServiceProvider serviceImpl;
- synchronized (mServiceMap) {
- serviceImpl = mServiceMap.get(slotId);
- }
- // We assume only one component might bind to the service. So if onUnbind is ever
- // called, we destroy the serviceImpl.
- if (serviceImpl != null) {
- serviceImpl.onDestroy();
- }
- mBinderMap.remove(slotId);
- }
+ mHandler.obtainMessage(NETWORK_SERVICE_REMOVE_ALL_NETWORK_SERVICE_PROVIDERS, 0,
+ 0, null).sendToTarget();
return false;
}
@@ -260,16 +242,6 @@
/** @hide */
@Override
public void onDestroy() {
- synchronized (mServiceMap) {
- for (int i = 0; i < mServiceMap.size(); i++) {
- NetworkServiceProvider serviceImpl = mServiceMap.get(i);
- if (serviceImpl != null) {
- serviceImpl.onDestroy();
- }
- }
- mServiceMap.clear();
- }
-
mHandlerThread.quit();
}
@@ -279,27 +251,36 @@
*/
private class INetworkServiceWrapper extends INetworkService.Stub {
- private final int mSlotId;
-
- INetworkServiceWrapper(int slotId) {
- mSlotId = slotId;
+ @Override
+ public void createNetworkServiceProvider(int slotId) {
+ mHandler.obtainMessage(NETWORK_SERVICE_CREATE_NETWORK_SERVICE_PROVIDER, slotId,
+ 0, null).sendToTarget();
}
@Override
- public void getNetworkRegistrationState(int domain, INetworkServiceCallback callback) {
- mHandler.obtainMessage(NETWORK_SERVICE_GET_REGISTRATION_STATE, mSlotId,
+ public void removeNetworkServiceProvider(int slotId) {
+ mHandler.obtainMessage(NETWORK_SERVICE_REMOVE_NETWORK_SERVICE_PROVIDER, slotId,
+ 0, null).sendToTarget();
+ }
+
+ @Override
+ public void getNetworkRegistrationState(
+ int slotId, int domain, INetworkServiceCallback callback) {
+ mHandler.obtainMessage(NETWORK_SERVICE_GET_REGISTRATION_STATE, slotId,
domain, callback).sendToTarget();
}
@Override
- public void registerForNetworkRegistrationStateChanged(INetworkServiceCallback callback) {
- mHandler.obtainMessage(NETWORK_SERVICE_REGISTER_FOR_STATE_CHANGE, mSlotId,
+ public void registerForNetworkRegistrationStateChanged(
+ int slotId, INetworkServiceCallback callback) {
+ mHandler.obtainMessage(NETWORK_SERVICE_REGISTER_FOR_STATE_CHANGE, slotId,
0, callback).sendToTarget();
}
@Override
- public void unregisterForNetworkRegistrationStateChanged(INetworkServiceCallback callback) {
- mHandler.obtainMessage(NETWORK_SERVICE_UNREGISTER_FOR_STATE_CHANGE, mSlotId,
+ public void unregisterForNetworkRegistrationStateChanged(
+ int slotId,INetworkServiceCallback callback) {
+ mHandler.obtainMessage(NETWORK_SERVICE_UNREGISTER_FOR_STATE_CHANGE, slotId,
0, callback).sendToTarget();
}
}
@@ -311,4 +292,4 @@
private final void loge(String s) {
Rlog.e(TAG, s);
}
-}
\ No newline at end of file
+}
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index 77706e8..90a3677 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -17,6 +17,7 @@
package android.telephony;
import android.annotation.IntDef;
+import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.os.Bundle;
import android.os.Parcel;
@@ -25,6 +26,7 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;
@@ -36,6 +38,7 @@
*
* <ul>
* <li>Service state: IN_SERVICE, OUT_OF_SERVICE, EMERGENCY_ONLY, POWER_OFF
+ * <li>Duplex mode: UNKNOWN, FDD, TDD
* <li>Roaming indicator
* <li>Operator name, short name and numeric id
* <li>Network selection mode
@@ -71,6 +74,26 @@
*/
public static final int STATE_POWER_OFF = 3;
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({DUPLEX_MODE_UNKNOWN, DUPLEX_MODE_FDD, DUPLEX_MODE_TDD})
+ public @interface DuplexMode {}
+
+ /**
+ * Duplex mode for the phone is unknown.
+ */
+ public static final int DUPLEX_MODE_UNKNOWN = 0;
+
+ /**
+ * Duplex mode for the phone is frequency-division duplexing.
+ */
+ public static final int DUPLEX_MODE_FDD = 1;
+
+ /**
+ * Duplex mode for the phone is time-division duplexing.
+ */
+ public static final int DUPLEX_MODE_TDD = 2;
+
/**
* RIL level registration state values from ril.h
* ((const char **)response)[0] is registration state 0-6,
@@ -286,6 +309,9 @@
private boolean mIsUsingCarrierAggregation;
+ private int mChannelNumber;
+ private int[] mCellBandwidths = new int[0];
+
/* EARFCN stands for E-UTRA Absolute Radio Frequency Channel Number,
* Reference: 3GPP TS 36.104 5.4.3 */
private int mLteEarfcnRsrpBoost = 0;
@@ -405,6 +431,8 @@
mLteEarfcnRsrpBoost = in.readInt();
mNetworkRegistrationStates = new ArrayList<>();
in.readList(mNetworkRegistrationStates, NetworkRegistrationState.class.getClassLoader());
+ mChannelNumber = in.readInt();
+ mCellBandwidths = in.createIntArray();
}
public void writeToParcel(Parcel out, int flags) {
@@ -433,6 +461,8 @@
out.writeInt(mIsUsingCarrierAggregation ? 1 : 0);
out.writeInt(mLteEarfcnRsrpBoost);
out.writeList(mNetworkRegistrationStates);
+ out.writeInt(mChannelNumber);
+ out.writeIntArray(mCellBandwidths);
}
public int describeContents() {
@@ -486,6 +516,43 @@
}
/**
+ * Get the current duplex mode
+ *
+ * @see #DUPLEX_MODE_UNKNOWN
+ * @see #DUPLEX_MODE_FDD
+ * @see #DUPLEX_MODE_TDD
+ *
+ * @return Current {@code DuplexMode} for the phone
+ */
+ @DuplexMode
+ public int getDuplexMode() {
+ // TODO(b/72117602) determine duplex mode from channel number, using 3GPP 36.101 sections
+ // 5.7.3-1 and 5.5-1
+ return DUPLEX_MODE_UNKNOWN;
+ }
+
+ /**
+ * Get the channel number of the current primary serving cell, or -1 if unknown
+ *
+ * <p>This is EARFCN for LTE, UARFCN for UMTS, and ARFCN for GSM.
+ *
+ * @return Channel number of primary serving cell
+ */
+ public int getChannelNumber() {
+ return mChannelNumber;
+ }
+
+ /**
+ * Get an array of cell bandwidths (kHz) for the current serving cells
+ *
+ * @return Current serving cell bandwidths
+ */
+ @Nullable
+ public int[] getCellBandwidths() {
+ return mCellBandwidths;
+ }
+
+ /**
* Get current roaming indicator of phone
* (note: not just decoding from TS 27.007 7.2)
*
@@ -713,6 +780,8 @@
+ (mDataRegState * 37)
+ mVoiceRoamingType
+ mDataRoamingType
+ + mChannelNumber
+ + Arrays.hashCode(mCellBandwidths)
+ (mIsManualNetworkSelection ? 1 : 0)
+ ((null == mVoiceOperatorAlphaLong) ? 0 : mVoiceOperatorAlphaLong.hashCode())
+ ((null == mVoiceOperatorAlphaShort) ? 0 : mVoiceOperatorAlphaShort.hashCode())
@@ -745,6 +814,8 @@
&& mIsManualNetworkSelection == s.mIsManualNetworkSelection
&& mVoiceRoamingType == s.mVoiceRoamingType
&& mDataRoamingType == s.mDataRoamingType
+ && mChannelNumber == s.mChannelNumber
+ && Arrays.equals(mCellBandwidths, s.mCellBandwidths)
&& equalsHandlesNulls(mVoiceOperatorAlphaLong, s.mVoiceOperatorAlphaLong)
&& equalsHandlesNulls(mVoiceOperatorAlphaShort, s.mVoiceOperatorAlphaShort)
&& equalsHandlesNulls(mVoiceOperatorNumeric, s.mVoiceOperatorNumeric)
@@ -874,6 +945,8 @@
.append("(" + rilServiceStateToString(mVoiceRegState) + ")")
.append(", mDataRegState=").append(mDataRegState)
.append("(" + rilServiceStateToString(mDataRegState) + ")")
+ .append(", mChannelNumber=").append(mChannelNumber)
+ .append(", mCellBandwidths=").append(Arrays.toString(mCellBandwidths))
.append(", mVoiceRoamingType=").append(getRoamingLogString(mVoiceRoamingType))
.append(", mDataRoamingType=").append(getRoamingLogString(mDataRoamingType))
.append(", mVoiceOperatorAlphaLong=").append(mVoiceOperatorAlphaLong)
@@ -905,6 +978,8 @@
mDataRegState = state;
mVoiceRoamingType = ROAMING_TYPE_NOT_ROAMING;
mDataRoamingType = ROAMING_TYPE_NOT_ROAMING;
+ mChannelNumber = -1;
+ mCellBandwidths = new int[0];
mVoiceOperatorAlphaLong = null;
mVoiceOperatorAlphaShort = null;
mVoiceOperatorNumeric = null;
@@ -953,6 +1028,16 @@
if (VDBG) Rlog.d(LOG_TAG, "[ServiceState] setDataRegState=" + mDataRegState);
}
+ /** @hide */
+ public void setCellBandwidths(int[] bandwidths) {
+ mCellBandwidths = bandwidths;
+ }
+
+ /** @hide */
+ public void setChannelNumber(int channelNumber) {
+ mChannelNumber = channelNumber;
+ }
+
public void setRoaming(boolean roaming) {
mVoiceRoamingType = (roaming ? ROAMING_TYPE_UNKNOWN : ROAMING_TYPE_NOT_ROAMING);
mDataRoamingType = mVoiceRoamingType;
@@ -1101,6 +1186,8 @@
mIsDataRoamingFromRegistration = m.getBoolean("isDataRoamingFromRegistration");
mIsUsingCarrierAggregation = m.getBoolean("isUsingCarrierAggregation");
mLteEarfcnRsrpBoost = m.getInt("LteEarfcnRsrpBoost");
+ mChannelNumber = m.getInt("ChannelNumber");
+ mCellBandwidths = m.getIntArray("CellBandwidths");
}
/**
@@ -1132,6 +1219,8 @@
m.putBoolean("isDataRoamingFromRegistration", mIsDataRoamingFromRegistration);
m.putBoolean("isUsingCarrierAggregation", mIsUsingCarrierAggregation);
m.putInt("LteEarfcnRsrpBoost", mLteEarfcnRsrpBoost);
+ m.putInt("ChannelNumber", mChannelNumber);
+ m.putIntArray("CellBandwidths", mCellBandwidths);
}
/** @hide */
diff --git a/telephony/java/com/android/internal/telephony/uicc/IccUtils.java b/telephony/java/com/android/internal/telephony/uicc/IccUtils.java
index 9f8b3a8..c095438 100644
--- a/telephony/java/com/android/internal/telephony/uicc/IccUtils.java
+++ b/telephony/java/com/android/internal/telephony/uicc/IccUtils.java
@@ -837,6 +837,13 @@
}
/**
+ * Strip all the trailing 'F' characters of a string, e.g., an ICCID.
+ */
+ public static String stripTrailingFs(String s) {
+ return s == null ? null : s.replaceAll("(?i)f*$", "");
+ }
+
+ /**
* Converts a character of [0-9a-aA-F] to its hex value in a byte. If the character is not a
* hex number, 0 will be returned.
*/