diff options
15 files changed, 191 insertions, 62 deletions
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto index 7a016522d597..36b46c3d03a3 100644 --- a/cmds/statsd/src/atoms.proto +++ b/cmds/statsd/src/atoms.proto @@ -5178,6 +5178,12 @@ message DataUsageBytesTransfer { // record is combined across opportunistic data subscriptions. // See {@link SubscriptionManager#setOpportunistic}. optional DataSubscriptionState opportunistic_data_sub = 10; + + // Indicate whether NR is connected, server side could use this with RAT type to determine if + // the record is for 5G NSA (Non Stand Alone) mode, where the primary cell is still LTE and + // network allocates a secondary 5G cell so telephony reports RAT = LTE along with NR state as + // connected. + optional bool is_nr_connected = 11; } /** diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java index eba7ff348328..7234eb1d81cd 100644 --- a/core/java/android/net/NetworkTemplate.java +++ b/core/java/android/net/NetworkTemplate.java @@ -87,6 +87,15 @@ public class NetworkTemplate implements Parcelable { * @hide */ public static final int NETWORK_TYPE_ALL = -1; + /** + * Virtual RAT type to represent 5G NSA (Non Stand Alone) mode, where the primary cell is + * still LTE and network allocates a secondary 5G cell so telephony reports RAT = LTE along + * with NR state as connected. This should not be overlapped with any of the + * {@code TelephonyManager.NETWORK_TYPE_*} constants. + * + * @hide + */ + public static final int NETWORK_TYPE_5G_NSA = -2; private static boolean isKnownMatchRule(final int rule) { switch (rule) { @@ -475,6 +484,9 @@ public class NetworkTemplate implements Parcelable { return TelephonyManager.NETWORK_TYPE_LTE; case TelephonyManager.NETWORK_TYPE_NR: return TelephonyManager.NETWORK_TYPE_NR; + // Virtual RAT type for 5G NSA mode, see {@link NetworkTemplate#NETWORK_TYPE_5G_NSA}. + case NetworkTemplate.NETWORK_TYPE_5G_NSA: + return NetworkTemplate.NETWORK_TYPE_5G_NSA; default: return TelephonyManager.NETWORK_TYPE_UNKNOWN; } diff --git a/core/java/android/view/ImeFocusController.java b/core/java/android/view/ImeFocusController.java index ad43f9556d8d..92772c1d7a44 100644 --- a/core/java/android/view/ImeFocusController.java +++ b/core/java/android/view/ImeFocusController.java @@ -125,10 +125,10 @@ public final class ImeFocusController { final View viewForWindowFocus = focusedView != null ? focusedView : mViewRootImpl.mView; onViewFocusChanged(viewForWindowFocus, true); - // Starting new input when the next focused view is same as served view but the - // editor is not aligned with the same editor or editor is inactive. - final boolean nextFocusIsServedView = mServedView != null && mServedView == focusedView; - if (nextFocusIsServedView && !immDelegate.isSameEditorAndAcceptingText(focusedView)) { + // Starting new input when the next focused view is same as served view but the currently + // active connection (if any) is not associated with it. + final boolean nextFocusIsServedView = mServedView == viewForWindowFocus; + if (nextFocusIsServedView && !immDelegate.hasActiveConnection(viewForWindowFocus)) { forceFocus = true; } @@ -254,7 +254,7 @@ public final class ImeFocusController { void setCurrentRootView(ViewRootImpl rootView); boolean isCurrentRootView(ViewRootImpl rootView); boolean isRestartOnNextWindowFocus(boolean reset); - boolean isSameEditorAndAcceptingText(View view); + boolean hasActiveConnection(View view); } public View getServedView() { diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java index 37b352940ee4..0d21673dfc71 100644 --- a/core/java/android/view/inputmethod/InputMethodManager.java +++ b/core/java/android/view/inputmethod/InputMethodManager.java @@ -19,8 +19,8 @@ package android.view.inputmethod; import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL; import static android.Manifest.permission.WRITE_SECURE_SETTINGS; -import static com.android.internal.inputmethod.StartInputReason.WINDOW_FOCUS_GAIN_REPORT_WITHOUT_EDITOR; -import static com.android.internal.inputmethod.StartInputReason.WINDOW_FOCUS_GAIN_REPORT_WITH_SAME_EDITOR; +import static com.android.internal.inputmethod.StartInputReason.WINDOW_FOCUS_GAIN_REPORT_WITHOUT_CONNECTION; +import static com.android.internal.inputmethod.StartInputReason.WINDOW_FOCUS_GAIN_REPORT_WITH_CONNECTION; import android.annotation.DrawableRes; import android.annotation.NonNull; @@ -89,6 +89,7 @@ import com.android.internal.view.InputBindResult; import java.io.FileDescriptor; import java.io.PrintWriter; +import java.lang.ref.WeakReference; import java.lang.reflect.Proxy; import java.util.Arrays; import java.util.Collections; @@ -610,14 +611,13 @@ public final class InputMethodManager { @Override public void startInputAsyncOnWindowFocusGain(View focusedView, @SoftInputModeFlags int softInputMode, int windowFlags, boolean forceNewFocus) { - final boolean forceNewFocus1 = forceNewFocus; final int startInputFlags = getStartInputFlags(focusedView, 0); final ImeFocusController controller = getFocusController(); if (controller == null) { return; } - if (controller.checkFocus(forceNewFocus1, false)) { + if (controller.checkFocus(forceNewFocus, false)) { // We need to restart input on the current focus view. This // should be done in conjunction with telling the system service // about the window gaining focus, to help make the transition @@ -633,15 +633,15 @@ public final class InputMethodManager { // we'll just do a window focus gain and call it a day. try { View servedView = controller.getServedView(); - boolean nextFocusSameEditor = servedView != null && servedView == focusedView - && isSameEditorAndAcceptingText(focusedView); + boolean nextFocusHasConnection = servedView != null && servedView == focusedView + && hasActiveConnection(focusedView); if (DEBUG) { Log.v(TAG, "Reporting focus gain, without startInput" - + ", nextFocusIsServedView=" + nextFocusSameEditor); + + ", nextFocusIsServedView=" + nextFocusHasConnection); } final int startInputReason = - nextFocusSameEditor ? WINDOW_FOCUS_GAIN_REPORT_WITH_SAME_EDITOR - : WINDOW_FOCUS_GAIN_REPORT_WITHOUT_EDITOR; + nextFocusHasConnection ? WINDOW_FOCUS_GAIN_REPORT_WITH_CONNECTION + : WINDOW_FOCUS_GAIN_REPORT_WITHOUT_CONNECTION; mService.startInputOrWindowGainedFocus( startInputReason, mClient, focusedView.getWindowToken(), startInputFlags, softInputMode, @@ -701,33 +701,24 @@ public final class InputMethodManager { } /** - * For {@link ImeFocusController} to check if the given focused view aligns with the same - * editor and the editor is active to accept the text input. + * Checks whether the active input connection (if any) is for the given view. * - * TODO(b/160968797): Remove this method and move mCurrentTextBoxAttritube to + * TODO(b/160968797): Remove this method and move mServedInputConnectionWrapper to * ImeFocusController. - * In the long-term, we should make mCurrentTextBoxAtrtribue as per-window base instance, - * so that we we can directly check if the current focused view aligned with the same editor - * in the window without using this checking. * - * Note that this method is only use for fixing start new input may ignored issue + * Note that this method is only intended for restarting input after focus gain * (e.g. b/160391516), DO NOT leverage this method to do another check. */ - public boolean isSameEditorAndAcceptingText(View view) { + @Override + public boolean hasActiveConnection(View view) { synchronized (mH) { - if (!hasServedByInputMethodLocked(view) || mCurrentTextBoxAttribute == null) { + if (!hasServedByInputMethodLocked(view)) { return false; } - final EditorInfo ic = mCurrentTextBoxAttribute; - // This sameEditor checking is based on using object hash comparison to check if - // some fields of the current EditorInfo (e.g. autoFillId, OpPackageName) the - // hash code is same as the given focused view. - final boolean sameEditor = view.onCheckIsTextEditor() && view.getId() == ic.fieldId - && view.getAutofillId() == ic.autofillId - && view.getContext().getOpPackageName() == ic.packageName; - return sameEditor && mServedInputConnectionWrapper != null - && mServedInputConnectionWrapper.isActive(); + return mServedInputConnectionWrapper != null + && mServedInputConnectionWrapper.isActive() + && mServedInputConnectionWrapper.mServedView.get() == view; } } } @@ -980,11 +971,13 @@ public final class InputMethodManager { private static class ControlledInputConnectionWrapper extends IInputConnectionWrapper { private final InputMethodManager mParentInputMethodManager; + private final WeakReference<View> mServedView; - public ControlledInputConnectionWrapper(final Looper mainLooper, final InputConnection conn, - final InputMethodManager inputMethodManager) { + ControlledInputConnectionWrapper(Looper mainLooper, InputConnection conn, + InputMethodManager inputMethodManager, View servedView) { super(mainLooper, conn); mParentInputMethodManager = inputMethodManager; + mServedView = new WeakReference<>(servedView); } @Override @@ -1007,6 +1000,7 @@ public final class InputMethodManager { + "connection=" + getInputConnection() + " finished=" + isFinished() + " mParentInputMethodManager.mActive=" + mParentInputMethodManager.mActive + + " mServedView=" + mServedView.get() + "}"; } } @@ -1187,7 +1181,8 @@ public final class InputMethodManager { mMainLooper = looper; mH = new H(looper); mDisplayId = displayId; - mIInputContext = new ControlledInputConnectionWrapper(looper, mDummyInputConnection, this); + mIInputContext = new ControlledInputConnectionWrapper(looper, mDummyInputConnection, this, + null); } /** @@ -1968,7 +1963,7 @@ public final class InputMethodManager { icHandler = ic.getHandler(); } servedContext = new ControlledInputConnectionWrapper( - icHandler != null ? icHandler.getLooper() : vh.getLooper(), ic, this); + icHandler != null ? icHandler.getLooper() : vh.getLooper(), ic, this, view); } else { servedContext = null; missingMethodFlags = 0; diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 226f57976ec8..f2bc89e9deb6 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -10900,17 +10900,18 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * not among the handles. */ boolean isFromPrimePointer(MotionEvent event, boolean fromHandleView) { + boolean res = true; if (mPrimePointerId == NO_POINTER_ID) { mPrimePointerId = event.getPointerId(0); mIsPrimePointerFromHandleView = fromHandleView; } else if (mPrimePointerId != event.getPointerId(0)) { - return mIsPrimePointerFromHandleView && fromHandleView; + res = mIsPrimePointerFromHandleView && fromHandleView; } if (event.getActionMasked() == MotionEvent.ACTION_UP || event.getActionMasked() == MotionEvent.ACTION_CANCEL) { mPrimePointerId = -1; } - return true; + return res; } @Override diff --git a/core/java/com/android/internal/inputmethod/InputMethodDebug.java b/core/java/com/android/internal/inputmethod/InputMethodDebug.java index 085cdfcf9462..37f68233db53 100644 --- a/core/java/com/android/internal/inputmethod/InputMethodDebug.java +++ b/core/java/com/android/internal/inputmethod/InputMethodDebug.java @@ -46,10 +46,10 @@ public final class InputMethodDebug { return "UNSPECIFIED"; case StartInputReason.WINDOW_FOCUS_GAIN: return "WINDOW_FOCUS_GAIN"; - case StartInputReason.WINDOW_FOCUS_GAIN_REPORT_WITH_SAME_EDITOR: - return "WINDOW_FOCUS_GAIN_REPORT_WITH_SAME_EDITOR"; - case StartInputReason.WINDOW_FOCUS_GAIN_REPORT_WITHOUT_EDITOR: - return "WINDOW_FOCUS_GAIN_REPORT_WITHOUT_EDITOR"; + case StartInputReason.WINDOW_FOCUS_GAIN_REPORT_WITH_CONNECTION: + return "WINDOW_FOCUS_GAIN_REPORT_WITH_CONNECTION"; + case StartInputReason.WINDOW_FOCUS_GAIN_REPORT_WITHOUT_CONNECTION: + return "WINDOW_FOCUS_GAIN_REPORT_WITHOUT_CONNECTION"; case StartInputReason.APP_CALLED_RESTART_INPUT_API: return "APP_CALLED_RESTART_INPUT_API"; case StartInputReason.CHECK_FOCUS: diff --git a/core/java/com/android/internal/inputmethod/StartInputReason.java b/core/java/com/android/internal/inputmethod/StartInputReason.java index 946ce858c12d..2ba708dd9312 100644 --- a/core/java/com/android/internal/inputmethod/StartInputReason.java +++ b/core/java/com/android/internal/inputmethod/StartInputReason.java @@ -30,8 +30,8 @@ import java.lang.annotation.Retention; @IntDef(value = { StartInputReason.UNSPECIFIED, StartInputReason.WINDOW_FOCUS_GAIN, - StartInputReason.WINDOW_FOCUS_GAIN_REPORT_WITH_SAME_EDITOR, - StartInputReason.WINDOW_FOCUS_GAIN_REPORT_WITHOUT_EDITOR, + StartInputReason.WINDOW_FOCUS_GAIN_REPORT_WITH_CONNECTION, + StartInputReason.WINDOW_FOCUS_GAIN_REPORT_WITHOUT_CONNECTION, StartInputReason.APP_CALLED_RESTART_INPUT_API, StartInputReason.CHECK_FOCUS, StartInputReason.BOUND_TO_IMMS, @@ -54,13 +54,13 @@ public @interface StartInputReason { * view and its input connection remains. {@link android.view.inputmethod.InputMethodManager} * just reports this window focus change event to sync IME input target for system. */ - int WINDOW_FOCUS_GAIN_REPORT_WITH_SAME_EDITOR = 2; + int WINDOW_FOCUS_GAIN_REPORT_WITH_CONNECTION = 2; /** * {@link android.view.Window} gained focus but there is no {@link android.view.View} that is * eligible to have IME focus. {@link android.view.inputmethod.InputMethodManager} just reports * this window focus change event for logging. */ - int WINDOW_FOCUS_GAIN_REPORT_WITHOUT_EDITOR = 3; + int WINDOW_FOCUS_GAIN_REPORT_WITHOUT_CONNECTION = 3; /** * {@link android.view.inputmethod.InputMethodManager#restartInput(android.view.View)} is * either explicitly called by the application or indirectly called by some Framework class diff --git a/libs/hwui/DeferredLayerUpdater.cpp b/libs/hwui/DeferredLayerUpdater.cpp index 5a50245a3765..67d8c07e61de 100644 --- a/libs/hwui/DeferredLayerUpdater.cpp +++ b/libs/hwui/DeferredLayerUpdater.cpp @@ -149,6 +149,9 @@ void DeferredLayerUpdater::apply() { sk_sp<SkImage> layerImage = mImageSlots[slot].createIfNeeded( hardwareBuffer, dataspace, newContent, mRenderState.getRenderThread().getGrContext()); + // unref to match the ref added by ASurfaceTexture_dequeueBuffer. eglCreateImageKHR + // (invoked by createIfNeeded) will add a ref to the AHardwareBuffer. + AHardwareBuffer_release(hardwareBuffer); if (layerImage.get()) { SkMatrix textureTransform; mat4(transformMatrix).copyTo(textureTransform); diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java index 87f0fb14ee33..ea047888caff 100644 --- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java @@ -3910,11 +3910,14 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { private void updateRulesForAppIdleParoleUL() { final boolean paroled = mAppStandby.isInParole(); final boolean enableChain = !paroled; - enableFirewallChainUL(FIREWALL_CHAIN_STANDBY, enableChain); int ruleCount = mUidFirewallStandbyRules.size(); + final SparseIntArray blockedUids = new SparseIntArray(); for (int i = 0; i < ruleCount; i++) { final int uid = mUidFirewallStandbyRules.keyAt(i); + if (!isUidValidForBlacklistRulesUL(uid)) { + continue; + } int oldRules = mUidRules.get(uid); if (enableChain) { // Chain wasn't enabled before and the other power-related @@ -3926,13 +3929,24 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { // Skip if it had no restrictions to begin with if ((oldRules & MASK_ALL_NETWORKS) == 0) continue; } - final int newUidRules = updateRulesForPowerRestrictionsUL(uid, oldRules, paroled); + final boolean isUidIdle = !paroled && isUidIdle(uid); + if (isUidIdle && !mPowerSaveTempWhitelistAppIds.get(UserHandle.getAppId(uid)) + && !isUidForegroundOnRestrictPowerUL(uid)) { + mUidFirewallStandbyRules.put(uid, FIREWALL_RULE_DENY); + blockedUids.put(uid, FIREWALL_RULE_DENY); + } else { + mUidFirewallStandbyRules.put(uid, FIREWALL_RULE_DEFAULT); + } + final int newUidRules = updateRulesForPowerRestrictionsUL(uid, oldRules, + isUidIdle); if (newUidRules == RULE_NONE) { mUidRules.delete(uid); } else { mUidRules.put(uid, newUidRules); } } + setUidFirewallRulesUL(FIREWALL_CHAIN_STANDBY, blockedUids, + enableChain ? CHAIN_TOGGLE_ENABLE : CHAIN_TOGGLE_DISABLE); } /** @@ -4400,7 +4414,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { private void updateRulesForPowerRestrictionsUL(int uid) { final int oldUidRules = mUidRules.get(uid, RULE_NONE); - final int newUidRules = updateRulesForPowerRestrictionsUL(uid, oldUidRules, false); + final int newUidRules = updateRulesForPowerRestrictionsUL(uid, oldUidRules, + isUidIdle(uid)); if (newUidRules == RULE_NONE) { mUidRules.delete(uid); @@ -4414,33 +4429,33 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { * * @param uid the uid of the app to update rules for * @param oldUidRules the current rules for the uid, in order to determine if there's a change - * @param paroled whether to ignore idle state of apps and only look at other restrictions + * @param isUidIdle whether uid is idle or not * * @return the new computed rules for the uid */ @GuardedBy("mUidRulesFirstLock") - private int updateRulesForPowerRestrictionsUL(int uid, int oldUidRules, boolean paroled) { + private int updateRulesForPowerRestrictionsUL(int uid, int oldUidRules, boolean isUidIdle) { if (Trace.isTagEnabled(Trace.TRACE_TAG_NETWORK)) { Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "updateRulesForPowerRestrictionsUL: " + uid + "/" + oldUidRules + "/" - + (paroled ? "P" : "-")); + + (isUidIdle ? "I" : "-")); } try { - return updateRulesForPowerRestrictionsULInner(uid, oldUidRules, paroled); + return updateRulesForPowerRestrictionsULInner(uid, oldUidRules, isUidIdle); } finally { Trace.traceEnd(Trace.TRACE_TAG_NETWORK); } } @GuardedBy("mUidRulesFirstLock") - private int updateRulesForPowerRestrictionsULInner(int uid, int oldUidRules, boolean paroled) { + private int updateRulesForPowerRestrictionsULInner(int uid, int oldUidRules, + boolean isUidIdle) { if (!isUidValidForBlacklistRulesUL(uid)) { if (LOGD) Slog.d(TAG, "no need to update restrict power rules for uid " + uid); return RULE_NONE; } - final boolean isIdle = !paroled && isUidIdle(uid); - final boolean restrictMode = isIdle || mRestrictPower || mDeviceIdleMode; + final boolean restrictMode = isUidIdle || mRestrictPower || mDeviceIdleMode; final boolean isForeground = isUidForegroundOnRestrictPowerUL(uid); final boolean isWhitelisted = isWhitelistedFromPowerSaveUL(uid, mDeviceIdleMode); @@ -4463,7 +4478,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { if (LOGV) { Log.v(TAG, "updateRulesForPowerRestrictionsUL(" + uid + ")" - + ", isIdle: " + isIdle + + ", isIdle: " + isUidIdle + ", mRestrictPower: " + mRestrictPower + ", mDeviceIdleMode: " + mDeviceIdleMode + ", isForeground=" + isForeground diff --git a/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java b/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java index a0ab5eae7315..cb1c7e4fd0de 100644 --- a/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java +++ b/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java @@ -16,11 +16,13 @@ package com.android.server.net; +import static android.net.NetworkTemplate.NETWORK_TYPE_5G_NSA; import static android.net.NetworkTemplate.getCollapsedRatType; import android.annotation.NonNull; import android.content.Context; import android.telephony.Annotation; +import android.telephony.NetworkRegistrationInfo; import android.telephony.PhoneStateListener; import android.telephony.ServiceState; import android.telephony.SubscriptionManager; @@ -195,7 +197,18 @@ public class NetworkStatsSubscriptionsMonitor extends @Override public void onServiceStateChanged(@NonNull ServiceState ss) { - final int networkType = ss.getDataNetworkType(); + // In 5G SA (Stand Alone) mode, the primary cell itself will be 5G hence telephony + // would report RAT = 5G_NR. + // However, in 5G NSA (Non Stand Alone) mode, the primary cell is still LTE and + // network allocates a secondary 5G cell so telephony reports RAT = LTE along with + // NR state as connected. In such case, attributes the data usage to NR. + // See b/160727498. + final boolean is5GNsa = (ss.getDataNetworkType() == TelephonyManager.NETWORK_TYPE_LTE + || ss.getDataNetworkType() == TelephonyManager.NETWORK_TYPE_LTE_CA) + && ss.getNrState() == NetworkRegistrationInfo.NR_STATE_CONNECTED; + + final int networkType = + (is5GNsa ? NETWORK_TYPE_5G_NSA : ss.getDataNetworkType()); final int collapsedRatType = getCollapsedRatType(networkType); if (collapsedRatType == mLastCollapsedRatType) return; diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java index dbdef2368c7c..8979d8c6ba10 100644 --- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java +++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java @@ -1145,6 +1145,15 @@ public class StatsPullAtomService extends SystemService { private void addDataUsageBytesTransferAtoms(@NonNull NetworkStatsExt statsExt, @NonNull List<StatsEvent> pulledData) { + + // Workaround for 5G NSA mode, see {@link NetworkTemplate#NETWORK_TYPE_5G_NSA}. + // 5G NSA mode means the primary cell is LTE with a secondary connection to an + // NR cell. To mitigate risk, NetworkStats is currently storing this state as + // a fake RAT type rather than storing the boolean separately. + final boolean is5GNsa = statsExt.ratType == NetworkTemplate.NETWORK_TYPE_5G_NSA; + // Report NR connected in 5G non-standalone mode, or if the RAT type is NR to begin with. + final boolean isNR = is5GNsa || statsExt.ratType == TelephonyManager.NETWORK_TYPE_NR; + final NetworkStats.Entry entry = new NetworkStats.Entry(); // for recycling for (int i = 0; i < statsExt.stats.size(); i++) { statsExt.stats.getValues(i, entry); @@ -1156,7 +1165,7 @@ public class StatsPullAtomService extends SystemService { .writeLong(entry.rxPackets) .writeLong(entry.txBytes) .writeLong(entry.txPackets) - .writeInt(statsExt.ratType) + .writeInt(is5GNsa ? TelephonyManager.NETWORK_TYPE_LTE : statsExt.ratType) // Fill information about subscription, these cannot be null since invalid data // would be filtered when adding into subInfo list. .writeString(statsExt.subInfo.mcc) @@ -1165,6 +1174,7 @@ public class StatsPullAtomService extends SystemService { .writeInt(statsExt.subInfo.isOpportunistic ? DATA_USAGE_BYTES_TRANSFER__OPPORTUNISTIC_DATA_SUB__OPPORTUNISTIC : DATA_USAGE_BYTES_TRANSFER__OPPORTUNISTIC_DATA_SUB__NOT_OPPORTUNISTIC) + .writeBoolean(isNR) .build(); pulledData.add(e); } diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 26bcf3b285ec..1cf9aeb1e4c7 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -2170,6 +2170,9 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP if (isInputMethodTarget()) { dc.computeImeTarget(true /* updateImeTarget */); } + if (dc.mInputMethodInputTarget == this) { + dc.setInputMethodInputTarget(null); + } if (dc.mInputMethodControlTarget == this) { dc.updateImeControlTarget(); } diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java index 94acd776fcb3..d6e038d8d027 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java @@ -890,6 +890,21 @@ public class DisplayContentTests extends WindowTestsBase { } @Test + public void testInputMethodInputTarget_isClearedWhenWindowStateIsRemoved() throws Exception { + final DisplayContent dc = createNewDisplay(); + + WindowState app = createWindow(null, TYPE_BASE_APPLICATION, dc, "app"); + + dc.mInputMethodInputTarget = app; + assertEquals(app, dc.computeImeControlTarget()); + + app.removeImmediately(); + + assertNull(dc.mInputMethodInputTarget); + assertNull(dc.computeImeControlTarget()); + } + + @Test public void testComputeImeControlTarget() throws Exception { final DisplayContent dc = createNewDisplay(); dc.setRemoteInsetsController(createDisplayWindowInsetsController()); diff --git a/tests/net/java/android/net/NetworkTemplateTest.kt b/tests/net/java/android/net/NetworkTemplateTest.kt index 5dd0fda4da28..9ba56e44fe88 100644 --- a/tests/net/java/android/net/NetworkTemplateTest.kt +++ b/tests/net/java/android/net/NetworkTemplateTest.kt @@ -26,6 +26,7 @@ import android.net.NetworkStats.METERED_ALL import android.net.NetworkStats.ROAMING_ALL import android.net.NetworkTemplate.MATCH_MOBILE import android.net.NetworkTemplate.MATCH_WIFI +import android.net.NetworkTemplate.NETWORK_TYPE_5G_NSA import android.net.NetworkTemplate.NETWORK_TYPE_ALL import android.net.NetworkTemplate.buildTemplateMobileWithRatType import android.telephony.TelephonyManager @@ -145,11 +146,13 @@ class NetworkTemplateTest { assertParcelSane(templateWifi, 8) } - // Verify NETWORK_TYPE_ALL does not conflict with TelephonyManager#NETWORK_TYPE_* constants. + // Verify NETWORK_TYPE_* constants in NetworkTemplate do not conflict with + // TelephonyManager#NETWORK_TYPE_* constants. @Test - fun testNetworkTypeAll() { + fun testNetworkTypeConstants() { for (ratType in TelephonyManager.getAllNetworkTypes()) { assertNotEquals(NETWORK_TYPE_ALL, ratType) + assertNotEquals(NETWORK_TYPE_5G_NSA, ratType) } } } diff --git a/tests/net/java/com/android/server/net/NetworkStatsSubscriptionsMonitorTest.java b/tests/net/java/com/android/server/net/NetworkStatsSubscriptionsMonitorTest.java index 058856dcd6fb..c91dfecf041b 100644 --- a/tests/net/java/com/android/server/net/NetworkStatsSubscriptionsMonitorTest.java +++ b/tests/net/java/com/android/server/net/NetworkStatsSubscriptionsMonitorTest.java @@ -17,6 +17,7 @@ package com.android.server.net; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; import static org.mockito.Mockito.any; import static org.mockito.Mockito.anyInt; import static org.mockito.Mockito.eq; @@ -29,7 +30,9 @@ import static org.mockito.Mockito.when; import android.annotation.NonNull; import android.content.Context; +import android.net.NetworkTemplate; import android.os.Looper; +import android.telephony.NetworkRegistrationInfo; import android.telephony.PhoneStateListener; import android.telephony.ServiceState; import android.telephony.SubscriptionManager; @@ -61,7 +64,6 @@ public final class NetworkStatsSubscriptionsMonitorTest { private static final String TEST_IMSI3 = "466929999999999"; @Mock private Context mContext; - @Mock private PhoneStateListener mPhoneStateListener; @Mock private SubscriptionManager mSubscriptionManager; @Mock private TelephonyManager mTelephonyManager; @Mock private Delegate mDelegate; @@ -215,4 +217,55 @@ public final class NetworkStatsSubscriptionsMonitorTest { verify(mTelephonyManager, times(2)).listen(any(), eq(PhoneStateListener.LISTEN_NONE)); assertRatTypeChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UNKNOWN); } + + + @Test + public void test5g() { + mMonitor.start(); + // Insert sim1, verify RAT type is NETWORK_TYPE_UNKNOWN, and never get any callback + // before changing RAT type. Also capture listener for later use. + addTestSub(TEST_SUBID1, TEST_IMSI1); + assertRatTypeNotChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UNKNOWN); + final ArgumentCaptor<RatTypeListener> ratTypeListenerCaptor = + ArgumentCaptor.forClass(RatTypeListener.class); + verify(mTelephonyManager, times(1)).listen(ratTypeListenerCaptor.capture(), + eq(PhoneStateListener.LISTEN_SERVICE_STATE)); + final RatTypeListener listener = CollectionUtils + .find(ratTypeListenerCaptor.getAllValues(), it -> it.getSubId() == TEST_SUBID1); + assertNotNull(listener); + + // Set RAT type to 5G NSA (non-standalone) mode, verify the monitor outputs + // NETWORK_TYPE_5G_NSA. + final ServiceState serviceState = mock(ServiceState.class); + when(serviceState.getDataNetworkType()).thenReturn(TelephonyManager.NETWORK_TYPE_LTE); + when(serviceState.getNrState()).thenReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED); + listener.onServiceStateChanged(serviceState); + assertRatTypeChangedForSub(TEST_IMSI1, NetworkTemplate.NETWORK_TYPE_5G_NSA); + reset(mDelegate); + + // Set RAT type to LTE without NR connected, the RAT type should be downgraded to LTE. + when(serviceState.getNrState()).thenReturn(NetworkRegistrationInfo.NR_STATE_NONE); + listener.onServiceStateChanged(serviceState); + assertRatTypeChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_LTE); + reset(mDelegate); + + // Verify NR connected with other RAT type does not take effect. + when(serviceState.getDataNetworkType()).thenReturn(TelephonyManager.NETWORK_TYPE_UMTS); + when(serviceState.getNrState()).thenReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED); + listener.onServiceStateChanged(serviceState); + assertRatTypeChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UMTS); + reset(mDelegate); + + // Set RAT type to 5G standalone mode, the RAT type should be NR. + setRatTypeForSub(ratTypeListenerCaptor.getAllValues(), TEST_SUBID1, + TelephonyManager.NETWORK_TYPE_NR); + assertRatTypeChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_NR); + reset(mDelegate); + + // Set NR state to none in standalone mode does not change anything. + when(serviceState.getDataNetworkType()).thenReturn(TelephonyManager.NETWORK_TYPE_NR); + when(serviceState.getNrState()).thenReturn(NetworkRegistrationInfo.NR_STATE_NONE); + listener.onServiceStateChanged(serviceState); + assertRatTypeNotChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_NR); + } } |