diff options
17 files changed, 246 insertions, 125 deletions
diff --git a/api/test-current.txt b/api/test-current.txt index 075963ef5efd..144e5f5c8f53 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -1532,6 +1532,15 @@ package android.telephony { method public void setVoiceRoamingType(int); } + public final class SmsManager { + method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public int checkSmsShortCodeDestination(String, String); + field public static final int SMS_CATEGORY_FREE_SHORT_CODE = 1; // 0x1 + field public static final int SMS_CATEGORY_NOT_SHORT_CODE = 0; // 0x0 + field public static final int SMS_CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE = 3; // 0x3 + field public static final int SMS_CATEGORY_PREMIUM_SHORT_CODE = 4; // 0x4 + field public static final int SMS_CATEGORY_STANDARD_SHORT_CODE = 2; // 0x2 + } + public class TelephonyManager { method public int getCarrierIdListVersion(); method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getLine1AlphaTag(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java index b7c20aa197ca..b67a9f03822c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java @@ -548,7 +548,7 @@ public class MobileSignalController extends SignalController< } private boolean isDataDisabled() { - return !mPhone.getDataEnabled(mSubscriptionInfo.getSubscriptionId()); + return !mPhone.isDataCapable(); } @VisibleForTesting @@ -568,6 +568,7 @@ public class MobileSignalController extends SignalController< pw.println(" mSignalStrength=" + mSignalStrength + ","); pw.println(" mDataState=" + mDataState + ","); pw.println(" mDataNetType=" + mDataNetType + ","); + pw.println(" isDataDisabled=" + isDataDisabled() + ","); } class MobilePhoneStateListener extends PhoneStateListener { diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java index c1f88855ac24..02f99a00c1a0 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java @@ -155,7 +155,7 @@ public class NetworkControllerBaseTest extends SysuiTestCase { protected void setupNetworkController() { // For now just pretend to be the data sim, so we can test that too. mSubId = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID; - when(mMockTm.getDataEnabled(mSubId)).thenReturn(true); + when(mMockTm.isDataCapable()).thenReturn(true); setDefaultSubId(mSubId); setSubscriptions(mSubId); mMobileSignalController = mNetworkController.mMobileSignalControllers.get(mSubId); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java index 96fad21ed7a3..2aa933e723c2 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java @@ -119,7 +119,7 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest { @Test public void testNoInternetIcon() { setupNetworkController(); - when(mMockTm.getDataEnabled(mSubId)).thenReturn(false); + when(mMockTm.isDataCapable()).thenReturn(false); setupDefaultSignal(); updateDataConnectionState(TelephonyManager.DATA_CONNECTED, 0); setConnectivityViaBroadcast(NetworkCapabilities.TRANSPORT_CELLULAR, false, false); @@ -133,7 +133,7 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest { @Test public void testDataDisabledIcon() { setupNetworkController(); - when(mMockTm.getDataEnabled(mSubId)).thenReturn(false); + when(mMockTm.isDataCapable()).thenReturn(false); setupDefaultSignal(); updateDataConnectionState(TelephonyManager.DATA_DISCONNECTED, 0); setConnectivityViaBroadcast(NetworkCapabilities.TRANSPORT_CELLULAR, false, false); @@ -188,7 +188,7 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest { @Test public void testDataDisabledIcon_UserNotSetup() { setupNetworkController(); - when(mMockTm.getDataEnabled(mSubId)).thenReturn(false); + when(mMockTm.isDataCapable()).thenReturn(false); setupDefaultSignal(); updateDataConnectionState(TelephonyManager.DATA_DISCONNECTED, 0); setConnectivityViaBroadcast(NetworkCapabilities.TRANSPORT_CELLULAR, false, false); @@ -203,7 +203,7 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest { @Test public void testAlwaysShowDataRatIcon() { setupDefaultSignal(); - when(mMockTm.getDataEnabled(mSubId)).thenReturn(false); + when(mMockTm.isDataCapable()).thenReturn(false); updateDataConnectionState(TelephonyManager.DATA_DISCONNECTED, TelephonyManager.NETWORK_TYPE_GSM); diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index ae80d7ef11e5..a71d46cbe886 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -2614,9 +2614,11 @@ public class ConnectivityService extends IConnectivityManager.Stub final boolean valid = ((msg.arg1 & NETWORK_VALIDATION_RESULT_VALID) != 0); final boolean wasValidated = nai.lastValidated; final boolean wasDefault = isDefaultNetwork(nai); - if (nai.everCaptivePortalDetected && !nai.captivePortalLoginNotified - && valid) { - nai.captivePortalLoginNotified = true; + // Only show a connected notification if the network is pending validation + // after the captive portal app was open, and it has now validated. + if (nai.captivePortalValidationPending && valid) { + // User is now logged in, network validated. + nai.captivePortalValidationPending = false; showNetworkNotification(nai, NotificationType.LOGGED_IN); } @@ -2687,9 +2689,6 @@ public class ConnectivityService extends IConnectivityManager.Stub final int oldScore = nai.getCurrentScore(); nai.lastCaptivePortalDetected = visible; nai.everCaptivePortalDetected |= visible; - if (visible) { - nai.captivePortalLoginNotified = false; - } if (nai.lastCaptivePortalDetected && Settings.Global.CAPTIVE_PORTAL_MODE_AVOID == getCaptivePortalMode()) { if (DBG) log("Avoiding captive portal network: " + nai.name()); @@ -3498,6 +3497,12 @@ public class ConnectivityService extends IConnectivityManager.Stub new CaptivePortal(new CaptivePortalImpl(network).asBinder())); appIntent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_NEW_TASK); + // This runs on a random binder thread, but getNetworkAgentInfoForNetwork is thread-safe, + // and captivePortalValidationPending is volatile. + final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network); + if (nai != null) { + nai.captivePortalValidationPending = true; + } Binder.withCleanCallingIdentity(() -> mContext.startActivityAsUser(appIntent, UserHandle.CURRENT)); } diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java index 864a793b8f40..5b043799f848 100644 --- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java +++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java @@ -155,9 +155,9 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> { // Whether a captive portal was found during the last network validation attempt. public boolean lastCaptivePortalDetected; - // Indicates the user was notified of a successful captive portal login since a portal was - // last detected. - public boolean captivePortalLoginNotified; + // Indicates the captive portal app was opened to show a login UI to the user, but the network + // has not validated yet. + public volatile boolean captivePortalValidationPending; // Set to true when partial connectivity was detected. public boolean partialConnectivity; @@ -629,7 +629,7 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> { + "acceptUnvalidated{" + networkMisc.acceptUnvalidated + "} " + "everCaptivePortalDetected{" + everCaptivePortalDetected + "} " + "lastCaptivePortalDetected{" + lastCaptivePortalDetected + "} " - + "captivePortalLoginNotified{" + captivePortalLoginNotified + "} " + + "captivePortalValidationPending{" + captivePortalValidationPending + "} " + "partialConnectivity{" + partialConnectivity + "} " + "acceptPartialConnectivity{" + networkMisc.acceptPartialConnectivity + "} " + "clat{" + clatd + "} " diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 2fc78d6f4760..5505828063ed 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -373,14 +373,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } public void systemReady() { - mSystemReady = true; - - if (!isBandwidthControlEnabled()) { - Slog.w(TAG, "bandwidth controls disabled, unable to track stats"); - return; - } - synchronized (mStatsLock) { + mSystemReady = true; + // create data recorders along with historical rotators mDevRecorder = buildRecorder(PREFIX_DEV, mSettings.getDevConfig(), false); mXtRecorder = buildRecorder(PREFIX_XT, mSettings.getXtConfig(), false); @@ -426,7 +421,14 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // ignored; service lives in system_server } - registerPollAlarmLocked(); + // schedule periodic pall alarm based on {@link NetworkStatsSettings#getPollInterval()}. + final PendingIntent pollIntent = + PendingIntent.getBroadcast(mContext, 0, new Intent(ACTION_NETWORK_STATS_POLL), 0); + + final long currentRealtime = SystemClock.elapsedRealtime(); + mAlarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, currentRealtime, + mSettings.getPollInterval(), pollIntent); + registerGlobalAlert(); } @@ -487,23 +489,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } /** - * Clear any existing {@link #ACTION_NETWORK_STATS_POLL} alarms, and - * reschedule based on current {@link NetworkStatsSettings#getPollInterval()}. - */ - private void registerPollAlarmLocked() { - if (mPollIntent != null) { - mAlarmManager.cancel(mPollIntent); - } - - mPollIntent = PendingIntent.getBroadcast( - mContext, 0, new Intent(ACTION_NETWORK_STATS_POLL), 0); - - final long currentRealtime = SystemClock.elapsedRealtime(); - mAlarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, currentRealtime, - mSettings.getPollInterval(), mPollIntent); - } - - /** * Register for a global alert that is delivered through * {@link INetworkManagementEventObserver} once a threshold amount of data * has been transferred. @@ -548,8 +533,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } private INetworkStatsSession openSessionInternal(final int flags, final String callingPackage) { - assertBandwidthControlEnabled(); - final int callingUid = Binder.getCallingUid(); final int usedFlags = isRateLimitedForPoll(callingUid) ? flags & (~NetworkStatsManager.FLAG_POLL_ON_OPEN) @@ -742,7 +725,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private long getNetworkTotalBytes(NetworkTemplate template, long start, long end) { assertSystemReady(); - assertBandwidthControlEnabled(); // NOTE: if callers want to get non-augmented data, they should go // through the public API @@ -753,7 +735,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private NetworkStats getNetworkUidBytes(NetworkTemplate template, long start, long end) { assertSystemReady(); - assertBandwidthControlEnabled(); final NetworkStatsCollection uidComplete; synchronized (mStatsLock) { @@ -768,7 +749,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { if (Binder.getCallingUid() != uid) { mContext.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, TAG); } - assertBandwidthControlEnabled(); // TODO: switch to data layer stats once kernel exports // for now, read network layer stats and flatten across all ifaces @@ -855,7 +835,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { NetworkState[] networkStates, String activeIface) { checkNetworkStackPermission(mContext); - assertBandwidthControlEnabled(); final long token = Binder.clearCallingIdentity(); try { @@ -868,7 +847,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @Override public void forceUpdate() { mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG); - assertBandwidthControlEnabled(); final long token = Binder.clearCallingIdentity(); try { @@ -879,8 +857,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } private void advisePersistThreshold(long thresholdBytes) { - assertBandwidthControlEnabled(); - // clamp threshold into safe range mPersistThreshold = MathUtils.constrain(thresholdBytes, 128 * KB_IN_BYTES, 2 * MB_IN_BYTES); if (LOGV) { @@ -1739,24 +1715,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } } - private void assertBandwidthControlEnabled() { - if (!isBandwidthControlEnabled()) { - throw new IllegalStateException("Bandwidth module disabled"); - } - } - - private boolean isBandwidthControlEnabled() { - final long token = Binder.clearCallingIdentity(); - try { - return mNetworkManager.isBandwidthControlEnabled(); - } catch (RemoteException e) { - // ignored; service lives in system_server - return false; - } finally { - Binder.restoreCallingIdentity(token); - } - } - private class DropBoxNonMonotonicObserver implements NonMonotonicObserver<String> { @Override public void foundNonMonotonic(NetworkStats left, int leftIndex, NetworkStats right, diff --git a/services/net/java/android/net/ip/IpServer.java b/services/net/java/android/net/ip/IpServer.java index 66884c60b0bc..6a6a1307723e 100644 --- a/services/net/java/android/net/ip/IpServer.java +++ b/services/net/java/android/net/ip/IpServer.java @@ -433,6 +433,9 @@ public class IpServer extends StateMachine { } } ifcg.clearFlag("running"); + + // TODO: this may throw if the interface is already gone. Do proper handling and + // simplify the DHCP server start/stop. mNMService.setInterfaceConfig(mIfaceName, ifcg); if (!configureDhcp(enabled, (Inet4Address) addr, prefixLen)) { @@ -440,6 +443,14 @@ public class IpServer extends StateMachine { } } catch (Exception e) { mLog.e("Error configuring interface " + e); + if (!enabled) { + try { + // Calling stopDhcp several times is fine + stopDhcp(); + } catch (Exception dhcpError) { + mLog.e("Error stopping DHCP", dhcpError); + } + } return false; } diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java index 63e3801a9b4f..d4ea29fe1463 100644 --- a/telephony/java/android/telephony/SmsManager.java +++ b/telephony/java/android/telephony/SmsManager.java @@ -16,9 +16,11 @@ package android.telephony; +import android.annotation.IntDef; import android.annotation.RequiresPermission; import android.annotation.SuppressAutoDoc; import android.annotation.SystemApi; +import android.annotation.TestApi; import android.annotation.UnsupportedAppUsage; import android.app.ActivityThread; import android.app.PendingIntent; @@ -43,6 +45,8 @@ import com.android.internal.telephony.ISms; import com.android.internal.telephony.ITelephony; import com.android.internal.telephony.SmsRawData; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -2798,4 +2802,85 @@ public final class SmsManager { config.getBoolean(MMS_CONFIG_SUPPORT_HTTP_CHARSET_HEADER)); return filtered; } + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = {"SMS_CATEGORY_"}, + value = { + SmsManager.SMS_CATEGORY_NOT_SHORT_CODE, + SmsManager.SMS_CATEGORY_FREE_SHORT_CODE, + SmsManager.SMS_CATEGORY_STANDARD_SHORT_CODE, + SmsManager.SMS_CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE, + SmsManager.SMS_CATEGORY_PREMIUM_SHORT_CODE}) + public @interface SmsShortCodeCategory {} + + /** + * Return value from {@link #checkSmsShortCodeDestination(String, String)} ()} for regular + * phone numbers. + * @hide + */ + @TestApi + public static final int SMS_CATEGORY_NOT_SHORT_CODE = 0; + /** + * Return value from {@link #checkSmsShortCodeDestination(String, String)} ()} for free + * (no cost) short codes. + * @hide + */ + @TestApi + public static final int SMS_CATEGORY_FREE_SHORT_CODE = 1; + /** + * Return value from {@link #checkSmsShortCodeDestination(String, String)} ()} for + * standard rate (non-premium) + * short codes. + * @hide + */ + @TestApi + public static final int SMS_CATEGORY_STANDARD_SHORT_CODE = 2; + /** + * Return value from {@link #checkSmsShortCodeDestination(String, String)} ()} for possible + * premium short codes. + * @hide + */ + @TestApi + public static final int SMS_CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE = 3; + /** + * Return value from {@link #checkSmsShortCodeDestination(String, String)} ()} for + * premium short codes. + * @hide + */ + @TestApi + public static final int SMS_CATEGORY_PREMIUM_SHORT_CODE = 4; + + /** + * Check if the destination address is a possible premium short code. + * NOTE: the caller is expected to strip non-digits from the destination number with + * {@link PhoneNumberUtils#extractNetworkPortion} before calling this method. + * + * @param destAddress the destination address to test for possible short code + * @param countryIso the ISO country code + * + * @return + * {@link SmsManager#SMS_CATEGORY_NOT_SHORT_CODE}, + * {@link SmsManager#SMS_CATEGORY_FREE_SHORT_CODE}, + * {@link SmsManager#SMS_CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE}, + * {@link SmsManager#SMS_CATEGORY_PREMIUM_SHORT_CODE}, or + * {@link SmsManager#SMS_CATEGORY_STANDARD_SHORT_CODE} + * + * @hide + */ + @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) + @TestApi + public @SmsShortCodeCategory int checkSmsShortCodeDestination( + String destAddress, String countryIso) { + try { + ISms iccISms = getISmsServiceOrThrow(); + if (iccISms != null) { + return iccISms.checkSmsShortCodeDestination(getSubscriptionId(), + ActivityThread.currentPackageName(), destAddress, countryIso); + } + } catch (RemoteException e) { + Log.e(TAG, "checkSmsShortCodeDestination() RemoteException", e); + } + return SmsManager.SMS_CATEGORY_NOT_SHORT_CODE; + } } diff --git a/telephony/java/com/android/internal/telephony/ISms.aidl b/telephony/java/com/android/internal/telephony/ISms.aidl index c3dcc3db7d45..87aff8a57e27 100644 --- a/telephony/java/com/android/internal/telephony/ISms.aidl +++ b/telephony/java/com/android/internal/telephony/ISms.aidl @@ -551,4 +551,11 @@ interface ISms { * @param intent PendingIntent to be sent when an SMS is received containing the token. */ String createAppSpecificSmsToken(int subId, String callingPkg, in PendingIntent intent); + + /** + * Check if the destination is a possible premium short code. + * + * @param destAddress the destination address to test for possible short code + */ + int checkSmsShortCodeDestination(int subId, String callingApk, String destAddress, String countryIso); } diff --git a/telephony/java/com/android/internal/telephony/ISmsImplBase.java b/telephony/java/com/android/internal/telephony/ISmsImplBase.java index 1cdf44d897b2..194f46195c55 100644 --- a/telephony/java/com/android/internal/telephony/ISmsImplBase.java +++ b/telephony/java/com/android/internal/telephony/ISmsImplBase.java @@ -188,4 +188,10 @@ public class ISmsImplBase extends ISms.Stub { public String createAppSpecificSmsToken(int subId, String callingPkg, PendingIntent intent) { throw new UnsupportedOperationException(); } + + @Override + public int checkSmsShortCodeDestination( + int subid, String callingApk, String destAddress, String countryIso) { + throw new UnsupportedOperationException(); + } } diff --git a/telephony/java/com/android/internal/telephony/SmsCbEtwsInfo.java b/telephony/java/com/android/internal/telephony/SmsCbEtwsInfo.java index 14e02de276fd..15fbc404756f 100644 --- a/telephony/java/com/android/internal/telephony/SmsCbEtwsInfo.java +++ b/telephony/java/com/android/internal/telephony/SmsCbEtwsInfo.java @@ -18,10 +18,11 @@ package android.telephony; import android.os.Parcel; import android.os.Parcelable; -import android.text.format.Time; import com.android.internal.telephony.uicc.IccUtils; +import java.time.LocalDateTime; +import java.time.ZoneOffset; import java.util.Arrays; /** @@ -165,19 +166,21 @@ public class SmsCbEtwsInfo implements Parcelable { int timezoneOffset = IccUtils.gsmBcdByteToInt((byte) (tzByte & (~0x08))); timezoneOffset = ((tzByte & 0x08) == 0) ? timezoneOffset : -timezoneOffset; - - Time time = new Time(Time.TIMEZONE_UTC); - - // We only need to support years above 2000. - time.year = year + 2000; - time.month = month - 1; - time.monthDay = day; - time.hour = hour; - time.minute = minute; - time.second = second; - - // Timezone offset is in quarter hours. - return time.toMillis(true) - timezoneOffset * 15 * 60 * 1000; + // timezoneOffset is in quarter hours. + int timeZoneOffsetSeconds = timezoneOffset * 15 * 60; + + LocalDateTime localDateTime = LocalDateTime.of( + // We only need to support years above 2000. + year + 2000, + month /* 1-12 */, + day, + hour, + minute, + second); + + long epochSeconds = localDateTime.toEpochSecond(ZoneOffset.UTC) - timeZoneOffsetSeconds; + // Convert to milliseconds, ignore overflow. + return epochSeconds * 1000; } /** diff --git a/telephony/java/com/android/internal/telephony/cdma/BearerData.java b/telephony/java/com/android/internal/telephony/cdma/BearerData.java index 694cc69c2b3f..9e6f19f9243d 100644 --- a/telephony/java/com/android/internal/telephony/cdma/BearerData.java +++ b/telephony/java/com/android/internal/telephony/cdma/BearerData.java @@ -20,7 +20,6 @@ import android.content.res.Resources; import android.telephony.SmsCbCmasInfo; import android.telephony.cdma.CdmaSmsCbProgramData; import android.telephony.cdma.CdmaSmsCbProgramResults; -import android.text.format.Time; import android.telephony.Rlog; import com.android.internal.telephony.GsmAlphabet; @@ -32,8 +31,10 @@ import com.android.internal.telephony.uicc.IccUtils; import com.android.internal.util.BitwiseInputStream; import com.android.internal.util.BitwiseOutputStream; +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneId; import java.util.ArrayList; -import java.util.TimeZone; /** * An object to encode and decode CDMA SMS bearer data. @@ -228,10 +229,23 @@ public final class BearerData { /** * 6-byte-field, see 3GPP2 C.S0015-B, v2, 4.5.4 */ - public static class TimeStamp extends Time { + public static class TimeStamp { + + public int second; + public int minute; + public int hour; + public int monthDay; + + /** Month [0-11] */ + public int month; + + /** Full year. For example, 1970. */ + public int year; + + private ZoneId mZoneId; public TimeStamp() { - super(TimeZone.getDefault().getID()); // 3GPP2 timestamps use the local timezone + mZoneId = ZoneId.systemDefault(); // 3GPP2 timestamps use the local timezone } public static TimeStamp fromByteArray(byte[] data) { @@ -258,6 +272,14 @@ public final class BearerData { return ts; } + public long toMillis() { + LocalDateTime localDateTime = + LocalDateTime.of(year, month + 1, monthDay, hour, minute, second); + Instant instant = localDateTime.toInstant(mZoneId.getRules().getOffset(localDateTime)); + return instant.toEpochMilli(); + } + + @Override public String toString() { StringBuilder builder = new StringBuilder(); diff --git a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java index da4e3f87730f..e2a8913b91e6 100644 --- a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java +++ b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java @@ -718,7 +718,7 @@ public class SmsMessage extends SmsMessageBase { } if (mBearerData.msgCenterTimeStamp != null) { - mScTimeMillis = mBearerData.msgCenterTimeStamp.toMillis(true); + mScTimeMillis = mBearerData.msgCenterTimeStamp.toMillis(); } if (VDBG) Rlog.d(LOG_TAG, "SMS SC timestamp: " + mScTimeMillis); diff --git a/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java b/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java index a6156ff20912..5667387bdc1b 100644 --- a/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java +++ b/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java @@ -17,7 +17,6 @@ package com.android.internal.telephony.gsm; import android.telephony.PhoneNumberUtils; -import android.text.format.Time; import android.telephony.Rlog; import android.content.res.Resources; import android.text.TextUtils; @@ -33,6 +32,8 @@ import com.android.internal.telephony.Sms7BitEncodingTranslator; import java.io.ByteArrayOutputStream; import java.io.UnsupportedEncodingException; import java.text.ParseException; +import java.time.LocalDateTime; +import java.time.ZoneOffset; import static com.android.internal.telephony.SmsConstants.MessageClass; import static com.android.internal.telephony.SmsConstants.ENCODING_UNKNOWN; @@ -722,19 +723,21 @@ public class SmsMessage extends SmsMessageBase { int timezoneOffset = IccUtils.gsmBcdByteToInt((byte) (tzByte & (~0x08))); timezoneOffset = ((tzByte & 0x08) == 0) ? timezoneOffset : -timezoneOffset; - - Time time = new Time(Time.TIMEZONE_UTC); + // timezoneOffset is in quarter hours. + int timeZoneOffsetSeconds = timezoneOffset * 15 * 60; // It's 2006. Should I really support years < 2000? - time.year = year >= 90 ? year + 1900 : year + 2000; - time.month = month - 1; - time.monthDay = day; - time.hour = hour; - time.minute = minute; - time.second = second; - - // Timezone offset is in quarter hours. - return time.toMillis(true) - (timezoneOffset * 15 * 60 * 1000); + int fullYear = year >= 90 ? year + 1900 : year + 2000; + LocalDateTime localDateTime = LocalDateTime.of( + fullYear, + month /* 1-12 */, + day, + hour, + minute, + second); + long epochSeconds = localDateTime.toEpochSecond(ZoneOffset.UTC) - timeZoneOffsetSeconds; + // Convert to milliseconds. + return epochSeconds * 1000; } /** diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index 7317d625a202..9ac331c884b6 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -18,6 +18,7 @@ package com.android.server; import static android.content.pm.PackageManager.GET_PERMISSIONS; import static android.content.pm.PackageManager.MATCH_ANY_USER; +import static android.net.ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN; import static android.net.ConnectivityManager.CONNECTIVITY_ACTION; import static android.net.ConnectivityManager.NETID_UNSET; import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OFF; @@ -84,13 +85,13 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Matchers.anyInt; import static org.mockito.Mockito.any; import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.eq; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; @@ -145,6 +146,7 @@ import android.net.NetworkInfo.DetailedState; import android.net.NetworkMisc; import android.net.NetworkRequest; import android.net.NetworkSpecifier; +import android.net.NetworkStack; import android.net.NetworkStackClient; import android.net.NetworkState; import android.net.NetworkUtils; @@ -158,6 +160,7 @@ import android.net.shared.NetworkMonitorUtils; import android.net.shared.PrivateDnsConfig; import android.net.util.MultinetworkPolicyTracker; import android.os.Binder; +import android.os.Bundle; import android.os.ConditionVariable; import android.os.Handler; import android.os.HandlerThread; @@ -195,6 +198,7 @@ import com.android.server.connectivity.DefaultNetworkMetrics; import com.android.server.connectivity.IpConnectivityMetrics; import com.android.server.connectivity.MockableSystemProperties; import com.android.server.connectivity.Nat464Xlat; +import com.android.server.connectivity.NetworkNotificationManager.NotificationType; import com.android.server.connectivity.ProxyTracker; import com.android.server.connectivity.Tethering; import com.android.server.connectivity.Vpn; @@ -289,6 +293,7 @@ public class ConnectivityServiceTest { @Mock NetworkStackClient mNetworkStack; @Mock PackageManager mPackageManager; @Mock UserManager mUserManager; + @Mock NotificationManager mNotificationManager; private ArgumentCaptor<ResolverParamsParcel> mResolverParamsParcelCaptor = ArgumentCaptor.forClass(ResolverParamsParcel.class); @@ -358,7 +363,7 @@ public class ConnectivityServiceTest { @Override public Object getSystemService(String name) { if (Context.CONNECTIVITY_SERVICE.equals(name)) return mCm; - if (Context.NOTIFICATION_SERVICE.equals(name)) return mock(NotificationManager.class); + if (Context.NOTIFICATION_SERVICE.equals(name)) return mNotificationManager; if (Context.NETWORK_STACK_SERVICE.equals(name)) return mNetworkStack; if (Context.USER_SERVICE.equals(name)) return mUserManager; return super.getSystemService(name); @@ -378,7 +383,17 @@ public class ConnectivityServiceTest { public PackageManager getPackageManager() { return mPackageManager; } - } + + @Override + public void enforceCallingOrSelfPermission(String permission, String message) { + // The mainline permission can only be held if signed with the network stack certificate + // Skip testing for this permission. + if (NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK.equals(permission)) return; + // All other permissions should be held by the test or unnecessary: check as normal to + // make sure the code does not rely on unexpected permissions. + super.enforceCallingOrSelfPermission(permission, message); + } + } public void waitForIdle(int timeoutMsAsInt) { long timeoutMs = timeoutMsAsInt; @@ -2863,6 +2878,9 @@ public class ConnectivityServiceTest { // Expect NET_CAPABILITY_VALIDATED onAvailable callback. validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent); + // Expect no notification to be shown when captive portal disappears by itself + verify(mNotificationManager, never()).notifyAsUser( + anyString(), eq(NotificationType.LOGGED_IN.eventId), any(), any()); // Break network connectivity. // Expect NET_CAPABILITY_VALIDATED onLost callback. @@ -2892,6 +2910,8 @@ public class ConnectivityServiceTest { // Check that calling startCaptivePortalApp does nothing. final int fastTimeoutMs = 100; mCm.startCaptivePortalApp(wifiNetwork); + waitForIdle(); + verify(mWiFiNetworkAgent.mNetworkMonitor, never()).launchCaptivePortalApp(); mServiceContext.expectNoStartActivityIntent(fastTimeoutMs); // Turn into a captive portal. @@ -2902,14 +2922,26 @@ public class ConnectivityServiceTest { // Check that startCaptivePortalApp sends the expected command to NetworkMonitor. mCm.startCaptivePortalApp(wifiNetwork); - verify(mWiFiNetworkAgent.mNetworkMonitor, timeout(TIMEOUT_MS).times(1)) - .launchCaptivePortalApp(); + waitForIdle(); + verify(mWiFiNetworkAgent.mNetworkMonitor).launchCaptivePortalApp(); + + // NetworkMonitor uses startCaptivePortal(Network, Bundle) (startCaptivePortalAppInternal) + final Bundle testBundle = new Bundle(); + final String testKey = "testkey"; + final String testValue = "testvalue"; + testBundle.putString(testKey, testValue); + mCm.startCaptivePortalApp(wifiNetwork, testBundle); + final Intent signInIntent = mServiceContext.expectStartActivityIntent(TIMEOUT_MS); + assertEquals(ACTION_CAPTIVE_PORTAL_SIGN_IN, signInIntent.getAction()); + assertEquals(testValue, signInIntent.getStringExtra(testKey)); // Report that the captive portal is dismissed, and check that callbacks are fired mWiFiNetworkAgent.setNetworkValid(); mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid()); validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent); captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); + verify(mNotificationManager, times(1)).notifyAsUser(anyString(), + eq(NotificationType.LOGGED_IN.eventId), any(), eq(UserHandle.ALL)); mCm.unregisterNetworkCallback(validatedCallback); mCm.unregisterNetworkCallback(captivePortalCallback); diff --git a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java index 1682dd17c4a3..adaef40b51e3 100644 --- a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java +++ b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java @@ -239,7 +239,6 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { NetworkState[] states = new NetworkState[] {buildWifiState()}; expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); - expectBandwidthControlCheck(); mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states)); @@ -283,7 +282,6 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { NetworkState[] states = new NetworkState[] {buildWifiState()}; expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); - expectBandwidthControlCheck(); mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states)); @@ -357,7 +355,6 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { NetworkState[] states = new NetworkState[] {buildWifiState()}; expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); - expectBandwidthControlCheck(); mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states)); @@ -398,7 +395,6 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { NetworkState[] states = new NetworkState[] {buildMobile3gState(IMSI_1)}; expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); - expectBandwidthControlCheck(); mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states)); @@ -433,7 +429,6 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1536L, 12L, 512L, 4L, 0L) .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L) .addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 512L, 4L, 0L, 0L, 0L)); - expectBandwidthControlCheck(); mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states)); forcePollAndWaitForIdle(); @@ -473,7 +468,6 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { NetworkState[] states = new NetworkState[] {buildWifiState()}; expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); - expectBandwidthControlCheck(); mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states)); @@ -531,7 +525,6 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { NetworkState[] states = new NetworkState[] {buildMobile3gState(IMSI_1)}; expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); - expectBandwidthControlCheck(); mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states)); @@ -558,7 +551,6 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1) .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1024L, 8L, 1024L, 8L, 0L) .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L)); - expectBandwidthControlCheck(); mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states)); forcePollAndWaitForIdle(); @@ -588,7 +580,6 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { NetworkState[] states = new NetworkState[] {buildWifiState()}; expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); - expectBandwidthControlCheck(); mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states)); @@ -646,7 +637,6 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { NetworkState[] states = new NetworkState[] {buildWifiState()}; expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); - expectBandwidthControlCheck(); mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states)); @@ -690,7 +680,6 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); - expectBandwidthControlCheck(); mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states)); @@ -740,7 +729,6 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { NetworkState[] states = new NetworkState[] {buildWifiState()}; expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); - expectBandwidthControlCheck(); mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states)); @@ -797,7 +785,6 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { NetworkState[] states = new NetworkState[] {buildWifiState(true /* isMetered */)}; expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); - expectBandwidthControlCheck(); mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states)); @@ -837,7 +824,6 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { new NetworkState[] {buildMobile3gState(IMSI_1, true /* isRoaming */)}; expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); - expectBandwidthControlCheck(); mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states)); @@ -875,7 +861,6 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { NetworkState[] states = new NetworkState[] {buildMobile3gState(IMSI_1)}; expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); - expectBandwidthControlCheck(); mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states)); @@ -916,7 +901,6 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { NetworkState[] states = new NetworkState[] {buildWifiState()}; expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); - expectBandwidthControlCheck(); mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states)); @@ -1057,7 +1041,6 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { private void expectSystemReady() throws Exception { expectNetworkStatsSummary(buildEmptyStats()); - expectBandwidthControlCheck(); } private String getActiveIface(NetworkState... states) throws Exception { @@ -1125,10 +1108,6 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { when(mSettings.getUidTagPersistBytes(anyLong())).thenReturn(MB_IN_BYTES); } - private void expectBandwidthControlCheck() throws Exception { - when(mNetManager.isBandwidthControlEnabled()).thenReturn(true); - } - private void assertStatsFilesExist(boolean exist) { final File basePath = new File(mStatsDir, "netstats"); if (exist) { |