Merge "Fix up NetworkCapabilities' toString"
diff --git a/api/system-current.txt b/api/system-current.txt
index a289a58..d3f7260 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -3532,6 +3532,7 @@
method public static boolean putString(android.content.ContentResolver, java.lang.String, java.lang.String, java.lang.String, boolean);
method public static void resetToDefaults(android.content.ContentResolver, java.lang.String);
field public static final java.lang.String DEFAULT_SM_DP_PLUS = "default_sm_dp_plus";
+ field public static final java.lang.String EUICC_PROVISIONED = "euicc_provisioned";
field public static final java.lang.String OTA_DISABLE_AUTOMATIC_UPDATE = "ota_disable_automatic_update";
field public static final java.lang.String THEATER_MODE_ON = "theater_mode_on";
field public static final java.lang.String WEBVIEW_MULTIPROCESS = "webview_multiprocess";
@@ -5103,7 +5104,6 @@
method public void setUiTtyMode(int, android.os.Message);
method public int shouldProcessCall(java.lang.String[]);
field public static final int PROCESS_CALL_CSFB = 1; // 0x1
- field public static final int PROCESS_CALL_EMERGENCY_CSFB = 2; // 0x2
field public static final int PROCESS_CALL_IMS = 0; // 0x0
}
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index 6526123..78a2d4a6 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -29,11 +29,11 @@
#include <signal.h>
#include <time.h>
+#include <cutils/atomic.h>
#include <cutils/properties.h>
#include <androidfw/AssetManager.h>
#include <binder/IPCThreadState.h>
-#include <utils/Atomic.h>
#include <utils/Errors.h>
#include <utils/Log.h>
#include <utils/SystemClock.h>
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index a3e3354..0e74d9e 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -3304,7 +3304,7 @@
&& (perm.info.protectionLevel&PermissionInfo.PROTECTION_FLAG_RUNTIME_ONLY) == 0
&& (perm.info.protectionLevel&PermissionInfo.PROTECTION_MASK_BASE) !=
PermissionInfo.PROTECTION_SIGNATURE) {
- outError[0] = "<permission> protectionLevel specifies a non-instnat flag but is "
+ outError[0] = "<permission> protectionLevel specifies a non-instant flag but is "
+ "not based on signature type";
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
return false;
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index c4dfafa..d8e1741 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -116,6 +116,7 @@
NET_CAPABILITY_FOREGROUND,
NET_CAPABILITY_NOT_CONGESTED,
NET_CAPABILITY_NOT_SUSPENDED,
+ NET_CAPABILITY_OEM_PAID,
})
public @interface NetCapability { }
@@ -263,8 +264,15 @@
*/
public static final int NET_CAPABILITY_NOT_SUSPENDED = 21;
+ /**
+ * Indicates that traffic that goes through this network is paid by oem. For example,
+ * this network can be used by system apps to upload telemetry data.
+ * @hide
+ */
+ public static final int NET_CAPABILITY_OEM_PAID = 22;
+
private static final int MIN_NET_CAPABILITY = NET_CAPABILITY_MMS;
- private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_NOT_SUSPENDED;
+ private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_OEM_PAID;
/**
* Network capabilities that are expected to be mutable, i.e., can change while a particular
@@ -312,7 +320,8 @@
(1 << NET_CAPABILITY_IA) |
(1 << NET_CAPABILITY_IMS) |
(1 << NET_CAPABILITY_RCS) |
- (1 << NET_CAPABILITY_XCAP);
+ (1 << NET_CAPABILITY_XCAP) |
+ (1 << NET_CAPABILITY_OEM_PAID);
/**
* Capabilities that suggest that a network is unrestricted.
@@ -1323,6 +1332,7 @@
case NET_CAPABILITY_FOREGROUND: return "FOREGROUND";
case NET_CAPABILITY_NOT_CONGESTED: return "NOT_CONGESTED";
case NET_CAPABILITY_NOT_SUSPENDED: return "NOT_SUSPENDED";
+ case NET_CAPABILITY_OEM_PAID: return "OEM_PAID";
default: return Integer.toString(capability);
}
}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 36dcca6..ca3f5e9 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -7863,6 +7863,7 @@
* (0 = false, 1 = true)
* @hide
*/
+ @SystemApi
public static final String EUICC_PROVISIONED = "euicc_provisioned";
/**
diff --git a/core/java/android/webkit/WebViewZygote.java b/core/java/android/webkit/WebViewZygote.java
index d2923c4..ca3a227 100644
--- a/core/java/android/webkit/WebViewZygote.java
+++ b/core/java/android/webkit/WebViewZygote.java
@@ -93,13 +93,11 @@
synchronized (sLock) {
sMultiprocessEnabled = enabled;
- // When toggling between multi-process being on/off, start or stop the
- // zygote. If it is enabled and the zygote is not yet started, launch it.
- // Otherwise, kill it. The name may be null if the package information has
- // not yet been resolved.
- if (enabled) {
- connectToZygoteIfNeededLocked();
- } else {
+ // When multi-process is disabled, kill the zygote. When it is enabled,
+ // the zygote is not explicitly started here to avoid waiting on the
+ // zygote launch at boot. Instead, the zygote will be started when it is
+ // first needed in getProcess().
+ if (!enabled) {
stopZygoteLocked();
}
}
diff --git a/core/jni/android_os_Parcel.cpp b/core/jni/android_os_Parcel.cpp
index f0ac79a..a5a3986 100644
--- a/core/jni/android_os_Parcel.cpp
+++ b/core/jni/android_os_Parcel.cpp
@@ -28,9 +28,9 @@
#include <sys/types.h>
#include <unistd.h>
-#include <utils/Atomic.h>
#include <binder/IInterface.h>
#include <binder/IPCThreadState.h>
+#include <cutils/atomic.h>
#include <utils/Log.h>
#include <utils/SystemClock.h>
#include <utils/List.h>
diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp
index 93abc63..a040940 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -34,8 +34,8 @@
#include <binder/IPCThreadState.h>
#include <binder/Parcel.h>
#include <binder/ProcessState.h>
+#include <cutils/atomic.h>
#include <log/log.h>
-#include <utils/Atomic.h>
#include <utils/KeyedVector.h>
#include <utils/List.h>
#include <utils/Log.h>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 0a36ba7..dc14b23 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3462,6 +3462,13 @@
<string name="tethered_notification_title">Tethering or hotspot active</string>
<string name="tethered_notification_message">Tap to set up.</string>
+ <!-- Strings for tether disabling notification -->
+ <!-- This notification is shown when tethering has been disabled on a user's device.
+ The device is managed by the user's employer. Tethering can't be turned on unless the
+ IT administrator allows it. The noun "admin" is another reference for "IT administrator." -->
+ <string name="disable_tether_notification_title">Tethering is disabled</string>
+ <string name="disable_tether_notification_message">Contact your admin for details</string>
+
<!-- Strings for possible PreferenceActivity Back/Next buttons -->
<string name="back_button_label">Back</string>
<string name="next_button_label">Next</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 6396c4c..ad5af95 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1967,6 +1967,8 @@
<java-symbol type="string" name="smv_process" />
<java-symbol type="string" name="tethered_notification_message" />
<java-symbol type="string" name="tethered_notification_title" />
+ <java-symbol type="string" name="disable_tether_notification_message" />
+ <java-symbol type="string" name="disable_tether_notification_title" />
<java-symbol type="string" name="adb_debugging_notification_channel_tv" />
<java-symbol type="string" name="usb_accessory_notification_title" />
<java-symbol type="string" name="usb_mtp_notification_title" />
diff --git a/libs/androidfw/Asset.cpp b/libs/androidfw/Asset.cpp
index 247458d..c512a6b 100644
--- a/libs/androidfw/Asset.cpp
+++ b/libs/androidfw/Asset.cpp
@@ -26,7 +26,7 @@
#include <androidfw/Util.h>
#include <androidfw/ZipFileRO.h>
#include <androidfw/ZipUtils.h>
-#include <utils/Atomic.h>
+#include <cutils/atomic.h>
#include <utils/FileMap.h>
#include <utils/Log.h>
#include <utils/threads.h>
diff --git a/libs/androidfw/AssetManager.cpp b/libs/androidfw/AssetManager.cpp
index 5603508..b4ccae7 100644
--- a/libs/androidfw/AssetManager.cpp
+++ b/libs/androidfw/AssetManager.cpp
@@ -28,7 +28,7 @@
#include <androidfw/misc.h>
#include <androidfw/ResourceTypes.h>
#include <androidfw/ZipFileRO.h>
-#include <utils/Atomic.h>
+#include <cutils/atomic.h>
#include <utils/Log.h>
#include <utils/String8.h>
#include <utils/String8.h>
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index 7a0ef2b..b184d12 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -32,7 +32,7 @@
#include <androidfw/ByteBucketArray.h>
#include <androidfw/ResourceTypes.h>
#include <androidfw/TypeWrappers.h>
-#include <utils/Atomic.h>
+#include <cutils/atomic.h>
#include <utils/ByteOrder.h>
#include <utils/Debug.h>
#include <utils/Log.h>
diff --git a/native/android/storage_manager.cpp b/native/android/storage_manager.cpp
index 137b72c..bf15b8d 100644
--- a/native/android/storage_manager.cpp
+++ b/native/android/storage_manager.cpp
@@ -21,7 +21,7 @@
#include <binder/Binder.h>
#include <binder/IServiceManager.h>
-#include <utils/Atomic.h>
+#include <cutils/atomic.h>
#include <utils/Log.h>
#include <utils/RefBase.h>
#include <utils/String8.h>
diff --git a/services/autofill/java/com/android/server/autofill/RemoteFillService.java b/services/autofill/java/com/android/server/autofill/RemoteFillService.java
index af55807..93df507 100644
--- a/services/autofill/java/com/android/server/autofill/RemoteFillService.java
+++ b/services/autofill/java/com/android/server/autofill/RemoteFillService.java
@@ -342,7 +342,8 @@
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
if (mDestroyed || !mBinding) {
- mContext.unbindService(mServiceConnection);
+ // This is abnormal. Unbinding the connection has been requested already.
+ Slog.wtf(LOG_TAG, "onServiceConnected was dispatched after unbindService.");
return;
}
mBinding = false;
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 8b5176e..e202618 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -37,6 +37,7 @@
import android.telephony.DisconnectCause;
import android.telephony.LocationAccessPolicy;
import android.telephony.PhoneStateListener;
+import android.telephony.PhysicalChannelConfig;
import android.telephony.PreciseCallState;
import android.telephony.PreciseDataConnectionState;
import android.telephony.PreciseDisconnectCause;
@@ -179,6 +180,8 @@
private ArrayList<List<CellInfo>> mCellInfo = null;
+ private ArrayList<List<PhysicalChannelConfig>> mPhysicalChannelConfigs;
+
private VoLteServiceState mVoLteServiceState = new VoLteServiceState();
private int mDefaultSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
@@ -335,6 +338,7 @@
mDataConnectionLinkProperties = new LinkProperties[numPhones];
mDataConnectionNetworkCapabilities = new NetworkCapabilities[numPhones];
mCellInfo = new ArrayList<List<CellInfo>>();
+ mPhysicalChannelConfigs = new ArrayList<List<PhysicalChannelConfig>>();
for (int i = 0; i < numPhones; i++) {
mCallState[i] = TelephonyManager.CALL_STATE_IDLE;
mDataActivity[i] = TelephonyManager.DATA_ACTIVITY_NONE;
@@ -349,6 +353,7 @@
mCallForwarding[i] = false;
mCellLocation[i] = new Bundle();
mCellInfo.add(i, null);
+ mPhysicalChannelConfigs.add(i, null);
mConnectedApns[i] = new ArrayList<String>();
}
@@ -659,6 +664,14 @@
remove(r.binder);
}
}
+ if ((events & PhoneStateListener.LISTEN_PHYSICAL_CHANNEL_CONFIGURATION) != 0) {
+ try {
+ r.callback.onPhysicalChannelConfigurationChanged(
+ mPhysicalChannelConfigs.get(phoneId));
+ } catch (RemoteException ex) {
+ remove(r.binder);
+ }
+ }
}
}
} else {
@@ -1020,6 +1033,45 @@
}
}
+ public void notifyPhysicalChannelConfiguration(List<PhysicalChannelConfig> configs) {
+ notifyPhysicalChannelConfigurationForSubscriber(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
+ configs);
+ }
+
+ public void notifyPhysicalChannelConfigurationForSubscriber(int subId,
+ List<PhysicalChannelConfig> configs) {
+ if (!checkNotifyPermission("notifyPhysicalChannelConfiguration()")) {
+ return;
+ }
+
+ if (VDBG) {
+ log("notifyPhysicalChannelConfiguration: subId=" + subId + " configs=" + configs);
+ }
+
+ synchronized (mRecords) {
+ int phoneId = SubscriptionManager.getPhoneId(subId);
+ if (validatePhoneId(phoneId)) {
+ mPhysicalChannelConfigs.set(phoneId, configs);
+ for (Record r : mRecords) {
+ if (r.matchPhoneStateListenerEvent(
+ PhoneStateListener.LISTEN_PHYSICAL_CHANNEL_CONFIGURATION)
+ && idMatch(r.subId, subId, phoneId)) {
+ try {
+ if (DBG_LOC) {
+ log("notifyPhysicalChannelConfiguration: mPhysicalChannelConfigs="
+ + configs + " r=" + r);
+ }
+ r.callback.onPhysicalChannelConfigurationChanged(configs);
+ } catch (RemoteException ex) {
+ mRemoveList.add(r.binder);
+ }
+ }
+ }
+ }
+ handleRemoveListLocked();
+ }
+ }
+
@Override
public void notifyMessageWaitingChangedForPhoneId(int phoneId, int subId, boolean mwi) {
if (!checkNotifyPermission("notifyMessageWaitingChanged()")) {
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 503dfe9..cb96bac 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -1494,17 +1494,6 @@
if (adjustVolume && (direction != AudioManager.ADJUST_SAME)) {
mAudioHandler.removeMessages(MSG_UNMUTE_STREAM);
- // Check if volume update should be send to AVRCP
- if (streamTypeAlias == AudioSystem.STREAM_MUSIC &&
- (device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 &&
- (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) == 0) {
- synchronized (mA2dpAvrcpLock) {
- if (mA2dp != null && mAvrcpAbsVolSupported) {
- mA2dp.adjustAvrcpAbsoluteVolume(direction);
- }
- }
- }
-
if (isMuteAdjust) {
boolean state;
if (direction == AudioManager.ADJUST_TOGGLE_MUTE) {
@@ -1553,8 +1542,20 @@
0);
}
- // Check if volume update should be sent to Hdmi system audio.
int newIndex = mStreamStates[streamType].getIndex(device);
+
+ // Check if volume update should be send to AVRCP
+ if (streamTypeAlias == AudioSystem.STREAM_MUSIC &&
+ (device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 &&
+ (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) == 0) {
+ synchronized (mA2dpAvrcpLock) {
+ if (mA2dp != null && mAvrcpAbsVolSupported) {
+ mA2dp.setAvrcpAbsoluteVolume(newIndex / 10);
+ }
+ }
+ }
+
+ // Check if volume update should be sent to Hdmi system audio.
if (streamTypeAlias == AudioSystem.STREAM_MUSIC) {
setSystemAudioVolume(oldIndex, newIndex, getStreamMaxVolume(streamType), flags);
}
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index 1767a21..cffa834 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -71,6 +71,9 @@
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.UserHandle;
+import android.os.UserManager;
+import android.os.UserManagerInternal;
+import android.os.UserManagerInternal.UserRestrictionsListener;
import android.provider.Settings;
import android.telephony.CarrierConfigManager;
import android.text.TextUtils;
@@ -87,6 +90,7 @@
import com.android.internal.util.Protocol;
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
+import com.android.server.LocalServices;
import com.android.server.connectivity.tethering.IControlsTethering;
import com.android.server.connectivity.tethering.IPv6TetheringCoordinator;
import com.android.server.connectivity.tethering.OffloadController;
@@ -246,6 +250,13 @@
filter.addDataScheme("file");
mContext.registerReceiver(mStateReceiver, filter, null, smHandler);
+ UserManagerInternal userManager = LocalServices.getService(UserManagerInternal.class);
+
+ // this check is useful only for some unit tests; example: ConnectivityServiceTest
+ if (userManager != null) {
+ userManager.addUserRestrictionsListener(new TetheringUserRestrictionListener(this));
+ }
+
// load device config info
updateConfiguration();
}
@@ -733,6 +744,11 @@
}
private void showTetheredNotification(int id) {
+ showTetheredNotification(id, true);
+ }
+
+ @VisibleForTesting
+ protected void showTetheredNotification(int id, boolean tetheringOn) {
NotificationManager notificationManager =
(NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
if (notificationManager == null) {
@@ -769,9 +785,16 @@
null, UserHandle.CURRENT);
Resources r = Resources.getSystem();
- CharSequence title = r.getText(com.android.internal.R.string.tethered_notification_title);
- CharSequence message = r.getText(com.android.internal.R.string.
- tethered_notification_message);
+ final CharSequence title;
+ final CharSequence message;
+
+ if (tetheringOn) {
+ title = r.getText(com.android.internal.R.string.tethered_notification_title);
+ message = r.getText(com.android.internal.R.string.tethered_notification_message);
+ } else {
+ title = r.getText(com.android.internal.R.string.disable_tether_notification_title);
+ message = r.getText(com.android.internal.R.string.disable_tether_notification_message);
+ }
if (mTetheredNotificationBuilder == null) {
mTetheredNotificationBuilder =
@@ -793,7 +816,8 @@
mTetheredNotificationBuilder.buildInto(new Notification()), UserHandle.ALL);
}
- private void clearTetheredNotification() {
+ @VisibleForTesting
+ protected void clearTetheredNotification() {
NotificationManager notificationManager =
(NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
if (notificationManager != null && mLastNotificationId != 0) {
@@ -896,6 +920,38 @@
}
}
+ @VisibleForTesting
+ protected static class TetheringUserRestrictionListener implements UserRestrictionsListener {
+ private final Tethering mWrapper;
+
+ public TetheringUserRestrictionListener(Tethering wrapper) {
+ mWrapper = wrapper;
+ }
+
+ public void onUserRestrictionsChanged(int userId,
+ Bundle newRestrictions,
+ Bundle prevRestrictions) {
+ final boolean newlyDisallowed =
+ newRestrictions.getBoolean(UserManager.DISALLOW_CONFIG_TETHERING);
+ final boolean previouslyDisallowed =
+ prevRestrictions.getBoolean(UserManager.DISALLOW_CONFIG_TETHERING);
+ final boolean tetheringDisallowedChanged = (newlyDisallowed != previouslyDisallowed);
+
+ if (!tetheringDisallowedChanged) {
+ return;
+ }
+
+ mWrapper.clearTetheredNotification();
+ final boolean isTetheringActiveOnDevice = (mWrapper.getTetheredIfaces().length != 0);
+
+ if (newlyDisallowed && isTetheringActiveOnDevice) {
+ mWrapper.showTetheredNotification(
+ com.android.internal.R.drawable.stat_sys_tether_general, false);
+ mWrapper.untetherAll();
+ }
+ }
+ }
+
private void disableWifiIpServingLocked(String ifname, int apState) {
mLog.log("Canceling WiFi tethering request - AP_STATE=" + apState);
diff --git a/services/core/java/com/android/server/pm/BackgroundDexOptService.java b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
index 423201a..3814ef3 100644
--- a/services/core/java/com/android/server/pm/BackgroundDexOptService.java
+++ b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
@@ -144,6 +144,12 @@
Intent intent = registerReceiver(null, filter);
int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
int scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
+ boolean present = intent.getBooleanExtra(BatteryManager.EXTRA_PRESENT, true);
+
+ if (!present) {
+ // No battery, treat as if 100%, no possibility of draining battery.
+ return 100;
+ }
if (level < 0 || scale <= 0) {
// Battery data unavailable. This should never happen, so assume the worst.
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index de75ac4..e8b2fa7 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -1800,7 +1800,14 @@
public static final String KEY_CARRIER_CONFIG_APPLIED_BOOL = "carrier_config_applied_bool";
/**
- * List of thresholds of RSRP for determining the display level of LTE signal bar.
+ * A list of 4 LTE RSRP thresholds above which a signal level is considered POOR,
+ * MODERATE, GOOD, or EXCELLENT, to be used in SignalStrength reporting.
+ *
+ * Note that the min and max thresholds are fixed at -140 and -44, as explained in
+ * TS 36.133 9.1.4 - RSRP Measurement Report Mapping.
+ * <p>
+ * See SignalStrength#MAX_LTE_RSRP and SignalStrength#MIN_LTE_RSRP. Any signal level outside
+ * these boundaries is considered invalid.
* @hide
*/
public static final String KEY_LTE_RSRP_THRESHOLDS_INT_ARRAY =
@@ -2118,12 +2125,10 @@
sDefaults.putBoolean(KEY_CARRIER_CONFIG_APPLIED_BOOL, false);
sDefaults.putIntArray(KEY_LTE_RSRP_THRESHOLDS_INT_ARRAY,
new int[] {
- -140, /* SIGNAL_STRENGTH_NONE_OR_UNKNOWN */
-128, /* SIGNAL_STRENGTH_POOR */
-118, /* SIGNAL_STRENGTH_MODERATE */
-108, /* SIGNAL_STRENGTH_GOOD */
-98, /* SIGNAL_STRENGTH_GREAT */
- -44
});
}
diff --git a/telephony/java/android/telephony/PhoneStateListener.java b/telephony/java/android/telephony/PhoneStateListener.java
index 0ee870a..0446925 100644
--- a/telephony/java/android/telephony/PhoneStateListener.java
+++ b/telephony/java/android/telephony/PhoneStateListener.java
@@ -372,7 +372,7 @@
break;
case LISTEN_PHYSICAL_CHANNEL_CONFIGURATION:
PhoneStateListener.this.onPhysicalChannelConfigurationChanged(
- (List<PhysicalChannelConfig>)msg.obj);
+ (List<PhysicalChannelConfig>)msg.obj);
break;
}
}
@@ -700,6 +700,10 @@
public void onCarrierNetworkChange(boolean active) {
send(LISTEN_CARRIER_NETWORK_CHANGE, 0, 0, active);
}
+
+ public void onPhysicalChannelConfigurationChanged(List<PhysicalChannelConfig> configs) {
+ send(LISTEN_PHYSICAL_CHANNEL_CONFIGURATION, 0, 0, configs);
+ }
}
IPhoneStateListener callback = new IPhoneStateListenerStub(this);
diff --git a/telephony/java/android/telephony/PhysicalChannelConfig.java b/telephony/java/android/telephony/PhysicalChannelConfig.java
index 651d68d..ce444dd 100644
--- a/telephony/java/android/telephony/PhysicalChannelConfig.java
+++ b/telephony/java/android/telephony/PhysicalChannelConfig.java
@@ -27,8 +27,9 @@
*/
public final class PhysicalChannelConfig implements Parcelable {
+ // TODO(b/72993578) consolidate these enums in a central location.
@Retention(RetentionPolicy.SOURCE)
- @IntDef({CONNECTION_PRIMARY_SERVING, CONNECTION_SECONDARY_SERVING})
+ @IntDef({CONNECTION_PRIMARY_SERVING, CONNECTION_SECONDARY_SERVING, CONNECTION_UNKNOWN})
public @interface ConnectionStatus {}
/**
@@ -41,6 +42,9 @@
*/
public static final int CONNECTION_SECONDARY_SERVING = 2;
+ /** Connection status is unknown. */
+ public static final int CONNECTION_UNKNOWN = Integer.MAX_VALUE;
+
/**
* Connection status of the cell.
*
@@ -86,6 +90,7 @@
*
* @see #CONNECTION_PRIMARY_SERVING
* @see #CONNECTION_SECONDARY_SERVING
+ * @see #CONNECTION_UNKNOWN
*
* @return Connection status of the cell
*/
diff --git a/telephony/java/android/telephony/SignalStrength.java b/telephony/java/android/telephony/SignalStrength.java
index fc2ef27..e508b19 100644
--- a/telephony/java/android/telephony/SignalStrength.java
+++ b/telephony/java/android/telephony/SignalStrength.java
@@ -57,7 +57,9 @@
*/
public static final int INVALID = Integer.MAX_VALUE;
- private static final int LTE_RSRP_THRESHOLDS_NUM = 6;
+ private static final int LTE_RSRP_THRESHOLDS_NUM = 4;
+ private static final int MAX_LTE_RSRP = -44;
+ private static final int MIN_LTE_RSRP = -140;
/** Parameters reported by the Radio */
private int mGsmSignalStrength; // Valid values are (0-31, 99) as defined in TS 27.007 8.5
@@ -81,7 +83,8 @@
// onSignalStrengthResult.
private boolean mUseOnlyRsrpForLteLevel; // Use only RSRP for the number of LTE signal bar.
- // The threshold of LTE RSRP for determining the display level of LTE signal bar.
+ // The threshold of LTE RSRP for determining the display level of LTE signal bar. Note that the
+ // min and max are fixed at MIN_LTE_RSRP (-140) and MAX_LTE_RSRP (-44).
private int mLteRsrpThresholds[] = new int[LTE_RSRP_THRESHOLDS_NUM];
/**
@@ -319,7 +322,8 @@
// TS 36.214 Physical Layer Section 5.1.3, TS 36.331 RRC
mLteSignalStrength = (mLteSignalStrength >= 0) ? mLteSignalStrength : 99;
- mLteRsrp = ((mLteRsrp >= 44) && (mLteRsrp <= 140)) ? -mLteRsrp : SignalStrength.INVALID;
+ mLteRsrp = ((-mLteRsrp >= MIN_LTE_RSRP) && (-mLteRsrp <= MAX_LTE_RSRP)) ? -mLteRsrp
+ : SignalStrength.INVALID;
mLteRsrq = ((mLteRsrq >= 3) && (mLteRsrq <= 20)) ? -mLteRsrq : SignalStrength.INVALID;
mLteRssnr = ((mLteRssnr >= -200) && (mLteRssnr <= 300)) ? mLteRssnr
: SignalStrength.INVALID;
@@ -735,24 +739,29 @@
*/
public int getLteLevel() {
/*
- * TS 36.214 Physical Layer Section 5.1.3 TS 36.331 RRC RSSI = received
- * signal + noise RSRP = reference signal dBm RSRQ = quality of signal
- * dB= Number of Resource blocksxRSRP/RSSI SNR = gain=signal/noise ratio
- * = -10log P1/P2 dB
+ * TS 36.214 Physical Layer Section 5.1.3
+ * TS 36.331 RRC
+ *
+ * RSSI = received signal + noise
+ * RSRP = reference signal dBm
+ * RSRQ = quality of signal dB = Number of Resource blocks*RSRP/RSSI
+ * SNR = gain = signal/noise ratio = -10log P1/P2 dB
*/
int rssiIconLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN, rsrpIconLevel = -1, snrIconLevel = -1;
- if (mLteRsrp > mLteRsrpThresholds[5]) {
- rsrpIconLevel = -1;
- } else if (mLteRsrp >= (mLteRsrpThresholds[4] - mLteRsrpBoost)) {
- rsrpIconLevel = SIGNAL_STRENGTH_GREAT;
+ if (mLteRsrp > MAX_LTE_RSRP || mLteRsrp < MIN_LTE_RSRP) {
+ if (mLteRsrp != INVALID) {
+ Log.wtf(LOG_TAG, "getLteLevel - invalid lte rsrp: mLteRsrp=" + mLteRsrp);
+ }
} else if (mLteRsrp >= (mLteRsrpThresholds[3] - mLteRsrpBoost)) {
- rsrpIconLevel = SIGNAL_STRENGTH_GOOD;
+ rsrpIconLevel = SIGNAL_STRENGTH_GREAT;
} else if (mLteRsrp >= (mLteRsrpThresholds[2] - mLteRsrpBoost)) {
- rsrpIconLevel = SIGNAL_STRENGTH_MODERATE;
+ rsrpIconLevel = SIGNAL_STRENGTH_GOOD;
} else if (mLteRsrp >= (mLteRsrpThresholds[1] - mLteRsrpBoost)) {
+ rsrpIconLevel = SIGNAL_STRENGTH_MODERATE;
+ } else if (mLteRsrp >= (mLteRsrpThresholds[0] - mLteRsrpBoost)) {
rsrpIconLevel = SIGNAL_STRENGTH_POOR;
- } else if (mLteRsrp >= mLteRsrpThresholds[0]) {
+ } else {
rsrpIconLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
}
diff --git a/telephony/java/android/telephony/Telephony.java b/telephony/java/android/telephony/Telephony.java
index e7f0cc2..cb87d1f 100644
--- a/telephony/java/android/telephony/Telephony.java
+++ b/telephony/java/android/telephony/Telephony.java
@@ -1103,10 +1103,15 @@
"android.provider.Telephony.MMS_DOWNLOADED";
/**
- * Broadcast Action: A debug code has been entered in the dialer. These "secret codes"
- * are used to activate developer menus by dialing certain codes. And they are of the
- * form {@code *#*#<code>#*#*}. The intent will have the data URI:
- * {@code android_secret_code://<code>}.
+ * Broadcast Action: A debug code has been entered in the dialer. This intent is
+ * broadcast by the system and OEM telephony apps may need to receive these broadcasts.
+ * These "secret codes" are used to activate developer menus by dialing certain codes.
+ * And they are of the form {@code *#*#<code>#*#*}. The intent will have the data
+ * URI: {@code android_secret_code://<code>}. It is possible that a manifest
+ * receiver would be woken up even if it is not currently running.
+ *
+ * <p>Requires {@code android.Manifest.permission#CONTROL_INCALL_EXPERIENCE} to
+ * send and receive.</p>
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String SECRET_CODE_ACTION =
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 0c92a68..fdb31eb 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -5107,6 +5107,24 @@
}
/**
+ * Determines if emergency calling is allowed for the MMTEL feature on the slot provided.
+ * @param slotIndex The SIM slot of the MMTEL feature
+ * @return true if emergency calling is allowed, false otherwise.
+ * @hide
+ */
+ public boolean isEmergencyMmTelAvailable(int slotIndex) {
+ try {
+ ITelephony telephony = getITelephony();
+ if (telephony != null) {
+ return telephony.isEmergencyMmTelAvailable(slotIndex);
+ }
+ } catch (RemoteException e) {
+ Rlog.e(TAG, "isEmergencyMmTelAvailable, RemoteException: " + e.getMessage());
+ }
+ return false;
+ }
+
+ /**
* Set IMS registration state
*
* @param Registration state
@@ -6968,18 +6986,16 @@
*
* @return Carrier id of the current subscription. Return {@link #UNKNOWN_CARRIER_ID} if the
* subscription is unavailable or the carrier cannot be identified.
- * @throws IllegalStateException if telephony service is unavailable.
*/
public int getAndroidCarrierIdForSubscription() {
try {
ITelephony service = getITelephony();
- return service.getSubscriptionCarrierId(getSubId());
+ if (service != null) {
+ return service.getSubscriptionCarrierId(getSubId());
+ }
} catch (RemoteException ex) {
// This could happen if binder process crashes.
ex.rethrowAsRuntimeException();
- } catch (NullPointerException ex) {
- // This could happen before phone restarts due to crashing.
- throw new IllegalStateException("Telephony service unavailable");
}
return UNKNOWN_CARRIER_ID;
}
@@ -6995,18 +7011,16 @@
*
* @return Carrier name of the current subscription. Return {@code null} if the subscription is
* unavailable or the carrier cannot be identified.
- * @throws IllegalStateException if telephony service is unavailable.
*/
public CharSequence getAndroidCarrierNameForSubscription() {
try {
ITelephony service = getITelephony();
- return service.getSubscriptionCarrierName(getSubId());
+ if (service != null) {
+ return service.getSubscriptionCarrierName(getSubId());
+ }
} catch (RemoteException ex) {
// This could happen if binder process crashes.
ex.rethrowAsRuntimeException();
- } catch (NullPointerException ex) {
- // This could happen before phone restarts due to crashing.
- throw new IllegalStateException("Telephony service unavailable");
}
return null;
}
diff --git a/telephony/java/android/telephony/ims/feature/ImsFeature.java b/telephony/java/android/telephony/ims/feature/ImsFeature.java
index 1fdbae9..d537699 100644
--- a/telephony/java/android/telephony/ims/feature/ImsFeature.java
+++ b/telephony/java/android/telephony/ims/feature/ImsFeature.java
@@ -87,7 +87,9 @@
// ImsFeatures that are defined in the Manifests. Ensure that these values match the previously
// defined values in ImsServiceClass for compatibility purposes.
/**
- * This feature supports emergency calling over MMTEL.
+ * This feature supports emergency calling over MMTEL. If defined, the framework will try to
+ * place an emergency call over IMS first. If it is not defined, the framework will only use
+ * CSFB for emergency calling.
*/
public static final int FEATURE_EMERGENCY_MMTEL = 0;
/**
diff --git a/telephony/java/android/telephony/ims/feature/MmTelFeature.java b/telephony/java/android/telephony/ims/feature/MmTelFeature.java
index 09267fc..2fffd36 100644
--- a/telephony/java/android/telephony/ims/feature/MmTelFeature.java
+++ b/telephony/java/android/telephony/ims/feature/MmTelFeature.java
@@ -332,20 +332,14 @@
public static final int PROCESS_CALL_IMS = 0;
/**
* To be returned by {@link #shouldProcessCall(String[])} when the telephony framework should
- * not process the outgoing NON_EMERGENCY call as IMS and should instead use circuit switch.
+ * not process the outgoing call as IMS and should instead use circuit switch.
*/
public static final int PROCESS_CALL_CSFB = 1;
- /**
- * To be returned by {@link #shouldProcessCall(String[])} when the telephony framework should
- * not process the outgoing EMERGENCY call as IMS and should instead use circuit switch.
- */
- public static final int PROCESS_CALL_EMERGENCY_CSFB = 2;
@IntDef(flag = true,
value = {
PROCESS_CALL_IMS,
- PROCESS_CALL_CSFB,
- PROCESS_CALL_EMERGENCY_CSFB
+ PROCESS_CALL_CSFB
})
@Retention(RetentionPolicy.SOURCE)
public @interface ProcessCallResult {}
@@ -536,12 +530,15 @@
/**
* Called by the framework to determine if the outgoing call, designated by the outgoing
- * {@link Uri}s, should be processed as an IMS call or CSFB call.
+ * {@link String}s, should be processed as an IMS call or CSFB call. If this method's
+ * functionality is not overridden, the platform will process every call as IMS as long as the
+ * MmTelFeature reports that the {@link MmTelCapabilities#CAPABILITY_TYPE_VOICE} capability is
+ * available.
* @param numbers An array of {@link String}s that will be used for placing the call. There can
* be multiple {@link String}s listed in the case when we want to place an outgoing
* call as a conference.
* @return a {@link ProcessCallResult} to the framework, which will be used to determine if the
- * call wil lbe placed over IMS or via CSFB.
+ * call will be placed over IMS or via CSFB.
*/
public @ProcessCallResult int shouldProcessCall(String[] numbers) {
return PROCESS_CALL_IMS;
diff --git a/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl b/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl
index 8e3f4c0..1cfe8c2 100644
--- a/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl
+++ b/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl
@@ -21,6 +21,7 @@
import android.telephony.SignalStrength;
import android.telephony.CellInfo;
import android.telephony.DataConnectionRealTimeInfo;
+import android.telephony.PhysicalChannelConfig;
import android.telephony.PreciseCallState;
import android.telephony.PreciseDataConnectionState;
import android.telephony.VoLteServiceState;
@@ -37,6 +38,7 @@
void onDataConnectionStateChanged(int state, int networkType);
void onDataActivity(int direction);
void onSignalStrengthsChanged(in SignalStrength signalStrength);
+ void onPhysicalChannelConfigurationChanged(in List<PhysicalChannelConfig> configs);
void onOtaspChanged(in int otaspMode);
void onCellInfoChanged(in List<CellInfo> cellInfo);
void onPreciseCallStateChanged(in PreciseCallState callState);
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 9e2b519..d96f926 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -823,6 +823,12 @@
IImsConfig getImsConfig(int slotId, int feature);
/**
+ * Returns true if emergency calling is available for the MMTEL feature associated with the
+ * slot specified.
+ */
+ boolean isEmergencyMmTelAvailable(int slotId);
+
+ /**
* Set the network selection mode to automatic.
*
* @param subId the id of the subscription to update.
diff --git a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
index 188167c..06dc13e 100644
--- a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
@@ -21,9 +21,9 @@
import android.net.NetworkCapabilities;
import android.os.Bundle;
import android.telephony.CellInfo;
+import android.telephony.PhysicalChannelConfig;
import android.telephony.ServiceState;
import android.telephony.SignalStrength;
-import android.telephony.CellInfo;
import android.telephony.VoLteServiceState;
import com.android.internal.telephony.IPhoneStateListener;
import com.android.internal.telephony.IOnSubscriptionsChangedListener;
@@ -58,6 +58,9 @@
void notifyCellLocationForSubscriber(in int subId, in Bundle cellLocation);
void notifyOtaspChanged(in int otaspMode);
void notifyCellInfo(in List<CellInfo> cellInfo);
+ void notifyPhysicalChannelConfiguration(in List<PhysicalChannelConfig> configs);
+ void notifyPhysicalChannelConfigurationForSubscriber(in int subId,
+ in List<PhysicalChannelConfig> configs);
void notifyPreciseCallState(int ringingCallState, int foregroundCallState,
int backgroundCallState);
void notifyDisconnectCause(int disconnectCause, int preciseDisconnectCause);
diff --git a/tests/net/java/android/net/NetworkCapabilitiesTest.java b/tests/net/java/android/net/NetworkCapabilitiesTest.java
index 4c6a644..2414a8e 100644
--- a/tests/net/java/android/net/NetworkCapabilitiesTest.java
+++ b/tests/net/java/android/net/NetworkCapabilitiesTest.java
@@ -23,6 +23,7 @@
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_OEM_PAID;
import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
import static android.net.NetworkCapabilities.RESTRICTED_CAPABILITIES;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
@@ -261,6 +262,19 @@
assertEqualsThroughMarshalling(netCap);
}
+ @Test
+ public void testOemPaid() {
+ NetworkCapabilities nc = new NetworkCapabilities();
+ nc.maybeMarkCapabilitiesRestricted();
+ assertFalse(nc.hasCapability(NET_CAPABILITY_OEM_PAID));
+ assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
+
+ nc.addCapability(NET_CAPABILITY_OEM_PAID);
+ nc.maybeMarkCapabilitiesRestricted();
+ assertTrue(nc.hasCapability(NET_CAPABILITY_OEM_PAID));
+ assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
+ }
+
private void assertEqualsThroughMarshalling(NetworkCapabilities netCap) {
Parcel p = Parcel.obtain();
netCap.writeToParcel(p, /* flags */ 0);
diff --git a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java
index 66e0955..3e1ff6d 100644
--- a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java
+++ b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java
@@ -281,6 +281,7 @@
anyInt());
}
+ @Test
public void testCreateTwoTransformsWithSameSpis() throws Exception {
IpSecConfig ipSecConfig = new IpSecConfig();
addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
diff --git a/tests/net/java/com/android/server/connectivity/TetheringTest.java b/tests/net/java/com/android/server/connectivity/TetheringTest.java
index a115146..099cfd4 100644
--- a/tests/net/java/com/android/server/connectivity/TetheringTest.java
+++ b/tests/net/java/com/android/server/connectivity/TetheringTest.java
@@ -40,6 +40,7 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.mock;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
@@ -59,12 +60,14 @@
import android.net.util.SharedLog;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
+import android.os.Bundle;
import android.os.Handler;
import android.os.INetworkManagementService;
import android.os.PersistableBundle;
import android.os.RemoteException;
import android.os.test.TestLooper;
import android.os.UserHandle;
+import android.os.UserManager;
import android.provider.Settings;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
@@ -558,6 +561,90 @@
verifyNoMoreInteractions(mNMService);
}
+ private void userRestrictionsListenerBehaviour(
+ boolean currentDisallow, boolean nextDisallow, String[] activeTetheringIfacesList,
+ int expectedInteractionsWithShowNotification) throws Exception {
+ final int userId = 0;
+ final Bundle currRestrictions = new Bundle();
+ final Bundle newRestrictions = new Bundle();
+ Tethering tethering = mock(Tethering.class);
+ Tethering.TetheringUserRestrictionListener turl =
+ new Tethering.TetheringUserRestrictionListener(tethering);
+
+ currRestrictions.putBoolean(UserManager.DISALLOW_CONFIG_TETHERING, currentDisallow);
+ newRestrictions.putBoolean(UserManager.DISALLOW_CONFIG_TETHERING, nextDisallow);
+ when(tethering.getTetheredIfaces()).thenReturn(activeTetheringIfacesList);
+
+ turl.onUserRestrictionsChanged(userId, newRestrictions, currRestrictions);
+
+ verify(tethering, times(expectedInteractionsWithShowNotification))
+ .showTetheredNotification(anyInt(), eq(false));
+
+ verify(tethering, times(expectedInteractionsWithShowNotification)).untetherAll();
+ }
+
+ @Test
+ public void testDisallowTetheringWhenNoTetheringInterfaceIsActive() throws Exception {
+ final String[] emptyActiveIfacesList = new String[]{};
+ final boolean currDisallow = false;
+ final boolean nextDisallow = true;
+ final int expectedInteractionsWithShowNotification = 0;
+
+ userRestrictionsListenerBehaviour(currDisallow, nextDisallow, emptyActiveIfacesList,
+ expectedInteractionsWithShowNotification);
+ }
+
+ @Test
+ public void testDisallowTetheringWhenAtLeastOneTetheringInterfaceIsActive() throws Exception {
+ final String[] nonEmptyActiveIfacesList = new String[]{mTestIfname};
+ final boolean currDisallow = false;
+ final boolean nextDisallow = true;
+ final int expectedInteractionsWithShowNotification = 1;
+
+ userRestrictionsListenerBehaviour(currDisallow, nextDisallow, nonEmptyActiveIfacesList,
+ expectedInteractionsWithShowNotification);
+ }
+
+ @Test
+ public void testAllowTetheringWhenNoTetheringInterfaceIsActive() throws Exception {
+ final String[] nonEmptyActiveIfacesList = new String[]{};
+ final boolean currDisallow = true;
+ final boolean nextDisallow = false;
+ final int expectedInteractionsWithShowNotification = 0;
+
+ userRestrictionsListenerBehaviour(currDisallow, nextDisallow, nonEmptyActiveIfacesList,
+ expectedInteractionsWithShowNotification);
+ }
+
+ @Test
+ public void testAllowTetheringWhenAtLeastOneTetheringInterfaceIsActive() throws Exception {
+ final String[] nonEmptyActiveIfacesList = new String[]{mTestIfname};
+ final boolean currDisallow = true;
+ final boolean nextDisallow = false;
+ final int expectedInteractionsWithShowNotification = 0;
+
+ userRestrictionsListenerBehaviour(currDisallow, nextDisallow, nonEmptyActiveIfacesList,
+ expectedInteractionsWithShowNotification);
+ }
+
+ @Test
+ public void testDisallowTetheringUnchanged() throws Exception {
+ final String[] nonEmptyActiveIfacesList = new String[]{mTestIfname};
+ final int expectedInteractionsWithShowNotification = 0;
+ boolean currDisallow = true;
+ boolean nextDisallow = true;
+
+ userRestrictionsListenerBehaviour(currDisallow, nextDisallow, nonEmptyActiveIfacesList,
+ expectedInteractionsWithShowNotification);
+
+ currDisallow = false;
+ nextDisallow = false;
+
+ userRestrictionsListenerBehaviour(currDisallow, nextDisallow, nonEmptyActiveIfacesList,
+ expectedInteractionsWithShowNotification);
+ }
+
+
// TODO: Test that a request for hotspot mode doesn't interfere with an
// already operating tethering mode interface.
}