summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--config/Android.bp18
-rw-r--r--core/java/android/net/ConnectivityManager.java18
-rw-r--r--core/java/android/net/DnsResolver.java12
-rw-r--r--core/java/android/net/TrafficStats.java5
-rw-r--r--core/java/android/os/BugreportManager.java1
-rw-r--r--core/java/android/view/ViewRootImpl.java1
-rw-r--r--core/jni/android_os_HwBinder.cpp19
-rw-r--r--core/jni/android_os_HwBinder.h2
-rw-r--r--core/jni/android_os_HwParcel.cpp8
-rw-r--r--services/core/java/com/android/server/connectivity/KeepaliveTracker.java59
-rw-r--r--services/core/java/com/android/server/connectivity/Tethering.java27
-rw-r--r--services/core/java/com/android/server/connectivity/tethering/EntitlementManager.java126
-rw-r--r--telephony/java/android/telephony/SubscriptionInfo.java59
-rw-r--r--telephony/java/android/telephony/SubscriptionManager.java16
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java12
-rw-r--r--telephony/java/android/telephony/ims/ImsMmTelManager.java9
-rw-r--r--telephony/java/android/telephony/ims/compat/feature/ImsFeature.java51
-rw-r--r--telephony/java/android/telephony/ims/feature/ImsFeature.java25
-rw-r--r--tests/net/java/com/android/server/ConnectivityServiceTest.java8
-rw-r--r--tests/net/java/com/android/server/connectivity/tethering/EntitlementManagerTest.java58
-rw-r--r--tools/preload-check/Android.bp1
-rw-r--r--tools/preload-check/src/com/android/preload/check/PreloadCheck.java41
22 files changed, 348 insertions, 228 deletions
diff --git a/config/Android.bp b/config/Android.bp
new file mode 100644
index 000000000000..0fb56cb3410a
--- /dev/null
+++ b/config/Android.bp
@@ -0,0 +1,18 @@
+// 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.
+
+filegroup {
+ name: "preloaded-classes-blacklist",
+ srcs: ["preloaded-classes-blacklist"],
+}
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 2906710b0655..0e10de8c4e3f 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -510,7 +510,7 @@ public class ConnectivityManager {
* The absence of a connection type.
* @hide
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 130143562)
public static final int TYPE_NONE = -1;
/**
@@ -627,7 +627,7 @@ public class ConnectivityManager {
* {@hide}
*/
@Deprecated
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 130143562)
public static final int TYPE_MOBILE_FOTA = 10;
/**
@@ -645,7 +645,7 @@ public class ConnectivityManager {
* {@hide}
*/
@Deprecated
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 130143562)
public static final int TYPE_MOBILE_CBS = 12;
/**
@@ -655,7 +655,7 @@ public class ConnectivityManager {
* {@hide}
*/
@Deprecated
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 130143562)
public static final int TYPE_WIFI_P2P = 13;
/**
@@ -674,7 +674,7 @@ public class ConnectivityManager {
* {@hide}
*/
@Deprecated
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 130143562)
public static final int TYPE_MOBILE_EMERGENCY = 15;
/**
@@ -775,7 +775,7 @@ public class ConnectivityManager {
*/
public static final String PRIVATE_DNS_DEFAULT_MODE_FALLBACK = PRIVATE_DNS_MODE_OPPORTUNISTIC;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 130143562)
private final IConnectivityManager mService;
/**
* A kludge to facilitate static access where a Context pointer isn't available, like in the
@@ -867,7 +867,7 @@ public class ConnectivityManager {
* {@hide}
*/
@Deprecated
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 130143562)
public static boolean isNetworkTypeMobile(int networkType) {
switch (networkType) {
case TYPE_MOBILE:
@@ -1304,7 +1304,7 @@ public class ConnectivityManager {
*/
@Deprecated
@RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 130143562)
public LinkProperties getLinkProperties(int networkType) {
try {
return mService.getLinkPropertiesForType(networkType);
@@ -3042,7 +3042,7 @@ public class ConnectivityManager {
*/
@Deprecated
@RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 130143562)
public boolean isNetworkSupported(int networkType) {
try {
return mService.isNetworkSupported(networkType);
diff --git a/core/java/android/net/DnsResolver.java b/core/java/android/net/DnsResolver.java
index b6c4fe2de4f4..68826cbeb845 100644
--- a/core/java/android/net/DnsResolver.java
+++ b/core/java/android/net/DnsResolver.java
@@ -197,7 +197,7 @@ public final class DnsResolver {
final FileDescriptor queryfd;
try {
queryfd = resNetworkSend((network != null
- ? network.netId : NETID_UNSET), query, query.length, flags);
+ ? network.getNetIdForResolv() : NETID_UNSET), query, query.length, flags);
} catch (ErrnoException e) {
executor.execute(() -> callback.onError(new DnsException(ERROR_SYSTEM, e)));
return;
@@ -238,7 +238,7 @@ public final class DnsResolver {
final FileDescriptor queryfd;
try {
queryfd = resNetworkQuery((network != null
- ? network.netId : NETID_UNSET), domain, nsClass, nsType, flags);
+ ? network.getNetIdForResolv() : NETID_UNSET), domain, nsClass, nsType, flags);
} catch (ErrnoException e) {
executor.execute(() -> callback.onError(new DnsException(ERROR_SYSTEM, e)));
return;
@@ -346,7 +346,8 @@ public final class DnsResolver {
if (queryIpv6) {
try {
v6fd = resNetworkQuery((network != null
- ? network.netId : NETID_UNSET), domain, CLASS_IN, TYPE_AAAA, flags);
+ ? network.getNetIdForResolv() : NETID_UNSET),
+ domain, CLASS_IN, TYPE_AAAA, flags);
} catch (ErrnoException e) {
executor.execute(() -> callback.onError(new DnsException(ERROR_SYSTEM, e)));
return;
@@ -365,7 +366,8 @@ public final class DnsResolver {
if (queryIpv4) {
try {
v4fd = resNetworkQuery((network != null
- ? network.netId : NETID_UNSET), domain, CLASS_IN, TYPE_A, flags);
+ ? network.getNetIdForResolv() : NETID_UNSET),
+ domain, CLASS_IN, TYPE_A, flags);
} catch (ErrnoException e) {
if (queryIpv6) resNetworkCancel(v6fd); // Closes fd, marks it invalid.
executor.execute(() -> callback.onError(new DnsException(ERROR_SYSTEM, e)));
@@ -423,7 +425,7 @@ public final class DnsResolver {
final FileDescriptor queryfd;
try {
queryfd = resNetworkQuery((network != null
- ? network.netId : NETID_UNSET), domain, CLASS_IN, nsType, flags);
+ ? network.getNetIdForResolv() : NETID_UNSET), domain, CLASS_IN, nsType, flags);
} catch (ErrnoException e) {
executor.execute(() -> callback.onError(new DnsException(ERROR_SYSTEM, e)));
return;
diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java
index 49c6f74b1a34..5a22747cb499 100644
--- a/core/java/android/net/TrafficStats.java
+++ b/core/java/android/net/TrafficStats.java
@@ -25,6 +25,7 @@ import android.app.backup.BackupManager;
import android.app.usage.NetworkStatsManager;
import android.content.Context;
import android.media.MediaPlayer;
+import android.os.Build;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.DataUnit;
@@ -150,7 +151,7 @@ public class TrafficStats {
private static INetworkStatsService sStatsService;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 130143562)
private synchronized static INetworkStatsService getStatsService() {
if (sStatsService == null) {
sStatsService = INetworkStatsService.Stub.asInterface(
@@ -960,7 +961,7 @@ public class TrafficStats {
* Interfaces are never removed from this list, so counters should always be
* monotonic.
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 130143562)
private static String[] getMobileIfaces() {
try {
return getStatsService().getMobileIfaces();
diff --git a/core/java/android/os/BugreportManager.java b/core/java/android/os/BugreportManager.java
index 0feed68163e2..e366fe05723e 100644
--- a/core/java/android/os/BugreportManager.java
+++ b/core/java/android/os/BugreportManager.java
@@ -175,6 +175,7 @@ public final class BugreportManager {
// Need to delete the file if it was created but failed while trying to get fd
deleteFile(tmpScreenshotFile);
Log.e(TAG, "Not able to create/open temporary screenshot file ", e);
+ callback.onError(BugreportCallback.BUGREPORT_ERROR_RUNTIME);
} finally {
// We can close the file descriptors here because binder would have duped them.
IoUtils.closeQuietly(bugreportFd);
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 5a1089bbc2b4..d17646216a64 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -1365,6 +1365,7 @@ public final class ViewRootImpl implements ViewParent,
renderer.setStopped(mStopped);
}
if (!mStopped) {
+ mNewSurfaceNeeded = true;
scheduleTraversals();
} else {
if (renderer != null) {
diff --git a/core/jni/android_os_HwBinder.cpp b/core/jni/android_os_HwBinder.cpp
index 42e3942eb350..9c60e6bd8565 100644
--- a/core/jni/android_os_HwBinder.cpp
+++ b/core/jni/android_os_HwBinder.cpp
@@ -224,6 +224,21 @@ status_t JHwBinder::onTransact(
return err;
}
+bool validateCanUseHwBinder(const sp<hardware::IBinder>& binder) {
+ if (binder != nullptr && binder->localBinder() != nullptr) {
+ // untested/unsupported/inefficient
+ // see b/129150021, doesn't work with scatter-gather
+ //
+ // explicitly disabling until it is supported
+ // (note, even if this is fixed to work with scatter gather, we would also need
+ // to convert this to the Java object rather than re-wrapping with a proxy)
+ LOG(ERROR) << "Local Java Binder not supported.";
+ return false;
+ }
+
+ return true;
+}
+
} // namespace android
////////////////////////////////////////////////////////////////////////////////
@@ -324,9 +339,9 @@ static jobject JHwBinder_native_getService(
sp<IBase> ret = getRawServiceInternal(ifaceName, serviceName, retry /* retry */, false /* getStub */);
sp<hardware::IBinder> service = hardware::toBinder<hidl::base::V1_0::IBase>(ret);
- if (service == NULL) {
+ if (service == nullptr || !validateCanUseHwBinder(service)) {
signalExceptionForError(env, NAME_NOT_FOUND);
- return NULL;
+ return nullptr;
}
LOG(INFO) << "HwBinder: Starting thread pool for getting: " << ifaceName << "/" << serviceName;
diff --git a/core/jni/android_os_HwBinder.h b/core/jni/android_os_HwBinder.h
index 5352f1e607c2..99195b1abc9c 100644
--- a/core/jni/android_os_HwBinder.h
+++ b/core/jni/android_os_HwBinder.h
@@ -54,6 +54,8 @@ private:
int register_android_os_HwBinder(JNIEnv *env);
+bool validateCanUseHwBinder(const sp<hardware::IBinder>& binder);
+
} // namespace android
#endif // _ANDROID_OS_HW_BINDER_H
diff --git a/core/jni/android_os_HwParcel.cpp b/core/jni/android_os_HwParcel.cpp
index 7221ca11cc00..f437a78e35f8 100644
--- a/core/jni/android_os_HwParcel.cpp
+++ b/core/jni/android_os_HwParcel.cpp
@@ -883,8 +883,12 @@ static jobject JHwParcel_native_readStrongBinder(JNIEnv *env, jobject thiz) {
sp<hardware::IBinder> binder = parcel->readStrongBinder();
- if (binder == NULL) {
- return NULL;
+ if (binder == nullptr) {
+ return nullptr;
+ }
+
+ if (!validateCanUseHwBinder(binder)) {
+ return nullptr;
}
return JHwRemoteBinder::NewObject(env, binder);
diff --git a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java
index 35f7ea3ae0fe..77a18e2b3ddc 100644
--- a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java
+++ b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java
@@ -191,6 +191,7 @@ public class KeepaliveTracker {
case NOT_STARTED : return "NOT_STARTED";
case STARTING : return "STARTING";
case STARTED : return "STARTED";
+ case STOPPING : return "STOPPING";
}
throw new IllegalArgumentException("Unknown state");
}
@@ -314,18 +315,27 @@ public class KeepaliveTracker {
Log.e(TAG, "Cannot stop unowned keepalive " + mSlot + " on " + mNai.network);
}
}
- if (NOT_STARTED != mStartedState) {
- mStartedState = STOPPING;
- Log.d(TAG, "Stopping keepalive " + mSlot + " on " + mNai.name());
- if (mType == TYPE_NATT) {
- mNai.asyncChannel.sendMessage(CMD_STOP_SOCKET_KEEPALIVE, mSlot);
- } else if (mType == TYPE_TCP) {
- mNai.asyncChannel.sendMessage(CMD_STOP_SOCKET_KEEPALIVE, mSlot);
- mNai.asyncChannel.sendMessage(CMD_REMOVE_KEEPALIVE_PACKET_FILTER, mSlot);
- mTcpController.stopSocketMonitor(mSlot);
- } else {
- Log.wtf(TAG, "Stopping keepalive with unknown type: " + mType);
- }
+ Log.d(TAG, "Stopping keepalive " + mSlot + " on " + mNai.name() + ": " + reason);
+ switch (mStartedState) {
+ case NOT_STARTED:
+ // Remove the reference of the keepalive that meet error before starting,
+ // e.g. invalid parameter.
+ cleanupStoppedKeepalive(mNai, mSlot);
+ break;
+ case STOPPING:
+ // Keepalive is already in stopping state, ignore.
+ return;
+ default:
+ mStartedState = STOPPING;
+ if (mType == TYPE_NATT) {
+ mNai.asyncChannel.sendMessage(CMD_STOP_SOCKET_KEEPALIVE, mSlot);
+ } else if (mType == TYPE_TCP) {
+ mNai.asyncChannel.sendMessage(CMD_STOP_SOCKET_KEEPALIVE, mSlot);
+ mNai.asyncChannel.sendMessage(CMD_REMOVE_KEEPALIVE_PACKET_FILTER, mSlot);
+ mTcpController.stopSocketMonitor(mSlot);
+ } else {
+ Log.wtf(TAG, "Stopping keepalive with unknown type: " + mType);
+ }
}
// Close the duplicated fd that maintains the lifecycle of socket whenever
@@ -405,9 +415,9 @@ public class KeepaliveTracker {
for (KeepaliveInfo ki : networkKeepalives.values()) {
ki.stop(reason);
}
- networkKeepalives.clear();
- mKeepalives.remove(nai);
}
+ // Clean up keepalives will be done as a result of calling ki.stop() after the slots are
+ // freed.
}
public void handleStopKeepalive(NetworkAgentInfo nai, int slot, int reason) {
@@ -423,8 +433,24 @@ public class KeepaliveTracker {
return;
}
ki.stop(reason);
+ // Clean up keepalives will be done as a result of calling ki.stop() after the slots are
+ // freed.
+ }
+
+ private void cleanupStoppedKeepalive(NetworkAgentInfo nai, int slot) {
+ String networkName = (nai == null) ? "(null)" : nai.name();
+ HashMap<Integer, KeepaliveInfo> networkKeepalives = mKeepalives.get(nai);
+ if (networkKeepalives == null) {
+ Log.e(TAG, "Attempt to remove keepalive on nonexistent network " + networkName);
+ return;
+ }
+ KeepaliveInfo ki = networkKeepalives.get(slot);
+ if (ki == null) {
+ Log.e(TAG, "Attempt to remove nonexistent keepalive " + slot + " on " + networkName);
+ return;
+ }
networkKeepalives.remove(slot);
- Log.d(TAG, "Stopped keepalive " + slot + " on " + networkName + ", "
+ Log.d(TAG, "Remove keepalive " + slot + " on " + networkName + ", "
+ networkKeepalives.size() + " remains.");
if (networkKeepalives.isEmpty()) {
mKeepalives.remove(nai);
@@ -495,10 +521,11 @@ public class KeepaliveTracker {
handleStopKeepalive(nai, slot, reason);
}
} else if (KeepaliveInfo.STOPPING == ki.mStartedState) {
- // The message indicated result of stopping : don't call handleStopKeepalive.
+ // The message indicated result of stopping : clean up keepalive slots.
Log.d(TAG, "Stopped keepalive " + slot + " on " + nai.name()
+ " stopped: " + reason);
ki.mStartedState = KeepaliveInfo.NOT_STARTED;
+ cleanupStoppedKeepalive(nai, slot);
} else {
Log.wtf(TAG, "Event " + message.what + "," + slot + "," + reason
+ " for keepalive in wrong state: " + ki.toString());
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index b140c1b25320..33c84d161a90 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -237,13 +237,17 @@ public class Tethering extends BaseNetworkObserver {
mLog.log("OBSERVED UiEnitlementFailed");
stopTethering(downstream);
});
+ mEntitlementMgr.setTetheringConfigurationFetcher(() -> {
+ maybeDefaultDataSubChanged();
+ return mConfig;
+ });
mCarrierConfigChange = new VersionedBroadcastListener(
"CarrierConfigChangeListener", mContext, mHandler, filter,
(Intent ignored) -> {
mLog.log("OBSERVED carrier config change");
updateConfiguration();
- mEntitlementMgr.reevaluateSimCardProvisioning();
+ mEntitlementMgr.reevaluateSimCardProvisioning(mConfig);
});
filter = new IntentFilter();
@@ -252,12 +256,12 @@ public class Tethering extends BaseNetworkObserver {
"DefaultSubscriptionChangeListener", mContext, mHandler, filter,
(Intent ignored) -> {
mLog.log("OBSERVED default data subscription change");
- updateConfiguration();
+ maybeDefaultDataSubChanged();
// To avoid launch unexpected provisioning checks, ignore re-provisioning when
// no CarrierConfig loaded yet. Assume reevaluateSimCardProvisioning() will be
// triggered again when CarrierConfig is loaded.
- if (mEntitlementMgr.getCarrierConfig() != null) {
- mEntitlementMgr.reevaluateSimCardProvisioning();
+ if (mEntitlementMgr.getCarrierConfig(mConfig) != null) {
+ mEntitlementMgr.reevaluateSimCardProvisioning(mConfig);
} else {
mLog.log("IGNORED reevaluate provisioning due to no carrier config loaded");
}
@@ -301,17 +305,26 @@ public class Tethering extends BaseNetworkObserver {
// NOTE: This is always invoked on the mLooper thread.
private void updateConfiguration() {
final int subId = mDeps.getDefaultDataSubscriptionId();
+ updateConfiguration(subId);
+ }
+
+ private void updateConfiguration(final int subId) {
mConfig = new TetheringConfiguration(mContext, mLog, subId);
mUpstreamNetworkMonitor.updateMobileRequiresDun(mConfig.isDunRequired);
- mEntitlementMgr.updateConfiguration(mConfig);
}
- private void maybeUpdateConfiguration() {
+ private void maybeDunSettingChanged() {
final boolean isDunRequired = TetheringConfiguration.checkDunRequired(mContext);
if (isDunRequired == mConfig.isDunRequired) return;
updateConfiguration();
}
+ private void maybeDefaultDataSubChanged() {
+ final int subId = mDeps.getDefaultDataSubscriptionId();
+ if (subId == mConfig.subId) return;
+ updateConfiguration(subId);
+ }
+
@Override
public void interfaceStatusChanged(String iface, boolean up) {
// Never called directly: only called from interfaceLinkStateChanged.
@@ -1183,7 +1196,7 @@ public class Tethering extends BaseNetworkObserver {
protected void chooseUpstreamType(boolean tryCell) {
// We rebuild configuration on ACTION_CONFIGURATION_CHANGED, but we
// do not currently know how to watch for changes in DUN settings.
- maybeUpdateConfiguration();
+ maybeDunSettingChanged();
final TetheringConfiguration config = mConfig;
final NetworkState ns = (config.chooseUpstreamAutomatically)
diff --git a/services/core/java/com/android/server/connectivity/tethering/EntitlementManager.java b/services/core/java/com/android/server/connectivity/tethering/EntitlementManager.java
index b0bbd72794d9..836f1e64aa9c 100644
--- a/services/core/java/com/android/server/connectivity/tethering/EntitlementManager.java
+++ b/services/core/java/com/android/server/connectivity/tethering/EntitlementManager.java
@@ -29,7 +29,6 @@ import static android.net.ConnectivityManager.TETHER_ERROR_PROVISION_FAILED;
import static com.android.internal.R.string.config_wifi_tether_enable;
-import android.annotation.Nullable;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
@@ -76,6 +75,7 @@ public class EntitlementManager {
protected static final String DISABLE_PROVISIONING_SYSPROP_KEY = "net.tethering.noprovisioning";
private static final String ACTION_PROVISIONING_ALARM =
"com.android.server.connectivity.tethering.PROVISIONING_RECHECK_ALARM";
+ private static final String EXTRA_SUBID = "subId";
// {@link ComponentName} of the Service used to run tether provisioning.
private static final ComponentName TETHER_SERVICE = ComponentName.unflattenFromString(
@@ -99,7 +99,6 @@ public class EntitlementManager {
private final SharedLog mLog;
private final SparseIntArray mEntitlementCacheValue;
private final EntitlementHandler mHandler;
- private @Nullable TetheringConfiguration mConfig;
private final StateMachine mTetherMasterSM;
// Key: ConnectivityManager.TETHERING_*(downstream).
// Value: ConnectivityManager.TETHER_ERROR_{NO_ERROR or PROVISION_FAILED}(provisioning result).
@@ -109,6 +108,7 @@ public class EntitlementManager {
private boolean mUsingCellularAsUpstream = false;
private boolean mNeedReRunProvisioningUi = false;
private OnUiEntitlementFailedListener mListener;
+ private TetheringConfigurationFetcher mFetcher;
public EntitlementManager(Context ctx, StateMachine tetherMasterSM, SharedLog log,
int permissionChangeMessageCode, MockableSystemProperties systemProperties) {
@@ -143,12 +143,18 @@ public class EntitlementManager {
void onUiEntitlementFailed(int downstream);
}
- /**
- * Pass a new TetheringConfiguration instance each time when
- * Tethering#updateConfiguration() is called.
- */
- public void updateConfiguration(TetheringConfiguration conf) {
- mConfig = conf;
+ public void setTetheringConfigurationFetcher(final TetheringConfigurationFetcher fetcher) {
+ mFetcher = fetcher;
+ }
+
+ /** Interface to fetch TetheringConfiguration. */
+ public interface TetheringConfigurationFetcher {
+ /**
+ * Fetch current tethering configuration. This will be called to ensure whether entitlement
+ * check is needed.
+ * @return TetheringConfiguration instance.
+ */
+ TetheringConfiguration fetchTetheringConfiguration();
}
/**
@@ -176,7 +182,8 @@ public class EntitlementManager {
if (!mCurrentTethers.contains(type)) mCurrentTethers.add(type);
- if (isTetherProvisioningRequired()) {
+ final TetheringConfiguration config = mFetcher.fetchTetheringConfiguration();
+ if (isTetherProvisioningRequired(config)) {
// If provisioning is required and the result is not available yet,
// cellular upstream should not be allowed.
if (mCellularPermitted.size() == 0) {
@@ -186,9 +193,9 @@ public class EntitlementManager {
// till upstream change to cellular.
if (mUsingCellularAsUpstream) {
if (showProvisioningUi) {
- runUiTetherProvisioning(type);
+ runUiTetherProvisioning(type, config.subId);
} else {
- runSilentTetherProvisioning(type);
+ runSilentTetherProvisioning(type, config.subId);
}
mNeedReRunProvisioningUi = false;
} else {
@@ -237,7 +244,8 @@ public class EntitlementManager {
mUsingCellularAsUpstream = isCellular;
if (mUsingCellularAsUpstream) {
- handleMaybeRunProvisioning();
+ final TetheringConfiguration config = mFetcher.fetchTetheringConfiguration();
+ handleMaybeRunProvisioning(config);
}
}
@@ -246,8 +254,8 @@ public class EntitlementManager {
mHandler.sendMessage(mHandler.obtainMessage(EVENT_MAYBE_RUN_PROVISIONING));
}
- private void handleMaybeRunProvisioning() {
- if (mCurrentTethers.size() == 0 || !isTetherProvisioningRequired()) {
+ private void handleMaybeRunProvisioning(final TetheringConfiguration config) {
+ if (mCurrentTethers.size() == 0 || !isTetherProvisioningRequired(config)) {
return;
}
@@ -259,9 +267,9 @@ public class EntitlementManager {
if (mCellularPermitted.indexOfKey(downstream) < 0) {
if (mNeedReRunProvisioningUi) {
mNeedReRunProvisioningUi = false;
- runUiTetherProvisioning(downstream);
+ runUiTetherProvisioning(downstream, config.subId);
} else {
- runSilentTetherProvisioning(downstream);
+ runSilentTetherProvisioning(downstream, config.subId);
}
}
}
@@ -270,29 +278,31 @@ public class EntitlementManager {
/**
* Check if the device requires a provisioning check in order to enable tethering.
*
+ * @param config an object that encapsulates the various tethering configuration elements.
* @return a boolean - {@code true} indicating tether provisioning is required by the carrier.
*/
@VisibleForTesting
- public boolean isTetherProvisioningRequired() {
+ protected boolean isTetherProvisioningRequired(final TetheringConfiguration config) {
if (mSystemProperties.getBoolean(DISABLE_PROVISIONING_SYSPROP_KEY, false)
- || mConfig.provisioningApp.length == 0) {
+ || config.provisioningApp.length == 0) {
return false;
}
- if (carrierConfigAffirmsEntitlementCheckNotRequired()) {
+ if (carrierConfigAffirmsEntitlementCheckNotRequired(config)) {
return false;
}
- return (mConfig.provisioningApp.length == 2);
+ return (config.provisioningApp.length == 2);
}
/**
* Re-check tethering provisioning for all enabled tether types.
* Reference ConnectivityManager.TETHERING_{@code *} for each tether type.
*
+ * @param config an object that encapsulates the various tethering configuration elements.
* Note: this method is only called from TetherMaster on the handler thread.
* If there are new callers from different threads, the logic should move to
* masterHandler to avoid race conditions.
*/
- public void reevaluateSimCardProvisioning() {
+ public void reevaluateSimCardProvisioning(final TetheringConfiguration config) {
if (DBG) mLog.i("reevaluateSimCardProvisioning");
if (!mHandler.getLooper().isCurrentThread()) {
@@ -303,24 +313,27 @@ public class EntitlementManager {
mCellularPermitted.clear();
// TODO: refine provisioning check to isTetherProvisioningRequired() ??
- if (!mConfig.hasMobileHotspotProvisionApp()
- || carrierConfigAffirmsEntitlementCheckNotRequired()) {
- evaluateCellularPermission();
+ if (!config.hasMobileHotspotProvisionApp()
+ || carrierConfigAffirmsEntitlementCheckNotRequired(config)) {
+ evaluateCellularPermission(config);
return;
}
if (mUsingCellularAsUpstream) {
- handleMaybeRunProvisioning();
+ handleMaybeRunProvisioning(config);
}
}
- /** Get carrier configuration bundle. */
- public PersistableBundle getCarrierConfig() {
+ /**
+ * Get carrier configuration bundle.
+ * @param config an object that encapsulates the various tethering configuration elements.
+ * */
+ public PersistableBundle getCarrierConfig(final TetheringConfiguration config) {
final CarrierConfigManager configManager = (CarrierConfigManager) mContext
.getSystemService(Context.CARRIER_CONFIG_SERVICE);
if (configManager == null) return null;
- final PersistableBundle carrierConfig = configManager.getConfig();
+ final PersistableBundle carrierConfig = configManager.getConfigForSubId(config.subId);
if (CarrierConfigManager.isConfigForIdentifiedCarrier(carrierConfig)) {
return carrierConfig;
@@ -334,9 +347,10 @@ public class EntitlementManager {
//
// TODO: find a better way to express this, or alter the checking process
// entirely so that this is more intuitive.
- private boolean carrierConfigAffirmsEntitlementCheckNotRequired() {
+ private boolean carrierConfigAffirmsEntitlementCheckNotRequired(
+ final TetheringConfiguration config) {
// Check carrier config for entitlement checks
- final PersistableBundle carrierConfig = getCarrierConfig();
+ final PersistableBundle carrierConfig = getCarrierConfig(config);
if (carrierConfig == null) return false;
// A CarrierConfigManager was found and it has a config.
@@ -348,17 +362,19 @@ public class EntitlementManager {
/**
* Run no UI tethering provisioning check.
* @param type tethering type from ConnectivityManager.TETHERING_{@code *}
+ * @param subId default data subscription ID.
*/
- protected void runSilentTetherProvisioning(int type) {
+ @VisibleForTesting
+ protected void runSilentTetherProvisioning(int type, int subId) {
if (DBG) mLog.i("runSilentTetherProvisioning: " + type);
// For silent provisioning, settings would stop tethering when entitlement fail.
- ResultReceiver receiver = buildProxyReceiver(type,
- false/* notifyFail */, null);
+ ResultReceiver receiver = buildProxyReceiver(type, false/* notifyFail */, null);
Intent intent = new Intent();
intent.putExtra(EXTRA_ADD_TETHER_TYPE, type);
intent.putExtra(EXTRA_RUN_PROVISION, true);
intent.putExtra(EXTRA_PROVISION_CALLBACK, receiver);
+ intent.putExtra(EXTRA_SUBID, subId);
intent.setComponent(TETHER_SERVICE);
final long ident = Binder.clearCallingIdentity();
try {
@@ -368,24 +384,25 @@ public class EntitlementManager {
}
}
+ private void runUiTetherProvisioning(int type, int subId) {
+ ResultReceiver receiver = buildProxyReceiver(type, true/* notifyFail */, null);
+ runUiTetherProvisioning(type, subId, receiver);
+ }
+
/**
* Run the UI-enabled tethering provisioning check.
* @param type tethering type from ConnectivityManager.TETHERING_{@code *}
+ * @param subId default data subscription ID.
+ * @param receiver to receive entitlement check result.
*/
@VisibleForTesting
- protected void runUiTetherProvisioning(int type) {
- ResultReceiver receiver = buildProxyReceiver(type,
- true/* notifyFail */, null);
- runUiTetherProvisioning(type, receiver);
- }
-
- @VisibleForTesting
- protected void runUiTetherProvisioning(int type, ResultReceiver receiver) {
+ protected void runUiTetherProvisioning(int type, int subId, ResultReceiver receiver) {
if (DBG) mLog.i("runUiTetherProvisioning: " + type);
Intent intent = new Intent(Settings.ACTION_TETHER_PROVISIONING);
intent.putExtra(EXTRA_ADD_TETHER_TYPE, type);
intent.putExtra(EXTRA_PROVISION_CALLBACK, receiver);
+ intent.putExtra(EXTRA_SUBID, subId);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
final long ident = Binder.clearCallingIdentity();
try {
@@ -396,9 +413,9 @@ public class EntitlementManager {
}
// Not needed to check if this don't run on the handler thread because it's private.
- private void scheduleProvisioningRechecks() {
+ private void scheduleProvisioningRechecks(final TetheringConfiguration config) {
if (mProvisioningRecheckAlarm == null) {
- final int period = mConfig.provisioningCheckPeriod;
+ final int period = config.provisioningCheckPeriod;
if (period <= 0) return;
Intent intent = new Intent(ACTION_PROVISIONING_ALARM);
@@ -421,9 +438,9 @@ public class EntitlementManager {
}
}
- private void evaluateCellularPermission() {
+ private void evaluateCellularPermission(final TetheringConfiguration config) {
final boolean oldPermitted = mCellularUpstreamPermitted;
- mCellularUpstreamPermitted = (!isTetherProvisioningRequired()
+ mCellularUpstreamPermitted = (!isTetherProvisioningRequired(config)
|| mCellularPermitted.indexOfValue(TETHER_ERROR_NO_ERROR) > -1);
if (DBG) {
@@ -438,7 +455,7 @@ public class EntitlementManager {
// Only schedule periodic re-check when tether is provisioned
// and the result is ok.
if (mCellularUpstreamPermitted && mCellularPermitted.size() > 0) {
- scheduleProvisioningRechecks();
+ scheduleProvisioningRechecks(config);
} else {
cancelTetherProvisioningRechecks();
}
@@ -457,7 +474,8 @@ public class EntitlementManager {
if (!mCurrentTethers.contains(type)) return;
mCellularPermitted.put(type, resultCode);
- evaluateCellularPermission();
+ final TetheringConfiguration config = mFetcher.fetchTetheringConfiguration();
+ evaluateCellularPermission(config);
}
/**
@@ -467,7 +485,8 @@ public class EntitlementManager {
protected void removeDownstreamMapping(int type) {
mLog.i("removeDownstreamMapping: " + type);
mCellularPermitted.delete(type);
- evaluateCellularPermission();
+ final TetheringConfiguration config = mFetcher.fetchTetheringConfiguration();
+ evaluateCellularPermission(config);
}
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@@ -475,7 +494,8 @@ public class EntitlementManager {
public void onReceive(Context context, Intent intent) {
if (ACTION_PROVISIONING_ALARM.equals(intent.getAction())) {
mLog.log("Received provisioning alarm");
- reevaluateSimCardProvisioning();
+ final TetheringConfiguration config = mFetcher.fetchTetheringConfiguration();
+ reevaluateSimCardProvisioning(config);
}
}
};
@@ -498,7 +518,8 @@ public class EntitlementManager {
handleNotifyUpstream(toBool(msg.arg1));
break;
case EVENT_MAYBE_RUN_PROVISIONING:
- handleMaybeRunProvisioning();
+ final TetheringConfiguration config = mFetcher.fetchTetheringConfiguration();
+ handleMaybeRunProvisioning(config);
break;
case EVENT_GET_ENTITLEMENT_VALUE:
handleGetLatestTetheringEntitlementValue(msg.arg1, (ResultReceiver) msg.obj,
@@ -636,7 +657,8 @@ public class EntitlementManager {
private void handleGetLatestTetheringEntitlementValue(int downstream, ResultReceiver receiver,
boolean showEntitlementUi) {
- if (!isTetherProvisioningRequired()) {
+ final TetheringConfiguration config = mFetcher.fetchTetheringConfiguration();
+ if (!isTetherProvisioningRequired(config)) {
receiver.send(TETHER_ERROR_NO_ERROR, null);
return;
}
@@ -647,7 +669,7 @@ public class EntitlementManager {
receiver.send(cacheValue, null);
} else {
ResultReceiver proxy = buildProxyReceiver(downstream, false/* notifyFail */, receiver);
- runUiTetherProvisioning(downstream, proxy);
+ runUiTetherProvisioning(downstream, config.subId, proxy);
}
}
}
diff --git a/telephony/java/android/telephony/SubscriptionInfo.java b/telephony/java/android/telephony/SubscriptionInfo.java
index 2ce3cafa3e1d..770f780372ad 100644
--- a/telephony/java/android/telephony/SubscriptionInfo.java
+++ b/telephony/java/android/telephony/SubscriptionInfo.java
@@ -39,6 +39,7 @@ import android.util.DisplayMetrics;
import android.util.Log;
import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
import java.util.Objects;
@@ -123,6 +124,16 @@ public class SubscriptionInfo implements Parcelable {
private String mMnc;
/**
+ * EHPLMNs associated with the subscription
+ */
+ private String[] mEhplmns;
+
+ /**
+ * HPLMNs associated with the subscription
+ */
+ private String[] mHplmns;
+
+ /**
* ISO Country code for the subscription's provider
*/
private String mCountryIso;
@@ -316,6 +327,14 @@ public class SubscriptionInfo implements Parcelable {
}
/**
+ * @hide
+ */
+ public void setAssociatedPlmns(String[] ehplmns, String[] hplmns) {
+ mEhplmns = ehplmns;
+ mHplmns = hplmns;
+ }
+
+ /**
* Creates and returns an icon {@code Bitmap} to represent this {@code SubscriptionInfo} in a
* user interface.
*
@@ -467,6 +486,20 @@ public class SubscriptionInfo implements Parcelable {
}
/**
+ * @hide
+ */
+ public List<String> getEhplmns() {
+ return mEhplmns == null ? Collections.emptyList() : Arrays.asList(mEhplmns);
+ }
+
+ /**
+ * @hide
+ */
+ public List<String> getHplmns() {
+ return mHplmns == null ? Collections.emptyList() : Arrays.asList(mHplmns);
+ }
+
+ /**
* @return the profile class of this subscription.
* @hide
*/
@@ -599,7 +632,7 @@ public class SubscriptionInfo implements Parcelable {
String mcc = source.readString();
String mnc = source.readString();
String countryIso = source.readString();
- Bitmap iconBitmap = Bitmap.CREATOR.createFromParcel(source);
+ Bitmap iconBitmap = source.readParcelable(Bitmap.class.getClassLoader());
boolean isEmbedded = source.readBoolean();
UiccAccessRule[] accessRules = source.createTypedArray(UiccAccessRule.CREATOR);
String cardString = source.readString();
@@ -610,11 +643,15 @@ public class SubscriptionInfo implements Parcelable {
int carrierid = source.readInt();
int profileClass = source.readInt();
int subType = source.readInt();
-
- return new SubscriptionInfo(id, iccId, simSlotIndex, displayName, carrierName,
- nameSource, iconTint, number, dataRoaming, iconBitmap, mcc, mnc, countryIso,
- isEmbedded, accessRules, cardString, cardId, isOpportunistic, groupUUID,
- isGroupDisabled, carrierid, profileClass, subType);
+ String[] ehplmns = source.readStringArray();
+ String[] hplmns = source.readStringArray();
+
+ SubscriptionInfo info = new SubscriptionInfo(id, iccId, simSlotIndex, displayName,
+ carrierName, nameSource, iconTint, number, dataRoaming, iconBitmap, mcc, mnc,
+ countryIso, isEmbedded, accessRules, cardString, cardId, isOpportunistic,
+ groupUUID, isGroupDisabled, carrierid, profileClass, subType);
+ info.setAssociatedPlmns(ehplmns, hplmns);
+ return info;
}
@Override
@@ -637,7 +674,7 @@ public class SubscriptionInfo implements Parcelable {
dest.writeString(mMcc);
dest.writeString(mMnc);
dest.writeString(mCountryIso);
- mIconBitmap.writeToParcel(dest, flags);
+ dest.writeParcelable(mIconBitmap, flags);
dest.writeBoolean(mIsEmbedded);
dest.writeTypedArray(mAccessRules, flags);
dest.writeString(mCardString);
@@ -648,6 +685,8 @@ public class SubscriptionInfo implements Parcelable {
dest.writeInt(mCarrierId);
dest.writeInt(mProfileClass);
dest.writeInt(mSubscriptionType);
+ dest.writeStringArray(mEhplmns);
+ dest.writeStringArray(mHplmns);
}
@Override
@@ -685,6 +724,8 @@ public class SubscriptionInfo implements Parcelable {
+ " isOpportunistic " + mIsOpportunistic + " mGroupUUID=" + mGroupUUID
+ " mIsGroupDisabled=" + mIsGroupDisabled
+ " profileClass=" + mProfileClass
+ + " ehplmns = " + Arrays.toString(mEhplmns)
+ + " hplmns = " + Arrays.toString(mHplmns)
+ " subscriptionType=" + mSubscriptionType + "}";
}
@@ -728,6 +769,8 @@ public class SubscriptionInfo implements Parcelable {
&& TextUtils.equals(mDisplayName, toCompare.mDisplayName)
&& TextUtils.equals(mCarrierName, toCompare.mCarrierName)
&& Arrays.equals(mAccessRules, toCompare.mAccessRules)
- && mProfileClass == toCompare.mProfileClass;
+ && mProfileClass == toCompare.mProfileClass
+ && Arrays.equals(mEhplmns, toCompare.mEhplmns)
+ && Arrays.equals(mHplmns, toCompare.mHplmns);
}
}
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index b0fa9d526b16..586c815ae7b5 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -458,6 +458,18 @@ public class SubscriptionManager {
public static final String CARRIER_ID = "carrier_id";
/**
+ * @hide A comma-separated list of EHPLMNs associated with the subscription
+ * <P>Type: TEXT (String)</P>
+ */
+ public static final String EHPLMNS = "ehplmns";
+
+ /**
+ * @hide A comma-separated list of HPLMNs associated with the subscription
+ * <P>Type: TEXT (String)</P>
+ */
+ public static final String HPLMNS = "hplmns";
+
+ /**
* TelephonyProvider column name for the MCC associated with a SIM, stored as a string.
* <P>Type: TEXT (String)</P>
* @hide
@@ -2733,6 +2745,8 @@ public class SubscriptionManager {
*
* @throws SecurityException if the caller doesn't meet the requirements
* outlined above.
+ * @throws IllegalArgumentException if any of the subscriptions in the list doesn't exist.
+ * @throws IllegalStateException if Telephony service is in bad state.
*
* @param subIdList list of subId that will be in the same group
* @return groupUUID a UUID assigned to the subscription group.
@@ -2781,6 +2795,7 @@ public class SubscriptionManager {
* outlined above.
* @throws IllegalArgumentException if the some subscriptions in the list doesn't exist,
* or the groupUuid doesn't exist.
+ * @throws IllegalStateException if Telephony service is in bad state.
*
* @param subIdList list of subId that need adding into the group
* @param groupUuid the groupUuid the subscriptions are being added to.
@@ -2833,6 +2848,7 @@ public class SubscriptionManager {
* outlined above.
* @throws IllegalArgumentException if the some subscriptions in the list doesn't belong
* the specified group.
+ * @throws IllegalStateException if Telephony service is in bad state.
*
* @param subIdList list of subId that need removing from their groups.
*
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 12acf9d09830..e1425b975525 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -10321,10 +10321,10 @@ public class TelephonyManager {
* <p>Requires permission {@link android.Manifest.permission#READ_PHONE_STATE} or the calling
* app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
- * @return Map including the key as the active subscription ID (Note: if there is no active
+ * @return Map including the keys as the active subscription IDs (Note: if there is no active
* subscription, the key is {@link SubscriptionManager#getDefaultSubscriptionId}) and the value
- * as the list of {@link EmergencyNumber}; null if this information is not available; or throw
- * a SecurityException if the caller does not have the permission.
+ * as the list of {@link EmergencyNumber}; empty Map if this information is not available;
+ * or throw a SecurityException if the caller does not have the permission.
*/
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
@NonNull
@@ -10374,10 +10374,10 @@ public class TelephonyManager {
* <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_MIEC} </li>
* <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_AIEC} </li>
* </ol>
- * @return Map including the key as the active subscription ID (Note: if there is no active
+ * @return Map including the keys as the active subscription IDs (Note: if there is no active
* subscription, the key is {@link SubscriptionManager#getDefaultSubscriptionId}) and the value
- * as the list of {@link EmergencyNumber}; null if this information is not available; or throw
- * a SecurityException if the caller does not have the permission.
+ * as the list of {@link EmergencyNumber}; empty Map if this information is not available;
+ * or throw a SecurityException if the caller does not have the permission.
*/
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
@NonNull
diff --git a/telephony/java/android/telephony/ims/ImsMmTelManager.java b/telephony/java/android/telephony/ims/ImsMmTelManager.java
index e9aede7336f0..be5872387d7b 100644
--- a/telephony/java/android/telephony/ims/ImsMmTelManager.java
+++ b/telephony/java/android/telephony/ims/ImsMmTelManager.java
@@ -781,8 +781,13 @@ public class ImsMmTelManager {
}
/**
- * Change the user's setting for RTT capability of this device.
- * @param isEnabled if true RTT will be enabled during calls.
+ * Sets the capability of RTT for IMS calls placed on this subscription.
+ *
+ * Note: This does not affect the value of
+ * {@link android.provider.Settings.Secure#RTT_CALLING_MODE}, which is the global user setting
+ * for RTT. That value is enabled/disabled separately by the user through the Accessibility
+ * settings.
+ * @param isEnabled if true RTT should be enabled during calls made on this subscription.
*/
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
public void setRttCapabilitySetting(boolean isEnabled) {
diff --git a/telephony/java/android/telephony/ims/compat/feature/ImsFeature.java b/telephony/java/android/telephony/ims/compat/feature/ImsFeature.java
index e8fcac19f675..de4f17466a47 100644
--- a/telephony/java/android/telephony/ims/compat/feature/ImsFeature.java
+++ b/telephony/java/android/telephony/ims/compat/feature/ImsFeature.java
@@ -19,7 +19,6 @@ package android.telephony.ims.compat.feature;
import android.annotation.IntDef;
import android.annotation.UnsupportedAppUsage;
import android.content.Context;
-import android.content.Intent;
import android.os.IInterface;
import android.os.RemoteException;
import android.telephony.SubscriptionManager;
@@ -42,32 +41,6 @@ public abstract class ImsFeature {
private static final String LOG_TAG = "ImsFeature";
- /**
- * Action to broadcast when ImsService is up.
- * Internal use only.
- * Only defined here separately compatibility purposes with the old ImsService.
- * @hide
- */
- public static final String ACTION_IMS_SERVICE_UP =
- "com.android.ims.IMS_SERVICE_UP";
-
- /**
- * Action to broadcast when ImsService is down.
- * Internal use only.
- * Only defined here separately for compatibility purposes with the old ImsService.
- * @hide
- */
- public static final String ACTION_IMS_SERVICE_DOWN =
- "com.android.ims.IMS_SERVICE_DOWN";
-
- /**
- * Part of the ACTION_IMS_SERVICE_UP or _DOWN intents.
- * A long value; the phone ID corresponding to the IMS service coming up or down.
- * Only defined here separately for compatibility purposes with the old ImsService.
- * @hide
- */
- public static final String EXTRA_PHONE_ID = "android:phone_id";
-
// Invalid feature value
public static final int INVALID = -1;
// ImsFeatures that are defined in the Manifests. Ensure that these values match the previously
@@ -162,30 +135,6 @@ public abstract class ImsFeature {
}
}
}
- sendImsServiceIntent(state);
- }
-
- /**
- * Provide backwards compatibility using deprecated service UP/DOWN intents.
- */
- private void sendImsServiceIntent(@ImsState int state) {
- if(mContext == null || mSlotId == SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
- return;
- }
- Intent intent;
- switch (state) {
- case ImsFeature.STATE_NOT_AVAILABLE:
- case ImsFeature.STATE_INITIALIZING:
- intent = new Intent(ACTION_IMS_SERVICE_DOWN);
- break;
- case ImsFeature.STATE_READY:
- intent = new Intent(ACTION_IMS_SERVICE_UP);
- break;
- default:
- intent = new Intent(ACTION_IMS_SERVICE_DOWN);
- }
- intent.putExtra(EXTRA_PHONE_ID, mSlotId);
- mContext.sendBroadcast(intent);
}
/**
diff --git a/telephony/java/android/telephony/ims/feature/ImsFeature.java b/telephony/java/android/telephony/ims/feature/ImsFeature.java
index 5e3f3983b0a1..74af6bf6fe6e 100644
--- a/telephony/java/android/telephony/ims/feature/ImsFeature.java
+++ b/telephony/java/android/telephony/ims/feature/ImsFeature.java
@@ -20,7 +20,6 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.content.Context;
-import android.content.Intent;
import android.os.IInterface;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
@@ -395,30 +394,6 @@ public abstract class ImsFeature {
}
}
}
- sendImsServiceIntent(state);
- }
-
- /**
- * Provide backwards compatibility using deprecated service UP/DOWN intents.
- */
- private void sendImsServiceIntent(@ImsState int state) {
- if (mContext == null || mSlotId == SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
- return;
- }
- Intent intent;
- switch (state) {
- case ImsFeature.STATE_UNAVAILABLE:
- case ImsFeature.STATE_INITIALIZING:
- intent = new Intent(ACTION_IMS_SERVICE_DOWN);
- break;
- case ImsFeature.STATE_READY:
- intent = new Intent(ACTION_IMS_SERVICE_UP);
- break;
- default:
- intent = new Intent(ACTION_IMS_SERVICE_DOWN);
- }
- intent.putExtra(EXTRA_PHONE_ID, mSlotId);
- mContext.sendBroadcast(intent);
}
/**
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index ed93da16989c..b47b59b28e2a 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -4292,8 +4292,9 @@ public class ConnectivityServiceTest {
}
// Check that there is no port leaked after all keepalives and sockets are closed.
- assertFalse(isUdpPortInUse(srcPort));
- assertFalse(isUdpPortInUse(srcPort2));
+ // TODO: enable this check after ensuring a valid free port. See b/129512753#comment7.
+ // assertFalse(isUdpPortInUse(srcPort));
+ // assertFalse(isUdpPortInUse(srcPort2));
mWiFiNetworkAgent.disconnect();
waitFor(mWiFiNetworkAgent.getDisconnectedCV());
@@ -4421,7 +4422,8 @@ public class ConnectivityServiceTest {
assertEquals(anyIPv4, sa.getAddress());
testPfd.close();
- assertFalse(isUdpPortInUse(srcPort));
+ // TODO: enable this check after ensuring a valid free port. See b/129512753#comment7.
+ // assertFalse(isUdpPortInUse(srcPort));
mWiFiNetworkAgent.disconnect();
waitFor(mWiFiNetworkAgent.getDisconnectedCV());
diff --git a/tests/net/java/com/android/server/connectivity/tethering/EntitlementManagerTest.java b/tests/net/java/com/android/server/connectivity/tethering/EntitlementManagerTest.java
index d28ab708f051..2b2e8a72ab04 100644
--- a/tests/net/java/com/android/server/connectivity/tethering/EntitlementManagerTest.java
+++ b/tests/net/java/com/android/server/connectivity/tethering/EntitlementManagerTest.java
@@ -29,6 +29,7 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Matchers.anyBoolean;
+import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.times;
@@ -93,6 +94,7 @@ public final class EntitlementManagerTest {
private TestStateMachine mSM;
private WrappedEntitlementManager mEnMgr;
+ private TetheringConfiguration mConfig;
private class MockContext extends BroadcastInterceptingContext {
MockContext(Context base) {
@@ -127,13 +129,13 @@ public final class EntitlementManagerTest {
}
@Override
- protected void runUiTetherProvisioning(int type, ResultReceiver receiver) {
+ protected void runUiTetherProvisioning(int type, int subId, ResultReceiver receiver) {
uiProvisionCount++;
receiver.send(fakeEntitlementResult, null);
}
@Override
- protected void runSilentTetherProvisioning(int type) {
+ protected void runSilentTetherProvisioning(int type, int subId) {
silentProvisionCount++;
addDownstreamMapping(type, fakeEntitlementResult);
}
@@ -162,8 +164,10 @@ public final class EntitlementManagerTest {
mEnMgr = new WrappedEntitlementManager(mMockContext, mSM, mLog, EVENT_EM_UPDATE,
mSystemProperties);
mEnMgr.setOnUiEntitlementFailedListener(mEntitlementFailedListener);
- mEnMgr.updateConfiguration(
- new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID));
+ mConfig = new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
+ mEnMgr.setTetheringConfigurationFetcher(() -> {
+ return mConfig;
+ });
}
@After
@@ -186,17 +190,16 @@ public final class EntitlementManagerTest {
// Act like the CarrierConfigManager is present and ready unless told otherwise.
when(mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE))
.thenReturn(mCarrierConfigManager);
- when(mCarrierConfigManager.getConfig()).thenReturn(mCarrierConfig);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(mCarrierConfig);
mCarrierConfig.putBoolean(CarrierConfigManager.KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL, true);
mCarrierConfig.putBoolean(CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL, true);
+ mConfig = new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
}
@Test
public void canRequireProvisioning() {
setupForRequiredProvisioning();
- mEnMgr.updateConfiguration(
- new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID));
- assertTrue(mEnMgr.isTetherProvisioningRequired());
+ assertTrue(mEnMgr.isTetherProvisioningRequired(mConfig));
}
@Test
@@ -204,31 +207,27 @@ public final class EntitlementManagerTest {
setupForRequiredProvisioning();
when(mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE))
.thenReturn(null);
- mEnMgr.updateConfiguration(
- new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID));
+ mConfig = new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
// Couldn't get the CarrierConfigManager, but still had a declared provisioning app.
// Therefore provisioning still be required.
- assertTrue(mEnMgr.isTetherProvisioningRequired());
+ assertTrue(mEnMgr.isTetherProvisioningRequired(mConfig));
}
@Test
public void toleratesCarrierConfigMissing() {
setupForRequiredProvisioning();
when(mCarrierConfigManager.getConfig()).thenReturn(null);
- mEnMgr.updateConfiguration(
- new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID));
+ mConfig = new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
// We still have a provisioning app configured, so still require provisioning.
- assertTrue(mEnMgr.isTetherProvisioningRequired());
+ assertTrue(mEnMgr.isTetherProvisioningRequired(mConfig));
}
@Test
public void toleratesCarrierConfigNotLoaded() {
setupForRequiredProvisioning();
mCarrierConfig.putBoolean(CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL, false);
- mEnMgr.updateConfiguration(
- new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID));
// We still have a provisioning app configured, so still require provisioning.
- assertTrue(mEnMgr.isTetherProvisioningRequired());
+ assertTrue(mEnMgr.isTetherProvisioningRequired(mConfig));
}
@Test
@@ -236,14 +235,12 @@ public final class EntitlementManagerTest {
setupForRequiredProvisioning();
when(mResources.getStringArray(R.array.config_mobile_hotspot_provision_app))
.thenReturn(null);
- mEnMgr.updateConfiguration(
- new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID));
- assertFalse(mEnMgr.isTetherProvisioningRequired());
+ mConfig = new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
+ assertFalse(mEnMgr.isTetherProvisioningRequired(mConfig));
when(mResources.getStringArray(R.array.config_mobile_hotspot_provision_app))
.thenReturn(new String[] {"malformedApp"});
- mEnMgr.updateConfiguration(
- new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID));
- assertFalse(mEnMgr.isTetherProvisioningRequired());
+ mConfig = new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
+ assertFalse(mEnMgr.isTetherProvisioningRequired(mConfig));
}
@Test
@@ -265,8 +262,6 @@ public final class EntitlementManagerTest {
mEnMgr.reset();
setupForRequiredProvisioning();
- mEnMgr.updateConfiguration(new TetheringConfiguration(mMockContext, mLog,
- INVALID_SUBSCRIPTION_ID));
// 2. No cache value and don't need to run entitlement check.
receiver = new ResultReceiver(null) {
@Override
@@ -361,8 +356,6 @@ public final class EntitlementManagerTest {
public void verifyPermissionResult() {
setupForRequiredProvisioning();
mEnMgr.notifyUpstream(true);
- mEnMgr.updateConfiguration(new TetheringConfiguration(mMockContext, mLog,
- INVALID_SUBSCRIPTION_ID));
mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISION_FAILED;
mEnMgr.startProvisioningIfNeeded(TETHERING_WIFI, true);
mLooper.dispatchAll();
@@ -379,8 +372,6 @@ public final class EntitlementManagerTest {
public void verifyPermissionIfAllNotApproved() {
setupForRequiredProvisioning();
mEnMgr.notifyUpstream(true);
- mEnMgr.updateConfiguration(new TetheringConfiguration(mMockContext, mLog,
- INVALID_SUBSCRIPTION_ID));
mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISION_FAILED;
mEnMgr.startProvisioningIfNeeded(TETHERING_WIFI, true);
mLooper.dispatchAll();
@@ -399,8 +390,6 @@ public final class EntitlementManagerTest {
public void verifyPermissionIfAnyApproved() {
setupForRequiredProvisioning();
mEnMgr.notifyUpstream(true);
- mEnMgr.updateConfiguration(new TetheringConfiguration(mMockContext, mLog,
- INVALID_SUBSCRIPTION_ID));
mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR;
mEnMgr.startProvisioningIfNeeded(TETHERING_WIFI, true);
mLooper.dispatchAll();
@@ -419,8 +408,6 @@ public final class EntitlementManagerTest {
@Test
public void testRunTetherProvisioning() {
setupForRequiredProvisioning();
- mEnMgr.updateConfiguration(new TetheringConfiguration(mMockContext, mLog,
- INVALID_SUBSCRIPTION_ID));
// 1. start ui provisioning, upstream is mobile
mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR;
mEnMgr.notifyUpstream(true);
@@ -458,7 +445,7 @@ public final class EntitlementManagerTest {
// 5. tear down mobile, then switch SIM
mEnMgr.notifyUpstream(false);
mLooper.dispatchAll();
- mEnMgr.reevaluateSimCardProvisioning();
+ mEnMgr.reevaluateSimCardProvisioning(mConfig);
assertEquals(0, mEnMgr.uiProvisionCount);
assertEquals(0, mEnMgr.silentProvisionCount);
mEnMgr.reset();
@@ -474,8 +461,6 @@ public final class EntitlementManagerTest {
@Test
public void testCallStopTetheringWhenUiProvisioningFail() {
setupForRequiredProvisioning();
- mEnMgr.updateConfiguration(new TetheringConfiguration(mMockContext, mLog,
- INVALID_SUBSCRIPTION_ID));
verify(mEntitlementFailedListener, times(0)).onUiEntitlementFailed(TETHERING_WIFI);
mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISION_FAILED;
mEnMgr.notifyUpstream(true);
@@ -486,7 +471,6 @@ public final class EntitlementManagerTest {
verify(mEntitlementFailedListener, times(1)).onUiEntitlementFailed(TETHERING_WIFI);
}
-
public class TestStateMachine extends StateMachine {
public final ArrayList<Message> messages = new ArrayList<>();
private final State
diff --git a/tools/preload-check/Android.bp b/tools/preload-check/Android.bp
index c84567b704a6..2488341bfd97 100644
--- a/tools/preload-check/Android.bp
+++ b/tools/preload-check/Android.bp
@@ -15,6 +15,7 @@
java_test_host {
name: "PreloadCheck",
srcs: ["src/**/*.java"],
+ java_resources: [":preloaded-classes-blacklist"],
libs: ["tradefed"],
test_suites: ["general-tests"],
required: ["preload-check-device"],
diff --git a/tools/preload-check/src/com/android/preload/check/PreloadCheck.java b/tools/preload-check/src/com/android/preload/check/PreloadCheck.java
index dbdecdbecd12..1fde40252939 100644
--- a/tools/preload-check/src/com/android/preload/check/PreloadCheck.java
+++ b/tools/preload-check/src/com/android/preload/check/PreloadCheck.java
@@ -25,6 +25,9 @@ import com.android.tradefed.testtype.IDeviceTest;
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+
@RunWith(DeviceJUnit4ClassRunner.class)
public class PreloadCheck implements IDeviceTest {
private ITestDevice mTestDevice;
@@ -65,6 +68,35 @@ public class PreloadCheck implements IDeviceTest {
run("com.android.preload.check.Initialized", "android.animation.Animator");
}
+ /**
+ * Test the classes mentioned in the embedded preloaded-classes blacklist.
+ */
+ @Test
+ public void testBlackList() throws Exception {
+ StringBuilder sb = new StringBuilder();
+ try (BufferedReader br = new BufferedReader(new InputStreamReader(getClass()
+ .getResourceAsStream("/preloaded-classes-blacklist")))) {
+ String s;
+ while ((s = br.readLine()) != null) {
+ s = s.trim();
+ if (s.startsWith("#") || s.isEmpty()) {
+ continue;
+ }
+ try {
+ run("com.android.preload.check.NotInitialized", s);
+ } catch (Throwable t) {
+ if (sb.length() > 0) {
+ sb.append('\n');
+ }
+ sb.append(t.getMessage());
+ }
+ }
+ }
+ if (sb.length() > 0) {
+ throw new RuntimeException(sb.toString());
+ }
+ }
+
private void run(String cmd, String... args) throws Exception {
StringBuilder sb = new StringBuilder();
sb.append("app_process ")
@@ -72,9 +104,16 @@ public class PreloadCheck implements IDeviceTest {
.append(" /system/bin ")
.append(cmd);
for (String arg : args) {
- sb.append(' ').append(arg);
+ sb.append(' ').append(escape(arg));
}
String res = mTestDevice.executeShellCommand(sb.toString());
assertEquals(sb.toString(), "OK", res.trim());
}
+
+ private static String escape(String input) {
+ if (input.indexOf('$') == -1) {
+ return input;
+ }
+ return input.replace("$", "\\$");
+ }
}