Loading packages/Tethering/res/values-mcc310-mnc004/config.xml +3 −0 Original line number Original line Diff line number Diff line Loading @@ -17,4 +17,7 @@ <!-- Delay(millisecond) to show no upstream notification after there's no Backhaul. Set delay to <!-- Delay(millisecond) to show no upstream notification after there's no Backhaul. Set delay to "0" for disable this feature. --> "0" for disable this feature. --> <integer name="delay_to_show_no_upstream_after_no_backhaul">5000</integer> <integer name="delay_to_show_no_upstream_after_no_backhaul">5000</integer> <!-- Config for showing upstream roaming notification. --> <bool name="config_upstream_roaming_notification">true</bool> </resources> </resources> No newline at end of file packages/Tethering/res/values-mcc311-mnc480/config.xml +3 −0 Original line number Original line Diff line number Diff line Loading @@ -17,4 +17,7 @@ <!-- Delay(millisecond) to show no upstream notification after there's no Backhaul. Set delay to <!-- Delay(millisecond) to show no upstream notification after there's no Backhaul. Set delay to "0" for disable this feature. --> "0" for disable this feature. --> <integer name="delay_to_show_no_upstream_after_no_backhaul">5000</integer> <integer name="delay_to_show_no_upstream_after_no_backhaul">5000</integer> <!-- Config for showing upstream roaming notification. --> <bool name="config_upstream_roaming_notification">true</bool> </resources> </resources> No newline at end of file packages/Tethering/res/values/config.xml +5 −0 Original line number Original line Diff line number Diff line Loading @@ -208,4 +208,9 @@ <!-- Delay(millisecond) to show no upstream notification after there's no Backhaul. Set delay to <!-- Delay(millisecond) to show no upstream notification after there's no Backhaul. Set delay to "-1" for disable this feature. --> "-1" for disable this feature. --> <integer name="delay_to_show_no_upstream_after_no_backhaul">-1</integer> <integer name="delay_to_show_no_upstream_after_no_backhaul">-1</integer> <!-- Cellular roaming notification is shown when upstream is cellular network and in roaming state. --> <!-- Config for showing upstream roaming notification. --> <bool name="config_upstream_roaming_notification">false</bool> </resources> </resources> packages/Tethering/src/com/android/networkstack/tethering/Tethering.java +13 −4 Original line number Original line Diff line number Diff line Loading @@ -81,6 +81,7 @@ import android.net.IpPrefix; import android.net.LinkAddress; import android.net.LinkAddress; import android.net.LinkProperties; import android.net.LinkProperties; import android.net.Network; import android.net.Network; import android.net.NetworkCapabilities; import android.net.NetworkInfo; import android.net.NetworkInfo; import android.net.TetherStatesParcel; import android.net.TetherStatesParcel; import android.net.TetheredClient; import android.net.TetheredClient; Loading Loading @@ -1476,7 +1477,7 @@ public class Tethering { if (mTetherUpstream != newUpstream) { if (mTetherUpstream != newUpstream) { mTetherUpstream = newUpstream; mTetherUpstream = newUpstream; mUpstreamNetworkMonitor.setCurrentUpstream(mTetherUpstream); mUpstreamNetworkMonitor.setCurrentUpstream(mTetherUpstream); reportUpstreamChanged(mTetherUpstream); reportUpstreamChanged(ns); } } } } Loading Loading @@ -1598,7 +1599,8 @@ public class Tethering { } } } } private void handleUpstreamNetworkMonitorCallback(int arg1, Object o) { @VisibleForTesting void handleUpstreamNetworkMonitorCallback(int arg1, Object o) { if (arg1 == UpstreamNetworkMonitor.NOTIFY_LOCAL_PREFIXES) { if (arg1 == UpstreamNetworkMonitor.NOTIFY_LOCAL_PREFIXES) { mOffload.sendOffloadExemptPrefixes((Set<IpPrefix>) o); mOffload.sendOffloadExemptPrefixes((Set<IpPrefix>) o); return; return; Loading @@ -1624,6 +1626,9 @@ public class Tethering { switch (arg1) { switch (arg1) { case UpstreamNetworkMonitor.EVENT_ON_CAPABILITIES: case UpstreamNetworkMonitor.EVENT_ON_CAPABILITIES: if (ns.network.equals(mTetherUpstream)) { mNotificationUpdater.onUpstreamCapabilitiesChanged(ns.networkCapabilities); } handleNewUpstreamNetworkState(ns); handleNewUpstreamNetworkState(ns); break; break; case UpstreamNetworkMonitor.EVENT_ON_LINKPROPERTIES: case UpstreamNetworkMonitor.EVENT_ON_LINKPROPERTIES: Loading Loading @@ -2009,8 +2014,10 @@ public class Tethering { }); }); } } private void reportUpstreamChanged(Network network) { private void reportUpstreamChanged(UpstreamNetworkState ns) { final int length = mTetheringEventCallbacks.beginBroadcast(); final int length = mTetheringEventCallbacks.beginBroadcast(); final Network network = (ns != null) ? ns.network : null; final NetworkCapabilities capabilities = (ns != null) ? ns.networkCapabilities : null; try { try { for (int i = 0; i < length; i++) { for (int i = 0; i < length; i++) { try { try { Loading @@ -2022,7 +2029,9 @@ public class Tethering { } finally { } finally { mTetheringEventCallbacks.finishBroadcast(); mTetheringEventCallbacks.finishBroadcast(); } } mNotificationUpdater.onUpstreamNetworkChanged(network); // Need to notify capabilities change after upstream network changed because new network's // capabilities should be checked every time. mNotificationUpdater.onUpstreamCapabilitiesChanged(capabilities); } } private void reportConfigurationChanged(TetheringConfigurationParcel config) { private void reportConfigurationChanged(TetheringConfigurationParcel config) { Loading packages/Tethering/src/com/android/networkstack/tethering/TetheringNotificationUpdater.java +80 −22 Original line number Original line Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.networkstack.tethering; package com.android.networkstack.tethering; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING; import static android.net.TetheringManager.TETHERING_BLUETOOTH; import static android.net.TetheringManager.TETHERING_BLUETOOTH; import static android.net.TetheringManager.TETHERING_USB; import static android.net.TetheringManager.TETHERING_USB; import static android.net.TetheringManager.TETHERING_WIFI; import static android.net.TetheringManager.TETHERING_WIFI; Loading @@ -30,7 +31,7 @@ import android.content.Context; import android.content.Intent; import android.content.Intent; import android.content.res.Configuration; import android.content.res.Configuration; import android.content.res.Resources; import android.content.res.Resources; import android.net.Network; import android.net.NetworkCapabilities; import android.os.Handler; import android.os.Handler; import android.os.Looper; import android.os.Looper; import android.os.Message; import android.os.Message; Loading @@ -50,6 +51,9 @@ import androidx.annotation.Nullable; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** /** * A class to display tethering-related notifications. * A class to display tethering-related notifications. * * Loading Loading @@ -82,6 +86,9 @@ public class TetheringNotificationUpdater { // Id to update and cancel no upstream notification. Must be unique within the tethering app. // Id to update and cancel no upstream notification. Must be unique within the tethering app. @VisibleForTesting @VisibleForTesting static final int NO_UPSTREAM_NOTIFICATION_ID = 1002; static final int NO_UPSTREAM_NOTIFICATION_ID = 1002; // Id to update and cancel roaming notification. Must be unique within the tethering app. @VisibleForTesting static final int ROAMING_NOTIFICATION_ID = 1003; @VisibleForTesting @VisibleForTesting static final int NO_ICON_ID = 0; static final int NO_ICON_ID = 0; @VisibleForTesting @VisibleForTesting Loading @@ -95,13 +102,14 @@ public class TetheringNotificationUpdater { private final Handler mHandler; private final Handler mHandler; // WARNING : the constructor is called on a different thread. Thread safety therefore // WARNING : the constructor is called on a different thread. Thread safety therefore // relies on these values being initialized to 0 or false, and not any other value. If you need // relies on these values being initialized to 0, false or null, and not any other value. If you // to change this, you will need to change the thread where the constructor is invoked, // need to change this, you will need to change the thread where the constructor is invoked, or // or to introduce synchronization. // to introduce synchronization. // Downstream type is one of ConnectivityManager.TETHERING_* constants, 0 1 or 2. // Downstream type is one of ConnectivityManager.TETHERING_* constants, 0 1 or 2. // This value has to be made 1 2 and 4, and OR'd with the others. // This value has to be made 1 2 and 4, and OR'd with the others. private int mDownstreamTypesMask = DOWNSTREAM_NONE; private int mDownstreamTypesMask = DOWNSTREAM_NONE; private boolean mNoUpstream = false; private boolean mNoUpstream = false; private boolean mRoaming = false; // WARNING : this value is not able to being initialized to 0 and must have volatile because // WARNING : this value is not able to being initialized to 0 and must have volatile because // telephony service is not guaranteed that is up before tethering service starts. If telephony // telephony service is not guaranteed that is up before tethering service starts. If telephony Loading @@ -110,7 +118,13 @@ public class TetheringNotificationUpdater { // INVALID_SUBSCRIPTION_ID. // INVALID_SUBSCRIPTION_ID. private volatile int mActiveDataSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; private volatile int mActiveDataSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; @IntDef({ENABLE_NOTIFICATION_ID, RESTRICTED_NOTIFICATION_ID, NO_UPSTREAM_NOTIFICATION_ID}) @Retention(RetentionPolicy.SOURCE) @IntDef(value = { ENABLE_NOTIFICATION_ID, RESTRICTED_NOTIFICATION_ID, NO_UPSTREAM_NOTIFICATION_ID, ROAMING_NOTIFICATION_ID }) @interface NotificationId {} @interface NotificationId {} private static final class MccMncOverrideInfo { private static final class MccMncOverrideInfo { Loading Loading @@ -160,26 +174,22 @@ public class TetheringNotificationUpdater { /** Called when downstream has changed */ /** Called when downstream has changed */ public void onDownstreamChanged(@IntRange(from = 0, to = 7) final int downstreamTypesMask) { public void onDownstreamChanged(@IntRange(from = 0, to = 7) final int downstreamTypesMask) { if (mDownstreamTypesMask == downstreamTypesMask) return; updateActiveNotifications( mDownstreamTypesMask = downstreamTypesMask; mActiveDataSubId, downstreamTypesMask, mNoUpstream, mRoaming); updateEnableNotification(); updateNoUpstreamNotification(); } } /** Called when active data subscription id changed */ /** Called when active data subscription id changed */ public void onActiveDataSubscriptionIdChanged(final int subId) { public void onActiveDataSubscriptionIdChanged(final int subId) { if (mActiveDataSubId == subId) return; updateActiveNotifications(subId, mDownstreamTypesMask, mNoUpstream, mRoaming); mActiveDataSubId = subId; updateEnableNotification(); updateNoUpstreamNotification(); } } /** Called when upstream network changed */ /** Called when upstream network capabilities changed */ public void onUpstreamNetworkChanged(@Nullable final Network network) { public void onUpstreamCapabilitiesChanged(@Nullable final NetworkCapabilities capabilities) { final boolean isNoUpstream = (network == null); final boolean isNoUpstream = (capabilities == null); if (mNoUpstream == isNoUpstream) return; final boolean isRoaming = capabilities != null mNoUpstream = isNoUpstream; && !capabilities.hasCapability(NET_CAPABILITY_NOT_ROAMING); updateNoUpstreamNotification(); updateActiveNotifications( mActiveDataSubId, mDownstreamTypesMask, isNoUpstream, isRoaming); } } @NonNull @NonNull Loading Loading @@ -208,6 +218,25 @@ public class TetheringNotificationUpdater { return res; return res; } } private void updateActiveNotifications(final int subId, final int downstreamTypes, final boolean noUpstream, final boolean isRoaming) { final boolean tetheringActiveChanged = (downstreamTypes == DOWNSTREAM_NONE) != (mDownstreamTypesMask == DOWNSTREAM_NONE); final boolean subIdChanged = subId != mActiveDataSubId; final boolean downstreamChanged = downstreamTypes != mDownstreamTypesMask; final boolean upstreamChanged = noUpstream != mNoUpstream; final boolean roamingChanged = isRoaming != mRoaming; final boolean updateAll = tetheringActiveChanged || subIdChanged; mActiveDataSubId = subId; mDownstreamTypesMask = downstreamTypes; mNoUpstream = noUpstream; mRoaming = isRoaming; if (updateAll || downstreamChanged) updateEnableNotification(); if (updateAll || upstreamChanged) updateNoUpstreamNotification(); if (updateAll || roamingChanged) updateRoamingNotification(); } private void updateEnableNotification() { private void updateEnableNotification() { final boolean tetheringInactive = mDownstreamTypesMask == DOWNSTREAM_NONE; final boolean tetheringInactive = mDownstreamTypesMask == DOWNSTREAM_NONE; Loading @@ -219,14 +248,20 @@ public class TetheringNotificationUpdater { private void updateNoUpstreamNotification() { private void updateNoUpstreamNotification() { final boolean tetheringInactive = mDownstreamTypesMask == DOWNSTREAM_NONE; final boolean tetheringInactive = mDownstreamTypesMask == DOWNSTREAM_NONE; if (tetheringInactive if (tetheringInactive || !mNoUpstream || setupNoUpstreamNotification() == NO_NOTIFY) { || !mNoUpstream || setupNoUpstreamNotification() == NO_NOTIFY) { clearNotification(NO_UPSTREAM_NOTIFICATION_ID); clearNotification(NO_UPSTREAM_NOTIFICATION_ID); mHandler.removeMessages(EVENT_SHOW_NO_UPSTREAM); mHandler.removeMessages(EVENT_SHOW_NO_UPSTREAM); } } } } private void updateRoamingNotification() { final boolean tetheringInactive = mDownstreamTypesMask == DOWNSTREAM_NONE; if (tetheringInactive || !mRoaming || setupRoamingNotification() == NO_NOTIFY) { clearNotification(ROAMING_NOTIFICATION_ID); } } @VisibleForTesting @VisibleForTesting void tetheringRestrictionLifted() { void tetheringRestrictionLifted() { clearNotification(RESTRICTED_NOTIFICATION_ID); clearNotification(RESTRICTED_NOTIFICATION_ID); Loading Loading @@ -333,6 +368,29 @@ public class TetheringNotificationUpdater { return icons; return icons; } } private boolean setupRoamingNotification() { final Resources res = getResourcesForSubId(mContext, mActiveDataSubId); final boolean upstreamRoamingNotification = res.getBoolean(R.bool.config_upstream_roaming_notification); if (!upstreamRoamingNotification) return NO_NOTIFY; final String title = res.getString(R.string.upstream_roaming_notification_title); final String message = res.getString(R.string.upstream_roaming_notification_message); if (isEmpty(title) || isEmpty(message)) return NO_NOTIFY; final PendingIntent pi = PendingIntent.getActivity( mContext.createContextAsUser(UserHandle.CURRENT, 0 /* flags */), 0 /* requestCode */, new Intent(Settings.ACTION_TETHER_SETTINGS), Intent.FLAG_ACTIVITY_NEW_TASK, null /* options */); showNotification(R.drawable.stat_sys_tether_general, title, message, ROAMING_NOTIFICATION_ID, pi, new Action[0]); return NOTIFY_DONE; } private boolean setupNoUpstreamNotification() { private boolean setupNoUpstreamNotification() { final Resources res = getResourcesForSubId(mContext, mActiveDataSubId); final Resources res = getResourcesForSubId(mContext, mActiveDataSubId); final int delayToShowUpstreamNotification = final int delayToShowUpstreamNotification = Loading Loading
packages/Tethering/res/values-mcc310-mnc004/config.xml +3 −0 Original line number Original line Diff line number Diff line Loading @@ -17,4 +17,7 @@ <!-- Delay(millisecond) to show no upstream notification after there's no Backhaul. Set delay to <!-- Delay(millisecond) to show no upstream notification after there's no Backhaul. Set delay to "0" for disable this feature. --> "0" for disable this feature. --> <integer name="delay_to_show_no_upstream_after_no_backhaul">5000</integer> <integer name="delay_to_show_no_upstream_after_no_backhaul">5000</integer> <!-- Config for showing upstream roaming notification. --> <bool name="config_upstream_roaming_notification">true</bool> </resources> </resources> No newline at end of file
packages/Tethering/res/values-mcc311-mnc480/config.xml +3 −0 Original line number Original line Diff line number Diff line Loading @@ -17,4 +17,7 @@ <!-- Delay(millisecond) to show no upstream notification after there's no Backhaul. Set delay to <!-- Delay(millisecond) to show no upstream notification after there's no Backhaul. Set delay to "0" for disable this feature. --> "0" for disable this feature. --> <integer name="delay_to_show_no_upstream_after_no_backhaul">5000</integer> <integer name="delay_to_show_no_upstream_after_no_backhaul">5000</integer> <!-- Config for showing upstream roaming notification. --> <bool name="config_upstream_roaming_notification">true</bool> </resources> </resources> No newline at end of file
packages/Tethering/res/values/config.xml +5 −0 Original line number Original line Diff line number Diff line Loading @@ -208,4 +208,9 @@ <!-- Delay(millisecond) to show no upstream notification after there's no Backhaul. Set delay to <!-- Delay(millisecond) to show no upstream notification after there's no Backhaul. Set delay to "-1" for disable this feature. --> "-1" for disable this feature. --> <integer name="delay_to_show_no_upstream_after_no_backhaul">-1</integer> <integer name="delay_to_show_no_upstream_after_no_backhaul">-1</integer> <!-- Cellular roaming notification is shown when upstream is cellular network and in roaming state. --> <!-- Config for showing upstream roaming notification. --> <bool name="config_upstream_roaming_notification">false</bool> </resources> </resources>
packages/Tethering/src/com/android/networkstack/tethering/Tethering.java +13 −4 Original line number Original line Diff line number Diff line Loading @@ -81,6 +81,7 @@ import android.net.IpPrefix; import android.net.LinkAddress; import android.net.LinkAddress; import android.net.LinkProperties; import android.net.LinkProperties; import android.net.Network; import android.net.Network; import android.net.NetworkCapabilities; import android.net.NetworkInfo; import android.net.NetworkInfo; import android.net.TetherStatesParcel; import android.net.TetherStatesParcel; import android.net.TetheredClient; import android.net.TetheredClient; Loading Loading @@ -1476,7 +1477,7 @@ public class Tethering { if (mTetherUpstream != newUpstream) { if (mTetherUpstream != newUpstream) { mTetherUpstream = newUpstream; mTetherUpstream = newUpstream; mUpstreamNetworkMonitor.setCurrentUpstream(mTetherUpstream); mUpstreamNetworkMonitor.setCurrentUpstream(mTetherUpstream); reportUpstreamChanged(mTetherUpstream); reportUpstreamChanged(ns); } } } } Loading Loading @@ -1598,7 +1599,8 @@ public class Tethering { } } } } private void handleUpstreamNetworkMonitorCallback(int arg1, Object o) { @VisibleForTesting void handleUpstreamNetworkMonitorCallback(int arg1, Object o) { if (arg1 == UpstreamNetworkMonitor.NOTIFY_LOCAL_PREFIXES) { if (arg1 == UpstreamNetworkMonitor.NOTIFY_LOCAL_PREFIXES) { mOffload.sendOffloadExemptPrefixes((Set<IpPrefix>) o); mOffload.sendOffloadExemptPrefixes((Set<IpPrefix>) o); return; return; Loading @@ -1624,6 +1626,9 @@ public class Tethering { switch (arg1) { switch (arg1) { case UpstreamNetworkMonitor.EVENT_ON_CAPABILITIES: case UpstreamNetworkMonitor.EVENT_ON_CAPABILITIES: if (ns.network.equals(mTetherUpstream)) { mNotificationUpdater.onUpstreamCapabilitiesChanged(ns.networkCapabilities); } handleNewUpstreamNetworkState(ns); handleNewUpstreamNetworkState(ns); break; break; case UpstreamNetworkMonitor.EVENT_ON_LINKPROPERTIES: case UpstreamNetworkMonitor.EVENT_ON_LINKPROPERTIES: Loading Loading @@ -2009,8 +2014,10 @@ public class Tethering { }); }); } } private void reportUpstreamChanged(Network network) { private void reportUpstreamChanged(UpstreamNetworkState ns) { final int length = mTetheringEventCallbacks.beginBroadcast(); final int length = mTetheringEventCallbacks.beginBroadcast(); final Network network = (ns != null) ? ns.network : null; final NetworkCapabilities capabilities = (ns != null) ? ns.networkCapabilities : null; try { try { for (int i = 0; i < length; i++) { for (int i = 0; i < length; i++) { try { try { Loading @@ -2022,7 +2029,9 @@ public class Tethering { } finally { } finally { mTetheringEventCallbacks.finishBroadcast(); mTetheringEventCallbacks.finishBroadcast(); } } mNotificationUpdater.onUpstreamNetworkChanged(network); // Need to notify capabilities change after upstream network changed because new network's // capabilities should be checked every time. mNotificationUpdater.onUpstreamCapabilitiesChanged(capabilities); } } private void reportConfigurationChanged(TetheringConfigurationParcel config) { private void reportConfigurationChanged(TetheringConfigurationParcel config) { Loading
packages/Tethering/src/com/android/networkstack/tethering/TetheringNotificationUpdater.java +80 −22 Original line number Original line Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.networkstack.tethering; package com.android.networkstack.tethering; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING; import static android.net.TetheringManager.TETHERING_BLUETOOTH; import static android.net.TetheringManager.TETHERING_BLUETOOTH; import static android.net.TetheringManager.TETHERING_USB; import static android.net.TetheringManager.TETHERING_USB; import static android.net.TetheringManager.TETHERING_WIFI; import static android.net.TetheringManager.TETHERING_WIFI; Loading @@ -30,7 +31,7 @@ import android.content.Context; import android.content.Intent; import android.content.Intent; import android.content.res.Configuration; import android.content.res.Configuration; import android.content.res.Resources; import android.content.res.Resources; import android.net.Network; import android.net.NetworkCapabilities; import android.os.Handler; import android.os.Handler; import android.os.Looper; import android.os.Looper; import android.os.Message; import android.os.Message; Loading @@ -50,6 +51,9 @@ import androidx.annotation.Nullable; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** /** * A class to display tethering-related notifications. * A class to display tethering-related notifications. * * Loading Loading @@ -82,6 +86,9 @@ public class TetheringNotificationUpdater { // Id to update and cancel no upstream notification. Must be unique within the tethering app. // Id to update and cancel no upstream notification. Must be unique within the tethering app. @VisibleForTesting @VisibleForTesting static final int NO_UPSTREAM_NOTIFICATION_ID = 1002; static final int NO_UPSTREAM_NOTIFICATION_ID = 1002; // Id to update and cancel roaming notification. Must be unique within the tethering app. @VisibleForTesting static final int ROAMING_NOTIFICATION_ID = 1003; @VisibleForTesting @VisibleForTesting static final int NO_ICON_ID = 0; static final int NO_ICON_ID = 0; @VisibleForTesting @VisibleForTesting Loading @@ -95,13 +102,14 @@ public class TetheringNotificationUpdater { private final Handler mHandler; private final Handler mHandler; // WARNING : the constructor is called on a different thread. Thread safety therefore // WARNING : the constructor is called on a different thread. Thread safety therefore // relies on these values being initialized to 0 or false, and not any other value. If you need // relies on these values being initialized to 0, false or null, and not any other value. If you // to change this, you will need to change the thread where the constructor is invoked, // need to change this, you will need to change the thread where the constructor is invoked, or // or to introduce synchronization. // to introduce synchronization. // Downstream type is one of ConnectivityManager.TETHERING_* constants, 0 1 or 2. // Downstream type is one of ConnectivityManager.TETHERING_* constants, 0 1 or 2. // This value has to be made 1 2 and 4, and OR'd with the others. // This value has to be made 1 2 and 4, and OR'd with the others. private int mDownstreamTypesMask = DOWNSTREAM_NONE; private int mDownstreamTypesMask = DOWNSTREAM_NONE; private boolean mNoUpstream = false; private boolean mNoUpstream = false; private boolean mRoaming = false; // WARNING : this value is not able to being initialized to 0 and must have volatile because // WARNING : this value is not able to being initialized to 0 and must have volatile because // telephony service is not guaranteed that is up before tethering service starts. If telephony // telephony service is not guaranteed that is up before tethering service starts. If telephony Loading @@ -110,7 +118,13 @@ public class TetheringNotificationUpdater { // INVALID_SUBSCRIPTION_ID. // INVALID_SUBSCRIPTION_ID. private volatile int mActiveDataSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; private volatile int mActiveDataSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; @IntDef({ENABLE_NOTIFICATION_ID, RESTRICTED_NOTIFICATION_ID, NO_UPSTREAM_NOTIFICATION_ID}) @Retention(RetentionPolicy.SOURCE) @IntDef(value = { ENABLE_NOTIFICATION_ID, RESTRICTED_NOTIFICATION_ID, NO_UPSTREAM_NOTIFICATION_ID, ROAMING_NOTIFICATION_ID }) @interface NotificationId {} @interface NotificationId {} private static final class MccMncOverrideInfo { private static final class MccMncOverrideInfo { Loading Loading @@ -160,26 +174,22 @@ public class TetheringNotificationUpdater { /** Called when downstream has changed */ /** Called when downstream has changed */ public void onDownstreamChanged(@IntRange(from = 0, to = 7) final int downstreamTypesMask) { public void onDownstreamChanged(@IntRange(from = 0, to = 7) final int downstreamTypesMask) { if (mDownstreamTypesMask == downstreamTypesMask) return; updateActiveNotifications( mDownstreamTypesMask = downstreamTypesMask; mActiveDataSubId, downstreamTypesMask, mNoUpstream, mRoaming); updateEnableNotification(); updateNoUpstreamNotification(); } } /** Called when active data subscription id changed */ /** Called when active data subscription id changed */ public void onActiveDataSubscriptionIdChanged(final int subId) { public void onActiveDataSubscriptionIdChanged(final int subId) { if (mActiveDataSubId == subId) return; updateActiveNotifications(subId, mDownstreamTypesMask, mNoUpstream, mRoaming); mActiveDataSubId = subId; updateEnableNotification(); updateNoUpstreamNotification(); } } /** Called when upstream network changed */ /** Called when upstream network capabilities changed */ public void onUpstreamNetworkChanged(@Nullable final Network network) { public void onUpstreamCapabilitiesChanged(@Nullable final NetworkCapabilities capabilities) { final boolean isNoUpstream = (network == null); final boolean isNoUpstream = (capabilities == null); if (mNoUpstream == isNoUpstream) return; final boolean isRoaming = capabilities != null mNoUpstream = isNoUpstream; && !capabilities.hasCapability(NET_CAPABILITY_NOT_ROAMING); updateNoUpstreamNotification(); updateActiveNotifications( mActiveDataSubId, mDownstreamTypesMask, isNoUpstream, isRoaming); } } @NonNull @NonNull Loading Loading @@ -208,6 +218,25 @@ public class TetheringNotificationUpdater { return res; return res; } } private void updateActiveNotifications(final int subId, final int downstreamTypes, final boolean noUpstream, final boolean isRoaming) { final boolean tetheringActiveChanged = (downstreamTypes == DOWNSTREAM_NONE) != (mDownstreamTypesMask == DOWNSTREAM_NONE); final boolean subIdChanged = subId != mActiveDataSubId; final boolean downstreamChanged = downstreamTypes != mDownstreamTypesMask; final boolean upstreamChanged = noUpstream != mNoUpstream; final boolean roamingChanged = isRoaming != mRoaming; final boolean updateAll = tetheringActiveChanged || subIdChanged; mActiveDataSubId = subId; mDownstreamTypesMask = downstreamTypes; mNoUpstream = noUpstream; mRoaming = isRoaming; if (updateAll || downstreamChanged) updateEnableNotification(); if (updateAll || upstreamChanged) updateNoUpstreamNotification(); if (updateAll || roamingChanged) updateRoamingNotification(); } private void updateEnableNotification() { private void updateEnableNotification() { final boolean tetheringInactive = mDownstreamTypesMask == DOWNSTREAM_NONE; final boolean tetheringInactive = mDownstreamTypesMask == DOWNSTREAM_NONE; Loading @@ -219,14 +248,20 @@ public class TetheringNotificationUpdater { private void updateNoUpstreamNotification() { private void updateNoUpstreamNotification() { final boolean tetheringInactive = mDownstreamTypesMask == DOWNSTREAM_NONE; final boolean tetheringInactive = mDownstreamTypesMask == DOWNSTREAM_NONE; if (tetheringInactive if (tetheringInactive || !mNoUpstream || setupNoUpstreamNotification() == NO_NOTIFY) { || !mNoUpstream || setupNoUpstreamNotification() == NO_NOTIFY) { clearNotification(NO_UPSTREAM_NOTIFICATION_ID); clearNotification(NO_UPSTREAM_NOTIFICATION_ID); mHandler.removeMessages(EVENT_SHOW_NO_UPSTREAM); mHandler.removeMessages(EVENT_SHOW_NO_UPSTREAM); } } } } private void updateRoamingNotification() { final boolean tetheringInactive = mDownstreamTypesMask == DOWNSTREAM_NONE; if (tetheringInactive || !mRoaming || setupRoamingNotification() == NO_NOTIFY) { clearNotification(ROAMING_NOTIFICATION_ID); } } @VisibleForTesting @VisibleForTesting void tetheringRestrictionLifted() { void tetheringRestrictionLifted() { clearNotification(RESTRICTED_NOTIFICATION_ID); clearNotification(RESTRICTED_NOTIFICATION_ID); Loading Loading @@ -333,6 +368,29 @@ public class TetheringNotificationUpdater { return icons; return icons; } } private boolean setupRoamingNotification() { final Resources res = getResourcesForSubId(mContext, mActiveDataSubId); final boolean upstreamRoamingNotification = res.getBoolean(R.bool.config_upstream_roaming_notification); if (!upstreamRoamingNotification) return NO_NOTIFY; final String title = res.getString(R.string.upstream_roaming_notification_title); final String message = res.getString(R.string.upstream_roaming_notification_message); if (isEmpty(title) || isEmpty(message)) return NO_NOTIFY; final PendingIntent pi = PendingIntent.getActivity( mContext.createContextAsUser(UserHandle.CURRENT, 0 /* flags */), 0 /* requestCode */, new Intent(Settings.ACTION_TETHER_SETTINGS), Intent.FLAG_ACTIVITY_NEW_TASK, null /* options */); showNotification(R.drawable.stat_sys_tether_general, title, message, ROAMING_NOTIFICATION_ID, pi, new Action[0]); return NOTIFY_DONE; } private boolean setupNoUpstreamNotification() { private boolean setupNoUpstreamNotification() { final Resources res = getResourcesForSubId(mContext, mActiveDataSubId); final Resources res = getResourcesForSubId(mContext, mActiveDataSubId); final int delayToShowUpstreamNotification = final int delayToShowUpstreamNotification = Loading