Loading core/java/android/view/View.java +105 −1 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ import static android.view.flags.Flags.FLAG_SENSITIVE_CONTENT_APP_PROTECTION_API import static android.view.flags.Flags.FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY; import static android.view.flags.Flags.FLAG_VIEW_VELOCITY_API; import static android.view.flags.Flags.enableUseMeasureCacheDuringForceLayout; import static android.view.flags.Flags.sensitiveContentAppProtection; import static android.view.flags.Flags.toolkitMetricsForFrameRateDecision; import static android.view.flags.Flags.toolkitSetFrameRateReadOnly; import static android.view.flags.Flags.viewVelocityApi; Loading Loading @@ -135,6 +136,7 @@ import android.service.credentials.CredentialProviderService; import android.sysprop.DisplayProperties; import android.text.InputType; import android.text.TextUtils; import android.util.ArraySet; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.util.FloatProperty; Loading Loading @@ -3701,6 +3703,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * 1 PFLAG4_ROTARY_HAPTICS_SCROLL_SINCE_LAST_ROTARY_INPUT * 1 PFLAG4_ROTARY_HAPTICS_WAITING_FOR_SCROLL_EVENT * 11 PFLAG4_CONTENT_SENSITIVITY_MASK * 1 PFLAG4_IS_COUNTED_AS_SENSITIVE * |-------|-------|-------|-------| */ Loading Loading @@ -3826,6 +3829,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback, private static final int PFLAG4_CONTENT_SENSITIVITY_MASK = (CONTENT_SENSITIVITY_AUTO | CONTENT_SENSITIVITY_SENSITIVE | CONTENT_SENSITIVITY_NOT_SENSITIVE) << PFLAG4_CONTENT_SENSITIVITY_SHIFT; /** * Whether this view has been counted as a sensitive view or not. * * @see AttachInfo#mSensitiveViewsCount */ private static final int PFLAG4_IS_COUNTED_AS_SENSITIVE = 0x4000000; /* End of masks for mPrivateFlags4 */ /** @hide */ Loading Loading @@ -10387,6 +10397,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, mPrivateFlags4 &= ~PFLAG4_CONTENT_SENSITIVITY_MASK; mPrivateFlags4 |= ((mode << PFLAG4_CONTENT_SENSITIVITY_SHIFT) & PFLAG4_CONTENT_SENSITIVITY_MASK); if (sensitiveContentAppProtection()) { updateSensitiveViewsCountIfNeeded(isAggregatedVisible()); } } /** Loading Loading @@ -10418,12 +10431,43 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ @FlaggedApi(FLAG_SENSITIVE_CONTENT_APP_PROTECTION_API) public final boolean isContentSensitive() { if (getContentSensitivity() == CONTENT_SENSITIVITY_SENSITIVE) { final int contentSensitivity = getContentSensitivity(); if (contentSensitivity == CONTENT_SENSITIVITY_SENSITIVE) { return true; } else if (contentSensitivity == CONTENT_SENSITIVITY_NOT_SENSITIVE) { return false; } else if (sensitiveContentAppProtection()) { return SensitiveAutofillHintsHelper .containsSensitiveAutofillHint(getAutofillHints()); } return false; } /** * Helper used to track sensitive views when they are added or removed from the window * based on whether it's laid out and visible. * * <p>This method is called from many places (visibility changed, view laid out, view attached * or detached to/from window, etc...) */ private void updateSensitiveViewsCountIfNeeded(boolean appeared) { if (!sensitiveContentAppProtection() || mAttachInfo == null) { return; } if (appeared && isContentSensitive()) { if ((mPrivateFlags4 & PFLAG4_IS_COUNTED_AS_SENSITIVE) == 0) { mPrivateFlags4 |= PFLAG4_IS_COUNTED_AS_SENSITIVE; mAttachInfo.increaseSensitiveViewsCount(); } } else { if ((mPrivateFlags4 & PFLAG4_IS_COUNTED_AS_SENSITIVE) != 0) { mPrivateFlags4 &= ~PFLAG4_IS_COUNTED_AS_SENSITIVE; mAttachInfo.decreaseSensitiveViewsCount(); } } } /** * Gets the mode for determining whether this view is important for content capture. * Loading Loading @@ -13457,6 +13501,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } else { mAutofillHints = autofillHints; } if (sensitiveContentAppProtection()) { if (getContentSensitivity() == CONTENT_SENSITIVITY_AUTO) { updateSensitiveViewsCountIfNeeded(isAggregatedVisible()); } } } /** Loading Loading @@ -16681,6 +16730,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } notifyAppearedOrDisappearedForContentCaptureIfNeeded(isVisible); updateSensitiveViewsCountIfNeeded(isVisible); if (!getSystemGestureExclusionRects().isEmpty()) { postUpdate(this::updateSystemGestureExclusionRects); Loading Loading @@ -22670,6 +22720,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } notifyAppearedOrDisappearedForContentCaptureIfNeeded(false); updateSensitiveViewsCountIfNeeded(false); mAttachInfo = null; if (mOverlay != null) { Loading Loading @@ -31816,6 +31867,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ ScrollCaptureInternal mScrollCaptureInternal; /** * sensitive views attached to the window */ int mSensitiveViewsCount; /** * Creates a new set of attachment information with the specified * events handler and thread. Loading @@ -31835,6 +31891,24 @@ public class View implements Drawable.Callback, KeyEvent.Callback, mTreeObserver = new ViewTreeObserver(context); } void increaseSensitiveViewsCount() { if (mSensitiveViewsCount == 0) { mViewRootImpl.notifySensitiveContentAppProtection(true); } mSensitiveViewsCount++; } void decreaseSensitiveViewsCount() { mSensitiveViewsCount--; if (mSensitiveViewsCount == 0) { mViewRootImpl.notifySensitiveContentAppProtection(false); } if (mSensitiveViewsCount < 0) { Log.wtf(VIEW_LOG_TAG, "mSensitiveViewsCount is negative" + mSensitiveViewsCount); mSensitiveViewsCount = 0; } } @Nullable ContentCaptureManager getContentCaptureManager(@NonNull Context context) { if (mContentCaptureManager != null) { Loading Loading @@ -32448,6 +32522,36 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } } private static class SensitiveAutofillHintsHelper { /** * List of autofill hints deemed sensitive for screen protection during screen share. */ private static final ArraySet<String> SENSITIVE_CONTENT_AUTOFILL_HINTS = new ArraySet<>(); static { SENSITIVE_CONTENT_AUTOFILL_HINTS.add(View.AUTOFILL_HINT_USERNAME); SENSITIVE_CONTENT_AUTOFILL_HINTS.add(View.AUTOFILL_HINT_PASSWORD_AUTO); SENSITIVE_CONTENT_AUTOFILL_HINTS.add(View.AUTOFILL_HINT_PASSWORD); } /** * Whether View's autofill hints contains a sensitive autofill hint. * * @see #SENSITIVE_CONTENT_AUTOFILL_HINTS */ static boolean containsSensitiveAutofillHint(@Nullable String[] autofillHints) { if (autofillHints == null) { return false; } int size = autofillHints.length; for (int i = 0; i < size; i++) { if (SENSITIVE_CONTENT_AUTOFILL_HINTS.contains(autofillHints[i])) { return true; } } return false; } } /** * Returns the current scroll capture hint for this view. core/java/android/view/ViewRootImpl.java +34 −0 Original line number Diff line number Diff line Loading @@ -58,6 +58,7 @@ import static android.view.ViewRootImplProto.WIDTH; import static android.view.ViewRootImplProto.WINDOW_ATTRIBUTES; import static android.view.ViewRootImplProto.WIN_FRAME; import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION; import static android.view.flags.Flags.sensitiveContentAppProtection; import static android.view.WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS; import static android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS; import static android.view.WindowInsetsController.APPEARANCE_LOW_PROFILE_BARS; Loading Loading @@ -166,6 +167,7 @@ import android.os.Message; import android.os.ParcelFileDescriptor; import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemClock; import android.os.SystemProperties; import android.os.Trace; Loading Loading @@ -924,6 +926,8 @@ public final class ViewRootImpl implements ViewParent, private IAccessibilityEmbeddedConnection mAccessibilityEmbeddedConnection; private final ISensitiveContentProtectionManager mSensitiveContentProtectionService; static final class SystemUiVisibilityInfo { int globalVisibility; int localValue; Loading Loading @@ -1203,6 +1207,13 @@ public final class ViewRootImpl implements ViewParent, mScrollCaptureRequestTimeout = SCROLL_CAPTURE_REQUEST_TIMEOUT_MILLIS; mOnBackInvokedDispatcher = new WindowOnBackInvokedDispatcher(context); if (sensitiveContentAppProtection()) { mSensitiveContentProtectionService = ISensitiveContentProtectionManager.Stub.asInterface( ServiceManager.getService(Context.SENSITIVE_CONTENT_PROTECTION_SERVICE)); } else { mSensitiveContentProtectionService = null; } } public static void addFirstDrawHandler(Runnable callback) { Loading Loading @@ -4154,6 +4165,29 @@ public final class ViewRootImpl implements ViewParent, mWmsRequestSyncGroup.add(this, null /* runnable */); } /** * Helper used to notify the service to block projection when a sensitive * view (the view displays sensitive content) is attached to the window. * The window manager service is also notified to unblock projection when * no attached view (to the window) displays sensitive content. * * <ol> * <li>It should only notify service to block projection when first sensitive view is * attached to the window. * <li>It should only notify service to unblock projection when all sensitive view are * removed from the window. * </ol> */ void notifySensitiveContentAppProtection(boolean showSensitiveContent) { try { // The window would be blocked during screen share if it shows sensitive content. mSensitiveContentProtectionService.setSensitiveContentProtection( getWindowToken(), mContext.getPackageName(), showSensitiveContent); } catch (RemoteException ex) { Log.e(TAG, "Unable to protect sensitive content during screen share", ex); } } private void notifyContentCaptureEvents() { if (!isContentCaptureEnabled()) { if (DEBUG_CONTENT_CAPTURE) { Loading Loading
core/java/android/view/View.java +105 −1 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ import static android.view.flags.Flags.FLAG_SENSITIVE_CONTENT_APP_PROTECTION_API import static android.view.flags.Flags.FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY; import static android.view.flags.Flags.FLAG_VIEW_VELOCITY_API; import static android.view.flags.Flags.enableUseMeasureCacheDuringForceLayout; import static android.view.flags.Flags.sensitiveContentAppProtection; import static android.view.flags.Flags.toolkitMetricsForFrameRateDecision; import static android.view.flags.Flags.toolkitSetFrameRateReadOnly; import static android.view.flags.Flags.viewVelocityApi; Loading Loading @@ -135,6 +136,7 @@ import android.service.credentials.CredentialProviderService; import android.sysprop.DisplayProperties; import android.text.InputType; import android.text.TextUtils; import android.util.ArraySet; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.util.FloatProperty; Loading Loading @@ -3701,6 +3703,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * 1 PFLAG4_ROTARY_HAPTICS_SCROLL_SINCE_LAST_ROTARY_INPUT * 1 PFLAG4_ROTARY_HAPTICS_WAITING_FOR_SCROLL_EVENT * 11 PFLAG4_CONTENT_SENSITIVITY_MASK * 1 PFLAG4_IS_COUNTED_AS_SENSITIVE * |-------|-------|-------|-------| */ Loading Loading @@ -3826,6 +3829,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback, private static final int PFLAG4_CONTENT_SENSITIVITY_MASK = (CONTENT_SENSITIVITY_AUTO | CONTENT_SENSITIVITY_SENSITIVE | CONTENT_SENSITIVITY_NOT_SENSITIVE) << PFLAG4_CONTENT_SENSITIVITY_SHIFT; /** * Whether this view has been counted as a sensitive view or not. * * @see AttachInfo#mSensitiveViewsCount */ private static final int PFLAG4_IS_COUNTED_AS_SENSITIVE = 0x4000000; /* End of masks for mPrivateFlags4 */ /** @hide */ Loading Loading @@ -10387,6 +10397,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, mPrivateFlags4 &= ~PFLAG4_CONTENT_SENSITIVITY_MASK; mPrivateFlags4 |= ((mode << PFLAG4_CONTENT_SENSITIVITY_SHIFT) & PFLAG4_CONTENT_SENSITIVITY_MASK); if (sensitiveContentAppProtection()) { updateSensitiveViewsCountIfNeeded(isAggregatedVisible()); } } /** Loading Loading @@ -10418,12 +10431,43 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ @FlaggedApi(FLAG_SENSITIVE_CONTENT_APP_PROTECTION_API) public final boolean isContentSensitive() { if (getContentSensitivity() == CONTENT_SENSITIVITY_SENSITIVE) { final int contentSensitivity = getContentSensitivity(); if (contentSensitivity == CONTENT_SENSITIVITY_SENSITIVE) { return true; } else if (contentSensitivity == CONTENT_SENSITIVITY_NOT_SENSITIVE) { return false; } else if (sensitiveContentAppProtection()) { return SensitiveAutofillHintsHelper .containsSensitiveAutofillHint(getAutofillHints()); } return false; } /** * Helper used to track sensitive views when they are added or removed from the window * based on whether it's laid out and visible. * * <p>This method is called from many places (visibility changed, view laid out, view attached * or detached to/from window, etc...) */ private void updateSensitiveViewsCountIfNeeded(boolean appeared) { if (!sensitiveContentAppProtection() || mAttachInfo == null) { return; } if (appeared && isContentSensitive()) { if ((mPrivateFlags4 & PFLAG4_IS_COUNTED_AS_SENSITIVE) == 0) { mPrivateFlags4 |= PFLAG4_IS_COUNTED_AS_SENSITIVE; mAttachInfo.increaseSensitiveViewsCount(); } } else { if ((mPrivateFlags4 & PFLAG4_IS_COUNTED_AS_SENSITIVE) != 0) { mPrivateFlags4 &= ~PFLAG4_IS_COUNTED_AS_SENSITIVE; mAttachInfo.decreaseSensitiveViewsCount(); } } } /** * Gets the mode for determining whether this view is important for content capture. * Loading Loading @@ -13457,6 +13501,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } else { mAutofillHints = autofillHints; } if (sensitiveContentAppProtection()) { if (getContentSensitivity() == CONTENT_SENSITIVITY_AUTO) { updateSensitiveViewsCountIfNeeded(isAggregatedVisible()); } } } /** Loading Loading @@ -16681,6 +16730,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } notifyAppearedOrDisappearedForContentCaptureIfNeeded(isVisible); updateSensitiveViewsCountIfNeeded(isVisible); if (!getSystemGestureExclusionRects().isEmpty()) { postUpdate(this::updateSystemGestureExclusionRects); Loading Loading @@ -22670,6 +22720,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } notifyAppearedOrDisappearedForContentCaptureIfNeeded(false); updateSensitiveViewsCountIfNeeded(false); mAttachInfo = null; if (mOverlay != null) { Loading Loading @@ -31816,6 +31867,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ ScrollCaptureInternal mScrollCaptureInternal; /** * sensitive views attached to the window */ int mSensitiveViewsCount; /** * Creates a new set of attachment information with the specified * events handler and thread. Loading @@ -31835,6 +31891,24 @@ public class View implements Drawable.Callback, KeyEvent.Callback, mTreeObserver = new ViewTreeObserver(context); } void increaseSensitiveViewsCount() { if (mSensitiveViewsCount == 0) { mViewRootImpl.notifySensitiveContentAppProtection(true); } mSensitiveViewsCount++; } void decreaseSensitiveViewsCount() { mSensitiveViewsCount--; if (mSensitiveViewsCount == 0) { mViewRootImpl.notifySensitiveContentAppProtection(false); } if (mSensitiveViewsCount < 0) { Log.wtf(VIEW_LOG_TAG, "mSensitiveViewsCount is negative" + mSensitiveViewsCount); mSensitiveViewsCount = 0; } } @Nullable ContentCaptureManager getContentCaptureManager(@NonNull Context context) { if (mContentCaptureManager != null) { Loading Loading @@ -32448,6 +32522,36 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } } private static class SensitiveAutofillHintsHelper { /** * List of autofill hints deemed sensitive for screen protection during screen share. */ private static final ArraySet<String> SENSITIVE_CONTENT_AUTOFILL_HINTS = new ArraySet<>(); static { SENSITIVE_CONTENT_AUTOFILL_HINTS.add(View.AUTOFILL_HINT_USERNAME); SENSITIVE_CONTENT_AUTOFILL_HINTS.add(View.AUTOFILL_HINT_PASSWORD_AUTO); SENSITIVE_CONTENT_AUTOFILL_HINTS.add(View.AUTOFILL_HINT_PASSWORD); } /** * Whether View's autofill hints contains a sensitive autofill hint. * * @see #SENSITIVE_CONTENT_AUTOFILL_HINTS */ static boolean containsSensitiveAutofillHint(@Nullable String[] autofillHints) { if (autofillHints == null) { return false; } int size = autofillHints.length; for (int i = 0; i < size; i++) { if (SENSITIVE_CONTENT_AUTOFILL_HINTS.contains(autofillHints[i])) { return true; } } return false; } } /** * Returns the current scroll capture hint for this view.
core/java/android/view/ViewRootImpl.java +34 −0 Original line number Diff line number Diff line Loading @@ -58,6 +58,7 @@ import static android.view.ViewRootImplProto.WIDTH; import static android.view.ViewRootImplProto.WINDOW_ATTRIBUTES; import static android.view.ViewRootImplProto.WIN_FRAME; import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION; import static android.view.flags.Flags.sensitiveContentAppProtection; import static android.view.WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS; import static android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS; import static android.view.WindowInsetsController.APPEARANCE_LOW_PROFILE_BARS; Loading Loading @@ -166,6 +167,7 @@ import android.os.Message; import android.os.ParcelFileDescriptor; import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemClock; import android.os.SystemProperties; import android.os.Trace; Loading Loading @@ -924,6 +926,8 @@ public final class ViewRootImpl implements ViewParent, private IAccessibilityEmbeddedConnection mAccessibilityEmbeddedConnection; private final ISensitiveContentProtectionManager mSensitiveContentProtectionService; static final class SystemUiVisibilityInfo { int globalVisibility; int localValue; Loading Loading @@ -1203,6 +1207,13 @@ public final class ViewRootImpl implements ViewParent, mScrollCaptureRequestTimeout = SCROLL_CAPTURE_REQUEST_TIMEOUT_MILLIS; mOnBackInvokedDispatcher = new WindowOnBackInvokedDispatcher(context); if (sensitiveContentAppProtection()) { mSensitiveContentProtectionService = ISensitiveContentProtectionManager.Stub.asInterface( ServiceManager.getService(Context.SENSITIVE_CONTENT_PROTECTION_SERVICE)); } else { mSensitiveContentProtectionService = null; } } public static void addFirstDrawHandler(Runnable callback) { Loading Loading @@ -4154,6 +4165,29 @@ public final class ViewRootImpl implements ViewParent, mWmsRequestSyncGroup.add(this, null /* runnable */); } /** * Helper used to notify the service to block projection when a sensitive * view (the view displays sensitive content) is attached to the window. * The window manager service is also notified to unblock projection when * no attached view (to the window) displays sensitive content. * * <ol> * <li>It should only notify service to block projection when first sensitive view is * attached to the window. * <li>It should only notify service to unblock projection when all sensitive view are * removed from the window. * </ol> */ void notifySensitiveContentAppProtection(boolean showSensitiveContent) { try { // The window would be blocked during screen share if it shows sensitive content. mSensitiveContentProtectionService.setSensitiveContentProtection( getWindowToken(), mContext.getPackageName(), showSensitiveContent); } catch (RemoteException ex) { Log.e(TAG, "Unable to protect sensitive content during screen share", ex); } } private void notifyContentCaptureEvents() { if (!isContentCaptureEnabled()) { if (DEBUG_CONTENT_CAPTURE) { Loading