Merge "Remove NetworkParcelable"
diff --git a/Android.bp b/Android.bp
index 0d22ec0..8ffb11d 100644
--- a/Android.bp
+++ b/Android.bp
@@ -201,6 +201,7 @@
"core/java/android/net/INetworkScoreService.aidl",
"core/java/android/net/INetworkStatsService.aidl",
"core/java/android/net/INetworkStatsSession.aidl",
+ "core/java/android/net/ISocketKeepaliveCallback.aidl",
"core/java/android/net/ITestNetworkManager.aidl",
"core/java/android/net/ITetheringEventCallback.aidl",
"core/java/android/net/ITetheringStatsProvider.aidl",
@@ -1700,4 +1701,4 @@
name: "framework-aidl-mappings",
srcs: [":framework-defaults"],
output: "framework-aidl-mappings.txt"
-}
\ No newline at end of file
+}
diff --git a/api/current.txt b/api/current.txt
index 9553bf6..0fa6cc6 100755
--- a/api/current.txt
+++ b/api/current.txt
@@ -41276,9 +41276,9 @@
public abstract class CallRedirectionService extends android.app.Service {
ctor public CallRedirectionService();
method public final void cancelCall();
- method public final android.os.IBinder onBind(android.content.Intent);
+ method @Nullable public final android.os.IBinder onBind(@NonNull android.content.Intent);
method public abstract void onPlaceCall(@NonNull android.net.Uri, @NonNull android.telecom.PhoneAccountHandle, boolean);
- method public final boolean onUnbind(android.content.Intent);
+ method public final boolean onUnbind(@NonNull android.content.Intent);
method public final void placeCallUnmodified();
method public final void redirectCall(@NonNull android.net.Uri, @NonNull android.telecom.PhoneAccountHandle, boolean);
field public static final String SERVICE_INTERFACE = "android.telecom.CallRedirectionService";
@@ -42099,9 +42099,10 @@
}
public final class AvailableNetworkInfo implements android.os.Parcelable {
- ctor public AvailableNetworkInfo(int, int, java.util.List<java.lang.String>);
+ ctor public AvailableNetworkInfo(int, int, @NonNull java.util.List<java.lang.String>, @NonNull java.util.List<java.lang.Integer>);
method public int describeContents();
- method public java.util.List<java.lang.String> getMccMncs();
+ method @NonNull public java.util.List<java.lang.Integer> getBands();
+ method @NonNull public java.util.List<java.lang.String> getMccMncs();
method public int getPriority();
method public int getSubId();
method public void writeToParcel(android.os.Parcel, int);
@@ -43117,7 +43118,7 @@
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setNetworkSelectionModeManual(String, boolean);
method public boolean setOperatorBrandOverride(String);
method public boolean setPreferredNetworkTypeToGlobal();
- method public boolean setPreferredOpportunisticDataSubscription(int);
+ method public void setPreferredOpportunisticDataSubscription(int, boolean, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.Consumer<java.lang.Integer>);
method public void setVisualVoicemailSmsFilterSettings(android.telephony.VisualVoicemailSmsFilterSettings);
method public boolean setVoiceMailNumber(String, String);
method @Deprecated public void setVoicemailRingtoneUri(android.telecom.PhoneAccountHandle, android.net.Uri);
diff --git a/api/system-current.txt b/api/system-current.txt
index 568010b..849035d 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -5508,9 +5508,10 @@
package android.telephony {
- public static final class AccessNetworkConstants.TransportType {
- field public static final int WLAN = 2; // 0x2
- field public static final int WWAN = 1; // 0x1
+ public final class AccessNetworkConstants {
+ field public static final int TRANSPORT_TYPE_INVALID = -1; // 0xffffffff
+ field public static final int TRANSPORT_TYPE_WLAN = 2; // 0x2
+ field public static final int TRANSPORT_TYPE_WWAN = 1; // 0x1
}
public final class CallAttributes implements android.os.Parcelable {
@@ -5585,6 +5586,7 @@
field public static final int ACCESS_BLOCK_ALL = 2088; // 0x828
field public static final int ACCESS_CLASS_DSAC_REJECTION = 2108; // 0x83c
field public static final int ACCESS_CONTROL_LIST_CHECK_FAILURE = 2128; // 0x850
+ field public static final int ACCESS_PROBE_LIMIT_REACHED = 2079; // 0x81f
field public static final int ACTIVATION_REJECTED_BCM_VIOLATION = 48; // 0x30
field public static final int ACTIVATION_REJECT_GGSN = 30; // 0x1e
field public static final int ACTIVATION_REJECT_UNSPECIFIED = 31; // 0x1f
@@ -5699,7 +5701,9 @@
field public static final int INVALID_PRIMARY_NSAPI = 2158; // 0x86e
field public static final int INVALID_SIM_STATE = 2224; // 0x8b0
field public static final int INVALID_TRANSACTION_ID = 81; // 0x51
+ field public static final int IPV4_CONNECTIONS_LIMIT_REACHED = 2052; // 0x804
field public static final int IPV6_ADDRESS_TRANSFER_FAILED = 2047; // 0x7ff
+ field public static final int IPV6_CONNECTIONS_LIMIT_REACHED = 2053; // 0x805
field public static final int IPV6_PREFIX_UNAVAILABLE = 2250; // 0x8ca
field public static final int IP_ADDRESS_MISMATCH = 119; // 0x77
field public static final int IP_VERSION_MISMATCH = 2055; // 0x807
@@ -5718,10 +5722,6 @@
field public static final int MAC_FAILURE = 2183; // 0x887
field public static final int MAXIMIUM_NSAPIS_EXCEEDED = 2157; // 0x86d
field public static final int MAXINUM_SIZE_OF_L2_MESSAGE_EXCEEDED = 2166; // 0x876
- field public static final int MAX_ACCESS_PROBE = 2079; // 0x81f
- field public static final int MAX_IPV4_CONNECTIONS = 2052; // 0x804
- field public static final int MAX_IPV6_CONNECTIONS = 2053; // 0x805
- field public static final int MAX_PPP_INACTIVITY_TIMER_EXPIRED = 2046; // 0x7fe
field public static final int MESSAGE_INCORRECT_SEMANTIC = 95; // 0x5f
field public static final int MESSAGE_TYPE_UNSUPPORTED = 97; // 0x61
field public static final int MIP_CONFIG_FAILURE = 2050; // 0x802
@@ -5830,6 +5830,7 @@
field public static final int PPP_AUTH_FAILURE = 2229; // 0x8b5
field public static final int PPP_CHAP_FAILURE = 2232; // 0x8b8
field public static final int PPP_CLOSE_IN_PROGRESS = 2233; // 0x8b9
+ field public static final int PPP_INACTIVITY_TIMER_EXPIRED = 2046; // 0x7fe
field public static final int PPP_OPTION_MISMATCH = 2230; // 0x8b6
field public static final int PPP_PAP_FAILURE = 2231; // 0x8b7
field public static final int PPP_TIMEOUT = 2228; // 0x8b4
@@ -6314,7 +6315,7 @@
method public void requestEmbeddedSubscriptionInfoListRefresh(int);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDefaultDataSubId(int);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDefaultSmsSubId(int);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setPreferredDataSubscriptionId(int, boolean, @NonNull java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Integer>);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setPreferredDataSubscriptionId(int, boolean, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.Consumer<java.lang.Integer>);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setSubscriptionEnabled(int, boolean);
field @NonNull public static final android.net.Uri ADVANCED_CALLING_ENABLED_CONTENT_URI;
field public static final int PROFILE_CLASS_DEFAULT = -1; // 0xffffffff
@@ -6382,7 +6383,7 @@
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean getEmergencyCallbackMode();
method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getIsimDomain();
method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getIsimIst();
- method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.List<android.util.Pair<java.lang.Integer,java.lang.Integer>> getLogicalToPhysicalSlotMapping();
+ method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.Map<java.lang.Integer,java.lang.Integer> getLogicalToPhysicalSlotMapping();
method public static long getMaxNumberVerificationTimeoutMillis();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getPreferredNetworkTypeBitmap();
method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public int getRadioPowerState();
diff --git a/api/test-current.txt b/api/test-current.txt
index d43b1c4..6372197 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -234,6 +234,7 @@
method public android.os.UserHandle getUser();
method public int getUserId();
method public void setAutofillCompatibilityEnabled(boolean);
+ field public static final String TEST_NETWORK_SERVICE = "test_network";
}
}
diff --git a/config/hiddenapi-greylist.txt b/config/hiddenapi-greylist.txt
index b02cf48..0959462 100644
--- a/config/hiddenapi-greylist.txt
+++ b/config/hiddenapi-greylist.txt
@@ -3053,7 +3053,6 @@
Lcom/android/internal/telephony/SMSDispatcher;->mResolver:Landroid/content/ContentResolver;
Lcom/android/internal/telephony/SMSDispatcher;->mTelephonyManager:Landroid/telephony/TelephonyManager;
Lcom/android/internal/telephony/SMSDispatcher;->processSendSmsResponse(Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;II)V
-Lcom/android/internal/telephony/SMSDispatcher;->sendData(Ljava/lang/String;Ljava/lang/String;I[BLandroid/app/PendingIntent;Landroid/app/PendingIntent;)V
Lcom/android/internal/telephony/SMSDispatcher;->sendMultipartSms(Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;)V
Lcom/android/internal/telephony/SMSDispatcher;->sendSms(Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;)V
Lcom/android/internal/telephony/SMSDispatcher;->sendSubmitPdu(Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;)V
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index e92efde..a3ee849 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -84,11 +84,13 @@
import android.net.IIpMemoryStore;
import android.net.IIpSecService;
import android.net.INetworkPolicyManager;
+import android.net.ITestNetworkManager;
import android.net.IpMemoryStore;
import android.net.IpSecManager;
import android.net.NetworkPolicyManager;
import android.net.NetworkScoreManager;
import android.net.NetworkWatchlistManager;
+import android.net.TestNetworkManager;
import android.net.lowpan.ILowpanManager;
import android.net.lowpan.LowpanManager;
import android.net.nsd.INsdManager;
@@ -126,6 +128,7 @@
import android.os.IncidentManager;
import android.os.PowerManager;
import android.os.RecoverySystem;
+import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.ServiceManager.ServiceNotFoundException;
import android.os.SystemUpdateManager;
@@ -315,6 +318,29 @@
return new IpSecManager(ctx, service);
}});
+ registerService(
+ Context.TEST_NETWORK_SERVICE,
+ TestNetworkManager.class,
+ new StaticApplicationContextServiceFetcher<TestNetworkManager>() {
+ @Override
+ public TestNetworkManager createService(Context context)
+ throws ServiceNotFoundException {
+ IBinder csBinder =
+ ServiceManager.getServiceOrThrow(Context.CONNECTIVITY_SERVICE);
+ IConnectivityManager csMgr =
+ IConnectivityManager.Stub.asInterface(csBinder);
+
+ final IBinder tnBinder;
+ try {
+ tnBinder = csMgr.startOrGetTestNetworkService();
+ } catch (RemoteException e) {
+ throw new ServiceNotFoundException(Context.TEST_NETWORK_SERVICE);
+ }
+ ITestNetworkManager tnMgr = ITestNetworkManager.Stub.asInterface(tnBinder);
+ return new TestNetworkManager(context, tnMgr);
+ }
+ });
+
registerService(Context.COUNTRY_DETECTOR, CountryDetector.class,
new StaticServiceFetcher<CountryDetector>() {
@Override
diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java
index 171c2f5..9faa1d6 100644
--- a/core/java/android/bluetooth/BluetoothA2dp.java
+++ b/core/java/android/bluetooth/BluetoothA2dp.java
@@ -224,8 +224,10 @@
if (VDBG) Log.d(TAG, "Unbinding service...");
try {
mServiceLock.writeLock().lock();
- mService = null;
- mContext.unbindService(mConnection);
+ if (mService != null) {
+ mService = null;
+ mContext.unbindService(mConnection);
+ }
} catch (Exception re) {
Log.e(TAG, "", re);
} finally {
diff --git a/core/java/android/bluetooth/BluetoothHidHost.java b/core/java/android/bluetooth/BluetoothHidHost.java
index 0ca39f1..289e769 100644
--- a/core/java/android/bluetooth/BluetoothHidHost.java
+++ b/core/java/android/bluetooth/BluetoothHidHost.java
@@ -232,8 +232,10 @@
if (VDBG) Log.d(TAG, "Unbinding service...");
synchronized (mConnection) {
try {
- mService = null;
- mContext.unbindService(mConnection);
+ if (mService != null) {
+ mService = null;
+ mContext.unbindService(mConnection);
+ }
} catch (Exception re) {
Log.e(TAG, "", re);
}
diff --git a/core/java/android/bluetooth/BluetoothPbap.java b/core/java/android/bluetooth/BluetoothPbap.java
index ae264e1..b303c34 100644
--- a/core/java/android/bluetooth/BluetoothPbap.java
+++ b/core/java/android/bluetooth/BluetoothPbap.java
@@ -120,8 +120,10 @@
log("Unbinding service...");
synchronized (mConnection) {
try {
- mService = null;
- mContext.unbindService(mConnection);
+ if (mService != null) {
+ mService = null;
+ mContext.unbindService(mConnection);
+ }
} catch (Exception re) {
Log.e(TAG, "", re);
}
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 136657f..5a75d5df 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -3016,6 +3016,7 @@
CONNECTIVITY_SERVICE,
//@hide: IP_MEMORY_STORE_SERVICE,
IPSEC_SERVICE,
+ TEST_NETWORK_SERVICE,
//@hide: UPDATE_LOCK_SERVICE,
//@hide: NETWORKMANAGEMENT_SERVICE,
NETWORK_STATS_SERVICE,
@@ -3539,6 +3540,15 @@
/**
* Use with {@link #getSystemService(String)} to retrieve a {@link
+ * android.net.TestNetworkManager} for building TUNs and limited-use Networks
+ *
+ * @see #getSystemService(String)
+ * @hide
+ */
+ @TestApi public static final String TEST_NETWORK_SERVICE = "test_network";
+
+ /**
+ * Use with {@link #getSystemService(String)} to retrieve a {@link
* android.os.IUpdateLock} for managing runtime sequences that
* must not be interrupted by headless OTA application or similar.
*
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 2a357ff..d08379f 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -38,7 +38,6 @@
import android.os.Build.VERSION_CODES;
import android.os.Bundle;
import android.os.Handler;
-import android.os.HandlerThread;
import android.os.IBinder;
import android.os.INetworkActivityListener;
import android.os.INetworkManagementService;
@@ -75,6 +74,9 @@
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executor;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.RejectedExecutionException;
/**
* Class that answers queries about the state of network connectivity. It also
@@ -1813,23 +1815,26 @@
public static final int MIN_INTERVAL = 10;
private final Network mNetwork;
- private final PacketKeepaliveCallback mCallback;
- private final Looper mLooper;
- private final Messenger mMessenger;
+ private final ISocketKeepaliveCallback mCallback;
+ private final ExecutorService mExecutor;
private volatile Integer mSlot;
- void stopLooper() {
- mLooper.quit();
- }
-
@UnsupportedAppUsage
public void stop() {
try {
- mService.stopKeepalive(mNetwork, mSlot);
- } catch (RemoteException e) {
- Log.e(TAG, "Error stopping packet keepalive: ", e);
- stopLooper();
+ mExecutor.execute(() -> {
+ try {
+ if (mSlot != null) {
+ mService.stopKeepalive(mNetwork, mSlot);
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error stopping packet keepalive: ", e);
+ throw e.rethrowFromSystemServer();
+ }
+ });
+ } catch (RejectedExecutionException e) {
+ // The internal executor has already stopped due to previous event.
}
}
@@ -1837,40 +1842,43 @@
Preconditions.checkNotNull(network, "network cannot be null");
Preconditions.checkNotNull(callback, "callback cannot be null");
mNetwork = network;
- mCallback = callback;
- HandlerThread thread = new HandlerThread(TAG);
- thread.start();
- mLooper = thread.getLooper();
- mMessenger = new Messenger(new Handler(mLooper) {
+ mExecutor = Executors.newSingleThreadExecutor();
+ mCallback = new ISocketKeepaliveCallback.Stub() {
@Override
- public void handleMessage(Message message) {
- switch (message.what) {
- case NetworkAgent.EVENT_SOCKET_KEEPALIVE:
- int error = message.arg2;
- try {
- if (error == SUCCESS) {
- if (mSlot == null) {
- mSlot = message.arg1;
- mCallback.onStarted();
- } else {
- mSlot = null;
- stopLooper();
- mCallback.onStopped();
- }
- } else {
- stopLooper();
- mCallback.onError(error);
- }
- } catch (Exception e) {
- Log.e(TAG, "Exception in keepalive callback(" + error + ")", e);
- }
- break;
- default:
- Log.e(TAG, "Unhandled message " + Integer.toHexString(message.what));
- break;
- }
+ public void onStarted(int slot) {
+ Binder.withCleanCallingIdentity(() ->
+ mExecutor.execute(() -> {
+ mSlot = slot;
+ callback.onStarted();
+ }));
}
- });
+
+ @Override
+ public void onStopped() {
+ Binder.withCleanCallingIdentity(() ->
+ mExecutor.execute(() -> {
+ mSlot = null;
+ callback.onStopped();
+ }));
+ mExecutor.shutdown();
+ }
+
+ @Override
+ public void onError(int error) {
+ Binder.withCleanCallingIdentity(() ->
+ mExecutor.execute(() -> {
+ mSlot = null;
+ callback.onError(error);
+ }));
+ mExecutor.shutdown();
+ }
+
+ @Override
+ public void onDataReceived() {
+ // PacketKeepalive is only used for Nat-T keepalive and as such does not invoke
+ // this callback when data is received.
+ }
+ };
}
}
@@ -1887,12 +1895,11 @@
InetAddress srcAddr, int srcPort, InetAddress dstAddr) {
final PacketKeepalive k = new PacketKeepalive(network, callback);
try {
- mService.startNattKeepalive(network, intervalSeconds, k.mMessenger, new Binder(),
+ mService.startNattKeepalive(network, intervalSeconds, k.mCallback,
srcAddr.getHostAddress(), srcPort, dstAddr.getHostAddress());
} catch (RemoteException e) {
Log.e(TAG, "Error starting packet keepalive: ", e);
- k.stopLooper();
- return null;
+ throw e.rethrowFromSystemServer();
}
return k;
}
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index 403b44d..24e6a85 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -27,6 +27,7 @@
import android.net.NetworkQuotaInfo;
import android.net.NetworkRequest;
import android.net.NetworkState;
+import android.net.ISocketKeepaliveCallback;
import android.net.ProxyInfo;
import android.os.Bundle;
import android.os.IBinder;
@@ -194,15 +195,15 @@
void factoryReset();
- void startNattKeepalive(in Network network, int intervalSeconds, in Messenger messenger,
- in IBinder binder, String srcAddr, int srcPort, String dstAddr);
+ void startNattKeepalive(in Network network, int intervalSeconds,
+ in ISocketKeepaliveCallback cb, String srcAddr, int srcPort, String dstAddr);
void startNattKeepaliveWithFd(in Network network, in FileDescriptor fd, int resourceId,
- int intervalSeconds, in Messenger messenger, in IBinder binder, String srcAddr,
+ int intervalSeconds, in ISocketKeepaliveCallback cb, String srcAddr,
String dstAddr);
void startTcpKeepalive(in Network network, in FileDescriptor fd, int intervalSeconds,
- in Messenger messenger, in IBinder binder);
+ in ISocketKeepaliveCallback cb);
void stopKeepalive(in Network network, int slot);
@@ -219,4 +220,6 @@
void registerTetheringEventCallback(ITetheringEventCallback callback, String callerPkg);
void unregisterTetheringEventCallback(ITetheringEventCallback callback, String callerPkg);
+
+ IBinder startOrGetTestNetworkService();
}
diff --git a/core/java/android/net/ISocketKeepaliveCallback.aidl b/core/java/android/net/ISocketKeepaliveCallback.aidl
new file mode 100644
index 0000000..020fbca
--- /dev/null
+++ b/core/java/android/net/ISocketKeepaliveCallback.aidl
@@ -0,0 +1,34 @@
+/**
+ * Copyright (c) 2019, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+/**
+ * Callback to provide status changes of keepalive offload.
+ *
+ * @hide
+ */
+oneway interface ISocketKeepaliveCallback
+{
+ /** The keepalive was successfully started. */
+ void onStarted(int slot);
+ /** The keepalive was successfully stopped. */
+ void onStopped();
+ /** The keepalive was stopped because of an error. */
+ void onError(int error);
+ /** The keepalive on a TCP socket was stopped because the socket received data. */
+ void onDataReceived();
+}
diff --git a/core/java/android/net/NattSocketKeepalive.java b/core/java/android/net/NattSocketKeepalive.java
index 88631ae..84da294 100644
--- a/core/java/android/net/NattSocketKeepalive.java
+++ b/core/java/android/net/NattSocketKeepalive.java
@@ -17,7 +17,6 @@
package android.net;
import android.annotation.NonNull;
-import android.os.Binder;
import android.os.RemoteException;
import android.util.Log;
@@ -52,24 +51,30 @@
@Override
void startImpl(int intervalSec) {
- try {
- mService.startNattKeepaliveWithFd(mNetwork, mFd, mResourceId, intervalSec, mMessenger,
- new Binder(), mSource.getHostAddress(), mDestination.getHostAddress());
- } catch (RemoteException e) {
- Log.e(TAG, "Error starting packet keepalive: ", e);
- stopLooper();
- }
+ mExecutor.execute(() -> {
+ try {
+ mService.startNattKeepaliveWithFd(mNetwork, mFd, mResourceId, intervalSec,
+ mCallback,
+ mSource.getHostAddress(), mDestination.getHostAddress());
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error starting socket keepalive: ", e);
+ throw e.rethrowFromSystemServer();
+ }
+ });
}
@Override
void stopImpl() {
- try {
- if (mSlot != null) {
- mService.stopKeepalive(mNetwork, mSlot);
+ mExecutor.execute(() -> {
+ try {
+ if (mSlot != null) {
+ mService.stopKeepalive(mNetwork, mSlot);
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error stopping socket keepalive: ", e);
+ throw e.rethrowFromSystemServer();
}
- } catch (RemoteException e) {
- Log.e(TAG, "Error stopping packet keepalive: ", e);
- stopLooper();
- }
+ });
+
}
}
diff --git a/core/java/android/net/SocketKeepalive.java b/core/java/android/net/SocketKeepalive.java
index 07728be..0e768df 100644
--- a/core/java/android/net/SocketKeepalive.java
+++ b/core/java/android/net/SocketKeepalive.java
@@ -20,13 +20,8 @@
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.Looper;
-import android.os.Message;
-import android.os.Messenger;
-import android.os.Process;
-import android.util.Log;
+import android.os.Binder;
+import android.os.RemoteException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -152,10 +147,9 @@
@NonNull final IConnectivityManager mService;
@NonNull final Network mNetwork;
- @NonNull private final Executor mExecutor;
- @NonNull private final SocketKeepalive.Callback mCallback;
- @NonNull private final Looper mLooper;
- @NonNull final Messenger mMessenger;
+ @NonNull final Executor mExecutor;
+ @NonNull final ISocketKeepaliveCallback mCallback;
+ // TODO: remove slot since mCallback could be used to identify which keepalive to stop.
@Nullable Integer mSlot;
SocketKeepalive(@NonNull IConnectivityManager service, @NonNull Network network,
@@ -163,53 +157,53 @@
mService = service;
mNetwork = network;
mExecutor = executor;
- mCallback = callback;
- // TODO: 1. Use other thread modeling instead of create one thread for every instance to
- // reduce the memory cost.
- // 2. support restart.
- // 3. Fix race condition which caused by rapidly start and stop.
- HandlerThread thread = new HandlerThread(TAG, Process.THREAD_PRIORITY_BACKGROUND
- + Process.THREAD_PRIORITY_LESS_FAVORABLE);
- thread.start();
- mLooper = thread.getLooper();
- mMessenger = new Messenger(new Handler(mLooper) {
+ mCallback = new ISocketKeepaliveCallback.Stub() {
@Override
- public void handleMessage(Message message) {
- switch (message.what) {
- case NetworkAgent.EVENT_SOCKET_KEEPALIVE:
- final int status = message.arg2;
- try {
- if (status == SUCCESS) {
- if (mSlot == null) {
- mSlot = message.arg1;
- mExecutor.execute(() -> mCallback.onStarted());
- } else {
- mSlot = null;
- stopLooper();
- mExecutor.execute(() -> mCallback.onStopped());
- }
- } else if (status == DATA_RECEIVED) {
- stopLooper();
- mExecutor.execute(() -> mCallback.onDataReceived());
- } else {
- stopLooper();
- mExecutor.execute(() -> mCallback.onError(status));
- }
- } catch (Exception e) {
- Log.e(TAG, "Exception in keepalive callback(" + status + ")", e);
- }
- break;
- default:
- Log.e(TAG, "Unhandled message " + Integer.toHexString(message.what));
- break;
- }
+ public void onStarted(int slot) {
+ Binder.withCleanCallingIdentity(() ->
+ mExecutor.execute(() -> {
+ mSlot = slot;
+ callback.onStarted();
+ }));
}
- });
+
+ @Override
+ public void onStopped() {
+ Binder.withCleanCallingIdentity(() ->
+ executor.execute(() -> {
+ mSlot = null;
+ callback.onStopped();
+ }));
+ }
+
+ @Override
+ public void onError(int error) {
+ Binder.withCleanCallingIdentity(() ->
+ executor.execute(() -> {
+ mSlot = null;
+ callback.onError(error);
+ }));
+ }
+
+ @Override
+ public void onDataReceived() {
+ Binder.withCleanCallingIdentity(() ->
+ executor.execute(() -> {
+ mSlot = null;
+ callback.onDataReceived();
+ }));
+ }
+ };
}
/**
* Request that keepalive be started with the given {@code intervalSec}. See
- * {@link SocketKeepalive}.
+ * {@link SocketKeepalive}. If the remote binder dies, or the binder call throws an exception
+ * when invoking start or stop of the {@link SocketKeepalive}, a {@link RemoteException} will be
+ * thrown into the {@code executor}. This is typically not important to catch because the remote
+ * party is the system, so if it is not in shape to communicate through binder the system is
+ * probably going down anyway. If the caller cares regardless, it can use a custom
+ * {@link Executor} to catch the {@link RemoteException}.
*
* @param intervalSec The target interval in seconds between keepalive packet transmissions.
* The interval should be between 10 seconds and 3600 seconds, otherwise
@@ -222,12 +216,6 @@
abstract void startImpl(int intervalSec);
- /** @hide */
- protected void stopLooper() {
- // TODO: remove this after changing thread modeling.
- mLooper.quit();
- }
-
/**
* Requests that keepalive be stopped. The application must wait for {@link Callback#onStopped}
* before using the object. See {@link SocketKeepalive}.
@@ -245,7 +233,6 @@
@Override
public final void close() {
stop();
- stopLooper();
}
/**
@@ -259,7 +246,8 @@
public void onStopped() {}
/** An error occurred. */
public void onError(@ErrorCode int error) {}
- /** The keepalive on a TCP socket was stopped because the socket received data. */
+ /** The keepalive on a TCP socket was stopped because the socket received data. This is
+ * never called for UDP sockets. */
public void onDataReceived() {}
}
}
diff --git a/core/java/android/net/TcpSocketKeepalive.java b/core/java/android/net/TcpSocketKeepalive.java
index f691a0d..26cc8ff 100644
--- a/core/java/android/net/TcpSocketKeepalive.java
+++ b/core/java/android/net/TcpSocketKeepalive.java
@@ -17,7 +17,6 @@
package android.net;
import android.annotation.NonNull;
-import android.os.Binder;
import android.os.RemoteException;
import android.util.Log;
@@ -56,24 +55,28 @@
*/
@Override
void startImpl(int intervalSec) {
- try {
- final FileDescriptor fd = mSocket.getFileDescriptor$();
- mService.startTcpKeepalive(mNetwork, fd, intervalSec, mMessenger, new Binder());
- } catch (RemoteException e) {
- Log.e(TAG, "Error starting packet keepalive: ", e);
- stopLooper();
- }
+ mExecutor.execute(() -> {
+ try {
+ final FileDescriptor fd = mSocket.getFileDescriptor$();
+ mService.startTcpKeepalive(mNetwork, fd, intervalSec, mCallback);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error starting packet keepalive: ", e);
+ throw e.rethrowFromSystemServer();
+ }
+ });
}
@Override
void stopImpl() {
- try {
- if (mSlot != null) {
- mService.stopKeepalive(mNetwork, mSlot);
+ mExecutor.execute(() -> {
+ try {
+ if (mSlot != null) {
+ mService.stopKeepalive(mNetwork, mSlot);
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error stopping packet keepalive: ", e);
+ throw e.rethrowFromSystemServer();
}
- } catch (RemoteException e) {
- Log.e(TAG, "Error stopping packet keepalive: ", e);
- stopLooper();
- }
+ });
}
}
diff --git a/core/java/android/os/BugreportManager.java b/core/java/android/os/BugreportManager.java
index 672624c..f87abde 100644
--- a/core/java/android/os/BugreportManager.java
+++ b/core/java/android/os/BugreportManager.java
@@ -28,6 +28,8 @@
import com.android.internal.util.Preconditions;
+import libcore.io.IoUtils;
+
import java.io.FileDescriptor;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -124,6 +126,8 @@
* <p>The bugreport artifacts will be copied over to the given file descriptors only if the
* user consents to sharing with the calling app.
*
+ * <p>{@link BugreportManager} takes ownership of {@code bugreportFd} and {@code screenshotFd}.
+ *
* @param bugreportFd file to write the bugreport. This should be opened in write-only,
* append mode.
* @param screenshotFd file to write the screenshot, if necessary. This should be opened
@@ -137,12 +141,13 @@
@NonNull BugreportParams params,
@NonNull @CallbackExecutor Executor executor,
@NonNull BugreportCallback callback) {
- Preconditions.checkNotNull(bugreportFd);
- Preconditions.checkNotNull(params);
- Preconditions.checkNotNull(executor);
- Preconditions.checkNotNull(callback);
- DumpstateListener dsListener = new DumpstateListener(executor, callback);
try {
+ Preconditions.checkNotNull(bugreportFd);
+ Preconditions.checkNotNull(params);
+ Preconditions.checkNotNull(executor);
+ Preconditions.checkNotNull(callback);
+
+ DumpstateListener dsListener = new DumpstateListener(executor, callback);
// Note: mBinder can get callingUid from the binder transaction.
mBinder.startBugreport(-1 /* callingUid */,
mContext.getOpPackageName(),
@@ -152,6 +157,12 @@
params.getMode(), dsListener);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
+ } finally {
+ // We can close the file descriptors here because binder would have duped them.
+ IoUtils.closeQuietly(bugreportFd);
+ if (screenshotFd != null) {
+ IoUtils.closeQuietly(screenshotFd);
+ }
}
}
@@ -171,7 +182,7 @@
private final Executor mExecutor;
private final BugreportCallback mCallback;
- DumpstateListener(Executor executor, @Nullable BugreportCallback callback) {
+ DumpstateListener(Executor executor, BugreportCallback callback) {
mExecutor = executor;
mCallback = callback;
}
@@ -209,8 +220,6 @@
});
} finally {
Binder.restoreCallingIdentity(identity);
- // The bugreport has finished. Let's shutdown the service to minimize its footprint.
- cancelBugreport();
}
}
diff --git a/core/java/android/os/ParcelFileDescriptor.java b/core/java/android/os/ParcelFileDescriptor.java
index a89fc09..36b99d2 100644
--- a/core/java/android/os/ParcelFileDescriptor.java
+++ b/core/java/android/os/ParcelFileDescriptor.java
@@ -375,7 +375,11 @@
/**
* Take ownership of a raw native fd in to a new ParcelFileDescriptor.
* The returned ParcelFileDescriptor now owns the given fd, and will be
- * responsible for closing it. You must not close the fd yourself.
+ * responsible for closing it.
+ * <p>
+ * <strong>WARNING:</strong> You must not close the fd yourself after
+ * this call, and ownership of the file descriptor must have been
+ * released prior to the call to this function.
*
* @param fd The native fd that the ParcelFileDescriptor should adopt.
*
@@ -394,6 +398,16 @@
* ParcelFileDescriptor holds a dup of the original FileDescriptor in
* the Socket, so you must still close the Socket as well as the new
* ParcelFileDescriptor.
+ * <p>
+ * <strong>WARNING:</strong> Prior to API level 29, this function would not
+ * actually dup the Socket's FileDescriptor, and would take a
+ * reference to the its internal FileDescriptor instead. If the Socket
+ * gets garbage collected before the ParcelFileDescriptor, this may
+ * lead to the ParcelFileDescriptor being unexpectedly closed. To avoid
+ * this, the following pattern can be used:
+ * <pre>{@code
+ * ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(socket).dup();
+ * }</pre>
*
* @param socket The Socket whose FileDescriptor is used to create
* a new ParcelFileDescriptor.
@@ -417,6 +431,16 @@
* new ParcelFileDescriptor holds a dup of the original FileDescriptor in
* the DatagramSocket, so you must still close the DatagramSocket as well
* as the new ParcelFileDescriptor.
+ * <p>
+ * <strong>WARNING:</strong> Prior to API level 29, this function would not
+ * actually dup the DatagramSocket's FileDescriptor, and would take a
+ * reference to the its internal FileDescriptor instead. If the DatagramSocket
+ * gets garbage collected before the ParcelFileDescriptor, this may
+ * lead to the ParcelFileDescriptor being unexpectedly closed. To avoid
+ * this, the following pattern can be used:
+ * <pre>{@code
+ * ParcelFileDescriptor pfd = ParcelFileDescriptor.fromDatagramSocket(socket).dup();
+ * }</pre>
*
* @param datagramSocket The DatagramSocket whose FileDescriptor is used
* to create a new ParcelFileDescriptor.
@@ -674,6 +698,9 @@
* Return the native fd int for this ParcelFileDescriptor. The
* ParcelFileDescriptor still owns the fd, and it still must be closed
* through this API.
+ * <p>
+ * <strong>WARNING:</strong> Do not call close on the return value of this
+ * function or pass it to a function that assumes ownership of the fd.
*/
public int getFd() {
if (mWrapped != null) {
diff --git a/core/java/android/util/OWNERS b/core/java/android/util/OWNERS
index 86ed122..98297fb 100644
--- a/core/java/android/util/OWNERS
+++ b/core/java/android/util/OWNERS
@@ -1,2 +1,3 @@
per-file FeatureFlagUtils.java = sbasi@google.com
per-file FeatureFlagUtils.java = zhfan@google.com
+per-file FeatureFlagUtils.java = asapperstein@google.com
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 35bc46a..3d0b12d 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1384,6 +1384,13 @@
<permission android:name="android.permission.MANAGE_IPSEC_TUNNELS"
android:protectionLevel="signature|appop" />
+ <!-- @hide Allows apps to create and manage Test Networks.
+ <p>Granted only to shell. CTS tests will use
+ UiAutomation.AdoptShellPermissionIdentity() to gain access.
+ -->
+ <permission android:name="android.permission.MANAGE_TEST_NETWORKS"
+ android:protectionLevel="signature" />
+
<!-- @SystemApi @hide Allows applications to read Wi-Fi credential.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.READ_WIFI_CREDENTIAL"
diff --git a/media/mca/Android.mk b/media/mca/Android.mk
deleted file mode 100644
index b1ce91e..0000000
--- a/media/mca/Android.mk
+++ /dev/null
@@ -1,21 +0,0 @@
-# Copyright (C) 2011 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.
-#
-
-#
-# Build all native libraries
-#
-include $(call all-subdir-makefiles)
-
-
diff --git a/media/mca/samples/Android.mk b/media/mca/samples/Android.mk
deleted file mode 100644
index b1ce91e..0000000
--- a/media/mca/samples/Android.mk
+++ /dev/null
@@ -1,21 +0,0 @@
-# Copyright (C) 2011 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.
-#
-
-#
-# Build all native libraries
-#
-include $(call all-subdir-makefiles)
-
-
diff --git a/media/mca/samples/CameraEffectsRecordingSample/Android.bp b/media/mca/samples/CameraEffectsRecordingSample/Android.bp
new file mode 100644
index 0000000..96e81ab
--- /dev/null
+++ b/media/mca/samples/CameraEffectsRecordingSample/Android.bp
@@ -0,0 +1,26 @@
+// Copyright (C) 2011 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.
+//
+
+// Build activity
+
+android_test {
+ name: "CameraEffectsRecordingSample",
+ srcs: ["**/*.java"],
+ platform_apis: true,
+ optimize: {
+ enabled: false,
+ },
+}
+
diff --git a/media/mca/samples/CameraEffectsRecordingSample/Android.mk b/media/mca/samples/CameraEffectsRecordingSample/Android.mk
deleted file mode 100644
index c81f2fc..0000000
--- a/media/mca/samples/CameraEffectsRecordingSample/Android.mk
+++ /dev/null
@@ -1,35 +0,0 @@
-# Copyright (C) 2011 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.
-#
-
-# Build activity
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := CameraEffectsRecordingSample
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-include $(BUILD_PACKAGE)
-
-# ============================================================
-
-# Also build all of the sub-targets under this one: the shared library.
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/media/mca/tests/Android.bp b/media/mca/tests/Android.bp
new file mode 100644
index 0000000..6b11dd9
--- /dev/null
+++ b/media/mca/tests/Android.bp
@@ -0,0 +1,12 @@
+android_test {
+ name: "CameraEffectsTests",
+ libs: [
+ "android.test.runner",
+ "android.test.base",
+ ],
+ static_libs: ["junit"],
+ // Include all test java files.
+ srcs: ["src/**/*.java"],
+ platform_apis: true,
+ instrumentation_for: "CameraEffectsRecordingSample",
+}
diff --git a/media/mca/tests/Android.mk b/media/mca/tests/Android.mk
deleted file mode 100644
index 648af4e4..0000000
--- a/media/mca/tests/Android.mk
+++ /dev/null
@@ -1,20 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-# We only want this apk build for tests.
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base
-LOCAL_STATIC_JAVA_LIBRARIES := junit
-
-# Include all test java files.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := CameraEffectsTests
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_INSTRUMENTATION_FOR := CameraEffectsRecordingSample
-
-include $(BUILD_PACKAGE)
-
-
diff --git a/media/packages/BluetoothMidiService/Android.bp b/media/packages/BluetoothMidiService/Android.bp
new file mode 100644
index 0000000..f45114a
--- /dev/null
+++ b/media/packages/BluetoothMidiService/Android.bp
@@ -0,0 +1,6 @@
+android_app {
+ name: "BluetoothMidiService",
+ srcs: ["src/**/*.java"],
+ platform_apis: true,
+ certificate: "platform",
+}
diff --git a/media/packages/BluetoothMidiService/Android.mk b/media/packages/BluetoothMidiService/Android.mk
deleted file mode 100644
index 6f262bf..0000000
--- a/media/packages/BluetoothMidiService/Android.mk
+++ /dev/null
@@ -1,13 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES += \
- $(call all-java-files-under,src)
-
-LOCAL_PACKAGE_NAME := BluetoothMidiService
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_CERTIFICATE := platform
-
-include $(BUILD_PACKAGE)
diff --git a/media/tests/CameraBrowser/Android.bp b/media/tests/CameraBrowser/Android.bp
new file mode 100644
index 0000000..8e3ca19
--- /dev/null
+++ b/media/tests/CameraBrowser/Android.bp
@@ -0,0 +1,5 @@
+android_test {
+ name: "CameraBrowser",
+ srcs: ["**/*.java"],
+ sdk_version: "current",
+}
diff --git a/media/tests/CameraBrowser/Android.mk b/media/tests/CameraBrowser/Android.mk
deleted file mode 100644
index 46596a7..0000000
--- a/media/tests/CameraBrowser/Android.mk
+++ /dev/null
@@ -1,12 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := CameraBrowser
-
-LOCAL_SDK_VERSION := current
-
-include $(BUILD_PACKAGE)
diff --git a/media/tests/EffectsTest/Android.bp b/media/tests/EffectsTest/Android.bp
new file mode 100644
index 0000000..214e8c0
--- /dev/null
+++ b/media/tests/EffectsTest/Android.bp
@@ -0,0 +1,5 @@
+android_test {
+ name: "EffectsTest",
+ srcs: ["**/*.java"],
+ platform_apis: true,
+}
diff --git a/media/tests/EffectsTest/Android.mk b/media/tests/EffectsTest/Android.mk
deleted file mode 100644
index a066950..0000000
--- a/media/tests/EffectsTest/Android.mk
+++ /dev/null
@@ -1,11 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := EffectsTest
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-include $(BUILD_PACKAGE)
diff --git a/media/tests/MediaDump/Android.bp b/media/tests/MediaDump/Android.bp
new file mode 100644
index 0000000..0eba8b2
--- /dev/null
+++ b/media/tests/MediaDump/Android.bp
@@ -0,0 +1,6 @@
+android_app {
+ name: "MediaDump",
+ // Only compile source java files in this apk.
+ srcs: ["src/**/*.java"],
+ sdk_version: "current",
+}
diff --git a/media/tests/MediaDump/Android.mk b/media/tests/MediaDump/Android.mk
deleted file mode 100644
index 74afdd0..0000000
--- a/media/tests/MediaDump/Android.mk
+++ /dev/null
@@ -1,16 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-# Only compile source java files in this apk.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := MediaDump
-
-LOCAL_SDK_VERSION := current
-
-include $(BUILD_PACKAGE)
-
-# Use the following include to make our test apk.
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/media/tests/ScoAudioTest/Android.bp b/media/tests/ScoAudioTest/Android.bp
new file mode 100644
index 0000000..ad2b9171
--- /dev/null
+++ b/media/tests/ScoAudioTest/Android.bp
@@ -0,0 +1,5 @@
+android_test {
+ name: "scoaudiotest",
+ platform_apis: true,
+ srcs: ["**/*.java"],
+}
diff --git a/media/tests/ScoAudioTest/Android.mk b/media/tests/ScoAudioTest/Android.mk
deleted file mode 100644
index 2ad91a4..0000000
--- a/media/tests/ScoAudioTest/Android.mk
+++ /dev/null
@@ -1,13 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-#LOCAL_SDK_VERSION := current
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := scoaudiotest
-
-include $(BUILD_PACKAGE)
diff --git a/media/tests/SoundPoolTest/Android.bp b/media/tests/SoundPoolTest/Android.bp
new file mode 100644
index 0000000..473f531
--- /dev/null
+++ b/media/tests/SoundPoolTest/Android.bp
@@ -0,0 +1,5 @@
+android_test {
+ name: "SoundPoolTest",
+ srcs: ["**/*.java"],
+ platform_apis: true,
+}
diff --git a/media/tests/SoundPoolTest/Android.mk b/media/tests/SoundPoolTest/Android.mk
deleted file mode 100644
index 9ca33c8..0000000
--- a/media/tests/SoundPoolTest/Android.mk
+++ /dev/null
@@ -1,11 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := SoundPoolTest
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-include $(BUILD_PACKAGE)
diff --git a/media/tests/players/Android.bp b/media/tests/players/Android.bp
new file mode 100644
index 0000000..23c5f04
--- /dev/null
+++ b/media/tests/players/Android.bp
@@ -0,0 +1,31 @@
+// Copyright (C) 2009 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.
+
+cc_test_library {
+ name: "invoke_mock_media_player",
+ srcs: ["invoke_mock_media_player.cpp"],
+ shared_libs: [
+ "libbinder",
+ "libmedia",
+ "libutils",
+ "liblog",
+ ],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wunused",
+ "-Wunreachable-code",
+ ],
+ gtest: false,
+}
diff --git a/media/tests/players/Android.mk b/media/tests/players/Android.mk
deleted file mode 100644
index ee9d850..0000000
--- a/media/tests/players/Android.mk
+++ /dev/null
@@ -1,32 +0,0 @@
-# Copyright (C) 2009 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.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= invoke_mock_media_player.cpp
-
-LOCAL_SHARED_LIBRARIES:= \
- libbinder \
- libmedia \
- libutils \
- liblog
-
-LOCAL_MODULE:= invoke_mock_media_player
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java b/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
index fc56da7..bcfc412 100644
--- a/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
+++ b/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
@@ -1617,7 +1617,7 @@
// See if the data sub is registered for PS services on cell.
final NetworkRegistrationState nrs = dataSs.getNetworkRegistrationState(
NetworkRegistrationState.DOMAIN_PS,
- AccessNetworkConstants.TransportType.WWAN);
+ AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
latencyBroadcast.putExtra(
NetworkMonitorUtils.EXTRA_CELL_ID,
nrs == null ? null : nrs.getCellIdentity());
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 40c8b01..2687c68 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -159,6 +159,9 @@
<uses-permission android:name="android.permission.CONTROL_KEYGUARD" />
+ <!-- Permission needed to run network tests in CTS -->
+ <uses-permission android:name="android.permission.MANAGE_TEST_NETWORKS" />
+
<application android:label="@string/app_label"
android:defaultToDeviceProtectedStorage="true"
android:directBootAware="true">
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
index 2a4bb60..7148351 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
@@ -127,12 +127,12 @@
@Override
public void onTuningChanged(String key, String newValue) {
if (ALLOW_FANCY_ANIMATION.equals(key)) {
- mAllowFancy = newValue == null || Integer.parseInt(newValue) != 0;
+ mAllowFancy = TunerService.parseIntegerSwitch(newValue, true);
if (!mAllowFancy) {
clearAnimationState();
}
} else if (MOVE_FULL_ROWS.equals(key)) {
- mFullRows = newValue == null || Integer.parseInt(newValue) != 0;
+ mFullRows = TunerService.parseIntegerSwitch(newValue, true);
} else if (QuickQSPanel.NUM_QUICK_TILES.equals(key)) {
mNumQuickTiles = mQuickQsPanel.getNumQuickTiles(mQs.getContext());
clearAnimationState();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 3fc258b..bdc73d9 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -191,7 +191,7 @@
}
private void updateViewVisibilityForTuningValue(View view, @Nullable String newValue) {
- view.setVisibility(newValue == null || Integer.parseInt(newValue) != 0 ? VISIBLE : GONE);
+ view.setVisibility(TunerService.parseIntegerSwitch(newValue, true) ? VISIBLE : GONE);
}
public void openDetails(String subPanel) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
index 8517d90..9c2060d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
@@ -274,7 +274,7 @@
@Override
public void onTuningChanged(String key, String newValue) {
if (CLOCK_SECONDS.equals(key)) {
- mShowSeconds = newValue != null && Integer.parseInt(newValue) != 0;
+ mShowSeconds = TunerService.parseIntegerSwitch(newValue, false);
updateShowSeconds();
} else {
setClockVisibleByUser(!StatusBarIconController.getIconBlacklist(newValue)
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java
index 3a9d1c7..35ade2c 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java
@@ -109,4 +109,12 @@
});
dialog.show();
}
+
+ public static boolean parseIntegerSwitch(String value, boolean defaultValue) {
+ try {
+ return value != null ? Integer.parseInt(value) != 0 : defaultValue;
+ } catch (NumberFormatException e) {
+ return defaultValue;
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerSwitch.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerSwitch.java
index f53d516..89049f8 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerSwitch.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerSwitch.java
@@ -38,7 +38,7 @@
@Override
public void onTuningChanged(String key, String newValue) {
- setChecked(newValue != null ? Integer.parseInt(newValue) != 0 : mDefault);
+ setChecked(TunerService.parseIntegerSwitch(newValue, mDefault));
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java
index dd55264..d089b2f 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java
@@ -108,28 +108,23 @@
@Override
public void onTuningChanged(String key, String newValue) {
+ boolean volumeDownToEnterSilent = mVolumePolicy.volumeDownToEnterSilent;
+ boolean volumeUpToExitSilent = mVolumePolicy.volumeUpToExitSilent;
+ boolean doNotDisturbWhenSilent = mVolumePolicy.doNotDisturbWhenSilent;
+
if (VOLUME_DOWN_SILENT.equals(key)) {
- final boolean volumeDownToEnterSilent = newValue != null
- ? Integer.parseInt(newValue) != 0
- : DEFAULT_VOLUME_DOWN_TO_ENTER_SILENT;
- setVolumePolicy(volumeDownToEnterSilent,
- mVolumePolicy.volumeUpToExitSilent, mVolumePolicy.doNotDisturbWhenSilent,
- mVolumePolicy.vibrateToSilentDebounce);
+ volumeDownToEnterSilent =
+ TunerService.parseIntegerSwitch(newValue, DEFAULT_VOLUME_DOWN_TO_ENTER_SILENT);
} else if (VOLUME_UP_SILENT.equals(key)) {
- final boolean volumeUpToExitSilent = newValue != null
- ? Integer.parseInt(newValue) != 0
- : DEFAULT_VOLUME_UP_TO_EXIT_SILENT;
- setVolumePolicy(mVolumePolicy.volumeDownToEnterSilent,
- volumeUpToExitSilent, mVolumePolicy.doNotDisturbWhenSilent,
- mVolumePolicy.vibrateToSilentDebounce);
+ volumeUpToExitSilent =
+ TunerService.parseIntegerSwitch(newValue, DEFAULT_VOLUME_UP_TO_EXIT_SILENT);
} else if (VOLUME_SILENT_DO_NOT_DISTURB.equals(key)) {
- final boolean doNotDisturbWhenSilent = newValue != null
- ? Integer.parseInt(newValue) != 0
- : DEFAULT_DO_NOT_DISTURB_WHEN_SILENT;
- setVolumePolicy(mVolumePolicy.volumeDownToEnterSilent,
- mVolumePolicy.volumeUpToExitSilent, doNotDisturbWhenSilent,
- mVolumePolicy.vibrateToSilentDebounce);
+ doNotDisturbWhenSilent =
+ TunerService.parseIntegerSwitch(newValue, DEFAULT_DO_NOT_DISTURB_WHEN_SILENT);
}
+
+ setVolumePolicy(volumeDownToEnterSilent, volumeUpToExitSilent, doNotDisturbWhenSilent,
+ mVolumePolicy.vibrateToSilentDebounce);
}
private void setVolumePolicy(boolean volumeDownToEnterSilent, boolean volumeUpToExitSilent,
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 66c9735..4416b4d 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -72,6 +72,7 @@
import android.net.INetworkPolicyListener;
import android.net.INetworkPolicyManager;
import android.net.INetworkStatsService;
+import android.net.ISocketKeepaliveCallback;
import android.net.ITetheringEventCallback;
import android.net.InetAddresses;
import android.net.IpPrefix;
@@ -298,6 +299,15 @@
private INetworkPolicyManager mPolicyManager;
private NetworkPolicyManagerInternal mPolicyManagerInternal;
+ /**
+ * TestNetworkService (lazily) created upon first usage. Locked to prevent creation of multiple
+ * instances.
+ */
+ @GuardedBy("mTNSLock")
+ private TestNetworkService mTNS;
+
+ private final Object mTNSLock = new Object();
+
private String mCurrentTcpBufferSizes;
private static final SparseArray<String> sMagicDecoderRing = MessageUtils.findMessageNames(
@@ -6689,32 +6699,32 @@
}
@Override
- public void startNattKeepalive(Network network, int intervalSeconds, Messenger messenger,
- IBinder binder, String srcAddr, int srcPort, String dstAddr) {
+ public void startNattKeepalive(Network network, int intervalSeconds,
+ ISocketKeepaliveCallback cb, String srcAddr, int srcPort, String dstAddr) {
enforceKeepalivePermission();
mKeepaliveTracker.startNattKeepalive(
getNetworkAgentInfoForNetwork(network),
- intervalSeconds, messenger, binder,
+ intervalSeconds, cb,
srcAddr, srcPort, dstAddr, NattSocketKeepalive.NATT_PORT);
}
@Override
public void startNattKeepaliveWithFd(Network network, FileDescriptor fd, int resourceId,
- int intervalSeconds, Messenger messenger, IBinder binder, String srcAddr,
+ int intervalSeconds, ISocketKeepaliveCallback cb, String srcAddr,
String dstAddr) {
enforceKeepalivePermission();
mKeepaliveTracker.startNattKeepalive(
getNetworkAgentInfoForNetwork(network), fd, resourceId,
- intervalSeconds, messenger, binder,
+ intervalSeconds, cb,
srcAddr, dstAddr, NattSocketKeepalive.NATT_PORT);
}
@Override
public void startTcpKeepalive(Network network, FileDescriptor fd, int intervalSeconds,
- Messenger messenger, IBinder binder) {
+ ISocketKeepaliveCallback cb) {
enforceKeepalivePermission();
mKeepaliveTracker.startTcpKeepalive(
- getNetworkAgentInfoForNetwork(network), fd, intervalSeconds, messenger, binder);
+ getNetworkAgentInfoForNetwork(network), fd, intervalSeconds, cb);
}
@Override
@@ -6957,4 +6967,22 @@
return vpn != null && vpn.getLockdown();
}
}
+
+ /**
+ * Returns a IBinder to a TestNetworkService. Will be lazily created as needed.
+ *
+ * <p>The TestNetworkService must be run in the system server due to TUN creation.
+ */
+ @Override
+ public IBinder startOrGetTestNetworkService() {
+ synchronized (mTNSLock) {
+ TestNetworkService.enforceTestNetworkPermissions(mContext);
+
+ if (mTNS == null) {
+ mTNS = new TestNetworkService(mContext, mNMS);
+ }
+
+ return mTNS;
+ }
+ }
}
diff --git a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java
index cc4c173..35d6860 100644
--- a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java
+++ b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java
@@ -21,8 +21,8 @@
import static android.net.NetworkAgent.CMD_REMOVE_KEEPALIVE_PACKET_FILTER;
import static android.net.NetworkAgent.CMD_START_SOCKET_KEEPALIVE;
import static android.net.NetworkAgent.CMD_STOP_SOCKET_KEEPALIVE;
-import static android.net.NetworkAgent.EVENT_SOCKET_KEEPALIVE;
import static android.net.SocketKeepalive.BINDER_DIED;
+import static android.net.SocketKeepalive.DATA_RECEIVED;
import static android.net.SocketKeepalive.ERROR_INVALID_INTERVAL;
import static android.net.SocketKeepalive.ERROR_INVALID_IP_ADDRESS;
import static android.net.SocketKeepalive.ERROR_INVALID_NETWORK;
@@ -34,6 +34,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.net.ISocketKeepaliveCallback;
import android.net.KeepalivePacketData;
import android.net.NattKeepalivePacketData;
import android.net.NetworkAgent;
@@ -47,7 +48,6 @@
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
-import android.os.Messenger;
import android.os.Process;
import android.os.RemoteException;
import android.system.ErrnoException;
@@ -99,8 +99,7 @@
*/
class KeepaliveInfo implements IBinder.DeathRecipient {
// Bookkeeping data.
- private final Messenger mMessenger;
- private final IBinder mBinder;
+ private final ISocketKeepaliveCallback mCallback;
private final int mUid;
private final int mPid;
private final NetworkAgentInfo mNai;
@@ -124,15 +123,13 @@
private static final int STARTED = 3;
private int mStartedState = NOT_STARTED;
- KeepaliveInfo(@NonNull Messenger messenger,
- @NonNull IBinder binder,
+ KeepaliveInfo(@NonNull ISocketKeepaliveCallback callback,
@NonNull NetworkAgentInfo nai,
@NonNull KeepalivePacketData packet,
int interval,
int type,
@NonNull FileDescriptor fd) {
- mMessenger = messenger;
- mBinder = binder;
+ mCallback = callback;
mPid = Binder.getCallingPid();
mUid = Binder.getCallingUid();
@@ -143,7 +140,7 @@
mFd = fd;
try {
- mBinder.linkToDeath(this, 0);
+ mCallback.asBinder().linkToDeath(this, 0);
} catch (RemoteException e) {
binderDied();
}
@@ -176,22 +173,14 @@
+ " ]";
}
- /** Sends a message back to the application via its SocketKeepalive.Callback. */
- void notifyMessenger(int slot, int err) {
- if (DBG) {
- Log.d(TAG, "notify keepalive " + mSlot + " on " + mNai.network + " for " + err);
- }
- KeepaliveTracker.this.notifyMessenger(mMessenger, slot, err);
- }
-
/** Called when the application process is killed. */
public void binderDied() {
stop(BINDER_DIED);
}
void unlinkDeathRecipient() {
- if (mBinder != null) {
- mBinder.unlinkToDeath(this, 0);
+ if (mCallback != null) {
+ mCallback.asBinder().unlinkToDeath(this, 0);
}
}
@@ -283,9 +272,23 @@
Log.wtf(TAG, "Stopping keepalive with unknown type: " + mType);
}
}
- // TODO: at the moment we unconditionally return failure here. In cases where the
- // NetworkAgent is alive, should we ask it to reply, so it can return failure?
- notifyMessenger(mSlot, reason);
+
+ if (reason == SUCCESS) {
+ try {
+ mCallback.onStopped();
+ } catch (RemoteException e) {
+ Log.w(TAG, "Discarded onStop callback: " + reason);
+ }
+ } else if (reason == DATA_RECEIVED) {
+ try {
+ mCallback.onDataReceived();
+ } catch (RemoteException e) {
+ Log.w(TAG, "Discarded onDataReceived callback: " + reason);
+ }
+ } else {
+ notifyErrorCallback(mCallback, reason);
+ }
+
unlinkDeathRecipient();
}
@@ -294,16 +297,12 @@
}
}
- void notifyMessenger(Messenger messenger, int slot, int err) {
- Message message = Message.obtain();
- message.what = EVENT_SOCKET_KEEPALIVE;
- message.arg1 = slot;
- message.arg2 = err;
- message.obj = null;
+ void notifyErrorCallback(ISocketKeepaliveCallback cb, int error) {
+ if (DBG) Log.w(TAG, "Sending onError(" + error + ") callback");
try {
- messenger.send(message);
+ cb.onError(error);
} catch (RemoteException e) {
- // Process died?
+ Log.w(TAG, "Discarded onError(" + error + ") callback");
}
}
@@ -414,7 +413,11 @@
// Keepalive successfully started.
if (DBG) Log.d(TAG, "Started keepalive " + slot + " on " + nai.name());
ki.mStartedState = KeepaliveInfo.STARTED;
- ki.notifyMessenger(slot, reason);
+ try {
+ ki.mCallback.onStarted(slot);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Discarded onStarted(" + slot + ") callback");
+ }
} else {
// Keepalive successfully stopped, or error.
ki.mStartedState = KeepaliveInfo.NOT_STARTED;
@@ -436,14 +439,13 @@
**/
public void startNattKeepalive(@Nullable NetworkAgentInfo nai,
int intervalSeconds,
- @NonNull Messenger messenger,
- @NonNull IBinder binder,
+ @NonNull ISocketKeepaliveCallback cb,
@NonNull String srcAddrString,
int srcPort,
@NonNull String dstAddrString,
int dstPort) {
if (nai == null) {
- notifyMessenger(messenger, NO_KEEPALIVE, ERROR_INVALID_NETWORK);
+ notifyErrorCallback(cb, ERROR_INVALID_NETWORK);
return;
}
@@ -452,7 +454,7 @@
srcAddress = NetworkUtils.numericToInetAddress(srcAddrString);
dstAddress = NetworkUtils.numericToInetAddress(dstAddrString);
} catch (IllegalArgumentException e) {
- notifyMessenger(messenger, NO_KEEPALIVE, ERROR_INVALID_IP_ADDRESS);
+ notifyErrorCallback(cb, ERROR_INVALID_IP_ADDRESS);
return;
}
@@ -461,11 +463,12 @@
packet = NattKeepalivePacketData.nattKeepalivePacket(
srcAddress, srcPort, dstAddress, NATT_PORT);
} catch (InvalidPacketException e) {
- notifyMessenger(messenger, NO_KEEPALIVE, e.error);
+ notifyErrorCallback(cb, e.error);
return;
}
- KeepaliveInfo ki = new KeepaliveInfo(messenger, binder, nai, packet, intervalSeconds,
+ KeepaliveInfo ki = new KeepaliveInfo(cb, nai, packet, intervalSeconds,
KeepaliveInfo.TYPE_NATT, null);
+ Log.d(TAG, "Created keepalive: " + ki.toString());
mConnectivityServiceHandler.obtainMessage(
NetworkAgent.CMD_START_SOCKET_KEEPALIVE, ki).sendToTarget();
}
@@ -483,10 +486,9 @@
public void startTcpKeepalive(@Nullable NetworkAgentInfo nai,
@NonNull FileDescriptor fd,
int intervalSeconds,
- @NonNull Messenger messenger,
- @NonNull IBinder binder) {
+ @NonNull ISocketKeepaliveCallback cb) {
if (nai == null) {
- notifyMessenger(messenger, NO_KEEPALIVE, ERROR_INVALID_NETWORK);
+ notifyErrorCallback(cb, ERROR_INVALID_NETWORK);
return;
}
@@ -500,10 +502,10 @@
} catch (ErrnoException e1) {
Log.e(TAG, "Couldn't move fd out of repair mode after failure to start keepalive");
}
- notifyMessenger(messenger, NO_KEEPALIVE, e.error);
+ notifyErrorCallback(cb, e.error);
return;
}
- KeepaliveInfo ki = new KeepaliveInfo(messenger, binder, nai, packet, intervalSeconds,
+ KeepaliveInfo ki = new KeepaliveInfo(cb, nai, packet, intervalSeconds,
KeepaliveInfo.TYPE_TCP, fd);
Log.d(TAG, "Created keepalive: " + ki.toString());
mConnectivityServiceHandler.obtainMessage(CMD_START_SOCKET_KEEPALIVE, ki).sendToTarget();
@@ -520,14 +522,13 @@
@Nullable FileDescriptor fd,
int resourceId,
int intervalSeconds,
- @NonNull Messenger messenger,
- @NonNull IBinder binder,
+ @NonNull ISocketKeepaliveCallback cb,
@NonNull String srcAddrString,
@NonNull String dstAddrString,
int dstPort) {
// Ensure that the socket is created by IpSecService.
if (!isNattKeepaliveSocketValid(fd, resourceId)) {
- notifyMessenger(messenger, NO_KEEPALIVE, ERROR_INVALID_SOCKET);
+ notifyErrorCallback(cb, ERROR_INVALID_SOCKET);
}
// Get src port to adopt old API.
@@ -536,11 +537,11 @@
final SocketAddress srcSockAddr = Os.getsockname(fd);
srcPort = ((InetSocketAddress) srcSockAddr).getPort();
} catch (ErrnoException e) {
- notifyMessenger(messenger, NO_KEEPALIVE, ERROR_INVALID_SOCKET);
+ notifyErrorCallback(cb, ERROR_INVALID_SOCKET);
}
// Forward request to old API.
- startNattKeepalive(nai, intervalSeconds, messenger, binder, srcAddrString, srcPort,
+ startNattKeepalive(nai, intervalSeconds, cb, srcAddrString, srcPort,
dstAddrString, dstPort);
}
diff --git a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
index 053da0d..828a1e5 100644
--- a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
+++ b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
@@ -28,6 +28,7 @@
import android.content.res.Resources;
import android.net.wifi.WifiInfo;
import android.os.UserHandle;
+import android.telephony.AccessNetworkConstants.TransportType;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Slog;
@@ -92,7 +93,7 @@
return -1;
}
- private static String getTransportName(int transportType) {
+ private static String getTransportName(@TransportType int transportType) {
Resources r = Resources.getSystem();
String[] networkTypes = r.getStringArray(R.array.network_switch_type_name);
try {
diff --git a/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java b/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java
index ba5ca9c..5c0874d 100644
--- a/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java
+++ b/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java
@@ -40,10 +40,6 @@
import java.io.FileDescriptor;
-// TODO(b/111441001):
-// Intercept onFinished() & implement death recipient here and shutdown
-// bugreportd service.
-
/**
* Implementation of the service that provides a privileged API to capture and consume bugreports.
*
@@ -83,7 +79,12 @@
Preconditions.checkNotNull(bugreportFd);
Preconditions.checkNotNull(listener);
validateBugreportMode(bugreportMode);
- ensureIsPrimaryUser();
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ ensureIsPrimaryUser();
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
int callingUid = Binder.getCallingUid();
mAppOps.checkPackage(callingUid, callingPackage);
@@ -166,9 +167,12 @@
reportError(listener, IDumpstateListener.BUGREPORT_ERROR_RUNTIME_ERROR);
return;
}
+
+ // Wrap the listener so we can intercept binder events directly.
+ IDumpstateListener myListener = new DumpstateListener(listener, ds);
try {
ds.startBugreport(callingUid, callingPackage,
- bugreportFd, screenshotFd, bugreportMode, listener);
+ bugreportFd, screenshotFd, bugreportMode, myListener);
} catch (RemoteException e) {
reportError(listener, IDumpstateListener.BUGREPORT_ERROR_RUNTIME_ERROR);
}
@@ -235,4 +239,73 @@
Slog.w(TAG, message);
throw new IllegalArgumentException(message);
}
+
+
+ private final class DumpstateListener extends IDumpstateListener.Stub
+ implements DeathRecipient {
+ private final IDumpstateListener mListener;
+ private final IDumpstate mDs;
+ private boolean mDone = false;
+
+ DumpstateListener(IDumpstateListener listener, IDumpstate ds) {
+ mListener = listener;
+ mDs = ds;
+ try {
+ mDs.asBinder().linkToDeath(this, 0);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Unable to register Death Recipient for IDumpstate", e);
+ }
+ }
+
+ @Override
+ public void onProgress(int progress) throws RemoteException {
+ mListener.onProgress(progress);
+ }
+
+ @Override
+ public void onError(int errorCode) throws RemoteException {
+ synchronized (mLock) {
+ mDone = true;
+ }
+ mListener.onError(errorCode);
+ }
+
+ @Override
+ public void onFinished() throws RemoteException {
+ synchronized (mLock) {
+ mDone = true;
+ }
+ mListener.onFinished();
+ }
+
+ @Override
+ public void binderDied() {
+ synchronized (mLock) {
+ if (!mDone) {
+ // If we have not gotten a "done" callback this must be a crash.
+ Slog.e(TAG, "IDumpstate likely crashed. Notifying listener");
+ try {
+ mListener.onError(IDumpstateListener.BUGREPORT_ERROR_RUNTIME_ERROR);
+ } catch (RemoteException ignored) {
+ // If listener is not around, there isn't anything to do here.
+ }
+ }
+ }
+ mDs.asBinder().unlinkToDeath(this, 0);
+ }
+
+ // Old methods; unused in the API flow.
+ @Override
+ public void onProgressUpdated(int progress) throws RemoteException {
+ }
+
+ @Override
+ public void onMaxProgressUpdated(int maxProgress) throws RemoteException {
+ }
+
+ @Override
+ public void onSectionComplete(String title, int status, int size, int durationMs)
+ throws RemoteException {
+ }
+ }
}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index d33d7f5..4125b92 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -1118,6 +1118,14 @@
mSystemServiceManager.startService(ClipboardService.class);
traceEnd();
+ traceBeginAndSlog("InitNetworkStackClient");
+ try {
+ NetworkStackClient.getInstance().init();
+ } catch (Throwable e) {
+ reportWtf("initializing NetworkStackClient", e);
+ }
+ traceEnd();
+
traceBeginAndSlog("StartNetworkManagementService");
try {
networkManagement = NetworkManagementService.create(context);
diff --git a/services/net/java/android/net/NetworkStackClient.java b/services/net/java/android/net/NetworkStackClient.java
index 6162319..cc09fe3 100644
--- a/services/net/java/android/net/NetworkStackClient.java
+++ b/services/net/java/android/net/NetworkStackClient.java
@@ -164,6 +164,15 @@
}
/**
+ * Initialize the network stack. Should be called only once on device startup, before any
+ * client attempts to use the network stack.
+ */
+ public void init() {
+ log("Network stack init");
+ mNetworkStackStartRequested = true;
+ }
+
+ /**
* Start the network stack. Should be called only once on device startup.
*
* <p>This method will start the network stack either in the network stack process, or inside
@@ -173,8 +182,6 @@
*/
public void start(Context context) {
log("Starting network stack");
- mNetworkStackStartRequested = true;
-
final PackageManager pm = context.getPackageManager();
// Try to bind in-process if the device was shipped with an in-process version
diff --git a/telecomm/java/android/telecom/AudioState.java b/telecomm/java/android/telecom/AudioState.java
index eb202a7..a9b75a3 100644
--- a/telecomm/java/android/telecom/AudioState.java
+++ b/telecomm/java/android/telecom/AudioState.java
@@ -18,6 +18,7 @@
import android.annotation.SystemApi;
import android.annotation.UnsupportedAppUsage;
+import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
@@ -54,11 +55,11 @@
private static final int ROUTE_ALL = ROUTE_EARPIECE | ROUTE_BLUETOOTH | ROUTE_WIRED_HEADSET |
ROUTE_SPEAKER;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 127403196)
private final boolean isMuted;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 127403196)
private final int route;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 127403196)
private final int supportedRouteMask;
public AudioState(boolean muted, int route, int supportedRouteMask) {
diff --git a/telecomm/java/android/telecom/CallRedirectionService.java b/telecomm/java/android/telecom/CallRedirectionService.java
index 3299117..d01c889 100644
--- a/telecomm/java/android/telecom/CallRedirectionService.java
+++ b/telecomm/java/android/telecom/CallRedirectionService.java
@@ -17,6 +17,7 @@
package android.telecom;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.SdkConstant;
import android.app.Service;
import android.content.Intent;
@@ -62,16 +63,20 @@
private ICallRedirectionAdapter mCallRedirectionAdapter;
/**
- * Telecom calls this method to inform the implemented {@link CallRedirectionService} of
- * a new outgoing call which is being placed. Telecom does not request to redirect emergency
- * calls and does not request to redirect calls with gateway information.
+ * Telecom calls this method once upon binding to a {@link CallRedirectionService} to inform
+ * it of a new outgoing call which is being placed. Telecom does not request to redirect
+ * emergency calls and does not request to redirect calls with gateway information.
*
* <p>Telecom will cancel the call if Telecom does not receive a response in 5 seconds from
* the implemented {@link CallRedirectionService} set by users.
*
* <p>The implemented {@link CallRedirectionService} can call {@link #placeCallUnmodified()},
* {@link #redirectCall(Uri, PhoneAccountHandle, boolean)}, and {@link #cancelCall()} only
- * from here.
+ * from here. Calls to these methods are assumed by the Telecom framework to be the response
+ * for the phone call for which {@link #onPlaceCall(Uri, PhoneAccountHandle, boolean)} was
+ * invoked by Telecom. The Telecom framework will only invoke
+ * {@link #onPlaceCall(Uri, PhoneAccountHandle, boolean)} once each time it binds to a
+ * {@link CallRedirectionService}.
*
* @param handle the phone number dialed by the user, represented in E.164 format if possible
* @param initialPhoneAccount the {@link PhoneAccountHandle} on which the call will be placed.
@@ -91,13 +96,15 @@
* no changes are required to the outgoing call, and that the call should be placed as-is.
*
* <p>This can only be called from implemented
- * {@link #onPlaceCall(Uri, PhoneAccountHandle, boolean)}.
+ * {@link #onPlaceCall(Uri, PhoneAccountHandle, boolean)}. The response corresponds to the
+ * latest request via {@link #onPlaceCall(Uri, PhoneAccountHandle, boolean)}.
*
*/
public final void placeCallUnmodified() {
try {
mCallRedirectionAdapter.placeCallUnmodified();
} catch (RemoteException e) {
+ e.rethrowAsRuntimeException();
}
}
@@ -109,7 +116,8 @@
* replies Telecom a handle for an emergency number.
*
* <p>This can only be called from implemented
- * {@link #onPlaceCall(Uri, PhoneAccountHandle, boolean)}.
+ * {@link #onPlaceCall(Uri, PhoneAccountHandle, boolean)}. The response corresponds to the
+ * latest request via {@link #onPlaceCall(Uri, PhoneAccountHandle, boolean)}.
*
* @param handle the new phone number to dial
* @param targetPhoneAccount the {@link PhoneAccountHandle} to use when placing the call.
@@ -126,6 +134,7 @@
try {
mCallRedirectionAdapter.redirectCall(handle, targetPhoneAccount, confirmFirst);
} catch (RemoteException e) {
+ e.rethrowAsRuntimeException();
}
}
@@ -135,13 +144,15 @@
* an outgoing call should be canceled entirely.
*
* <p>This can only be called from implemented
- * {@link #onPlaceCall(Uri, PhoneAccountHandle, boolean)}.
+ * {@link #onPlaceCall(Uri, PhoneAccountHandle, boolean)}. The response corresponds to the
+ * latest request via {@link #onPlaceCall(Uri, PhoneAccountHandle, boolean)}.
*
*/
public final void cancelCall() {
try {
mCallRedirectionAdapter.cancelCall();
} catch (RemoteException e) {
+ e.rethrowAsRuntimeException();
}
}
@@ -196,12 +207,12 @@
}
@Override
- public final IBinder onBind(Intent intent) {
+ public final @Nullable IBinder onBind(@NonNull Intent intent) {
return new CallRedirectionBinder();
}
@Override
- public final boolean onUnbind(Intent intent) {
+ public final boolean onUnbind(@NonNull Intent intent) {
return false;
}
}
diff --git a/telecomm/java/android/telecom/Phone.java b/telecomm/java/android/telecom/Phone.java
index d3ccd2c..0cc052e 100644
--- a/telecomm/java/android/telecom/Phone.java
+++ b/telecomm/java/android/telecom/Phone.java
@@ -19,6 +19,7 @@
import android.annotation.SystemApi;
import android.annotation.UnsupportedAppUsage;
import android.bluetooth.BluetoothDevice;
+import android.os.Build;
import android.os.Bundle;
import android.os.RemoteException;
import android.util.ArrayMap;
@@ -328,10 +329,12 @@
* become active, and the touch screen and display will be turned off when the user's face
* is detected to be in close proximity to the screen. This operation is a no-op on devices
* that do not have a proximity sensor.
- *
+ * <p>
+ * This API does not actually turn on the proximity sensor; apps should do this on their own if
+ * required.
* @hide
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 127403196)
public final void setProximitySensorOn() {
mInCallAdapter.turnProximitySensorOn();
}
@@ -344,10 +347,12 @@
* @param screenOnImmediately If true, the screen will be turned on immediately if it was
* previously off. Otherwise, the screen will only be turned on after the proximity sensor
* is no longer triggered.
- *
+ * <p>
+ * This API does not actually turn of the proximity sensor; apps should do this on their own if
+ * required.
* @hide
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 127403196)
public final void setProximitySensorOff(boolean screenOnImmediately) {
mInCallAdapter.turnProximitySensorOff(screenOnImmediately);
}
diff --git a/telecomm/java/android/telecom/PhoneAccountHandle.java b/telecomm/java/android/telecom/PhoneAccountHandle.java
index 5dedb04..e25c17d 100644
--- a/telecomm/java/android/telecom/PhoneAccountHandle.java
+++ b/telecomm/java/android/telecom/PhoneAccountHandle.java
@@ -42,7 +42,7 @@
* See {@link PhoneAccount}, {@link TelecomManager}.
*/
public final class PhoneAccountHandle implements Parcelable {
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 127403196)
private final ComponentName mComponentName;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
private final String mId;
diff --git a/telecomm/java/android/telecom/VideoCallImpl.java b/telecomm/java/android/telecom/VideoCallImpl.java
index 2c7fecb..cb74012 100644
--- a/telecomm/java/android/telecom/VideoCallImpl.java
+++ b/telecomm/java/android/telecom/VideoCallImpl.java
@@ -18,6 +18,7 @@
import android.annotation.UnsupportedAppUsage;
import android.net.Uri;
+import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
@@ -218,7 +219,7 @@
mTargetSdkVersion = sdkVersion;
}
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 127403196)
public void destroy() {
unregisterCallback(mCallback);
}
diff --git a/telephony/java/android/telephony/AccessNetworkConstants.java b/telephony/java/android/telephony/AccessNetworkConstants.java
index 75165af..81553a3 100644
--- a/telephony/java/android/telephony/AccessNetworkConstants.java
+++ b/telephony/java/android/telephony/AccessNetworkConstants.java
@@ -16,13 +16,59 @@
package android.telephony;
+import android.annotation.IntDef;
import android.annotation.SystemApi;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
/**
* Contains access network related constants.
*/
public final class AccessNetworkConstants {
+ /**
+ * Wireless transportation type
+ *
+ * @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = {"TRANSPORT_TYPE_"},
+ value = {
+ TRANSPORT_TYPE_INVALID,
+ TRANSPORT_TYPE_WWAN,
+ TRANSPORT_TYPE_WLAN})
+ public @interface TransportType {}
+
+ /**
+ * Invalid transport type
+ * @hide
+ */
+ @SystemApi
+ public static final int TRANSPORT_TYPE_INVALID = -1;
+
+ /**
+ * Transport type for Wireless Wide Area Networks (i.e. Cellular)
+ * @hide
+ */
+ @SystemApi
+ public static final int TRANSPORT_TYPE_WWAN = 1;
+
+ /**
+ * Transport type for Wireless Local Area Networks (i.e. Wifi)
+ * @hide
+ */
+ @SystemApi
+ public static final int TRANSPORT_TYPE_WLAN = 2;
+
+ /** @hide */
+ public static String transportTypeToString(@TransportType int transportType) {
+ switch (transportType) {
+ case TRANSPORT_TYPE_WWAN: return "WWAN";
+ case TRANSPORT_TYPE_WLAN: return "WLAN";
+ default: return Integer.toString(transportType);
+ }
+ }
+
public static final class AccessNetworkType {
public static final int UNKNOWN = 0;
public static final int GERAN = 1;
@@ -49,39 +95,7 @@
}
/**
- * Wireless transportation type
- * @hide
- */
- @SystemApi
- public static final class TransportType {
- /**
- * Invalid transport type.
- * @hide
- */
- public static final int INVALID = -1;
-
- /** Wireless Wide Area Networks (i.e. Cellular) */
- public static final int WWAN = 1;
-
- /** Wireless Local Area Networks (i.e. Wifi) */
- public static final int WLAN = 2;
-
- /** @hide */
- private TransportType() {}
-
- /** @hide */
- public static String toString(int type) {
- switch (type) {
- case INVALID: return "INVALID";
- case WWAN: return "WWAN";
- case WLAN: return "WLAN";
- default: return Integer.toString(type);
- }
- }
- }
-
- /**
- * Frenquency bands for GERAN.
+ * Frequency bands for GERAN.
* http://www.etsi.org/deliver/etsi_ts/145000_145099/145005/14.00.00_60/ts_145005v140000p.pdf
*/
public static final class GeranBand {
diff --git a/telephony/java/android/telephony/AvailableNetworkInfo.java b/telephony/java/android/telephony/AvailableNetworkInfo.java
index b407b2a..8286e1e 100644
--- a/telephony/java/android/telephony/AvailableNetworkInfo.java
+++ b/telephony/java/android/telephony/AvailableNetworkInfo.java
@@ -16,6 +16,7 @@
package android.telephony;
+import android.annotation.NonNull;
import android.os.Parcel;
import android.os.Parcelable;
@@ -62,11 +63,22 @@
/**
* Describes the List of PLMN ids (MCC-MNC) associated with mSubId.
* If this entry is left empty, then the platform software will not scan the network
- * to revalidate the input.
+ * to revalidate the input else platform will scan and verify specified PLMNs are available.
*/
private ArrayList<String> mMccMncs;
/**
+ * Returns the frequency bands associated with the {@link #getMccMncs() MCC/MNCs}.
+ * Opportunistic network service will use these bands to scan.
+ *
+ * When no specific bands are specified (empty array or null) CBRS band (B48) will be
+ * used for network scan.
+ *
+ * See {@link AccessNetworkConstants} for details.
+ */
+ private ArrayList<Integer> mBands;
+
+ /**
* Return subscription Id of the available network.
* This value must be one of the entry retrieved from
* {@link SubscriptionManager#getOpportunisticSubscriptions}
@@ -91,10 +103,20 @@
* to revalidate the input.
* @return list of PLMN ids
*/
- public List<String> getMccMncs() {
+ public @NonNull List<String> getMccMncs() {
return (List<String>) mMccMncs.clone();
}
+ /**
+ * Returns the frequency bands that need to be scanned by opportunistic network service
+ *
+ * The returned value is defined in either of {@link AccessNetworkConstants.GeranBand},
+ * {@link AccessNetworkConstants.UtranBand} and {@link AccessNetworkConstants.EutranBand}
+ */
+ public @NonNull List<Integer> getBands() {
+ return (List<Integer>) mBands.clone();
+ }
+
@Override
public int describeContents() {
return 0;
@@ -105,6 +127,7 @@
dest.writeInt(mSubId);
dest.writeInt(mPriority);
dest.writeStringList(mMccMncs);
+ dest.writeList(mBands);
}
private AvailableNetworkInfo(Parcel in) {
@@ -112,12 +135,16 @@
mPriority = in.readInt();
mMccMncs = new ArrayList<>();
in.readStringList(mMccMncs);
+ mBands = new ArrayList<>();
+ in.readList(mBands, Integer.class.getClassLoader());
}
- public AvailableNetworkInfo(int subId, int priority, List<String> mccMncs) {
+ public AvailableNetworkInfo(int subId, int priority, @NonNull List<String> mccMncs,
+ @NonNull List<Integer> bands) {
mSubId = subId;
mPriority = priority;
mMccMncs = new ArrayList<String>(mccMncs);
+ mBands = new ArrayList<Integer>(bands);
}
@Override
@@ -135,14 +162,15 @@
}
return (mSubId == ani.mSubId
- && mPriority == ani.mPriority
- && (((mMccMncs != null)
- && mMccMncs.equals(ani.mMccMncs))));
+ && mPriority == ani.mPriority
+ && (((mMccMncs != null)
+ && mMccMncs.equals(ani.mMccMncs)))
+ && mBands.equals(ani.mBands));
}
@Override
public int hashCode() {
- return Objects.hash(mSubId, mPriority, mMccMncs);
+ return Objects.hash(mSubId, mPriority, mMccMncs, mBands);
}
public static final Parcelable.Creator<AvailableNetworkInfo> CREATOR =
@@ -161,9 +189,9 @@
@Override
public String toString() {
return ("AvailableNetworkInfo:"
- + " mSubId: " + mSubId
- + " mPriority: " + mPriority
- + " mMccMncs: " + Arrays.toString(mMccMncs.toArray()));
+ + " mSubId: " + mSubId
+ + " mPriority: " + mPriority
+ + " mMccMncs: " + Arrays.toString(mMccMncs.toArray())
+ + " mBands: " + Arrays.toString(mBands.toArray()));
}
}
-
diff --git a/telephony/java/android/telephony/DataFailCause.java b/telephony/java/android/telephony/DataFailCause.java
index ca264f7..f0a26f5 100644
--- a/telephony/java/android/telephony/DataFailCause.java
+++ b/telephony/java/android/telephony/DataFailCause.java
@@ -318,8 +318,8 @@
public static final int LOW_POWER_MODE_OR_POWERING_DOWN = 0x7FC;
/** APN has been disabled. */
public static final int APN_DISABLED = 0x7FD;
- /** Maximum PPP inactivity timer expired. */
- public static final int MAX_PPP_INACTIVITY_TIMER_EXPIRED = 0x7FE;
+ /** PPP inactivity timer expired. */
+ public static final int PPP_INACTIVITY_TIMER_EXPIRED = 0x7FE;
/** IPv6 address transfer failed. */
public static final int IPV6_ADDRESS_TRANSFER_FAILED = 0x7FF;
/** Target RAT swap failed. */
@@ -339,12 +339,12 @@
* IPv4 data call bring up is rejected because the UE already maintains the allotted maximum
* number of IPv4 data connections.
*/
- public static final int MAX_IPV4_CONNECTIONS = 0x804;
+ public static final int IPV4_CONNECTIONS_LIMIT_REACHED = 0x804;
/**
* IPv6 data call bring up is rejected because the UE already maintains the allotted maximum
* number of IPv6 data connections.
*/
- public static final int MAX_IPV6_CONNECTIONS = 0x805;
+ public static final int IPV6_CONNECTIONS_LIMIT_REACHED = 0x805;
/**
* New PDN bring up is rejected during interface selection because the UE has already allotted
* the available interfaces for other PDNs.
@@ -416,7 +416,7 @@
*/
public static final int CHANNEL_ACQUISITION_FAILURE = 0x81E;
/** Maximum access probes transmitted. */
- public static final int MAX_ACCESS_PROBE = 0x81F;
+ public static final int ACCESS_PROBE_LIMIT_REACHED = 0x81F;
/** Concurrent service is not supported by base station. */
public static final int CONCURRENT_SERVICE_NOT_SUPPORTED_BY_BASE_STATION = 0x820;
/** There was no response received from the base station. */
@@ -1079,14 +1079,14 @@
SIM_CARD_CHANGED,
LOW_POWER_MODE_OR_POWERING_DOWN,
APN_DISABLED,
- MAX_PPP_INACTIVITY_TIMER_EXPIRED,
+ PPP_INACTIVITY_TIMER_EXPIRED,
IPV6_ADDRESS_TRANSFER_FAILED,
TRAT_SWAP_FAILED,
EHRPD_TO_HRPD_FALLBACK,
MIP_CONFIG_FAILURE,
PDN_INACTIVITY_TIMER_EXPIRED,
- MAX_IPV4_CONNECTIONS,
- MAX_IPV6_CONNECTIONS,
+ IPV4_CONNECTIONS_LIMIT_REACHED,
+ IPV6_CONNECTIONS_LIMIT_REACHED,
APN_MISMATCH,
IP_VERSION_MISMATCH,
DUN_CALL_DISALLOWED,
@@ -1112,7 +1112,7 @@
CDMA_INCOMING_CALL,
CDMA_ALERT_STOP,
CHANNEL_ACQUISITION_FAILURE,
- MAX_ACCESS_PROBE,
+ ACCESS_PROBE_LIMIT_REACHED,
CONCURRENT_SERVICE_NOT_SUPPORTED_BY_BASE_STATION,
NO_RESPONSE_FROM_BASE_STATION,
REJECTED_BY_BASE_STATION,
@@ -1447,14 +1447,14 @@
sFailCauseMap.put(SIM_CARD_CHANGED, "SIM_CARD_CHANGED");
sFailCauseMap.put(LOW_POWER_MODE_OR_POWERING_DOWN, "LOW_POWER_MODE_OR_POWERING_DOWN");
sFailCauseMap.put(APN_DISABLED, "APN_DISABLED");
- sFailCauseMap.put(MAX_PPP_INACTIVITY_TIMER_EXPIRED, "MAX_PPP_INACTIVITY_TIMER_EXPIRED");
+ sFailCauseMap.put(PPP_INACTIVITY_TIMER_EXPIRED, "PPP_INACTIVITY_TIMER_EXPIRED");
sFailCauseMap.put(IPV6_ADDRESS_TRANSFER_FAILED, "IPV6_ADDRESS_TRANSFER_FAILED");
sFailCauseMap.put(TRAT_SWAP_FAILED, "TRAT_SWAP_FAILED");
sFailCauseMap.put(EHRPD_TO_HRPD_FALLBACK, "EHRPD_TO_HRPD_FALLBACK");
sFailCauseMap.put(MIP_CONFIG_FAILURE, "MIP_CONFIG_FAILURE");
sFailCauseMap.put(PDN_INACTIVITY_TIMER_EXPIRED, "PDN_INACTIVITY_TIMER_EXPIRED");
- sFailCauseMap.put(MAX_IPV4_CONNECTIONS, "MAX_IPV4_CONNECTIONS");
- sFailCauseMap.put(MAX_IPV6_CONNECTIONS, "MAX_IPV6_CONNECTIONS");
+ sFailCauseMap.put(IPV4_CONNECTIONS_LIMIT_REACHED, "IPV4_CONNECTIONS_LIMIT_REACHED");
+ sFailCauseMap.put(IPV6_CONNECTIONS_LIMIT_REACHED, "IPV6_CONNECTIONS_LIMIT_REACHED");
sFailCauseMap.put(APN_MISMATCH, "APN_MISMATCH");
sFailCauseMap.put(IP_VERSION_MISMATCH, "IP_VERSION_MISMATCH");
sFailCauseMap.put(DUN_CALL_DISALLOWED, "DUN_CALL_DISALLOWED");
@@ -1480,7 +1480,7 @@
sFailCauseMap.put(CDMA_INCOMING_CALL, "CDMA_INCOMING_CALL");
sFailCauseMap.put(CDMA_ALERT_STOP, "CDMA_ALERT_STOP");
sFailCauseMap.put(CHANNEL_ACQUISITION_FAILURE, "CHANNEL_ACQUISITION_FAILURE");
- sFailCauseMap.put(MAX_ACCESS_PROBE, "MAX_ACCESS_PROBE");
+ sFailCauseMap.put(ACCESS_PROBE_LIMIT_REACHED, "ACCESS_PROBE_LIMIT_REACHED");
sFailCauseMap.put(CONCURRENT_SERVICE_NOT_SUPPORTED_BY_BASE_STATION,
"CONCURRENT_SERVICE_NOT_SUPPORTED_BY_BASE_STATION");
sFailCauseMap.put(NO_RESPONSE_FROM_BASE_STATION, "NO_RESPONSE_FROM_BASE_STATION");
diff --git a/telephony/java/android/telephony/NetworkRegistrationState.java b/telephony/java/android/telephony/NetworkRegistrationState.java
index 4d97f81..74f200b 100644
--- a/telephony/java/android/telephony/NetworkRegistrationState.java
+++ b/telephony/java/android/telephony/NetworkRegistrationState.java
@@ -129,7 +129,6 @@
@Domain
private final int mDomain;
- /** {@link TransportType} */
private final int mTransportType;
@RegState
@@ -165,14 +164,15 @@
private DataSpecificRegistrationStates mDataSpecificStates;
/**
- * @param domain Network domain. Must be a {@link Domain}. For {@link TransportType#WLAN}
- * transport, this must set to {@link #DOMAIN_PS}.
- * @param transportType Transport type. Must be one of the{@link TransportType}.
+ * @param domain Network domain. Must be a {@link Domain}. For transport type
+ * {@link AccessNetworkConstants#TRANSPORT_TYPE_WLAN}, this must set to {@link #DOMAIN_PS}.
+ * @param transportType Transport type.
* @param regState Network registration state. Must be one of the {@link RegState}. For
- * {@link TransportType#WLAN} transport, only {@link #REG_STATE_HOME} and
- * {@link #REG_STATE_NOT_REG_NOT_SEARCHING} are valid states.
- * @param accessNetworkTechnology Access network technology.For {@link TransportType#WLAN}
- * transport, set to {@link TelephonyManager#NETWORK_TYPE_IWLAN}.
+ * transport type {@link AccessNetworkConstants#TRANSPORT_TYPE_WLAN}, only
+ * {@link #REG_STATE_HOME} and {@link #REG_STATE_NOT_REG_NOT_SEARCHING} are valid states.
+ * @param accessNetworkTechnology Access network technology.For transport type
+ * {@link AccessNetworkConstants#TRANSPORT_TYPE_WLAN}, set to
+ * {@link TelephonyManager#NETWORK_TYPE_IWLAN}.
* @param rejectCause Reason for denial if the registration state is {@link #REG_STATE_DENIED}.
* Depending on {@code accessNetworkTechnology}, the values are defined in 3GPP TS 24.008
* 10.5.3.6 for UMTS, 3GPP TS 24.301 9.9.3.9 for LTE, and 3GPP2 A.S0001 6.2.2.44 for CDMA. If
@@ -184,7 +184,8 @@
* @param cellIdentity The identity representing a unique cell or wifi AP. Set to null if the
* information is not available.
*/
- public NetworkRegistrationState(@Domain int domain, int transportType, @RegState int regState,
+ public NetworkRegistrationState(@Domain int domain, @TransportType int transportType,
+ @RegState int regState,
@NetworkType int accessNetworkTechnology, int rejectCause,
boolean emergencyOnly,
@NonNull @ServiceType int[] availableServices,
@@ -206,7 +207,7 @@
* Constructor for voice network registration states.
* @hide
*/
- public NetworkRegistrationState(int domain, int transportType, int regState,
+ public NetworkRegistrationState(int domain, @TransportType int transportType, int regState,
int accessNetworkTechnology, int rejectCause, boolean emergencyOnly,
int[] availableServices, @Nullable CellIdentity cellIdentity, boolean cssSupported,
int roamingIndicator, int systemIsInPrl, int defaultRoamingIndicator) {
@@ -221,7 +222,7 @@
* Constructor for data network registration states.
* @hide
*/
- public NetworkRegistrationState(int domain, int transportType, int regState,
+ public NetworkRegistrationState(int domain, @TransportType int transportType, int regState,
int accessNetworkTechnology, int rejectCause, boolean emergencyOnly,
int[] availableServices, @Nullable CellIdentity cellIdentity, int maxDataCalls,
boolean isDcNrRestricted, boolean isNrAvailable, boolean isEndcAvailable,
@@ -434,7 +435,8 @@
public String toString() {
return new StringBuilder("NetworkRegistrationState{")
.append(" domain=").append((mDomain == DOMAIN_CS) ? "CS" : "PS")
- .append(" transportType=").append(TransportType.toString(mTransportType))
+ .append(" transportType=").append(
+ AccessNetworkConstants.transportTypeToString(mTransportType))
.append(" regState=").append(regStateToString(mRegState))
.append(" roamingType=").append(ServiceState.roamingTypeToString(mRoamingType))
.append(" accessNetworkTechnology=")
@@ -627,7 +629,7 @@
*
* @return The same instance of the builder.
*/
- public @NonNull Builder setTransportType(int transportType) {
+ public @NonNull Builder setTransportType(@TransportType int transportType) {
mTransportType = transportType;
return this;
}
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index 6118129..4b15aac 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -28,6 +28,7 @@
import android.os.Parcel;
import android.os.Parcelable;
import android.telephony.AccessNetworkConstants.AccessNetworkType;
+import android.telephony.AccessNetworkConstants.TransportType;
import android.telephony.NetworkRegistrationState.Domain;
import android.telephony.NetworkRegistrationState.NRStatus;
import android.text.TextUtils;
@@ -620,7 +621,7 @@
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
public @RoamingType int getVoiceRoamingType() {
final NetworkRegistrationState regState = getNetworkRegistrationState(
- NetworkRegistrationState.DOMAIN_CS, AccessNetworkConstants.TransportType.WWAN);
+ NetworkRegistrationState.DOMAIN_CS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
if (regState != null) {
return regState.getRoamingType();
}
@@ -644,7 +645,7 @@
*/
public boolean getDataRoamingFromRegistration() {
final NetworkRegistrationState regState = getNetworkRegistrationState(
- NetworkRegistrationState.DOMAIN_PS, AccessNetworkConstants.TransportType.WWAN);
+ NetworkRegistrationState.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
if (regState != null) {
return (regState.getRegState() == NetworkRegistrationState.REG_STATE_ROAMING);
}
@@ -659,7 +660,7 @@
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
public @RoamingType int getDataRoamingType() {
final NetworkRegistrationState regState = getNetworkRegistrationState(
- NetworkRegistrationState.DOMAIN_PS, AccessNetworkConstants.TransportType.WWAN);
+ NetworkRegistrationState.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
if (regState != null) {
return regState.getRoamingType();
}
@@ -837,7 +838,7 @@
mVoiceRegState,
mDataRegState,
mChannelNumber,
- mCellBandwidths,
+ Arrays.hashCode(mCellBandwidths),
mVoiceOperatorAlphaLong,
mVoiceOperatorAlphaShort,
mVoiceOperatorNumeric,
@@ -1130,10 +1131,10 @@
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
public void setVoiceRoamingType(@RoamingType int type) {
NetworkRegistrationState regState = getNetworkRegistrationState(
- NetworkRegistrationState.DOMAIN_CS, AccessNetworkConstants.TransportType.WWAN);
+ NetworkRegistrationState.DOMAIN_CS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
if (regState == null) {
regState = new NetworkRegistrationState(
- NetworkRegistrationState.DOMAIN_CS, AccessNetworkConstants.TransportType.WWAN,
+ NetworkRegistrationState.DOMAIN_CS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN,
ServiceState.ROAMING_TYPE_NOT_ROAMING, TelephonyManager.NETWORK_TYPE_UNKNOWN, 0,
false, null, null);
addNetworkRegistrationState(regState);
@@ -1151,10 +1152,10 @@
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
public void setDataRoamingType(@RoamingType int type) {
NetworkRegistrationState regState = getNetworkRegistrationState(
- NetworkRegistrationState.DOMAIN_PS, AccessNetworkConstants.TransportType.WWAN);
+ NetworkRegistrationState.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
if (regState == null) {
regState = new NetworkRegistrationState(
- NetworkRegistrationState.DOMAIN_PS, AccessNetworkConstants.TransportType.WWAN,
+ NetworkRegistrationState.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN,
ServiceState.ROAMING_TYPE_NOT_ROAMING, TelephonyManager.NETWORK_TYPE_UNKNOWN, 0,
false, null, null);
addNetworkRegistrationState(regState);
@@ -1326,10 +1327,10 @@
// sync to network registration state
NetworkRegistrationState regState = getNetworkRegistrationState(
- NetworkRegistrationState.DOMAIN_CS, AccessNetworkConstants.TransportType.WWAN);
+ NetworkRegistrationState.DOMAIN_CS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
if (regState == null) {
regState = new NetworkRegistrationState(
- NetworkRegistrationState.DOMAIN_CS, AccessNetworkConstants.TransportType.WWAN,
+ NetworkRegistrationState.DOMAIN_CS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN,
ServiceState.ROAMING_TYPE_NOT_ROAMING, TelephonyManager.NETWORK_TYPE_UNKNOWN,
0, false, null, null);
addNetworkRegistrationState(regState);
@@ -1353,11 +1354,11 @@
// sync to network registration state
NetworkRegistrationState regState = getNetworkRegistrationState(
- NetworkRegistrationState.DOMAIN_PS, AccessNetworkConstants.TransportType.WWAN);
+ NetworkRegistrationState.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
if (regState == null) {
regState = new NetworkRegistrationState(
- NetworkRegistrationState.DOMAIN_PS, AccessNetworkConstants.TransportType.WWAN,
+ NetworkRegistrationState.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN,
ServiceState.ROAMING_TYPE_NOT_ROAMING, TelephonyManager.NETWORK_TYPE_UNKNOWN,
0, false, null, null);
addNetworkRegistrationState(regState);
@@ -1391,7 +1392,7 @@
*/
public @NRStatus int getNrStatus() {
final NetworkRegistrationState regState = getNetworkRegistrationState(
- NetworkRegistrationState.DOMAIN_PS, AccessNetworkConstants.TransportType.WWAN);
+ NetworkRegistrationState.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
if (regState == null) return NetworkRegistrationState.NR_STATUS_NONE;
return regState.getNrStatus();
}
@@ -1576,7 +1577,7 @@
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
public @TelephonyManager.NetworkType int getDataNetworkType() {
final NetworkRegistrationState iwlanRegState = getNetworkRegistrationState(
- NetworkRegistrationState.DOMAIN_PS, AccessNetworkConstants.TransportType.WLAN);
+ NetworkRegistrationState.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WLAN);
if (iwlanRegState != null
&& iwlanRegState.getRegState() == NetworkRegistrationState.REG_STATE_HOME) {
// If the device is on IWLAN, return IWLAN as the network type. This is to simulate the
@@ -1587,7 +1588,7 @@
}
final NetworkRegistrationState regState = getNetworkRegistrationState(
- NetworkRegistrationState.DOMAIN_PS, AccessNetworkConstants.TransportType.WWAN);
+ NetworkRegistrationState.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
if (regState != null) {
return regState.getAccessNetworkTechnology();
}
@@ -1598,7 +1599,7 @@
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
public @TelephonyManager.NetworkType int getVoiceNetworkType() {
final NetworkRegistrationState regState = getNetworkRegistrationState(
- NetworkRegistrationState.DOMAIN_CS, AccessNetworkConstants.TransportType.WWAN);
+ NetworkRegistrationState.DOMAIN_CS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
if (regState != null) {
return regState.getAccessNetworkTechnology();
}
@@ -1777,11 +1778,11 @@
/**
* Get the network registration states for the transport type.
*
- * @param transportType The {@link AccessNetworkConstants.TransportType transport type}
+ * @param transportType The transport type
* @return List of {@link NetworkRegistrationState}
* @hide
*
- * @deprecated Use {@link #getNetworkRegistrationStatesFromTransportType(int)}
+ * @deprecated Use {@link #getNetworkRegistrationStatesForTransportType(int)}
*/
@NonNull
@Deprecated
@@ -1793,14 +1794,14 @@
/**
* Get the network registration states for the transport type.
*
- * @param transportType The {@link AccessNetworkConstants.TransportType transport type}
+ * @param transportType The transport type
* @return List of {@link NetworkRegistrationState}
* @hide
*/
@NonNull
@SystemApi
public List<NetworkRegistrationState> getNetworkRegistrationStatesForTransportType(
- int transportType) {
+ @TransportType int transportType) {
List<NetworkRegistrationState> list = new ArrayList<>();
synchronized (mNetworkRegistrationStates) {
@@ -1842,7 +1843,7 @@
* Get the network registration state for the transport type and network domain.
*
* @param domain The network {@link NetworkRegistrationState.Domain domain}
- * @param transportType The {@link AccessNetworkConstants.TransportType transport type}
+ * @param transportType The transport type
* @return The matching {@link NetworkRegistrationState}
* @hide
*
@@ -1852,7 +1853,7 @@
@Deprecated
@SystemApi
public NetworkRegistrationState getNetworkRegistrationStates(@Domain int domain,
- int transportType) {
+ @TransportType int transportType) {
return getNetworkRegistrationState(domain, transportType);
}
@@ -1860,7 +1861,7 @@
* Get the network registration state for the transport type and network domain.
*
* @param domain The network {@link NetworkRegistrationState.Domain domain}
- * @param transportType The {@link AccessNetworkConstants.TransportType transport type}
+ * @param transportType The transport type
* @return The matching {@link NetworkRegistrationState}
* @hide
*
@@ -1868,7 +1869,7 @@
@Nullable
@SystemApi
public NetworkRegistrationState getNetworkRegistrationState(@Domain int domain,
- int transportType) {
+ @TransportType int transportType) {
synchronized (mNetworkRegistrationStates) {
for (NetworkRegistrationState networkRegistrationState : mNetworkRegistrationStates) {
if (networkRegistrationState.getTransportType() == transportType
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 1662d6e..0bbf054 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -2008,21 +2008,27 @@
}
/**
- * Checks if the supplied subscription ID is valid.
- * Note: a valid subscription ID does not necessarily correspond to an active subscription.
+ * Check if the supplied subscription ID is valid.
+ *
+ * <p>A valid subscription ID is not necessarily an active subscription ID
+ * (see {@link #isActiveSubscriptionId(int)}) or an usable subscription ID
+ * (see {@link #isUsableSubscriptionId(int)}). Unless specifically noted, subscription
+ * APIs work with a valid subscription ID.
*
* @param subscriptionId The subscription ID.
- * @return true if the supplied subscriptionId is valid; false otherwise.
+ * @return {@code true} if the supplied subscriptionId is valid; {@code false} otherwise.
*/
public static boolean isValidSubscriptionId(int subscriptionId) {
return subscriptionId > INVALID_SUBSCRIPTION_ID;
}
/**
- * Check if the subscription ID is usable.
+ * Check if the supplied subscription ID is usable.
*
- * A usable subscription ID has a valid value except some special values such as
- * {@link #DEFAULT_SUBSCRIPTION_ID}. It can be used for subscription functions.
+ * <p>A usable subscription ID is a valid subscription ID, but not necessarily an active
+ * subscription ID (see {@link #isActiveSubscriptionId(int)}). Some subscription APIs
+ * require a usable subscription ID, and this is noted in their documentation; otherwise, a
+ * subscription ID does not need to be usable for subscription functions, only valid.
*
* @param subscriptionId the subscription ID
* @return {@code true} if the subscription ID is usable; {@code false} otherwise.
@@ -2280,7 +2286,8 @@
}
/**
- * Checks if the supplied subscription ID corresponds to an active subscription.
+ * Checks if the supplied subscription ID corresponds to a subscription which is actively in
+ * use on the device. An active subscription ID is a valid and usable subscription ID.
*
* @param subscriptionId the subscription ID.
* @return {@code true} if the supplied subscription ID corresponds to an active subscription;
@@ -2599,7 +2606,7 @@
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
public void setPreferredDataSubscriptionId(int subId, boolean needValidation,
- @NonNull @CallbackExecutor Executor executor, Consumer<Integer> callback) {
+ @Nullable @CallbackExecutor Executor executor, @Nullable Consumer<Integer> callback) {
if (VDBG) logd("[setPreferredDataSubscriptionId]+ subId:" + subId);
try {
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
@@ -2608,10 +2615,11 @@
ISetOpportunisticDataCallback callbackStub = new ISetOpportunisticDataCallback.Stub() {
@Override
public void onComplete(int result) {
+ if (executor == null || callback == null) {
+ return;
+ }
Binder.withCleanCallingIdentity(() -> executor.execute(() -> {
- if (callback != null) {
- callback.accept(result);
- }
+ callback.accept(result);
}));
}
};
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 8bfc206..7ea50b0 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -81,6 +81,7 @@
import com.android.internal.telephony.INumberVerificationCallback;
import com.android.internal.telephony.IOns;
import com.android.internal.telephony.IPhoneSubInfo;
+import com.android.internal.telephony.ISetOpportunisticDataCallback;
import com.android.internal.telephony.ITelephony;
import com.android.internal.telephony.ITelephonyRegistry;
import com.android.internal.telephony.IUpdateAvailableNetworksCallback;
@@ -95,6 +96,7 @@
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
@@ -3298,26 +3300,25 @@
}
/**
- * Get the mapping from logical slots to physical slots. The mapping represent by a pair list.
- * The key of the piar is the logical slot id and the value of the pair is the physical
- * slots id mapped to this logical slot id.
+ * Get the mapping from logical slots to physical slots. The key of the map is the logical slot
+ * id and the value is the physical slots id mapped to this logical slot id.
*
- * @return an pair list indicates the mapping from logical slots to physical slots. The size of
- * the list should be {@link #getPhoneCount()} if success, otherwise return an empty list.
+ * @return a map indicates the mapping from logical slots to physical slots. The size of the map
+ * should be {@link #getPhoneCount()} if success, otherwise return an empty map.
*
* @hide
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
@NonNull
- public List<Pair<Integer, Integer>> getLogicalToPhysicalSlotMapping() {
- List<Pair<Integer, Integer>> slotMapping = new ArrayList<>();
+ public Map<Integer, Integer> getLogicalToPhysicalSlotMapping() {
+ Map<Integer, Integer> slotMapping = new HashMap<>();
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
int[] slotMappingArray = telephony.getSlotsMapping();
for (int i = 0; i < slotMappingArray.length; i++) {
- slotMapping.add(new Pair(i, slotMappingArray[i]));
+ slotMapping.put(i, slotMappingArray[i]);
}
}
} catch (RemoteException e) {
@@ -10195,21 +10196,40 @@
* @param subId which opportunistic subscription
* {@link SubscriptionManager#getOpportunisticSubscriptions} is preferred for cellular data.
* Pass {@link SubscriptionManager#DEFAULT_SUBSCRIPTION_ID} to unset the preference
- * @return true if request is accepted, else false.
+ * @param needValidation whether validation is needed before switch happens.
+ * @param executor The executor of where the callback will execute.
+ * @param callback Callback will be triggered once it succeeds or failed.
+ * See {@link TelephonyManager.SetOpportunisticSubscriptionResult}
+ * for more details. Pass null if don't care about the result.
*
*/
- public boolean setPreferredOpportunisticDataSubscription(int subId) {
+ public void setPreferredOpportunisticDataSubscription(int subId, boolean needValidation,
+ @Nullable @CallbackExecutor Executor executor, @Nullable Consumer<Integer> callback) {
String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>";
try {
IOns iOpportunisticNetworkService = getIOns();
- if (iOpportunisticNetworkService != null) {
- return iOpportunisticNetworkService
- .setPreferredDataSubscriptionId(subId, pkgForDebug);
+ if (iOpportunisticNetworkService == null) {
+ return;
}
+ ISetOpportunisticDataCallback callbackStub = new ISetOpportunisticDataCallback.Stub() {
+ @Override
+ public void onComplete(int result) {
+ if (executor == null || callback == null) {
+ return;
+ }
+ Binder.withCleanCallingIdentity(() -> executor.execute(() -> {
+ callback.accept(result);
+ }));
+ }
+ };
+
+ iOpportunisticNetworkService
+ .setPreferredDataSubscriptionId(subId, needValidation, callbackStub,
+ pkgForDebug);
} catch (RemoteException ex) {
Rlog.e(TAG, "setPreferredDataSubscriptionId RemoteException", ex);
}
- return false;
+ return;
}
/**
@@ -10244,11 +10264,11 @@
/**
* Update availability of a list of networks in the current location.
*
- * This api should be called by opportunistic network selection app to inform
- * OpportunisticNetwork Service about the availability of a network at the current location.
- * This information will be used by OpportunisticNetwork service to decide to attach to the
- * network opportunistically.
- * If an empty list is passed, it is assumed that no network is available.
+ * This api should be called to inform OpportunisticNetwork Service about the availability
+ * of a network at the current location. This information will be used by OpportunisticNetwork
+ * service to decide to attach to the network opportunistically. If an empty list is passed,
+ * it is assumed that no network is available and will result in disabling the modem stack
+ * to save power.
* Requires that the calling app has carrier privileges on both primary and
* secondary subscriptions (see {@link #hasCarrierPrivileges}), or has permission
* {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}.
diff --git a/telephony/java/android/telephony/ims/ImsMmTelManager.java b/telephony/java/android/telephony/ims/ImsMmTelManager.java
index 58ddf21..10457fc 100644
--- a/telephony/java/android/telephony/ims/ImsMmTelManager.java
+++ b/telephony/java/android/telephony/ims/ImsMmTelManager.java
@@ -107,9 +107,9 @@
// case, since it is defined.
put(ImsRegistrationImplBase.REGISTRATION_TECH_NONE, -1);
put(ImsRegistrationImplBase.REGISTRATION_TECH_LTE,
- AccessNetworkConstants.TransportType.WWAN);
+ AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
put(ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN,
- AccessNetworkConstants.TransportType.WLAN);
+ AccessNetworkConstants.TRANSPORT_TYPE_WLAN);
}};
private final RegistrationCallback mLocalCallback;
diff --git a/telephony/java/com/android/internal/telephony/IOns.aidl b/telephony/java/com/android/internal/telephony/IOns.aidl
index 4672e2d..a74498f 100755
--- a/telephony/java/com/android/internal/telephony/IOns.aidl
+++ b/telephony/java/com/android/internal/telephony/IOns.aidl
@@ -19,6 +19,8 @@
import android.telephony.AvailableNetworkInfo;
import com.android.internal.telephony.IUpdateAvailableNetworksCallback;
+import com.android.internal.telephony.ISetOpportunisticDataCallback;
+
interface IOns {
/**
@@ -63,11 +65,13 @@
* @param subId which opportunistic subscription
* {@link SubscriptionManager#getOpportunisticSubscriptions} is preferred for cellular data.
* Pass {@link SubscriptionManager#DEFAULT_SUBSCRIPTION_ID} to unset the preference
+ * @param needValidation whether validation is needed before switch happens.
+ * @param callback callback upon request completion.
* @param callingPackage caller's package name
- * @return true if request is accepted, else false.
*
*/
- boolean setPreferredDataSubscriptionId(int subId, String callingPackage);
+ void setPreferredDataSubscriptionId(int subId, boolean needValidation,
+ ISetOpportunisticDataCallback callbackStub, String callingPackage);
/**
* Get preferred opportunistic data subscription Id
diff --git a/tests/net/java/com/android/internal/util/TestUtils.java b/tests/net/java/com/android/internal/util/TestUtils.java
index 7e5a1d3..57cc172 100644
--- a/tests/net/java/com/android/internal/util/TestUtils.java
+++ b/tests/net/java/com/android/internal/util/TestUtils.java
@@ -19,6 +19,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
+import android.annotation.NonNull;
import android.os.ConditionVariable;
import android.os.Handler;
import android.os.HandlerThread;
@@ -26,6 +27,8 @@
import android.os.Parcel;
import android.os.Parcelable;
+import java.util.concurrent.Executor;
+
public final class TestUtils {
private TestUtils() { }
@@ -54,6 +57,17 @@
}
}
+ /**
+ * Block until the given Serial Executor becomes idle, or until timeoutMs has passed.
+ */
+ public static void waitForIdleSerialExecutor(@NonNull Executor executor, long timeoutMs) {
+ final ConditionVariable cv = new ConditionVariable();
+ executor.execute(() -> cv.open());
+ if (!cv.block(timeoutMs)) {
+ fail(executor.toString() + " did not become idle after " + timeoutMs + " ms");
+ }
+ }
+
// TODO : fetch the creator through reflection or something instead of passing it
public static <T extends Parcelable, C extends Parcelable.Creator<T>>
void assertParcelingIsLossless(T source, C creator) {
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index b92d934..3efdfd9 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -63,6 +63,7 @@
import static com.android.internal.util.TestUtils.waitForIdleHandler;
import static com.android.internal.util.TestUtils.waitForIdleLooper;
+import static com.android.internal.util.TestUtils.waitForIdleSerialExecutor;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -87,6 +88,7 @@
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
+import android.annotation.NonNull;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
@@ -3758,7 +3760,7 @@
}
}
- private LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
+ private final LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
@Override
public void onStarted() {
@@ -3833,6 +3835,11 @@
}
private LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
+ private final Executor mExecutor;
+
+ TestSocketKeepaliveCallback(@NonNull Executor executor) {
+ mExecutor = executor;
+ }
@Override
public void onStarted() {
@@ -3870,6 +3877,12 @@
public void expectError(int error) {
expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
}
+
+ public void assertNoCallback() {
+ waitForIdleSerialExecutor(mExecutor, TIMEOUT_MS);
+ CallbackValue cv = mCallbacks.peek();
+ assertNull("Unexpected callback: " + cv, cv);
+ }
}
private Network connectKeepaliveNetwork(LinkProperties lp) {
@@ -3976,19 +3989,6 @@
myNet = connectKeepaliveNetwork(lp);
mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
- // Check things work as expected when the keepalive is stopped and the network disconnects.
- ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
- callback.expectStarted();
- ka.stop();
- mWiFiNetworkAgent.disconnect();
- waitFor(mWiFiNetworkAgent.getDisconnectedCV());
- waitForIdle();
- callback.expectStopped();
-
- // Reconnect.
- myNet = connectKeepaliveNetwork(lp);
- mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
-
// Check that keepalive slots start from 1 and increment. The first one gets slot 1.
mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
@@ -4064,7 +4064,7 @@
Network notMyNet = new Network(61234);
Network myNet = connectKeepaliveNetwork(lp);
- TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback();
+ TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
SocketKeepalive ka;
// Attempt to start keepalives with invalid parameters and check for errors.
@@ -4107,6 +4107,22 @@
ka.stop();
callback.expectStopped();
+ // Check that keepalive could be restarted.
+ ka.start(validKaInterval);
+ callback.expectStarted();
+ ka.stop();
+ callback.expectStopped();
+
+ // Check that keepalive can be restarted without waiting for callback.
+ ka.start(validKaInterval);
+ callback.expectStarted();
+ ka.stop();
+ ka.start(validKaInterval);
+ callback.expectStopped();
+ callback.expectStarted();
+ ka.stop();
+ callback.expectStopped();
+
// Check that deleting the IP address stops the keepalive.
LinkProperties bogusLp = new LinkProperties(lp);
ka = mCm.createSocketKeepalive(myNet, testSocket, myIPv4, dstIPv4, executor, callback);
@@ -4131,20 +4147,7 @@
final Network myNetAlias = myNet;
assertNull(mCm.getNetworkCapabilities(myNetAlias));
ka.stop();
-
- // Reconnect.
- myNet = connectKeepaliveNetwork(lp);
- mWiFiNetworkAgent.setStartKeepaliveError(SocketKeepalive.SUCCESS);
-
- // Check things work as expected when the keepalive is stopped and the network disconnects.
- ka = mCm.createSocketKeepalive(myNet, testSocket, myIPv4, dstIPv4, executor, callback);
- ka.start(validKaInterval);
- callback.expectStarted();
- ka.stop();
- mWiFiNetworkAgent.disconnect();
- waitFor(mWiFiNetworkAgent.getDisconnectedCV());
- waitForIdle();
- callback.expectStopped();
+ callback.assertNoCallback();
// Reconnect.
myNet = connectKeepaliveNetwork(lp);
@@ -4159,7 +4162,7 @@
// The second one gets slot 2.
mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
final UdpEncapsulationSocket testSocket2 = mIpSec.openUdpEncapsulationSocket(6789);
- TestSocketKeepaliveCallback callback2 = new TestSocketKeepaliveCallback();
+ TestSocketKeepaliveCallback callback2 = new TestSocketKeepaliveCallback(executor);
SocketKeepalive ka2 =
mCm.createSocketKeepalive(myNet, testSocket2, myIPv4, dstIPv4, executor, callback2);
ka2.start(validKaInterval);
@@ -4212,7 +4215,7 @@
final Socket testSocketV4 = new Socket();
final Socket testSocketV6 = new Socket();
- TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback();
+ TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
SocketKeepalive ka;
// Attempt to start Tcp keepalives with invalid parameters and check for errors.