Merge "Per-app override sandboxing View API to Activity bounds" into tm-qpr-dev

This commit is contained in:
Oleg Blinnikov
2023-03-08 13:52:25 +00:00
committed by Android (Google) Code Review
5 changed files with 158 additions and 2 deletions

View File

@@ -797,6 +797,7 @@ package android.content.pm {
field public static final long OVERRIDE_MIN_ASPECT_RATIO_MEDIUM = 180326845L; // 0xabf91bdL
field public static final float OVERRIDE_MIN_ASPECT_RATIO_MEDIUM_VALUE = 1.5f;
field public static final long OVERRIDE_MIN_ASPECT_RATIO_PORTRAIT_ONLY = 203647190L; // 0xc2368d6L
field public static final long OVERRIDE_SANDBOX_VIEW_BOUNDS_APIS = 237531167L; // 0xe28701fL
field public static final int RESIZE_MODE_RESIZEABLE = 2; // 0x2
}
@@ -2917,7 +2918,9 @@ package android.view {
}
@UiThread public class View implements android.view.accessibility.AccessibilityEventSource android.graphics.drawable.Drawable.Callback android.view.KeyEvent.Callback {
method public void getBoundsOnScreen(@NonNull android.graphics.Rect, boolean);
method public android.view.View getTooltipView();
method public void getWindowDisplayFrame(@NonNull android.graphics.Rect);
method public boolean isAutofilled();
method public static boolean isDefaultFocusHighlightEnabled();
method public boolean isDefaultFocusHighlightNeeded(android.graphics.drawable.Drawable, android.graphics.drawable.Drawable);

View File

@@ -1103,6 +1103,34 @@ public class ActivityInfo extends ComponentInfo implements Parcelable {
public static final long OVERRIDE_CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE =
264301586L; // buganizer id
/**
* This change id forces the packages it is applied to sandbox {@link android.view.View} API to
* an activity bounds for:
*
* <p>{@link android.view.View#getLocationOnScreen},
* {@link android.view.View#getWindowVisibleDisplayFrame},
* {@link android.view.View}#getWindowDisplayFrame,
* {@link android.view.View}#getBoundsOnScreen.
*
* <p>For {@link android.view.View#getWindowVisibleDisplayFrame} and
* {@link android.view.View}#getWindowDisplayFrame this sandboxing is happening indirectly
* through
* {@link android.view.ViewRootImpl}#getWindowVisibleDisplayFrame,
* {@link android.view.ViewRootImpl}#getDisplayFrame respectively.
*
* <p>Some applications assume that they occupy the whole screen and therefore use the display
* coordinates in their calculations as if an activity is positioned in the top-left corner of
* the screen, with left coordinate equal to 0. This may not be the case of applications in
* multi-window and in letterbox modes. This can lead to shifted or out of bounds UI elements in
* case the activity is Letterboxed or is in multi-window mode.
* @hide
*/
@ChangeId
@Overridable
@Disabled
@TestApi
public static final long OVERRIDE_SANDBOX_VIEW_BOUNDS_APIS = 237531167L; // buganizer id
/**
* This change id is the gatekeeper for all treatments that force a given min aspect ratio.
* Enabling this change will allow the following min aspect ratio treatments to be applied:

View File

@@ -8774,7 +8774,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @hide
*/
@UnsupportedAppUsage
public void getBoundsOnScreen(Rect outRect, boolean clipToParent) {
@TestApi
public void getBoundsOnScreen(@NonNull Rect outRect, boolean clipToParent) {
if (mAttachInfo == null) {
return;
}
@@ -8782,6 +8783,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
getBoundsToScreenInternal(position, clipToParent);
outRect.set(Math.round(position.left), Math.round(position.top),
Math.round(position.right), Math.round(position.bottom));
// If "Sandboxing View Bounds APIs" override is enabled, applyViewBoundsSandboxingIfNeeded
// will sandbox outRect within window bounds.
mAttachInfo.mViewRootImpl.applyViewBoundsSandboxingIfNeeded(outRect);
}
/**
@@ -15586,7 +15590,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @hide
*/
@UnsupportedAppUsage
public void getWindowDisplayFrame(Rect outRect) {
@TestApi
public void getWindowDisplayFrame(@NonNull Rect outRect) {
if (mAttachInfo != null) {
mAttachInfo.mViewRootImpl.getDisplayFrame(outRect);
return;
@@ -25786,6 +25791,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
if (info != null) {
outLocation[0] += info.mWindowLeft;
outLocation[1] += info.mWindowTop;
// If OVERRIDE_SANDBOX_VIEW_BOUNDS_APIS override is enabled,
// applyViewLocationSandboxingIfNeeded sandboxes outLocation within window bounds.
info.mViewRootImpl.applyViewLocationSandboxingIfNeeded(outLocation);
}
}

View File

@@ -16,6 +16,7 @@
package android.view;
import static android.content.pm.ActivityInfo.OVERRIDE_SANDBOX_VIEW_BOUNDS_APIS;
import static android.graphics.HardwareRenderer.SYNC_CONTEXT_IS_STOPPED;
import static android.graphics.HardwareRenderer.SYNC_LOST_SURFACE_REWARD_IF_FOUND;
import static android.os.IInputConstants.INVALID_INPUT_EVENT_ID;
@@ -82,6 +83,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_ADDITIONAL
import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
import static android.view.WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY;
import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_SANDBOXING_VIEW_BOUNDS_APIS;
import static android.view.WindowManagerGlobal.RELAYOUT_RES_CANCEL_AND_REDRAW;
import static android.view.WindowManagerGlobal.RELAYOUT_RES_CONSUME_ALWAYS_SYSTEM_BARS;
import static android.view.WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED;
@@ -94,12 +96,14 @@ import android.animation.LayoutTransition;
import android.annotation.AnyThread;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Size;
import android.annotation.UiContext;
import android.app.ActivityManager;
import android.app.ActivityThread;
import android.app.ICompatCameraControlCallback;
import android.app.ResourcesManager;
import android.app.WindowConfiguration;
import android.app.compat.CompatChanges;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ClipData;
import android.content.ClipDescription;
@@ -871,6 +875,15 @@ public final class ViewRootImpl implements ViewParent,
private boolean mRelayoutRequested;
/**
* Whether sandboxing of {@link android.view.View#getBoundsOnScreen},
* {@link android.view.View#getLocationOnScreen(int[])},
* {@link android.view.View#getWindowDisplayFrame} and
* {@link android.view.View#getWindowVisibleDisplayFrame}
* within Activity bounds is enabled for the current application.
*/
private final boolean mViewBoundsSandboxingEnabled;
private int mLastTransformHint = Integer.MIN_VALUE;
/**
@@ -958,6 +971,8 @@ public final class ViewRootImpl implements ViewParent,
mHandwritingInitiator = new HandwritingInitiator(mViewConfiguration,
mContext.getSystemService(InputMethodManager.class));
mViewBoundsSandboxingEnabled = getViewBoundsSandboxingEnabled();
String processorOverrideName = context.getResources().getString(
R.string.config_inputEventCompatProcessorOverrideClassName);
if (processorOverrideName.isEmpty()) {
@@ -8426,6 +8441,9 @@ public final class ViewRootImpl implements ViewParent,
*/
void getDisplayFrame(Rect outFrame) {
outFrame.set(mTmpFrames.displayFrame);
// Apply sandboxing here (in getter) due to possible layout updates on the client after
// mTmpFrames.displayFrame is received from the server.
applyViewBoundsSandboxingIfNeeded(outFrame);
}
/**
@@ -8442,6 +8460,69 @@ public final class ViewRootImpl implements ViewParent,
outFrame.top += insets.top;
outFrame.right -= insets.right;
outFrame.bottom -= insets.bottom;
// Apply sandboxing here (in getter) due to possible layout updates on the client after
// mTmpFrames.displayFrame is received from the server.
applyViewBoundsSandboxingIfNeeded(outFrame);
}
/**
* Offset outRect to make it sandboxed within Window's bounds.
*
* <p>This is used by {@link android.view.View#getBoundsOnScreen},
* {@link android.view.ViewRootImpl#getDisplayFrame} and
* {@link android.view.ViewRootImpl#getWindowVisibleDisplayFrame}, which are invoked by
* {@link android.view.View#getWindowDisplayFrame} and
* {@link android.view.View#getWindowVisibleDisplayFrame}, as well as
* {@link android.view.ViewDebug#captureLayers} for debugging.
*/
void applyViewBoundsSandboxingIfNeeded(final Rect inOutRect) {
if (mViewBoundsSandboxingEnabled) {
final Rect bounds = getConfiguration().windowConfiguration.getBounds();
inOutRect.offset(-bounds.left, -bounds.top);
}
}
/**
* Offset outLocation to make it sandboxed within Window's bounds.
*
* <p>This is used by {@link android.view.View#getLocationOnScreen(int[])}
*/
public void applyViewLocationSandboxingIfNeeded(@Size(2) int[] outLocation) {
if (mViewBoundsSandboxingEnabled) {
final Rect bounds = getConfiguration().windowConfiguration.getBounds();
outLocation[0] -= bounds.left;
outLocation[1] -= bounds.top;
}
}
private boolean getViewBoundsSandboxingEnabled() {
// System dialogs (e.g. ANR) can be created within System process, so handleBindApplication
// may be never called. This results into all app compat changes being enabled
// (see b/268007823) because AppCompatCallbacks.install() is never called with non-empty
// array.
// With ActivityThread.isSystem we verify that it is not the system process,
// then this CompatChange can take effect.
if (ActivityThread.isSystem()
|| !CompatChanges.isChangeEnabled(OVERRIDE_SANDBOX_VIEW_BOUNDS_APIS)) {
// It is a system process or OVERRIDE_SANDBOX_VIEW_BOUNDS_APIS change-id is disabled.
return false;
}
// OVERRIDE_SANDBOX_VIEW_BOUNDS_APIS is enabled by the device manufacturer.
try {
final List<PackageManager.Property> properties = mContext.getPackageManager()
.queryApplicationProperty(PROPERTY_COMPAT_ALLOW_SANDBOXING_VIEW_BOUNDS_APIS);
final boolean isOptedOut = !properties.isEmpty() && !properties.get(0).getBoolean();
if (isOptedOut) {
// PROPERTY_COMPAT_ALLOW_SANDBOXING_VIEW_BOUNDS_APIS is disabled by the app devs.
return false;
}
} catch (RuntimeException e) {
// remote exception.
}
return true;
}
/**

View File

@@ -852,6 +852,42 @@ public interface WindowManager extends ViewManager {
String PROPERTY_COMPAT_IGNORE_REQUESTED_ORIENTATION =
"android.window.PROPERTY_COMPAT_IGNORE_REQUESTED_ORIENTATION";
/**
* Application level {@link android.content.pm.PackageManager.Property PackageManager
* .Property} for an app to inform the system that it needs to be opted-out from the
* compatibility treatment that sandboxes {@link android.view.View} API.
*
* <p>The treatment can be enabled by device manufacturers for applications which misuse
* {@link android.view.View} APIs by expecting that
* {@link android.view.View#getLocationOnScreen},
* {@link android.view.View#getBoundsOnScreen},
* {@link android.view.View#getWindowVisibleDisplayFrame},
* {@link android.view.View#getWindowDisplayFrame}
* return coordinates as if an activity is positioned in the top-left corner of the screen, with
* left coordinate equal to 0. This may not be the case for applications in multi-window and in
* letterbox modes.
*
* <p>Setting this property to {@code false} informs the system that the application must be
* opted-out from the "Sandbox {@link android.view.View} API to Activity bounds" treatment even
* if the device manufacturer has opted the app into the treatment.
*
* <p>Not setting this property at all, or setting this property to {@code true} has no effect.
*
* <p><b>Syntax:</b>
* <pre>
* &lt;application&gt;
* &lt;property
* android:name="android.window.PROPERTY_COMPAT_ALLOW_SANDBOXING_VIEW_BOUNDS_APIS"
* android:value="false"/&gt;
* &lt;/application&gt;
* </pre>
*
* @hide
*/
// TODO(b/263984287): Make this public API.
String PROPERTY_COMPAT_ALLOW_SANDBOXING_VIEW_BOUNDS_APIS =
"android.window.PROPERTY_COMPAT_ALLOW_SANDBOXING_VIEW_BOUNDS_APIS";
/**
* Application level {@link android.content.pm.PackageManager.Property PackageManager
* .Property} for an app to inform the system that the application can be opted-in or opted-out