summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmds/statsd/src/atoms.proto6
-rw-r--r--core/java/android/net/NetworkTemplate.java12
-rw-r--r--core/java/android/view/ImeFocusController.java10
-rw-r--r--core/java/android/view/inputmethod/InputMethodManager.java57
-rw-r--r--core/java/android/widget/TextView.java5
-rw-r--r--core/java/com/android/internal/inputmethod/InputMethodDebug.java8
-rw-r--r--core/java/com/android/internal/inputmethod/StartInputReason.java8
-rw-r--r--libs/hwui/DeferredLayerUpdater.cpp3
-rw-r--r--services/core/java/com/android/server/net/NetworkPolicyManagerService.java37
-rw-r--r--services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java15
-rw-r--r--services/core/java/com/android/server/stats/pull/StatsPullAtomService.java12
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java3
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java15
-rw-r--r--tests/net/java/android/net/NetworkTemplateTest.kt7
-rw-r--r--tests/net/java/com/android/server/net/NetworkStatsSubscriptionsMonitorTest.java55
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);
+ }
}