Merge "Clear calling identity before updating lock-task packages" into main
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 56fef1a..dab4110 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -1486,13 +1486,13 @@
AppProtoEnums.APP_OP_RECEIVE_SANDBOX_TRIGGER_AUDIO;
/**
- * Allows the assistant app to get the negative trigger data from the PCC sandbox to improve the
+ * Allows the assistant app to get the training data from the PCC sandbox to improve the
* hotword training model.
*
* @hide
*/
- public static final int OP_RECEIVE_SANDBOX_NEGATIVE_DATA_AUDIO =
- AppProtoEnums.APP_OP_RECEIVE_SANDBOX_NEGATIVE_DATA_AUDIO;
+ public static final int OP_RECEIVE_SANDBOX_TRAINING_DATA =
+ AppProtoEnums.APP_OP_RECEIVE_SANDBOX_TRAINING_DATA;
/** @hide */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
@@ -1640,7 +1640,7 @@
OPSTR_CAMERA_SANDBOXED,
OPSTR_RECORD_AUDIO_SANDBOXED,
OPSTR_RECEIVE_SANDBOX_TRIGGER_AUDIO,
- OPSTR_RECEIVE_SANDBOX_NEGATIVE_DATA_AUDIO
+ OPSTR_RECEIVE_SANDBOX_TRAINING_DATA
})
public @interface AppOpString {}
@@ -2261,13 +2261,13 @@
"android:receive_sandbox_trigger_audio";
/**
- * Allows the assistant app to get the negative trigger data from the PCC sandbox to improve
+ * Allows the assistant app to get the training data from the PCC sandbox to improve
* the hotword training model.
*
* @hide
*/
- public static final String OPSTR_RECEIVE_SANDBOX_NEGATIVE_DATA_AUDIO =
- "android:receive_sandbox_negative_data_audio";
+ public static final String OPSTR_RECEIVE_SANDBOX_TRAINING_DATA =
+ "android:receive_sandbox_training_data";
/** {@link #sAppOpsToNote} not initialized yet for this op */
private static final byte SHOULD_COLLECT_NOTE_OP_NOT_INITIALIZED = 0;
@@ -2811,9 +2811,9 @@
OPSTR_RECEIVE_SANDBOX_TRIGGER_AUDIO,
"RECEIVE_SANDBOX_TRIGGER_AUDIO")
.setDefaultMode(AppOpsManager.MODE_ALLOWED).build(),
- new AppOpInfo.Builder(OP_RECEIVE_SANDBOX_NEGATIVE_DATA_AUDIO,
- OPSTR_RECEIVE_SANDBOX_NEGATIVE_DATA_AUDIO,
- "RECEIVE_SANDBOX_NEGATIVE_DATA_AUDIO").build()
+ new AppOpInfo.Builder(OP_RECEIVE_SANDBOX_TRAINING_DATA,
+ OPSTR_RECEIVE_SANDBOX_TRAINING_DATA,
+ "RECEIVE_SANDBOX_TRAINING_DATA").build()
};
// The number of longs needed to form a full bitmask of app ops
diff --git a/core/java/android/app/assist/AssistStructure.java b/core/java/android/app/assist/AssistStructure.java
index d66fca8..ed0f872 100644
--- a/core/java/android/app/assist/AssistStructure.java
+++ b/core/java/android/app/assist/AssistStructure.java
@@ -2495,7 +2495,8 @@
+ ", hints=" + Arrays.toString(node.getAutofillHints())
+ ", value=" + node.getAutofillValue()
+ ", sanitized=" + node.isSanitized()
- + ", important=" + node.getImportantForAutofill());
+ + ", important=" + node.getImportantForAutofill()
+ + ", visibility=" + node.getVisibility());
}
final int NCHILDREN = node.getChildCount();
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index c7e5453..637770c 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -1307,9 +1307,9 @@
visibleFrame.intersect(mInsetsState.getDisplayFrame());
WindowInsets windowInsets = mInsetsState.calculateInsets(visibleFrame,
null /* ignoringVisibilityState */, config.isScreenRound(),
- false /* alwaysConsumeSystemBars */, mLayout.softInputMode,
- mLayout.flags, SYSTEM_UI_FLAG_VISIBLE, mLayout.type,
- config.windowConfiguration.getWindowingMode(), null /* idSideMap */);
+ mLayout.softInputMode, mLayout.flags, SYSTEM_UI_FLAG_VISIBLE,
+ mLayout.type, config.windowConfiguration.getActivityType(),
+ null /* idSideMap */);
if (!fixedSize) {
final Rect padding = mIWallpaperEngine.mDisplayPadding;
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index 85f5395..5fe2aa1 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -156,6 +156,13 @@
public static final String SETTINGS_BIOMETRICS2_FINGERPRINT_SETTINGS =
"settings_biometrics2_fingerprint";
+ /**
+ * Flag to enable/disable remote auth enrollment and settings
+ * @hide
+ */
+ public static final String SETTINGS_REMOTEAUTH_ENROLLMENT_SETTINGS =
+ "settings_remoteauth_enrollment";
+
/** Flag to enable/disable entire page in Accessibility -> Hearing aids
* @hide
*/
@@ -248,6 +255,8 @@
DEFAULT_FLAGS.put(SETTINGS_REMOTE_DEVICE_CREDENTIAL_VALIDATION, "true");
DEFAULT_FLAGS.put(SETTINGS_BIOMETRICS2_FINGERPRINT_SETTINGS, "false");
DEFAULT_FLAGS.put("settings_press_hold_nav_handle_to_search", "false");
+ // TODO: b/298454866 Replace with Trunk Stable Feature Flag
+ DEFAULT_FLAGS.put(SETTINGS_REMOTEAUTH_ENROLLMENT_SETTINGS, "false");
}
private static final Set<String> PERSISTENT_FLAGS;
diff --git a/core/java/android/view/InsetsAnimationControlImpl.java b/core/java/android/view/InsetsAnimationControlImpl.java
index fabfed3..1ec7c41 100644
--- a/core/java/android/view/InsetsAnimationControlImpl.java
+++ b/core/java/android/view/InsetsAnimationControlImpl.java
@@ -16,7 +16,7 @@
package android.view;
-import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.view.EventLogTags.IMF_IME_ANIM_CANCEL;
import static android.view.EventLogTags.IMF_IME_ANIM_FINISH;
import static android.view.EventLogTags.IMF_IME_ANIM_START;
@@ -39,6 +39,7 @@
import static android.view.InsetsState.ISIDE_RIGHT;
import static android.view.InsetsState.ISIDE_TOP;
import static android.view.WindowInsets.Type.ime;
+import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static android.view.inputmethod.ImeTracker.DEBUG_IME_VISIBILITY;
import static android.view.inputmethod.ImeTracker.TOKEN_NONE;
@@ -62,7 +63,6 @@
import android.view.SyncRtSurfaceTransactionApplier.SurfaceParams;
import android.view.WindowInsets.Type.InsetsType;
import android.view.WindowInsetsAnimation.Bounds;
-import android.view.WindowManager.LayoutParams;
import android.view.animation.Interpolator;
import android.view.inputmethod.ImeTracker;
@@ -396,10 +396,9 @@
private Insets getInsetsFromState(InsetsState state, Rect frame,
@Nullable @InternalInsetsSide SparseIntArray idSideMap) {
return state.calculateInsets(frame, null /* ignoringVisibilityState */,
- false /* isScreenRound */, false /* alwaysConsumeSystemBars */,
- LayoutParams.SOFT_INPUT_ADJUST_RESIZE /* legacySoftInputMode*/,
+ false /* isScreenRound */, SOFT_INPUT_ADJUST_RESIZE /* legacySoftInputMode */,
0 /* legacyWindowFlags */, 0 /* legacySystemUiFlags */, TYPE_APPLICATION,
- WINDOWING_MODE_UNDEFINED, idSideMap).getInsets(mTypes);
+ ACTIVITY_TYPE_UNDEFINED, idSideMap).getInsets(mTypes);
}
/** Computes the insets relative to the given frame. */
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java
index 8ec7d67..fb24211 100644
--- a/core/java/android/view/InsetsController.java
+++ b/core/java/android/view/InsetsController.java
@@ -652,7 +652,7 @@
private int mLastLegacySoftInputMode;
private int mLastLegacyWindowFlags;
private int mLastLegacySystemUiFlags;
- private int mLastWindowingMode;
+ private int mLastActivityType;
private boolean mStartingAnimation;
private int mCaptionInsetsHeight = 0;
private int mImeCaptionBarInsetsHeight = 0;
@@ -800,10 +800,10 @@
}
}
- WindowInsets insets = state.calculateInsets(mFrame, mState /* ignoringVisibilityState*/,
- mLastInsets.isRound(), false /* alwaysConsumeSystemBars */,
+ WindowInsets insets = state.calculateInsets(mFrame,
+ mState /* ignoringVisibilityState */, mLastInsets.isRound(),
mLastLegacySoftInputMode, mLastLegacyWindowFlags, mLastLegacySystemUiFlags,
- mWindowType, mLastWindowingMode, null /* idSideMap */);
+ mWindowType, mLastActivityType, null /* idSideMap */);
mHost.dispatchWindowInsetsAnimationProgress(insets,
Collections.unmodifiableList(runningAnimations));
if (DEBUG) {
@@ -939,30 +939,29 @@
}
/**
- * @see InsetsState#calculateInsets(Rect, InsetsState, boolean, boolean, int, int, int, int,
- * int, android.util.SparseIntArray)
+ * @see InsetsState#calculateInsets(Rect, InsetsState, boolean, int, int, int, int, int,
+ * android.util.SparseIntArray)
*/
@VisibleForTesting
- public WindowInsets calculateInsets(boolean isScreenRound, boolean alwaysConsumeSystemBars,
- int windowType, int windowingMode, int legacySoftInputMode, int legacyWindowFlags,
- int legacySystemUiFlags) {
+ public WindowInsets calculateInsets(boolean isScreenRound, int windowType, int activityType,
+ int legacySoftInputMode, int legacyWindowFlags, int legacySystemUiFlags) {
mWindowType = windowType;
- mLastWindowingMode = windowingMode;
+ mLastActivityType = activityType;
mLastLegacySoftInputMode = legacySoftInputMode;
mLastLegacyWindowFlags = legacyWindowFlags;
mLastLegacySystemUiFlags = legacySystemUiFlags;
- mLastInsets = mState.calculateInsets(mFrame, null /* ignoringVisibilityState*/,
- isScreenRound, alwaysConsumeSystemBars, legacySoftInputMode, legacyWindowFlags,
- legacySystemUiFlags, windowType, windowingMode, null /* idSideMap */);
+ mLastInsets = mState.calculateInsets(mFrame, null /* ignoringVisibilityState */,
+ isScreenRound, legacySoftInputMode, legacyWindowFlags,
+ legacySystemUiFlags, windowType, activityType, null /* idSideMap */);
return mLastInsets;
}
/**
* @see InsetsState#calculateVisibleInsets(Rect, int, int, int, int)
*/
- public Insets calculateVisibleInsets(int windowType, int windowingMode,
+ public Insets calculateVisibleInsets(int windowType, int activityType,
@SoftInputModeFlags int softInputMode, int windowFlags) {
- return mState.calculateVisibleInsets(mFrame, windowType, windowingMode, softInputMode,
+ return mState.calculateVisibleInsets(mFrame, windowType, activityType, softInputMode,
windowFlags);
}
diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java
index af24140..59e0932 100644
--- a/core/java/android/view/InsetsState.java
+++ b/core/java/android/view/InsetsState.java
@@ -16,6 +16,7 @@
package android.view;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.view.InsetsSource.FLAG_FORCE_CONSUMING;
import static android.view.InsetsSource.FLAG_INSETS_ROUNDED_CORNER;
import static android.view.InsetsStateProto.DISPLAY_CUTOUT;
@@ -39,7 +40,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.app.WindowConfiguration;
+import android.app.WindowConfiguration.ActivityType;
import android.graphics.Insets;
import android.graphics.Rect;
import android.os.Parcel;
@@ -136,9 +137,8 @@
* @return The calculated insets.
*/
public WindowInsets calculateInsets(Rect frame, @Nullable InsetsState ignoringVisibilityState,
- boolean isScreenRound, boolean alwaysConsumeSystemBars,
- int legacySoftInputMode, int legacyWindowFlags, int legacySystemUiFlags,
- int windowType, @WindowConfiguration.WindowingMode int windowingMode,
+ boolean isScreenRound, int legacySoftInputMode, int legacyWindowFlags,
+ int legacySystemUiFlags, int windowType, @ActivityType int activityType,
@Nullable @InternalInsetsSide SparseIntArray idSideMap) {
Insets[] typeInsetsMap = new Insets[Type.SIZE];
Insets[] typeMaxInsetsMap = new Insets[Type.SIZE];
@@ -185,9 +185,8 @@
if ((legacyWindowFlags & FLAG_FULLSCREEN) != 0) {
compatInsetsTypes &= ~statusBars();
}
- if (clearsCompatInsets(windowType, legacyWindowFlags, windowingMode)) {
- // Clear all types but forceConsumingTypes.
- compatInsetsTypes &= forceConsumingTypes;
+ if (clearsCompatInsets(windowType, legacyWindowFlags, activityType, forceConsumingTypes)) {
+ compatInsetsTypes = 0;
}
return new WindowInsets(typeInsetsMap, typeMaxInsetsMap, typeVisibilityMap, isScreenRound,
@@ -295,26 +294,27 @@
return insets;
}
- public Insets calculateVisibleInsets(Rect frame, int windowType, int windowingMode,
+ public Insets calculateVisibleInsets(Rect frame, int windowType, @ActivityType int activityType,
@SoftInputModeFlags int softInputMode, int windowFlags) {
- final boolean clearsCompatInsets = clearsCompatInsets(
- windowType, windowFlags, windowingMode);
final int softInputAdjustMode = softInputMode & SOFT_INPUT_MASK_ADJUST;
final int visibleInsetsTypes = softInputAdjustMode != SOFT_INPUT_ADJUST_NOTHING
? systemBars() | ime()
: systemBars();
+ @InsetsType int forceConsumingTypes = 0;
Insets insets = Insets.NONE;
for (int i = mSources.size() - 1; i >= 0; i--) {
final InsetsSource source = mSources.valueAt(i);
if ((source.getType() & visibleInsetsTypes) == 0) {
continue;
}
- if (clearsCompatInsets && !source.hasFlags(FLAG_FORCE_CONSUMING)) {
- continue;
+ if (source.hasFlags(FLAG_FORCE_CONSUMING)) {
+ forceConsumingTypes |= source.getType();
}
insets = Insets.max(source.calculateVisibleInsets(frame), insets);
}
- return insets;
+ return clearsCompatInsets(windowType, windowFlags, activityType, forceConsumingTypes)
+ ? Insets.NONE
+ : insets;
}
/**
@@ -662,10 +662,15 @@
mSources.put(source.getId(), source);
}
- public static boolean clearsCompatInsets(int windowType, int windowFlags, int windowingMode) {
+ public static boolean clearsCompatInsets(int windowType, int windowFlags,
+ @ActivityType int activityType, @InsetsType int forceConsumingTypes) {
return (windowFlags & FLAG_LAYOUT_NO_LIMITS) != 0
+ // For compatibility reasons, this excludes the wallpaper, the system error windows,
+ // and the app windows while any system bar is forcibly consumed.
&& windowType != TYPE_WALLPAPER && windowType != TYPE_SYSTEM_ERROR
- && !WindowConfiguration.inMultiWindowMode(windowingMode);
+ // This ensures the app content won't be obscured by compat insets even if the app
+ // has FLAG_LAYOUT_NO_LIMITS.
+ && (forceConsumingTypes == 0 || activityType != ACTIVITY_TYPE_STANDARD);
}
public void dump(String prefix, PrintWriter pw) {
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index e0fda7e..60d964e 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -2848,16 +2848,15 @@
if (mLastWindowInsets == null || forceConstruct) {
final Configuration config = getConfiguration();
mLastWindowInsets = mInsetsController.calculateInsets(
- config.isScreenRound(), mAttachInfo.mAlwaysConsumeSystemBars,
- mWindowAttributes.type, config.windowConfiguration.getWindowingMode(),
- mWindowAttributes.softInputMode, mWindowAttributes.flags,
- (mWindowAttributes.systemUiVisibility
+ config.isScreenRound(), mWindowAttributes.type,
+ config.windowConfiguration.getActivityType(), mWindowAttributes.softInputMode,
+ mWindowAttributes.flags, (mWindowAttributes.systemUiVisibility
| mWindowAttributes.subtreeSystemUiVisibility));
mAttachInfo.mContentInsets.set(mLastWindowInsets.getSystemWindowInsets().toRect());
mAttachInfo.mStableInsets.set(mLastWindowInsets.getStableInsets().toRect());
mAttachInfo.mVisibleInsets.set(mInsetsController.calculateVisibleInsets(
- mWindowAttributes.type, config.windowConfiguration.getWindowingMode(),
+ mWindowAttributes.type, config.windowConfiguration.getActivityType(),
mWindowAttributes.softInputMode, mWindowAttributes.flags).toRect());
}
return mLastWindowInsets;
diff --git a/core/java/android/window/WindowMetricsController.java b/core/java/android/window/WindowMetricsController.java
index 2858f0a..e32c8e5 100644
--- a/core/java/android/window/WindowMetricsController.java
+++ b/core/java/android/window/WindowMetricsController.java
@@ -16,7 +16,7 @@
package android.window;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.view.View.SYSTEM_UI_FLAG_VISIBLE;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
@@ -80,7 +80,7 @@
final Rect bounds;
final float density;
final boolean isScreenRound;
- final int windowingMode;
+ final int activityType;
synchronized (ResourcesManager.getInstance()) {
final Configuration config = mContext.getResources().getConfiguration();
final WindowConfiguration winConfig = config.windowConfiguration;
@@ -90,11 +90,11 @@
// as DisplayMetrics#density
density = config.densityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE;
isScreenRound = config.isScreenRound();
- windowingMode = winConfig.getWindowingMode();
+ activityType = winConfig.getActivityType();
}
final IBinder token = Context.getToken(mContext);
final Supplier<WindowInsets> insetsSupplier = () -> getWindowInsetsFromServerForDisplay(
- mContext.getDisplayId(), token, bounds, isScreenRound, windowingMode);
+ mContext.getDisplayId(), token, bounds, isScreenRound, activityType);
return new WindowMetrics(new Rect(bounds), insetsSupplier, density);
}
@@ -105,23 +105,22 @@
* @param token the token of Activity or WindowContext
* @param bounds the window bounds to calculate insets for
* @param isScreenRound if the display identified by displayId is round
- * @param windowingMode the windowing mode of the window to calculate insets for
+ * @param activityType the activity type of the window to calculate insets for
* @return WindowInsets calculated for the given window bounds, on the given display
*/
private static WindowInsets getWindowInsetsFromServerForDisplay(int displayId, IBinder token,
- Rect bounds, boolean isScreenRound, int windowingMode) {
+ Rect bounds, boolean isScreenRound, int activityType) {
try {
final InsetsState insetsState = new InsetsState();
- final boolean alwaysConsumeSystemBars = WindowManagerGlobal.getWindowManagerService()
- .getWindowInsets(displayId, token, insetsState);
+ WindowManagerGlobal.getWindowManagerService().getWindowInsets(
+ displayId, token, insetsState);
final float overrideInvScale = CompatibilityInfo.getOverrideInvertedScale();
if (overrideInvScale != 1f) {
insetsState.scale(overrideInvScale);
}
return insetsState.calculateInsets(bounds, null /* ignoringVisibilityState */,
- isScreenRound, alwaysConsumeSystemBars, SOFT_INPUT_ADJUST_NOTHING,
- 0 /* flags */, SYSTEM_UI_FLAG_VISIBLE,
- WindowManager.LayoutParams.INVALID_WINDOW_TYPE, windowingMode,
+ isScreenRound, SOFT_INPUT_ADJUST_NOTHING, 0 /* flags */, SYSTEM_UI_FLAG_VISIBLE,
+ WindowManager.LayoutParams.INVALID_WINDOW_TYPE, activityType,
null /* idSideMap */);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
@@ -157,7 +156,7 @@
currentDisplayInfo.displayId, null /* token */,
new Rect(0, 0, currentDisplayInfo.getNaturalWidth(),
currentDisplayInfo.getNaturalHeight()), isScreenRound,
- WINDOWING_MODE_FULLSCREEN);
+ ACTIVITY_TYPE_UNDEFINED);
// Set the hardware-provided insets.
windowInsets = new WindowInsets.Builder(windowInsets).setRoundedCorners(
currentDisplayInfo.roundedCorners)
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index bb86801..86ca077 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -1113,15 +1113,14 @@
if (insets != null) {
mLastForceConsumingTypes = insets.getForceConsumingTypes();
- @InsetsType int compatInsetsTypes =
+ final boolean clearsCompatInsets = clearsCompatInsets(attrs.type, attrs.flags,
+ getResources().getConfiguration().windowConfiguration.getActivityType(),
+ mLastForceConsumingTypes);
+ final @InsetsType int compatInsetsTypes =
WindowInsets.Type.systemBars() | WindowInsets.Type.displayCutout();
- if (clearsCompatInsets(attrs.type, attrs.flags,
- getResources().getConfiguration().windowConfiguration.getWindowingMode())) {
- compatInsetsTypes &= mLastForceConsumingTypes;
- }
final Insets stableBarInsets = insets.getInsetsIgnoringVisibility(
WindowInsets.Type.systemBars());
- final Insets systemInsets = compatInsetsTypes == 0
+ final Insets systemInsets = clearsCompatInsets
? Insets.NONE
: Insets.min(insets.getInsets(compatInsetsTypes), stableBarInsets);
mLastTopInset = systemInsets.top;
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index a72f779..7bfc7de 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1185,6 +1185,9 @@
-->
<integer name="config_shortPressOnSleepBehavior">0</integer>
+ <!-- Whether to silence telephony ringer on sleep key event -->
+ <bool name="config_silenceRingerOnSleepKey">false</bool>
+
<!-- Control the behavior when the user long presses the stem primary button.
Stem primary button is only used on watch form factor. If a device is not
a watch, setting this config is no-op.
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index ee0563b..c903e33 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -464,6 +464,7 @@
<java-symbol type="integer" name="config_toastDefaultGravity" />
<java-symbol type="integer" name="config_triplePressOnPowerBehavior" />
<java-symbol type="integer" name="config_shortPressOnSleepBehavior" />
+ <java-symbol type="bool" name="config_silenceRingerOnSleepKey" />
<java-symbol type="integer" name="config_longPressOnStemPrimaryBehavior" />
<java-symbol type="integer" name="config_shortPressOnStemPrimaryBehavior" />
<java-symbol type="string" name="config_primaryShortPressTargetActivity" />
diff --git a/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java b/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java
index f45db23..8c93fbb 100644
--- a/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java
+++ b/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java
@@ -16,7 +16,7 @@
package android.view;
-import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.view.InsetsSource.ID_IME;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
@@ -81,8 +81,7 @@
Insets.of(10, 10, 10, 10), rect, rect, rect, rect));
mController.calculateInsets(
false,
- false,
- TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED,
+ TYPE_APPLICATION, ACTIVITY_TYPE_UNDEFINED,
SOFT_INPUT_ADJUST_RESIZE, 0, 0);
mImeConsumer = mController.getImeSourceConsumer();
});
diff --git a/core/tests/coretests/src/android/view/InsetsControllerTest.java b/core/tests/coretests/src/android/view/InsetsControllerTest.java
index b8f0d5c..1568174 100644
--- a/core/tests/coretests/src/android/view/InsetsControllerTest.java
+++ b/core/tests/coretests/src/android/view/InsetsControllerTest.java
@@ -16,7 +16,7 @@
package android.view;
-import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.view.InsetsController.ANIMATION_TYPE_HIDE;
import static android.view.InsetsController.ANIMATION_TYPE_NONE;
import static android.view.InsetsController.ANIMATION_TYPE_RESIZE;
@@ -171,8 +171,7 @@
mController.onStateChanged(state);
mController.calculateInsets(
false,
- false,
- TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED,
+ TYPE_APPLICATION, ACTIVITY_TYPE_UNDEFINED,
SOFT_INPUT_ADJUST_RESIZE, 0, 0);
mController.onFrameChanged(new Rect(0, 0, 100, 100));
});
diff --git a/core/tests/coretests/src/android/view/InsetsStateTest.java b/core/tests/coretests/src/android/view/InsetsStateTest.java
index b06cd39..906d84e 100644
--- a/core/tests/coretests/src/android/view/InsetsStateTest.java
+++ b/core/tests/coretests/src/android/view/InsetsStateTest.java
@@ -16,8 +16,9 @@
package android.view;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
-import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
+import static android.view.InsetsSource.FLAG_FORCE_CONSUMING;
import static android.view.InsetsSource.ID_IME;
import static android.view.InsetsState.ISIDE_BOTTOM;
import static android.view.InsetsState.ISIDE_TOP;
@@ -101,7 +102,7 @@
.setVisible(true);
SparseIntArray typeSideMap = new SparseIntArray();
WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
- false, SOFT_INPUT_ADJUST_RESIZE, 0, 0, TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED,
+ SOFT_INPUT_ADJUST_RESIZE, 0, 0, TYPE_APPLICATION, ACTIVITY_TYPE_UNDEFINED,
typeSideMap);
assertEquals(Insets.of(0, 100, 0, 100), insets.getSystemWindowInsets());
assertEquals(Insets.of(0, 100, 0, 100), insets.getInsets(Type.all()));
@@ -120,7 +121,7 @@
.setFrame(new Rect(0, 100, 100, 300))
.setVisible(true);
WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
- false, SOFT_INPUT_ADJUST_RESIZE, 0, 0, TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED,
+ SOFT_INPUT_ADJUST_RESIZE, 0, 0, TYPE_APPLICATION, ACTIVITY_TYPE_UNDEFINED,
null);
assertEquals(100, insets.getStableInsetBottom());
assertEquals(Insets.of(0, 0, 0, 100), insets.getInsetsIgnoringVisibility(systemBars()));
@@ -139,7 +140,7 @@
.setFrame(new Rect(80, 0, 100, 300))
.setVisible(true);
WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
- false, 0, 0, 0, TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED, null);
+ 0, 0, 0, TYPE_APPLICATION, ACTIVITY_TYPE_UNDEFINED, null);
assertEquals(Insets.of(0, 100, 20, 0), insets.getSystemWindowInsets());
assertEquals(Insets.of(0, 100, 0, 0), insets.getInsets(statusBars()));
assertEquals(Insets.of(0, 0, 20, 0), insets.getInsets(navigationBars()));
@@ -154,7 +155,7 @@
.setFrame(new Rect(80, 0, 100, 300))
.setVisible(true);
WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
- false, 0, 0, 0, TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED, null);
+ 0, 0, 0, TYPE_APPLICATION, ACTIVITY_TYPE_UNDEFINED, null);
assertEquals(Insets.of(0, 100, 20, 0), insets.getSystemWindowInsets());
assertEquals(Insets.of(0, 100, 0, 0), insets.getInsets(Type.statusBars()));
assertEquals(Insets.of(0, 0, 20, 0), insets.getInsets(Type.navigationBars()));
@@ -169,7 +170,7 @@
.setFrame(new Rect(0, 200, 100, 300))
.setVisible(true);
WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
- false, SOFT_INPUT_ADJUST_NOTHING, 0, 0, TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED,
+ SOFT_INPUT_ADJUST_NOTHING, 0, 0, TYPE_APPLICATION, ACTIVITY_TYPE_UNDEFINED,
null);
assertEquals(0, insets.getSystemWindowInsetBottom());
assertEquals(100, insets.getInsets(ime()).bottom);
@@ -185,12 +186,12 @@
.setFrame(new Rect(0, 200, 100, 300))
.setVisible(true);
WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
- false, SOFT_INPUT_ADJUST_NOTHING, 0, SYSTEM_UI_FLAG_LAYOUT_STABLE, TYPE_APPLICATION,
- WINDOWING_MODE_UNDEFINED, null);
+ SOFT_INPUT_ADJUST_NOTHING, 0, SYSTEM_UI_FLAG_LAYOUT_STABLE, TYPE_APPLICATION,
+ ACTIVITY_TYPE_UNDEFINED, null);
assertEquals(100, insets.getSystemWindowInsetTop());
- insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false, false,
+ insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
SOFT_INPUT_ADJUST_NOTHING, 0, 0 /* legacySystemUiFlags */, TYPE_APPLICATION,
- WINDOWING_MODE_UNDEFINED, null);
+ ACTIVITY_TYPE_UNDEFINED, null);
assertEquals(0, insets.getSystemWindowInsetTop());
}
@@ -200,12 +201,12 @@
.setFrame(new Rect(0, 0, 100, 100))
.setVisible(false);
WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
- false, SOFT_INPUT_ADJUST_NOTHING, FLAG_FULLSCREEN, SYSTEM_UI_FLAG_LAYOUT_STABLE,
- TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED, null);
+ SOFT_INPUT_ADJUST_NOTHING, FLAG_FULLSCREEN, SYSTEM_UI_FLAG_LAYOUT_STABLE,
+ TYPE_APPLICATION, ACTIVITY_TYPE_UNDEFINED, null);
assertEquals(0, insets.getSystemWindowInsetTop());
- insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false, false,
+ insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
SOFT_INPUT_ADJUST_NOTHING, 0, 0 /* legacySystemUiFlags */, TYPE_APPLICATION,
- WINDOWING_MODE_UNDEFINED, null);
+ ACTIVITY_TYPE_UNDEFINED, null);
assertEquals(0, insets.getSystemWindowInsetTop());
}
@@ -213,22 +214,23 @@
public void testCalculateInsets_flagLayoutNoLimits() {
mState.getOrCreateSource(ID_STATUS_BAR, statusBars())
.setFrame(new Rect(0, 0, 100, 100))
- .setVisible(true);
+ .setVisible(true)
+ .setFlags(FLAG_FORCE_CONSUMING);
WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
- false, SOFT_INPUT_ADJUST_NOTHING, FLAG_LAYOUT_NO_LIMITS,
- 0 /* legacySystemUiFlags */, TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED, null);
+ SOFT_INPUT_ADJUST_NOTHING, FLAG_LAYOUT_NO_LIMITS,
+ 0 /* legacySystemUiFlags */, TYPE_APPLICATION, ACTIVITY_TYPE_UNDEFINED, null);
assertEquals(0, insets.getSystemWindowInsetTop());
insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
- false, SOFT_INPUT_ADJUST_NOTHING, FLAG_LAYOUT_NO_LIMITS,
- 0 /* legacySystemUiFlags */, TYPE_SYSTEM_ERROR, WINDOWING_MODE_UNDEFINED, null);
+ SOFT_INPUT_ADJUST_NOTHING, FLAG_LAYOUT_NO_LIMITS,
+ 0 /* legacySystemUiFlags */, TYPE_SYSTEM_ERROR, ACTIVITY_TYPE_UNDEFINED, null);
assertEquals(100, insets.getSystemWindowInsetTop());
insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
- false, SOFT_INPUT_ADJUST_NOTHING, FLAG_LAYOUT_NO_LIMITS,
- 0 /* legacySystemUiFlags */, TYPE_WALLPAPER, WINDOWING_MODE_UNDEFINED, null);
+ SOFT_INPUT_ADJUST_NOTHING, FLAG_LAYOUT_NO_LIMITS,
+ 0 /* legacySystemUiFlags */, TYPE_WALLPAPER, ACTIVITY_TYPE_UNDEFINED, null);
assertEquals(100, insets.getSystemWindowInsetTop());
insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
- false, SOFT_INPUT_ADJUST_NOTHING, FLAG_LAYOUT_NO_LIMITS,
- 0 /* legacySystemUiFlags */, TYPE_APPLICATION, WINDOWING_MODE_FREEFORM, null);
+ SOFT_INPUT_ADJUST_NOTHING, FLAG_LAYOUT_NO_LIMITS,
+ 0 /* legacySystemUiFlags */, TYPE_APPLICATION, ACTIVITY_TYPE_STANDARD, null);
assertEquals(100, insets.getSystemWindowInsetTop());
}
@@ -243,7 +245,7 @@
.setVisible(true);
Insets visibleInsets = mState.calculateVisibleInsets(
- new Rect(0, 0, 100, 400), TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED,
+ new Rect(0, 0, 100, 400), TYPE_APPLICATION, ACTIVITY_TYPE_UNDEFINED,
SOFT_INPUT_ADJUST_NOTHING, 0 /* windowFlags */);
assertEquals(Insets.of(0, 300, 0, 0), visibleInsets);
}
@@ -255,7 +257,7 @@
.setVisible(true);
Insets visibleInsets = mState.calculateVisibleInsets(
- new Rect(0, 0, 150, 400), TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED,
+ new Rect(0, 0, 150, 400), TYPE_APPLICATION, ACTIVITY_TYPE_UNDEFINED,
SOFT_INPUT_ADJUST_NOTHING, 0 /* windowFlags */);
assertEquals(Insets.of(0, 300, 0, 0), visibleInsets);
}
@@ -269,7 +271,7 @@
.setFrame(new Rect(80, 0, 100, 300))
.setVisible(true);
WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
- false, 0, 0, 0, TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED, null);
+ 0, 0, 0, TYPE_APPLICATION, ACTIVITY_TYPE_UNDEFINED, null);
assertEquals(Insets.of(0, 100, 20, 0), insets.getSystemWindowInsets());
assertEquals(Insets.of(0, 100, 0, 0), insets.getInsets(statusBars()));
assertEquals(Insets.of(0, 0, 20, 0), insets.getInsets(navigationBars()));
@@ -284,7 +286,7 @@
.setFrame(new Rect(80, 0, 100, 300))
.setVisible(true);
WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
- false, 0, 0, 0, TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED, null);
+ 0, 0, 0, TYPE_APPLICATION, ACTIVITY_TYPE_UNDEFINED, null);
assertEquals(Insets.of(0, 100, 20, 0), insets.getSystemWindowInsets());
assertEquals(Insets.of(0, 100, 0, 0), insets.getInsets(statusBars()));
assertEquals(Insets.of(0, 0, 20, 0), insets.getInsets(navigationBars()));
@@ -292,11 +294,11 @@
@Test
public void testCalculateInsets_emptyIme() {
- WindowInsets insets1 = mState.calculateInsets(new Rect(), null, false, false,
- SOFT_INPUT_ADJUST_NOTHING, 0, 0, TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED, null);
+ WindowInsets insets1 = mState.calculateInsets(new Rect(), null, false,
+ SOFT_INPUT_ADJUST_NOTHING, 0, 0, TYPE_APPLICATION, ACTIVITY_TYPE_UNDEFINED, null);
mState.getOrCreateSource(ID_IME, ime());
- WindowInsets insets2 = mState.calculateInsets(new Rect(), null, false, false,
- SOFT_INPUT_ADJUST_NOTHING, 0, 0, TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED, null);
+ WindowInsets insets2 = mState.calculateInsets(new Rect(), null, false,
+ SOFT_INPUT_ADJUST_NOTHING, 0, 0, TYPE_APPLICATION, ACTIVITY_TYPE_UNDEFINED, null);
assertEquals(Insets.NONE, insets1.getInsets(ime()));
assertEquals(Insets.NONE, insets2.getInsets(ime()));
assertEquals(insets1, insets2);
@@ -311,8 +313,8 @@
.setFrame(new Rect(0, 200, 100, 300))
.setVisible(true);
mState.removeSource(ID_IME);
- WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false, false,
- SOFT_INPUT_ADJUST_RESIZE, 0, 0, TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED, null);
+ WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
+ SOFT_INPUT_ADJUST_RESIZE, 0, 0, TYPE_APPLICATION, ACTIVITY_TYPE_UNDEFINED, null);
assertEquals(0, insets.getSystemWindowInsetBottom());
}
@@ -527,7 +529,7 @@
.setFrame(new Rect(0, 100, 100, 300))
.setVisible(true);
Insets visibleInsets = mState.calculateVisibleInsets(
- new Rect(0, 0, 100, 300), TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED,
+ new Rect(0, 0, 100, 300), TYPE_APPLICATION, ACTIVITY_TYPE_UNDEFINED,
SOFT_INPUT_ADJUST_PAN, 0 /* windowFlags */);
assertEquals(Insets.of(0, 100, 0, 100), visibleInsets);
}
@@ -546,7 +548,7 @@
.setFrame(new Rect(0, 100, 100, 300))
.setVisible(true);
Insets visibleInsets = mState.calculateVisibleInsets(
- new Rect(0, 0, 100, 300), TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED,
+ new Rect(0, 0, 100, 300), TYPE_APPLICATION, ACTIVITY_TYPE_UNDEFINED,
SOFT_INPUT_ADJUST_NOTHING, 0 /* windowFlags */);
assertEquals(Insets.of(0, 100, 0, 0), visibleInsets);
}
@@ -565,7 +567,7 @@
.setFrame(new Rect(0, 100, 100, 300))
.setVisible(true);
Insets visibleInsets = mState.calculateVisibleInsets(
- new Rect(0, 0, 100, 300), TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED,
+ new Rect(0, 0, 100, 300), TYPE_APPLICATION, ACTIVITY_TYPE_UNDEFINED,
SOFT_INPUT_ADJUST_PAN, FLAG_LAYOUT_NO_LIMITS);
assertEquals(Insets.NONE, visibleInsets);
}
@@ -599,8 +601,8 @@
new Rect(0, 0, 1, 2),
new Rect(197, 296, 200, 300),
new Rect(197, 296, 200, 300)));
- DisplayCutout cutout = mState.calculateInsets(new Rect(1, 1, 199, 300), null, false, false,
- SOFT_INPUT_ADJUST_UNSPECIFIED, 0, 0, TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED,
+ DisplayCutout cutout = mState.calculateInsets(new Rect(1, 1, 199, 300), null, false,
+ SOFT_INPUT_ADJUST_UNSPECIFIED, 0, 0, TYPE_APPLICATION, ACTIVITY_TYPE_UNDEFINED,
new SparseIntArray()).getDisplayCutout();
assertEquals(0, cutout.getSafeInsetLeft());
assertEquals(1, cutout.getSafeInsetTop());
@@ -625,8 +627,8 @@
new RoundedCorner(POSITION_BOTTOM_RIGHT, 20, 180, 380),
new RoundedCorner(POSITION_BOTTOM_LEFT, 20, 20, 380)));
WindowInsets windowInsets = mState.calculateInsets(new Rect(1, 2, 197, 396), null, false,
- false, SOFT_INPUT_ADJUST_UNSPECIFIED, 0, 0, TYPE_APPLICATION,
- WINDOWING_MODE_UNDEFINED, new SparseIntArray());
+ SOFT_INPUT_ADJUST_UNSPECIFIED, 0, 0, TYPE_APPLICATION,
+ ACTIVITY_TYPE_UNDEFINED, new SparseIntArray());
assertEquals(new RoundedCorner(POSITION_TOP_LEFT, 10, 9, 8),
windowInsets.getRoundedCorner(POSITION_TOP_LEFT));
assertEquals(new RoundedCorner(POSITION_TOP_RIGHT, 10, 189, 8),
@@ -642,8 +644,8 @@
mState.setDisplayFrame(new Rect(0, 0, 200, 400));
mState.setDisplayShape(DisplayShape.createDefaultDisplayShape(200, 400, false));
WindowInsets windowInsets = mState.calculateInsets(new Rect(10, 20, 200, 400), null, false,
- false, SOFT_INPUT_ADJUST_UNSPECIFIED, 0, 0, TYPE_APPLICATION,
- WINDOWING_MODE_UNDEFINED, new SparseIntArray());
+ SOFT_INPUT_ADJUST_UNSPECIFIED, 0, 0, TYPE_APPLICATION,
+ ACTIVITY_TYPE_UNDEFINED, new SparseIntArray());
final DisplayShape expect =
DisplayShape.createDefaultDisplayShape(200, 400, false).setOffset(-10, -20);
diff --git a/libs/WindowManager/Shell/tests/flicker/Android.bp b/libs/WindowManager/Shell/tests/flicker/Android.bp
index eb650ca..434b008 100644
--- a/libs/WindowManager/Shell/tests/flicker/Android.bp
+++ b/libs/WindowManager/Shell/tests/flicker/Android.bp
@@ -126,7 +126,6 @@
"flickertestapplib",
"flickerlib",
"flickerlib-helpers",
- "flickerlib-trace_processor_shell",
"platform-test-annotations",
"wm-flicker-common-app-helpers",
"wm-flicker-common-assertions",
diff --git a/libs/WindowManager/Shell/tests/flicker/manifests/AndroidManifest.xml b/libs/WindowManager/Shell/tests/flicker/manifests/AndroidManifest.xml
index ae130b8..6a87de4 100644
--- a/libs/WindowManager/Shell/tests/flicker/manifests/AndroidManifest.xml
+++ b/libs/WindowManager/Shell/tests/flicker/manifests/AndroidManifest.xml
@@ -45,13 +45,9 @@
<uses-permission android:name="android.permission.MANAGE_ACTIVITY_TASKS" />
<!-- Enable bubble notification-->
<uses-permission android:name="android.permission.STATUS_BAR_SERVICE" />
- <!-- Allow the test to connect to perfetto trace processor -->
- <uses-permission android:name="android.permission.INTERNET"/>
- <!-- Allow the test to write directly to /sdcard/ and connect to trace processor -->
- <application android:requestLegacyExternalStorage="true"
- android:networkSecurityConfig="@xml/network_security_config"
- android:largeHeap="true">
+ <!-- Allow the test to write directly to /sdcard/ -->
+ <application android:requestLegacyExternalStorage="true" android:largeHeap="true">
<uses-library android:name="android.test.runner"/>
<service android:name=".NotificationListener"
diff --git a/libs/WindowManager/Shell/tests/flicker/res/xml/network_security_config.xml b/libs/WindowManager/Shell/tests/flicker/res/xml/network_security_config.xml
deleted file mode 100644
index 4bd9ca0..0000000
--- a/libs/WindowManager/Shell/tests/flicker/res/xml/network_security_config.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2023 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<network-security-config>
- <domain-config cleartextTrafficPermitted="true">
- <domain includeSubdomains="true">localhost</domain>
- </domain-config>
-</network-security-config>
diff --git a/packages/SystemUI/src/com/android/systemui/display/data/repository/DisplayRepository.kt b/packages/SystemUI/src/com/android/systemui/display/data/repository/DisplayRepository.kt
index e7bbf97..f68078a 100644
--- a/packages/SystemUI/src/com/android/systemui/display/data/repository/DisplayRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/display/data/repository/DisplayRepository.kt
@@ -22,6 +22,7 @@
import android.hardware.display.DisplayManager.EVENT_FLAG_DISPLAY_CHANGED
import android.hardware.display.DisplayManager.EVENT_FLAG_DISPLAY_REMOVED
import android.os.Handler
+import android.os.Trace
import android.util.Log
import android.view.Display
import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
@@ -34,9 +35,14 @@
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flowOn
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.stateIn
/** Provides a [Flow] of [Display] as returned by [DisplayManager]. */
@@ -49,7 +55,25 @@
*
* When `null`, it means there is no pending display waiting to be enabled.
*/
- val pendingDisplayId: Flow<Int?>
+ val pendingDisplay: Flow<PendingDisplay?>
+
+ /** Represents a connected display that has not been enabled yet. */
+ interface PendingDisplay {
+ /** Id of the pending display. */
+ val id: Int
+
+ /** Enables the display, making it available to the system. */
+ suspend fun enable()
+
+ /**
+ * Ignores the pending display. When called, this specific display id doesn't appear as
+ * pending anymore until the display is disconnected and reconnected again.
+ */
+ suspend fun ignore()
+
+ /** Disables the display, making it unavailable to the system. */
+ suspend fun disable()
+ }
}
@SysUISingleton
@@ -62,7 +86,8 @@
@Background backgroundCoroutineDispatcher: CoroutineDispatcher
) : DisplayRepository {
- override val displays: Flow<Set<Display>> =
+ // Displays are enabled only after receiving them in [onDisplayAdded]
+ private val enabledDisplays: StateFlow<Set<Display>> =
conflatedCallbackFlow {
val callback =
object : DisplayListener {
@@ -99,27 +124,38 @@
displayManager.displays?.toSet() ?: emptySet()
}
- override val pendingDisplayId: Flow<Int?> =
+ /** Propagate to the listeners only enabled displays */
+ override val displays: Flow<Set<Display>> = enabledDisplays
+
+ private val enabledDisplayIds: Flow<Set<Int>> =
+ enabledDisplays
+ .map { enabledDisplaysSet -> enabledDisplaysSet.map { it.displayId }.toSet() }
+ .debugLog("enabledDisplayIds")
+
+ private val ignoredDisplayIds = MutableStateFlow<Set<Int>>(emptySet())
+
+ /* keeps connected displays until they are disconnected. */
+ private val connectedDisplayIds: StateFlow<Set<Int>> =
conflatedCallbackFlow {
val callback =
object : DisplayConnectionListener {
- private val pendingIds = mutableSetOf<Int>()
+ private val connectedIds = mutableSetOf<Int>()
override fun onDisplayConnected(id: Int) {
- pendingIds += id
- trySend(id)
+ if (DEBUG) {
+ Log.d(TAG, "$id connected")
+ }
+ connectedIds += id
+ ignoredDisplayIds.value -= id
+ trySend(connectedIds.toSet())
}
override fun onDisplayDisconnected(id: Int) {
- if (id in pendingIds) {
- pendingIds -= id
- trySend(null)
- } else {
- Log.e(
- TAG,
- "onDisplayDisconnected received for unknown display. " +
- "id=$id, knownIds=$pendingIds"
- )
+ connectedIds -= id
+ if (DEBUG) {
+ Log.d(TAG, "$id disconnected. Connected ids: $connectedIds")
}
+ ignoredDisplayIds.value -= id
+ trySend(connectedIds.toSet())
}
}
displayManager.registerDisplayListener(
@@ -130,15 +166,80 @@
awaitClose { displayManager.unregisterDisplayListener(callback) }
}
.distinctUntilChanged()
+ .debugLog("connectedDisplayIds")
.flowOn(backgroundCoroutineDispatcher)
.stateIn(
applicationScope,
started = SharingStarted.WhileSubscribed(),
- initialValue = null
+ initialValue = emptySet()
)
+ /**
+ * Pending displays are the ones connected, but not enabled and not ignored. A connected display
+ * is ignored after the user makes the decision to use it or not. For now, the initial decision
+ * from the user is final and not reversible.
+ */
+ private val pendingDisplayIds: Flow<Set<Int>> =
+ combine(enabledDisplayIds, connectedDisplayIds, ignoredDisplayIds) {
+ enabledDisplaysIds,
+ connectedDisplayIds,
+ ignoredDisplayIds ->
+ if (DEBUG) {
+ Log.d(
+ TAG,
+ "combining enabled: $enabledDisplaysIds, " +
+ "connected: $connectedDisplayIds, ignored: $ignoredDisplayIds"
+ )
+ }
+ connectedDisplayIds - enabledDisplaysIds - ignoredDisplayIds
+ }
+ .debugLog("pendingDisplayIds")
+
+ override val pendingDisplay: Flow<DisplayRepository.PendingDisplay?> =
+ pendingDisplayIds
+ .map { pendingDisplayIds ->
+ val id = pendingDisplayIds.maxOrNull() ?: return@map null
+ object : DisplayRepository.PendingDisplay {
+ override val id = id
+ override suspend fun enable() {
+ traceSection("DisplayRepository#enable($id)") {
+ displayManager.enableConnectedDisplay(id)
+ }
+ // After the display has been enabled, it is automatically ignored.
+ ignore()
+ }
+
+ override suspend fun ignore() {
+ traceSection("DisplayRepository#ignore($id)") {
+ ignoredDisplayIds.value += id
+ }
+ }
+
+ override suspend fun disable() {
+ ignore()
+ traceSection("DisplayRepository#disable($id)") {
+ displayManager.disableConnectedDisplay(id)
+ }
+ }
+ }
+ }
+ .debugLog("pendingDisplay")
+
+ private fun <T> Flow<T>.debugLog(flowName: String): Flow<T> {
+ return if (DEBUG) {
+ this.onEach {
+ Log.d(TAG, "$flowName: $it")
+ Trace.asyncTraceForTrackEnd(Trace.TRACE_TAG_APP, "$TAG#$flowName", 0)
+ Trace.asyncTraceForTrackBegin(Trace.TRACE_TAG_APP, "$TAG#$flowName", "$it", 0)
+ }
+ } else {
+ this
+ }
+ }
+
private companion object {
const val TAG = "DisplayRepository"
+ val DEBUG = Log.isLoggable(TAG, Log.DEBUG)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/display/domain/interactor/ConnectedDisplayInteractor.kt b/packages/SystemUI/src/com/android/systemui/display/domain/interactor/ConnectedDisplayInteractor.kt
index ef6fa26..11ed96d 100644
--- a/packages/SystemUI/src/com/android/systemui/display/domain/interactor/ConnectedDisplayInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/display/domain/interactor/ConnectedDisplayInteractor.kt
@@ -16,14 +16,12 @@
package com.android.systemui.display.domain.interactor
-import android.hardware.display.DisplayManager
import android.view.Display
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.display.data.repository.DisplayRepository
import com.android.systemui.display.domain.interactor.ConnectedDisplayInteractor.PendingDisplay
import com.android.systemui.display.domain.interactor.ConnectedDisplayInteractor.State
import com.android.systemui.keyguard.data.repository.KeyguardRepository
-import com.android.systemui.util.traceSection
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
@@ -52,13 +50,18 @@
CONNECTED_SECURE,
}
- /** Represents a connected display that has not been enabled yet. */
+ /** Represents a connected display that has not been enabled yet for the UI layer. */
interface PendingDisplay {
/** Enables the display, making it available to the system. */
- fun enable()
+ suspend fun enable()
- /** Disables the display, making it unavailable to the system. */
- fun disable()
+ /**
+ * Ignores the pending display.
+ *
+ * When called, this specific display id doesn't appear as pending anymore until the display
+ * is disconnected and reconnected again.
+ */
+ suspend fun ignore()
}
}
@@ -66,7 +69,6 @@
class ConnectedDisplayInteractorImpl
@Inject
constructor(
- private val displayManager: DisplayManager,
keyguardRepository: KeyguardRepository,
displayRepository: DisplayRepository,
) : ConnectedDisplayInteractor {
@@ -92,28 +94,19 @@
// Provides the pending display only if the lockscreen is unlocked
override val pendingDisplay: Flow<PendingDisplay?> =
- displayRepository.pendingDisplayId.combine(keyguardRepository.isKeyguardUnlocked) {
- pendingDisplayId,
- keyguardUnlocked ->
- if (pendingDisplayId != null && keyguardUnlocked) {
- pendingDisplayId.toPendingDisplay()
+ displayRepository.pendingDisplay.combine(keyguardRepository.isKeyguardShowing) {
+ repositoryPendingDisplay,
+ keyguardShowing ->
+ if (repositoryPendingDisplay != null && !keyguardShowing) {
+ repositoryPendingDisplay.toInteractorPendingDisplay()
} else {
null
}
}
- private fun Int.toPendingDisplay() =
+ private fun DisplayRepository.PendingDisplay.toInteractorPendingDisplay(): PendingDisplay =
object : PendingDisplay {
- val id = this@toPendingDisplay
- override fun enable() {
- traceSection("DisplayRepository#enable($id)") {
- displayManager.enableConnectedDisplay(id)
- }
- }
- override fun disable() {
- traceSection("DisplayRepository#enable($id)") {
- displayManager.disableConnectedDisplay(id)
- }
- }
+ override suspend fun enable() = this@toInteractorPendingDisplay.enable()
+ override suspend fun ignore() = this@toInteractorPendingDisplay.ignore()
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/display/ui/view/MirroringConfirmationDialog.kt b/packages/SystemUI/src/com/android/systemui/display/ui/view/MirroringConfirmationDialog.kt
index 174c6ff..ecc9d0e 100644
--- a/packages/SystemUI/src/com/android/systemui/display/ui/view/MirroringConfirmationDialog.kt
+++ b/packages/SystemUI/src/com/android/systemui/display/ui/view/MirroringConfirmationDialog.kt
@@ -24,15 +24,22 @@
import android.widget.TextView
import com.android.systemui.R
-/** Dialog used to decide what to do with a connected display. */
+/**
+ * Dialog used to decide what to do with a connected display.
+ *
+ * [onCancelMirroring] is called **only** if mirroring didn't start, or when the dismiss button is
+ * pressed.
+ */
class MirroringConfirmationDialog(
context: Context,
private val onStartMirroringClickListener: View.OnClickListener,
- private val onDismissClickListener: View.OnClickListener,
+ private val onCancelMirroring: View.OnClickListener,
) : Dialog(context, R.style.Theme_SystemUI_Dialog) {
private lateinit var mirrorButton: TextView
private lateinit var dismissButton: TextView
+ private var enabledPressed = false
+
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
window?.apply {
@@ -45,10 +52,15 @@
mirrorButton =
requireViewById<TextView>(R.id.enable_display).apply {
setOnClickListener(onStartMirroringClickListener)
+ enabledPressed = true
}
dismissButton =
- requireViewById<TextView>(R.id.cancel).apply {
- setOnClickListener(onDismissClickListener)
+ requireViewById<TextView>(R.id.cancel).apply { setOnClickListener(onCancelMirroring) }
+
+ setOnDismissListener {
+ if (!enabledPressed) {
+ onCancelMirroring.onClick(null)
}
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/display/ui/viewmodel/ConnectingDisplayViewModel.kt b/packages/SystemUI/src/com/android/systemui/display/ui/viewmodel/ConnectingDisplayViewModel.kt
index ece33b7..86ef439 100644
--- a/packages/SystemUI/src/com/android/systemui/display/ui/viewmodel/ConnectingDisplayViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/display/ui/viewmodel/ConnectingDisplayViewModel.kt
@@ -19,13 +19,16 @@
import android.content.Context
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.display.domain.interactor.ConnectedDisplayInteractor
import com.android.systemui.display.domain.interactor.ConnectedDisplayInteractor.PendingDisplay
import com.android.systemui.display.ui.view.MirroringConfirmationDialog
import javax.inject.Inject
+import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.launch
/**
* Shows/hides a dialog to allow the user to decide whether to use the external display for
@@ -38,6 +41,7 @@
private val context: Context,
private val connectedDisplayInteractor: ConnectedDisplayInteractor,
@Application private val scope: CoroutineScope,
+ @Background private val bgDispatcher: CoroutineDispatcher
) {
private var dialog: Dialog? = null
@@ -61,10 +65,13 @@
MirroringConfirmationDialog(
context,
onStartMirroringClickListener = {
- pendingDisplay.enable()
+ scope.launch(bgDispatcher) { pendingDisplay.enable() }
hideDialog()
},
- onDismissClickListener = { hideDialog() }
+ onCancelMirroring = {
+ scope.launch(bgDispatcher) { pendingDisplay.ignore() }
+ hideDialog()
+ }
)
.apply { show() }
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt
index 6bc9abf..257006e 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt
@@ -126,11 +126,11 @@
}
override fun start() {
+ bindKeyguardRootView()
if (featureFlags.isEnabled(Flags.LAZY_INFLATE_KEYGUARD)) {
keyguardRootView.removeAllViews()
initializeViews()
} else {
- bindKeyguardRootView()
val notificationPanel =
notificationShadeWindowView.requireViewById(R.id.notification_panel) as ViewGroup
unbindKeyguardBottomArea(notificationPanel)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/display/data/repository/DisplayRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/display/data/repository/DisplayRepositoryTest.kt
index db7c003..4bd380e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/display/data/repository/DisplayRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/display/data/repository/DisplayRepositoryTest.kt
@@ -52,6 +52,7 @@
private val displayManager = mock<DisplayManager>()
private val displayListener = kotlinArgumentCaptor<DisplayManager.DisplayListener>()
+ private val connectedDisplayListener = kotlinArgumentCaptor<DisplayManager.DisplayListener>()
private val testHandler = FakeHandler(Looper.getMainLooper())
private val testScope = TestScope(UnconfinedTestDispatcher())
@@ -114,7 +115,7 @@
// Let's make sure it has *NOT* been unregistered, as there is still a subscriber.
setDisplays(1)
- displayListener.value.onDisplayAdded(1)
+ sendOnDisplayAdded(1)
assertThat(firstSubscriber?.ids()).containsExactly(1)
}
@@ -127,7 +128,7 @@
val value by latestDisplayFlowValue()
setDisplays(1)
- displayListener.value.onDisplayAdded(1)
+ sendOnDisplayAdded(1)
assertThat(value?.ids()).containsExactly(1)
}
@@ -138,13 +139,13 @@
val value by latestDisplayFlowValue()
setDisplays(1, 2, 3, 4)
- displayListener.value.onDisplayAdded(1)
- displayListener.value.onDisplayAdded(2)
- displayListener.value.onDisplayAdded(3)
- displayListener.value.onDisplayAdded(4)
+ sendOnDisplayAdded(1)
+ sendOnDisplayAdded(2)
+ sendOnDisplayAdded(3)
+ sendOnDisplayAdded(4)
setDisplays(1, 2, 3)
- displayListener.value.onDisplayRemoved(4)
+ sendOnDisplayRemoved(4)
assertThat(value?.ids()).containsExactly(1, 2, 3)
}
@@ -155,10 +156,10 @@
val value by latestDisplayFlowValue()
setDisplays(1, 2, 3, 4)
- displayListener.value.onDisplayAdded(1)
- displayListener.value.onDisplayAdded(2)
- displayListener.value.onDisplayAdded(3)
- displayListener.value.onDisplayAdded(4)
+ sendOnDisplayAdded(1)
+ sendOnDisplayAdded(2)
+ sendOnDisplayAdded(3)
+ sendOnDisplayAdded(4)
displayListener.value.onDisplayChanged(4)
@@ -168,22 +169,22 @@
@Test
fun onDisplayConnected_pendingDisplayReceived() =
testScope.runTest {
- val pendingDisplay by latestPendingDisplayFlowValue()
+ val pendingDisplay by lastPendingDisplay()
- displayListener.value.onDisplayConnected(1)
+ sendOnDisplayConnected(1)
- assertThat(pendingDisplay).isEqualTo(1)
+ assertThat(pendingDisplay!!.id).isEqualTo(1)
}
@Test
fun onDisplayDisconnected_pendingDisplayNull() =
testScope.runTest {
- val pendingDisplay by latestPendingDisplayFlowValue()
- displayListener.value.onDisplayConnected(1)
+ val pendingDisplay by lastPendingDisplay()
+ sendOnDisplayConnected(1)
assertThat(pendingDisplay).isNotNull()
- displayListener.value.onDisplayDisconnected(1)
+ sendOnDisplayDisconnected(1)
assertThat(pendingDisplay).isNull()
}
@@ -191,24 +192,162 @@
@Test
fun onDisplayDisconnected_unknownDisplay_doesNotSendNull() =
testScope.runTest {
- val pendingDisplay by latestPendingDisplayFlowValue()
- displayListener.value.onDisplayConnected(1)
+ val pendingDisplay by lastPendingDisplay()
+ sendOnDisplayConnected(1)
assertThat(pendingDisplay).isNotNull()
- displayListener.value.onDisplayDisconnected(2)
+ sendOnDisplayDisconnected(2)
assertThat(pendingDisplay).isNotNull()
}
@Test
- fun onDisplayConnected_multipleTimes_sendsOnlyTheLastOne() =
+ fun onDisplayConnected_multipleTimes_sendsOnlyTheMaximum() =
testScope.runTest {
- val pendingDisplay by latestPendingDisplayFlowValue()
- displayListener.value.onDisplayConnected(1)
- displayListener.value.onDisplayConnected(2)
+ val pendingDisplay by lastPendingDisplay()
- assertThat(pendingDisplay).isEqualTo(2)
+ sendOnDisplayConnected(1)
+ sendOnDisplayConnected(2)
+
+ assertThat(pendingDisplay!!.id).isEqualTo(2)
+ }
+
+ @Test
+ fun onPendingDisplay_enable_displayEnabled() =
+ testScope.runTest {
+ val pendingDisplay by lastPendingDisplay()
+
+ sendOnDisplayConnected(1)
+ pendingDisplay!!.enable()
+
+ verify(displayManager).enableConnectedDisplay(eq(1))
+ }
+
+ @Test
+ fun onPendingDisplay_enableBySysui_disabledBySomeoneElse_pendingDisplayStillIgnored() =
+ testScope.runTest {
+ val pendingDisplay by lastPendingDisplay()
+
+ sendOnDisplayConnected(1)
+ pendingDisplay!!.enable()
+ // to mock the display being really enabled:
+ sendOnDisplayAdded(1)
+
+ // Simulate the display being disabled by someone else. Now, sysui will have it in the
+ // "pending displays" list again, but it should be ignored.
+ sendOnDisplayRemoved(1)
+
+ assertThat(pendingDisplay).isNull()
+ }
+
+ @Test
+ fun onPendingDisplay_ignoredBySysui_enabledDisabledBySomeoneElse_pendingDisplayStillIgnored() =
+ testScope.runTest {
+ val pendingDisplay by lastPendingDisplay()
+
+ sendOnDisplayConnected(1)
+ pendingDisplay!!.ignore()
+
+ // to mock the display being enabled and disabled by someone else:
+ sendOnDisplayAdded(1)
+ sendOnDisplayRemoved(1)
+
+ // Sysui already decided to ignore it, so the pending display should be null.
+ assertThat(pendingDisplay).isNull()
+ }
+
+ @Test
+ fun onPendingDisplay_disable_displayDisabled() =
+ testScope.runTest {
+ val pendingDisplay by lastPendingDisplay()
+
+ sendOnDisplayConnected(1)
+ pendingDisplay!!.disable()
+
+ verify(displayManager).disableConnectedDisplay(eq(1))
+ }
+
+ @Test
+ fun onPendingDisplay_ignore_pendingDisplayNull() =
+ testScope.runTest {
+ val pendingDisplay by lastPendingDisplay()
+ sendOnDisplayConnected(1)
+
+ pendingDisplay!!.ignore()
+
+ assertThat(pendingDisplay).isNull()
+ verify(displayManager, never()).disableConnectedDisplay(eq(1))
+ verify(displayManager, never()).enableConnectedDisplay(eq(1))
+ }
+
+ @Test
+ fun onPendingDisplay_enabled_pendingDisplayNull() =
+ testScope.runTest {
+ val pendingDisplay by lastPendingDisplay()
+
+ sendOnDisplayConnected(1)
+ assertThat(pendingDisplay).isNotNull()
+
+ setDisplays(1)
+ sendOnDisplayAdded(1)
+
+ assertThat(pendingDisplay).isNull()
+ }
+
+ @Test
+ fun onPendingDisplay_multipleConnected_oneEnabled_pendingDisplayNotNull() =
+ testScope.runTest {
+ val pendingDisplay by lastPendingDisplay()
+
+ sendOnDisplayConnected(1)
+ sendOnDisplayConnected(2)
+
+ assertThat(pendingDisplay).isNotNull()
+
+ setDisplays(1)
+ sendOnDisplayAdded(1)
+
+ assertThat(pendingDisplay).isNotNull()
+ assertThat(pendingDisplay!!.id).isEqualTo(2)
+
+ setDisplays(1, 2)
+ sendOnDisplayAdded(2)
+
+ assertThat(pendingDisplay).isNull()
+ }
+
+ @Test
+ fun pendingDisplay_connectedDisconnectedAndReconnected_expectedPendingDisplayState() =
+ testScope.runTest {
+ val pendingDisplay by lastPendingDisplay()
+
+ // Plug the cable
+ sendOnDisplayConnected(1)
+
+ // Enable it
+ assertThat(pendingDisplay).isNotNull()
+ pendingDisplay!!.enable()
+
+ // Enabled
+ verify(displayManager).enableConnectedDisplay(1)
+ setDisplays(1)
+ sendOnDisplayAdded(1)
+
+ // No more pending displays
+ assertThat(pendingDisplay).isNull()
+
+ // Let's disconnect the cable
+ setDisplays()
+ sendOnDisplayRemoved(1)
+ sendOnDisplayDisconnected(1)
+
+ assertThat(pendingDisplay).isNull()
+
+ // Let's reconnect it
+ sendOnDisplayConnected(1)
+
+ assertThat(pendingDisplay).isNotNull()
}
private fun Iterable<Display>.ids(): List<Int> = map { it.displayId }
@@ -216,6 +355,23 @@
// Wrapper to capture the displayListener.
private fun TestScope.latestDisplayFlowValue(): FlowValue<Set<Display>?> {
val flowValue = collectLastValue(displayRepository.displays)
+ captureAddedRemovedListener()
+ return flowValue
+ }
+
+ private fun TestScope.lastPendingDisplay(): FlowValue<DisplayRepository.PendingDisplay?> {
+ val flowValue = collectLastValue(displayRepository.pendingDisplay)
+ captureAddedRemovedListener()
+ verify(displayManager)
+ .registerDisplayListener(
+ connectedDisplayListener.capture(),
+ eq(testHandler),
+ eq(DisplayManager.EVENT_FLAG_DISPLAY_CONNECTION_CHANGED)
+ )
+ return flowValue
+ }
+
+ private fun captureAddedRemovedListener() {
verify(displayManager)
.registerDisplayListener(
displayListener.capture(),
@@ -226,18 +382,20 @@
DisplayManager.EVENT_FLAG_DISPLAY_REMOVED
)
)
- return flowValue
+ }
+ private fun sendOnDisplayAdded(id: Int) {
+ displayListener.value.onDisplayAdded(id)
+ }
+ private fun sendOnDisplayRemoved(id: Int) {
+ displayListener.value.onDisplayRemoved(id)
}
- private fun TestScope.latestPendingDisplayFlowValue(): FlowValue<Int?> {
- val flowValue = collectLastValue(displayRepository.pendingDisplayId)
- verify(displayManager)
- .registerDisplayListener(
- displayListener.capture(),
- eq(testHandler),
- eq(DisplayManager.EVENT_FLAG_DISPLAY_CONNECTION_CHANGED)
- )
- return flowValue
+ private fun sendOnDisplayDisconnected(id: Int) {
+ connectedDisplayListener.value.onDisplayDisconnected(id)
+ }
+
+ private fun sendOnDisplayConnected(id: Int) {
+ connectedDisplayListener.value.onDisplayConnected(id)
}
private fun setDisplays(displays: List<Display>) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/display/domain/interactor/ConnectedDisplayInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/display/domain/interactor/ConnectedDisplayInteractorTest.kt
index 50617a1..26ee094 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/display/domain/interactor/ConnectedDisplayInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/display/domain/interactor/ConnectedDisplayInteractorTest.kt
@@ -16,7 +16,6 @@
package com.android.systemui.display.domain.interactor
-import android.hardware.display.DisplayManager
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
import android.view.Display
@@ -27,12 +26,11 @@
import com.android.systemui.coroutines.FlowValue
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.display.data.repository.FakeDisplayRepository
+import com.android.systemui.display.data.repository.createPendingDisplay
import com.android.systemui.display.data.repository.display
import com.android.systemui.display.domain.interactor.ConnectedDisplayInteractor.PendingDisplay
import com.android.systemui.display.domain.interactor.ConnectedDisplayInteractor.State
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
-import com.android.systemui.util.mockito.eq
-import com.android.systemui.util.mockito.mock
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.TestScope
@@ -41,7 +39,6 @@
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
-import org.mockito.Mockito
@RunWith(AndroidTestingRunner::class)
@TestableLooper.RunWithLooper
@@ -49,20 +46,15 @@
@SmallTest
class ConnectedDisplayInteractorTest : SysuiTestCase() {
- private val displayManager = mock<DisplayManager>()
private val fakeDisplayRepository = FakeDisplayRepository()
private val fakeKeyguardRepository = FakeKeyguardRepository()
private val connectedDisplayStateProvider: ConnectedDisplayInteractor =
- ConnectedDisplayInteractorImpl(
- displayManager,
- fakeKeyguardRepository,
- fakeDisplayRepository
- )
+ ConnectedDisplayInteractorImpl(fakeKeyguardRepository, fakeDisplayRepository)
private val testScope = TestScope(UnconfinedTestDispatcher())
@Before
fun setup() {
- fakeKeyguardRepository.setKeyguardUnlocked(true)
+ fakeKeyguardRepository.setKeyguardShowing(false)
}
@Test
@@ -148,7 +140,7 @@
fun pendingDisplay_propagated() =
testScope.runTest {
val value by lastPendingDisplay()
- val pendingDisplayId = 4
+ val pendingDisplayId = createPendingDisplay()
fakeDisplayRepository.emit(pendingDisplayId)
@@ -156,51 +148,29 @@
}
@Test
- fun onPendingDisplay_enable_displayEnabled() =
+ fun onPendingDisplay_keyguardShowing_returnsPendingDisplay() =
testScope.runTest {
+ fakeKeyguardRepository.setKeyguardShowing(true)
val pendingDisplay by lastPendingDisplay()
- fakeDisplayRepository.emit(1)
- pendingDisplay!!.enable()
-
- Mockito.verify(displayManager).enableConnectedDisplay(eq(1))
- }
-
- @Test
- fun onPendingDisplay_disable_displayDisabled() =
- testScope.runTest {
- val pendingDisplay by lastPendingDisplay()
-
- fakeDisplayRepository.emit(1)
- pendingDisplay!!.disable()
-
- Mockito.verify(displayManager).disableConnectedDisplay(eq(1))
- }
-
- @Test
- fun onPendingDisplay_keyguardUnlocked_returnsPendingDisplay() =
- testScope.runTest {
- fakeKeyguardRepository.setKeyguardUnlocked(false)
- val pendingDisplay by lastPendingDisplay()
-
- fakeDisplayRepository.emit(1)
+ fakeDisplayRepository.emit(createPendingDisplay())
assertThat(pendingDisplay).isNull()
- fakeKeyguardRepository.setKeyguardUnlocked(true)
+ fakeKeyguardRepository.setKeyguardShowing(false)
assertThat(pendingDisplay).isNotNull()
}
@Test
- fun onPendingDisplay_keyguardLocked_returnsNull() =
+ fun onPendingDisplay_keyguardShowing_returnsNull() =
testScope.runTest {
- fakeKeyguardRepository.setKeyguardUnlocked(true)
+ fakeKeyguardRepository.setKeyguardShowing(false)
val pendingDisplay by lastPendingDisplay()
- fakeDisplayRepository.emit(1)
+ fakeDisplayRepository.emit(createPendingDisplay())
assertThat(pendingDisplay).isNotNull()
- fakeKeyguardRepository.setKeyguardUnlocked(false)
+ fakeKeyguardRepository.setKeyguardShowing(true)
assertThat(pendingDisplay).isNull()
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/display/ui/view/MirroringConfirmationDialogTest.kt b/packages/SystemUI/tests/src/com/android/systemui/display/ui/view/MirroringConfirmationDialogTest.kt
index 7059647..46f7582 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/display/ui/view/MirroringConfirmationDialogTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/display/ui/view/MirroringConfirmationDialogTest.kt
@@ -68,6 +68,28 @@
verify(onStartMirroringCallback, never()).onClick(any())
}
+ @Test
+ fun onCancel_afterEnablingMirroring_cancelCallbackNotCalled() {
+ dialog.show()
+ dialog.requireViewById<View>(R.id.enable_display).callOnClick()
+
+ dialog.cancel()
+
+ verify(onCancelCallback, never()).onClick(any())
+ verify(onStartMirroringCallback).onClick(any())
+ }
+
+ @Test
+ fun onDismiss_afterEnablingMirroring_cancelCallbackNotCalled() {
+ dialog.show()
+ dialog.requireViewById<View>(R.id.enable_display).callOnClick()
+
+ dialog.dismiss()
+
+ verify(onCancelCallback, never()).onClick(any())
+ verify(onStartMirroringCallback).onClick(any())
+ }
+
@After
fun teardown() {
if (::dialog.isInitialized) {
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/display/data/repository/FakeDisplayRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/display/data/repository/FakeDisplayRepository.kt
index 6f51d1b..2ac625d 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/display/data/repository/FakeDisplayRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/display/data/repository/FakeDisplayRepository.kt
@@ -30,20 +30,24 @@
}
}
+/** Creates a mock [DisplayRepository.PendingDisplay]. */
+fun createPendingDisplay(id: Int = 0): DisplayRepository.PendingDisplay =
+ mock<DisplayRepository.PendingDisplay> { whenever(this.id).thenReturn(id) }
+
/** Fake [DisplayRepository] implementation for testing. */
class FakeDisplayRepository : DisplayRepository {
private val flow = MutableSharedFlow<Set<Display>>()
- private val pendingDisplayFlow = MutableSharedFlow<Int?>()
+ private val pendingDisplayFlow = MutableSharedFlow<DisplayRepository.PendingDisplay?>()
/** Emits [value] as [displays] flow value. */
suspend fun emit(value: Set<Display>) = flow.emit(value)
- /** Emits [value] as [pendingDisplayId] flow value. */
- suspend fun emit(value: Int?) = pendingDisplayFlow.emit(value)
+ /** Emits [value] as [pendingDisplay] flow value. */
+ suspend fun emit(value: DisplayRepository.PendingDisplay?) = pendingDisplayFlow.emit(value)
override val displays: Flow<Set<Display>>
get() = flow
- override val pendingDisplayId: Flow<Int?>
+ override val pendingDisplay: Flow<DisplayRepository.PendingDisplay?>
get() = pendingDisplayFlow
}
diff --git a/services/companion/java/com/android/server/companion/virtual/Android.bp b/services/companion/java/com/android/server/companion/virtual/Android.bp
index 7a7d376..6526c78 100644
--- a/services/companion/java/com/android/server/companion/virtual/Android.bp
+++ b/services/companion/java/com/android/server/companion/virtual/Android.bp
@@ -1,9 +1,6 @@
java_aconfig_library {
name: "virtualdevice_flags_lib",
aconfig_declarations: "virtualdevice_flags",
- static_libs: [
- "android.companion.virtual.flags-aconfig-java",
- ],
}
aconfig_declarations {
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index b3aa09b..cbac39a 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -559,6 +559,7 @@
boolean mWakeOnDpadKeyPress;
boolean mWakeOnAssistKeyPress;
boolean mWakeOnBackKeyPress;
+ boolean mSilenceRingerOnSleepKey;
long mWakeUpToLastStateTimeout;
int mSearchKeyBehavior;
ComponentName mSearchKeyTargetActivity;
@@ -1423,6 +1424,15 @@
}
private void sleepRelease(long eventTime) {
+ if (mSilenceRingerOnSleepKey) {
+ TelecomManager telecomManager = getTelecommService();
+ if (telecomManager != null && telecomManager.isRinging()) {
+ telecomManager.silenceRinger();
+ Slog.i(TAG, "sleepRelease() silence ringer");
+ return;
+ }
+ }
+
switch (mShortPressOnSleepBehavior) {
case SHORT_PRESS_SLEEP_GO_TO_SLEEP:
case SHORT_PRESS_SLEEP_GO_TO_SLEEP_AND_GO_HOME:
@@ -2347,6 +2357,8 @@
com.android.internal.R.string.config_primaryShortPressTargetActivity));
mShortPressOnSleepBehavior = mContext.getResources().getInteger(
com.android.internal.R.integer.config_shortPressOnSleepBehavior);
+ mSilenceRingerOnSleepKey = mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_silenceRingerOnSleepKey);
mAllowStartActivityForLongPressOnPowerDuringSetup = mContext.getResources().getBoolean(
com.android.internal.R.bool.config_allowStartActivityForLongPressOnPowerInSetup);
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 90e67df..582536b 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -2929,7 +2929,7 @@
reparent(newTaskFrag, position);
}
- private boolean isHomeIntent(Intent intent) {
+ static boolean isHomeIntent(Intent intent) {
return ACTION_MAIN.equals(intent.getAction())
&& (intent.hasCategory(CATEGORY_HOME)
|| intent.hasCategory(CATEGORY_SECONDARY_HOME))
diff --git a/services/core/java/com/android/server/wm/ActivityStartInterceptor.java b/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
index 1eb56f1..a5b1132 100644
--- a/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
+++ b/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
@@ -55,6 +55,7 @@
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
+import android.util.Pair;
import android.util.SparseArray;
import com.android.internal.annotations.VisibleForTesting;
@@ -77,7 +78,6 @@
private final ActivityTaskManagerService mService;
private final ActivityTaskSupervisor mSupervisor;
- private final RootWindowContainer mRootWindowContainer;
private final Context mServiceContext;
// UserManager cannot be final as it's not ready when this class is instantiated during boot
@@ -110,17 +110,23 @@
TaskFragment mInTaskFragment;
ActivityOptions mActivityOptions;
+ /*
+ * Note that this is just a hint of what the launch display area will be as it is
+ * based only on the information at the early pre-interception stage of starting the
+ * intent. The real launch display area calculated later may be different from this one.
+ */
+ TaskDisplayArea mPresumableLaunchDisplayArea;
+
ActivityStartInterceptor(
ActivityTaskManagerService service, ActivityTaskSupervisor supervisor) {
- this(service, supervisor, service.mRootWindowContainer, service.mContext);
+ this(service, supervisor, service.mContext);
}
@VisibleForTesting
ActivityStartInterceptor(ActivityTaskManagerService service, ActivityTaskSupervisor supervisor,
- RootWindowContainer root, Context context) {
+ Context context) {
mService = service;
mSupervisor = supervisor;
- mRootWindowContainer = root;
mServiceContext = context;
}
@@ -162,7 +168,7 @@
/**
* A helper function to obtain the targeted {@link TaskFragment} during
* {@link #intercept(Intent, ResolveInfo, ActivityInfo, String, Task, TaskFragment, int, int,
- * ActivityOptions)} if any.
+ * ActivityOptions, TaskDisplayArea)} if any.
*/
@Nullable
private TaskFragment getLaunchTaskFragment() {
@@ -187,7 +193,7 @@
*/
boolean intercept(Intent intent, ResolveInfo rInfo, ActivityInfo aInfo, String resolvedType,
Task inTask, TaskFragment inTaskFragment, int callingPid, int callingUid,
- ActivityOptions activityOptions) {
+ ActivityOptions activityOptions, TaskDisplayArea presumableLaunchDisplayArea) {
mUserManager = UserManager.get(mServiceContext);
mIntent = intent;
@@ -199,6 +205,7 @@
mInTask = inTask;
mInTaskFragment = inTaskFragment;
mActivityOptions = activityOptions;
+ mPresumableLaunchDisplayArea = presumableLaunchDisplayArea;
if (interceptQuietProfileIfNeeded()) {
// If work profile is turned off, skip the work challenge since the profile can only
@@ -221,6 +228,11 @@
if (interceptLockedManagedProfileIfNeeded()) {
return true;
}
+ if (interceptHomeIfNeeded()) {
+ // Replace primary home intents directed at displays that do not support primary home
+ // but support secondary home with the relevant secondary home activity.
+ return true;
+ }
final SparseArray<ActivityInterceptorCallback> callbacks =
mService.getActivityInterceptorCallbacks();
@@ -470,6 +482,47 @@
return true;
}
+ private boolean interceptHomeIfNeeded() {
+ if (mPresumableLaunchDisplayArea == null || mService.mRootWindowContainer == null) {
+ return false;
+ }
+ if (!ActivityRecord.isHomeIntent(mIntent)) {
+ return false;
+ }
+ if (!mIntent.hasCategory(Intent.CATEGORY_HOME)) {
+ // Already a secondary home intent, leave it alone.
+ return false;
+ }
+ if (mService.mRootWindowContainer.shouldPlacePrimaryHomeOnDisplay(
+ mPresumableLaunchDisplayArea.getDisplayId())) {
+ // Primary home can be launched to the display area.
+ return false;
+ }
+ if (!mService.mRootWindowContainer.shouldPlaceSecondaryHomeOnDisplayArea(
+ mPresumableLaunchDisplayArea)) {
+ // Secondary home cannot be launched on the display area.
+ return false;
+ }
+
+ // At this point we have a primary home intent for a display that does not support primary
+ // home activity but it supports secondary home one. So replace it with secondary home.
+ Pair<ActivityInfo, Intent> info = mService.mRootWindowContainer
+ .resolveSecondaryHomeActivity(mUserId, mPresumableLaunchDisplayArea);
+ mIntent = info.second;
+ // The new task flag is needed because the home activity should already be in the root task
+ // and should not be moved to the caller's task. Also, activities cannot change their type,
+ // e.g. a standard activity cannot become a home activity.
+ mIntent.addFlags(FLAG_ACTIVITY_NEW_TASK);
+ mCallingPid = mRealCallingPid;
+ mCallingUid = mRealCallingUid;
+ mResolvedType = null;
+
+ mRInfo = mSupervisor.resolveIntent(mIntent, mResolvedType, mUserId, /* flags= */ 0,
+ mRealCallingUid, mRealCallingPid);
+ mAInfo = mSupervisor.resolveActivity(mIntent, mRInfo, mStartFlags, /*profilerInfo=*/ null);
+ return true;
+ }
+
private boolean isPackageSuspended() {
return mAInfo != null && mAInfo.applicationInfo != null
&& (mAInfo.applicationInfo.flags & FLAG_SUSPENDED) != 0;
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 1bc78d6..458d1e8 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -1154,10 +1154,12 @@
}
}
+ final TaskDisplayArea suggestedLaunchDisplayArea =
+ computeSuggestedLaunchDisplayArea(inTask, sourceRecord, checkedOptions);
mInterceptor.setStates(userId, realCallingPid, realCallingUid, startFlags, callingPackage,
callingFeatureId);
if (mInterceptor.intercept(intent, rInfo, aInfo, resolvedType, inTask, inTaskFragment,
- callingPid, callingUid, checkedOptions)) {
+ callingPid, callingUid, checkedOptions, suggestedLaunchDisplayArea)) {
// activity start was intercepted, e.g. because the target user is currently in quiet
// mode (turn off work) or the target application is suspended
intent = mInterceptor.mIntent;
@@ -1890,6 +1892,15 @@
mPreferredWindowingMode = mLaunchParams.mWindowingMode;
}
+ private TaskDisplayArea computeSuggestedLaunchDisplayArea(
+ Task task, ActivityRecord source, ActivityOptions options) {
+ mSupervisor.getLaunchParamsController().calculate(task, /*layout=*/null,
+ /*activity=*/ null, source, options, mRequest, PHASE_DISPLAY, mLaunchParams);
+ return mLaunchParams.hasPreferredTaskDisplayArea()
+ ? mLaunchParams.mPreferredTaskDisplayArea
+ : mRootWindowContainer.getDefaultTaskDisplayArea();
+ }
+
@VisibleForTesting
int isAllowedToStart(ActivityRecord r, boolean newTask, Task targetTask) {
if (r.packageName == null) {
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 57f8268..d56acaa 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -1608,6 +1608,19 @@
}
/**
+ * Check if the display is valid for primary home activity.
+ *
+ * @param displayId The target display ID
+ * @return {@code true} if allowed to launch, {@code false} otherwise.
+ */
+ boolean shouldPlacePrimaryHomeOnDisplay(int displayId) {
+ // No restrictions to default display, vr 2d display or main display for visible users.
+ return displayId == DEFAULT_DISPLAY || (displayId != INVALID_DISPLAY
+ && (displayId == mService.mVr2dDisplayId
+ || mWmService.shouldPlacePrimaryHomeOnDisplay(displayId)));
+ }
+
+ /**
* Check if the display area is valid for secondary home activity.
*
* @param taskDisplayArea The target display area.
@@ -1680,10 +1693,7 @@
final int displayId = taskDisplayArea != null ? taskDisplayArea.getDisplayId()
: INVALID_DISPLAY;
- if (displayId == DEFAULT_DISPLAY || (displayId != INVALID_DISPLAY
- && (displayId == mService.mVr2dDisplayId
- || mWmService.shouldPlacePrimaryHomeOnDisplay(displayId)))) {
- // No restrictions to default display, vr 2d display or main display for visible users.
+ if (shouldPlacePrimaryHomeOnDisplay(displayId)) {
return true;
}
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 387a876..21a4fe8 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -2815,7 +2815,7 @@
final WindowManager.LayoutParams attrs = win.mAttrs;
visibleFrame.set(win.getFrame());
visibleFrame.inset(win.getInsetsStateWithVisibilityOverride().calculateVisibleInsets(
- visibleFrame, attrs.type, win.getWindowingMode(), attrs.softInputMode,
+ visibleFrame, attrs.type, win.getActivityType(), attrs.softInputMode,
attrs.flags));
out.union(visibleFrame);
}
diff --git a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
index ad46770..fa620db 100644
--- a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
+++ b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
@@ -118,12 +118,14 @@
root = activity;
}
- if (root == null) {
+ if (root == null && phase != PHASE_DISPLAY) {
// There is a case that can lead us here. The caller is moving the top activity that is
// in a task that has multiple activities to PIP mode. For that the caller is creating a
// new task to host the activity so that we only move the top activity to PIP mode and
// keep other activities in the previous task. There is no point to apply the launch
// logic in this case.
+ // However, for PHASE_DISPLAY the root may be null, but we still want to get a hint of
+ // what the suggested launch display area would be.
return RESULT_SKIP;
}
@@ -395,8 +397,9 @@
}
private TaskDisplayArea getPreferredLaunchTaskDisplayArea(@Nullable Task task,
- @Nullable ActivityOptions options, ActivityRecord source, LaunchParams currentParams,
- @NonNull ActivityRecord activityRecord, @Nullable Request request) {
+ @Nullable ActivityOptions options, @Nullable ActivityRecord source,
+ @Nullable LaunchParams currentParams, @Nullable ActivityRecord activityRecord,
+ @Nullable Request request) {
TaskDisplayArea taskDisplayArea = null;
final WindowContainerToken optionLaunchTaskDisplayAreaToken = options != null
@@ -438,8 +441,7 @@
// If the source activity is a no-display activity, pass on the launch display area token
// from source activity as currently preferred.
- if (taskDisplayArea == null && source != null
- && source.noDisplay) {
+ if (taskDisplayArea == null && source != null && source.noDisplay) {
taskDisplayArea = source.mHandoverTaskDisplayArea;
if (taskDisplayArea != null) {
if (DEBUG) appendLog("display-area-from-no-display-source=" + taskDisplayArea);
@@ -478,21 +480,24 @@
}
}
- if (taskDisplayArea == null) {
+ if (taskDisplayArea == null && currentParams != null) {
taskDisplayArea = currentParams.mPreferredTaskDisplayArea;
+ if (DEBUG) appendLog("display-area-from-current-params=" + taskDisplayArea);
}
// Re-route to default display if the device didn't declare support for multi-display
if (taskDisplayArea != null && !mSupervisor.mService.mSupportsMultiDisplay
&& taskDisplayArea.getDisplayId() != DEFAULT_DISPLAY) {
taskDisplayArea = mSupervisor.mRootWindowContainer.getDefaultTaskDisplayArea();
+ if (DEBUG) appendLog("display-area-from-no-multidisplay=" + taskDisplayArea);
}
// Re-route to default display if the home activity doesn't support multi-display
- if (taskDisplayArea != null && activityRecord.isActivityTypeHome()
+ if (taskDisplayArea != null && activityRecord != null && activityRecord.isActivityTypeHome()
&& !mSupervisor.mRootWindowContainer.canStartHomeOnDisplayArea(activityRecord.info,
taskDisplayArea, false /* allowInstrumenting */)) {
taskDisplayArea = mSupervisor.mRootWindowContainer.getDefaultTaskDisplayArea();
+ if (DEBUG) appendLog("display-area-from-home=" + taskDisplayArea);
}
return (taskDisplayArea != null)
@@ -516,34 +521,56 @@
* @return {@link TaskDisplayArea} to house the task
*/
private TaskDisplayArea getFallbackDisplayAreaForActivity(
- @NonNull ActivityRecord activityRecord, @Nullable Request request) {
+ @Nullable ActivityRecord activityRecord, @Nullable Request request) {
+ if (activityRecord != null) {
+ WindowProcessController controllerFromLaunchingRecord =
+ mSupervisor.mService.getProcessController(
+ activityRecord.launchedFromPid, activityRecord.launchedFromUid);
+ if (controllerFromLaunchingRecord != null) {
+ final TaskDisplayArea taskDisplayAreaForLaunchingRecord =
+ controllerFromLaunchingRecord.getTopActivityDisplayArea();
+ if (taskDisplayAreaForLaunchingRecord != null) {
+ if (DEBUG) {
+ appendLog("display-area-for-launching-record="
+ + taskDisplayAreaForLaunchingRecord);
+ }
+ return taskDisplayAreaForLaunchingRecord;
+ }
+ }
- WindowProcessController controllerFromLaunchingRecord = mSupervisor.mService
- .getProcessController(activityRecord.launchedFromPid,
- activityRecord.launchedFromUid);
- final TaskDisplayArea displayAreaForLaunchingRecord = controllerFromLaunchingRecord == null
- ? null : controllerFromLaunchingRecord.getTopActivityDisplayArea();
- if (displayAreaForLaunchingRecord != null) {
- return displayAreaForLaunchingRecord;
+ WindowProcessController controllerFromProcess =
+ mSupervisor.mService.getProcessController(
+ activityRecord.getProcessName(), activityRecord.getUid());
+ if (controllerFromProcess != null) {
+ final TaskDisplayArea displayAreaForRecord =
+ controllerFromProcess.getTopActivityDisplayArea();
+ if (displayAreaForRecord != null) {
+ if (DEBUG) appendLog("display-area-for-record=" + displayAreaForRecord);
+ return displayAreaForRecord;
+ }
+ }
}
- WindowProcessController controllerFromProcess = mSupervisor.mService.getProcessController(
- activityRecord.getProcessName(), activityRecord.getUid());
- final TaskDisplayArea displayAreaForRecord = controllerFromProcess == null ? null
- : controllerFromProcess.getTopActivityDisplayArea();
- if (displayAreaForRecord != null) {
- return displayAreaForRecord;
+ if (request != null) {
+ WindowProcessController controllerFromRequest =
+ mSupervisor.mService.getProcessController(
+ request.realCallingPid, request.realCallingUid);
+ if (controllerFromRequest != null) {
+ final TaskDisplayArea displayAreaFromSourceProcess =
+ controllerFromRequest.getTopActivityDisplayArea();
+ if (displayAreaFromSourceProcess != null) {
+ if (DEBUG) {
+ appendLog("display-area-source-process=" + displayAreaFromSourceProcess);
+ }
+ return displayAreaFromSourceProcess;
+ }
+ }
}
- WindowProcessController controllerFromRequest = request == null ? null : mSupervisor
- .mService.getProcessController(request.realCallingPid, request.realCallingUid);
- final TaskDisplayArea displayAreaFromSourceProcess = controllerFromRequest == null ? null
- : controllerFromRequest.getTopActivityDisplayArea();
- if (displayAreaFromSourceProcess != null) {
- return displayAreaFromSourceProcess;
- }
-
- return mSupervisor.mRootWindowContainer.getDefaultTaskDisplayArea();
+ final TaskDisplayArea defaultTaskDisplayArea =
+ mSupervisor.mRootWindowContainer.getDefaultTaskDisplayArea();
+ if (DEBUG) appendLog("display-area-from-default-fallback=" + defaultTaskDisplayArea);
+ return defaultTaskDisplayArea;
}
private boolean canInheritWindowingModeFromSource(@NonNull DisplayContent display,
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index a172d99..9c04e0a 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -1759,7 +1759,7 @@
bounds.set(mWindowFrames.mFrame);
bounds.inset(getInsetsStateWithVisibilityOverride().calculateVisibleInsets(
- bounds, mAttrs.type, getWindowingMode(), mAttrs.softInputMode, mAttrs.flags));
+ bounds, mAttrs.type, getActivityType(), mAttrs.softInputMode, mAttrs.flags));
if (intersectWithRootTaskBounds) {
bounds.intersect(mTmpRect);
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java
index bcb0c6b..0989db4 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java
@@ -59,6 +59,7 @@
import android.os.UserManager;
import android.platform.test.annotations.Presubmit;
import android.testing.DexmakerShareClassLoaderRule;
+import android.util.Pair;
import android.util.SparseArray;
import androidx.test.filters.SmallTest;
@@ -128,6 +129,8 @@
private ActivityManagerInternal mAmInternal;
@Mock
private LockTaskController mLockTaskController;
+ @Mock
+ private TaskDisplayArea mTaskDisplayArea;
private ActivityStartInterceptor mInterceptor;
private ActivityInfo mAInfo = new ActivityInfo();
@@ -139,8 +142,8 @@
public void setUp() throws RemoteException {
MockitoAnnotations.initMocks(this);
mService.mAmInternal = mAmInternal;
- mInterceptor = new ActivityStartInterceptor(
- mService, mSupervisor, mRootWindowContainer, mContext);
+ mService.mRootWindowContainer = mRootWindowContainer;
+ mInterceptor = new ActivityStartInterceptor(mService, mSupervisor, mContext);
mInterceptor.setStates(TEST_USER_ID, TEST_REAL_CALLING_PID, TEST_REAL_CALLING_UID,
TEST_START_FLAGS, TEST_CALLING_PACKAGE, null);
@@ -201,7 +204,7 @@
.thenReturn(PLATFORM_PACKAGE_NAME);
// THEN calling intercept returns true
- assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null));
+ assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null, null));
// THEN the returned intent is the admin support intent
assertEquals(ADMIN_SUPPORT_INTENT, mInterceptor.mIntent);
@@ -212,7 +215,7 @@
final String suspendingPackage = "com.test.suspending.package";
final SuspendDialogInfo dialogInfo = suspendPackage(suspendingPackage);
// THEN calling intercept returns true
- assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null));
+ assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null, null));
// Check intent parameters
assertEquals(dialogInfo,
@@ -243,7 +246,7 @@
TEST_USER_ID, TEST_PACKAGE_NAME, LOCK_TASK_LAUNCH_MODE_DEFAULT))
.thenReturn(false);
- assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null));
+ assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null, null));
assertTrue(BlockedAppActivity.createIntent(TEST_USER_ID, TEST_PACKAGE_NAME)
.filterEquals(mInterceptor.mIntent));
@@ -257,7 +260,8 @@
when(mDevicePolicyManager.isKeepProfilesRunningEnabled()).thenReturn(true);
// THEN calling intercept returns false because package also has to be suspended.
- assertFalse(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null));
+ assertFalse(
+ mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null, null));
}
@Test
@@ -268,7 +272,7 @@
when(mDevicePolicyManager.isKeepProfilesRunningEnabled()).thenReturn(false);
// THEN calling intercept returns true
- assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null));
+ assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null, null));
// THEN the returned intent is the quiet mode intent
assertTrue(UnlaunchableAppActivity.createInQuietModeDialogIntent(TEST_USER_ID)
@@ -284,7 +288,7 @@
when(mDevicePolicyManager.isKeepProfilesRunningEnabled()).thenReturn(true);
// THEN calling intercept returns true
- assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null));
+ assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null, null));
// THEN the returned intent is the quiet mode intent
assertTrue(UnlaunchableAppActivity.createInQuietModeDialogIntent(TEST_USER_ID)
@@ -300,7 +304,7 @@
when(mDevicePolicyManager.isKeepProfilesRunningEnabled()).thenReturn(false);
// THEN calling intercept returns true
- assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null));
+ assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null, null));
// THEN the returned intent is the quiet mode intent
assertTrue(UnlaunchableAppActivity.createInQuietModeDialogIntent(TEST_USER_ID)
@@ -313,7 +317,7 @@
when(mAmInternal.shouldConfirmCredentials(TEST_USER_ID)).thenReturn(true);
// THEN calling intercept returns true
- mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null);
+ mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null, null);
// THEN the returned intent is the confirm credentials intent
assertTrue(CONFIRM_CREDENTIALS_INTENT.filterEquals(mInterceptor.mIntent));
@@ -329,7 +333,7 @@
mAInfo.flags |= ActivityInfo.FLAG_SHOW_WHEN_LOCKED;
// THEN calling intercept returns true
- mInterceptor.intercept(originalIntent, null, mAInfo, null, null, null, 0, 0, null);
+ mInterceptor.intercept(originalIntent, null, mAInfo, null, null, null, 0, 0, null, null);
// THEN the returned intent is original intent
assertSame(originalIntent, mInterceptor.mIntent);
@@ -345,7 +349,7 @@
mAInfo.directBootAware = false;
// THEN calling intercept returns true
- mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null);
+ mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null, null);
// THEN the returned intent is the confirm credentials intent
assertTrue(CONFIRM_CREDENTIALS_INTENT.filterEquals(mInterceptor.mIntent));
@@ -362,7 +366,7 @@
mAInfo.directBootAware = true;
// THEN calling intercept returns true
- mInterceptor.intercept(originalIntent, null, mAInfo, null, null, null, 0, 0, null);
+ mInterceptor.intercept(originalIntent, null, mAInfo, null, null, null, 0, 0, null, null);
// THEN the returned intent is original intent
assertSame(originalIntent, mInterceptor.mIntent);
@@ -375,7 +379,7 @@
.thenReturn("This app is bad");
// THEN calling intercept returns true
- assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null));
+ assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null, null));
// THEN the returned intent is the harmful app warning intent
assertEquals(HarmfulAppWarningActivity.class.getName(),
@@ -383,11 +387,40 @@
}
@Test
+ public void testHomeIntentInterception() {
+ // GIVEN a primary home intent and a display area that doesn't support it but supports
+ // secondary home activities
+ Intent originalIntent = new Intent(Intent.ACTION_MAIN);
+ originalIntent.addCategory(Intent.CATEGORY_HOME);
+
+ Intent expectedIntent = new Intent(Intent.ACTION_MAIN);
+ expectedIntent.addCategory(Intent.CATEGORY_SECONDARY_HOME);
+ expectedIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+ final int secondaryDisplayId = 7;
+ when(mTaskDisplayArea.getDisplayId()).thenReturn(secondaryDisplayId);
+ when(mRootWindowContainer.shouldPlacePrimaryHomeOnDisplay(eq(secondaryDisplayId)))
+ .thenReturn(false);
+ when(mRootWindowContainer.shouldPlaceSecondaryHomeOnDisplayArea(eq(mTaskDisplayArea)))
+ .thenReturn(true);
+ when(mRootWindowContainer.resolveSecondaryHomeActivity(
+ eq(TEST_USER_ID), eq(mTaskDisplayArea)))
+ .thenReturn(Pair.create(null, expectedIntent));
+
+ // THEN calling intercept returns true
+ assertTrue(mInterceptor.intercept(originalIntent, null, mAInfo, null, null, null, 0, 0,
+ null, mTaskDisplayArea));
+
+ // THEN the returned intent is the secondary home intent
+ assertSame(expectedIntent, mInterceptor.mIntent);
+ }
+
+ @Test
public void testNoInterception() {
// GIVEN that none of the interception conditions are met
// THEN calling intercept returns false
- assertFalse(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null));
+ assertFalse(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null, null));
}
public void addMockInterceptorCallback(
@@ -420,7 +453,7 @@
new Intent("android.test.foo"),
ActivityOptions.makeBasic().setLaunchDisplayId(3));
- assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null));
+ assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null, null));
assertEquals("android.test.foo", mInterceptor.mIntent.getAction());
assertEquals(3, mInterceptor.mActivityOptions.getLaunchDisplayId());
}
@@ -429,7 +462,7 @@
public void testInterceptionCallback_singleCallbackReturnsNull() {
addMockInterceptorCallback(null, null);
- assertFalse(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null));
+ assertFalse(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null, null));
}
@Test
@@ -437,7 +470,7 @@
addMockInterceptorCallback(null, null);
addMockInterceptorCallback(new Intent("android.test.second"), null);
- assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null));
+ assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null, null));
assertEquals("android.test.second", mInterceptor.mIntent.getAction());
}
@@ -447,7 +480,7 @@
new Intent("android.test.foo"),
ActivityOptions.makeBasic().setLaunchDisplayId(3), true);
ActivityInfo aInfo = mAInfo;
- assertTrue(mInterceptor.intercept(null, null, aInfo, null, null, null, 0, 0, null));
+ assertTrue(mInterceptor.intercept(null, null, aInfo, null, null, null, 0, 0, null, null));
assertEquals("android.test.foo", mInterceptor.mIntent.getAction());
assertEquals(3, mInterceptor.mActivityOptions.getLaunchDisplayId());
assertEquals(aInfo, mInterceptor.mAInfo); // mAInfo should not be resolved
@@ -459,7 +492,7 @@
new Intent("android.test.foo"),
ActivityOptions.makeBasic().setLaunchDisplayId(3));
ActivityInfo aInfo = mAInfo;
- assertTrue(mInterceptor.intercept(null, null, aInfo, null, null, null, 0, 0, null));
+ assertTrue(mInterceptor.intercept(null, null, aInfo, null, null, null, 0, 0, null, null));
assertEquals("android.test.foo", mInterceptor.mIntent.getAction());
assertEquals(3, mInterceptor.mActivityOptions.getLaunchDisplayId());
assertNotEquals(aInfo, mInterceptor.mAInfo); // mAInfo should be resolved after intercept
@@ -488,7 +521,7 @@
when(packageManagerMock.getSdkSandboxPackageName()).thenReturn(sandboxPackageNameMock);
Intent intent = new Intent().setAction(ACTION_START_SANDBOXED_ACTIVITY);
- mInterceptor.intercept(intent, null, mAInfo, null, null, null, 0, 0, null);
+ mInterceptor.intercept(intent, null, mAInfo, null, null, null, 0, 0, null, null);
verify(spyCallback, times(1)).onInterceptActivityLaunch(
any(ActivityInterceptorCallback.ActivityInterceptorInfo.class));
@@ -505,7 +538,7 @@
when(packageManagerMock.getSdkSandboxPackageName()).thenReturn(sandboxPackageNameMock);
Intent intent = new Intent().setPackage(sandboxPackageNameMock);
- mInterceptor.intercept(intent, null, mAInfo, null, null, null, 0, 0, null);
+ mInterceptor.intercept(intent, null, mAInfo, null, null, null, 0, 0, null, null);
verify(spyCallback, times(1)).onInterceptActivityLaunch(
any(ActivityInterceptorCallback.ActivityInterceptorInfo.class));
@@ -522,7 +555,7 @@
when(packageManagerMock.getSdkSandboxPackageName()).thenReturn(sandboxPackageNameMock);
Intent intent = new Intent().setComponent(new ComponentName(sandboxPackageNameMock, ""));
- mInterceptor.intercept(intent, null, mAInfo, null, null, null, 0, 0, null);
+ mInterceptor.intercept(intent, null, mAInfo, null, null, null, 0, 0, null, null);
verify(spyCallback, times(1)).onInterceptActivityLaunch(
any(ActivityInterceptorCallback.ActivityInterceptorInfo.class));
@@ -539,23 +572,23 @@
when(packageManagerMock.getSdkSandboxPackageName()).thenReturn(sandboxPackageNameMock);
// Intent: null
- mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null);
+ mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null, null);
// Action: null, Package: null, ComponentName: null
Intent intent = new Intent();
- mInterceptor.intercept(intent, null, mAInfo, null, null, null, 0, 0, null);
+ mInterceptor.intercept(intent, null, mAInfo, null, null, null, 0, 0, null, null);
// Wrong Action
intent = new Intent().setAction(Intent.ACTION_VIEW);
- mInterceptor.intercept(intent, null, mAInfo, null, null, null, 0, 0, null);
+ mInterceptor.intercept(intent, null, mAInfo, null, null, null, 0, 0, null, null);
// Wrong Package
intent = new Intent().setPackage("Random");
- mInterceptor.intercept(intent, null, mAInfo, null, null, null, 0, 0, null);
+ mInterceptor.intercept(intent, null, mAInfo, null, null, null, 0, 0, null, null);
// Wrong ComponentName's package
intent = new Intent().setComponent(new ComponentName("Random", ""));
- mInterceptor.intercept(intent, null, mAInfo, null, null, null, 0, 0, null);
+ mInterceptor.intercept(intent, null, mAInfo, null, null, null, 0, 0, null, null);
verify(spyCallback, never()).onInterceptActivityLaunch(
any(ActivityInterceptorCallback.ActivityInterceptorInfo.class));
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 0bb75d8..ac8200a 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -9456,6 +9456,19 @@
"carrier_supported_satellite_services_per_provider_bundle";
/**
+ * This config enables modem to scan satellite PLMNs specified as per
+ * {@link #KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE} and attach to same
+ * in case cellular networks are not enabled. This will need specific agreement between
+ * satellite provider and the carrier before enabling this flag.
+ *
+ * The default value is false.
+ *
+ * @hide
+ */
+ public static final String KEY_SATELLITE_ATTACH_SUPPORTED_BOOL =
+ "satellite_attach_supported_bool";
+
+ /**
* Indicating whether DUN APN should be disabled when the device is roaming. In that case,
* the default APN (i.e. internet) will be used for tethering.
*
@@ -10465,6 +10478,7 @@
sDefaults.putPersistableBundle(
KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE,
PersistableBundle.EMPTY);
+ sDefaults.putBoolean(KEY_SATELLITE_ATTACH_SUPPORTED_BOOL, false);
sDefaults.putBoolean(KEY_DISABLE_DUN_APN_WHILE_ROAMING_WITH_PRESET_APN_BOOL, false);
sDefaults.putString(KEY_DEFAULT_PREFERRED_APN_NAME_STRING, "");
sDefaults.putBoolean(KEY_SUPPORTS_CALL_COMPOSER_BOOL, false);
diff --git a/telephony/java/android/telephony/satellite/SatelliteManager.java b/telephony/java/android/telephony/satellite/SatelliteManager.java
index 75b5f55..5f6c14a 100644
--- a/telephony/java/android/telephony/satellite/SatelliteManager.java
+++ b/telephony/java/android/telephony/satellite/SatelliteManager.java
@@ -44,10 +44,14 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.time.Duration;
+import java.util.Arrays;
+import java.util.HashSet;
import java.util.Objects;
+import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
+import java.util.stream.Collectors;
/**
* Manages satellite operations such as provisioning, pointing, messaging, location sharing, etc.
@@ -79,6 +83,23 @@
@Nullable private final Context mContext;
/**
+ * Create a new SatelliteManager object pinned to the given subscription ID.
+ * This is needed only to handle carrier specific satellite features.
+ * For eg: requestSatelliteAttachEnabledForCarrier and
+ * requestIsSatelliteAttachEnabledForCarrier
+ *
+ * @return a SatelliteManager that uses the given subId for all satellite activities.
+ * @throws IllegalArgumentException if the subscription is invalid.
+ * @hide
+ */
+ public SatelliteManager createForSubscriptionId(int subId) {
+ if (!SubscriptionManager.isValidSubscriptionId(subId)) {
+ throw new IllegalArgumentException("Invalid subscription ID");
+ }
+ return new SatelliteManager(mContext, subId);
+ }
+
+ /**
* Create an instance of the SatelliteManager.
*
* @param context The context the SatelliteManager belongs to.
@@ -791,6 +812,27 @@
public @interface DatagramType {}
/**
+ * Satellite communication restricted by user.
+ * @hide
+ */
+ public static final int SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER = 0;
+
+ /**
+ * Satellite communication restricted by geolocation. This can be
+ * triggered based upon geofence input provided by carrier to enable or disable satellite.
+ * @hide
+ */
+ public static final int SATELLITE_COMMUNICATION_RESTRICTION_REASON_GEOLOCATION = 1;
+
+ /** @hide */
+ @IntDef(prefix = "SATELLITE_COMMUNICATION_RESTRICTION_REASON_", value = {
+ SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER,
+ SATELLITE_COMMUNICATION_RESTRICTION_REASON_GEOLOCATION
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface SatelliteCommunicationRestrictionReason {}
+
+ /**
* Start receiving satellite transmission updates.
* This can be called by the pointing UI when the user starts pointing to the satellite.
* Modem should continue to report the pointing input as the device or satellite moves.
@@ -1559,6 +1601,182 @@
}
}
+ /**
+ * User request to enable or disable carrier supported satellite plmn scan and attach by modem.
+ * <p>
+ * This API should be called by only settings app to pass down the user input for
+ * enabling/disabling satellite. This user input will be persisted across device reboots.
+ * <p>
+ * Satellite will be enabled only when the following conditions are met:
+ * <ul>
+ * <li>Users want to enable it.</li>
+ * <li>There is no satellite communication restriction, which is added by
+ * {@link #addSatelliteAttachRestrictionForCarrier(int, Executor, Consumer)}</li>
+ * <li>The carrier config {@link
+ * android.telephony.CarrierConfigManager#KEY_SATELLITE_ATTACH_SUPPORTED_BOOL} is set to
+ * {@code true}.</li>
+ * </ul>
+ *
+ * @param enableSatellite {@code true} to enable the satellite and {@code false} to disable.
+ * @param executor The executor on which the error code listener will be called.
+ * @param resultListener Listener for the {@link SatelliteError} result of the operation.
+ *
+ * @throws SecurityException if the caller doesn't have required permission.
+ * @throws IllegalStateException if the Telephony process is not currently available.
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
+ public void requestSatelliteAttachEnabledForCarrier(boolean enableSatellite,
+ @NonNull @CallbackExecutor Executor executor,
+ @SatelliteResult @NonNull Consumer<Integer> resultListener) {
+ Objects.requireNonNull(executor);
+ Objects.requireNonNull(resultListener);
+
+ if (enableSatellite) {
+ removeSatelliteAttachRestrictionForCarrier(
+ SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER, executor, resultListener);
+ } else {
+ addSatelliteAttachRestrictionForCarrier(
+ SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER, executor, resultListener);
+ }
+ }
+
+ /**
+ * Request to get whether the carrier supported satellite plmn scan and attach by modem is
+ * enabled by user.
+ *
+ * @param executor The executor on which the callback will be called.
+ * @param callback The callback object to which the result will be delivered.
+ * If the request is successful, {@link OutcomeReceiver#onResult(Object)}
+ * will return a {@code boolean} with value {@code true} if the satellite
+ * is enabled and {@code false} otherwise.
+ * If the request is not successful, {@link OutcomeReceiver#onError(Throwable)}
+ * will return a {@link SatelliteException} with the {@link SatelliteError}.
+ *
+ * @throws SecurityException if the caller doesn't have required permission.
+ * @throws IllegalStateException if the Telephony process is not currently available.
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
+ public void requestIsSatelliteAttachEnabledForCarrier(
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull OutcomeReceiver<Boolean, SatelliteException> callback) {
+ Objects.requireNonNull(executor);
+ Objects.requireNonNull(callback);
+
+ Set<Integer> restrictionReason = getSatelliteAttachRestrictionReasonsForCarrier();
+ executor.execute(() -> callback.onResult(
+ !restrictionReason.contains(SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER)));
+ }
+
+ /**
+ * Add a restriction reason for disallowing carrier supported satellite plmn scan and attach
+ * by modem.
+ *
+ * @param reason Reason for disallowing satellite communication.
+ * @param executor The executor on which the error code listener will be called.
+ * @param resultListener Listener for the {@link SatelliteError} result of the operation.
+ *
+ * @throws SecurityException if the caller doesn't have required permission.
+ * @throws IllegalStateException if the Telephony process is not currently available.
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
+ public void addSatelliteAttachRestrictionForCarrier(
+ @SatelliteCommunicationRestrictionReason int reason,
+ @NonNull @CallbackExecutor Executor executor,
+ @SatelliteResult @NonNull Consumer<Integer> resultListener) {
+ try {
+ ITelephony telephony = getITelephony();
+ if (telephony != null) {
+ IIntegerConsumer errorCallback = new IIntegerConsumer.Stub() {
+ @Override
+ public void accept(int result) {
+ executor.execute(() -> Binder.withCleanCallingIdentity(
+ () -> resultListener.accept(result)));
+ }
+ };
+ telephony.addSatelliteAttachRestrictionForCarrier(mSubId, reason, errorCallback);
+ } else {
+ throw new IllegalStateException("telephony service is null.");
+ }
+ } catch (RemoteException ex) {
+ loge("addSatelliteAttachRestrictionForCarrier() RemoteException:" + ex);
+ ex.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Remove a restriction reason for disallowing carrier supported satellite plmn scan and attach
+ * by modem.
+ *
+ * @param reason Reason for disallowing satellite communication.
+ * @param executor The executor on which the error code listener will be called.
+ * @param resultListener Listener for the {@link SatelliteError} result of the operation.
+ *
+ * @throws SecurityException if the caller doesn't have required permission.
+ * @throws IllegalStateException if the Telephony process is not currently available.
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
+ public void removeSatelliteAttachRestrictionForCarrier(
+ @SatelliteCommunicationRestrictionReason int reason,
+ @NonNull @CallbackExecutor Executor executor,
+ @SatelliteResult @NonNull Consumer<Integer> resultListener) {
+ try {
+ ITelephony telephony = getITelephony();
+ if (telephony != null) {
+ IIntegerConsumer errorCallback = new IIntegerConsumer.Stub() {
+ @Override
+ public void accept(int result) {
+ executor.execute(() -> Binder.withCleanCallingIdentity(
+ () -> resultListener.accept(result)));
+ }
+ };
+ telephony.removeSatelliteAttachRestrictionForCarrier(mSubId, reason, errorCallback);
+ } else {
+ throw new IllegalStateException("telephony service is null.");
+ }
+ } catch (RemoteException ex) {
+ loge("removeSatelliteAttachRestrictionForCarrier() RemoteException:" + ex);
+ ex.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Get reasons for disallowing satellite attach, as requested by
+ * {@link #addSatelliteAttachRestrictionForCarrier(int, Executor, Consumer)}
+ *
+ * @return Set of reasons for disallowing satellite communication.
+ *
+ * @throws SecurityException if the caller doesn't have required permission.
+ * @throws IllegalStateException if the Telephony process is not currently available.
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
+ @SatelliteCommunicationRestrictionReason
+ public @NonNull Set<Integer> getSatelliteAttachRestrictionReasonsForCarrier() {
+ try {
+ ITelephony telephony = getITelephony();
+ if (telephony != null) {
+ int[] receivedArray =
+ telephony.getSatelliteAttachRestrictionReasonsForCarrier(mSubId);
+ if (receivedArray.length == 0) {
+ logd("received set is empty, create empty set");
+ return new HashSet<>();
+ } else {
+ return Arrays.stream(receivedArray).boxed().collect(Collectors.toSet());
+ }
+ } else {
+ throw new IllegalStateException("telephony service is null.");
+ }
+ } catch (RemoteException ex) {
+ loge("getSatelliteAttachRestrictionReasonsForCarrier() RemoteException: " + ex);
+ ex.rethrowFromSystemServer();
+ }
+ return null;
+ }
+
private static ITelephony getITelephony() {
ITelephony binder = ITelephony.Stub.asInterface(TelephonyFrameworkInitializer
.getTelephonyServiceManager()
diff --git a/telephony/java/android/telephony/satellite/stub/ISatellite.aidl b/telephony/java/android/telephony/satellite/stub/ISatellite.aidl
index ea4e2e2..02661de 100644
--- a/telephony/java/android/telephony/satellite/stub/ISatellite.aidl
+++ b/telephony/java/android/telephony/satellite/stub/ISatellite.aidl
@@ -382,4 +382,64 @@
*/
void requestTimeForNextSatelliteVisibility(in IIntegerConsumer resultCallback,
in IIntegerConsumer callback);
+
+ /**
+ * Set the non-terrestrial PLMN with lower priority than terrestrial networks.
+ * MCC/MNC broadcast by the non-terrestrial networks may not be included in OPLMNwACT file on
+ * SIM profile. Acquisition of satellite based system is lower priority to terrestrial
+ * networks. UE shall make all attempts to acquire terrestrial service prior to camping on
+ * satellite LTE service.
+ *
+ * @param simSlot Indicates the SIM slot to which this API will be applied. The modem will use
+ * this information to determine the relevant carrier.
+ * @param plmnList The list of roaming PLMN used for connecting to satellite networks.
+ * @param resultCallback The callback to receive the error code result of the operation.
+ *
+ * Valid error codes returned:
+ * SatelliteError:NONE
+ * SatelliteError:INVALID_ARGUMENTS
+ * SatelliteError:INVALID_MODEM_STATE
+ * SatelliteError:MODEM_ERR
+ * SatelliteError:NO_RESOURCES
+ * SatelliteError:RADIO_NOT_AVAILABLE
+ * SatelliteError:REQUEST_NOT_SUPPORTED
+ */
+ void setSatellitePlmn(int simSlot, in List<String> plmnList,
+ in IIntegerConsumer resultCallback);
+
+ /**
+ * Enable or disable satellite in the cellular modem associated with a carrier.
+ * Refer setSatellitePlmn for the details of satellite PLMN scanning process.
+ *
+ * @param simSlot Indicates the SIM slot to which this API will be applied. The modem will use
+ * this information to determine the relevant carrier.
+ * @param serial Serial number of request.
+ * @param enable {@code true} to enable satellite, {@code false} to disable satellite.
+ *
+ * Valid errors returned:
+ * SatelliteError:NONE
+ * SatelliteError:INVALID_MODEM_STATE
+ * SatelliteError:MODEM_ERR
+ * SatelliteError:RADIO_NOT_AVAILABLE
+ * SatelliteError:REQUEST_NOT_SUPPORTED
+ */
+ void setSatelliteEnabledForCarrier(int simSlot, boolean satelliteEnabled,
+ in IIntegerConsumer callback);
+
+ /**
+ * Check whether satellite is enabled in the cellular modem associated with a carrier.
+ *
+ * @param simSlot Indicates the SIM slot to which this API will be applied. The modem will use
+ * this information to determine the relevant carrier.
+ * @param serial Serial number of request.
+ *
+ * Valid errors returned:
+ * SatelliteError:NONE
+ * SatelliteError:INVALID_MODEM_STATE
+ * SatelliteError:MODEM_ERR
+ * SatelliteError:RADIO_NOT_AVAILABLE
+ * SatelliteError:REQUEST_NOT_SUPPORTED
+ */
+ void requestIsSatelliteEnabledForCarrier(int simSlot, in IIntegerConsumer resultCallback,
+ in IBooleanConsumer callback);
}
diff --git a/telephony/java/android/telephony/satellite/stub/SatelliteImplBase.java b/telephony/java/android/telephony/satellite/stub/SatelliteImplBase.java
index 17d026c..6451daf 100644
--- a/telephony/java/android/telephony/satellite/stub/SatelliteImplBase.java
+++ b/telephony/java/android/telephony/satellite/stub/SatelliteImplBase.java
@@ -25,6 +25,7 @@
import com.android.internal.telephony.IIntegerConsumer;
import com.android.internal.telephony.util.TelephonyUtils;
+import java.util.List;
import java.util.concurrent.CancellationException;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
@@ -212,6 +213,34 @@
"requestTimeForNextSatelliteVisibility");
}
+ @Override
+ public void setSatellitePlmn(int simSlot, List<String> plmnList,
+ IIntegerConsumer errorCallback)
+ throws RemoteException {
+ executeMethodAsync(
+ () -> SatelliteImplBase.this
+ .setSatellitePlmn(simSlot, plmnList, errorCallback),
+ "setSatellitePlmn");
+ }
+
+ @Override
+ public void setSatelliteEnabledForCarrier(int simSlot, boolean enableSatellite,
+ IIntegerConsumer errorCallback) throws RemoteException {
+ executeMethodAsync(
+ () -> SatelliteImplBase.this
+ .setSatelliteEnabledForCarrier(simSlot, enableSatellite, errorCallback),
+ "setSatelliteEnabledForCarrier");
+ }
+
+ @Override
+ public void requestIsSatelliteEnabledForCarrier(int simSlot, IIntegerConsumer errorCallback,
+ IBooleanConsumer callback) throws RemoteException {
+ executeMethodAsync(
+ () -> SatelliteImplBase.this
+ .requestIsSatelliteEnabledForCarrier(simSlot, errorCallback, callback),
+ "requestIsSatelliteEnabledForCarrier");
+ }
+
// Call the methods with a clean calling identity on the executor and wait indefinitely for
// the future to return.
private void executeMethodAsync(Runnable r, String errorLogName) throws RemoteException {
@@ -618,4 +647,75 @@
@NonNull IIntegerConsumer callback) {
// stub implementation
}
+
+
+ /**
+ * Set the non-terrestrial PLMN with lower priority than terrestrial networks.
+ * MCC/MNC broadcast by the non-terrestrial networks may not be included in OPLMNwACT file on
+ * SIM profile. Acquisition of satellite based system is lower priority to terrestrial
+ * networks. UE shall make all attempts to acquire terrestrial service prior to camping on
+ * satellite LTE service.
+ * This method must only take effect if {@link #setSatelliteEnabledForCarrier} is {@code true},
+ * and return an error otherwise.
+ *
+ * @param simLogicalSlotIndex Indicates the SIM logical slot index to which this API will be
+ * applied. The modem will use this information to determine the relevant carrier.
+ * @param errorCallback The callback to receive the error code result of the operation.
+ * @param plmnList The list of roaming PLMN used for connecting to satellite networks.
+ *
+ * Valid error codes returned:
+ * SatelliteError:NONE
+ * SatelliteError:INVALID_ARGUMENTS
+ * SatelliteError:INVALID_MODEM_STATE
+ * SatelliteError:MODEM_ERR
+ * SatelliteError:NO_RESOURCES
+ * SatelliteError:RADIO_NOT_AVAILABLE
+ * SatelliteError:REQUEST_NOT_SUPPORTED
+ */
+ public void setSatellitePlmn(@NonNull int simLogicalSlotIndex, @NonNull List<String> plmnList,
+ @NonNull IIntegerConsumer errorCallback) {
+ // stub implementation
+ }
+
+ /**
+ * Request to enable or disable carrier supported satellite plmn scan and attach by modem.
+ * Refer {@link #setSatellitePlmn} for the details of satellite PLMN scanning process.
+ *
+ * @param simLogicalSlotIndex Indicates the SIM logical slot index to which this API will be
+ * applied. The modem will use this information to determine the relevant carrier.
+ * @param satelliteEnabled {@code true} to enable satellite, {@code false} to disable satellite.
+ * @param callback {@code true} to enable satellite, {@code false} to disable satellite.
+ *
+ * Valid errors returned:
+ * SatelliteError:NONE
+ * SatelliteError:INVALID_MODEM_STATE
+ * SatelliteError:MODEM_ERR
+ * SatelliteError:RADIO_NOT_AVAILABLE
+ * SatelliteError:REQUEST_NOT_SUPPORTED
+ */
+ public void setSatelliteEnabledForCarrier(@NonNull int simLogicalSlotIndex,
+ @NonNull boolean satelliteEnabled, @NonNull IIntegerConsumer callback) {
+ // stub implementation
+ }
+
+ /**
+ * Request to get whether the satellite is enabled in the cellular modem associated with a
+ * carrier.
+ *
+ * @param simLogicalSlotIndex Indicates the SIM logical slot index to which this API will be
+ * applied. The modem will use this information to determine the relevant carrier.
+ * @param errorCallback The callback to receive the error code result of the operation.
+ * @param callback {@code true} to satellite enabled, {@code false} to satellite disabled.
+ *
+ * Valid errors returned:
+ * SatelliteError:NONE
+ * SatelliteError:INVALID_MODEM_STATE
+ * SatelliteError:MODEM_ERR
+ * SatelliteError:RADIO_NOT_AVAILABLE
+ * SatelliteError:REQUEST_NOT_SUPPORTED
+ */
+ public void requestIsSatelliteEnabledForCarrier(@NonNull int simLogicalSlotIndex,
+ @NonNull IIntegerConsumer errorCallback, @NonNull IBooleanConsumer callback) {
+ // stub implementation
+ }
}
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 06071fe..3aa5a5a 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -3033,4 +3033,42 @@
@JavaPassthrough(annotation="@android.annotation.RequiresPermission("
+ "android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)")
List<String> getShaIdFromAllowList(String pkgName, int carrierId);
+
+ /**
+ * Add a restriction reason for disallowing satellite communication.
+ *
+ * @param subId The subId of the subscription to request for.
+ * @param reason Reason for disallowing satellite communication for carrier.
+ * @param callback Listener for the {@link SatelliteManager.SatelliteError} result of the
+ * operation.
+ */
+ @JavaPassthrough(annotation="@android.annotation.RequiresPermission("
+ + "android.Manifest.permission.SATELLITE_COMMUNICATION)")
+ void addSatelliteAttachRestrictionForCarrier(int subId, int reason,
+ in IIntegerConsumer callback);
+
+ /**
+ * Remove a restriction reason for disallowing satellite communication.
+ *
+ * @param subId The subId of the subscription to request for.
+ * @param reason Reason for disallowing satellite communication.
+ * @param callback Listener for the {@link SatelliteManager.SatelliteError} result of the
+ * operation.
+ */
+ @JavaPassthrough(annotation="@android.annotation.RequiresPermission("
+ + "android.Manifest.permission.SATELLITE_COMMUNICATION)")
+ void removeSatelliteAttachRestrictionForCarrier(int subId, int reason,
+ in IIntegerConsumer callback);
+
+ /**
+ * Get reasons for disallowing satellite communication, as requested by
+ * {@link #addSatelliteAttachRestrictionForCarrier(int, int)}.
+ *
+ * @param subId The subId of the subscription to request for.
+ *
+ * @return Set of reasons for disallowing satellite communication.
+ */
+ @JavaPassthrough(annotation="@android.annotation.RequiresPermission("
+ + "android.Manifest.permission.SATELLITE_COMMUNICATION)")
+ int[] getSatelliteAttachRestrictionReasonsForCarrier(int subId);
}
diff --git a/tests/FlickerTests/Android.bp b/tests/FlickerTests/Android.bp
index a2ae56e..2ccc0fa 100644
--- a/tests/FlickerTests/Android.bp
+++ b/tests/FlickerTests/Android.bp
@@ -95,7 +95,6 @@
"flickertestapplib",
"flickerlib",
"flickerlib-helpers",
- "flickerlib-trace_processor_shell",
"platform-test-annotations",
"wm-flicker-common-app-helpers",
"wm-shell-flicker-utils",
diff --git a/tests/FlickerTests/manifests/AndroidManifest.xml b/tests/FlickerTests/manifests/AndroidManifest.xml
index 6bc7cbe..1a34d9e 100644
--- a/tests/FlickerTests/manifests/AndroidManifest.xml
+++ b/tests/FlickerTests/manifests/AndroidManifest.xml
@@ -44,12 +44,8 @@
<uses-permission android:name="android.permission.MANAGE_ACTIVITY_TASKS" />
<!-- ActivityOptions.makeCustomTaskAnimation() -->
<uses-permission android:name="android.permission.START_TASKS_FROM_RECENTS" />
- <!-- Allow the test to connect to perfetto trace processor -->
- <uses-permission android:name="android.permission.INTERNET"/>
- <!-- Allow the test to write directly to /sdcard/ and connect to trace processor -->
- <application android:requestLegacyExternalStorage="true"
- android:networkSecurityConfig="@xml/network_security_config"
- android:largeHeap="true">
+ <!-- Allow the test to write directly to /sdcard/ -->
+ <application android:requestLegacyExternalStorage="true" android:largeHeap="true">
<uses-library android:name="android.test.runner"/>
<uses-library android:name="androidx.window.extensions" android:required="false"/>
diff --git a/tests/FlickerTests/res/xml/network_security_config.xml b/tests/FlickerTests/res/xml/network_security_config.xml
deleted file mode 100644
index 4bd9ca0..0000000
--- a/tests/FlickerTests/res/xml/network_security_config.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2023 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<network-security-config>
- <domain-config cleartextTrafficPermitted="true">
- <domain includeSubdomains="true">localhost</domain>
- </domain-config>
-</network-security-config>
diff --git a/tests/SurfaceViewBufferTests/Android.bp b/tests/SurfaceViewBufferTests/Android.bp
index 38313f8..dc75f00 100644
--- a/tests/SurfaceViewBufferTests/Android.bp
+++ b/tests/SurfaceViewBufferTests/Android.bp
@@ -23,10 +23,7 @@
android_test {
name: "SurfaceViewBufferTests",
- srcs: [
- "**/*.java",
- "**/*.kt",
- ],
+ srcs: ["**/*.java","**/*.kt"],
manifest: "AndroidManifest.xml",
test_config: "AndroidTest.xml",
platform_apis: true,
@@ -44,7 +41,6 @@
"kotlin-stdlib",
"kotlinx-coroutines-android",
"flickerlib",
- "flickerlib-trace_processor_shell",
"truth-prebuilt",
"cts-wm-util",
"CtsSurfaceValidatorLib",
@@ -64,7 +60,7 @@
"libandroid",
],
include_dirs: [
- "system/core/include",
+ "system/core/include"
],
stl: "libc++_static",
cflags: [
diff --git a/tests/SurfaceViewBufferTests/AndroidManifest.xml b/tests/SurfaceViewBufferTests/AndroidManifest.xml
index 798c67a..78415e8 100644
--- a/tests/SurfaceViewBufferTests/AndroidManifest.xml
+++ b/tests/SurfaceViewBufferTests/AndroidManifest.xml
@@ -29,12 +29,9 @@
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<!-- Save failed test bitmap images !-->
<uses-permission android:name="android.Manifest.permission.WRITE_EXTERNAL_STORAGE"/>
- <!-- Allow the test to connect to perfetto trace processor -->
- <uses-permission android:name="android.permission.INTERNET"/>
<application android:allowBackup="false"
- android:supportsRtl="true"
- android:networkSecurityConfig="@xml/network_security_config">
+ android:supportsRtl="true">
<activity android:name=".MainActivity"
android:taskAffinity="com.android.test.MainActivity"
android:theme="@style/AppTheme"
diff --git a/tests/SurfaceViewBufferTests/res/xml/network_security_config.xml b/tests/SurfaceViewBufferTests/res/xml/network_security_config.xml
deleted file mode 100644
index 4bd9ca0..0000000
--- a/tests/SurfaceViewBufferTests/res/xml/network_security_config.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2023 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<network-security-config>
- <domain-config cleartextTrafficPermitted="true">
- <domain includeSubdomains="true">localhost</domain>
- </domain-config>
-</network-security-config>
diff --git a/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceTracingTestBase.kt b/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceTracingTestBase.kt
index b03b733..a38019d 100644
--- a/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceTracingTestBase.kt
+++ b/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceTracingTestBase.kt
@@ -21,9 +21,11 @@
import android.graphics.Rect
import android.util.Log
import androidx.test.ext.junit.rules.ActivityScenarioRule
+import android.tools.common.flicker.subject.layers.LayerSubject
import android.tools.common.traces.surfaceflinger.LayersTrace
+import android.tools.device.traces.io.ResultWriter
+import android.tools.device.traces.monitors.surfaceflinger.LayersTraceMonitor
import android.tools.device.traces.monitors.withSFTracing
-import android.tools.device.traces.monitors.PerfettoTraceMonitor
import junit.framework.Assert
import org.junit.After
import org.junit.Before
@@ -31,7 +33,6 @@
import java.io.FileOutputStream
import java.io.IOException
import java.util.concurrent.CountDownLatch
-import perfetto.protos.PerfettoConfig.SurfaceFlingerLayersConfig
open class SurfaceTracingTestBase(useBlastAdapter: Boolean) :
SurfaceViewBufferTestBase(useBlastAdapter) {
@@ -42,7 +43,7 @@
@Before
override fun setup() {
super.setup()
- PerfettoTraceMonitor.stopAllSessions()
+ stopLayerTrace()
addSurfaceView()
}
@@ -82,6 +83,10 @@
instrumentation.waitForIdleSync()
}
+ private fun stopLayerTrace() {
+ LayersTraceMonitor().stop(ResultWriter())
+ }
+
fun checkPixels(bounds: Rect, @ColorInt color: Int) {
val screenshot = instrumentation.getUiAutomation().takeScreenshot()
val pixels = IntArray(screenshot.width * screenshot.height)
@@ -101,19 +106,14 @@
Log.e("SurfaceViewBufferTests", "Error writing bitmap to file", e)
}
}
- Assert.assertEquals(
- "Checking $bounds found mismatch $i,$j",
- Color.valueOf(color),
- Color.valueOf(actualColor)
- )
+ Assert.assertEquals("Checking $bounds found mismatch $i,$j",
+ Color.valueOf(color), Color.valueOf(actualColor))
}
}
}
private companion object {
- private val TRACE_FLAGS = listOf(
- SurfaceFlingerLayersConfig.TraceFlag.TRACE_FLAG_BUFFERS,
- SurfaceFlingerLayersConfig.TraceFlag.TRACE_FLAG_VIRTUAL_DISPLAYS,
- )
+ private const val TRACE_FLAGS =
+ (1 shl 0) or (1 shl 5) or (1 shl 6) // TRACE_CRITICAL | TRACE_BUFFERS | TRACE_SYNC
}
}
\ No newline at end of file
diff --git a/tests/TaskOrganizerTest/Android.bp b/tests/TaskOrganizerTest/Android.bp
index bf12f42..9b72d35 100644
--- a/tests/TaskOrganizerTest/Android.bp
+++ b/tests/TaskOrganizerTest/Android.bp
@@ -25,10 +25,7 @@
android_test {
name: "TaskOrganizerTest",
- srcs: [
- "**/*.java",
- "**/*.kt",
- ],
+ srcs: ["**/*.java","**/*.kt"],
manifest: "AndroidManifest.xml",
test_config: "AndroidTest.xml",
platform_apis: true,
@@ -42,7 +39,6 @@
"kotlin-stdlib",
"kotlinx-coroutines-android",
"flickerlib",
- "flickerlib-trace_processor_shell",
"truth-prebuilt",
],
-}
+}
\ No newline at end of file
diff --git a/tests/TaskOrganizerTest/AndroidManifest.xml b/tests/TaskOrganizerTest/AndroidManifest.xml
index cbeb246..1f1bd3e 100644
--- a/tests/TaskOrganizerTest/AndroidManifest.xml
+++ b/tests/TaskOrganizerTest/AndroidManifest.xml
@@ -16,11 +16,9 @@
<uses-permission android:name="android.permission.CHANGE_CONFIGURATION"/>
<uses-permission android:name="android.permission.MANAGE_ACTIVITY_TASKS"/>
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL"/>
- <!-- Allow the test to connect to perfetto trace processor -->
- <uses-permission android:name="android.permission.INTERNET"/>
<!-- Enable / Disable tracing !-->
<uses-permission android:name="android.permission.DUMP" />
- <application android:networkSecurityConfig="@xml/network_security_config">
+ <application>
<activity android:name="TaskOrganizerMultiWindowTest"
android:label="TaskOrganizer MW Test"
android:exported="true"
diff --git a/tests/TaskOrganizerTest/res/xml/network_security_config.xml b/tests/TaskOrganizerTest/res/xml/network_security_config.xml
deleted file mode 100644
index e450a99..0000000
--- a/tests/TaskOrganizerTest/res/xml/network_security_config.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-~ Copyright (C) 2023 The Android Open Source Project
-~
-~ Licensed under the Apache License, Version 2.0 (the "License");
-~ you may not use this file except in compliance with the License.
-~ You may obtain a copy of the License at
-~
-~ http://www.apache.org/licenses/LICENSE-2.0
-~
-~ Unless required by applicable law or agreed to in writing, software
-~ distributed under the License is distributed on an "AS IS" BASIS,
-~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-~ See the License for the specific language governing permissions and
-~ limitations under the License.
--->
-<network-security-config>
- <domain-config cleartextTrafficPermitted="true">
- <domain includeSubdomains="true">localhost</domain>
- </domain-config>
-</network-security-config>
\ No newline at end of file
diff --git a/tests/TaskOrganizerTest/src/com/android/test/taskembed/ResizeTasksSyncTest.kt b/tests/TaskOrganizerTest/src/com/android/test/taskembed/ResizeTasksSyncTest.kt
index 2c7905d..6f4f7b1 100644
--- a/tests/TaskOrganizerTest/src/com/android/test/taskembed/ResizeTasksSyncTest.kt
+++ b/tests/TaskOrganizerTest/src/com/android/test/taskembed/ResizeTasksSyncTest.kt
@@ -22,6 +22,8 @@
import androidx.test.runner.AndroidJUnit4
import android.tools.common.datatypes.Size
import android.tools.common.flicker.subject.layers.LayersTraceSubject
+import android.tools.device.traces.io.ResultWriter
+import android.tools.device.traces.monitors.surfaceflinger.LayersTraceMonitor
import android.tools.device.traces.monitors.withSFTracing
import org.junit.After
import org.junit.Before
@@ -39,13 +41,16 @@
@get:Rule
var scenarioRule: ActivityScenarioRule<TaskOrganizerMultiWindowTest> =
ActivityScenarioRule<TaskOrganizerMultiWindowTest>(
- TaskOrganizerMultiWindowTest::class.java
- )
+ TaskOrganizerMultiWindowTest::class.java)
protected val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
@Before
fun setup() {
+ val monitor = LayersTraceMonitor()
+ if (monitor.isEnabled) {
+ monitor.stop(ResultWriter())
+ }
val firstTaskBounds = Rect(0, 0, 1080, 1000)
val secondTaskBounds = Rect(0, 1000, 1080, 2000)
@@ -66,7 +71,7 @@
val firstBounds = Rect(0, 0, 1080, 800)
val secondBounds = Rect(0, 1000, 1080, 1800)
- val trace = withSFTracing() {
+ val trace = withSFTracing(TRACE_FLAGS) {
lateinit var resizeReadyLatch: CountDownLatch
scenarioRule.getScenario().onActivity {
resizeReadyLatch = it.resizeTaskView(firstBounds, secondBounds)
@@ -101,6 +106,7 @@
}
companion object {
+ private const val TRACE_FLAGS = 0x1 // TRACE_CRITICAL
private const val FIRST_ACTIVITY = "Activity1"
private const val SECOND_ACTIVITY = "Activity2"
}