Merge "Add a new condition provider for manual rules" into main
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 50d97cf..5393475 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -12886,7 +12886,14 @@
field public static final String KEY_SENSITIVE_CONTENT = "key_sensitive_content";
field public static final String KEY_SNOOZE_CRITERIA = "key_snooze_criteria";
field public static final String KEY_TEXT_REPLIES = "key_text_replies";
+ field @FlaggedApi("android.service.notification.notification_classification") public static final String KEY_TYPE = "key_type";
field public static final String KEY_USER_SENTIMENT = "key_user_sentiment";
+ field @FlaggedApi("android.service.notification.notification_classification") public static final int TYPE_CONTENT_RECOMMENDATION = 4; // 0x4
+ field @FlaggedApi("android.service.notification.notification_classification") public static final int TYPE_NEWS = 3; // 0x3
+ field @FlaggedApi("android.service.notification.notification_classification") public static final int TYPE_OTHER = 0; // 0x0
+ field @FlaggedApi("android.service.notification.notification_classification") public static final int TYPE_PROMOTION = 1; // 0x1
+ field @FlaggedApi("android.service.notification.notification_classification") public static final int TYPE_SOCIAL_MEDIA = 2; // 0x2
+ field @FlaggedApi("android.service.notification.notification_classification") public static final int TYPE_UNKNOWN = -1; // 0xffffffff
}
public abstract class NotificationAssistantService extends android.service.notification.NotificationListenerService {
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index c2f960f..d899511 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -379,6 +379,10 @@
method public void setImportantConversation(boolean);
method public void setOriginalImportance(int);
method public void setUserVisibleTaskShown(boolean);
+ field @FlaggedApi("android.service.notification.notification_classification") public static final String NEWS_ID = "android.app.news";
+ field @FlaggedApi("android.service.notification.notification_classification") public static final String PROMOTIONS_ID = "android.app.promotions";
+ field @FlaggedApi("android.service.notification.notification_classification") public static final String RECS_ID = "android.app.recs";
+ field @FlaggedApi("android.service.notification.notification_classification") public static final String SOCIAL_MEDIA_ID = "android.app.social";
}
public final class NotificationChannelGroup implements android.os.Parcelable {
diff --git a/core/java/android/app/AppCompatCallbacks.java b/core/java/android/app/AppCompatCallbacks.java
index f2debfc..4bfa3b3 100644
--- a/core/java/android/app/AppCompatCallbacks.java
+++ b/core/java/android/app/AppCompatCallbacks.java
@@ -82,7 +82,7 @@
private void reportChange(long changeId, int state, boolean isLoggable) {
int uid = Process.myUid();
- mChangeReporter.reportChange(uid, changeId, state, isLoggable);
+ mChangeReporter.reportChange(uid, changeId, state, false, isLoggable);
}
}
diff --git a/core/java/android/app/NotificationChannel.java b/core/java/android/app/NotificationChannel.java
index 3f6c81b..326d7ce 100644
--- a/core/java/android/app/NotificationChannel.java
+++ b/core/java/android/app/NotificationChannel.java
@@ -72,6 +72,35 @@
public static final String DEFAULT_CHANNEL_ID = "miscellaneous";
/**
+ * A reserved id for a system channel reserved for promotional notifications.
+ * @hide
+ */
+ @TestApi
+ @FlaggedApi(android.service.notification.Flags.FLAG_NOTIFICATION_CLASSIFICATION)
+ public static final String PROMOTIONS_ID = "android.app.promotions";
+ /**
+ * A reserved id for a system channel reserved for non-conversation social media notifications.
+ * @hide
+ */
+ @TestApi
+ @FlaggedApi(android.service.notification.Flags.FLAG_NOTIFICATION_CLASSIFICATION)
+ public static final String SOCIAL_MEDIA_ID = "android.app.social";
+ /**
+ * A reserved id for a system channel reserved for news notifications.
+ * @hide
+ */
+ @TestApi
+ @FlaggedApi(android.service.notification.Flags.FLAG_NOTIFICATION_CLASSIFICATION)
+ public static final String NEWS_ID = "android.app.news";
+ /**
+ * A reserved id for a system channel reserved for content recommendation notifications.
+ * @hide
+ */
+ @TestApi
+ @FlaggedApi(android.service.notification.Flags.FLAG_NOTIFICATION_CLASSIFICATION)
+ public static final String RECS_ID = "android.app.recs";
+
+ /**
* The formatter used by the system to create an id for notification
* channels when it automatically creates conversation channels on behalf of an app. The format
* string takes two arguments, in this order: the
diff --git a/core/java/android/appwidget/flags.aconfig b/core/java/android/appwidget/flags.aconfig
index 18cfca6..4e0379e 100644
--- a/core/java/android/appwidget/flags.aconfig
+++ b/core/java/android/appwidget/flags.aconfig
@@ -50,3 +50,10 @@
purpose: PURPOSE_BUGFIX
}
}
+
+flag {
+ name: "remote_views_proto"
+ namespace: "app_widgets"
+ description: "Enable support for persisting RemoteViews previews to Protobuf"
+ bug: "306546610"
+}
diff --git a/core/java/android/content/OWNERS b/core/java/android/content/OWNERS
index a37408b..6d9dc45 100644
--- a/core/java/android/content/OWNERS
+++ b/core/java/android/content/OWNERS
@@ -14,3 +14,4 @@
per-file ComponentCallbacksController = charlesccchen@google.com
per-file AttributionSource* = file:/core/java/android/permission/OWNERS
per-file Broadcast* = file:/BROADCASTS_OWNERS
+per-file ComponentCallbacks*.java = file:/PERFORMANCE_OWNERS
\ No newline at end of file
diff --git a/core/java/android/content/pm/dex/OWNERS b/core/java/android/content/pm/dex/OWNERS
index 267e5d58..558b5f7 100644
--- a/core/java/android/content/pm/dex/OWNERS
+++ b/core/java/android/content/pm/dex/OWNERS
@@ -1,7 +1,6 @@
# Bug component: 86431
-toddke@android.com
-toddke@google.com
patb@google.com
-calin@google.com
ngeoffray@google.com
+jiakaiz@google.com
+mast@google.com
diff --git a/core/java/android/hardware/OWNERS b/core/java/android/hardware/OWNERS
index d2a2f12..51ad151 100644
--- a/core/java/android/hardware/OWNERS
+++ b/core/java/android/hardware/OWNERS
@@ -5,7 +5,7 @@
sumir@google.com
# Camera
-per-file *Camera*=cychen@google.com,epeev@google.com,etalvala@google.com,shuzhenwang@google.com,yinchiayeh@google.com,zhijunhe@google.com,jchowdhary@google.com
+per-file *Camera*=cychen@google.com,epeev@google.com,etalvala@google.com,shuzhenwang@google.com,zhijunhe@google.com,jchowdhary@google.com
# Sensor Privacy
per-file *SensorPrivacy* = file:platform/frameworks/native:/libs/sensorprivacy/OWNERS
diff --git a/core/java/android/hardware/biometrics/BiometricManager.java b/core/java/android/hardware/biometrics/BiometricManager.java
index fdd8b04..678bd6b 100644
--- a/core/java/android/hardware/biometrics/BiometricManager.java
+++ b/core/java/android/hardware/biometrics/BiometricManager.java
@@ -137,6 +137,7 @@
BIOMETRIC_WEAK,
BIOMETRIC_CONVENIENCE,
DEVICE_CREDENTIAL,
+ MANDATORY_BIOMETRICS,
})
@Retention(RetentionPolicy.SOURCE)
@interface Types {}
@@ -214,6 +215,21 @@
*/
int DEVICE_CREDENTIAL = 1 << 15;
+ /**
+ * The bit is used to request for mandatory biometrics.
+ *
+ * <p> The requirements to trigger mandatory biometrics are as follows:
+ * 1. User must have enabled the toggle for mandatory biometrics is settings
+ * 2. User must have enrollments for all {@link #BIOMETRIC_STRONG} sensors available
+ * 3. The device must not be in a trusted location
+ * </p>
+ *
+ * <p> If all the above conditions are satisfied, only {@link #BIOMETRIC_STRONG} sensors
+ * will be eligible for authentication, and device credential fallback will be dropped.
+ * @hide
+ */
+ int MANDATORY_BIOMETRICS = 1 << 16;
+
}
/**
diff --git a/core/java/android/hardware/biometrics/BiometricPrompt.java b/core/java/android/hardware/biometrics/BiometricPrompt.java
index 37a2df8..42f5fc8 100644
--- a/core/java/android/hardware/biometrics/BiometricPrompt.java
+++ b/core/java/android/hardware/biometrics/BiometricPrompt.java
@@ -794,10 +794,15 @@
public void onDialogDismissed(int reason) {
// Check the reason and invoke OnClickListener(s) if necessary
if (reason == DISMISSED_REASON_NEGATIVE) {
- mNegativeButtonInfo.executor.execute(() -> {
- mNegativeButtonInfo.listener.onClick(null, DialogInterface.BUTTON_NEGATIVE);
- mIsPromptShowing = false;
- });
+ if (mNegativeButtonInfo != null) {
+ mNegativeButtonInfo.executor.execute(() -> {
+ mNegativeButtonInfo.listener.onClick(null, DialogInterface.BUTTON_NEGATIVE);
+ mIsPromptShowing = false;
+ });
+ } else {
+ mAuthenticationCallback.onAuthenticationError(BIOMETRIC_ERROR_USER_CANCELED,
+ null /* errString */);
+ }
} else if (reason == DISMISSED_REASON_CONTENT_VIEW_MORE_OPTIONS) {
if (mContentViewMoreOptionsButtonInfo != null) {
mContentViewMoreOptionsButtonInfo.executor.execute(() -> {
diff --git a/core/java/android/hardware/biometrics/PromptInfo.java b/core/java/android/hardware/biometrics/PromptInfo.java
index ba9f30d..901f6b7 100644
--- a/core/java/android/hardware/biometrics/PromptInfo.java
+++ b/core/java/android/hardware/biometrics/PromptInfo.java
@@ -195,6 +195,10 @@
return true;
} else if (mContentView != null && isContentViewMoreOptionsButtonUsed()) {
return true;
+ } else if (Flags.mandatoryBiometrics()
+ && (mAuthenticators & BiometricManager.Authenticators.MANDATORY_BIOMETRICS)
+ != 0) {
+ return true;
}
return false;
}
diff --git a/core/java/android/net/OWNERS b/core/java/android/net/OWNERS
index feeef55..92ea0cf 100644
--- a/core/java/android/net/OWNERS
+++ b/core/java/android/net/OWNERS
@@ -3,6 +3,6 @@
include platform/frameworks/base:/services/core/java/com/android/server/net/OWNERS
per-file **IpSec* = file:/services/core/java/com/android/server/vcn/OWNERS
-per-file SSL*,Uri*,Url* = prb@google.com,oth@google.com,narayan@google.com,ngeoffray@google.com
+per-file SSL*,Uri*,Url* = prb@google.com,sorinbasca@google.com,narayan@google.com,ngeoffray@google.com
per-file SntpClient* = file:/services/core/java/com/android/server/timedetector/OWNERS
per-file Uri.java,Uri.aidl = varunshah@google.com
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index d91508f..4e8a04f 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -11046,6 +11046,12 @@
public static final String BIOMETRIC_APP_ENABLED = "biometric_app_enabled";
/**
+ * Whether or not mandatory biometrics is enabled.
+ * @hide
+ */
+ public static final String MANDATORY_BIOMETRICS = "mandatory_biometrics";
+
+ /**
* Whether or not active unlock triggers on wake.
* @hide
*/
diff --git a/core/java/android/service/notification/Adjustment.java b/core/java/android/service/notification/Adjustment.java
index 9c14946..63410c7 100644
--- a/core/java/android/service/notification/Adjustment.java
+++ b/core/java/android/service/notification/Adjustment.java
@@ -15,6 +15,8 @@
*/
package android.service.notification;
+import android.annotation.FlaggedApi;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.StringDef;
@@ -62,7 +64,8 @@
KEY_IMPORTANCE_PROPOSAL,
KEY_SENSITIVE_CONTENT,
KEY_RANKING_SCORE,
- KEY_NOT_CONVERSATION
+ KEY_NOT_CONVERSATION,
+ KEY_TYPE
})
@Retention(RetentionPolicy.SOURCE)
public @interface Keys {}
@@ -172,6 +175,59 @@
public static final String KEY_NOT_CONVERSATION = "key_not_conversation";
/**
+ * Data type: int, the classification type of this notification. The OS may display
+ * notifications differently depending on the type, and may change the alerting level of the
+ * notification.
+ */
+ @FlaggedApi(Flags.FLAG_NOTIFICATION_CLASSIFICATION)
+ public static final String KEY_TYPE = "key_type";
+
+ /** @hide */
+ @IntDef(prefix = { "TYPE_" }, value = {
+ TYPE_UNKNOWN,
+ TYPE_OTHER,
+ TYPE_PROMOTION,
+ TYPE_SOCIAL_MEDIA,
+ TYPE_NEWS,
+ TYPE_CONTENT_RECOMMENDATION
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Types {}
+
+ /**
+ * The type of this notification is unknown.
+ */
+ @FlaggedApi(Flags.FLAG_NOTIFICATION_CLASSIFICATION)
+ public static final int TYPE_UNKNOWN = -1;
+ /**
+ * The type of this notification is not one of ones known to the NotificationAssistantService.
+ */
+ @FlaggedApi(Flags.FLAG_NOTIFICATION_CLASSIFICATION)
+ public static final int TYPE_OTHER = 0;
+ /**
+ * The type of this notification is a promotion/deal.
+ */
+ @FlaggedApi(Flags.FLAG_NOTIFICATION_CLASSIFICATION)
+ public static final int TYPE_PROMOTION = 1;
+ /**
+ * The type of this notification is social media content that isn't a
+ * {@link Notification.Builder#setShortcutId(String) conversation}.
+ */
+ @FlaggedApi(Flags.FLAG_NOTIFICATION_CLASSIFICATION)
+ public static final int TYPE_SOCIAL_MEDIA = 2;
+ /**
+ * The type of this notification is news.
+ */
+ @FlaggedApi(Flags.FLAG_NOTIFICATION_CLASSIFICATION)
+ public static final int TYPE_NEWS = 3;
+ /**
+ * The type of this notification is content recommendation, for example new videos or books the
+ * user may be interested in.
+ */
+ @FlaggedApi(Flags.FLAG_NOTIFICATION_CLASSIFICATION)
+ public static final int TYPE_CONTENT_RECOMMENDATION = 4;
+
+ /**
* Create a notification adjustment.
*
* @param pkg The package of the notification.
diff --git a/core/java/android/service/notification/flags.aconfig b/core/java/android/service/notification/flags.aconfig
index c5b4b41..bdef041 100644
--- a/core/java/android/service/notification/flags.aconfig
+++ b/core/java/android/service/notification/flags.aconfig
@@ -35,4 +35,12 @@
description: "Guards the new CallStyleNotificationEventsCallback"
bug: "305095040"
is_fixed_read_only: true
+}
+
+flag {
+ name: "notification_classification"
+ is_exported: true
+ namespace: "systemui"
+ description: "Allows the NAS to classify notifications"
+ bug: "343988084"
}
\ No newline at end of file
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index 79a9f2d..72d2d3b 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -16,15 +16,6 @@
package android.view;
-import static android.os.IInputConstants.INPUT_EVENT_FLAG_CANCELED;
-import static android.os.IInputConstants.MOTION_EVENT_FLAG_HOVER_EXIT_PENDING;
-import static android.os.IInputConstants.INPUT_EVENT_FLAG_IS_ACCESSIBILITY_EVENT;
-import static android.os.IInputConstants.MOTION_EVENT_FLAG_IS_GENERATED_GESTURE;
-import static android.os.IInputConstants.MOTION_EVENT_FLAG_NO_FOCUS_CHANGE;
-import static android.os.IInputConstants.INPUT_EVENT_FLAG_TAINTED;
-import static android.os.IInputConstants.MOTION_EVENT_FLAG_TARGET_ACCESSIBILITY_FOCUS;
-import static android.os.IInputConstants.MOTION_EVENT_FLAG_WINDOW_IS_OBSCURED;
-import static android.os.IInputConstants.MOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
import static android.view.Display.DEFAULT_DISPLAY;
import static java.lang.annotation.RetentionPolicy.SOURCE;
@@ -38,6 +29,7 @@
import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Matrix;
import android.os.Build;
+import android.os.MotionEventFlag;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.SystemClock;
@@ -476,7 +468,7 @@
* to drop the suspect touches or to take additional precautions to confirm the user's
* actual intent.
*/
- public static final int FLAG_WINDOW_IS_OBSCURED = MOTION_EVENT_FLAG_WINDOW_IS_OBSCURED;
+ public static final int FLAG_WINDOW_IS_OBSCURED = MotionEventFlag.WINDOW_IS_OBSCURED;
/**
* This flag indicates that the window that received this motion event is partly
@@ -493,7 +485,7 @@
* obstructed in areas other than the touched location.
*/
public static final int FLAG_WINDOW_IS_PARTIALLY_OBSCURED =
- MOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
+ MotionEventFlag.WINDOW_IS_PARTIALLY_OBSCURED;
/**
* This private flag is only set on {@link #ACTION_HOVER_MOVE} events and indicates that
@@ -501,7 +493,7 @@
* prevent generating redundant {@link #ACTION_HOVER_ENTER} events.
* @hide
*/
- public static final int FLAG_HOVER_EXIT_PENDING = MOTION_EVENT_FLAG_HOVER_EXIT_PENDING;
+ public static final int FLAG_HOVER_EXIT_PENDING = MotionEventFlag.HOVER_EXIT_PENDING;
/**
* This flag indicates that the event has been generated by a gesture generator. It
@@ -509,7 +501,7 @@
*
* @hide
*/
- public static final int FLAG_IS_GENERATED_GESTURE = MOTION_EVENT_FLAG_IS_GENERATED_GESTURE;
+ public static final int FLAG_IS_GENERATED_GESTURE = MotionEventFlag.IS_GENERATED_GESTURE;
/**
* This flag is only set for events with {@link #ACTION_POINTER_UP} and {@link #ACTION_CANCEL}.
@@ -522,7 +514,7 @@
* @see #ACTION_POINTER_UP
* @see #ACTION_CANCEL
*/
- public static final int FLAG_CANCELED = INPUT_EVENT_FLAG_CANCELED;
+ public static final int FLAG_CANCELED = MotionEventFlag.CANCELED;
/**
* This flag indicates that the event will not cause a focus change if it is directed to an
@@ -531,7 +523,7 @@
* window into focus.
* @hide
*/
- public static final int FLAG_NO_FOCUS_CHANGE = MOTION_EVENT_FLAG_NO_FOCUS_CHANGE;
+ public static final int FLAG_NO_FOCUS_CHANGE = MotionEventFlag.NO_FOCUS_CHANGE;
/**
* This flag indicates that this event was modified by or generated from an accessibility
@@ -539,7 +531,7 @@
* @hide
*/
@TestApi
- public static final int FLAG_IS_ACCESSIBILITY_EVENT = INPUT_EVENT_FLAG_IS_ACCESSIBILITY_EVENT;
+ public static final int FLAG_IS_ACCESSIBILITY_EVENT = MotionEventFlag.IS_ACCESSIBILITY_EVENT;
/**
* Private flag that indicates when the system has detected that this motion event
@@ -550,7 +542,7 @@
* @see #isTainted
* @see #setTainted
*/
- public static final int FLAG_TAINTED = INPUT_EVENT_FLAG_TAINTED;
+ public static final int FLAG_TAINTED = MotionEventFlag.TAINTED;
/**
* Private flag indicating that this event was synthesized by the system and should be delivered
@@ -566,7 +558,7 @@
* @see #setTargetAccessibilityFocus(boolean)
*/
public static final int FLAG_TARGET_ACCESSIBILITY_FOCUS =
- MOTION_EVENT_FLAG_TARGET_ACCESSIBILITY_FOCUS;
+ MotionEventFlag.TARGET_ACCESSIBILITY_FOCUS;
/** @hide */
@IntDef(flag = true, prefix = { "FLAG_" }, value = {
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 3c5623f..9896d98 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -17,8 +17,10 @@
package android.widget;
import static android.appwidget.flags.Flags.FLAG_DRAW_DATA_PARCEL;
+import static android.appwidget.flags.Flags.FLAG_REMOTE_VIEWS_PROTO;
import static android.appwidget.flags.Flags.drawDataParcel;
import static android.appwidget.flags.Flags.remoteAdapterConversion;
+import static android.util.proto.ProtoInputStream.NO_MORE_FIELDS;
import static android.view.inputmethod.Flags.FLAG_HOME_SCREEN_HANDWRITING_DELEGATOR;
import android.annotation.AttrRes;
@@ -94,6 +96,9 @@
import android.util.SparseIntArray;
import android.util.TypedValue;
import android.util.TypedValue.ComplexDimensionUnit;
+import android.util.proto.ProtoInputStream;
+import android.util.proto.ProtoOutputStream;
+import android.util.proto.ProtoUtils;
import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
import android.view.LayoutInflater.Filter;
@@ -7822,4 +7827,278 @@
mClassCookies = classCookies;
}
}
+
+ /**
+ * Write this RemoteViews to proto.
+ * @hide
+ */
+ @FlaggedApi(FLAG_REMOTE_VIEWS_PROTO)
+ public void writePreviewToProto(@NonNull Context context, @NonNull ProtoOutputStream out) {
+ if (mApplication != null) {
+ // mApplication may be null if this was created with DrawInstructions constructor.
+ out.write(RemoteViewsProto.PACKAGE_NAME, mApplication.packageName);
+ }
+ Resources appResources = getContextForResourcesEnsuringCorrectCachedApkPaths(
+ context).getResources();
+ if (mLayoutId != 0) {
+ out.write(RemoteViewsProto.LAYOUT_ID, appResources.getResourceName(mLayoutId));
+ }
+ if (mLightBackgroundLayoutId != 0) {
+ out.write(RemoteViewsProto.LIGHT_BACKGROUND_LAYOUT_ID,
+ appResources.getResourceName(mLightBackgroundLayoutId));
+ }
+ if (mViewId != 0 && mViewId != -1) {
+ out.write(RemoteViewsProto.VIEW_ID, appResources.getResourceName(mViewId));
+ }
+ out.write(RemoteViewsProto.IS_ROOT, mIsRoot);
+ out.write(RemoteViewsProto.APPLY_FLAGS, mApplyFlags);
+ out.write(RemoteViewsProto.HAS_DRAW_INSTRUCTIONS, mHasDrawInstructions);
+ if (mProviderInstanceId != -1) {
+ out.write(RemoteViewsProto.PROVIDER_INSTANCE_ID, mProviderInstanceId);
+ }
+
+ if (!hasMultipleLayouts()) {
+ out.write(RemoteViewsProto.MODE, MODE_NORMAL);
+ if (mIdealSize != null) {
+ final long token = out.start(RemoteViewsProto.IDEAL_SIZE);
+ out.write(SizeFProto.WIDTH, mIdealSize.getWidth());
+ out.write(SizeFProto.HEIGHT, mIdealSize.getHeight());
+ out.end(token);
+ }
+ } else if (hasSizedRemoteViews()) {
+ out.write(RemoteViewsProto.MODE, MODE_HAS_SIZED_REMOTEVIEWS);
+ for (RemoteViews view : mSizedRemoteViews) {
+ final long sizedViewToken = out.start(RemoteViewsProto.SIZED_REMOTEVIEWS);
+ view.writePreviewToProto(context, out);
+ out.end(sizedViewToken);
+ }
+ } else {
+ out.write(RemoteViewsProto.MODE, MODE_HAS_LANDSCAPE_AND_PORTRAIT);
+ final long landscapeViewToken = out.start(RemoteViewsProto.LANDSCAPE_REMOTEVIEWS);
+ mLandscape.writePreviewToProto(context, out);
+ out.end(landscapeViewToken);
+ final long portraitViewToken = out.start(RemoteViewsProto.PORTRAIT_REMOTEVIEWS);
+ mPortrait.writePreviewToProto(context, out);
+ out.end(portraitViewToken);
+ }
+ }
+
+ /**
+ * Create a RemoteViews from proto input.
+ * @hide
+ */
+ @FlaggedApi(FLAG_REMOTE_VIEWS_PROTO)
+ public static RemoteViews createPreviewFromProto(Context context, ProtoInputStream in)
+ throws Exception {
+ return createFromProto(in).create(context, context.getResources(), /* rootData= */ null,
+ /* depth= */ 0);
+ }
+
+ private static PendingResources<RemoteViews> createFromProto(ProtoInputStream in)
+ throws Exception {
+ // Grouping these variables into an anonymous object allows us to access them through `ref`
+ // (which is final) later in the lambda.
+ final var ref = new Object() {
+ final RemoteViews mRv = new RemoteViews();
+ int mMode = 0;
+ int mApplyFlags = 0;
+ long mProviderInstanceId = -1;
+ String mPackageName = null;
+ SizeF mIdealSize = null;
+ String mLayoutResName = null;
+ String mLightBackgroundResName = null;
+ String mViewResName = null;
+ final List<PendingResources<RemoteViews>> mSizedRemoteViews = new ArrayList<>();
+ PendingResources<RemoteViews> mLandscapeViews = null;
+ PendingResources<RemoteViews> mPortraitViews = null;
+ boolean mIsRoot = false;
+ boolean mHasDrawInstructions = false;
+ };
+
+ try {
+ while (in.nextField() != NO_MORE_FIELDS) {
+ switch (in.getFieldNumber()) {
+ case (int) RemoteViewsProto.MODE:
+ ref.mMode = in.readInt(RemoteViewsProto.MODE);
+ break;
+ case (int) RemoteViewsProto.PACKAGE_NAME:
+ ref.mPackageName = in.readString(RemoteViewsProto.PACKAGE_NAME);
+ break;
+ case (int) RemoteViewsProto.IDEAL_SIZE:
+ final long idealSizeToken = in.start(RemoteViewsProto.IDEAL_SIZE);
+ ref.mIdealSize = createSizeFFromProto(in);
+ in.end(idealSizeToken);
+ break;
+ case (int) RemoteViewsProto.LAYOUT_ID:
+ ref.mLayoutResName = in.readString(RemoteViewsProto.LAYOUT_ID);
+ break;
+ case (int) RemoteViewsProto.LIGHT_BACKGROUND_LAYOUT_ID:
+ ref.mLightBackgroundResName = in.readString(
+ RemoteViewsProto.LIGHT_BACKGROUND_LAYOUT_ID);
+ break;
+ case (int) RemoteViewsProto.VIEW_ID:
+ ref.mViewResName = in.readString(RemoteViewsProto.VIEW_ID);
+ break;
+ case (int) RemoteViewsProto.APPLY_FLAGS:
+ ref.mApplyFlags = in.readInt(RemoteViewsProto.APPLY_FLAGS);
+ break;
+ case (int) RemoteViewsProto.PROVIDER_INSTANCE_ID:
+ ref.mProviderInstanceId = in.readInt(RemoteViewsProto.PROVIDER_INSTANCE_ID);
+ break;
+ case (int) RemoteViewsProto.SIZED_REMOTEVIEWS:
+ final long sizedToken = in.start(RemoteViewsProto.SIZED_REMOTEVIEWS);
+ ref.mSizedRemoteViews.add(createFromProto(in));
+ in.end(sizedToken);
+ break;
+ case (int) RemoteViewsProto.LANDSCAPE_REMOTEVIEWS:
+ final long landscapeToken = in.start(
+ RemoteViewsProto.LANDSCAPE_REMOTEVIEWS);
+ ref.mLandscapeViews = createFromProto(in);
+ in.end(landscapeToken);
+ break;
+ case (int) RemoteViewsProto.PORTRAIT_REMOTEVIEWS:
+ final long portraitToken = in.start(RemoteViewsProto.PORTRAIT_REMOTEVIEWS);
+ ref.mPortraitViews = createFromProto(in);
+ in.end(portraitToken);
+ break;
+ case (int) RemoteViewsProto.IS_ROOT:
+ ref.mIsRoot = in.readBoolean(RemoteViewsProto.IS_ROOT);
+ break;
+ case (int) RemoteViewsProto.HAS_DRAW_INSTRUCTIONS:
+ ref.mHasDrawInstructions = in.readBoolean(
+ RemoteViewsProto.HAS_DRAW_INSTRUCTIONS);
+ break;
+ default:
+ Log.w(LOG_TAG, "Unhandled field while reading RemoteViews proto!\n"
+ + ProtoUtils.currentFieldToString(in));
+ }
+ }
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+
+ return (context, resources, rootData, depth) -> {
+ if (depth > MAX_NESTED_VIEWS && (UserHandle.getAppId(Binder.getCallingUid())
+ != Process.SYSTEM_UID)) {
+ throw new IllegalArgumentException("Too many nested views.");
+ }
+ depth++;
+
+ RemoteViews rv = ref.mRv;
+ rv.mApplyFlags = ref.mApplyFlags;
+ rv.mIsRoot = ref.mIsRoot;
+ rv.mHasDrawInstructions = ref.mHasDrawInstructions;
+
+ // The root view will read its HierarchyRootData (bitmap cache, collection cache) from
+ // proto; all nested views will instead get it through the rootData parameter.
+ if (rootData == null) {
+ if (!rv.mIsRoot || depth != 1) {
+ throw new IllegalStateException(
+ "A nested view did not receive HierarchyRootData");
+ }
+ rootData = rv.getHierarchyRootData();
+ } else {
+ rv.configureAsChild(rootData);
+ }
+
+ Context appContext = null;
+ Resources appResources = null;
+ if (!ref.mHasDrawInstructions) {
+ checkProtoResultNotNull(ref.mPackageName, "No application info");
+ rv.mApplication = context.getPackageManager().getApplicationInfo(ref.mPackageName,
+ /* flags= */ 0);
+ appContext = rv.getContextForResourcesEnsuringCorrectCachedApkPaths(context);
+ appResources = appContext.getResources();
+
+ checkProtoResultNotNull(ref.mLayoutResName, "No layout id");
+ rv.mLayoutId = appResources.getIdentifier(ref.mLayoutResName, /* defType= */ null,
+ /* defPackage= */ null);
+ checkValidResource(rv.mLayoutId, "Invalid layout id", ref.mLayoutResName);
+
+ if (ref.mViewResName != null) {
+ rv.mViewId = appResources.getIdentifier(ref.mViewResName, /* defType= */ null,
+ /* defPackage= */ null);
+ checkValidResource(rv.mViewId, "Invalid view id", ref.mViewResName);
+ }
+
+ if (ref.mLightBackgroundResName != null) {
+ int lightBackgroundLayoutId = appResources.getIdentifier(
+ ref.mLightBackgroundResName,
+ /* defType= */ null, /* defPackage= */ null);
+ checkValidResource(lightBackgroundLayoutId,
+ "Invalid light background layout id", ref.mLightBackgroundResName);
+ rv.setLightBackgroundLayoutId(lightBackgroundLayoutId);
+ }
+ }
+ if (ref.mProviderInstanceId != -1) {
+ rv.mProviderInstanceId = ref.mProviderInstanceId;
+ }
+ if (ref.mMode == MODE_NORMAL) {
+ rv.setIdealSize(ref.mIdealSize);
+ return rv;
+ } else if (ref.mMode == MODE_HAS_SIZED_REMOTEVIEWS) {
+ List<RemoteViews> sizedViews = new ArrayList<>();
+ for (RemoteViews.PendingResources<RemoteViews> pendingViews :
+ ref.mSizedRemoteViews) {
+ RemoteViews views = pendingViews.create(context, resources, rootData, depth);
+ sizedViews.add(views);
+ }
+ rv.initializeSizedRemoteViews(sizedViews.iterator());
+ return rv;
+ } else if (ref.mMode == MODE_HAS_LANDSCAPE_AND_PORTRAIT) {
+ checkProtoResultNotNull(ref.mLandscapeViews, "Missing landscape views");
+ checkProtoResultNotNull(ref.mPortraitViews, "Missing portrait views");
+ RemoteViews parentRv = new RemoteViews(
+ ref.mLandscapeViews.create(context, resources, rootData, depth),
+ ref.mPortraitViews.create(context, resources, rootData, depth));
+ parentRv.initializeFrom(/* src= */ rv, /* hierarchyRoot= */ rv);
+ return parentRv;
+ } else {
+ throw new InvalidProtoException(ref.mMode + " is not a valid mode.");
+ }
+ };
+ }
+
+ private static class InvalidProtoException extends Exception {
+ InvalidProtoException(String message) {
+ super(message);
+ }
+ }
+
+ private interface PendingResources<T> {
+ T create(Context context, Resources appResources, HierarchyRootData rootData, int depth)
+ throws Exception;
+ }
+
+ private static void checkValidResource(int id, String message, String resName)
+ throws Exception {
+ if (id == 0) throw new Exception(message + ": " + resName);
+ }
+
+ private static void checkProtoResultNotNull(Object o, String message)
+ throws InvalidProtoException {
+ if (o == null) {
+ throw new InvalidProtoException(message);
+ }
+ }
+
+ private static SizeF createSizeFFromProto(ProtoInputStream in) throws Exception {
+ float width = 0;
+ float height = 0;
+ while (in.nextField() != NO_MORE_FIELDS) {
+ switch (in.getFieldNumber()) {
+ case (int) SizeFProto.WIDTH:
+ width = in.readFloat(SizeFProto.WIDTH);
+ break;
+ case (int) SizeFProto.HEIGHT:
+ height = in.readFloat(SizeFProto.HEIGHT);
+ break;
+ default:
+ Log.w(LOG_TAG, "Unhandled field while reading SizeF proto!\n"
+ + ProtoUtils.currentFieldToString(in));
+ }
+ }
+
+ return new SizeF(width, height);
+ }
}
diff --git a/core/java/android/window/WindowTokenClient.java b/core/java/android/window/WindowTokenClient.java
index cc54a93..15adc80 100644
--- a/core/java/android/window/WindowTokenClient.java
+++ b/core/java/android/window/WindowTokenClient.java
@@ -19,8 +19,6 @@
import static android.window.ConfigurationHelper.isDifferentDisplay;
import static android.window.ConfigurationHelper.shouldUpdateResources;
-import static com.android.window.flags.Flags.windowTokenConfigThreadSafe;
-
import android.annotation.AnyThread;
import android.annotation.MainThread;
import android.annotation.NonNull;
@@ -146,7 +144,7 @@
if (context == null) {
return;
}
- if (shouldReportConfigChange && windowTokenConfigThreadSafe()) {
+ if (shouldReportConfigChange) {
// Only report to ClientTransactionListenerController when shouldReportConfigChange.
final ClientTransactionListenerController controller =
getClientTransactionListenerController();
diff --git a/core/java/android/window/flags/windowing_sdk.aconfig b/core/java/android/window/flags/windowing_sdk.aconfig
index 0a4762d..552bb46 100644
--- a/core/java/android/window/flags/windowing_sdk.aconfig
+++ b/core/java/android/window/flags/windowing_sdk.aconfig
@@ -93,16 +93,6 @@
flag {
namespace: "windowing_sdk"
- name: "window_token_config_thread_safe"
- description: "Ensure the Configuration pre/post changed is thread safe"
- bug: "334285008"
- metadata {
- purpose: PURPOSE_BUGFIX
- }
-}
-
-flag {
- namespace: "windowing_sdk"
name: "always_defer_transition_when_apply_wct"
description: "Report error when defer transition fails when it should not"
bug: "335562144"
diff --git a/core/java/com/android/internal/compat/ChangeReporter.java b/core/java/com/android/internal/compat/ChangeReporter.java
index ded142c..f611571 100644
--- a/core/java/com/android/internal/compat/ChangeReporter.java
+++ b/core/java/com/android/internal/compat/ChangeReporter.java
@@ -42,7 +42,7 @@
*
* @hide
*/
-public final class ChangeReporter {
+public class ChangeReporter {
private static final String TAG = "CompatChangeReporter";
private static final Function<Integer, Set<ChangeReport>> NEW_CHANGE_REPORT_SET =
uid -> Collections.synchronizedSet(new HashSet<>());
@@ -88,17 +88,20 @@
* Report the change to stats log and to the debug log if the change was not previously
* logged already.
*
- * @param uid affected by the change
- * @param changeId the reported change id
- * @param state of the reported change - enabled/disabled/only logged
- * @param isLoggableBySdk whether debug logging is allowed for this change based on target
- * SDK version. This is combined with other logic to determine whether to
- * actually log. If the sdk version does not matter, should be true.
+ * @param uid affected by the change
+ * @param changeId the reported change id
+ * @param state of the reported change - enabled/disabled/only logged
+ * @param isKnownSystemApp do we know that the affected app is a system app? (if true is
+ * definitely a system app, if false it may or may not be a system app)
+ * @param isLoggableBySdk whether debug logging is allowed for this change based on target
+ * SDK version. This is combined with other logic to determine whether
+ * to actually log. If the sdk version does not matter, should be true.
*/
- public void reportChange(int uid, long changeId, int state, boolean isLoggableBySdk) {
+ public void reportChange(int uid, long changeId, int state, boolean isKnownSystemApp,
+ boolean isLoggableBySdk) {
boolean isAlreadyReported =
checkAndSetIsAlreadyReported(uid, new ChangeReport(changeId, state));
- if (!isAlreadyReported) {
+ if (shouldWriteToStatsLog(isKnownSystemApp, isAlreadyReported)) {
FrameworkStatsLog.write(FrameworkStatsLog.APP_COMPATIBILITY_CHANGE_REPORTED, uid,
changeId, state, mSource);
}
@@ -116,7 +119,7 @@
* @param state of the reported change - enabled/disabled/only logged
*/
public void reportChange(int uid, long changeId, int state) {
- reportChange(uid, changeId, state, true);
+ reportChange(uid, changeId, state, false, true);
}
/**
@@ -136,14 +139,15 @@
/**
* Returns whether the next report should be logged to FrameworkStatsLog.
*
- * @param uid affected by the change
- * @param changeId the reported change id
- * @param state of the reported change - enabled/disabled/only logged
+ * @param isKnownSystemApp do we know that the affected app is a system app? (if true is
+ * definitely a system app, if false it may or may not be a system app)
+ * @param isAlreadyReported is the change already reported
* @return true if the report should be logged
*/
@VisibleForTesting
- boolean shouldWriteToStatsLog(int uid, long changeId, int state) {
- return !isAlreadyReported(uid, new ChangeReport(changeId, state));
+ boolean shouldWriteToStatsLog(boolean isKnownSystemApp, boolean isAlreadyReported) {
+ // We don't log where we know the source is a system app or is already reported
+ return !isKnownSystemApp && !isAlreadyReported;
}
/**
@@ -224,6 +228,19 @@
return mReportedChanges.getOrDefault(uid, EMPTY_SET).contains(report);
}
+ /**
+ * Returns whether the next report should be logged.
+ *
+ * @param uid affected by the change
+ * @param changeId the reported change id
+ * @param state of the reported change - enabled/disabled/only logged
+ * @return true if the report should be logged
+ */
+ @VisibleForTesting
+ boolean isAlreadyReported(int uid, long changeId, int state) {
+ return isAlreadyReported(uid, new ChangeReport(changeId, state));
+ }
+
private void markAsReported(int uid, ChangeReport report) {
mReportedChanges.computeIfAbsent(uid, NEW_CHANGE_REPORT_SET).add(report);
}
diff --git a/core/java/com/android/internal/jank/Cuj.java b/core/java/com/android/internal/jank/Cuj.java
index 23bd64d..a52d33a 100644
--- a/core/java/com/android/internal/jank/Cuj.java
+++ b/core/java/com/android/internal/jank/Cuj.java
@@ -147,8 +147,16 @@
*/
public static final int CUJ_DESKTOP_MODE_MAXIMIZE_WINDOW = 104;
+ /**
+ * Track fade-in animation when in SystemUI process fold
+ *
+ * <p>Tracking starts after the screen turns on and finish when the animation is over {@link
+ * com.android.systemui.unfold.FoldLightRevealOverlayAnimation#playFoldLightRevealOverlayAnimation} for the span
+ */
+ public static final int CUJ_FOLD_ANIM = 105;
+
// When adding a CUJ, update this and make sure to also update CUJ_TO_STATSD_INTERACTION_TYPE.
- @VisibleForTesting static final int LAST_CUJ = CUJ_DESKTOP_MODE_MAXIMIZE_WINDOW;
+ @VisibleForTesting static final int LAST_CUJ = CUJ_FOLD_ANIM;
/** @hide */
@IntDef({
@@ -244,7 +252,8 @@
CUJ_LAUNCHER_WIDGET_BOTTOM_SHEET_CLOSE_BACK,
CUJ_LAUNCHER_PRIVATE_SPACE_LOCK,
CUJ_LAUNCHER_PRIVATE_SPACE_UNLOCK,
- CUJ_DESKTOP_MODE_MAXIMIZE_WINDOW
+ CUJ_DESKTOP_MODE_MAXIMIZE_WINDOW,
+ CUJ_FOLD_ANIM
})
@Retention(RetentionPolicy.SOURCE)
public @interface CujType {}
@@ -351,6 +360,7 @@
CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_PRIVATE_SPACE_LOCK] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_PRIVATE_SPACE_LOCK;
CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_PRIVATE_SPACE_UNLOCK] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_PRIVATE_SPACE_UNLOCK;
CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_DESKTOP_MODE_MAXIMIZE_WINDOW] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__DESKTOP_MODE_MAXIMIZE_WINDOW;
+ CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_FOLD_ANIM] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__FOLD_ANIM;
}
private Cuj() {
@@ -555,6 +565,8 @@
return "LAUNCHER_PRIVATE_SPACE_UNLOCK";
case CUJ_DESKTOP_MODE_MAXIMIZE_WINDOW:
return "DESKTOP_MODE_MAXIMIZE_WINDOW";
+ case CUJ_FOLD_ANIM:
+ return "FOLD_ANIM";
}
return "UNKNOWN";
}
diff --git a/core/java/com/android/internal/jank/OWNERS b/core/java/com/android/internal/jank/OWNERS
index 2f3bbee..5463883 100644
--- a/core/java/com/android/internal/jank/OWNERS
+++ b/core/java/com/android/internal/jank/OWNERS
@@ -4,4 +4,5 @@
ahanwu@google.com
vadimt@google.com
marcinoc@google.com
-pmuetschard@google.com
\ No newline at end of file
+pmuetschard@google.com
+nicomazz@google.com
diff --git a/core/jni/OWNERS b/core/jni/OWNERS
index 163f32e..b2bc19c 100644
--- a/core/jni/OWNERS
+++ b/core/jni/OWNERS
@@ -2,7 +2,7 @@
per-file *Camera*,*camera* = file:platform/frameworks/av:/camera/OWNERS
# Connectivity
-per-file android_net_* = codewiz@google.com, jchalard@google.com, lorenzo@google.com, reminv@google.com, satk@google.com
+per-file android_net_* = jchalard@google.com, lorenzo@google.com, reminv@google.com, satk@google.com
# Choreographer
per-file android_view_DisplayEventReceiver* = file:platform/frameworks/native:/services/surfaceflinger/OWNERS
@@ -84,7 +84,7 @@
# These are highly common-use files
per-file Android.bp = file:/graphics/java/android/graphics/OWNERS
per-file AndroidRuntime.cpp = file:/graphics/java/android/graphics/OWNERS
-per-file AndroidRuntime.cpp = calin@google.com, ngeoffray@google.com, oth@google.com
+per-file AndroidRuntime.cpp = file:platform/art:main:/OWNERS
# Although marked "view" this is mostly graphics stuff
per-file android_view_* = file:/graphics/java/android/graphics/OWNERS
# File used for Android Studio layoutlib
diff --git a/core/proto/android/server/activitymanagerservice.proto b/core/proto/android/server/activitymanagerservice.proto
index 921c41c..90069f1 100644
--- a/core/proto/android/server/activitymanagerservice.proto
+++ b/core/proto/android/server/activitymanagerservice.proto
@@ -1038,7 +1038,7 @@
optional int32 uid = 1;
repeated .android.app.ApplicationExitInfoProto app_exit_info = 2;
- repeated .android.app.ApplicationExitInfoProto app_recoverable_crash = 3;
+ repeated .android.app.ApplicationExitInfoProto app_recoverable_crash = 3 [deprecated=true];
}
repeated User users = 2;
}
diff --git a/core/proto/android/widget/remoteviews.proto b/core/proto/android/widget/remoteviews.proto
new file mode 100644
index 0000000..d24da03
--- /dev/null
+++ b/core/proto/android/widget/remoteviews.proto
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2024 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 optional 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.
+ */
+
+syntax = "proto2";
+
+option java_multiple_files = true;
+
+package android.widget;
+
+import "frameworks/base/core/proto/android/privacy.proto";
+
+/**
+ * An android.widget.RemoteViews object. This is used by RemoteViews.createPreviewFromProto
+ * and RemoteViews.writePreviewToProto.
+ *
+ * Any addition of fields here will require an update to the parsing code in RemoteViews.java.
+ * Otherwise the field will be ignored when parsing (with a logged warning).
+ *
+ * Do not change the tag number or type of any fields in order to maintain compatibility with
+ * previous versions. If a field is deleted, use `reserved` to mark its tag number.
+ */
+message RemoteViewsProto {
+ option (android.msg_privacy).dest = DEST_AUTOMATIC;
+ optional int32 mode = 1;
+ optional string package_name = 2;
+ optional string layout_id = 3;
+ optional string light_background_layout_id = 4;
+ optional string view_id = 5;
+ optional SizeFProto ideal_size = 6;
+ optional int32 apply_flags = 7;
+ optional int64 provider_instance_id = 8;
+ // RemoteViews for different sizes (created with RemoteViews(Map<SizeF, RemoteViews)
+ // constructor).
+ repeated RemoteViewsProto sized_remoteviews = 9;
+ // RemoteViews for portrait/landscape (created with RemoteViews(RemoteViews, RemoteViews)i
+ // constructor).
+ optional RemoteViewsProto portrait_remoteviews = 10;
+ optional RemoteViewsProto landscape_remoteviews = 11;
+ optional bool is_root = 12;
+ optional bool has_draw_instructions = 13;
+}
+
+
+message SizeFProto {
+ optional float width = 1;
+ optional float height = 2;
+}
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index b10e318..678dcff 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -6973,6 +6973,9 @@
Note that, indefinitely repeating vibrations are not allowed as shutdown vibrations. -->
<string name="config_defaultShutdownVibrationFile" />
+ <!-- Whether or not vibration is disabled during shutdown -->
+ <bool name="config_disableShutdownVibrationInZen">false</bool>
+
<!-- Whether single finger panning is enabled by default when magnification is on -->
<bool name="config_enable_a11y_magnification_single_panning">false</bool>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index b6e8383..351cbad 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -5430,6 +5430,10 @@
<string name="call_notification_screening_text">Screening an incoming call</string>
<string name="default_notification_channel_label">Uncategorized</string>
+ <string name="promotional_notification_channel_label">Promotions</string>
+ <string name="social_notification_channel_label">Social</string>
+ <string name="news_notification_channel_label">News</string>
+ <string name="recs_notification_channel_label">Recommendations</string>
<string name="importance_from_user">You set the importance of these notifications.</string>
<string name="importance_from_person">This is important because of the people involved.</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 85397fa..63934c4 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -5425,6 +5425,7 @@
<java-symbol type="drawable" name="focus_event_pressed_key_background" />
<java-symbol type="drawable" name="focus_event_rotary_input_background" />
<java-symbol type="string" name="config_defaultShutdownVibrationFile" />
+ <java-symbol type="bool" name="config_disableShutdownVibrationInZen" />
<java-symbol type="string" name="lockscreen_too_many_failed_attempts_countdown" />
<java-symbol type="bool" name="config_enable_a11y_magnification_single_panning" />
@@ -5516,6 +5517,12 @@
<java-symbol type="string" name="biometric_dangling_notification_action_set_up" />
<java-symbol type="string" name="biometric_dangling_notification_action_not_now" />
+ <!-- Notification bundles -->
+ <java-symbol type="string" name="promotional_notification_channel_label"/>
+ <java-symbol type="string" name="social_notification_channel_label"/>
+ <java-symbol type="string" name="news_notification_channel_label"/>
+ <java-symbol type="string" name="recs_notification_channel_label"/>
+
<!-- Priority Modes icons -->
<java-symbol type="drawable" name="ic_zen_mode_type_bedtime" />
<java-symbol type="drawable" name="ic_zen_mode_type_driving" />
@@ -5526,5 +5533,4 @@
<java-symbol type="drawable" name="ic_zen_mode_type_schedule_time" />
<java-symbol type="drawable" name="ic_zen_mode_type_theater" />
<java-symbol type="drawable" name="ic_zen_mode_type_unknown" />
-
</resources>
diff --git a/core/tests/BroadcastRadioTests/src/android/hardware/radio/RadioMetadataTest.java b/core/tests/BroadcastRadioTests/src/android/hardware/radio/RadioMetadataTest.java
index b3a0aba..db3a2da 100644
--- a/core/tests/BroadcastRadioTests/src/android/hardware/radio/RadioMetadataTest.java
+++ b/core/tests/BroadcastRadioTests/src/android/hardware/radio/RadioMetadataTest.java
@@ -470,6 +470,20 @@
}
@Test
+ public void equals_forMetadataWithDifferentContents_returnsFalse() {
+ mSetFlagsRule.enableFlags(Flags.FLAG_HD_RADIO_IMPROVED);
+ RadioMetadata metadata1 = mBuilder
+ .putStringArray(RadioMetadata.METADATA_KEY_UFIDS, UFIDS_VALUE)
+ .build();
+ RadioMetadata metadata2 = mBuilder
+ .putStringArray(RadioMetadata.METADATA_KEY_UFIDS, new String[]{"ufid3", "ufid2"})
+ .build();
+
+ mExpect.withMessage("Metadata with the same contents")
+ .that(metadata1).isNotEqualTo(metadata2);
+ }
+
+ @Test
public void describeContents_forMetadata() {
RadioMetadata metadata = mBuilder.build();
@@ -553,4 +567,25 @@
.that(metadata.getBitmap(RadioMetadata.METADATA_KEY_ICON))
.isEqualTo(bitmapResized);
}
+
+ @Test
+ public void toString_containsMetadataValues() {
+ mSetFlagsRule.enableFlags(Flags.FLAG_HD_RADIO_IMPROVED);
+ RadioMetadata metadataExpected = mBuilder
+ .putInt(RadioMetadata.METADATA_KEY_RDS_PI, INT_KEY_VALUE)
+ .putString(RadioMetadata.METADATA_KEY_ARTIST, ARTIST_KEY_VALUE)
+ .putStringArray(RadioMetadata.METADATA_KEY_UFIDS, UFIDS_VALUE)
+ .build();
+
+ String metadateString = metadataExpected.toString();
+
+ mExpect.withMessage("RDS PI value in converted sting for metadata")
+ .that(metadateString).contains(Integer.toString(INT_KEY_VALUE));
+ mExpect.withMessage("Artist value in converted sting for metadata")
+ .that(metadateString).contains(ARTIST_KEY_VALUE);
+ for (int i = 0; i < UFIDS_VALUE.length; i++) {
+ mExpect.withMessage("UFIDs[%s] value in converted sting for metadata", i)
+ .that(metadateString).contains(UFIDS_VALUE[i]);
+ }
+ }
}
diff --git a/core/tests/PlatformCompatFramework/src/com/android/internal/compat/ChangeReporterTest.java b/core/tests/PlatformCompatFramework/src/com/android/internal/compat/ChangeReporterTest.java
index 12a42f9..ed5e4af 100644
--- a/core/tests/PlatformCompatFramework/src/com/android/internal/compat/ChangeReporterTest.java
+++ b/core/tests/PlatformCompatFramework/src/com/android/internal/compat/ChangeReporterTest.java
@@ -37,15 +37,20 @@
long myChangeId = 500L, otherChangeId = 600L;
int myState = ChangeReporter.STATE_ENABLED, otherState = ChangeReporter.STATE_DISABLED;
- assertTrue(reporter.shouldWriteToStatsLog(myUid, myChangeId, myState));
+ assertTrue(reporter.shouldWriteToStatsLog(false,
+ reporter.isAlreadyReported(myUid, myChangeId, myState)));
reporter.reportChange(myUid, myChangeId, myState);
// Same report will not be logged again.
- assertFalse(reporter.shouldWriteToStatsLog(myUid, myChangeId, myState));
+ assertFalse(reporter.shouldWriteToStatsLog(false,
+ reporter.isAlreadyReported(myUid, myChangeId, myState)));
// Other reports will be logged.
- assertTrue(reporter.shouldWriteToStatsLog(otherUid, myChangeId, myState));
- assertTrue(reporter.shouldWriteToStatsLog(myUid, otherChangeId, myState));
- assertTrue(reporter.shouldWriteToStatsLog(myUid, myChangeId, otherState));
+ assertTrue(reporter.shouldWriteToStatsLog(false,
+ reporter.isAlreadyReported(otherUid, myChangeId, myState)));
+ assertTrue(reporter.shouldWriteToStatsLog(false,
+ reporter.isAlreadyReported(myUid, otherChangeId, myState)));
+ assertTrue(reporter.shouldWriteToStatsLog(false,
+ reporter.isAlreadyReported(myUid, myChangeId, otherState)));
}
@Test
@@ -55,15 +60,18 @@
long myChangeId = 500L;
int myState = ChangeReporter.STATE_ENABLED;
- assertTrue(reporter.shouldWriteToStatsLog(myUid, myChangeId, myState));
+ assertTrue(reporter.shouldWriteToStatsLog(false,
+ reporter.isAlreadyReported(myUid, myChangeId, myState)));
reporter.reportChange(myUid, myChangeId, myState);
// Same report will not be logged again.
- assertFalse(reporter.shouldWriteToStatsLog(myUid, myChangeId, myState));
+ assertFalse(reporter.shouldWriteToStatsLog(false,
+ reporter.isAlreadyReported(myUid, myChangeId, myState)));
reporter.resetReportedChanges(myUid);
// Same report will be logged again after reset.
- assertTrue(reporter.shouldWriteToStatsLog(myUid, myChangeId, myState));
+ assertTrue(reporter.shouldWriteToStatsLog(false,
+ reporter.isAlreadyReported(myUid, myChangeId, myState)));
}
@Test
@@ -196,4 +204,21 @@
// off.
assertTrue(reporter.shouldWriteToDebug(myUid, myChangeId, myDisabledState, false));
}
+
+ @Test
+ public void testDontLogSystemApps() {
+ // Verify we don't log an app if we know it's a system app when source is system server.
+ ChangeReporter systemServerReporter =
+ new ChangeReporter(ChangeReporter.SOURCE_SYSTEM_SERVER);
+
+ assertFalse(systemServerReporter.shouldWriteToStatsLog(true, false));
+ assertFalse(systemServerReporter.shouldWriteToStatsLog(true, true));
+
+ // Verify we don't log an app if we know it's a system app when source is unknown.
+ ChangeReporter unknownReporter =
+ new ChangeReporter(ChangeReporter.SOURCE_UNKNOWN_SOURCE);
+
+ assertFalse(unknownReporter.shouldWriteToStatsLog(true, false));
+ assertFalse(unknownReporter.shouldWriteToStatsLog(true, true));
+ }
}
diff --git a/core/tests/coretests/src/android/app/servertransaction/ClientTransactionListenerControllerTest.java b/core/tests/coretests/src/android/app/servertransaction/ClientTransactionListenerControllerTest.java
index ee1d1e1..3104f16 100644
--- a/core/tests/coretests/src/android/app/servertransaction/ClientTransactionListenerControllerTest.java
+++ b/core/tests/coretests/src/android/app/servertransaction/ClientTransactionListenerControllerTest.java
@@ -21,7 +21,6 @@
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
import static com.android.window.flags.Flags.FLAG_BUNDLE_CLIENT_TRANSACTION_FLAG;
-import static com.android.window.flags.Flags.FLAG_WINDOW_TOKEN_CONFIG_THREAD_SAFE;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
@@ -192,8 +191,6 @@
@Test
public void testWindowTokenClient_onConfigurationChanged() {
- mSetFlagsRule.enableFlags(FLAG_WINDOW_TOKEN_CONFIG_THREAD_SAFE);
-
doNothing().when(mController).onContextConfigurationPreChanged(any());
doNothing().when(mController).onContextConfigurationPostChanged(any());
diff --git a/core/tests/coretests/src/android/hardware/biometrics/BiometricPromptTest.java b/core/tests/coretests/src/android/hardware/biometrics/BiometricPromptTest.java
index ca91542..5464ea3 100644
--- a/core/tests/coretests/src/android/hardware/biometrics/BiometricPromptTest.java
+++ b/core/tests/coretests/src/android/hardware/biometrics/BiometricPromptTest.java
@@ -28,6 +28,7 @@
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -209,6 +210,25 @@
"The number of list items exceeds ");
}
+ @Test
+ public void testOnDialogDismissed_dialogDismissedNegative() throws RemoteException {
+ final ArgumentCaptor<IBiometricServiceReceiver> biometricServiceReceiverCaptor =
+ ArgumentCaptor.forClass(IBiometricServiceReceiver.class);
+ final BiometricPrompt.AuthenticationCallback callback =
+ mock(BiometricPrompt.AuthenticationCallback.class);
+ mBiometricPrompt.authenticate(mCancellationSignal, mExecutor, callback);
+ mLooper.dispatchAll();
+
+ verify(mService).authenticate(any(), anyLong(), anyInt(),
+ biometricServiceReceiverCaptor.capture(), anyString(), any());
+
+ biometricServiceReceiverCaptor.getValue().onDialogDismissed(
+ BiometricPrompt.DISMISSED_REASON_NEGATIVE);
+
+ verify(callback).onAuthenticationError(BiometricConstants.BIOMETRIC_ERROR_USER_CANCELED,
+ null /* errString */);
+ }
+
private String generateRandomString(int charNum) {
final Random random = new Random();
final StringBuilder longString = new StringBuilder(charNum);
diff --git a/core/tests/coretests/src/android/net/OWNERS b/core/tests/coretests/src/android/net/OWNERS
index beb77dc..831f444 100644
--- a/core/tests/coretests/src/android/net/OWNERS
+++ b/core/tests/coretests/src/android/net/OWNERS
@@ -1,5 +1,5 @@
include /services/core/java/com/android/server/net/OWNERS
-per-file SSL*,Url* = prb@google.com,oth@google.com,narayan@google.com,ngeoffray@google.com
+per-file SSL*,Url* = file:platform/libcore:main:/OWNERS_net_tests
per-file SntpClient* = file:/services/core/java/com/android/server/timedetector/OWNERS
per-file Uri* = varunshah@google.com
diff --git a/core/tests/coretests/src/android/widget/RemoteViewsProtoTest.java b/core/tests/coretests/src/android/widget/RemoteViewsProtoTest.java
new file mode 100644
index 0000000..8e9ba7b
--- /dev/null
+++ b/core/tests/coretests/src/android/widget/RemoteViewsProtoTest.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+package android.widget;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import android.content.Context;
+import android.util.SizeF;
+import android.util.proto.ProtoInputStream;
+import android.util.proto.ProtoOutputStream;
+import android.view.View;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.frameworks.coretests.R;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+
+import java.util.Map;
+
+/**
+ * Tests for RemoteViews.
+ */
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class RemoteViewsProtoTest {
+
+ // This can point to any other package which exists on the device.
+ private static final String OTHER_PACKAGE = "com.android.systemui";
+
+ @Rule
+ public final ExpectedException exception = ExpectedException.none();
+
+ private Context mContext;
+ private String mPackage;
+ private LinearLayout mContainer;
+
+ @Before
+ public void setup() {
+ mContext = InstrumentationRegistry.getContext();
+ mPackage = mContext.getPackageName();
+ mContainer = new LinearLayout(mContext);
+ }
+
+ @Test
+ public void copy_canStillBeApplied() {
+ RemoteViews original = new RemoteViews(mPackage, R.layout.remote_views_test);
+
+ RemoteViews clone = recreateFromProto(original);
+
+ clone.apply(mContext, mContainer);
+ }
+
+ @SuppressWarnings("ReturnValueIgnored")
+ @Test
+ public void clone_repeatedly() {
+ RemoteViews original = new RemoteViews(mPackage, R.layout.remote_views_test);
+
+ recreateFromProto(original);
+ recreateFromProto(original);
+
+ original.apply(mContext, mContainer);
+ }
+
+ @Test
+ public void clone_chained() {
+ RemoteViews original = new RemoteViews(mPackage, R.layout.remote_views_test);
+
+ RemoteViews clone = recreateFromProto(recreateFromProto(original));
+
+
+ clone.apply(mContext, mContainer);
+ }
+
+ @Test
+ public void landscapePortraitViews_lightBackgroundLayoutFlag() {
+ RemoteViews inner = new RemoteViews(mPackage, R.layout.remote_views_text);
+ inner.setLightBackgroundLayoutId(R.layout.remote_views_light_background_text);
+
+ RemoteViews parent = new RemoteViews(inner, inner);
+ parent.addFlags(RemoteViews.FLAG_USE_LIGHT_BACKGROUND_LAYOUT);
+
+ View view = recreateFromProto(parent).apply(mContext, mContainer);
+ assertNull(view.findViewById(R.id.text));
+ assertNotNull(view.findViewById(R.id.light_background_text));
+ }
+
+ @Test
+ public void sizedViews_lightBackgroundLayoutFlag() {
+ RemoteViews inner = new RemoteViews(mPackage, R.layout.remote_views_text);
+ inner.setLightBackgroundLayoutId(R.layout.remote_views_light_background_text);
+
+ RemoteViews parent = new RemoteViews(
+ Map.of(new SizeF(0, 0), inner, new SizeF(100, 100), inner));
+ parent.addFlags(RemoteViews.FLAG_USE_LIGHT_BACKGROUND_LAYOUT);
+
+ View view = recreateFromProto(parent).apply(mContext, mContainer);
+ assertNull(view.findViewById(R.id.text));
+ assertNotNull(view.findViewById(R.id.light_background_text));
+ }
+
+ @Test
+ public void nestedLandscapeViews() throws Exception {
+ RemoteViews views = new RemoteViews(mPackage, R.layout.remote_views_test);
+ for (int i = 0; i < 10; i++) {
+ views = new RemoteViews(views, new RemoteViews(mPackage, R.layout.remote_views_test));
+ }
+ // writeTo/createFromProto works
+ recreateFromProto(views);
+
+ views = new RemoteViews(mPackage, R.layout.remote_views_test);
+ for (int i = 0; i < 11; i++) {
+ views = new RemoteViews(views, new RemoteViews(mPackage, R.layout.remote_views_test));
+ }
+ // writeTo/createFromProto fails
+ exception.expect(IllegalArgumentException.class);
+ recreateFromProtoNoRethrow(views);
+ }
+
+ private RemoteViews recreateFromProto(RemoteViews views) {
+ try {
+ return recreateFromProtoNoRethrow(views);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private RemoteViews recreateFromProtoNoRethrow(RemoteViews views) throws Exception {
+ ProtoOutputStream out = new ProtoOutputStream();
+ views.writePreviewToProto(mContext, out);
+ ProtoInputStream in = new ProtoInputStream(out.getBytes());
+ return RemoteViews.createPreviewFromProto(mContext, in);
+ }
+}
diff --git a/data/etc/com.android.settings.xml b/data/etc/com.android.settings.xml
index 7a4b6bc..99911de 100644
--- a/data/etc/com.android.settings.xml
+++ b/data/etc/com.android.settings.xml
@@ -69,5 +69,6 @@
<permission name="android.permission.LIST_ENABLED_CREDENTIAL_PROVIDERS" />
<permission name="android.permission.SATELLITE_COMMUNICATION" />
<permission name="android.permission.READ_SYSTEM_GRAMMATICAL_GENDER" />
+ <permission name="android.permission.SET_BIOMETRIC_DIALOG_ADVANCED" />
</privapp-permissions>
</permissions>
diff --git a/data/etc/package-shareduid-allowlist.xml b/data/etc/package-shareduid-allowlist.xml
index 2401d4a..3b35f44 100644
--- a/data/etc/package-shareduid-allowlist.xml
+++ b/data/etc/package-shareduid-allowlist.xml
@@ -32,4 +32,5 @@
<config>
<allow-package-shareduid package="android.test.settings" shareduid="android.uid.system" />
+ <allow-package-shareduid package="com.android.performanceLaunch" shareduid="com.android.performanceapp.tests" />
</config>
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/DividerPresenter.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/DividerPresenter.java
index 290fefa..822a07c 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/DividerPresenter.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/DividerPresenter.java
@@ -169,6 +169,11 @@
@GuardedBy("mLock")
private int mDividerPosition;
+ /** Indicates if there are containers to be finished since the divider has appeared. */
+ @GuardedBy("mLock")
+ @VisibleForTesting
+ private boolean mHasContainersToFinish = false;
+
DividerPresenter(int taskId, @NonNull DragEventCallback dragEventCallback,
@NonNull Executor callbackExecutor) {
mTaskId = taskId;
@@ -180,7 +185,8 @@
void updateDivider(
@NonNull WindowContainerTransaction wct,
@NonNull TaskFragmentParentInfo parentInfo,
- @Nullable SplitContainer topSplitContainer) {
+ @Nullable SplitContainer topSplitContainer,
+ boolean isTaskFragmentVanished) {
if (!Flags.activityEmbeddingInteractiveDividerFlag()) {
return;
}
@@ -188,6 +194,18 @@
synchronized (mLock) {
// Clean up the decor surface if top SplitContainer is null.
if (topSplitContainer == null) {
+ // Check if there are containers to finish but the TaskFragment hasn't vanished yet.
+ // Don't remove the decor surface and divider if so as the removal should happen in
+ // a following step when the TaskFragment has vanished. This ensures that the decor
+ // surface is removed only after the resulting Activity is ready to be shown,
+ // otherwise there may be flicker.
+ if (mHasContainersToFinish) {
+ if (isTaskFragmentVanished) {
+ setHasContainersToFinish(false);
+ } else {
+ return;
+ }
+ }
removeDecorSurfaceAndDivider(wct);
return;
}
@@ -868,6 +886,12 @@
}
}
+ void setHasContainersToFinish(boolean hasContainersToFinish) {
+ synchronized (mLock) {
+ mHasContainersToFinish = hasContainersToFinish;
+ }
+ }
+
private static boolean isDraggingToFullscreenAllowed(
@NonNull DividerAttributes dividerAttributes) {
// TODO(b/293654166) Use DividerAttributes.isDraggingToFullscreenAllowed when extension is
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
index f78e2b5..d5eaedd 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
@@ -673,7 +673,7 @@
break;
case TYPE_TASK_FRAGMENT_VANISHED:
mPresenter.removeTaskFragmentInfo(info);
- onTaskFragmentVanished(wct, info);
+ onTaskFragmentVanished(wct, info, taskId);
break;
case TYPE_TASK_FRAGMENT_PARENT_INFO_CHANGED:
onTaskFragmentParentInfoChanged(wct, taskId,
@@ -834,7 +834,7 @@
@VisibleForTesting
@GuardedBy("mLock")
void onTaskFragmentVanished(@NonNull WindowContainerTransaction wct,
- @NonNull TaskFragmentInfo taskFragmentInfo) {
+ @NonNull TaskFragmentInfo taskFragmentInfo, int taskId) {
final TaskFragmentContainer container = getContainer(taskFragmentInfo.getFragmentToken());
if (container != null) {
// Cleanup if the TaskFragment vanished is not requested by the organizer.
@@ -843,6 +843,11 @@
updateContainersInTaskIfVisible(wct, container.getTaskId());
}
cleanupTaskFragment(taskFragmentInfo.getFragmentToken());
+ final TaskContainer taskContainer = getTaskContainer(taskId);
+ if (taskContainer != null) {
+ // Update the divider to clean up any decor surfaces.
+ updateDivider(wct, taskContainer, true /* isTaskFragmentVanished */);
+ }
}
/**
@@ -884,7 +889,7 @@
// The divider need to be updated even if shouldUpdateContainer is false, because the decor
// surface may change in TaskFragmentParentInfo, which requires divider update but not
// container update.
- updateDivider(wct, taskContainer);
+ updateDivider(wct, taskContainer, false /* isTaskFragmentVanished */);
// If the last direct activity of the host task is dismissed and there's an always-on-top
// overlay container in the task, the overlay container should also be dismissed.
@@ -3257,12 +3262,15 @@
}
@GuardedBy("mLock")
- void updateDivider(
- @NonNull WindowContainerTransaction wct, @NonNull TaskContainer taskContainer) {
+ void updateDivider(@NonNull WindowContainerTransaction wct,
+ @NonNull TaskContainer taskContainer, boolean isTaskFragmentVanished) {
final DividerPresenter dividerPresenter = mDividerPresenters.get(taskContainer.getTaskId());
final TaskFragmentParentInfo parentInfo = taskContainer.getTaskFragmentParentInfo();
- dividerPresenter.updateDivider(
- wct, parentInfo, taskContainer.getTopNonFinishingSplitContainer());
+ final SplitContainer topSplitContainer = taskContainer.getTopNonFinishingSplitContainer();
+ if (dividerPresenter != null) {
+ dividerPresenter.updateDivider(
+ wct, parentInfo, topSplitContainer, isTaskFragmentVanished);
+ }
}
@Override
@@ -3292,6 +3300,9 @@
final List<TaskFragmentContainer> containersToFinish = new ArrayList<>();
taskContainer.updateTopSplitContainerForDivider(
dividerPresenter, containersToFinish);
+ if (!containersToFinish.isEmpty()) {
+ dividerPresenter.setHasContainersToFinish(true);
+ }
for (final TaskFragmentContainer container : containersToFinish) {
mPresenter.cleanupContainer(wct, container, false /* shouldFinishDependent */);
}
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
index d888fa9..d0e49d8 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
@@ -374,7 +374,7 @@
updateTaskFragmentWindowingModeIfRegistered(wct, secondaryContainer, windowingMode);
updateAnimationParams(wct, primaryContainer.getTaskFragmentToken(), splitAttributes);
updateAnimationParams(wct, secondaryContainer.getTaskFragmentToken(), splitAttributes);
- mController.updateDivider(wct, taskContainer);
+ mController.updateDivider(wct, taskContainer, false /* isTaskFragmentVanished */);
}
private void setAdjacentTaskFragments(@NonNull WindowContainerTransaction wct,
@@ -757,7 +757,8 @@
void expandTaskFragment(@NonNull WindowContainerTransaction wct,
@NonNull TaskFragmentContainer container) {
super.expandTaskFragment(wct, container);
- mController.updateDivider(wct, container.getTaskContainer());
+ mController.updateDivider(
+ wct, container.getTaskContainer(), false /* isTaskFragmentVanished */);
}
static boolean shouldShowSplit(@NonNull SplitContainer splitContainer) {
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java
index 070fa5b..859bc2c 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java
@@ -17,6 +17,7 @@
package androidx.window.extensions.layout;
import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.Display.INVALID_DISPLAY;
import static androidx.window.common.CommonFoldingFeature.COMMON_STATE_FLAT;
import static androidx.window.common.CommonFoldingFeature.COMMON_STATE_HALF_OPENED;
@@ -41,6 +42,7 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.UiContext;
+import androidx.annotation.VisibleForTesting;
import androidx.window.common.CommonFoldingFeature;
import androidx.window.common.DeviceStateManagerFoldingFeatureProducer;
import androidx.window.common.EmptyLifecycleCallbacksAdapter;
@@ -138,6 +140,10 @@
throw new IllegalArgumentException("Context must be a UI Context, which should be"
+ " an Activity, WindowContext or InputMethodService");
}
+ if (context.getAssociatedDisplayId() == INVALID_DISPLAY) {
+ Log.w(TAG, "The registered Context is a UI Context but not associated with any"
+ + " display. This Context may not receive any WindowLayoutInfo update");
+ }
mFoldingFeatureProducer.getData((features) -> {
WindowLayoutInfo newWindowLayout = getWindowLayoutInfo(context, features);
consumer.accept(newWindowLayout);
@@ -257,7 +263,8 @@
}
}
- private void onDisplayFeaturesChanged(List<CommonFoldingFeature> storedFeatures) {
+ @VisibleForTesting
+ void onDisplayFeaturesChanged(List<CommonFoldingFeature> storedFeatures) {
synchronized (mLock) {
mLastReportedFoldingFeatures.clear();
mLastReportedFoldingFeatures.addAll(storedFeatures);
@@ -409,9 +416,10 @@
* @return true if the display features should be reported for the UI Context, false otherwise.
*/
private boolean shouldReportDisplayFeatures(@NonNull @UiContext Context context) {
- int displayId = context.getDisplay().getDisplayId();
+ int displayId = context.getAssociatedDisplayId();
if (displayId != DEFAULT_DISPLAY) {
- // Display features are not supported on secondary displays.
+ // Display features are not supported on secondary displays or the context is not
+ // associated with any display.
return false;
}
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/DividerPresenterTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/DividerPresenterTest.java
index 4f51815..bc18cd2 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/DividerPresenterTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/DividerPresenterTest.java
@@ -82,6 +82,7 @@
*/
@Presubmit
@SmallTest
+@SuppressWarnings("GuardedBy")
@RunWith(AndroidJUnit4.class)
public class DividerPresenterTest {
@Rule
@@ -186,7 +187,8 @@
mDividerPresenter.updateDivider(
mTransaction,
mParentInfo,
- mSplitContainer);
+ mSplitContainer,
+ false /* isTaskFragmentVanished */);
assertNotEquals(mProperties, mDividerPresenter.mProperties);
verify(mRenderer).update();
@@ -206,7 +208,8 @@
mDividerPresenter.updateDivider(
mTransaction,
mParentInfo,
- mSplitContainer);
+ mSplitContainer,
+ false /* isTaskFragmentVanished */);
assertNotEquals(mProperties, mDividerPresenter.mProperties);
verify(mRenderer).update();
@@ -222,7 +225,8 @@
mDividerPresenter.updateDivider(
mTransaction,
mParentInfo,
- mSplitContainer);
+ mSplitContainer,
+ false /* isTaskFragmentVanished */);
assertEquals(mProperties, mDividerPresenter.mProperties);
verify(mRenderer, never()).update();
@@ -234,7 +238,42 @@
mDividerPresenter.updateDivider(
mTransaction,
mParentInfo,
- null /* splitContainer */);
+ null /* splitContainer */,
+ false /* isTaskFragmentVanished */);
+ final TaskFragmentOperation taskFragmentOperation = new TaskFragmentOperation.Builder(
+ OP_TYPE_REMOVE_TASK_FRAGMENT_DECOR_SURFACE)
+ .build();
+
+ verify(mTransaction).addTaskFragmentOperation(
+ mPrimaryContainerToken, taskFragmentOperation);
+ verify(mRenderer).release();
+ assertNull(mDividerPresenter.mRenderer);
+ assertNull(mDividerPresenter.mProperties);
+ assertNull(mDividerPresenter.mDecorSurfaceOwner);
+ }
+
+ @Test
+ public void testUpdateDivider_noChangeWhenHasContainersToFinishButTaskFragmentNotVanished() {
+ mDividerPresenter.setHasContainersToFinish(true);
+ mDividerPresenter.updateDivider(
+ mTransaction,
+ mParentInfo,
+ null /* splitContainer */,
+ false /* isTaskFragmentVanished */);
+
+ assertEquals(mProperties, mDividerPresenter.mProperties);
+ verify(mRenderer, never()).update();
+ verify(mTransaction, never()).addTaskFragmentOperation(any(), any());
+ }
+
+ @Test
+ public void testUpdateDivider_dividerRemovedWhenHasContainersToFinishAndTaskFragmentVanished() {
+ mDividerPresenter.setHasContainersToFinish(true);
+ mDividerPresenter.updateDivider(
+ mTransaction,
+ mParentInfo,
+ null /* splitContainer */,
+ true /* isTaskFragmentVanished */);
final TaskFragmentOperation taskFragmentOperation = new TaskFragmentOperation.Builder(
OP_TYPE_REMOVE_TASK_FRAGMENT_DECOR_SURFACE)
.build();
@@ -254,7 +293,8 @@
mDividerPresenter.updateDivider(
mTransaction,
mParentInfo,
- mSplitContainer);
+ mSplitContainer,
+ false /* isTaskFragmentVanished */);
final TaskFragmentOperation taskFragmentOperation = new TaskFragmentOperation.Builder(
OP_TYPE_REMOVE_TASK_FRAGMENT_DECOR_SURFACE)
.build();
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java
index 640b1fc..efeec82 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java
@@ -200,12 +200,14 @@
public void testOnTaskFragmentVanished() {
final TaskFragmentContainer tf = createTfContainer(mSplitController, mActivity);
doReturn(tf.getTaskFragmentToken()).when(mInfo).getFragmentToken();
+ doReturn(createTestTaskContainer()).when(mSplitController).getTaskContainer(TASK_ID);
// The TaskFragment has been removed in the server, we only need to cleanup the reference.
- mSplitController.onTaskFragmentVanished(mTransaction, mInfo);
+ mSplitController.onTaskFragmentVanished(mTransaction, mInfo, TASK_ID);
verify(mSplitPresenter, never()).deleteTaskFragment(any(), any());
verify(mSplitController).removeContainer(tf);
+ verify(mSplitController).updateDivider(any(), any(), anyBoolean());
verify(mTransaction, never()).finishActivity(any());
}
@@ -1152,7 +1154,7 @@
.setTaskFragmentInfo(info));
mSplitController.onTransactionReady(transaction);
- verify(mSplitController).onTaskFragmentVanished(any(), eq(info));
+ verify(mSplitController).onTaskFragmentVanished(any(), eq(info), anyInt());
verify(mSplitPresenter).onTransactionHandled(eq(transaction.getTransactionToken()), any(),
anyInt(), anyBoolean());
}
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/layout/WindowLayoutComponentImplTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/layout/WindowLayoutComponentImplTest.java
new file mode 100644
index 0000000..ff0a82f
--- /dev/null
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/layout/WindowLayoutComponentImplTest.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+package androidx.window.extensions.layout;
+
+import static org.mockito.Mockito.mock;
+
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+import androidx.window.common.DeviceStateManagerFoldingFeatureProducer;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Collections;
+
+/**
+ * Test class for {@link WindowLayoutComponentImpl}.
+ *
+ * Build/Install/Run:
+ * atest WMJetpackUnitTests:WindowLayoutComponentImplTest
+ */
+@Presubmit
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class WindowLayoutComponentImplTest {
+
+ private WindowLayoutComponentImpl mWindowLayoutComponent;
+
+ @Before
+ public void setUp() {
+ mWindowLayoutComponent = new WindowLayoutComponentImpl(
+ ApplicationProvider.getApplicationContext(),
+ mock(DeviceStateManagerFoldingFeatureProducer.class));
+ }
+
+ @Test
+ public void testAddWindowLayoutListenerOnFakeUiContext_noCrash() {
+ final Context fakeUiContext = createTestContext();
+
+ mWindowLayoutComponent.addWindowLayoutInfoListener(fakeUiContext, info -> {});
+
+ mWindowLayoutComponent.onDisplayFeaturesChanged(Collections.emptyList());
+ }
+
+ private static Context createTestContext() {
+ return new FakeUiContext(ApplicationProvider.getApplicationContext());
+ }
+
+ /**
+ * A {@link android.content.Context} overrides {@link android.content.Context#isUiContext} to
+ * {@code true}.
+ */
+ private static class FakeUiContext extends ContextWrapper {
+
+ FakeUiContext(Context base) {
+ super(base);
+ }
+
+ @Override
+ public boolean isUiContext() {
+ return true;
+ }
+ }
+}
diff --git a/libs/WindowManager/Shell/aconfig/multitasking.aconfig b/libs/WindowManager/Shell/aconfig/multitasking.aconfig
index 112eb61..3b7eb29 100644
--- a/libs/WindowManager/Shell/aconfig/multitasking.aconfig
+++ b/libs/WindowManager/Shell/aconfig/multitasking.aconfig
@@ -121,3 +121,13 @@
purpose: PURPOSE_BUGFIX
}
}
+
+flag {
+ name: "enable_taskbar_on_phones"
+ namespace: "multitasking"
+ description: "Enables taskbar on phones"
+ bug: "348007377"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeEventLogger.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeEventLogger.kt
index 9192e6e..fbc11c1 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeEventLogger.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeEventLogger.kt
@@ -159,13 +159,24 @@
}
companion object {
+ /**
+ * Describes a task position and dimensions.
+ *
+ * @property instanceId instance id of the task
+ * @property uid uid of the app associated with the task
+ * @property taskHeight height of the task in px
+ * @property taskWidth width of the task in px
+ * @property taskX x-coordinate of the top-left corner
+ * @property taskY y-coordinate of the top-left corner
+ *
+ */
data class TaskUpdate(
val instanceId: Int,
val uid: Int,
- val taskHeight: Int = Int.MIN_VALUE,
- val taskWidth: Int = Int.MIN_VALUE,
- val taskX: Int = Int.MIN_VALUE,
- val taskY: Int = Int.MIN_VALUE,
+ val taskHeight: Int,
+ val taskWidth: Int,
+ val taskX: Int,
+ val taskY: Int,
)
/**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeLoggerTransitionObserver.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeLoggerTransitionObserver.kt
index 641952b..e710560 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeLoggerTransitionObserver.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeLoggerTransitionObserver.kt
@@ -282,17 +282,23 @@
visibleFreeformTaskInfos.putAll(postTransitionVisibleFreeformTasks)
}
- // TODO(b/326231724) - Add logging around taskInfoChanges Updates
/** Compare the old and new state of taskInfos and identify and log the changes */
private fun identifyAndLogTaskUpdates(
sessionId: Int,
preTransitionVisibleFreeformTasks: SparseArray<TaskInfo>,
postTransitionVisibleFreeformTasks: SparseArray<TaskInfo>
) {
- // find new tasks that were added
postTransitionVisibleFreeformTasks.forEach { taskId, taskInfo ->
- if (!preTransitionVisibleFreeformTasks.containsKey(taskId)) {
- desktopModeEventLogger.logTaskAdded(sessionId, buildTaskUpdateForTask(taskInfo))
+ val currentTaskUpdate = buildTaskUpdateForTask(taskInfo)
+ val previousTaskInfo = preTransitionVisibleFreeformTasks[taskId]
+ when {
+ // new tasks added
+ previousTaskInfo == null ->
+ desktopModeEventLogger.logTaskAdded(sessionId, currentTaskUpdate)
+ // old tasks that were resized or repositioned
+ // TODO(b/347935387): Log changes only once they are stable.
+ buildTaskUpdateForTask(previousTaskInfo) != currentTaskUpdate ->
+ desktopModeEventLogger.logTaskInfoChanged(sessionId, currentTaskUpdate)
}
}
@@ -304,13 +310,17 @@
}
}
- // TODO(b/326231724: figure out how to get taskWidth and taskHeight from TaskInfo
private fun buildTaskUpdateForTask(taskInfo: TaskInfo): TaskUpdate {
- val taskUpdate = TaskUpdate(taskInfo.taskId, taskInfo.userId)
- // add task x, y if available
- taskInfo.positionInParent?.let { taskUpdate.copy(taskX = it.x, taskY = it.y) }
-
- return taskUpdate
+ val screenBounds = taskInfo.configuration.windowConfiguration.bounds
+ val positionInParent = taskInfo.positionInParent
+ return TaskUpdate(
+ instanceId = taskInfo.taskId,
+ uid = taskInfo.userId,
+ taskHeight = screenBounds.height(),
+ taskWidth = screenBounds.width(),
+ taskX = positionInParent.x,
+ taskY = positionInParent.y,
+ )
}
/** Get [EnterReason] for this session enter */
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeTaskRepository.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeTaskRepository.kt
index 7d01580..9bf244e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeTaskRepository.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeTaskRepository.kt
@@ -46,6 +46,9 @@
val activeTasks: ArraySet<Int> = ArraySet(),
val visibleTasks: ArraySet<Int> = ArraySet(),
val minimizedTasks: ArraySet<Int> = ArraySet(),
+ // Tasks that are closing, but are still visible
+ // TODO(b/332682201): Remove when the repository state is updated via TransitionObserver
+ val closingTasks: ArraySet<Int> = ArraySet(),
// Tasks currently in freeform mode, ordered from top to bottom (top is at index 0).
val freeformTasksInZOrder: ArrayList<Int> = ArrayList(),
)
@@ -169,6 +172,42 @@
return result
}
+ /**
+ * Mark a task with given [taskId] as closing on given [displayId]
+ *
+ * @return `true` if the task was not closing on given [displayId]
+ */
+ fun addClosingTask(displayId: Int, taskId: Int): Boolean {
+ val added = displayData.getOrCreate(displayId).closingTasks.add(taskId)
+ if (added) {
+ KtProtoLog.d(
+ WM_SHELL_DESKTOP_MODE,
+ "DesktopTaskRepo: added closing task=%d displayId=%d",
+ taskId,
+ displayId
+ )
+ }
+ return added
+ }
+
+ /**
+ * Remove task with given [taskId] from closing tasks.
+ *
+ * @return `true` if the task was closing
+ */
+ fun removeClosingTask(taskId: Int): Boolean {
+ var removed = false
+ displayData.forEach { _, data ->
+ if (data.closingTasks.remove(taskId)) {
+ removed = true
+ }
+ }
+ if (removed) {
+ KtProtoLog.d(WM_SHELL_DESKTOP_MODE, "DesktopTaskRepo: remove closing task=%d", taskId)
+ }
+ return removed
+ }
+
/** Check if a task with the given [taskId] was marked as an active task */
fun isActiveTask(taskId: Int): Boolean {
return displayData.valueIterator().asSequence().any { data ->
@@ -176,6 +215,10 @@
}
}
+ /** Check if a task with the given [taskId] was marked as a closing task */
+ fun isClosingTask(taskId: Int): Boolean =
+ displayData.valueIterator().asSequence().any { data -> taskId in data.closingTasks }
+
/** Whether a task is visible. */
fun isVisibleTask(taskId: Int): Boolean {
return displayData.valueIterator().asSequence().any { data ->
@@ -190,10 +233,16 @@
}
}
- /** Check if a task with the given [taskId] is the only active task on its display */
- fun isOnlyActiveTask(taskId: Int): Boolean {
+ /**
+ * Check if a task with the given [taskId] is the only active, non-closing, not-minimized task
+ * on its display
+ */
+ fun isOnlyActiveNonClosingTask(taskId: Int): Boolean {
return displayData.valueIterator().asSequence().any { data ->
- data.activeTasks.singleOrNull() == taskId
+ data.activeTasks
+ .subtract(data.closingTasks)
+ .subtract(data.minimizedTasks)
+ .singleOrNull() == taskId
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
index c5111d6..d28cda3 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
@@ -442,12 +442,21 @@
* active task.
*
* @param wct transaction to modify if the last active task is closed
+ * @param displayId display id of the window that's being closed
* @param taskId task id of the window that's being closed
*/
- fun onDesktopWindowClose(wct: WindowContainerTransaction, taskId: Int) {
- if (desktopModeTaskRepository.isOnlyActiveTask(taskId)) {
+ fun onDesktopWindowClose(wct: WindowContainerTransaction, displayId: Int, taskId: Int) {
+ if (desktopModeTaskRepository.isOnlyActiveNonClosingTask(taskId)) {
removeWallpaperActivity(wct)
}
+ if (!desktopModeTaskRepository.addClosingTask(displayId, taskId)) {
+ // Could happen if the task hasn't been removed from closing list after it disappeared
+ KtProtoLog.w(
+ WM_SHELL_DESKTOP_MODE,
+ "DesktopTasksController: the task with taskId=%d is already closing!",
+ taskId
+ )
+ }
}
/** Move a task with given `taskId` to fullscreen */
@@ -871,7 +880,7 @@
false
}
// Handle back navigation for the last window if wallpaper available
- shouldRemoveWallpaper(request) -> true
+ shouldHandleBackNavigation(request) -> true
// Only handle open or to front transitions
request.type != TRANSIT_OPEN && request.type != TRANSIT_TO_FRONT -> {
reason = "transition type not handled (${request.type})"
@@ -951,13 +960,9 @@
private fun shouldLaunchAsModal(task: TaskInfo) =
Flags.enableDesktopWindowingModalsPolicy() && isSingleTopActivityTranslucent(task)
- private fun shouldRemoveWallpaper(request: TransitionRequestInfo): Boolean {
+ private fun shouldHandleBackNavigation(request: TransitionRequestInfo): Boolean {
return Flags.enableDesktopWindowingWallpaperActivity() &&
- request.type == TRANSIT_TO_BACK &&
- request.triggerTask?.let { task ->
- desktopModeTaskRepository.isOnlyActiveTask(task.taskId)
- }
- ?: false
+ request.type == TRANSIT_TO_BACK
}
private fun handleFreeformTaskLaunch(
@@ -1026,15 +1031,24 @@
/** Handle back navigation by removing wallpaper activity if it's the last active task */
private fun handleBackNavigation(task: RunningTaskInfo): WindowContainerTransaction? {
- if (
- desktopModeTaskRepository.isOnlyActiveTask(task.taskId) &&
+ val wct = if (
+ desktopModeTaskRepository.isOnlyActiveNonClosingTask(task.taskId) &&
desktopModeTaskRepository.wallpaperActivityToken != null
) {
// Remove wallpaper activity when the last active task is removed
- return WindowContainerTransaction().also { wct -> removeWallpaperActivity(wct) }
+ WindowContainerTransaction().also { wct -> removeWallpaperActivity(wct) }
} else {
- return null
+ null
}
+ if (!desktopModeTaskRepository.addClosingTask(task.displayId, task.taskId)) {
+ // Could happen if the task hasn't been removed from closing list after it disappeared
+ KtProtoLog.w(
+ WM_SHELL_DESKTOP_MODE,
+ "DesktopTasksController: the task with taskId=%d is already closing!",
+ task.taskId
+ )
+ }
+ return wct
}
private fun addMoveToDesktopChanges(
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java
index 7d2aa27..b88afb9 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java
@@ -122,6 +122,10 @@
mDesktopModeTaskRepository.ifPresent(repository -> {
repository.removeFreeformTask(taskInfo.displayId, taskInfo.taskId);
repository.unminimizeTask(taskInfo.displayId, taskInfo.taskId);
+ if (repository.removeClosingTask(taskInfo.taskId)) {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE,
+ "Removing closing freeform task: #%d", taskInfo.taskId);
+ }
if (repository.removeActiveTask(taskInfo.taskId)) {
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE,
"Removing active freeform task: #%d", taskInfo.taskId);
@@ -150,6 +154,10 @@
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE,
"Adding active freeform task: #%d", taskInfo.taskId);
}
+ } else if (repository.isClosingTask(taskInfo.taskId)
+ && repository.removeClosingTask(taskInfo.taskId)) {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE,
+ "Removing closing freeform task: #%d", taskInfo.taskId);
}
repository.updateVisibleFreeformTasks(taskInfo.displayId, taskInfo.taskId,
taskInfo.isVisible);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
index e4420d7..82add29 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
@@ -608,6 +608,7 @@
public void exitPip(int animationDurationMs, boolean requestEnterSplit) {
if (!mPipTransitionState.isInPip()
|| mPipTransitionState.getTransitionState() == PipTransitionState.EXITING_PIP
+ || mPipTransitionState.getInSwipePipToHomeTransition()
|| mToken == null) {
ProtoLog.wtf(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
"%s: Not allowed to exitPip in current state"
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
index 21b6db2..5e7e5e6 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
@@ -435,7 +435,7 @@
SplitScreenController.EXIT_REASON_DESKTOP_MODE);
} else {
WindowContainerTransaction wct = new WindowContainerTransaction();
- mDesktopTasksController.onDesktopWindowClose(wct, mTaskId);
+ mDesktopTasksController.onDesktopWindowClose(wct, mDisplayId, mTaskId);
mTaskOperations.closeTask(mTaskToken, wct);
}
} else if (id == R.id.back_button) {
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeLoggerTransitionObserverTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeLoggerTransitionObserverTest.kt
index fb03f20..665bed0 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeLoggerTransitionObserverTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeLoggerTransitionObserverTest.kt
@@ -19,6 +19,8 @@
import android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM
import android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN
import android.content.Context
+import android.graphics.Point
+import android.graphics.Rect
import android.os.IBinder
import android.testing.AndroidTestingRunner
import android.view.SurfaceControl
@@ -36,11 +38,12 @@
import android.window.TransitionInfo.Change
import android.window.WindowContainerToken
import androidx.test.filters.SmallTest
-import com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn
import com.android.modules.utils.testing.ExtendedMockitoRule
+import com.android.wm.shell.ShellTestCase
import com.android.wm.shell.common.ShellExecutor
import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.EnterReason
import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.ExitReason
+import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.TaskUpdate
import com.android.wm.shell.desktopmode.DesktopModeTransitionTypes.TRANSIT_ENTER_DESKTOP_FROM_APP_FROM_OVERVIEW
import com.android.wm.shell.desktopmode.DesktopModeTransitionTypes.TRANSIT_ENTER_DESKTOP_FROM_APP_HANDLE_MENU_BUTTON
import com.android.wm.shell.desktopmode.DesktopModeTransitionTypes.TRANSIT_ENTER_DESKTOP_FROM_KEYBOARD_SHORTCUT
@@ -53,22 +56,23 @@
import com.android.wm.shell.sysui.ShellInit
import com.android.wm.shell.transition.TransitionInfoBuilder
import com.android.wm.shell.transition.Transitions
-import com.google.common.truth.Truth.assertThat
+import junit.framework.Assert.assertNotNull
+import junit.framework.Assert.assertNull
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor
-import org.mockito.Mock
-import org.mockito.Mockito
-import org.mockito.Mockito.mock
-import org.mockito.Mockito.verify
import org.mockito.kotlin.any
import org.mockito.kotlin.eq
+import org.mockito.kotlin.mock
import org.mockito.kotlin.never
import org.mockito.kotlin.same
+import org.mockito.kotlin.spy
import org.mockito.kotlin.times
+import org.mockito.kotlin.verify
import org.mockito.kotlin.verifyZeroInteractions
+import org.mockito.kotlin.whenever
/**
* Test class for {@link DesktopModeLoggerTransitionObserver}
@@ -77,20 +81,17 @@
*/
@SmallTest
@RunWith(AndroidTestingRunner::class)
-class DesktopModeLoggerTransitionObserverTest {
+class DesktopModeLoggerTransitionObserverTest : ShellTestCase() {
@JvmField
@Rule
val extendedMockitoRule =
- ExtendedMockitoRule.Builder(this)
- .mockStatic(DesktopModeEventLogger::class.java)
- .mockStatic(DesktopModeStatus::class.java)
- .build()!!
+ ExtendedMockitoRule.Builder(this).mockStatic(DesktopModeStatus::class.java).build()!!
- @Mock lateinit var testExecutor: ShellExecutor
- @Mock private lateinit var mockShellInit: ShellInit
- @Mock private lateinit var transitions: Transitions
- @Mock private lateinit var context: Context
+ private val testExecutor = mock<ShellExecutor>()
+ private val mockShellInit = mock<ShellInit>()
+ private val transitions = mock<Transitions>()
+ private val context = mock<Context>()
private lateinit var transitionObserver: DesktopModeLoggerTransitionObserver
private lateinit var shellInit: ShellInit
@@ -98,9 +99,9 @@
@Before
fun setup() {
- doReturn(true).`when` { DesktopModeStatus.canEnterDesktopMode(any()) }
- shellInit = Mockito.spy(ShellInit(testExecutor))
- desktopModeEventLogger = mock(DesktopModeEventLogger::class.java)
+ whenever(DesktopModeStatus.canEnterDesktopMode(any())).thenReturn(true)
+ shellInit = spy(ShellInit(testExecutor))
+ desktopModeEventLogger = mock<DesktopModeEventLogger>()
transitionObserver =
DesktopModeLoggerTransitionObserver(
@@ -121,7 +122,7 @@
@Test
fun transitOpen_notFreeformWindow_doesNotLogTaskAddedOrSessionEnter() {
- val change = createChange(TRANSIT_OPEN, createTaskInfo(1, WINDOWING_MODE_FULLSCREEN))
+ val change = createChange(TRANSIT_OPEN, createTaskInfo(WINDOWING_MODE_FULLSCREEN))
val transitionInfo = TransitionInfoBuilder(TRANSIT_OPEN, 0).addChange(change).build()
callOnTransitionReady(transitionInfo)
@@ -132,22 +133,17 @@
@Test
fun transitOpen_logTaskAddedAndEnterReasonAppFreeformIntent() {
- val change = createChange(TRANSIT_OPEN, createTaskInfo(1, WINDOWING_MODE_FREEFORM))
+ val change = createChange(TRANSIT_OPEN, createTaskInfo(WINDOWING_MODE_FREEFORM))
val transitionInfo = TransitionInfoBuilder(TRANSIT_OPEN, 0).addChange(change).build()
callOnTransitionReady(transitionInfo)
- val sessionId = transitionObserver.getLoggerSessionId()
- assertThat(sessionId).isNotNull()
- verify(desktopModeEventLogger, times(1))
- .logSessionEnter(eq(sessionId!!), eq(EnterReason.APP_FREEFORM_INTENT))
- verify(desktopModeEventLogger, times(1)).logTaskAdded(eq(sessionId), any())
- verifyZeroInteractions(desktopModeEventLogger)
+ verifyTaskAddedAndEnterLogging(EnterReason.APP_FREEFORM_INTENT, DEFAULT_TASK_UPDATE)
}
@Test
fun transitEndDragToDesktop_logTaskAddedAndEnterReasonAppHandleDrag() {
- val change = createChange(TRANSIT_TO_FRONT, createTaskInfo(1, WINDOWING_MODE_FREEFORM))
+ val change = createChange(TRANSIT_TO_FRONT, createTaskInfo(WINDOWING_MODE_FREEFORM))
// task change is finalised when drag ends
val transitionInfo =
TransitionInfoBuilder(Transitions.TRANSIT_DESKTOP_MODE_END_DRAG_TO_DESKTOP, 0)
@@ -155,82 +151,57 @@
.build()
callOnTransitionReady(transitionInfo)
- val sessionId = transitionObserver.getLoggerSessionId()
- assertThat(sessionId).isNotNull()
- verify(desktopModeEventLogger, times(1))
- .logSessionEnter(eq(sessionId!!), eq(EnterReason.APP_HANDLE_DRAG))
- verify(desktopModeEventLogger, times(1)).logTaskAdded(eq(sessionId), any())
- verifyZeroInteractions(desktopModeEventLogger)
+ verifyTaskAddedAndEnterLogging(EnterReason.APP_HANDLE_DRAG, DEFAULT_TASK_UPDATE)
}
@Test
fun transitEnterDesktopByButtonTap_logTaskAddedAndEnterReasonButtonTap() {
- val change = createChange(TRANSIT_TO_FRONT, createTaskInfo(1, WINDOWING_MODE_FREEFORM))
+ val change = createChange(TRANSIT_TO_FRONT, createTaskInfo(WINDOWING_MODE_FREEFORM))
val transitionInfo =
TransitionInfoBuilder(TRANSIT_ENTER_DESKTOP_FROM_APP_HANDLE_MENU_BUTTON, 0)
.addChange(change)
.build()
callOnTransitionReady(transitionInfo)
- val sessionId = transitionObserver.getLoggerSessionId()
- assertThat(sessionId).isNotNull()
- verify(desktopModeEventLogger, times(1))
- .logSessionEnter(eq(sessionId!!), eq(EnterReason.APP_HANDLE_MENU_BUTTON))
- verify(desktopModeEventLogger, times(1)).logTaskAdded(eq(sessionId), any())
- verifyZeroInteractions(desktopModeEventLogger)
+ verifyTaskAddedAndEnterLogging(EnterReason.APP_HANDLE_MENU_BUTTON, DEFAULT_TASK_UPDATE)
}
@Test
fun transitEnterDesktopFromAppFromOverview_logTaskAddedAndEnterReasonAppFromOverview() {
- val change = createChange(TRANSIT_TO_FRONT, createTaskInfo(1, WINDOWING_MODE_FREEFORM))
+ val change = createChange(TRANSIT_TO_FRONT, createTaskInfo(WINDOWING_MODE_FREEFORM))
val transitionInfo =
TransitionInfoBuilder(TRANSIT_ENTER_DESKTOP_FROM_APP_FROM_OVERVIEW, 0)
.addChange(change)
.build()
callOnTransitionReady(transitionInfo)
- val sessionId = transitionObserver.getLoggerSessionId()
- assertThat(sessionId).isNotNull()
- verify(desktopModeEventLogger, times(1))
- .logSessionEnter(eq(sessionId!!), eq(EnterReason.APP_FROM_OVERVIEW))
- verify(desktopModeEventLogger, times(1)).logTaskAdded(eq(sessionId), any())
- verifyZeroInteractions(desktopModeEventLogger)
+ verifyTaskAddedAndEnterLogging(EnterReason.APP_FROM_OVERVIEW, DEFAULT_TASK_UPDATE)
}
@Test
fun transitEnterDesktopFromKeyboardShortcut_logTaskAddedAndEnterReasonKeyboardShortcut() {
- val change = createChange(TRANSIT_TO_FRONT, createTaskInfo(1, WINDOWING_MODE_FREEFORM))
+ val change = createChange(TRANSIT_TO_FRONT, createTaskInfo(WINDOWING_MODE_FREEFORM))
val transitionInfo =
TransitionInfoBuilder(TRANSIT_ENTER_DESKTOP_FROM_KEYBOARD_SHORTCUT, 0)
.addChange(change)
.build()
callOnTransitionReady(transitionInfo)
- val sessionId = transitionObserver.getLoggerSessionId()
- assertThat(sessionId).isNotNull()
- verify(desktopModeEventLogger, times(1))
- .logSessionEnter(eq(sessionId!!), eq(EnterReason.KEYBOARD_SHORTCUT_ENTER))
- verify(desktopModeEventLogger, times(1)).logTaskAdded(eq(sessionId), any())
- verifyZeroInteractions(desktopModeEventLogger)
+ verifyTaskAddedAndEnterLogging(EnterReason.KEYBOARD_SHORTCUT_ENTER, DEFAULT_TASK_UPDATE)
}
@Test
fun transitToFront_logTaskAddedAndEnterReasonOverview() {
- val change = createChange(TRANSIT_TO_FRONT, createTaskInfo(1, WINDOWING_MODE_FREEFORM))
+ val change = createChange(TRANSIT_TO_FRONT, createTaskInfo(WINDOWING_MODE_FREEFORM))
val transitionInfo = TransitionInfoBuilder(TRANSIT_TO_FRONT, 0).addChange(change).build()
callOnTransitionReady(transitionInfo)
- val sessionId = transitionObserver.getLoggerSessionId()
- assertThat(sessionId).isNotNull()
- verify(desktopModeEventLogger, times(1))
- .logSessionEnter(eq(sessionId!!), eq(EnterReason.OVERVIEW))
- verify(desktopModeEventLogger, times(1)).logTaskAdded(eq(sessionId), any())
- verifyZeroInteractions(desktopModeEventLogger)
+ verifyTaskAddedAndEnterLogging(EnterReason.OVERVIEW, DEFAULT_TASK_UPDATE)
}
@Test
@@ -238,35 +209,29 @@
// previous exit to overview transition
val previousSessionId = 1
// add a freeform task
- transitionObserver.addTaskInfosToCachedMap(createTaskInfo(1, WINDOWING_MODE_FREEFORM))
+ val previousTaskInfo = createTaskInfo(WINDOWING_MODE_FREEFORM)
+ transitionObserver.addTaskInfosToCachedMap(previousTaskInfo)
transitionObserver.setLoggerSessionId(previousSessionId)
- val previousChange = createChange(TRANSIT_TO_BACK, createTaskInfo(1, WINDOWING_MODE_FREEFORM))
val previousTransitionInfo =
TransitionInfoBuilder(TRANSIT_TO_FRONT, TRANSIT_FLAG_IS_RECENTS)
- .addChange(previousChange)
+ .addChange(createChange(TRANSIT_TO_BACK, previousTaskInfo))
.build()
callOnTransitionReady(previousTransitionInfo)
- verify(desktopModeEventLogger, times(1)).logTaskRemoved(eq(previousSessionId), any())
- verify(desktopModeEventLogger, times(1))
- .logSessionExit(eq(previousSessionId), eq(ExitReason.RETURN_HOME_OR_OVERVIEW))
+ verifyTaskRemovedAndExitLogging(
+ previousSessionId, ExitReason.RETURN_HOME_OR_OVERVIEW, DEFAULT_TASK_UPDATE)
// Enter desktop mode from cancelled recents has no transition. Enter is detected on the
// next transition involving freeform windows
// TRANSIT_TO_FRONT
- val change = createChange(TRANSIT_TO_FRONT, createTaskInfo(1, WINDOWING_MODE_FREEFORM))
+ val change = createChange(TRANSIT_TO_FRONT, createTaskInfo(WINDOWING_MODE_FREEFORM))
val transitionInfo = TransitionInfoBuilder(TRANSIT_TO_FRONT, 0).addChange(change).build()
callOnTransitionReady(transitionInfo)
- val sessionId = transitionObserver.getLoggerSessionId()
- assertThat(sessionId).isNotNull()
- verify(desktopModeEventLogger, times(1))
- .logSessionEnter(eq(sessionId!!), eq(EnterReason.OVERVIEW))
- verify(desktopModeEventLogger, times(1)).logTaskAdded(eq(sessionId), any())
- verifyZeroInteractions(desktopModeEventLogger)
+ verifyTaskAddedAndEnterLogging(EnterReason.OVERVIEW, DEFAULT_TASK_UPDATE)
}
@Test
@@ -274,35 +239,29 @@
// previous exit to overview transition
val previousSessionId = 1
// add a freeform task
- transitionObserver.addTaskInfosToCachedMap(createTaskInfo(1, WINDOWING_MODE_FREEFORM))
+ val previousTaskInfo = createTaskInfo(WINDOWING_MODE_FREEFORM)
+ transitionObserver.addTaskInfosToCachedMap(previousTaskInfo)
transitionObserver.setLoggerSessionId(previousSessionId)
- val previousChange = createChange(TRANSIT_TO_BACK, createTaskInfo(1, WINDOWING_MODE_FREEFORM))
val previousTransitionInfo =
TransitionInfoBuilder(TRANSIT_TO_FRONT, TRANSIT_FLAG_IS_RECENTS)
- .addChange(previousChange)
+ .addChange(createChange(TRANSIT_TO_BACK, previousTaskInfo))
.build()
callOnTransitionReady(previousTransitionInfo)
- verify(desktopModeEventLogger, times(1)).logTaskRemoved(eq(previousSessionId), any())
- verify(desktopModeEventLogger, times(1))
- .logSessionExit(eq(previousSessionId), eq(ExitReason.RETURN_HOME_OR_OVERVIEW))
+ verifyTaskRemovedAndExitLogging(
+ previousSessionId, ExitReason.RETURN_HOME_OR_OVERVIEW, DEFAULT_TASK_UPDATE)
// Enter desktop mode from cancelled recents has no transition. Enter is detected on the
// next transition involving freeform windows
// TRANSIT_CHANGE
- val change = createChange(TRANSIT_TO_FRONT, createTaskInfo(1, WINDOWING_MODE_FREEFORM))
+ val change = createChange(TRANSIT_TO_FRONT, createTaskInfo(WINDOWING_MODE_FREEFORM))
val transitionInfo = TransitionInfoBuilder(TRANSIT_CHANGE, 0).addChange(change).build()
callOnTransitionReady(transitionInfo)
- val sessionId = transitionObserver.getLoggerSessionId()
- assertThat(sessionId).isNotNull()
- verify(desktopModeEventLogger, times(1))
- .logSessionEnter(eq(sessionId!!), eq(EnterReason.OVERVIEW))
- verify(desktopModeEventLogger, times(1)).logTaskAdded(eq(sessionId), any())
- verifyZeroInteractions(desktopModeEventLogger)
+ verifyTaskAddedAndEnterLogging(EnterReason.OVERVIEW, DEFAULT_TASK_UPDATE)
}
@Test
@@ -310,35 +269,29 @@
// previous exit to overview transition
val previousSessionId = 1
// add a freeform task
- transitionObserver.addTaskInfosToCachedMap(createTaskInfo(1, WINDOWING_MODE_FREEFORM))
+ val previousTaskInfo = createTaskInfo(WINDOWING_MODE_FREEFORM)
+ transitionObserver.addTaskInfosToCachedMap(previousTaskInfo)
transitionObserver.setLoggerSessionId(previousSessionId)
- val previousChange = createChange(TRANSIT_TO_BACK, createTaskInfo(1, WINDOWING_MODE_FREEFORM))
val previousTransitionInfo =
TransitionInfoBuilder(TRANSIT_TO_FRONT, TRANSIT_FLAG_IS_RECENTS)
- .addChange(previousChange)
+ .addChange(createChange(TRANSIT_TO_BACK, previousTaskInfo))
.build()
callOnTransitionReady(previousTransitionInfo)
- verify(desktopModeEventLogger, times(1)).logTaskRemoved(eq(previousSessionId), any())
- verify(desktopModeEventLogger, times(1))
- .logSessionExit(eq(previousSessionId), eq(ExitReason.RETURN_HOME_OR_OVERVIEW))
+ verifyTaskRemovedAndExitLogging(
+ previousSessionId, ExitReason.RETURN_HOME_OR_OVERVIEW, DEFAULT_TASK_UPDATE)
// Enter desktop mode from cancelled recents has no transition. Enter is detected on the
// next transition involving freeform windows
// TRANSIT_OPEN
- val change = createChange(TRANSIT_TO_FRONT, createTaskInfo(1, WINDOWING_MODE_FREEFORM))
+ val change = createChange(TRANSIT_TO_FRONT, createTaskInfo(WINDOWING_MODE_FREEFORM))
val transitionInfo = TransitionInfoBuilder(TRANSIT_OPEN, 0).addChange(change).build()
callOnTransitionReady(transitionInfo)
- val sessionId = transitionObserver.getLoggerSessionId()
- assertThat(sessionId).isNotNull()
- verify(desktopModeEventLogger, times(1))
- .logSessionEnter(eq(sessionId!!), eq(EnterReason.OVERVIEW))
- verify(desktopModeEventLogger, times(1)).logTaskAdded(eq(sessionId), any())
- verifyZeroInteractions(desktopModeEventLogger)
+ verifyTaskAddedAndEnterLogging(EnterReason.OVERVIEW, DEFAULT_TASK_UPDATE)
}
@Test
@@ -349,286 +302,389 @@
// previous exit to overview transition
val previousSessionId = 1
// add a freeform task
- transitionObserver.addTaskInfosToCachedMap(createTaskInfo(1, WINDOWING_MODE_FREEFORM))
+ val previousTaskInfo = createTaskInfo(WINDOWING_MODE_FREEFORM)
+ transitionObserver.addTaskInfosToCachedMap(previousTaskInfo)
transitionObserver.setLoggerSessionId(previousSessionId)
- val previousChange = createChange(TRANSIT_TO_BACK, createTaskInfo(1, WINDOWING_MODE_FREEFORM))
val previousTransitionInfo =
- TransitionInfoBuilder(TRANSIT_TO_FRONT, TRANSIT_FLAG_IS_RECENTS)
- .addChange(previousChange)
- .build()
+ TransitionInfoBuilder(TRANSIT_TO_FRONT, TRANSIT_FLAG_IS_RECENTS)
+ .addChange(createChange(TRANSIT_TO_BACK, previousTaskInfo))
+ .build()
callOnTransitionReady(previousTransitionInfo)
- verify(desktopModeEventLogger, times(1)).logTaskRemoved(eq(previousSessionId), any())
- verify(desktopModeEventLogger, times(1))
- .logSessionExit(eq(previousSessionId), eq(ExitReason.RETURN_HOME_OR_OVERVIEW))
+ verifyTaskRemovedAndExitLogging(
+ previousSessionId, ExitReason.RETURN_HOME_OR_OVERVIEW, DEFAULT_TASK_UPDATE)
// TRANSIT_ENTER_DESKTOP_FROM_APP_FROM_OVERVIEW
- val change = createChange(TRANSIT_TO_FRONT, createTaskInfo(1, WINDOWING_MODE_FREEFORM))
+ val change = createChange(TRANSIT_TO_FRONT, createTaskInfo(WINDOWING_MODE_FREEFORM))
val transitionInfo =
- TransitionInfoBuilder(TRANSIT_ENTER_DESKTOP_FROM_APP_FROM_OVERVIEW, 0)
- .addChange(change)
- .build()
+ TransitionInfoBuilder(TRANSIT_ENTER_DESKTOP_FROM_APP_FROM_OVERVIEW, 0)
+ .addChange(change)
+ .build()
callOnTransitionReady(transitionInfo)
- val sessionId = transitionObserver.getLoggerSessionId()
- assertThat(sessionId).isNotNull()
- verify(desktopModeEventLogger, times(1))
- .logSessionEnter(eq(sessionId!!), eq(EnterReason.APP_FROM_OVERVIEW))
- verify(desktopModeEventLogger, times(1)).logTaskAdded(eq(sessionId), any())
- verifyZeroInteractions(desktopModeEventLogger)
+ verifyTaskAddedAndEnterLogging(EnterReason.APP_FROM_OVERVIEW, DEFAULT_TASK_UPDATE)
}
@Test
fun transitEnterDesktopFromUnknown_logTaskAddedAndEnterReasonUnknown() {
- val change = createChange(TRANSIT_TO_FRONT, createTaskInfo(1, WINDOWING_MODE_FREEFORM))
+ val change = createChange(TRANSIT_TO_FRONT, createTaskInfo(WINDOWING_MODE_FREEFORM))
val transitionInfo =
TransitionInfoBuilder(TRANSIT_ENTER_DESKTOP_FROM_UNKNOWN, 0).addChange(change).build()
callOnTransitionReady(transitionInfo)
- val sessionId = transitionObserver.getLoggerSessionId()
- assertThat(sessionId).isNotNull()
- verify(desktopModeEventLogger, times(1))
- .logSessionEnter(eq(sessionId!!), eq(EnterReason.UNKNOWN_ENTER))
- verify(desktopModeEventLogger, times(1)).logTaskAdded(eq(sessionId), any())
- verifyZeroInteractions(desktopModeEventLogger)
+ verifyTaskAddedAndEnterLogging(EnterReason.UNKNOWN_ENTER, DEFAULT_TASK_UPDATE)
}
@Test
fun transitWake_logTaskAddedAndEnterReasonScreenOn() {
- val change = createChange(TRANSIT_TO_FRONT, createTaskInfo(1, WINDOWING_MODE_FREEFORM))
+ val change = createChange(TRANSIT_TO_FRONT, createTaskInfo(WINDOWING_MODE_FREEFORM))
val transitionInfo = TransitionInfoBuilder(TRANSIT_WAKE, 0).addChange(change).build()
callOnTransitionReady(transitionInfo)
- val sessionId = transitionObserver.getLoggerSessionId()
- assertThat(sessionId).isNotNull()
- verify(desktopModeEventLogger, times(1))
- .logSessionEnter(eq(sessionId!!), eq(EnterReason.SCREEN_ON))
- verify(desktopModeEventLogger, times(1)).logTaskAdded(eq(sessionId), any())
- verifyZeroInteractions(desktopModeEventLogger)
+ verifyTaskAddedAndEnterLogging(EnterReason.SCREEN_ON, DEFAULT_TASK_UPDATE)
}
@Test
- fun transitSleep_logTaskAddedAndExitReasonScreenOff_sessionIdNull() {
+ fun transitSleep_logTaskRemovedAndExitReasonScreenOff_sessionIdNull() {
val sessionId = 1
// add a freeform task
- transitionObserver.addTaskInfosToCachedMap(createTaskInfo(1, WINDOWING_MODE_FREEFORM))
+ transitionObserver.addTaskInfosToCachedMap(createTaskInfo(WINDOWING_MODE_FREEFORM))
transitionObserver.setLoggerSessionId(sessionId)
val transitionInfo = TransitionInfoBuilder(TRANSIT_SLEEP).build()
callOnTransitionReady(transitionInfo)
- verify(desktopModeEventLogger, times(1)).logTaskRemoved(eq(sessionId), any())
- verify(desktopModeEventLogger, times(1))
- .logSessionExit(eq(sessionId), eq(ExitReason.SCREEN_OFF))
- verifyZeroInteractions(desktopModeEventLogger)
- assertThat(transitionObserver.getLoggerSessionId()).isNull()
+ verifyTaskRemovedAndExitLogging(sessionId, ExitReason.SCREEN_OFF, DEFAULT_TASK_UPDATE)
}
@Test
fun transitExitDesktopTaskDrag_logTaskRemovedAndExitReasonDragToExit_sessionIdNull() {
val sessionId = 1
// add a freeform task
- transitionObserver.addTaskInfosToCachedMap(createTaskInfo(1, WINDOWING_MODE_FREEFORM))
+ transitionObserver.addTaskInfosToCachedMap(createTaskInfo(WINDOWING_MODE_FREEFORM))
transitionObserver.setLoggerSessionId(sessionId)
// window mode changing from FREEFORM to FULLSCREEN
- val change = createChange(TRANSIT_TO_FRONT, createTaskInfo(1, WINDOWING_MODE_FULLSCREEN))
+ val change = createChange(TRANSIT_TO_FRONT, createTaskInfo(WINDOWING_MODE_FULLSCREEN))
val transitionInfo =
TransitionInfoBuilder(TRANSIT_EXIT_DESKTOP_MODE_TASK_DRAG).addChange(change).build()
callOnTransitionReady(transitionInfo)
- verify(desktopModeEventLogger, times(1)).logTaskRemoved(eq(sessionId), any())
- verify(desktopModeEventLogger, times(1))
- .logSessionExit(eq(sessionId), eq(ExitReason.DRAG_TO_EXIT))
- verifyZeroInteractions(desktopModeEventLogger)
- assertThat(transitionObserver.getLoggerSessionId()).isNull()
+ verifyTaskRemovedAndExitLogging(sessionId, ExitReason.DRAG_TO_EXIT, DEFAULT_TASK_UPDATE)
}
@Test
fun transitExitDesktopAppHandleButton_logTaskRemovedAndExitReasonButton_sessionIdNull() {
val sessionId = 1
// add a freeform task
- transitionObserver.addTaskInfosToCachedMap(createTaskInfo(1, WINDOWING_MODE_FREEFORM))
+ transitionObserver.addTaskInfosToCachedMap(createTaskInfo(WINDOWING_MODE_FREEFORM))
transitionObserver.setLoggerSessionId(sessionId)
// window mode changing from FREEFORM to FULLSCREEN
- val change = createChange(TRANSIT_TO_FRONT, createTaskInfo(1, WINDOWING_MODE_FULLSCREEN))
+ val change = createChange(TRANSIT_TO_FRONT, createTaskInfo(WINDOWING_MODE_FULLSCREEN))
val transitionInfo =
TransitionInfoBuilder(TRANSIT_EXIT_DESKTOP_MODE_HANDLE_MENU_BUTTON)
.addChange(change)
.build()
callOnTransitionReady(transitionInfo)
- verify(desktopModeEventLogger, times(1)).logTaskRemoved(eq(sessionId), any())
- verify(desktopModeEventLogger, times(1))
- .logSessionExit(eq(sessionId), eq(ExitReason.APP_HANDLE_MENU_BUTTON_EXIT))
- verifyZeroInteractions(desktopModeEventLogger)
- assertThat(transitionObserver.getLoggerSessionId()).isNull()
+ verifyTaskRemovedAndExitLogging(
+ sessionId, ExitReason.APP_HANDLE_MENU_BUTTON_EXIT, DEFAULT_TASK_UPDATE)
}
@Test
fun transitExitDesktopUsingKeyboard_logTaskRemovedAndExitReasonKeyboard_sessionIdNull() {
val sessionId = 1
// add a freeform task
- transitionObserver.addTaskInfosToCachedMap(createTaskInfo(1, WINDOWING_MODE_FREEFORM))
+ transitionObserver.addTaskInfosToCachedMap(createTaskInfo(WINDOWING_MODE_FREEFORM))
transitionObserver.setLoggerSessionId(sessionId)
// window mode changing from FREEFORM to FULLSCREEN
- val change = createChange(TRANSIT_TO_FRONT, createTaskInfo(1, WINDOWING_MODE_FULLSCREEN))
+ val change = createChange(TRANSIT_TO_FRONT, createTaskInfo(WINDOWING_MODE_FULLSCREEN))
val transitionInfo =
TransitionInfoBuilder(TRANSIT_EXIT_DESKTOP_MODE_KEYBOARD_SHORTCUT).addChange(change).build()
callOnTransitionReady(transitionInfo)
- verify(desktopModeEventLogger, times(1)).logTaskRemoved(eq(sessionId), any())
- verify(desktopModeEventLogger, times(1))
- .logSessionExit(eq(sessionId), eq(ExitReason.KEYBOARD_SHORTCUT_EXIT))
- verifyZeroInteractions(desktopModeEventLogger)
- assertThat(transitionObserver.getLoggerSessionId()).isNull()
+ verifyTaskRemovedAndExitLogging(
+ sessionId, ExitReason.KEYBOARD_SHORTCUT_EXIT, DEFAULT_TASK_UPDATE)
}
@Test
fun transitExitDesktopUnknown_logTaskRemovedAndExitReasonUnknown_sessionIdNull() {
val sessionId = 1
// add a freeform task
- transitionObserver.addTaskInfosToCachedMap(createTaskInfo(1, WINDOWING_MODE_FREEFORM))
+ transitionObserver.addTaskInfosToCachedMap(createTaskInfo(WINDOWING_MODE_FREEFORM))
transitionObserver.setLoggerSessionId(sessionId)
// window mode changing from FREEFORM to FULLSCREEN
- val change = createChange(TRANSIT_TO_FRONT, createTaskInfo(1, WINDOWING_MODE_FULLSCREEN))
+ val change = createChange(TRANSIT_TO_FRONT, createTaskInfo(WINDOWING_MODE_FULLSCREEN))
val transitionInfo =
TransitionInfoBuilder(TRANSIT_EXIT_DESKTOP_MODE_UNKNOWN).addChange(change).build()
callOnTransitionReady(transitionInfo)
- verify(desktopModeEventLogger, times(1)).logTaskRemoved(eq(sessionId), any())
- verify(desktopModeEventLogger, times(1))
- .logSessionExit(eq(sessionId), eq(ExitReason.UNKNOWN_EXIT))
- verifyZeroInteractions(desktopModeEventLogger)
- assertThat(transitionObserver.getLoggerSessionId()).isNull()
+ verifyTaskRemovedAndExitLogging(sessionId, ExitReason.UNKNOWN_EXIT, DEFAULT_TASK_UPDATE)
}
@Test
fun transitToFrontWithFlagRecents_logTaskRemovedAndExitReasonOverview_sessionIdNull() {
val sessionId = 1
// add a freeform task
- transitionObserver.addTaskInfosToCachedMap(createTaskInfo(1, WINDOWING_MODE_FREEFORM))
+ transitionObserver.addTaskInfosToCachedMap(createTaskInfo(WINDOWING_MODE_FREEFORM))
transitionObserver.setLoggerSessionId(sessionId)
// recents transition
- val change = createChange(TRANSIT_TO_BACK, createTaskInfo(1, WINDOWING_MODE_FREEFORM))
+ val change = createChange(TRANSIT_TO_BACK, createTaskInfo(WINDOWING_MODE_FREEFORM))
val transitionInfo =
TransitionInfoBuilder(TRANSIT_TO_FRONT, TRANSIT_FLAG_IS_RECENTS).addChange(change).build()
callOnTransitionReady(transitionInfo)
- verify(desktopModeEventLogger, times(1)).logTaskRemoved(eq(sessionId), any())
- verify(desktopModeEventLogger, times(1))
- .logSessionExit(eq(sessionId), eq(ExitReason.RETURN_HOME_OR_OVERVIEW))
- verifyZeroInteractions(desktopModeEventLogger)
- assertThat(transitionObserver.getLoggerSessionId()).isNull()
+ verifyTaskRemovedAndExitLogging(
+ sessionId, ExitReason.RETURN_HOME_OR_OVERVIEW, DEFAULT_TASK_UPDATE)
}
@Test
fun transitClose_logTaskRemovedAndExitReasonTaskFinished_sessionIdNull() {
val sessionId = 1
// add a freeform task
- transitionObserver.addTaskInfosToCachedMap(createTaskInfo(1, WINDOWING_MODE_FREEFORM))
+ transitionObserver.addTaskInfosToCachedMap(createTaskInfo(WINDOWING_MODE_FREEFORM))
transitionObserver.setLoggerSessionId(sessionId)
// task closing
- val change = createChange(TRANSIT_CLOSE, createTaskInfo(1, WINDOWING_MODE_FULLSCREEN))
+ val change = createChange(TRANSIT_CLOSE, createTaskInfo(WINDOWING_MODE_FULLSCREEN))
val transitionInfo = TransitionInfoBuilder(TRANSIT_CLOSE).addChange(change).build()
callOnTransitionReady(transitionInfo)
- verify(desktopModeEventLogger, times(1)).logTaskRemoved(eq(sessionId), any())
- verify(desktopModeEventLogger, times(1))
- .logSessionExit(eq(sessionId), eq(ExitReason.TASK_FINISHED))
- verifyZeroInteractions(desktopModeEventLogger)
- assertThat(transitionObserver.getLoggerSessionId()).isNull()
+ verifyTaskRemovedAndExitLogging(sessionId, ExitReason.TASK_FINISHED, DEFAULT_TASK_UPDATE)
}
@Test
fun sessionExitByRecents_cancelledAnimation_sessionRestored() {
val sessionId = 1
// add a freeform task to an existing session
- transitionObserver.addTaskInfosToCachedMap(createTaskInfo(1, WINDOWING_MODE_FREEFORM))
+ val taskInfo = createTaskInfo(WINDOWING_MODE_FREEFORM)
+ transitionObserver.addTaskInfosToCachedMap(taskInfo)
transitionObserver.setLoggerSessionId(sessionId)
// recents transition sent freeform window to back
- val change = createChange(TRANSIT_TO_BACK, createTaskInfo(1, WINDOWING_MODE_FREEFORM))
+ val change = createChange(TRANSIT_TO_BACK, taskInfo)
val transitionInfo1 =
TransitionInfoBuilder(TRANSIT_TO_FRONT, TRANSIT_FLAG_IS_RECENTS).addChange(change).build()
callOnTransitionReady(transitionInfo1)
- verify(desktopModeEventLogger, times(1)).logTaskRemoved(eq(sessionId), any())
- verify(desktopModeEventLogger, times(1))
- .logSessionExit(eq(sessionId), eq(ExitReason.RETURN_HOME_OR_OVERVIEW))
- assertThat(transitionObserver.getLoggerSessionId()).isNull()
+
+ verifyTaskRemovedAndExitLogging(
+ sessionId, ExitReason.RETURN_HOME_OR_OVERVIEW, DEFAULT_TASK_UPDATE)
val transitionInfo2 = TransitionInfoBuilder(TRANSIT_NONE).build()
callOnTransitionReady(transitionInfo2)
- verify(desktopModeEventLogger, times(1)).logSessionEnter(any(), any())
- verify(desktopModeEventLogger, times(1)).logTaskAdded(any(), any())
+ verifyTaskAddedAndEnterLogging(EnterReason.OVERVIEW, DEFAULT_TASK_UPDATE)
}
@Test
fun sessionAlreadyStarted_newFreeformTaskAdded_logsTaskAdded() {
val sessionId = 1
// add an existing freeform task
- transitionObserver.addTaskInfosToCachedMap(createTaskInfo(1, WINDOWING_MODE_FREEFORM))
+ transitionObserver.addTaskInfosToCachedMap(createTaskInfo(WINDOWING_MODE_FREEFORM))
transitionObserver.setLoggerSessionId(sessionId)
// new freeform task added
- val change = createChange(TRANSIT_OPEN, createTaskInfo(2, WINDOWING_MODE_FREEFORM))
+ val change = createChange(TRANSIT_OPEN, createTaskInfo(WINDOWING_MODE_FREEFORM, id = 2))
val transitionInfo = TransitionInfoBuilder(TRANSIT_OPEN, 0).addChange(change).build()
callOnTransitionReady(transitionInfo)
- verify(desktopModeEventLogger, times(1)).logTaskAdded(eq(sessionId), any())
+ verify(desktopModeEventLogger, times(1))
+ .logTaskAdded(eq(sessionId), eq(DEFAULT_TASK_UPDATE.copy(instanceId = 2)))
verify(desktopModeEventLogger, never()).logSessionEnter(any(), any())
}
@Test
+ fun sessionAlreadyStarted_taskPositionChanged_logsTaskUpdate() {
+ val sessionId = 1
+ // add an existing freeform task
+ val taskInfo = createTaskInfo(WINDOWING_MODE_FREEFORM)
+ transitionObserver.addTaskInfosToCachedMap(taskInfo)
+ transitionObserver.setLoggerSessionId(sessionId)
+
+ // task position changed
+ val newTaskInfo = createTaskInfo(WINDOWING_MODE_FREEFORM, taskX = DEFAULT_TASK_X + 100)
+ val transitionInfo =
+ TransitionInfoBuilder(TRANSIT_CHANGE, 0)
+ .addChange(createChange(TRANSIT_CHANGE, newTaskInfo))
+ .build()
+ callOnTransitionReady(transitionInfo)
+
+ verify(desktopModeEventLogger, times(1))
+ .logTaskInfoChanged(
+ eq(sessionId), eq(DEFAULT_TASK_UPDATE.copy(taskX = DEFAULT_TASK_X + 100)))
+ verifyZeroInteractions(desktopModeEventLogger)
+ }
+
+ @Test
+ fun sessionAlreadyStarted_taskResized_logsTaskUpdate() {
+ val sessionId = 1
+ // add an existing freeform task
+ val taskInfo = createTaskInfo(WINDOWING_MODE_FREEFORM)
+ transitionObserver.addTaskInfosToCachedMap(taskInfo)
+ transitionObserver.setLoggerSessionId(sessionId)
+
+ // task resized
+ val newTaskInfo =
+ createTaskInfo(
+ WINDOWING_MODE_FREEFORM,
+ taskWidth = DEFAULT_TASK_WIDTH + 100,
+ taskHeight = DEFAULT_TASK_HEIGHT - 100)
+ val transitionInfo =
+ TransitionInfoBuilder(TRANSIT_CHANGE, 0)
+ .addChange(createChange(TRANSIT_CHANGE, newTaskInfo))
+ .build()
+ callOnTransitionReady(transitionInfo)
+
+ verify(desktopModeEventLogger, times(1))
+ .logTaskInfoChanged(
+ eq(sessionId),
+ eq(
+ DEFAULT_TASK_UPDATE.copy(
+ taskWidth = DEFAULT_TASK_WIDTH + 100, taskHeight = DEFAULT_TASK_HEIGHT - 100)))
+ verifyZeroInteractions(desktopModeEventLogger)
+ }
+
+ @Test
+ fun sessionAlreadyStarted_multipleTasksUpdated_logsTaskUpdateForCorrectTask() {
+ val sessionId = 1
+ // add 2 existing freeform task
+ val taskInfo1 = createTaskInfo(WINDOWING_MODE_FREEFORM)
+ val taskInfo2 = createTaskInfo(WINDOWING_MODE_FREEFORM, id = 2)
+ transitionObserver.addTaskInfosToCachedMap(taskInfo1)
+ transitionObserver.addTaskInfosToCachedMap(taskInfo2)
+ transitionObserver.setLoggerSessionId(sessionId)
+
+ // task 1 position update
+ val newTaskInfo1 = createTaskInfo(WINDOWING_MODE_FREEFORM, taskX = DEFAULT_TASK_X + 100)
+ val transitionInfo1 =
+ TransitionInfoBuilder(TRANSIT_CHANGE, 0)
+ .addChange(createChange(TRANSIT_CHANGE, newTaskInfo1))
+ .build()
+ callOnTransitionReady(transitionInfo1)
+
+ verify(desktopModeEventLogger, times(1))
+ .logTaskInfoChanged(
+ eq(sessionId), eq(DEFAULT_TASK_UPDATE.copy(taskX = DEFAULT_TASK_X + 100)))
+ verifyZeroInteractions(desktopModeEventLogger)
+
+ // task 2 resize
+ val newTaskInfo2 =
+ createTaskInfo(
+ WINDOWING_MODE_FREEFORM,
+ id = 2,
+ taskWidth = DEFAULT_TASK_WIDTH + 100,
+ taskHeight = DEFAULT_TASK_HEIGHT - 100)
+ val transitionInfo2 =
+ TransitionInfoBuilder(TRANSIT_CHANGE, 0)
+ .addChange(createChange(TRANSIT_CHANGE, newTaskInfo2))
+ .build()
+
+ callOnTransitionReady(transitionInfo2)
+
+ verify(desktopModeEventLogger, times(1))
+ .logTaskInfoChanged(
+ eq(sessionId),
+ eq(
+ DEFAULT_TASK_UPDATE.copy(
+ instanceId = 2,
+ taskWidth = DEFAULT_TASK_WIDTH + 100,
+ taskHeight = DEFAULT_TASK_HEIGHT - 100)))
+ verifyZeroInteractions(desktopModeEventLogger)
+ }
+
+ @Test
fun sessionAlreadyStarted_freeformTaskRemoved_logsTaskRemoved() {
val sessionId = 1
// add two existing freeform tasks
- transitionObserver.addTaskInfosToCachedMap(createTaskInfo(1, WINDOWING_MODE_FREEFORM))
- transitionObserver.addTaskInfosToCachedMap(createTaskInfo(2, WINDOWING_MODE_FREEFORM))
+ transitionObserver.addTaskInfosToCachedMap(createTaskInfo(WINDOWING_MODE_FREEFORM))
+ transitionObserver.addTaskInfosToCachedMap(createTaskInfo(WINDOWING_MODE_FREEFORM, id = 2))
transitionObserver.setLoggerSessionId(sessionId)
- // new freeform task added
- val change = createChange(TRANSIT_CLOSE, createTaskInfo(2, WINDOWING_MODE_FREEFORM))
+ // new freeform task closed
+ val change = createChange(TRANSIT_CLOSE, createTaskInfo(WINDOWING_MODE_FREEFORM, id = 2))
val transitionInfo = TransitionInfoBuilder(TRANSIT_CLOSE, 0).addChange(change).build()
callOnTransitionReady(transitionInfo)
- verify(desktopModeEventLogger, times(1)).logTaskRemoved(eq(sessionId), any())
+ verify(desktopModeEventLogger, times(1))
+ .logTaskRemoved(eq(sessionId), eq(DEFAULT_TASK_UPDATE.copy(instanceId = 2)))
verify(desktopModeEventLogger, never()).logSessionExit(any(), any())
}
/** Simulate calling the onTransitionReady() method */
private fun callOnTransitionReady(transitionInfo: TransitionInfo) {
- val transition = mock(IBinder::class.java)
- val startT = mock(SurfaceControl.Transaction::class.java)
- val finishT = mock(SurfaceControl.Transaction::class.java)
+ val transition = mock<IBinder>()
+ val startT = mock<SurfaceControl.Transaction>()
+ val finishT = mock<SurfaceControl.Transaction>()
transitionObserver.onTransitionReady(transition, transitionInfo, startT, finishT)
}
- companion object {
- fun createTaskInfo(taskId: Int, windowMode: Int): ActivityManager.RunningTaskInfo {
- val taskInfo = ActivityManager.RunningTaskInfo()
- taskInfo.taskId = taskId
- taskInfo.configuration.windowConfiguration.windowingMode = windowMode
+ private fun verifyTaskAddedAndEnterLogging(enterReason: EnterReason, taskUpdate: TaskUpdate) {
+ val sessionId = transitionObserver.getLoggerSessionId()
+ assertNotNull(sessionId)
+ verify(desktopModeEventLogger, times(1)).logSessionEnter(eq(sessionId!!), eq(enterReason))
+ verify(desktopModeEventLogger, times(1)).logTaskAdded(eq(sessionId), eq(taskUpdate))
+ verifyZeroInteractions(desktopModeEventLogger)
+ }
- return taskInfo
- }
+ private fun verifyTaskRemovedAndExitLogging(
+ sessionId: Int,
+ exitReason: ExitReason,
+ taskUpdate: TaskUpdate
+ ) {
+ verify(desktopModeEventLogger, times(1)).logTaskRemoved(eq(sessionId), eq(taskUpdate))
+ verify(desktopModeEventLogger, times(1)).logSessionExit(eq(sessionId), eq(exitReason))
+ verifyZeroInteractions(desktopModeEventLogger)
+ assertNull(transitionObserver.getLoggerSessionId())
+ }
+
+ private companion object {
+ const val DEFAULT_TASK_ID = 1
+ const val DEFAULT_TASK_UID = 2
+ const val DEFAULT_TASK_HEIGHT = 100
+ const val DEFAULT_TASK_WIDTH = 200
+ const val DEFAULT_TASK_X = 30
+ const val DEFAULT_TASK_Y = 70
+ val DEFAULT_TASK_UPDATE =
+ TaskUpdate(
+ DEFAULT_TASK_ID,
+ DEFAULT_TASK_UID,
+ DEFAULT_TASK_HEIGHT,
+ DEFAULT_TASK_WIDTH,
+ DEFAULT_TASK_X,
+ DEFAULT_TASK_Y,
+ )
+
+ fun createTaskInfo(
+ windowMode: Int,
+ id: Int = DEFAULT_TASK_ID,
+ uid: Int = DEFAULT_TASK_UID,
+ taskHeight: Int = DEFAULT_TASK_HEIGHT,
+ taskWidth: Int = DEFAULT_TASK_WIDTH,
+ taskX: Int = DEFAULT_TASK_X,
+ taskY: Int = DEFAULT_TASK_Y,
+ ) =
+ ActivityManager.RunningTaskInfo().apply {
+ taskId = id
+ userId = uid
+ configuration.windowConfiguration.apply {
+ windowingMode = windowMode
+ positionInParent = Point(taskX, taskY)
+ bounds.set(Rect(taskX, taskY, taskX + taskWidth, taskY + taskHeight))
+ }
+ }
fun createChange(mode: Int, taskInfo: ActivityManager.RunningTaskInfo): Change {
val change =
- Change(
- WindowContainerToken(mock(IWindowContainerToken::class.java)),
- mock(SurfaceControl::class.java))
+ Change(WindowContainerToken(mock<IWindowContainerToken>()), mock<SurfaceControl>())
change.mode = mode
change.taskInfo = taskInfo
return change
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeTaskRepositoryTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeTaskRepositoryTest.kt
index 310ccc2..193d614 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeTaskRepositoryTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeTaskRepositoryTest.kt
@@ -119,54 +119,86 @@
}
@Test
- fun isOnlyActiveTask_noActiveTasks() {
+ fun isOnlyActiveNonClosingTask_noActiveNonClosingTasks() {
// Not an active task
- assertThat(repo.isOnlyActiveTask(1)).isFalse()
+ assertThat(repo.isOnlyActiveNonClosingTask(1)).isFalse()
+ assertThat(repo.isClosingTask(1)).isFalse()
}
@Test
- fun isOnlyActiveTask_singleActiveTask() {
+ fun isOnlyActiveNonClosingTask_singleActiveNonClosingTask() {
repo.addActiveTask(DEFAULT_DISPLAY, 1)
// The only active task
assertThat(repo.isActiveTask(1)).isTrue()
- assertThat(repo.isOnlyActiveTask(1)).isTrue()
+ assertThat(repo.isClosingTask(1)).isFalse()
+ assertThat(repo.isOnlyActiveNonClosingTask(1)).isTrue()
// Not an active task
assertThat(repo.isActiveTask(99)).isFalse()
- assertThat(repo.isOnlyActiveTask(99)).isFalse()
+ assertThat(repo.isClosingTask(99)).isFalse()
+ assertThat(repo.isOnlyActiveNonClosingTask(99)).isFalse()
}
@Test
- fun isOnlyActiveTask_multipleActiveTasks() {
+ fun isOnlyActiveNonClosingTask_singleActiveClosingTask() {
+ repo.addActiveTask(DEFAULT_DISPLAY, 1)
+ repo.addClosingTask(DEFAULT_DISPLAY, 1)
+ // The active task that's closing
+ assertThat(repo.isActiveTask(1)).isTrue()
+ assertThat(repo.isClosingTask(1)).isTrue()
+ assertThat(repo.isOnlyActiveNonClosingTask(1)).isFalse()
+ // Not an active task
+ assertThat(repo.isActiveTask(99)).isFalse()
+ assertThat(repo.isOnlyActiveNonClosingTask(99)).isFalse()
+ }
+
+ @Test
+ fun isOnlyActiveNonClosingTask_singleActiveMinimizedTask() {
+ repo.addActiveTask(DEFAULT_DISPLAY, 1)
+ repo.minimizeTask(DEFAULT_DISPLAY, 1)
+ // The active task that's closing
+ assertThat(repo.isActiveTask(1)).isTrue()
+ assertThat(repo.isMinimizedTask(1)).isTrue()
+ assertThat(repo.isOnlyActiveNonClosingTask(1)).isFalse()
+ // Not an active task
+ assertThat(repo.isActiveTask(99)).isFalse()
+ assertThat(repo.isOnlyActiveNonClosingTask(99)).isFalse()
+ }
+
+ @Test
+ fun isOnlyActiveNonClosingTask_multipleActiveNonClosingTasks() {
repo.addActiveTask(DEFAULT_DISPLAY, 1)
repo.addActiveTask(DEFAULT_DISPLAY, 2)
// Not the only task
assertThat(repo.isActiveTask(1)).isTrue()
- assertThat(repo.isOnlyActiveTask(1)).isFalse()
+ assertThat(repo.isClosingTask(1)).isFalse()
+ assertThat(repo.isOnlyActiveNonClosingTask(1)).isFalse()
// Not the only task
assertThat(repo.isActiveTask(2)).isTrue()
- assertThat(repo.isOnlyActiveTask(2)).isFalse()
+ assertThat(repo.isClosingTask(2)).isFalse()
+ assertThat(repo.isOnlyActiveNonClosingTask(2)).isFalse()
// Not an active task
assertThat(repo.isActiveTask(99)).isFalse()
- assertThat(repo.isOnlyActiveTask(99)).isFalse()
+ assertThat(repo.isClosingTask(99)).isFalse()
+ assertThat(repo.isOnlyActiveNonClosingTask(99)).isFalse()
}
@Test
- fun isOnlyActiveTask_multipleDisplays() {
+ fun isOnlyActiveNonClosingTask_multipleDisplays() {
repo.addActiveTask(DEFAULT_DISPLAY, 1)
repo.addActiveTask(DEFAULT_DISPLAY, 2)
repo.addActiveTask(SECOND_DISPLAY, 3)
// Not the only task on DEFAULT_DISPLAY
assertThat(repo.isActiveTask(1)).isTrue()
- assertThat(repo.isOnlyActiveTask(1)).isFalse()
+ assertThat(repo.isOnlyActiveNonClosingTask(1)).isFalse()
// Not the only task on DEFAULT_DISPLAY
assertThat(repo.isActiveTask(2)).isTrue()
- assertThat(repo.isOnlyActiveTask(2)).isFalse()
+ assertThat(repo.isOnlyActiveNonClosingTask(2)).isFalse()
// The only active task on SECOND_DISPLAY
assertThat(repo.isActiveTask(3)).isTrue()
- assertThat(repo.isOnlyActiveTask(3)).isTrue()
+ assertThat(repo.isOnlyActiveNonClosingTask(3)).isTrue()
// Not an active task
assertThat(repo.isActiveTask(99)).isFalse()
- assertThat(repo.isOnlyActiveTask(99)).isFalse()
+ assertThat(repo.isOnlyActiveNonClosingTask(99)).isFalse()
}
@Test
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
index e17f7f2..392161f 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
@@ -923,7 +923,7 @@
@Test
fun onDesktopWindowClose_noActiveTasks() {
val wct = WindowContainerTransaction()
- controller.onDesktopWindowClose(wct, 1 /* taskId */)
+ controller.onDesktopWindowClose(wct, displayId = DEFAULT_DISPLAY, taskId = 1)
// Doesn't modify transaction
assertThat(wct.hierarchyOps).isEmpty()
}
@@ -932,7 +932,7 @@
fun onDesktopWindowClose_singleActiveTask_noWallpaperActivityToken() {
val task = setUpFreeformTask()
val wct = WindowContainerTransaction()
- controller.onDesktopWindowClose(wct, task.taskId)
+ controller.onDesktopWindowClose(wct, displayId = DEFAULT_DISPLAY, taskId = task.taskId)
// Doesn't modify transaction
assertThat(wct.hierarchyOps).isEmpty()
}
@@ -944,12 +944,38 @@
desktopModeTaskRepository.wallpaperActivityToken = wallpaperToken
val wct = WindowContainerTransaction()
- controller.onDesktopWindowClose(wct, task.taskId)
+ controller.onDesktopWindowClose(wct, displayId = DEFAULT_DISPLAY, taskId = task.taskId)
// Adds remove wallpaper operation
wct.assertRemoveAt(index = 0, wallpaperToken)
}
@Test
+ fun onDesktopWindowClose_singleActiveTask_isClosing() {
+ val task = setUpFreeformTask()
+ val wallpaperToken = MockToken().token()
+ desktopModeTaskRepository.wallpaperActivityToken = wallpaperToken
+ desktopModeTaskRepository.addClosingTask(DEFAULT_DISPLAY, task.taskId)
+
+ val wct = WindowContainerTransaction()
+ controller.onDesktopWindowClose(wct, displayId = DEFAULT_DISPLAY, taskId = task.taskId)
+ // Doesn't modify transaction
+ assertThat(wct.hierarchyOps).isEmpty()
+ }
+
+ @Test
+ fun onDesktopWindowClose_singleActiveTask_isMinimized() {
+ val task = setUpFreeformTask()
+ val wallpaperToken = MockToken().token()
+ desktopModeTaskRepository.wallpaperActivityToken = wallpaperToken
+ desktopModeTaskRepository.minimizeTask(DEFAULT_DISPLAY, task.taskId)
+
+ val wct = WindowContainerTransaction()
+ controller.onDesktopWindowClose(wct, displayId = DEFAULT_DISPLAY, taskId = task.taskId)
+ // Doesn't modify transaction
+ assertThat(wct.hierarchyOps).isEmpty()
+ }
+
+ @Test
fun onDesktopWindowClose_multipleActiveTasks() {
val task1 = setUpFreeformTask()
setUpFreeformTask()
@@ -957,12 +983,40 @@
desktopModeTaskRepository.wallpaperActivityToken = wallpaperToken
val wct = WindowContainerTransaction()
- controller.onDesktopWindowClose(wct, task1.taskId)
+ controller.onDesktopWindowClose(wct, displayId = DEFAULT_DISPLAY, taskId = task1.taskId)
// Doesn't modify transaction
assertThat(wct.hierarchyOps).isEmpty()
}
@Test
+ fun onDesktopWindowClose_multipleActiveTasks_isOnlyNonClosingTask() {
+ val task1 = setUpFreeformTask()
+ val task2 = setUpFreeformTask()
+ val wallpaperToken = MockToken().token()
+ desktopModeTaskRepository.wallpaperActivityToken = wallpaperToken
+ desktopModeTaskRepository.addClosingTask(DEFAULT_DISPLAY, task2.taskId)
+
+ val wct = WindowContainerTransaction()
+ controller.onDesktopWindowClose(wct, displayId = DEFAULT_DISPLAY, taskId = task1.taskId)
+ // Adds remove wallpaper operation
+ wct.assertRemoveAt(index = 0, wallpaperToken)
+ }
+
+ @Test
+ fun onDesktopWindowClose_multipleActiveTasks_hasMinimized() {
+ val task1 = setUpFreeformTask()
+ val task2 = setUpFreeformTask()
+ val wallpaperToken = MockToken().token()
+ desktopModeTaskRepository.wallpaperActivityToken = wallpaperToken
+ desktopModeTaskRepository.minimizeTask(DEFAULT_DISPLAY, task2.taskId)
+
+ val wct = WindowContainerTransaction()
+ controller.onDesktopWindowClose(wct, displayId = DEFAULT_DISPLAY, taskId = task1.taskId)
+ // Adds remove wallpaper operation
+ wct.assertRemoveAt(index = 0, wallpaperToken)
+ }
+
+ @Test
fun handleRequest_fullscreenTask_freeformVisible_returnSwitchToFreeformWCT() {
assumeTrue(ENABLE_SHELL_TRANSITIONS)
@@ -1245,6 +1299,30 @@
}
@Test
+ @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY)
+ fun handleRequest_backTransition_multipleActiveTasks_singleNonClosing() {
+ desktopModeTaskRepository.wallpaperActivityToken = MockToken().token()
+
+ val task1 = setUpFreeformTask()
+ setUpFreeformTask()
+ val result = controller.handleRequest(Binder(), createTransition(task1, type = TRANSIT_TO_BACK))
+ // Doesn't handle request
+ assertThat(result).isNull()
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY)
+ fun handleRequest_backTransition_multipleActiveTasks_singleNonMinimized() {
+ desktopModeTaskRepository.wallpaperActivityToken = MockToken().token()
+
+ val task1 = setUpFreeformTask()
+ setUpFreeformTask()
+ val result = controller.handleRequest(Binder(), createTransition(task1, type = TRANSIT_TO_BACK))
+ // Doesn't handle request
+ assertThat(result).isNull()
+ }
+
+ @Test
fun desktopTasksVisibilityChange_visible_setLaunchAdjacentDisabled() {
val task = setUpFreeformTask()
clearInvocations(launchAdjacentController)
diff --git a/lint-baseline.xml b/lint-baseline.xml
index 660884a..0320aab 100644
--- a/lint-baseline.xml
+++ b/lint-baseline.xml
@@ -562,4 +562,10707 @@
column="74"/>
</issue>
+ <issue
+ id="FlaggedApi"
+ message="Method `getItemCount()` is a flagged API and should be inside an `if (Flags.collectionInfoItemCounts())` check (or annotate the surrounding method `writeToParcelNoRecycle` with `@FlaggedApi(Flags.FLAG_COLLECTION_INFO_ITEM_COUNTS) to transfer requirement to caller`)"
+ errorLine1=" parcel.writeInt(mCollectionInfo.getItemCount());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/accessibility/AccessibilityNodeInfo.java"
+ line="4498"
+ column="29"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getImportantForAccessibilityItemCount()` is a flagged API and should be inside an `if (Flags.collectionInfoItemCounts())` check (or annotate the surrounding method `writeToParcelNoRecycle` with `@FlaggedApi(Flags.FLAG_COLLECTION_INFO_ITEM_COUNTS) to transfer requirement to caller`)"
+ errorLine1=" parcel.writeInt(mCollectionInfo.getImportantForAccessibilityItemCount());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/accessibility/AccessibilityNodeInfo.java"
+ line="4499"
+ column="29"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `isGranularScrollingSupported()` is a flagged API and should be inside an `if (Flags.granularScrolling())` check (or annotate the surrounding method `toString` with `@FlaggedApi(Flags.FLAG_GRANULAR_SCROLLING) to transfer requirement to caller`)"
+ errorLine1=" builder.append("; granularScrollingSupported: ").append(isGranularScrollingSupported());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/accessibility/AccessibilityNodeInfo.java"
+ line="5079"
+ column="65"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `UNDEFINED` is a flagged API and should be inside an `if (Flags.collectionInfoItemCounts())` check (or annotate the surrounding method `CollectionInfo` with `@FlaggedApi(Flags.FLAG_COLLECTION_INFO_ITEM_COUNTS) to transfer requirement to caller`)"
+ errorLine1=" mItemCount = UNDEFINED;"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/accessibility/AccessibilityNodeInfo.java"
+ line="6211"
+ column="26"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `UNDEFINED` is a flagged API and should be inside an `if (Flags.collectionInfoItemCounts())` check (or annotate the surrounding method `CollectionInfo` with `@FlaggedApi(Flags.FLAG_COLLECTION_INFO_ITEM_COUNTS) to transfer requirement to caller`)"
+ errorLine1=" mImportantForAccessibilityItemCount = UNDEFINED;"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/accessibility/AccessibilityNodeInfo.java"
+ line="6212"
+ column="51"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `UNDEFINED` is a flagged API and should be inside an `if (Flags.collectionInfoItemCounts())` check (or annotate the surrounding method `clear` with `@FlaggedApi(Flags.FLAG_COLLECTION_INFO_ITEM_COUNTS) to transfer requirement to caller`)"
+ errorLine1=" mItemCount = UNDEFINED;"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/accessibility/AccessibilityNodeInfo.java"
+ line="6319"
+ column="26"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `UNDEFINED` is a flagged API and should be inside an `if (Flags.collectionInfoItemCounts())` check (or annotate the surrounding method `clear` with `@FlaggedApi(Flags.FLAG_COLLECTION_INFO_ITEM_COUNTS) to transfer requirement to caller`)"
+ errorLine1=" mImportantForAccessibilityItemCount = UNDEFINED;"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/accessibility/AccessibilityNodeInfo.java"
+ line="6320"
+ column="51"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @FlaggedApi("android.view.accessibility.a11y_overlay_callbacks")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/accessibilityservice/AccessibilityService.java"
+ line="800"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @FlaggedApi("android.view.accessibility.a11y_overlay_callbacks")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/accessibilityservice/AccessibilityService.java"
+ line="811"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @FlaggedApi("android.view.accessibility.a11y_overlay_callbacks")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/accessibilityservice/AccessibilityService.java"
+ line="811"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @FlaggedApi("android.view.accessibility.a11y_overlay_callbacks")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/accessibilityservice/AccessibilityService.java"
+ line="811"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @FlaggedApi("android.view.accessibility.a11y_overlay_callbacks")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/accessibilityservice/AccessibilityService.java"
+ line="819"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @FlaggedApi("android.view.accessibility.a11y_overlay_callbacks")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/accessibilityservice/AccessibilityService.java"
+ line="819"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @FlaggedApi("android.view.accessibility.a11y_overlay_callbacks")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/accessibilityservice/AccessibilityService.java"
+ line="819"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @FlaggedApi("android.view.accessibility.a11y_overlay_callbacks")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/accessibilityservice/AccessibilityService.java"
+ line="819"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @FlaggedApi("android.view.accessibility.a11y_overlay_callbacks")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/accessibilityservice/AccessibilityService.java"
+ line="819"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @FlaggedApi("android.view.accessibility.a11y_overlay_callbacks")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/accessibilityservice/AccessibilityService.java"
+ line="819"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @FlaggedApi("android.view.accessibility.a11y_overlay_callbacks")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/accessibilityservice/AccessibilityService.java"
+ line="819"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @FlaggedApi("android.view.accessibility.a11y_overlay_callbacks")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/accessibilityservice/AccessibilityService.java"
+ line="827"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @FlaggedApi("android.view.accessibility.a11y_overlay_callbacks")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/accessibilityservice/AccessibilityService.java"
+ line="827"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `setObservedMotionEventSources()` is a flagged API and should be inside an `if (Flags.motionEventObserving())` check (or annotate the surrounding method `initFromParcel` with `@FlaggedApi(Flags.FLAG_MOTION_EVENT_OBSERVING) to transfer requirement to caller`)"
+ errorLine1=" setObservedMotionEventSources(parcel.readInt());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/accessibilityservice/AccessibilityServiceInfo.java"
+ line="1420"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `TYPE_WINDOW_CONTROL` is a flagged API and should be inside an `if (Flags.addTypeWindowControl())` check (or annotate the surrounding method `typeToString` with `@FlaggedApi(Flags.FLAG_ADD_TYPE_WINDOW_CONTROL) to transfer requirement to caller`)"
+ errorLine1=" if (Flags.addTypeWindowControl() && type == TYPE_WINDOW_CONTROL) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/accessibility/AccessibilityWindowInfo.java"
+ line="883"
+ column="53"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `requestPermissions()` is a flagged API and should be inside an `if (Flags.deviceAwarePermissionApisEnabled())` check (or annotate the surrounding method `requestPermissions` with `@FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) to transfer requirement to caller`)"
+ errorLine1=" requestPermissions(permissions, requestCode, getDeviceId());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/Activity.java"
+ line="5636"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `EXTRA_REQUEST_PERMISSIONS_DEVICE_ID` is a flagged API and should be inside an `if (Flags.deviceAwarePermissionApisEnabled())` check (or annotate the surrounding method `dispatchRequestPermissionsResult` with `@FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) to transfer requirement to caller`)"
+ errorLine1=" PackageManager.EXTRA_REQUEST_PERMISSIONS_DEVICE_ID, Context.DEVICE_ID_DEFAULT"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/Activity.java"
+ line="9530"
+ column="32"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `onRequestPermissionsResult()` is a flagged API and should be inside an `if (Flags.deviceAwarePermissionApisEnabled())` check (or annotate the surrounding method `dispatchRequestPermissionsResult` with `@FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) to transfer requirement to caller`)"
+ errorLine1=" onRequestPermissionsResult(requestCode, permissions, grantResults, deviceId);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/Activity.java"
+ line="9532"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `uptimeNanos()` is a flagged API and should be inside an `if (Flags.adpfGpuReportActualWorkDuration())` check (or annotate the surrounding method `handleBindApplication` with `@FlaggedApi(Flags.FLAG_ADPF_GPU_REPORT_ACTUAL_WORK_DURATION) to transfer requirement to caller`)"
+ errorLine1=" timestampApplicationOnCreateNs = SystemClock.uptimeNanos();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/ActivityThread.java"
+ line="7503"
+ column="50"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `SeServiceManager()` is a flagged API and should be inside an `if (Flags.enableNfcMainline())` check (or annotate the surrounding method `initializeMainlineModules` with `@FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) to transfer requirement to caller`)"
+ errorLine1=" SeFrameworkInitializer.setSeServiceManager(new SeServiceManager());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/ActivityThread.java"
+ line="8725"
+ column="52"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `setSeServiceManager()` is a flagged API and should be inside an `if (Flags.enableNfcMainline())` check (or annotate the surrounding method `initializeMainlineModules` with `@FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) to transfer requirement to caller`)"
+ errorLine1=" SeFrameworkInitializer.setSeServiceManager(new SeServiceManager());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/ActivityThread.java"
+ line="8725"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `ProfilingServiceManager()` is a flagged API and should be inside an `if (Flags.telemetryApisFrameworkInitialization())` check (or annotate the surrounding method `initializeMainlineModules` with `@FlaggedApi(Flags.FLAG_TELEMETRY_APIS_FRAMEWORK_INITIALIZATION) to transfer requirement to caller`)"
+ errorLine1=" ProfilingFrameworkInitializer.setProfilingServiceManager(new ProfilingServiceManager());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/ActivityThread.java"
+ line="8727"
+ column="70"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `TvExtender()` is a flagged API and should be inside an `if (Flags.apiTvextender())` check (or annotate the surrounding method `createNotification` with `@FlaggedApi(Flags.FLAG_API_TVEXTENDER) to transfer requirement to caller`)"
+ errorLine1=" .extend(new Notification.TvExtender()"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/debug/AdbNotifications.java"
+ line="95"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `setChannelId()` is a flagged API and should be inside an `if (Flags.apiTvextender())` check (or annotate the surrounding method `createNotification` with `@FlaggedApi(Flags.FLAG_API_TVEXTENDER) to transfer requirement to caller`)"
+ errorLine1=" .extend(new Notification.TvExtender()"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/core/java/android/debug/AdbNotifications.java"
+ line="95"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `isMgf1DigestsSpecified()` is a flagged API and should be inside an `if (Flags.mgf1DigestSetterV2())` check (or annotate the surrounding method `initialize` with `@FlaggedApi(Flags.FLAG_MGF1_DIGEST_SETTER_V2) to transfer requirement to caller`)"
+ errorLine1=" if (spec.isMgf1DigestsSpecified()) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java"
+ line="346"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getMgf1Digests()` is a flagged API and should be inside an `if (Flags.mgf1DigestSetterV2())` check (or annotate the surrounding method `initialize` with `@FlaggedApi(Flags.FLAG_MGF1_DIGEST_SETTER_V2) to transfer requirement to caller`)"
+ errorLine1=" Set<String> mgfDigests = spec.getMgf1Digests();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java"
+ line="349"
+ column="46"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `isMgf1DigestsSpecified()` is a flagged API and should be inside an `if (Flags.mgf1DigestSetterV2())` check (or annotate the surrounding method `setPrivateKeyEntry` with `@FlaggedApi(Flags.FLAG_MGF1_DIGEST_SETTER_V2) to transfer requirement to caller`)"
+ errorLine1=" if (spec.isMgf1DigestsSpecified()) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java"
+ line="539"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getMgf1Digests()` is a flagged API and should be inside an `if (Flags.mgf1DigestSetterV2())` check (or annotate the surrounding method `setPrivateKeyEntry` with `@FlaggedApi(Flags.FLAG_MGF1_DIGEST_SETTER_V2) to transfer requirement to caller`)"
+ errorLine1=" for (String mgf1Digest : spec.getMgf1Digests()) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java"
+ line="540"
+ column="50"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `TYPE_RCS_STRING` is a flagged API and should be inside an `if (Flags.carrierEnabledSatelliteFlag())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG) to transfer requirement to caller`)"
+ errorLine1=" APN_TYPE_STRING_MAP.put(TYPE_RCS_STRING, TYPE_RCS);"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/data/ApnSetting.java"
+ line="491"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `TYPE_RCS` is a flagged API and should be inside an `if (Flags.carrierEnabledSatelliteFlag())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG) to transfer requirement to caller`)"
+ errorLine1=" APN_TYPE_STRING_MAP.put(TYPE_RCS_STRING, TYPE_RCS);"
+ errorLine2=" ~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/data/ApnSetting.java"
+ line="491"
+ column="50"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `TYPE_RCS_STRING` is a flagged API and should be inside an `if (Flags.carrierEnabledSatelliteFlag())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG) to transfer requirement to caller`)"
+ errorLine1=" APN_TYPE_INT_MAP.put(TYPE_RCS, TYPE_RCS_STRING);"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/data/ApnSetting.java"
+ line="509"
+ column="40"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `TYPE_RCS` is a flagged API and should be inside an `if (Flags.carrierEnabledSatelliteFlag())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG) to transfer requirement to caller`)"
+ errorLine1=" APN_TYPE_INT_MAP.put(TYPE_RCS, TYPE_RCS_STRING);"
+ errorLine2=" ~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/data/ApnSetting.java"
+ line="509"
+ column="30"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `MTU_V4` is a flagged API and should be inside an `if (Flags.apnSettingFieldSupportFlag())` check (or annotate the surrounding method `makeApnSetting` with `@FlaggedApi(Flags.FLAG_APN_SETTING_FIELD_SUPPORT_FLAG) to transfer requirement to caller`)"
+ errorLine1=" int mtuV4 = cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.MTU_V4));"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/data/ApnSetting.java"
+ line="1075"
+ column="83"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `setAlwaysOn()` is a flagged API and should be inside an `if (Flags.apnSettingFieldSupportFlag())` check (or annotate the surrounding method `makeApnSetting` with `@FlaggedApi(Flags.FLAG_APN_SETTING_FIELD_SUPPORT_FLAG) to transfer requirement to caller`)"
+ errorLine1=" return new Builder()"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/data/ApnSetting.java"
+ line="1080"
+ column="16"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `MTU_V6` is a flagged API and should be inside an `if (Flags.apnSettingFieldSupportFlag())` check (or annotate the surrounding method `makeApnSetting` with `@FlaggedApi(Flags.FLAG_APN_SETTING_FIELD_SUPPORT_FLAG) to transfer requirement to caller`)"
+ errorLine1=" .setMtuV6(cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.MTU_V6)))"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/data/ApnSetting.java"
+ line="1126"
+ column="89"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `ALWAYS_ON` is a flagged API and should be inside an `if (Flags.apnSettingFieldSupportFlag())` check (or annotate the surrounding method `makeApnSetting` with `@FlaggedApi(Flags.FLAG_APN_SETTING_FIELD_SUPPORT_FLAG) to transfer requirement to caller`)"
+ errorLine1=" .setAlwaysOn(cursor.getInt(cursor.getColumnIndexOrThrow(Carriers.ALWAYS_ON)) == 1)"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/data/ApnSetting.java"
+ line="1137"
+ column="82"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `setAlwaysOn()` is a flagged API and should be inside an `if (Flags.apnSettingFieldSupportFlag())` check (or annotate the surrounding method `makeApnSetting` with `@FlaggedApi(Flags.FLAG_APN_SETTING_FIELD_SUPPORT_FLAG) to transfer requirement to caller`)"
+ errorLine1=" return new Builder()"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/data/ApnSetting.java"
+ line="1151"
+ column="16"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `MTU_V4` is a flagged API and should be inside an `if (Flags.apnSettingFieldSupportFlag())` check (or annotate the surrounding method `toContentValues` with `@FlaggedApi(Flags.FLAG_APN_SETTING_FIELD_SUPPORT_FLAG) to transfer requirement to caller`)"
+ errorLine1=" apnValue.put(Telephony.Carriers.MTU_V4, mMtuV4);"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/data/ApnSetting.java"
+ line="1500"
+ column="41"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `MTU_V6` is a flagged API and should be inside an `if (Flags.apnSettingFieldSupportFlag())` check (or annotate the surrounding method `toContentValues` with `@FlaggedApi(Flags.FLAG_APN_SETTING_FIELD_SUPPORT_FLAG) to transfer requirement to caller`)"
+ errorLine1=" apnValue.put(Telephony.Carriers.MTU_V6, mMtuV6);"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/data/ApnSetting.java"
+ line="1501"
+ column="41"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `ALWAYS_ON` is a flagged API and should be inside an `if (Flags.apnSettingFieldSupportFlag())` check (or annotate the surrounding method `toContentValues` with `@FlaggedApi(Flags.FLAG_APN_SETTING_FIELD_SUPPORT_FLAG) to transfer requirement to caller`)"
+ errorLine1=" apnValue.put(Telephony.Carriers.ALWAYS_ON, mAlwaysOn);"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/data/ApnSetting.java"
+ line="1504"
+ column="41"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `setAlwaysOn()` is a flagged API and should be inside an `if (Flags.apnSettingFieldSupportFlag())` check (or annotate the surrounding method `readFromParcel` with `@FlaggedApi(Flags.FLAG_APN_SETTING_FIELD_SUPPORT_FLAG) to transfer requirement to caller`)"
+ errorLine1=" return new Builder()"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/data/ApnSetting.java"
+ line="1785"
+ column="16"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `TYPE_RCS` is a flagged API and should be inside an `if (Flags.carrierEnabledSatelliteFlag())` check (or annotate the surrounding method `build` with `@FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG) to transfer requirement to caller`)"
+ errorLine1=" | TYPE_XCAP | TYPE_VSIM | TYPE_BIP | TYPE_ENTERPRISE | TYPE_RCS)) == 0"
+ errorLine2=" ~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/data/ApnSetting.java"
+ line="2386"
+ column="76"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `OPSTR_ACCESS_RESTRICTED_SETTINGS` is a flagged API and should be inside an `if (Flags.enhancedConfirmationModeApisEnabled())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_ENHANCED_CONFIRMATION_MODE_APIS_ENABLED) to transfer requirement to caller`)"
+ errorLine1=" new AppOpInfo.Builder(OP_ACCESS_RESTRICTED_SETTINGS, OPSTR_ACCESS_RESTRICTED_SETTINGS,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/AppOpsManager.java"
+ line="2983"
+ column="62"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `OPSTR_CREATE_ACCESSIBILITY_OVERLAY` is a flagged API and should be inside an `if (Flags.createAccessibilityOverlayAppOpEnabled())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_CREATE_ACCESSIBILITY_OVERLAY_APP_OP_ENABLED) to transfer requirement to caller`)"
+ errorLine1=" OPSTR_CREATE_ACCESSIBILITY_OVERLAY,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/AppOpsManager.java"
+ line="3050"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `OPSTR_MEDIA_ROUTING_CONTROL` is a flagged API and should be inside an `if (Flags.enablePrivilegedRoutingForMediaRoutingControl())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_ENABLE_PRIVILEGED_ROUTING_FOR_MEDIA_ROUTING_CONTROL) to transfer requirement to caller`)"
+ errorLine1=" new AppOpInfo.Builder(OP_MEDIA_ROUTING_CONTROL, OPSTR_MEDIA_ROUTING_CONTROL,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/AppOpsManager.java"
+ line="3053"
+ column="57"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `OPSTR_ENABLE_MOBILE_DATA_BY_USER` is a flagged API and should be inside an `if (Flags.opEnableMobileDataByUser())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_OP_ENABLE_MOBILE_DATA_BY_USER) to transfer requirement to caller`)"
+ errorLine1=" new AppOpInfo.Builder(OP_ENABLE_MOBILE_DATA_BY_USER, OPSTR_ENABLE_MOBILE_DATA_BY_USER,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/AppOpsManager.java"
+ line="3056"
+ column="62"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `OPSTR_RAPID_CLEAR_NOTIFICATIONS_BY_LISTENER` is a flagged API and should be inside an `if (Flags.rapidClearNotificationsByListenerAppOpEnabled())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_RAPID_CLEAR_NOTIFICATIONS_BY_LISTENER_APP_OP_ENABLED) to transfer requirement to caller`)"
+ errorLine1=" OPSTR_RAPID_CLEAR_NOTIFICATIONS_BY_LISTENER,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/AppOpsManager.java"
+ line="3061"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `OPSTR_EMERGENCY_LOCATION` is a flagged API and should be inside an `if (Flags.locationBypass())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_LOCATION_BYPASS) to transfer requirement to caller`)"
+ errorLine1=" new AppOpInfo.Builder(OP_EMERGENCY_LOCATION, OPSTR_EMERGENCY_LOCATION, "EMERGENCY_LOCATION")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/AppOpsManager.java"
+ line="3077"
+ column="54"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `OPSTR_RECEIVE_SENSITIVE_NOTIFICATIONS` is a flagged API and should be inside an `if (Flags.redactSensitiveNotificationsFromUntrustedListeners())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_REDACT_SENSITIVE_NOTIFICATIONS_FROM_UNTRUSTED_LISTENERS) to transfer requirement to caller`)"
+ errorLine1=" OPSTR_RECEIVE_SENSITIVE_NOTIFICATIONS, "RECEIVE_SENSITIVE_NOTIFICATIONS")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/AppOpsManager.java"
+ line="3083"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `PERSISTENT_DEVICE_ID_DEFAULT` is a flagged API and should be inside an `if (Flags.persistentDeviceIdApi())` check (or annotate the surrounding method `OpEventProxyInfo` with `@FlaggedApi(Flags.FLAG_PERSISTENT_DEVICE_ID_API) to transfer requirement to caller`)"
+ errorLine1=" VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/AppOpsManager.java"
+ line="3550"
+ column="42"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `PERSISTENT_DEVICE_ID_DEFAULT` is a flagged API and should be inside an `if (Flags.persistentDeviceIdApi())` check (or annotate the surrounding method `onOpChanged` with `@FlaggedApi(Flags.FLAG_PERSISTENT_DEVICE_ID_API) to transfer requirement to caller`)"
+ errorLine1=" VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT)) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/AppOpsManager.java"
+ line="7483"
+ column="42"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `PERSISTENT_DEVICE_ID_DEFAULT` is a flagged API and should be inside an `if (Flags.persistentDeviceIdApi())` check (or annotate the surrounding method `getPackagesForOps` with `@FlaggedApi(Flags.FLAG_PERSISTENT_DEVICE_ID_API) to transfer requirement to caller`)"
+ errorLine1=" VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/AppOpsManager.java"
+ line="7891"
+ column="42"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getDeviceId()` is a flagged API and should be inside an `if (Flags.deviceAwarePermissionApisEnabled())` check (or annotate the surrounding method `unsafeCheckOpRawNoThrow` with `@FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) to transfer requirement to caller`)"
+ errorLine1=" attributionSource.getPackageName(), attributionSource.getDeviceId());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/AppOpsManager.java"
+ line="8848"
+ column="53"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getDeviceId()` is a flagged API and should be inside an `if (Flags.deviceAwarePermissionApisEnabled())` check (or annotate the surrounding method `noteOpNoThrow` with `@FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) to transfer requirement to caller`)"
+ errorLine1=" attributionSource.getAttributionTag(), attributionSource.getDeviceId(), message);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/AppOpsManager.java"
+ line="9034"
+ column="56"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getDeviceId()` is a flagged API and should be inside an `if (Flags.deviceAwarePermissionApisEnabled())` check (or annotate the surrounding method `checkOpNoThrow` with `@FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) to transfer requirement to caller`)"
+ errorLine1=" attributionSource.getDeviceId());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/AppOpsManager.java"
+ line="9329"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getDeviceId()` is a flagged API and should be inside an `if (Flags.deviceAwarePermissionApisEnabled())` check (or annotate the surrounding method `startOpNoThrow` with `@FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) to transfer requirement to caller`)"
+ errorLine1=" attributionSource.getAttributionTag(), attributionSource.getDeviceId(),"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/AppOpsManager.java"
+ line="9589"
+ column="56"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getDeviceId()` is a flagged API and should be inside an `if (Flags.deviceAwarePermissionApisEnabled())` check (or annotate the surrounding method `finishOp` with `@FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) to transfer requirement to caller`)"
+ errorLine1=" attributionSource.getDeviceId());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/AppOpsManager.java"
+ line="9842"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `EXTRA_REQUEST_PERMISSIONS_DEVICE_ID` is a flagged API and should be inside an `if (Flags.deviceAwarePermissionApisEnabled())` check (or annotate the surrounding method `buildRequestPermissionsIntent` with `@FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) to transfer requirement to caller`)"
+ errorLine1=" intent.putExtra(EXTRA_REQUEST_PERMISSIONS_DEVICE_ID, mContext.getDeviceId());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/ApplicationPackageManager.java"
+ line="965"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `APP_METADATA_SOURCE_UNKNOWN` is a flagged API and should be inside an `if (Flags.aslInApkAppMetadataSource())` check (or annotate the surrounding method `getAppMetadataSource` with `@FlaggedApi(Flags.FLAG_ASL_IN_APK_APP_METADATA_SOURCE) to transfer requirement to caller`)"
+ errorLine1=" int source = PackageManager.APP_METADATA_SOURCE_UNKNOWN;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/ApplicationPackageManager.java"
+ line="1283"
+ column="37"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `isArchived` is a flagged API and should be inside an `if (Flags.archiving())` check (or annotate the surrounding method `loadUnbadgedItemIcon` with `@FlaggedApi(Flags.FLAG_ARCHIVING) to transfer requirement to caller`)"
+ errorLine1=" if (itemInfo.isArchived) {"
+ errorLine2=" ~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/ApplicationPackageManager.java"
+ line="3430"
+ column="26"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `ArchivedPackageInfo()` is a flagged API and should be inside an `if (Flags.archiving())` check (or annotate the surrounding method `getArchivedPackage` with `@FlaggedApi(Flags.FLAG_ARCHIVING) to transfer requirement to caller`)"
+ errorLine1=" return new ArchivedPackageInfo(parcel);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/ApplicationPackageManager.java"
+ line="3995"
+ column="20"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getPendingCredentialRequest()` is a flagged API and should be inside an `if (Flags.autofillCredmanDevIntegration())` check (or annotate the surrounding method `dump` with `@FlaggedApi(Flags.FLAG_AUTOFILL_CREDMAN_DEV_INTEGRATION) to transfer requirement to caller`)"
+ errorLine1=" GetCredentialRequest getCredentialRequest = node.getPendingCredentialRequest();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/assist/AssistStructure.java"
+ line="2657"
+ column="53"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `AttributionSource()` is a flagged API and should be inside an `if (Flags.deviceAwarePermissionApisEnabled())` check (or annotate the surrounding method `AttributionSource` with `@FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) to transfer requirement to caller`)"
+ errorLine1=" this(uid, Process.INVALID_PID, packageName, attributionTag, sDefaultToken, null,"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/core/java/android/content/AttributionSource.java"
+ line="112"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `AttributionSource()` is a flagged API and should be inside an `if (Flags.deviceAwarePermissionApisEnabled())` check (or annotate the surrounding method `AttributionSource` with `@FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) to transfer requirement to caller`)"
+ errorLine1=" this(uid, Process.INVALID_PID, packageName, attributionTag, token,"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/core/java/android/content/AttributionSource.java"
+ line="126"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `AttributionSource()` is a flagged API and should be inside an `if (Flags.deviceAwarePermissionApisEnabled())` check (or annotate the surrounding method `AttributionSource` with `@FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) to transfer requirement to caller`)"
+ errorLine1=" this(uid, pid, packageName, attributionTag, token, /*renouncedPermissions*/ null,"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/core/java/android/content/AttributionSource.java"
+ line="133"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `AttributionSource()` is a flagged API and should be inside an `if (Flags.deviceAwarePermissionApisEnabled())` check (or annotate the surrounding method `AttributionSource` with `@FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) to transfer requirement to caller`)"
+ errorLine1=" this(uid, Process.INVALID_PID, packageName, attributionTag, sDefaultToken,"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/core/java/android/content/AttributionSource.java"
+ line="142"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `AttributionSource()` is a flagged API and should be inside an `if (Flags.deviceAwarePermissionApisEnabled())` check (or annotate the surrounding method `AttributionSource` with `@FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) to transfer requirement to caller`)"
+ errorLine1=" this(current.getUid(), current.getPid(), current.getPackageName(),"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/core/java/android/content/AttributionSource.java"
+ line="150"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getDeviceId()` is a flagged API and should be inside an `if (Flags.deviceAwarePermissionApisEnabled())` check (or annotate the surrounding method `AttributionSource` with `@FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) to transfer requirement to caller`)"
+ errorLine1=" current.mAttributionSourceState.renouncedPermissions, current.getDeviceId(), next);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/content/AttributionSource.java"
+ line="152"
+ column="71"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `AttributionSource()` is a flagged API and should be inside an `if (Flags.deviceAwarePermissionApisEnabled())` check (or annotate the surrounding method `AttributionSource` with `@FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) to transfer requirement to caller`)"
+ errorLine1=" this(uid, pid, packageName, attributionTag, sDefaultToken, renouncedPermissions, deviceId,"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/core/java/android/content/AttributionSource.java"
+ line="159"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `AttributionSource()` is a flagged API and should be inside an `if (Flags.deviceAwarePermissionApisEnabled())` check (or annotate the surrounding method `withNextAttributionSource` with `@FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) to transfer requirement to caller`)"
+ errorLine1=" return new AttributionSource(getUid(), getPid(), getPackageName(), getAttributionTag(),"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/core/java/android/content/AttributionSource.java"
+ line="212"
+ column="16"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getDeviceId()` is a flagged API and should be inside an `if (Flags.deviceAwarePermissionApisEnabled())` check (or annotate the surrounding method `withNextAttributionSource` with `@FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) to transfer requirement to caller`)"
+ errorLine1=" getToken(), mAttributionSourceState.renouncedPermissions, getDeviceId(), next);"
+ errorLine2=" ~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/content/AttributionSource.java"
+ line="213"
+ column="75"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `AttributionSource()` is a flagged API and should be inside an `if (Flags.deviceAwarePermissionApisEnabled())` check (or annotate the surrounding method `withPackageName` with `@FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) to transfer requirement to caller`)"
+ errorLine1=" return new AttributionSource(getUid(), getPid(), packageName, getAttributionTag(),"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/core/java/android/content/AttributionSource.java"
+ line="218"
+ column="16"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getDeviceId()` is a flagged API and should be inside an `if (Flags.deviceAwarePermissionApisEnabled())` check (or annotate the surrounding method `withPackageName` with `@FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) to transfer requirement to caller`)"
+ errorLine1=" getToken(), mAttributionSourceState.renouncedPermissions, getDeviceId(), getNext());"
+ errorLine2=" ~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/content/AttributionSource.java"
+ line="219"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `AttributionSource()` is a flagged API and should be inside an `if (Flags.deviceAwarePermissionApisEnabled())` check (or annotate the surrounding method `withToken` with `@FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) to transfer requirement to caller`)"
+ errorLine1=" return new AttributionSource(getUid(), getPid(), getPackageName(), getAttributionTag(),"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/core/java/android/content/AttributionSource.java"
+ line="224"
+ column="16"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getDeviceId()` is a flagged API and should be inside an `if (Flags.deviceAwarePermissionApisEnabled())` check (or annotate the surrounding method `withToken` with `@FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) to transfer requirement to caller`)"
+ errorLine1=" token, mAttributionSourceState.renouncedPermissions, getDeviceId(), getNext());"
+ errorLine2=" ~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/content/AttributionSource.java"
+ line="225"
+ column="70"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `AttributionSource()` is a flagged API and should be inside an `if (Flags.deviceAwarePermissionApisEnabled())` check (or annotate the surrounding method `withPid` with `@FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) to transfer requirement to caller`)"
+ errorLine1=" return new AttributionSource(getUid(), pid, getPackageName(), getAttributionTag(),"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/core/java/android/content/AttributionSource.java"
+ line="235"
+ column="16"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getDeviceId()` is a flagged API and should be inside an `if (Flags.deviceAwarePermissionApisEnabled())` check (or annotate the surrounding method `withPid` with `@FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) to transfer requirement to caller`)"
+ errorLine1=" getToken(), mAttributionSourceState.renouncedPermissions, getDeviceId(), getNext());"
+ errorLine2=" ~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/content/AttributionSource.java"
+ line="236"
+ column="75"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `AttributionSource()` is a flagged API and should be inside an `if (Flags.deviceAwarePermissionApisEnabled())` check (or annotate the surrounding method `withDeviceId` with `@FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) to transfer requirement to caller`)"
+ errorLine1=" return new AttributionSource(getUid(), getPid(), getPackageName(), getAttributionTag(),"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/core/java/android/content/AttributionSource.java"
+ line="241"
+ column="16"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `setDeviceId()` is a flagged API and should be inside an `if (Flags.deviceAwarePermissionApisEnabled())` check (or annotate the surrounding method `myAttributionSource` with `@FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) to transfer requirement to caller`)"
+ errorLine1=" return new AttributionSource.Builder(uid)"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/core/java/android/content/AttributionSource.java"
+ line="284"
+ column="20"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `isRegisteredAttributionSource()` is a flagged API and should be inside an `if (Flags.shouldRegisterAttributionSource())` check (or annotate the surrounding method `isTrusted` with `@FlaggedApi(Flags.FLAG_SHOULD_REGISTER_ATTRIBUTION_SOURCE) to transfer requirement to caller`)"
+ errorLine1=" && context.getSystemService(PermissionManager.class)"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/core/java/android/content/AttributionSource.java"
+ line="487"
+ column="20"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `isResumed()` is a flagged API and should be inside an `if (Flags.enableNfcMainline())` check (or annotate the surrounding method `isDisablingEnterExitEventForAutofill` with `@FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) to transfer requirement to caller`)"
+ errorLine1=" return mAutoFillIgnoreFirstResumePause || !mActivity.isResumed();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/autofill/AutofillClientController.java"
+ line="473"
+ column="52"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `FIELD_NAME` is a flagged API and should be inside an `if (Flags.modesApi())` check (or annotate the surrounding method `fieldsToString` with `@FlaggedApi(Flags.FLAG_MODES_API) to transfer requirement to caller`)"
+ errorLine1=" if ((bitmask & FIELD_NAME) != 0) {"
+ errorLine2=" ~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/AutomaticZenRule.java"
+ line="582"
+ column="24"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `FIELD_INTERRUPTION_FILTER` is a flagged API and should be inside an `if (Flags.modesApi())` check (or annotate the surrounding method `fieldsToString` with `@FlaggedApi(Flags.FLAG_MODES_API) to transfer requirement to caller`)"
+ errorLine1=" if ((bitmask & FIELD_INTERRUPTION_FILTER) != 0) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/AutomaticZenRule.java"
+ line="585"
+ column="24"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `FIELD_ICON` is a flagged API and should be inside an `if (Flags.modesApi())` check (or annotate the surrounding method `fieldsToString` with `@FlaggedApi(Flags.FLAG_MODES_API) to transfer requirement to caller`)"
+ errorLine1=" if ((bitmask & FIELD_ICON) != 0) {"
+ errorLine2=" ~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/AutomaticZenRule.java"
+ line="588"
+ column="24"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getFrameTimeNanos()` is a flagged API and should be inside an `if (Flags.expectedPresentationTimeApi())` check (or annotate the surrounding method `run` with `@FlaggedApi(Flags.FLAG_EXPECTED_PRESENTATION_TIME_API) to transfer requirement to caller`)"
+ errorLine1=" doConsumeBatchedInput(mChoreographer.getFrameTimeNanos());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/BatchedInputEventReceiver.java"
+ line="130"
+ column="39"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `Gainmap()` is a flagged API and should be inside an `if (Flags.gainmapConstructorWithMetadata())` check (or annotate the surrounding method `createBitmap` with `@FlaggedApi(Flags.FLAG_GAINMAP_CONSTRUCTOR_WITH_METADATA) to transfer requirement to caller`)"
+ errorLine1=" bitmap.setGainmap(new Gainmap(source.getGainmap(), newMapContents));"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/graphics/java/android/graphics/Bitmap.java"
+ line="1030"
+ column="35"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `Gainmap()` is a flagged API and should be inside an `if (Flags.gainmapConstructorWithMetadata())` check (or annotate the surrounding method `setOverrideGainmap` with `@FlaggedApi(Flags.FLAG_GAINMAP_CONSTRUCTOR_WITH_METADATA) to transfer requirement to caller`)"
+ errorLine1=" mOverrideGainmap = new Gainmap(overrideGainmap, overrideGainmap.getGainmapContents());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/graphics/java/android/graphics/BitmapShader.java"
+ line="193"
+ column="32"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `set()` is a flagged API and should be inside an `if (Flags.fixLineHeightForLocale())` check (or annotate the surrounding method `isBoring` with `@FlaggedApi(Flags.FLAG_FIX_LINE_HEIGHT_FOR_LOCALE) to transfer requirement to caller`)"
+ errorLine1=" fm.set(minimumFontMetrics);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/text/BoringLayout.java"
+ line="594"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getUseBoundsForWidth()` is a flagged API and should be inside an `if (Flags.useBoundsForWidth())` check (or annotate the surrounding method `getLineMax` with `@FlaggedApi(Flags.FLAG_USE_BOUNDS_FOR_WIDTH) to transfer requirement to caller`)"
+ errorLine1=" if (getUseBoundsForWidth()) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/text/BoringLayout.java"
+ line="658"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getUseBoundsForWidth()` is a flagged API and should be inside an `if (Flags.useBoundsForWidth())` check (or annotate the surrounding method `getLineWidth` with `@FlaggedApi(Flags.FLAG_USE_BOUNDS_FOR_WIDTH) to transfer requirement to caller`)"
+ errorLine1=" if (getUseBoundsForWidth()) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/text/BoringLayout.java"
+ line="667"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getShiftDrawingOffsetForStartOverhang()` is a flagged API and should be inside an `if (Flags.useBoundsForWidth())` check (or annotate the surrounding method `draw` with `@FlaggedApi(Flags.FLAG_USE_BOUNDS_FOR_WIDTH) to transfer requirement to caller`)"
+ errorLine1=" if (getUseBoundsForWidth() && getShiftDrawingOffsetForStartOverhang()) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/text/BoringLayout.java"
+ line="720"
+ column="43"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getUseBoundsForWidth()` is a flagged API and should be inside an `if (Flags.useBoundsForWidth())` check (or annotate the surrounding method `draw` with `@FlaggedApi(Flags.FLAG_USE_BOUNDS_FOR_WIDTH) to transfer requirement to caller`)"
+ errorLine1=" if (getUseBoundsForWidth() && getShiftDrawingOffsetForStartOverhang()) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/text/BoringLayout.java"
+ line="720"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `createFromParcelBody()` is a flagged API and should be inside an `if (Flags.tiafVApis())` check (or annotate the surrounding method `createFromParcel` with `@FlaggedApi(Flags.FLAG_TIAF_V_APIS) to transfer requirement to caller`)"
+ errorLine1=" return SignalingDataRequest.createFromParcelBody(source);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/media/java/android/media/tv/BroadcastInfoRequest.java"
+ line="89"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `createFromParcelBody()` is a flagged API and should be inside an `if (Flags.tiafVApis())` check (or annotate the surrounding method `createFromParcel` with `@FlaggedApi(Flags.FLAG_TIAF_V_APIS) to transfer requirement to caller`)"
+ errorLine1=" return SignalingDataResponse.createFromParcelBody(source);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/media/java/android/media/tv/BroadcastInfoResponse.java"
+ line="75"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `BUGREPORT_MODE_ONBOARDING` is a flagged API and should be inside an `if (Flags.onboardingBugreportV2Enabled())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_ONBOARDING_BUGREPORT_V2_ENABLED) to transfer requirement to caller`)"
+ errorLine1=" public static final int BUGREPORT_MODE_MAX_VALUE = BUGREPORT_MODE_ONBOARDING;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/os/BugreportParams.java"
+ line="139"
+ column="56"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `PROPERTY_IS_TRANSACTIONAL` is a flagged API and should be inside an `if (Flags.voipAppActionsSupport())` check (or annotate the surrounding method `propertiesToString` with `@FlaggedApi(Flags.FLAG_VOIP_APP_ACTIONS_SUPPORT) to transfer requirement to caller`)"
+ errorLine1=" if (hasProperty(properties, PROPERTY_IS_TRANSACTIONAL)) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telecomm/java/android/telecom/Call.java"
+ line="854"
+ column="41"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getImsReasonInfo()` is a flagged API and should be inside an `if (Flags.telecomResolveHiddenDependencies())` check (or annotate the surrounding method `handleCallDisconnected` with `@FlaggedApi(Flags.FLAG_TELECOM_RESOLVE_HIDDEN_DEPENDENCIES) to transfer requirement to caller`)"
+ errorLine1=" if (disconnectCause.getImsReasonInfo() != null) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telecomm/java/android/telecom/CallDiagnosticService.java"
+ line="365"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getImsReasonInfo()` is a flagged API and should be inside an `if (Flags.telecomResolveHiddenDependencies())` check (or annotate the surrounding method `handleCallDisconnected` with `@FlaggedApi(Flags.FLAG_TELECOM_RESOLVE_HIDDEN_DEPENDENCIES) to transfer requirement to caller`)"
+ errorLine1=" message = callDiagnostics.onCallDisconnected(disconnectCause.getImsReasonInfo());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telecomm/java/android/telecom/CallDiagnosticService.java"
+ line="366"
+ column="58"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getTelephonyDisconnectCause()` is a flagged API and should be inside an `if (Flags.telecomResolveHiddenDependencies())` check (or annotate the surrounding method `handleCallDisconnected` with `@FlaggedApi(Flags.FLAG_TELECOM_RESOLVE_HIDDEN_DEPENDENCIES) to transfer requirement to caller`)"
+ errorLine1=" disconnectCause.getTelephonyDisconnectCause(),"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telecomm/java/android/telecom/CallDiagnosticService.java"
+ line="369"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getTelephonyPreciseDisconnectCause()` is a flagged API and should be inside an `if (Flags.telecomResolveHiddenDependencies())` check (or annotate the surrounding method `handleCallDisconnected` with `@FlaggedApi(Flags.FLAG_TELECOM_RESOLVE_HIDDEN_DEPENDENCIES) to transfer requirement to caller`)"
+ errorLine1=" disconnectCause.getTelephonyPreciseDisconnectCause());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telecomm/java/android/telecom/CallDiagnosticService.java"
+ line="370"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `POLICY_TYPE_CAMERA` is a flagged API and should be inside an `if (Flags.virtualCamera())` check (or annotate the surrounding method `getDevicePolicyFromContext` with `@FlaggedApi(Flags.FLAG_VIRTUAL_CAMERA) to transfer requirement to caller`)"
+ errorLine1=" return virtualDeviceManager.getDevicePolicy(context.getDeviceId(), POLICY_TYPE_CAMERA);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/hardware/Camera.java"
+ line="350"
+ column="76"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `FALLBACK_PACKAGE_NAME` is a flagged API and should be inside an `if (Flags.concertMode())` check (or annotate the surrounding method `onSuccess` with `@FlaggedApi(Flags.FLAG_CONCERT_MODE) to transfer requirement to caller`)"
+ errorLine1=" .getString(FALLBACK_PACKAGE_NAME);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java"
+ line="591"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `POLICY_TYPE_CAMERA` is a flagged API and should be inside an `if (Flags.virtualCamera())` check (or annotate the surrounding method `getDevicePolicyFromContext` with `@FlaggedApi(Flags.FLAG_VIRTUAL_CAMERA) to transfer requirement to caller`)"
+ errorLine1=" return mVirtualDeviceManager.getDevicePolicy(context.getDeviceId(), POLICY_TYPE_CAMERA);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/hardware/camera2/CameraManager.java"
+ line="584"
+ column="77"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `CameraDeviceSetupImpl()` is a flagged API and should be inside an `if (Flags.cameraDeviceSetup())` check (or annotate the surrounding method `getCameraDeviceSetupUnsafe` with `@FlaggedApi(Flags.FLAG_CAMERA_DEVICE_SETUP) to transfer requirement to caller`)"
+ errorLine1=" return new CameraDeviceSetupImpl(cameraId, /*cameraManager=*/ this, mContext);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/hardware/camera2/CameraManager.java"
+ line="903"
+ column="16"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `isCameraDeviceSetupSupported()` is a flagged API and should be inside an `if (Flags.cameraDeviceSetup())` check (or annotate the surrounding method `openCameraDeviceUserAsync` with `@FlaggedApi(Flags.FLAG_CAMERA_DEVICE_SETUP) to transfer requirement to caller`)"
+ errorLine1=" && CameraDeviceSetupImpl.isCameraDeviceSetupSupported(characteristics)) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/hardware/camera2/CameraManager.java"
+ line="983"
+ column="24"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Class `DeviceStateManager` is a flagged API and should be inside an `if (Flags.deviceStatePropertyApi())` check (or annotate the surrounding method `registerDeviceStateListener` with `@FlaggedApi(Flags.FLAG_DEVICE_STATE_PROPERTY_API) to transfer requirement to caller`)"
+ errorLine1=" ctx.getSystemService(DeviceStateManager.class).registerCallback("
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/hardware/camera2/CameraManager.java"
+ line="2141"
+ column="46"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `registerCallback()` is a flagged API and should be inside an `if (Flags.deviceStatePropertyApi())` check (or annotate the surrounding method `registerDeviceStateListener` with `@FlaggedApi(Flags.FLAG_DEVICE_STATE_PROPERTY_API) to transfer requirement to caller`)"
+ errorLine1=" ctx.getSystemService(DeviceStateManager.class).registerCallback("
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/core/java/android/hardware/camera2/CameraManager.java"
+ line="2141"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `STATISTICS_LENS_INTRINSICS_SAMPLES` is a flagged API and should be inside an `if (Flags.concertMode())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_CONCERT_MODE) to transfer requirement to caller`)"
+ errorLine1=" CaptureResult.STATISTICS_LENS_INTRINSICS_SAMPLES.getNativeKey(),"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/hardware/camera2/impl/CameraMetadataNative.java"
+ line="856"
+ column="31"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `STATISTICS_LENS_INTRINSICS_SAMPLES` is a flagged API and should be inside an `if (Flags.concertMode())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_CONCERT_MODE) to transfer requirement to caller`)"
+ errorLine1=" CaptureResult.STATISTICS_LENS_INTRINSICS_SAMPLES.getNativeKey(),"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/hardware/camera2/impl/CameraMetadataNative.java"
+ line="2021"
+ column="31"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `KEY_EMERGENCY_OVER_IMS_SUPPORTED_3GPP_NETWORK_TYPES_INT_ARRAY` is a flagged API and should be inside an `if (Flags.useOemDomainSelectionService())` check (or annotate the surrounding method `getDefaults` with `@FlaggedApi(Flags.FLAG_USE_OEM_DOMAIN_SELECTION_SERVICE) to transfer requirement to caller`)"
+ errorLine1=" KEY_EMERGENCY_OVER_IMS_SUPPORTED_3GPP_NETWORK_TYPES_INT_ARRAY,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/CarrierConfigManager.java"
+ line="8054"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `KEY_EMERGENCY_OVER_IMS_ROAMING_SUPPORTED_3GPP_NETWORK_TYPES_INT_ARRAY` is a flagged API and should be inside an `if (Flags.useOemDomainSelectionService())` check (or annotate the surrounding method `getDefaults` with `@FlaggedApi(Flags.FLAG_USE_OEM_DOMAIN_SELECTION_SERVICE) to transfer requirement to caller`)"
+ errorLine1=" KEY_EMERGENCY_OVER_IMS_ROAMING_SUPPORTED_3GPP_NETWORK_TYPES_INT_ARRAY,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/CarrierConfigManager.java"
+ line="8060"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `KEY_EMERGENCY_OVER_CS_SUPPORTED_ACCESS_NETWORK_TYPES_INT_ARRAY` is a flagged API and should be inside an `if (Flags.useOemDomainSelectionService())` check (or annotate the surrounding method `getDefaults` with `@FlaggedApi(Flags.FLAG_USE_OEM_DOMAIN_SELECTION_SERVICE) to transfer requirement to caller`)"
+ errorLine1=" KEY_EMERGENCY_OVER_CS_SUPPORTED_ACCESS_NETWORK_TYPES_INT_ARRAY,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/CarrierConfigManager.java"
+ line="8066"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `KEY_EMERGENCY_OVER_CS_ROAMING_SUPPORTED_ACCESS_NETWORK_TYPES_INT_ARRAY` is a flagged API and should be inside an `if (Flags.useOemDomainSelectionService())` check (or annotate the surrounding method `getDefaults` with `@FlaggedApi(Flags.FLAG_USE_OEM_DOMAIN_SELECTION_SERVICE) to transfer requirement to caller`)"
+ errorLine1=" KEY_EMERGENCY_OVER_CS_ROAMING_SUPPORTED_ACCESS_NETWORK_TYPES_INT_ARRAY,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/CarrierConfigManager.java"
+ line="8073"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `KEY_EMERGENCY_DOMAIN_PREFERENCE_INT_ARRAY` is a flagged API and should be inside an `if (Flags.useOemDomainSelectionService())` check (or annotate the surrounding method `getDefaults` with `@FlaggedApi(Flags.FLAG_USE_OEM_DOMAIN_SELECTION_SERVICE) to transfer requirement to caller`)"
+ errorLine1=" defaults.putIntArray(KEY_EMERGENCY_DOMAIN_PREFERENCE_INT_ARRAY,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/CarrierConfigManager.java"
+ line="8079"
+ column="34"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `DOMAIN_PS_3GPP` is a flagged API and should be inside an `if (Flags.useOemDomainSelectionService())` check (or annotate the surrounding method `getDefaults` with `@FlaggedApi(Flags.FLAG_USE_OEM_DOMAIN_SELECTION_SERVICE) to transfer requirement to caller`)"
+ errorLine1=" DOMAIN_PS_3GPP,"
+ errorLine2=" ~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/CarrierConfigManager.java"
+ line="8081"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `DOMAIN_CS` is a flagged API and should be inside an `if (Flags.useOemDomainSelectionService())` check (or annotate the surrounding method `getDefaults` with `@FlaggedApi(Flags.FLAG_USE_OEM_DOMAIN_SELECTION_SERVICE) to transfer requirement to caller`)"
+ errorLine1=" DOMAIN_CS,"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/CarrierConfigManager.java"
+ line="8082"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `DOMAIN_PS_NON_3GPP` is a flagged API and should be inside an `if (Flags.useOemDomainSelectionService())` check (or annotate the surrounding method `getDefaults` with `@FlaggedApi(Flags.FLAG_USE_OEM_DOMAIN_SELECTION_SERVICE) to transfer requirement to caller`)"
+ errorLine1=" DOMAIN_PS_NON_3GPP"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/CarrierConfigManager.java"
+ line="8083"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `KEY_EMERGENCY_DOMAIN_PREFERENCE_ROAMING_INT_ARRAY` is a flagged API and should be inside an `if (Flags.useOemDomainSelectionService())` check (or annotate the surrounding method `getDefaults` with `@FlaggedApi(Flags.FLAG_USE_OEM_DOMAIN_SELECTION_SERVICE) to transfer requirement to caller`)"
+ errorLine1=" defaults.putIntArray(KEY_EMERGENCY_DOMAIN_PREFERENCE_ROAMING_INT_ARRAY,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/CarrierConfigManager.java"
+ line="8085"
+ column="34"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `DOMAIN_PS_3GPP` is a flagged API and should be inside an `if (Flags.useOemDomainSelectionService())` check (or annotate the surrounding method `getDefaults` with `@FlaggedApi(Flags.FLAG_USE_OEM_DOMAIN_SELECTION_SERVICE) to transfer requirement to caller`)"
+ errorLine1=" DOMAIN_PS_3GPP,"
+ errorLine2=" ~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/CarrierConfigManager.java"
+ line="8087"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `DOMAIN_CS` is a flagged API and should be inside an `if (Flags.useOemDomainSelectionService())` check (or annotate the surrounding method `getDefaults` with `@FlaggedApi(Flags.FLAG_USE_OEM_DOMAIN_SELECTION_SERVICE) to transfer requirement to caller`)"
+ errorLine1=" DOMAIN_CS,"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/CarrierConfigManager.java"
+ line="8088"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `DOMAIN_PS_NON_3GPP` is a flagged API and should be inside an `if (Flags.useOemDomainSelectionService())` check (or annotate the surrounding method `getDefaults` with `@FlaggedApi(Flags.FLAG_USE_OEM_DOMAIN_SELECTION_SERVICE) to transfer requirement to caller`)"
+ errorLine1=" DOMAIN_PS_NON_3GPP"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/CarrierConfigManager.java"
+ line="8089"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `KEY_PREFER_IMS_EMERGENCY_WHEN_VOICE_CALLS_ON_CS_BOOL` is a flagged API and should be inside an `if (Flags.useOemDomainSelectionService())` check (or annotate the surrounding method `getDefaults` with `@FlaggedApi(Flags.FLAG_USE_OEM_DOMAIN_SELECTION_SERVICE) to transfer requirement to caller`)"
+ errorLine1=" defaults.putBoolean(KEY_PREFER_IMS_EMERGENCY_WHEN_VOICE_CALLS_ON_CS_BOOL, false);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/CarrierConfigManager.java"
+ line="8092"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `KEY_EMERGENCY_VOWIFI_REQUIRES_CONDITION_INT` is a flagged API and should be inside an `if (Flags.useOemDomainSelectionService())` check (or annotate the surrounding method `getDefaults` with `@FlaggedApi(Flags.FLAG_USE_OEM_DOMAIN_SELECTION_SERVICE) to transfer requirement to caller`)"
+ errorLine1=" defaults.putInt(KEY_EMERGENCY_VOWIFI_REQUIRES_CONDITION_INT, VOWIFI_REQUIRES_NONE);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/CarrierConfigManager.java"
+ line="8093"
+ column="29"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `VOWIFI_REQUIRES_NONE` is a flagged API and should be inside an `if (Flags.useOemDomainSelectionService())` check (or annotate the surrounding method `getDefaults` with `@FlaggedApi(Flags.FLAG_USE_OEM_DOMAIN_SELECTION_SERVICE) to transfer requirement to caller`)"
+ errorLine1=" defaults.putInt(KEY_EMERGENCY_VOWIFI_REQUIRES_CONDITION_INT, VOWIFI_REQUIRES_NONE);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/CarrierConfigManager.java"
+ line="8093"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `KEY_MAXIMUM_NUMBER_OF_EMERGENCY_TRIES_OVER_VOWIFI_INT` is a flagged API and should be inside an `if (Flags.useOemDomainSelectionService())` check (or annotate the surrounding method `getDefaults` with `@FlaggedApi(Flags.FLAG_USE_OEM_DOMAIN_SELECTION_SERVICE) to transfer requirement to caller`)"
+ errorLine1=" defaults.putInt(KEY_MAXIMUM_NUMBER_OF_EMERGENCY_TRIES_OVER_VOWIFI_INT, 1);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/CarrierConfigManager.java"
+ line="8094"
+ column="29"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `KEY_EMERGENCY_SCAN_TIMER_SEC_INT` is a flagged API and should be inside an `if (Flags.useOemDomainSelectionService())` check (or annotate the surrounding method `getDefaults` with `@FlaggedApi(Flags.FLAG_USE_OEM_DOMAIN_SELECTION_SERVICE) to transfer requirement to caller`)"
+ errorLine1=" defaults.putInt(KEY_EMERGENCY_SCAN_TIMER_SEC_INT, 10);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/CarrierConfigManager.java"
+ line="8095"
+ column="29"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `KEY_MAXIMUM_CELLULAR_SEARCH_TIMER_SEC_INT` is a flagged API and should be inside an `if (Flags.useOemDomainSelectionService())` check (or annotate the surrounding method `getDefaults` with `@FlaggedApi(Flags.FLAG_USE_OEM_DOMAIN_SELECTION_SERVICE) to transfer requirement to caller`)"
+ errorLine1=" defaults.putInt(KEY_MAXIMUM_CELLULAR_SEARCH_TIMER_SEC_INT, REDIAL_TIMER_DISABLED);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/CarrierConfigManager.java"
+ line="8096"
+ column="29"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `REDIAL_TIMER_DISABLED` is a flagged API and should be inside an `if (Flags.useOemDomainSelectionService())` check (or annotate the surrounding method `getDefaults` with `@FlaggedApi(Flags.FLAG_USE_OEM_DOMAIN_SELECTION_SERVICE) to transfer requirement to caller`)"
+ errorLine1=" defaults.putInt(KEY_MAXIMUM_CELLULAR_SEARCH_TIMER_SEC_INT, REDIAL_TIMER_DISABLED);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/CarrierConfigManager.java"
+ line="8096"
+ column="72"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `KEY_EMERGENCY_NETWORK_SCAN_TYPE_INT` is a flagged API and should be inside an `if (Flags.useOemDomainSelectionService())` check (or annotate the surrounding method `getDefaults` with `@FlaggedApi(Flags.FLAG_USE_OEM_DOMAIN_SELECTION_SERVICE) to transfer requirement to caller`)"
+ errorLine1=" defaults.putInt(KEY_EMERGENCY_NETWORK_SCAN_TYPE_INT, SCAN_TYPE_NO_PREFERENCE);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/CarrierConfigManager.java"
+ line="8097"
+ column="29"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `SCAN_TYPE_NO_PREFERENCE` is a flagged API and should be inside an `if (Flags.useOemDomainSelectionService())` check (or annotate the surrounding method `getDefaults` with `@FlaggedApi(Flags.FLAG_USE_OEM_DOMAIN_SELECTION_SERVICE) to transfer requirement to caller`)"
+ errorLine1=" defaults.putInt(KEY_EMERGENCY_NETWORK_SCAN_TYPE_INT, SCAN_TYPE_NO_PREFERENCE);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/CarrierConfigManager.java"
+ line="8097"
+ column="66"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `KEY_EMERGENCY_CALL_SETUP_TIMER_ON_CURRENT_NETWORK_SEC_INT` is a flagged API and should be inside an `if (Flags.useOemDomainSelectionService())` check (or annotate the surrounding method `getDefaults` with `@FlaggedApi(Flags.FLAG_USE_OEM_DOMAIN_SELECTION_SERVICE) to transfer requirement to caller`)"
+ errorLine1=" defaults.putInt(KEY_EMERGENCY_CALL_SETUP_TIMER_ON_CURRENT_NETWORK_SEC_INT, 0);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/CarrierConfigManager.java"
+ line="8098"
+ column="29"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `KEY_EMERGENCY_REQUIRES_IMS_REGISTRATION_BOOL` is a flagged API and should be inside an `if (Flags.useOemDomainSelectionService())` check (or annotate the surrounding method `getDefaults` with `@FlaggedApi(Flags.FLAG_USE_OEM_DOMAIN_SELECTION_SERVICE) to transfer requirement to caller`)"
+ errorLine1=" defaults.putBoolean(KEY_EMERGENCY_REQUIRES_IMS_REGISTRATION_BOOL, false);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/CarrierConfigManager.java"
+ line="8099"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `KEY_EMERGENCY_LTE_PREFERRED_AFTER_NR_FAILED_BOOL` is a flagged API and should be inside an `if (Flags.useOemDomainSelectionService())` check (or annotate the surrounding method `getDefaults` with `@FlaggedApi(Flags.FLAG_USE_OEM_DOMAIN_SELECTION_SERVICE) to transfer requirement to caller`)"
+ errorLine1=" defaults.putBoolean(KEY_EMERGENCY_LTE_PREFERRED_AFTER_NR_FAILED_BOOL, false);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/CarrierConfigManager.java"
+ line="8100"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `KEY_EMERGENCY_REQUIRES_VOLTE_ENABLED_BOOL` is a flagged API and should be inside an `if (Flags.useOemDomainSelectionService())` check (or annotate the surrounding method `getDefaults` with `@FlaggedApi(Flags.FLAG_USE_OEM_DOMAIN_SELECTION_SERVICE) to transfer requirement to caller`)"
+ errorLine1=" defaults.putBoolean(KEY_EMERGENCY_REQUIRES_VOLTE_ENABLED_BOOL, false);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/CarrierConfigManager.java"
+ line="8101"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `KEY_EMERGENCY_CDMA_PREFERRED_NUMBERS_STRING_ARRAY` is a flagged API and should be inside an `if (Flags.useOemDomainSelectionService())` check (or annotate the surrounding method `getDefaults` with `@FlaggedApi(Flags.FLAG_USE_OEM_DOMAIN_SELECTION_SERVICE) to transfer requirement to caller`)"
+ errorLine1=" defaults.putStringArray(KEY_EMERGENCY_CDMA_PREFERRED_NUMBERS_STRING_ARRAY,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/CarrierConfigManager.java"
+ line="8102"
+ column="37"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `KEY_CROSS_STACK_REDIAL_TIMER_SEC_INT` is a flagged API and should be inside an `if (Flags.useOemDomainSelectionService())` check (or annotate the surrounding method `getDefaults` with `@FlaggedApi(Flags.FLAG_USE_OEM_DOMAIN_SELECTION_SERVICE) to transfer requirement to caller`)"
+ errorLine1=" defaults.putInt(KEY_CROSS_STACK_REDIAL_TIMER_SEC_INT, 120);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/CarrierConfigManager.java"
+ line="8104"
+ column="29"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `KEY_QUICK_CROSS_STACK_REDIAL_TIMER_SEC_INT` is a flagged API and should be inside an `if (Flags.useOemDomainSelectionService())` check (or annotate the surrounding method `getDefaults` with `@FlaggedApi(Flags.FLAG_USE_OEM_DOMAIN_SELECTION_SERVICE) to transfer requirement to caller`)"
+ errorLine1=" defaults.putInt(KEY_QUICK_CROSS_STACK_REDIAL_TIMER_SEC_INT, REDIAL_TIMER_DISABLED);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/CarrierConfigManager.java"
+ line="8105"
+ column="29"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `REDIAL_TIMER_DISABLED` is a flagged API and should be inside an `if (Flags.useOemDomainSelectionService())` check (or annotate the surrounding method `getDefaults` with `@FlaggedApi(Flags.FLAG_USE_OEM_DOMAIN_SELECTION_SERVICE) to transfer requirement to caller`)"
+ errorLine1=" defaults.putInt(KEY_QUICK_CROSS_STACK_REDIAL_TIMER_SEC_INT, REDIAL_TIMER_DISABLED);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/CarrierConfigManager.java"
+ line="8105"
+ column="73"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `KEY_START_QUICK_CROSS_STACK_REDIAL_TIMER_WHEN_REGISTERED_BOOL` is a flagged API and should be inside an `if (Flags.useOemDomainSelectionService())` check (or annotate the surrounding method `getDefaults` with `@FlaggedApi(Flags.FLAG_USE_OEM_DOMAIN_SELECTION_SERVICE) to transfer requirement to caller`)"
+ errorLine1=" defaults.putBoolean(KEY_START_QUICK_CROSS_STACK_REDIAL_TIMER_WHEN_REGISTERED_BOOL,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/CarrierConfigManager.java"
+ line="8106"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `KEY_SCAN_LIMITED_SERVICE_AFTER_VOLTE_FAILURE_BOOL` is a flagged API and should be inside an `if (Flags.useOemDomainSelectionService())` check (or annotate the surrounding method `getDefaults` with `@FlaggedApi(Flags.FLAG_USE_OEM_DOMAIN_SELECTION_SERVICE) to transfer requirement to caller`)"
+ errorLine1=" defaults.putBoolean(KEY_SCAN_LIMITED_SERVICE_AFTER_VOLTE_FAILURE_BOOL, false);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/CarrierConfigManager.java"
+ line="8108"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `KEY_SUPPORTS_IKE_SESSION_MULTIPLE_SA_PROPOSALS_BOOL` is a flagged API and should be inside an `if (Flags.enableMultipleSaProposals())` check (or annotate the surrounding method `getDefaults` with `@FlaggedApi(Flags.FLAG_ENABLE_MULTIPLE_SA_PROPOSALS) to transfer requirement to caller`)"
+ errorLine1=" defaults.putBoolean(KEY_SUPPORTS_IKE_SESSION_MULTIPLE_SA_PROPOSALS_BOOL, false);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/CarrierConfigManager.java"
+ line="9405"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `KEY_SUPPORTS_CHILD_SESSION_MULTIPLE_SA_PROPOSALS_BOOL` is a flagged API and should be inside an `if (Flags.enableMultipleSaProposals())` check (or annotate the surrounding method `getDefaults` with `@FlaggedApi(Flags.FLAG_ENABLE_MULTIPLE_SA_PROPOSALS) to transfer requirement to caller`)"
+ errorLine1=" defaults.putBoolean(KEY_SUPPORTS_CHILD_SESSION_MULTIPLE_SA_PROPOSALS_BOOL, false);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/CarrierConfigManager.java"
+ line="9406"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `KEY_SUPPORTED_IKE_SESSION_AEAD_ALGORITHMS_INT_ARRAY` is a flagged API and should be inside an `if (Flags.enableAeadAlgorithms())` check (or annotate the surrounding method `getDefaults` with `@FlaggedApi(Flags.FLAG_ENABLE_AEAD_ALGORITHMS) to transfer requirement to caller`)"
+ errorLine1=" KEY_SUPPORTED_IKE_SESSION_AEAD_ALGORITHMS_INT_ARRAY, new int[] {});"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/CarrierConfigManager.java"
+ line="9422"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `KEY_SUPPORTED_CHILD_SESSION_AEAD_ALGORITHMS_INT_ARRAY` is a flagged API and should be inside an `if (Flags.enableAeadAlgorithms())` check (or annotate the surrounding method `getDefaults` with `@FlaggedApi(Flags.FLAG_ENABLE_AEAD_ALGORITHMS) to transfer requirement to caller`)"
+ errorLine1=" KEY_SUPPORTED_CHILD_SESSION_AEAD_ALGORITHMS_INT_ARRAY, new int[] {});"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/CarrierConfigManager.java"
+ line="9427"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `KEY_IKE_SESSION_AES_GCM_KEY_SIZE_INT_ARRAY` is a flagged API and should be inside an `if (Flags.enableAeadAlgorithms())` check (or annotate the surrounding method `getDefaults` with `@FlaggedApi(Flags.FLAG_ENABLE_AEAD_ALGORITHMS) to transfer requirement to caller`)"
+ errorLine1=" KEY_IKE_SESSION_AES_GCM_KEY_SIZE_INT_ARRAY, new int[] {});"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/CarrierConfigManager.java"
+ line="9477"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `KEY_CHILD_SESSION_AES_GCM_KEY_SIZE_INT_ARRAY` is a flagged API and should be inside an `if (Flags.enableAeadAlgorithms())` check (or annotate the surrounding method `getDefaults` with `@FlaggedApi(Flags.FLAG_ENABLE_AEAD_ALGORITHMS) to transfer requirement to caller`)"
+ errorLine1=" KEY_CHILD_SESSION_AES_GCM_KEY_SIZE_INT_ARRAY, new int[] {});"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/CarrierConfigManager.java"
+ line="9479"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `KEY_ADDITIONAL_SETTINGS_CALLER_ID_VISIBILITY_BOOL` is a flagged API and should be inside an `if (Flags.showCallIdAndCallWaitingInAdditionalSettingsMenu())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_SHOW_CALL_ID_AND_CALL_WAITING_IN_ADDITIONAL_SETTINGS_MENU) to transfer requirement to caller`)"
+ errorLine1=" sDefaults.putBoolean(KEY_ADDITIONAL_SETTINGS_CALLER_ID_VISIBILITY_BOOL, true);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/CarrierConfigManager.java"
+ line="10519"
+ column="30"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `KEY_ADDITIONAL_SETTINGS_CALL_WAITING_VISIBILITY_BOOL` is a flagged API and should be inside an `if (Flags.showCallIdAndCallWaitingInAdditionalSettingsMenu())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_SHOW_CALL_ID_AND_CALL_WAITING_IN_ADDITIONAL_SETTINGS_MENU) to transfer requirement to caller`)"
+ errorLine1=" sDefaults.putBoolean(KEY_ADDITIONAL_SETTINGS_CALL_WAITING_VISIBILITY_BOOL, true);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/CarrierConfigManager.java"
+ line="10520"
+ column="30"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `KEY_PREFER_3G_VISIBILITY_BOOL` is a flagged API and should be inside an `if (Flags.hidePrefer3gItem())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_HIDE_PREFER_3G_ITEM) to transfer requirement to caller`)"
+ errorLine1=" sDefaults.putBoolean(KEY_PREFER_3G_VISIBILITY_BOOL, true);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/CarrierConfigManager.java"
+ line="10526"
+ column="30"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `KEY_SHOW_ROAMING_INDICATOR_BOOL` is a flagged API and should be inside an `if (Flags.hideRoamingIcon())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_HIDE_ROAMING_ICON) to transfer requirement to caller`)"
+ errorLine1=" sDefaults.putBoolean(KEY_SHOW_ROAMING_INDICATOR_BOOL, true);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/CarrierConfigManager.java"
+ line="10794"
+ column="30"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE` is a flagged API and should be inside an `if (Flags.carrierEnabledSatelliteFlag())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG) to transfer requirement to caller`)"
+ errorLine1=" KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/CarrierConfigManager.java"
+ line="11093"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `KEY_SATELLITE_ATTACH_SUPPORTED_BOOL` is a flagged API and should be inside an `if (Flags.carrierEnabledSatelliteFlag())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG) to transfer requirement to caller`)"
+ errorLine1=" sDefaults.putBoolean(KEY_SATELLITE_ATTACH_SUPPORTED_BOOL, false);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/CarrierConfigManager.java"
+ line="11095"
+ column="30"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT` is a flagged API and should be inside an `if (Flags.carrierEnabledSatelliteFlag())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG) to transfer requirement to caller`)"
+ errorLine1=" sDefaults.putInt(KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT, 300);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/CarrierConfigManager.java"
+ line="11096"
+ column="26"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `KEY_NTN_LTE_RSRP_THRESHOLDS_INT_ARRAY` is a flagged API and should be inside an `if (Flags.carrierEnabledSatelliteFlag())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG) to transfer requirement to caller`)"
+ errorLine1=" sDefaults.putIntArray(KEY_NTN_LTE_RSRP_THRESHOLDS_INT_ARRAY,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/CarrierConfigManager.java"
+ line="11097"
+ column="31"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `KEY_NTN_LTE_RSRQ_THRESHOLDS_INT_ARRAY` is a flagged API and should be inside an `if (Flags.carrierEnabledSatelliteFlag())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG) to transfer requirement to caller`)"
+ errorLine1=" sDefaults.putIntArray(KEY_NTN_LTE_RSRQ_THRESHOLDS_INT_ARRAY,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/CarrierConfigManager.java"
+ line="11105"
+ column="31"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `KEY_NTN_LTE_RSSNR_THRESHOLDS_INT_ARRAY` is a flagged API and should be inside an `if (Flags.carrierEnabledSatelliteFlag())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG) to transfer requirement to caller`)"
+ errorLine1=" sDefaults.putIntArray(KEY_NTN_LTE_RSSNR_THRESHOLDS_INT_ARRAY,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/CarrierConfigManager.java"
+ line="11113"
+ column="31"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `KEY_PARAMETERS_USED_FOR_NTN_LTE_SIGNAL_BAR_INT` is a flagged API and should be inside an `if (Flags.carrierEnabledSatelliteFlag())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG) to transfer requirement to caller`)"
+ errorLine1=" sDefaults.putInt(KEY_PARAMETERS_USED_FOR_NTN_LTE_SIGNAL_BAR_INT,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/CarrierConfigManager.java"
+ line="11121"
+ column="26"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `KEY_SATELLITE_ENTITLEMENT_STATUS_REFRESH_DAYS_INT` is a flagged API and should be inside an `if (Flags.carrierEnabledSatelliteFlag())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG) to transfer requirement to caller`)"
+ errorLine1=" sDefaults.putInt(KEY_SATELLITE_ENTITLEMENT_STATUS_REFRESH_DAYS_INT, 7);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/CarrierConfigManager.java"
+ line="11127"
+ column="26"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL` is a flagged API and should be inside an `if (Flags.carrierEnabledSatelliteFlag())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG) to transfer requirement to caller`)"
+ errorLine1=" sDefaults.putBoolean(KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL, false);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/CarrierConfigManager.java"
+ line="11128"
+ column="30"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `SERVICE_TYPE_MMS` is a flagged API and should be inside an `if (Flags.carrierEnabledSatelliteFlag())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG) to transfer requirement to caller`)"
+ errorLine1=" NetworkRegistrationInfo.SERVICE_TYPE_MMS"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/CarrierConfigManager.java"
+ line="11134"
+ column="49"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `KEY_SUPPORTS_BUSINESS_CALL_COMPOSER_BOOL` is a flagged API and should be inside an `if (Flags.businessCallComposer())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_BUSINESS_CALL_COMPOSER) to transfer requirement to caller`)"
+ errorLine1=" sDefaults.putBoolean(KEY_SUPPORTS_BUSINESS_CALL_COMPOSER_BOOL, false);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/CarrierConfigManager.java"
+ line="11142"
+ column="30"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `KEY_CELLULAR_SERVICE_CAPABILITIES_INT_ARRAY` is a flagged API and should be inside an `if (Flags.dataOnlyCellularService())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_DATA_ONLY_CELLULAR_SERVICE) to transfer requirement to caller`)"
+ errorLine1=" sDefaults.putIntArray(KEY_CELLULAR_SERVICE_CAPABILITIES_INT_ARRAY, new int[]{1, 2, 3});"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/CarrierConfigManager.java"
+ line="11233"
+ column="31"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Class `TelephonyRegistryManager` is a flagged API and should be inside an `if (Flags.telecomResolveHiddenDependencies())` check (or annotate the surrounding method `registerCarrierConfigChangeListener` with `@FlaggedApi(Flags.FLAG_TELECOM_RESOLVE_HIDDEN_DEPENDENCIES) to transfer requirement to caller`)"
+ errorLine1=" TelephonyRegistryManager trm = mContext.getSystemService(TelephonyRegistryManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/CarrierConfigManager.java"
+ line="11771"
+ column="66"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `addCarrierConfigChangedListener()` is a flagged API and should be inside an `if (Flags.telecomResolveHiddenDependencies())` check (or annotate the surrounding method `registerCarrierConfigChangeListener` with `@FlaggedApi(Flags.FLAG_TELECOM_RESOLVE_HIDDEN_DEPENDENCIES) to transfer requirement to caller`)"
+ errorLine1=" trm.addCarrierConfigChangedListener(executor, listener);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/CarrierConfigManager.java"
+ line="11775"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Class `TelephonyRegistryManager` is a flagged API and should be inside an `if (Flags.telecomResolveHiddenDependencies())` check (or annotate the surrounding method `unregisterCarrierConfigChangeListener` with `@FlaggedApi(Flags.FLAG_TELECOM_RESOLVE_HIDDEN_DEPENDENCIES) to transfer requirement to caller`)"
+ errorLine1=" TelephonyRegistryManager trm = mContext.getSystemService(TelephonyRegistryManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/CarrierConfigManager.java"
+ line="11789"
+ column="66"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `removeCarrierConfigChangedListener()` is a flagged API and should be inside an `if (Flags.telecomResolveHiddenDependencies())` check (or annotate the surrounding method `unregisterCarrierConfigChangeListener` with `@FlaggedApi(Flags.FLAG_TELECOM_RESOLVE_HIDDEN_DEPENDENCIES) to transfer requirement to caller`)"
+ errorLine1=" trm.removeCarrierConfigChangedListener(listener);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/CarrierConfigManager.java"
+ line="11793"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="This is a flagged API and should be inside an `if (Flags.telecomResolveHiddenDependencies())` check (or annotate the surrounding method `notifyCarrierNetworkChange` with `@FlaggedApi(Flags.FLAG_TELECOM_RESOLVE_HIDDEN_DEPENDENCIES) to transfer requirement to caller`)"
+ errorLine1=" (TelephonyRegistryManager) this.getSystemService("
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/service/carrier/CarrierService.java"
+ line="180"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `notifyCarrierNetworkChange()` is a flagged API and should be inside an `if (Flags.telecomResolveHiddenDependencies())` check (or annotate the surrounding method `notifyCarrierNetworkChange` with `@FlaggedApi(Flags.FLAG_TELECOM_RESOLVE_HIDDEN_DEPENDENCIES) to transfer requirement to caller`)"
+ errorLine1=" telephonyRegistryMgr.notifyCarrierNetworkChange(active);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/service/carrier/CarrierService.java"
+ line="183"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Class `TelephonyRegistryManager` is a flagged API and should be inside an `if (Flags.telecomResolveHiddenDependencies())` check (or annotate the surrounding method `notifyCarrierNetworkChange` with `@FlaggedApi(Flags.FLAG_TELECOM_RESOLVE_HIDDEN_DEPENDENCIES) to transfer requirement to caller`)"
+ errorLine1=" TelephonyRegistryManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/service/carrier/CarrierService.java"
+ line="206"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `notifyCarrierNetworkChange()` is a flagged API and should be inside an `if (Flags.telecomResolveHiddenDependencies())` check (or annotate the surrounding method `notifyCarrierNetworkChange` with `@FlaggedApi(Flags.FLAG_TELECOM_RESOLVE_HIDDEN_DEPENDENCIES) to transfer requirement to caller`)"
+ errorLine1=" telephonyRegistryMgr.notifyCarrierNetworkChange(subscriptionId, active);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/service/carrier/CarrierService.java"
+ line="208"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `isUsingNonTerrestrialNetwork()` is a flagged API and should be inside an `if (Flags.carrierEnabledSatelliteFlag())` check (or annotate the surrounding method `updateLevel` with `@FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG) to transfer requirement to caller`)"
+ errorLine1=" if (ss != null && ss.isUsingNonTerrestrialNetwork()) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/CellSignalStrengthLte.java"
+ line="266"
+ column="31"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `KEY_PARAMETERS_USED_FOR_NTN_LTE_SIGNAL_BAR_INT` is a flagged API and should be inside an `if (Flags.carrierEnabledSatelliteFlag())` check (or annotate the surrounding method `updateLevel` with `@FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG) to transfer requirement to caller`)"
+ errorLine1=" CarrierConfigManager.KEY_PARAMETERS_USED_FOR_NTN_LTE_SIGNAL_BAR_INT);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/CellSignalStrengthLte.java"
+ line="269"
+ column="46"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `KEY_NTN_LTE_RSRP_THRESHOLDS_INT_ARRAY` is a flagged API and should be inside an `if (Flags.carrierEnabledSatelliteFlag())` check (or annotate the surrounding method `updateLevel` with `@FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG) to transfer requirement to caller`)"
+ errorLine1=" CarrierConfigManager.KEY_NTN_LTE_RSRP_THRESHOLDS_INT_ARRAY);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/CellSignalStrengthLte.java"
+ line="271"
+ column="46"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `KEY_NTN_LTE_RSRQ_THRESHOLDS_INT_ARRAY` is a flagged API and should be inside an `if (Flags.carrierEnabledSatelliteFlag())` check (or annotate the surrounding method `updateLevel` with `@FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG) to transfer requirement to caller`)"
+ errorLine1=" CarrierConfigManager.KEY_NTN_LTE_RSRQ_THRESHOLDS_INT_ARRAY);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/CellSignalStrengthLte.java"
+ line="273"
+ column="46"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `KEY_NTN_LTE_RSSNR_THRESHOLDS_INT_ARRAY` is a flagged API and should be inside an `if (Flags.carrierEnabledSatelliteFlag())` check (or annotate the surrounding method `updateLevel` with `@FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG) to transfer requirement to caller`)"
+ errorLine1=" CarrierConfigManager.KEY_NTN_LTE_RSSNR_THRESHOLDS_INT_ARRAY);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/CellSignalStrengthLte.java"
+ line="275"
+ column="46"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getFrameTimeNanos()` is a flagged API and should be inside an `if (Flags.expectedPresentationTimeApi())` check (or annotate the surrounding method `getFrameTime` with `@FlaggedApi(Flags.FLAG_EXPECTED_PRESENTATION_TIME_API) to transfer requirement to caller`)"
+ errorLine1=" return getFrameTimeNanos() / TimeUtils.NANOS_PER_MS;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/Choreographer.java"
+ line="694"
+ column="16"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `lockAnimationClock()` is a flagged API and should be inside an `if (Flags.expectedPresentationTimeReadOnly())` check (or annotate the surrounding method `doFrame` with `@FlaggedApi(Flags.FLAG_EXPECTED_PRESENTATION_TIME_READ_ONLY) to transfer requirement to caller`)"
+ errorLine1=" AnimationUtils.lockAnimationClock(frameTimeNanos / TimeUtils.NANOS_PER_MS,"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/core/java/android/view/Choreographer.java"
+ line="934"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `SOURCE_UNKNOWN` is a flagged API and should be inside an `if (Flags.modesApi())` check (or annotate the surrounding method `Condition` with `@FlaggedApi(Flags.FLAG_MODES_API) to transfer requirement to caller`)"
+ errorLine1=" this(id, summary, "", "", -1, state, SOURCE_UNKNOWN, FLAG_RELEVANT_ALWAYS);"
+ errorLine2=" ~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/service/notification/Condition.java"
+ line="138"
+ column="46"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `Condition()` is a flagged API and should be inside an `if (Flags.modesApi())` check (or annotate the surrounding method `Condition` with `@FlaggedApi(Flags.FLAG_MODES_API) to transfer requirement to caller`)"
+ errorLine1=" this(id, summary, "", "", -1, state, SOURCE_UNKNOWN, FLAG_RELEVANT_ALWAYS);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/service/notification/Condition.java"
+ line="138"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `SOURCE_UNKNOWN` is a flagged API and should be inside an `if (Flags.modesApi())` check (or annotate the surrounding method `Condition` with `@FlaggedApi(Flags.FLAG_MODES_API) to transfer requirement to caller`)"
+ errorLine1=" this(id, summary, line1, line2, icon, state, SOURCE_UNKNOWN, flags);"
+ errorLine2=" ~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/service/notification/Condition.java"
+ line="157"
+ column="54"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `Condition()` is a flagged API and should be inside an `if (Flags.modesApi())` check (or annotate the surrounding method `Condition` with `@FlaggedApi(Flags.FLAG_MODES_API) to transfer requirement to caller`)"
+ errorLine1=" this(id, summary, line1, line2, icon, state, SOURCE_UNKNOWN, flags);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/service/notification/Condition.java"
+ line="157"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `Condition()` is a flagged API and should be inside an `if (Flags.modesApi())` check (or annotate the surrounding method `Condition` with `@FlaggedApi(Flags.FLAG_MODES_API) to transfer requirement to caller`)"
+ errorLine1=" this((Uri)source.readParcelable(Condition.class.getClassLoader(), android.net.Uri.class),"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/core/java/android/service/notification/Condition.java"
+ line="192"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `SOURCE_UNKNOWN` is a flagged API and should be inside an `if (Flags.modesApi())` check (or annotate the surrounding method `Condition` with `@FlaggedApi(Flags.FLAG_MODES_API) to transfer requirement to caller`)"
+ errorLine1=" Flags.modesApi() ? source.readInt() : SOURCE_UNKNOWN,"
+ errorLine2=" ~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/service/notification/Condition.java"
+ line="198"
+ column="55"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `onCreateConnectionComplete()` is a flagged API and should be inside an `if (Flags.telecomResolveHiddenDependencies())` check (or annotate the surrounding method `notifyCreateConnectionComplete` with `@FlaggedApi(Flags.FLAG_TELECOM_RESOLVE_HIDDEN_DEPENDENCIES) to transfer requirement to caller`)"
+ errorLine1=" onCreateConnectionComplete(findConnectionForAction(callId,"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/telecomm/java/android/telecom/ConnectionService.java"
+ line="2531"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `onCreateConferenceComplete()` is a flagged API and should be inside an `if (Flags.telecomResolveHiddenDependencies())` check (or annotate the surrounding method `notifyCreateConferenceComplete` with `@FlaggedApi(Flags.FLAG_TELECOM_RESOLVE_HIDDEN_DEPENDENCIES) to transfer requirement to caller`)"
+ errorLine1=" onCreateConferenceComplete(findConferenceForAction(callId,"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/telecomm/java/android/telecom/ConnectionService.java"
+ line="2548"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getCallDirection()` is a flagged API and should be inside an `if (Flags.telecomResolveHiddenDependencies())` check (or annotate the surrounding method `addExistingConnection` with `@FlaggedApi(Flags.FLAG_TELECOM_RESOLVE_HIDDEN_DEPENDENCIES) to transfer requirement to caller`)"
+ errorLine1=" connection.getCallDirection(),"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telecomm/java/android/telecom/ConnectionService.java"
+ line="3179"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `supportsReliableMessages()` is a flagged API and should be inside an `if (Flags.reliableMessage())` check (or annotate the surrounding method `equals` with `@FlaggedApi(Flags.FLAG_RELIABLE_MESSAGE) to transfer requirement to caller`)"
+ errorLine1=" || (other.supportsReliableMessages() == mSupportsReliableMessages))"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/hardware/location/ContextHubInfo.java"
+ line="365"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `isReliable()` is a flagged API and should be inside an `if (Flags.reliableMessage())` check (or annotate the surrounding method `onMessageFromNanoApp` with `@FlaggedApi(Flags.FLAG_RELIABLE_MESSAGE) to transfer requirement to caller`)"
+ errorLine1=" && message.isReliable()) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/hardware/location/ContextHubManager.java"
+ line="715"
+ column="44"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `TYPE_RELIABLE_MESSAGE` is a flagged API and should be inside an `if (Flags.reliableMessage())` check (or annotate the surrounding method `typeToString` with `@FlaggedApi(Flags.FLAG_RELIABLE_MESSAGE) to transfer requirement to caller`)"
+ errorLine1=" case ContextHubTransaction.TYPE_RELIABLE_MESSAGE: {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/hardware/location/ContextHubTransaction.java"
+ line="235"
+ column="40"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `shouldRegisterAttributionSource()` is a flagged API and should be inside an `if (Flags.shouldRegisterAttributionSource())` check (or annotate the surrounding method `ContextImpl` with `@FlaggedApi(Flags.FLAG_SHOULD_REGISTER_ATTRIBUTION_SOURCE) to transfer requirement to caller`)"
+ errorLine1=" params.getRenouncedPermissions(), params.shouldRegisterAttributionSource(), mDeviceId);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/ContextImpl.java"
+ line="3540"
+ column="51"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `NETWORK_VALIDATION_UNSUPPORTED` is a flagged API and should be inside an `if (Flags.networkValidation())` check (or annotate the surrounding method `DataCallResponse` with `@FlaggedApi(Flags.FLAG_NETWORK_VALIDATION) to transfer requirement to caller`)"
+ errorLine1=" PreciseDataConnectionState.NETWORK_VALIDATION_UNSUPPORTED);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/data/DataCallResponse.java"
+ line="192"
+ column="44"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `NETWORK_VALIDATION_UNSUPPORTED` is a flagged API and should be inside an `if (Flags.networkValidation())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_NETWORK_VALIDATION) to transfer requirement to caller`)"
+ errorLine1=" PreciseDataConnectionState.NETWORK_VALIDATION_UNSUPPORTED;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/data/DataCallResponse.java"
+ line="655"
+ column="44"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `TYPE_RCS` is a flagged API and should be inside an `if (Flags.carrierEnabledSatelliteFlag())` check (or annotate the surrounding method `networkCapabilityToApnType` with `@FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG) to transfer requirement to caller`)"
+ errorLine1=" return ApnSetting.TYPE_RCS;"
+ errorLine2=" ~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/data/DataProfile.java"
+ line="435"
+ column="35"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `requestNetworkValidation()` is a flagged API and should be inside an `if (Flags.networkValidation())` check (or annotate the surrounding method `handleMessage` with `@FlaggedApi(Flags.FLAG_NETWORK_VALIDATION) to transfer requirement to caller`)"
+ errorLine1=" serviceProvider.requestNetworkValidation("
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/data/DataService.java"
+ line="744"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `HEADLESS_DEVICE_OWNER_MODE_SINGLE_USER` is a flagged API and should be inside an `if (Flags.headlessDeviceOwnerSingleUserEnabled())` check (or annotate the surrounding method `DeviceAdminInfo` with `@FlaggedApi(Flags.FLAG_HEADLESS_DEVICE_OWNER_SINGLE_USER_ENABLED) to transfer requirement to caller`)"
+ errorLine1=" mHeadlessDeviceOwnerMode = HEADLESS_DEVICE_OWNER_MODE_SINGLE_USER;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/admin/DeviceAdminInfo.java"
+ line="410"
+ column="52"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `CONTENT_PROTECTION_DISABLED` is a flagged API and should be inside an `if (Flags.manageDevicePolicyEnabled())` check (or annotate the surrounding method `getContentProtectionPolicy` with `@FlaggedApi(Flags.FLAG_MANAGE_DEVICE_POLICY_ENABLED) to transfer requirement to caller`)"
+ errorLine1=" return CONTENT_PROTECTION_DISABLED;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/admin/DevicePolicyCache.java"
+ line="105"
+ column="20"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `equals()` is a flagged API and should be inside an `if (Flags.deviceStatePropertyApi())` check (or annotate the surrounding method `equals` with `@FlaggedApi(Flags.FLAG_DEVICE_STATE_PROPERTY_API) to transfer requirement to caller`)"
+ errorLine1=" return baseState.equals(that.baseState)"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/hardware/devicestate/DeviceStateInfo.java"
+ line="101"
+ column="16"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `equals()` is a flagged API and should be inside an `if (Flags.deviceStatePropertyApi())` check (or annotate the surrounding method `equals` with `@FlaggedApi(Flags.FLAG_DEVICE_STATE_PROPERTY_API) to transfer requirement to caller`)"
+ errorLine1=" && currentState.equals(that.currentState)"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/hardware/devicestate/DeviceStateInfo.java"
+ line="102"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `equals()` is a flagged API and should be inside an `if (Flags.deviceStatePropertyApi())` check (or annotate the surrounding method `diff` with `@FlaggedApi(Flags.FLAG_DEVICE_STATE_PROPERTY_API) to transfer requirement to caller`)"
+ errorLine1=" if (!baseState.equals(other.baseState)) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/hardware/devicestate/DeviceStateInfo.java"
+ line="120"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `equals()` is a flagged API and should be inside an `if (Flags.deviceStatePropertyApi())` check (or annotate the surrounding method `diff` with `@FlaggedApi(Flags.FLAG_DEVICE_STATE_PROPERTY_API) to transfer requirement to caller`)"
+ errorLine1=" if (!currentState.equals(other.currentState)) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/hardware/devicestate/DeviceStateInfo.java"
+ line="123"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getConfiguration()` is a flagged API and should be inside an `if (Flags.deviceStatePropertyApi())` check (or annotate the surrounding method `writeToParcel` with `@FlaggedApi(Flags.FLAG_DEVICE_STATE_PROPERTY_API) to transfer requirement to caller`)"
+ errorLine1=" dest.writeTypedObject(supportedStates.get(i).getConfiguration(), flags);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/hardware/devicestate/DeviceStateInfo.java"
+ line="133"
+ column="35"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getConfiguration()` is a flagged API and should be inside an `if (Flags.deviceStatePropertyApi())` check (or annotate the surrounding method `writeToParcel` with `@FlaggedApi(Flags.FLAG_DEVICE_STATE_PROPERTY_API) to transfer requirement to caller`)"
+ errorLine1=" dest.writeTypedObject(baseState.getConfiguration(), flags);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/hardware/devicestate/DeviceStateInfo.java"
+ line="136"
+ column="31"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getConfiguration()` is a flagged API and should be inside an `if (Flags.deviceStatePropertyApi())` check (or annotate the surrounding method `writeToParcel` with `@FlaggedApi(Flags.FLAG_DEVICE_STATE_PROPERTY_API) to transfer requirement to caller`)"
+ errorLine1=" dest.writeTypedObject(currentState.getConfiguration(), flags);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/hardware/devicestate/DeviceStateInfo.java"
+ line="137"
+ column="31"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `CREATOR` is a flagged API and should be inside an `if (Flags.deviceStatePropertyApi())` check (or annotate the surrounding method `createFromParcel` with `@FlaggedApi(Flags.FLAG_DEVICE_STATE_PROPERTY_API) to transfer requirement to caller`)"
+ errorLine1=" DeviceState.Configuration.CREATOR);"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/hardware/devicestate/DeviceStateInfo.java"
+ line="152"
+ column="51"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `DeviceState()` is a flagged API and should be inside an `if (Flags.deviceStatePropertyApi())` check (or annotate the surrounding method `createFromParcel` with `@FlaggedApi(Flags.FLAG_DEVICE_STATE_PROPERTY_API) to transfer requirement to caller`)"
+ errorLine1=" supportedStates.add(i, new DeviceState(configuration));"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/hardware/devicestate/DeviceStateInfo.java"
+ line="153"
+ column="40"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `DeviceState()` is a flagged API and should be inside an `if (Flags.deviceStatePropertyApi())` check (or annotate the surrounding method `createFromParcel` with `@FlaggedApi(Flags.FLAG_DEVICE_STATE_PROPERTY_API) to transfer requirement to caller`)"
+ errorLine1=" final DeviceState baseState = new DeviceState("
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/core/java/android/hardware/devicestate/DeviceStateInfo.java"
+ line="156"
+ column="43"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `CREATOR` is a flagged API and should be inside an `if (Flags.deviceStatePropertyApi())` check (or annotate the surrounding method `createFromParcel` with `@FlaggedApi(Flags.FLAG_DEVICE_STATE_PROPERTY_API) to transfer requirement to caller`)"
+ errorLine1=" source.readTypedObject(DeviceState.Configuration.CREATOR));"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/hardware/devicestate/DeviceStateInfo.java"
+ line="157"
+ column="70"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `DeviceState()` is a flagged API and should be inside an `if (Flags.deviceStatePropertyApi())` check (or annotate the surrounding method `createFromParcel` with `@FlaggedApi(Flags.FLAG_DEVICE_STATE_PROPERTY_API) to transfer requirement to caller`)"
+ errorLine1=" final DeviceState currentState = new DeviceState("
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/core/java/android/hardware/devicestate/DeviceStateInfo.java"
+ line="158"
+ column="46"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `CREATOR` is a flagged API and should be inside an `if (Flags.deviceStatePropertyApi())` check (or annotate the surrounding method `createFromParcel` with `@FlaggedApi(Flags.FLAG_DEVICE_STATE_PROPERTY_API) to transfer requirement to caller`)"
+ errorLine1=" source.readTypedObject(DeviceState.Configuration.CREATOR));"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/hardware/devicestate/DeviceStateInfo.java"
+ line="159"
+ column="70"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `onSupportedStatesChanged()` is a flagged API and should be inside an `if (Flags.deviceStatePropertyApi())` check (or annotate the surrounding method `notifySupportedDeviceStatesChanged` with `@FlaggedApi(Flags.FLAG_DEVICE_STATE_PROPERTY_API) to transfer requirement to caller`)"
+ errorLine1=" mDeviceStateCallback.onSupportedStatesChanged(newSupportedDeviceStates));"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/hardware/devicestate/DeviceStateManagerGlobal.java"
+ line="393"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `onDeviceStateChanged()` is a flagged API and should be inside an `if (Flags.deviceStatePropertyApi())` check (or annotate the surrounding method `notifyDeviceStateChanged` with `@FlaggedApi(Flags.FLAG_DEVICE_STATE_PROPERTY_API) to transfer requirement to caller`)"
+ errorLine1=" () -> mDeviceStateCallback.onDeviceStateChanged(newDeviceState));"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/hardware/devicestate/DeviceStateManagerGlobal.java"
+ line="398"
+ column="27"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getConfiguration()` is a flagged API and should be inside an `if (Flags.deviceStatePropertyApi())` check (or annotate the surrounding method `calculateBaseStateIdentifier` with `@FlaggedApi(Flags.FLAG_DEVICE_STATE_PROPERTY_API) to transfer requirement to caller`)"
+ errorLine1=" DeviceState.Configuration stateConfiguration = currentState.getConfiguration();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/hardware/devicestate/DeviceStateUtil.java"
+ line="45"
+ column="56"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getConfiguration()` is a flagged API and should be inside an `if (Flags.deviceStatePropertyApi())` check (or annotate the surrounding method `calculateBaseStateIdentifier` with `@FlaggedApi(Flags.FLAG_DEVICE_STATE_PROPERTY_API) to transfer requirement to caller`)"
+ errorLine1=" if (stateToCompare.getConfiguration().getPhysicalProperties().isEmpty()) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/hardware/devicestate/DeviceStateUtil.java"
+ line="48"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getPhysicalProperties()` is a flagged API and should be inside an `if (Flags.deviceStatePropertyApi())` check (or annotate the surrounding method `calculateBaseStateIdentifier` with `@FlaggedApi(Flags.FLAG_DEVICE_STATE_PROPERTY_API) to transfer requirement to caller`)"
+ errorLine1=" if (stateToCompare.getConfiguration().getPhysicalProperties().isEmpty()) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/hardware/devicestate/DeviceStateUtil.java"
+ line="48"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getPhysicalProperties()` is a flagged API and should be inside an `if (Flags.deviceStatePropertyApi())` check (or annotate the surrounding method `calculateBaseStateIdentifier` with `@FlaggedApi(Flags.FLAG_DEVICE_STATE_PROPERTY_API) to transfer requirement to caller`)"
+ errorLine1=" if (isDeviceStateMatchingPhysicalProperties(stateConfiguration.getPhysicalProperties(),"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/hardware/devicestate/DeviceStateUtil.java"
+ line="51"
+ column="57"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getIdentifier()` is a flagged API and should be inside an `if (Flags.deviceStatePropertyApi())` check (or annotate the surrounding method `calculateBaseStateIdentifier` with `@FlaggedApi(Flags.FLAG_DEVICE_STATE_PROPERTY_API) to transfer requirement to caller`)"
+ errorLine1=" return supportedStates.get(i).getIdentifier();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/hardware/devicestate/DeviceStateUtil.java"
+ line="53"
+ column="24"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `INVALID_DEVICE_STATE_IDENTIFIER` is a flagged API and should be inside an `if (Flags.deviceStatePropertyApi())` check (or annotate the surrounding method `calculateBaseStateIdentifier` with `@FlaggedApi(Flags.FLAG_DEVICE_STATE_PROPERTY_API) to transfer requirement to caller`)"
+ errorLine1=" return INVALID_DEVICE_STATE_IDENTIFIER;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/hardware/devicestate/DeviceStateUtil.java"
+ line="56"
+ column="16"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `hasProperty()` is a flagged API and should be inside an `if (Flags.deviceStatePropertyApi())` check (or annotate the surrounding method `isDeviceStateMatchingPhysicalProperties` with `@FlaggedApi(Flags.FLAG_DEVICE_STATE_PROPERTY_API) to transfer requirement to caller`)"
+ errorLine1=" if (!state.hasProperty(iterator.next())) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/hardware/devicestate/DeviceStateUtil.java"
+ line="69"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getTelephonyDisconnectCause()` is a flagged API and should be inside an `if (Flags.telecomResolveHiddenDependencies())` check (or annotate the surrounding method `equals` with `@FlaggedApi(Flags.FLAG_TELECOM_RESOLVE_HIDDEN_DEPENDENCIES) to transfer requirement to caller`)"
+ errorLine1=" && Objects.equals(mTelephonyDisconnectCause, d.getTelephonyDisconnectCause())"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telecomm/java/android/telecom/DisconnectCause.java"
+ line="498"
+ column="66"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getTelephonyPreciseDisconnectCause()` is a flagged API and should be inside an `if (Flags.telecomResolveHiddenDependencies())` check (or annotate the surrounding method `equals` with `@FlaggedApi(Flags.FLAG_TELECOM_RESOLVE_HIDDEN_DEPENDENCIES) to transfer requirement to caller`)"
+ errorLine1=" d.getTelephonyPreciseDisconnectCause())"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telecomm/java/android/telecom/DisconnectCause.java"
+ line="500"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getImsReasonInfo()` is a flagged API and should be inside an `if (Flags.telecomResolveHiddenDependencies())` check (or annotate the surrounding method `equals` with `@FlaggedApi(Flags.FLAG_TELECOM_RESOLVE_HIDDEN_DEPENDENCIES) to transfer requirement to caller`)"
+ errorLine1=" && Objects.equals(mImsReasonInfo, d.getImsReasonInfo());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telecomm/java/android/telecom/DisconnectCause.java"
+ line="501"
+ column="55"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `SATELLITE_ENABLED` is a flagged API and should be inside an `if (Flags.oemEnabledSatelliteFlag())` check (or annotate the surrounding method `toString` with `@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) to transfer requirement to caller`)"
+ errorLine1=" case SATELLITE_ENABLED:"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/DisconnectCause.java"
+ line="550"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `dreamCategory` is a flagged API and should be inside an `if (Flags.homePanelDream())` check (or annotate the surrounding method `DreamMetadata` with `@FlaggedApi(Flags.FLAG_HOME_PANEL_DREAM) to transfer requirement to caller`)"
+ errorLine1=" this.dreamCategory = DREAM_CATEGORY_DEFAULT;"
+ errorLine2=" ~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/service/dreams/DreamService.java"
+ line="1825"
+ column="22"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `setMinimumFontMetrics()` is a flagged API and should be inside an `if (Flags.fixLineHeightForLocale())` check (or annotate the surrounding method `reflow` with `@FlaggedApi(Flags.FLAG_FIX_LINE_HEIGHT_FOR_LOCALE) to transfer requirement to caller`)"
+ errorLine1=" b.setText(text, where, where + after)"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/core/java/android/text/DynamicLayout.java"
+ line="736"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `setShiftDrawingOffsetForStartOverhang()` is a flagged API and should be inside an `if (Flags.useBoundsForWidth())` check (or annotate the surrounding method `reflow` with `@FlaggedApi(Flags.FLAG_USE_BOUNDS_FOR_WIDTH) to transfer requirement to caller`)"
+ errorLine1=" b.setText(text, where, where + after)"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/core/java/android/text/DynamicLayout.java"
+ line="736"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `setUseBoundsForWidth()` is a flagged API and should be inside an `if (Flags.useBoundsForWidth())` check (or annotate the surrounding method `reflow` with `@FlaggedApi(Flags.FLAG_USE_BOUNDS_FOR_WIDTH) to transfer requirement to caller`)"
+ errorLine1=" b.setText(text, where, where + after)"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/core/java/android/text/DynamicLayout.java"
+ line="736"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getTextDirectionHeuristic()` is a flagged API and should be inside an `if (Flags.useBoundsForWidth())` check (or annotate the surrounding method `reflow` with `@FlaggedApi(Flags.FLAG_USE_BOUNDS_FOR_WIDTH) to transfer requirement to caller`)"
+ errorLine1=" .setTextDirection(getTextDirectionHeuristic())"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/text/DynamicLayout.java"
+ line="739"
+ column="35"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `setLocalePreferredLineHeightForMinimumUsed()` is a flagged API and should be inside an `if (Flags.fixLineHeightForLocale())` check (or annotate the surrounding method `EditText` with `@FlaggedApi(Flags.FLAG_FIX_LINE_HEIGHT_FOR_LOCALE) to transfer requirement to caller`)"
+ errorLine1=" setLocalePreferredLineHeightForMinimumUsed(useLocalePreferredLineHeightForMinimumInt);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/widget/EditText.java"
+ line="150"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `convertSpToDp()` is a flagged API and should be inside an `if (Flags.fontScaleConverterPublic())` check (or annotate the surrounding method `createInterpolatedTableBetween` with `@FlaggedApi(Flags.FLAG_FONT_SCALE_CONVERTER_PUBLIC) to transfer requirement to caller`)"
+ errorLine1=" float startDp = start.convertSpToDp(sp);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/content/res/FontScaleConverterFactory.java"
+ line="242"
+ column="29"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `convertSpToDp()` is a flagged API and should be inside an `if (Flags.fontScaleConverterPublic())` check (or annotate the surrounding method `createInterpolatedTableBetween` with `@FlaggedApi(Flags.FLAG_FONT_SCALE_CONVERTER_PUBLIC) to transfer requirement to caller`)"
+ errorLine1=" float endDp = end.convertSpToDp(sp);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/content/res/FontScaleConverterFactory.java"
+ line="243"
+ column="27"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="This is a flagged API and should be inside an `if (Flags.fontScaleConverterPublic())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_FONT_SCALE_CONVERTER_PUBLIC) to transfer requirement to caller`)"
+ errorLine1="public class FontScaleConverterImpl implements FontScaleConverter {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/content/res/FontScaleConverterImpl.java"
+ line="36"
+ column="48"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `FOREGROUND_SERVICE_TYPE_MEDIA_PROCESSING` is a flagged API and should be inside an `if (Flags.introduceMediaProcessingType())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_INTRODUCE_MEDIA_PROCESSING_TYPE) to transfer requirement to caller`)"
+ errorLine1=" FOREGROUND_SERVICE_TYPE_MEDIA_PROCESSING,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/ForegroundServiceTypePolicy.java"
+ line="587"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `FOREGROUND_SERVICE_TYPE_MEDIA_PROCESSING` is a flagged API and should be inside an `if (Flags.introduceMediaProcessingType())` check (or annotate the surrounding method `DefaultForegroundServiceTypePolicy` with `@FlaggedApi(Flags.FLAG_INTRODUCE_MEDIA_PROCESSING_TYPE) to transfer requirement to caller`)"
+ errorLine1=" mForegroundServiceTypePolicies.put(FOREGROUND_SERVICE_TYPE_MEDIA_PROCESSING,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/ForegroundServiceTypePolicy.java"
+ line="1355"
+ column="48"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `InputTransferToken()` is a flagged API and should be inside an `if (Flags.surfaceControlInputReceiver())` check (or annotate the surrounding method `doCreate` with `@FlaggedApi(Flags.FLAG_SURFACE_CONTROL_INPUT_RECEIVER) to transfer requirement to caller`)"
+ errorLine1=" new InputTransferToken(), "GameSessionService");"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/service/games/GameSessionService.java"
+ line="127"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `CREATOR` is a flagged API and should be inside an `if (Flags.configurableSelectorUiEnabled())` check (or annotate the surrounding method `GetCandidateCredentialsResponse` with `@FlaggedApi(Flags.FLAG_CONFIGURABLE_SELECTOR_UI_ENABLED) to transfer requirement to caller`)"
+ errorLine1=" in.readTypedList(candidateProviderDataList, GetCredentialProviderData.CREATOR);"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/credentials/GetCandidateCredentialsResponse.java"
+ line="98"
+ column="79"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `isConnectionlessStylusHandwritingAvailable()` is a flagged API and should be inside an `if (Flags.connectionlessHandwriting())` check (or annotate the surrounding method `prepareDelegation` with `@FlaggedApi(Flags.FLAG_CONNECTIONLESS_HANDWRITING) to transfer requirement to caller`)"
+ errorLine1=" if (mImm.isConnectionlessStylusHandwritingAvailable()) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/HandwritingInitiator.java"
+ line="450"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `startConnectionlessStylusHandwritingForDelegation()` is a flagged API and should be inside an `if (Flags.connectionlessHandwriting())` check (or annotate the surrounding method `prepareDelegation` with `@FlaggedApi(Flags.FLAG_CONNECTIONLESS_HANDWRITING) to transfer requirement to caller`)"
+ errorLine1=" mImm.startConnectionlessStylusHandwritingForDelegation("
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/core/java/android/view/HandwritingInitiator.java"
+ line="454"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="This is a flagged API and should be inside an `if (Flags.connectionlessHandwriting())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_CONNECTIONLESS_HANDWRITING) to transfer requirement to caller`)"
+ errorLine1=" private class DelegationCallback implements ConnectionlessHandwritingCallback {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/HandwritingInitiator.java"
+ line="1116"
+ column="49"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `CONNECTIONLESS_HANDWRITING_ERROR_NO_TEXT_RECOGNIZED` is a flagged API and should be inside an `if (Flags.connectionlessHandwriting())` check (or annotate the surrounding method `onError` with `@FlaggedApi(Flags.FLAG_CONNECTIONLESS_HANDWRITING) to transfer requirement to caller`)"
+ errorLine1=" case CONNECTIONLESS_HANDWRITING_ERROR_NO_TEXT_RECOGNIZED:"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/HandwritingInitiator.java"
+ line="1133"
+ column="22"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `CONNECTIONLESS_HANDWRITING_ERROR_UNSUPPORTED` is a flagged API and should be inside an `if (Flags.connectionlessHandwriting())` check (or annotate the surrounding method `onError` with `@FlaggedApi(Flags.FLAG_CONNECTIONLESS_HANDWRITING) to transfer requirement to caller`)"
+ errorLine1=" case CONNECTIONLESS_HANDWRITING_ERROR_UNSUPPORTED:"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/HandwritingInitiator.java"
+ line="1136"
+ column="22"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="This is a flagged API and should be inside an `if (Flags.scrollFeedbackApi())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_SCROLL_FEEDBACK_API) to transfer requirement to caller`)"
+ errorLine1="public class HapticScrollFeedbackProvider implements ScrollFeedbackProvider {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/HapticScrollFeedbackProvider.java"
+ line="36"
+ column="54"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getOverlaySupport()` is a flagged API and should be inside an `if (Flags.overlaypropertiesClassApi())` check (or annotate the surrounding method `initDisplayInfo` with `@FlaggedApi(Flags.FLAG_OVERLAYPROPERTIES_CLASS_API) to transfer requirement to caller`)"
+ errorLine1=" final OverlayProperties overlayProperties = defaultDisplay.getOverlaySupport();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/graphics/java/android/graphics/HardwareRenderer.java"
+ line="1394"
+ column="57"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `isCombinationSupported()` is a flagged API and should be inside an `if (Flags.overlaypropertiesClassApi())` check (or annotate the surrounding method `initDisplayInfo` with `@FlaggedApi(Flags.FLAG_OVERLAYPROPERTIES_CLASS_API) to transfer requirement to caller`)"
+ errorLine1=" overlayProperties.isCombinationSupported("
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/graphics/java/android/graphics/HardwareRenderer.java"
+ line="1422"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `isCombinationSupported()` is a flagged API and should be inside an `if (Flags.overlaypropertiesClassApi())` check (or annotate the surrounding method `initDisplayInfo` with `@FlaggedApi(Flags.FLAG_OVERLAYPROPERTIES_CLASS_API) to transfer requirement to caller`)"
+ errorLine1=" overlayProperties.isCombinationSupported("
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/graphics/java/android/graphics/HardwareRenderer.java"
+ line="1424"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `RGBA_10101010` is a flagged API and should be inside an `if (Flags.requestedFormatsV())` check (or annotate the surrounding method `initDisplayInfo` with `@FlaggedApi(Flags.FLAG_REQUESTED_FORMATS_V) to transfer requirement to caller`)"
+ errorLine1=" HardwareBuffer.RGBA_10101010),"
+ errorLine2=" ~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/graphics/java/android/graphics/HardwareRenderer.java"
+ line="1429"
+ column="44"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `isMixedColorSpacesSupported()` is a flagged API and should be inside an `if (Flags.overlaypropertiesClassApi())` check (or annotate the surrounding method `initDisplayInfo` with `@FlaggedApi(Flags.FLAG_OVERLAYPROPERTIES_CLASS_API) to transfer requirement to caller`)"
+ errorLine1=" overlayProperties.isMixedColorSpacesSupported());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/graphics/java/android/graphics/HardwareRenderer.java"
+ line="1430"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `CONFIDENCE_LEVEL_VERY_HIGH` is a flagged API and should be inside an `if (Flags.allowHotwordBumpEgress())` check (or annotate the surrounding method `confidenceLevelToString` with `@FlaggedApi(Flags.FLAG_ALLOW_HOTWORD_BUMP_EGRESS) to transfer requirement to caller`)"
+ errorLine1=" case CONFIDENCE_LEVEL_VERY_HIGH:"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/service/voice/HotwordRejectedResult.java"
+ line="120"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `scheduleMediaViewCleanup()` is a flagged API and should be inside an `if (Flags.enableAdServiceFw())` check (or annotate the surrounding method `release` with `@FlaggedApi(Flags.FLAG_ENABLE_AD_SERVICE_FW) to transfer requirement to caller`)"
+ errorLine1=" mSessionImpl.scheduleMediaViewCleanup();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/media/java/android/media/tv/ad/ITvAdSessionWrapper.java"
+ line="87"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `release()` is a flagged API and should be inside an `if (Flags.enableAdServiceFw())` check (or annotate the surrounding method `executeMessage` with `@FlaggedApi(Flags.FLAG_ENABLE_AD_SERVICE_FW) to transfer requirement to caller`)"
+ errorLine1=" mSessionImpl.release();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/media/java/android/media/tv/ad/ITvAdSessionWrapper.java"
+ line="101"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `setSurface()` is a flagged API and should be inside an `if (Flags.enableAdServiceFw())` check (or annotate the surrounding method `executeMessage` with `@FlaggedApi(Flags.FLAG_ENABLE_AD_SERVICE_FW) to transfer requirement to caller`)"
+ errorLine1=" mSessionImpl.setSurface((Surface) msg.obj);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/media/java/android/media/tv/ad/ITvAdSessionWrapper.java"
+ line="114"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `dispatchSurfaceChanged()` is a flagged API and should be inside an `if (Flags.enableAdServiceFw())` check (or annotate the surrounding method `executeMessage` with `@FlaggedApi(Flags.FLAG_ENABLE_AD_SERVICE_FW) to transfer requirement to caller`)"
+ errorLine1=" mSessionImpl.dispatchSurfaceChanged("
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/media/java/android/media/tv/ad/ITvAdSessionWrapper.java"
+ line="119"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `createMediaView()` is a flagged API and should be inside an `if (Flags.enableAdServiceFw())` check (or annotate the surrounding method `executeMessage` with `@FlaggedApi(Flags.FLAG_ENABLE_AD_SERVICE_FW) to transfer requirement to caller`)"
+ errorLine1=" mSessionImpl.createMediaView((IBinder) args.arg1, (Rect) args.arg2);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/media/java/android/media/tv/ad/ITvAdSessionWrapper.java"
+ line="126"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `relayoutMediaView()` is a flagged API and should be inside an `if (Flags.enableAdServiceFw())` check (or annotate the surrounding method `executeMessage` with `@FlaggedApi(Flags.FLAG_ENABLE_AD_SERVICE_FW) to transfer requirement to caller`)"
+ errorLine1=" mSessionImpl.relayoutMediaView((Rect) msg.obj);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/media/java/android/media/tv/ad/ITvAdSessionWrapper.java"
+ line="131"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `removeMediaView()` is a flagged API and should be inside an `if (Flags.enableAdServiceFw())` check (or annotate the surrounding method `executeMessage` with `@FlaggedApi(Flags.FLAG_ENABLE_AD_SERVICE_FW) to transfer requirement to caller`)"
+ errorLine1=" mSessionImpl.removeMediaView(true);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/media/java/android/media/tv/ad/ITvAdSessionWrapper.java"
+ line="135"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `startAdService()` is a flagged API and should be inside an `if (Flags.enableAdServiceFw())` check (or annotate the surrounding method `executeMessage` with `@FlaggedApi(Flags.FLAG_ENABLE_AD_SERVICE_FW) to transfer requirement to caller`)"
+ errorLine1=" mSessionImpl.startAdService();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/media/java/android/media/tv/ad/ITvAdSessionWrapper.java"
+ line="139"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `stopAdService()` is a flagged API and should be inside an `if (Flags.enableAdServiceFw())` check (or annotate the surrounding method `executeMessage` with `@FlaggedApi(Flags.FLAG_ENABLE_AD_SERVICE_FW) to transfer requirement to caller`)"
+ errorLine1=" mSessionImpl.stopAdService();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/media/java/android/media/tv/ad/ITvAdSessionWrapper.java"
+ line="143"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `resetAdService()` is a flagged API and should be inside an `if (Flags.enableAdServiceFw())` check (or annotate the surrounding method `executeMessage` with `@FlaggedApi(Flags.FLAG_ENABLE_AD_SERVICE_FW) to transfer requirement to caller`)"
+ errorLine1=" mSessionImpl.resetAdService();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/media/java/android/media/tv/ad/ITvAdSessionWrapper.java"
+ line="147"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `sendCurrentVideoBounds()` is a flagged API and should be inside an `if (Flags.enableAdServiceFw())` check (or annotate the surrounding method `executeMessage` with `@FlaggedApi(Flags.FLAG_ENABLE_AD_SERVICE_FW) to transfer requirement to caller`)"
+ errorLine1=" mSessionImpl.sendCurrentVideoBounds((Rect) msg.obj);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/media/java/android/media/tv/ad/ITvAdSessionWrapper.java"
+ line="151"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `sendCurrentChannelUri()` is a flagged API and should be inside an `if (Flags.enableAdServiceFw())` check (or annotate the surrounding method `executeMessage` with `@FlaggedApi(Flags.FLAG_ENABLE_AD_SERVICE_FW) to transfer requirement to caller`)"
+ errorLine1=" mSessionImpl.sendCurrentChannelUri((Uri) msg.obj);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/media/java/android/media/tv/ad/ITvAdSessionWrapper.java"
+ line="155"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `sendTrackInfoList()` is a flagged API and should be inside an `if (Flags.enableAdServiceFw())` check (or annotate the surrounding method `executeMessage` with `@FlaggedApi(Flags.FLAG_ENABLE_AD_SERVICE_FW) to transfer requirement to caller`)"
+ errorLine1=" mSessionImpl.sendTrackInfoList((List<TvTrackInfo>) msg.obj);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/media/java/android/media/tv/ad/ITvAdSessionWrapper.java"
+ line="159"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `sendCurrentTvInputId()` is a flagged API and should be inside an `if (Flags.enableAdServiceFw())` check (or annotate the surrounding method `executeMessage` with `@FlaggedApi(Flags.FLAG_ENABLE_AD_SERVICE_FW) to transfer requirement to caller`)"
+ errorLine1=" mSessionImpl.sendCurrentTvInputId((String) msg.obj);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/media/java/android/media/tv/ad/ITvAdSessionWrapper.java"
+ line="163"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `sendSigningResult()` is a flagged API and should be inside an `if (Flags.enableAdServiceFw())` check (or annotate the surrounding method `executeMessage` with `@FlaggedApi(Flags.FLAG_ENABLE_AD_SERVICE_FW) to transfer requirement to caller`)"
+ errorLine1=" mSessionImpl.sendSigningResult((String) args.arg1, (byte[]) args.arg2);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/media/java/android/media/tv/ad/ITvAdSessionWrapper.java"
+ line="168"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `notifyError()` is a flagged API and should be inside an `if (Flags.enableAdServiceFw())` check (or annotate the surrounding method `executeMessage` with `@FlaggedApi(Flags.FLAG_ENABLE_AD_SERVICE_FW) to transfer requirement to caller`)"
+ errorLine1=" mSessionImpl.notifyError((String) args.arg1, (Bundle) args.arg2);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/media/java/android/media/tv/ad/ITvAdSessionWrapper.java"
+ line="174"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `notifyTvMessage()` is a flagged API and should be inside an `if (Flags.enableAdServiceFw())` check (or annotate the surrounding method `executeMessage` with `@FlaggedApi(Flags.FLAG_ENABLE_AD_SERVICE_FW) to transfer requirement to caller`)"
+ errorLine1=" mSessionImpl.notifyTvMessage((Integer) args.arg1, (Bundle) args.arg2);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/media/java/android/media/tv/ad/ITvAdSessionWrapper.java"
+ line="180"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `notifyTvInputSessionData()` is a flagged API and should be inside an `if (Flags.enableAdServiceFw())` check (or annotate the surrounding method `executeMessage` with `@FlaggedApi(Flags.FLAG_ENABLE_AD_SERVICE_FW) to transfer requirement to caller`)"
+ errorLine1=" mSessionImpl.notifyTvInputSessionData((String) args.arg1, (Bundle) args.arg2);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/media/java/android/media/tv/ad/ITvAdSessionWrapper.java"
+ line="186"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `dispatchInputEvent()` is a flagged API and should be inside an `if (Flags.enableAdServiceFw())` check (or annotate the surrounding method `onInputEvent` with `@FlaggedApi(Flags.FLAG_ENABLE_AD_SERVICE_FW) to transfer requirement to caller`)"
+ errorLine1=" int handled = mSessionImpl.dispatchInputEvent(event, this);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/media/java/android/media/tv/ad/ITvAdSessionWrapper.java"
+ line="309"
+ column="27"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `DISPATCH_IN_PROGRESS` is a flagged API and should be inside an `if (Flags.enableAdServiceFw())` check (or annotate the surrounding method `onInputEvent` with `@FlaggedApi(Flags.FLAG_ENABLE_AD_SERVICE_FW) to transfer requirement to caller`)"
+ errorLine1=" if (handled != TvAdManager.Session.DISPATCH_IN_PROGRESS) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/media/java/android/media/tv/ad/ITvAdSessionWrapper.java"
+ line="310"
+ column="48"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `DISPATCH_HANDLED` is a flagged API and should be inside an `if (Flags.enableAdServiceFw())` check (or annotate the surrounding method `onInputEvent` with `@FlaggedApi(Flags.FLAG_ENABLE_AD_SERVICE_FW) to transfer requirement to caller`)"
+ errorLine1=" event, handled == TvAdManager.Session.DISPATCH_HANDLED);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/media/java/android/media/tv/ad/ITvAdSessionWrapper.java"
+ line="312"
+ column="63"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `onDeregistered()` is a flagged API and should be inside an `if (Flags.emergencyRegistrationState())` check (or annotate the surrounding method `onDeregistered` with `@FlaggedApi(Flags.FLAG_EMERGENCY_REGISTRATION_STATE) to transfer requirement to caller`)"
+ errorLine1=" onDeregistered(info, suggestedAction, attributes);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java"
+ line="576"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `onTechnologyChangeFailed()` is a flagged API and should be inside an `if (Flags.emergencyRegistrationState())` check (or annotate the surrounding method `onTechnologyChangeFailed` with `@FlaggedApi(Flags.FLAG_EMERGENCY_REGISTRATION_STATE) to transfer requirement to caller`)"
+ errorLine1=" onTechnologyChangeFailed(info, attributes);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java"
+ line="703"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `ATTR_REGISTRATION_TYPE_EMERGENCY` is a flagged API and should be inside an `if (Flags.emergencyRegistrationState())` check (or annotate the surrounding method `isEmergency` with `@FlaggedApi(Flags.FLAG_EMERGENCY_REGISTRATION_STATE) to transfer requirement to caller`)"
+ errorLine1=" & ImsRegistrationAttributes.ATTR_REGISTRATION_TYPE_EMERGENCY) != 0;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java"
+ line="753"
+ column="49"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `CAPABILITY_SUPPORTS_SIMULTANEOUS_CALLING` is a flagged API and should be inside an `if (Flags.simultaneousCallingIndications())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_SIMULTANEOUS_CALLING_INDICATIONS) to transfer requirement to caller`)"
+ errorLine1=" Long.numberOfTrailingZeros(CAPABILITY_SUPPORTS_SIMULTANEOUS_CALLING);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/ims/ImsService.java"
+ line="186"
+ column="40"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `CAPABILITY_SUPPORTS_SIMULTANEOUS_CALLING` is a flagged API and should be inside an `if (Flags.simultaneousCallingIndications())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_SIMULTANEOUS_CALLING_INDICATIONS) to transfer requirement to caller`)"
+ errorLine1=" CAPABILITY_SUPPORTS_SIMULTANEOUS_CALLING, "SIMULTANEOUS_CALLING");"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/ims/ImsService.java"
+ line="212"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `InputTransferToken()` is a flagged API and should be inside an `if (Flags.surfaceControlInputReceiver())` check (or annotate the surrounding method `handleRenderSuggestion` with `@FlaggedApi(Flags.FLAG_SURFACE_CONTROL_INPUT_RECEIVER) to transfer requirement to caller`)"
+ errorLine1=" new InputTransferToken(hostInputToken), "InlineSuggestionRenderService");"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/service/autofill/InlineSuggestionRenderService.java"
+ line="170"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `ViewBehavior()` is a flagged API and should be inside an `if (Flags.inputDeviceViewBehaviorApi())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_INPUT_DEVICE_VIEW_BEHAVIOR_API) to transfer requirement to caller`)"
+ errorLine1=" private final ViewBehavior mViewBehavior = new ViewBehavior(this);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/InputDevice.java"
+ line="99"
+ column="48"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `mShouldSmoothScroll` is a flagged API and should be inside an `if (Flags.inputDeviceViewBehaviorApi())` check (or annotate the surrounding method `InputDevice` with `@FlaggedApi(Flags.FLAG_INPUT_DEVICE_VIEW_BEHAVIOR_API) to transfer requirement to caller`)"
+ errorLine1=" mViewBehavior.mShouldSmoothScroll = in.readBoolean();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/InputDevice.java"
+ line="575"
+ column="23"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `mShouldSmoothScroll` is a flagged API and should be inside an `if (Flags.inputDeviceViewBehaviorApi())` check (or annotate the surrounding method `setShouldSmoothScroll` with `@FlaggedApi(Flags.FLAG_INPUT_DEVICE_VIEW_BEHAVIOR_API) to transfer requirement to caller`)"
+ errorLine1=" mViewBehavior.mShouldSmoothScroll = shouldSmoothScroll;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/InputDevice.java"
+ line="1207"
+ column="23"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `mShouldSmoothScroll` is a flagged API and should be inside an `if (Flags.inputDeviceViewBehaviorApi())` check (or annotate the surrounding method `writeToParcel` with `@FlaggedApi(Flags.FLAG_INPUT_DEVICE_VIEW_BEHAVIOR_API) to transfer requirement to caller`)"
+ errorLine1=" out.writeBoolean(mViewBehavior.mShouldSmoothScroll);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/InputDevice.java"
+ line="1642"
+ column="40"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getHandwritingDelegateFlags()` is a flagged API and should be inside an `if (Flags.homeScreenHandwritingDelegator())` check (or annotate the surrounding method `acceptStylusHandwritingDelegation` with `@FlaggedApi(Flags.FLAG_HOME_SCREEN_HANDWRITING_DELEGATOR) to transfer requirement to caller`)"
+ errorLine1=" delegateView.getHandwritingDelegateFlags());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/inputmethod/InputMethodManager.java"
+ line="2880"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getHandwritingDelegateFlags()` is a flagged API and should be inside an `if (Flags.homeScreenHandwritingDelegator())` check (or annotate the surrounding method `acceptStylusHandwritingDelegation` with `@FlaggedApi(Flags.FLAG_HOME_SCREEN_HANDWRITING_DELEGATOR) to transfer requirement to caller`)"
+ errorLine1=" delegateView, delegatorPackageName, delegateView.getHandwritingDelegateFlags());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/inputmethod/InputMethodManager.java"
+ line="2911"
+ column="53"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `acceptStylusHandwritingDelegation()` is a flagged API and should be inside an `if (Flags.homeScreenHandwritingDelegator())` check (or annotate the surrounding method `acceptStylusHandwritingDelegation` with `@FlaggedApi(Flags.FLAG_HOME_SCREEN_HANDWRITING_DELEGATOR) to transfer requirement to caller`)"
+ errorLine1=" acceptStylusHandwritingDelegation("
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/core/java/android/view/inputmethod/InputMethodManager.java"
+ line="2940"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `onError()` is a flagged API and should be inside an `if (Flags.connectionlessHandwriting())` check (or annotate the surrounding method `onResult` with `@FlaggedApi(Flags.FLAG_CONNECTIONLESS_HANDWRITING) to transfer requirement to caller`)"
+ errorLine1=" executor.execute(() -> callback.onError("
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/core/java/android/view/inputmethod/InputMethodManager.java"
+ line="4808"
+ column="44"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `CONNECTIONLESS_HANDWRITING_ERROR_NO_TEXT_RECOGNIZED` is a flagged API and should be inside an `if (Flags.connectionlessHandwriting())` check (or annotate the surrounding method `onResult` with `@FlaggedApi(Flags.FLAG_CONNECTIONLESS_HANDWRITING) to transfer requirement to caller`)"
+ errorLine1=" .CONNECTIONLESS_HANDWRITING_ERROR_NO_TEXT_RECOGNIZED));"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/inputmethod/InputMethodManager.java"
+ line="4810"
+ column="38"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `onResult()` is a flagged API and should be inside an `if (Flags.connectionlessHandwriting())` check (or annotate the surrounding method `onResult` with `@FlaggedApi(Flags.FLAG_CONNECTIONLESS_HANDWRITING) to transfer requirement to caller`)"
+ errorLine1=" executor.execute(() -> callback.onResult(text));"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/inputmethod/InputMethodManager.java"
+ line="4812"
+ column="44"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `onError()` is a flagged API and should be inside an `if (Flags.connectionlessHandwriting())` check (or annotate the surrounding method `onError` with `@FlaggedApi(Flags.FLAG_CONNECTIONLESS_HANDWRITING) to transfer requirement to caller`)"
+ errorLine1=" executor.execute(() -> callback.onError(errorCode));"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/inputmethod/InputMethodManager.java"
+ line="4834"
+ column="40"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `onStartConnectionlessStylusHandwriting()` is a flagged API and should be inside an `if (Flags.connectionlessHandwriting())` check (or annotate the surrounding method `canStartStylusHandwriting` with `@FlaggedApi(Flags.FLAG_CONNECTIONLESS_HANDWRITING) to transfer requirement to caller`)"
+ errorLine1=" if (onStartConnectionlessStylusHandwriting("
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/core/java/android/inputmethodservice/InputMethodService.java"
+ line="1085"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `CONNECTIONLESS_HANDWRITING_ERROR_UNSUPPORTED` is a flagged API and should be inside an `if (Flags.connectionlessHandwriting())` check (or annotate the surrounding method `canStartStylusHandwriting` with `@FlaggedApi(Flags.FLAG_CONNECTIONLESS_HANDWRITING) to transfer requirement to caller`)"
+ errorLine1=" CONNECTIONLESS_HANDWRITING_ERROR_UNSUPPORTED);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/inputmethodservice/InputMethodService.java"
+ line="1096"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `CONNECTIONLESS_HANDWRITING_ERROR_OTHER` is a flagged API and should be inside an `if (Flags.connectionlessHandwriting())` check (or annotate the surrounding method `finishStylusHandwriting` with `@FlaggedApi(Flags.FLAG_CONNECTIONLESS_HANDWRITING) to transfer requirement to caller`)"
+ errorLine1=" mConnectionlessHandwritingCallback.onError(CONNECTIONLESS_HANDWRITING_ERROR_OTHER);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/inputmethodservice/InputMethodService.java"
+ line="2825"
+ column="60"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getAccessibilityBounceKeysThreshold()` is a flagged API and should be inside an `if (Flags.keyboardA11yBounceKeysFlag())` check (or annotate the surrounding method `isAccessibilityBounceKeysEnabled` with `@FlaggedApi(Flags.FLAG_KEYBOARD_A11Y_BOUNCE_KEYS_FLAG) to transfer requirement to caller`)"
+ errorLine1=" return getAccessibilityBounceKeysThreshold(context) != 0;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/hardware/input/InputSettings.java"
+ line="458"
+ column="16"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getAccessibilitySlowKeysThreshold()` is a flagged API and should be inside an `if (Flags.keyboardA11ySlowKeysFlag())` check (or annotate the surrounding method `isAccessibilitySlowKeysEnabled` with `@FlaggedApi(Flags.FLAG_KEYBOARD_A11Y_SLOW_KEYS_FLAG) to transfer requirement to caller`)"
+ errorLine1=" return getAccessibilitySlowKeysThreshold(context) != 0;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/hardware/input/InputSettings.java"
+ line="542"
+ column="16"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `APPEARANCE_TRANSPARENT_CAPTION_BAR_BACKGROUND` is a flagged API and should be inside an `if (Flags.customizableWindowHeaders())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_CUSTOMIZABLE_WINDOW_HEADERS) to transfer requirement to caller`)"
+ errorLine1=" mask = APPEARANCE_TRANSPARENT_CAPTION_BAR_BACKGROUND,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/InsetsFlags.java"
+ line="76"
+ column="28"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `APPEARANCE_TRANSPARENT_CAPTION_BAR_BACKGROUND` is a flagged API and should be inside an `if (Flags.customizableWindowHeaders())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_CUSTOMIZABLE_WINDOW_HEADERS) to transfer requirement to caller`)"
+ errorLine1=" equals = APPEARANCE_TRANSPARENT_CAPTION_BAR_BACKGROUND,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/InsetsFlags.java"
+ line="77"
+ column="30"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `APPEARANCE_LIGHT_CAPTION_BARS` is a flagged API and should be inside an `if (Flags.customizableWindowHeaders())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_CUSTOMIZABLE_WINDOW_HEADERS) to transfer requirement to caller`)"
+ errorLine1=" mask = APPEARANCE_LIGHT_CAPTION_BARS,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/InsetsFlags.java"
+ line="80"
+ column="28"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `APPEARANCE_LIGHT_CAPTION_BARS` is a flagged API and should be inside an `if (Flags.customizableWindowHeaders())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_CUSTOMIZABLE_WINDOW_HEADERS) to transfer requirement to caller`)"
+ errorLine1=" equals = APPEARANCE_LIGHT_CAPTION_BARS,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/InsetsFlags.java"
+ line="81"
+ column="30"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `countUriRelativeFilterGroups()` is a flagged API and should be inside an `if (Flags.relativeReferenceIntentFilters())` check (or annotate the surrounding method `toLongString` with `@FlaggedApi(Flags.FLAG_RELATIVE_REFERENCE_INTENT_FILTERS) to transfer requirement to caller`)"
+ errorLine1=" if (Flags.relativeReferenceIntentFilters() && countUriRelativeFilterGroups() > 0) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/content/IntentFilter.java"
+ line="577"
+ column="55"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `matchGroupsToUri()` is a flagged API and should be inside an `if (Flags.relativeReferenceIntentFilters())` check (or annotate the surrounding method `matchRelRefGroups` with `@FlaggedApi(Flags.FLAG_RELATIVE_REFERENCE_INTENT_FILTERS) to transfer requirement to caller`)"
+ errorLine1=" return UriRelativeFilterGroup.matchGroupsToUri(mUriRelativeFilterGroups, data);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/content/IntentFilter.java"
+ line="1839"
+ column="16"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `isPrivateProfile()` is a flagged API and should be inside an `if (Flags.allowPrivateProfile())` check (or annotate the surrounding method `getPrivateProfile` with `@FlaggedApi(Flags.FLAG_ALLOW_PRIVATE_PROFILE) to transfer requirement to caller`)"
+ errorLine1=" if (userInfo.isPrivateProfile()) return userInfo;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/com/android/internal/app/IntentForwarderActivity.java"
+ line="631"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `uptimeNanos()` is a flagged API and should be inside an `if (Flags.adpfGpuReportActualWorkDuration())` check (or annotate the surrounding method `postEventLogToWorkerThread` with `@FlaggedApi(Flags.FLAG_ADPF_GPU_REPORT_ACTUAL_WORK_DURATION) to transfer requirement to caller`)"
+ errorLine1=" final long realtimeNanos = SystemClock.uptimeNanos();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/com/android/internal/jank/InteractionJankMonitor.java"
+ line="606"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `KEYCODE_SCREENSHOT` is a flagged API and should be inside an `if (Flags.emojiAndScreenshotKeycodesAvailable())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_EMOJI_AND_SCREENSHOT_KEYCODES_AVAILABLE) to transfer requirement to caller`)"
+ errorLine1=" public static final int LAST_KEYCODE = KEYCODE_SCREENSHOT;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/KeyEvent.java"
+ line="955"
+ column="44"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `isMgf1DigestsSpecified()` is a flagged API and should be inside an `if (Flags.mgf1DigestSetterV2())` check (or annotate the surrounding method `Builder` with `@FlaggedApi(Flags.FLAG_MGF1_DIGEST_SETTER_V2) to transfer requirement to caller`)"
+ errorLine1=" if (sourceSpec.isMgf1DigestsSpecified()) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/keystore/java/android/security/keystore/KeyGenParameterSpec.java"
+ line="1025"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getMgf1Digests()` is a flagged API and should be inside an `if (Flags.mgf1DigestSetterV2())` check (or annotate the surrounding method `Builder` with `@FlaggedApi(Flags.FLAG_MGF1_DIGEST_SETTER_V2) to transfer requirement to caller`)"
+ errorLine1=" mMgf1Digests = sourceSpec.getMgf1Digests();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/keystore/java/android/security/keystore/KeyGenParameterSpec.java"
+ line="1026"
+ column="32"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `BIOMETRIC_NO_AUTHENTICATION` is a flagged API and should be inside an `if (Flags.lastAuthenticationTime())` check (or annotate the surrounding method `getLastAuthTime` with `@FlaggedApi(Flags.FLAG_LAST_AUTHENTICATION_TIME) to transfer requirement to caller`)"
+ errorLine1=" return BiometricConstants.BIOMETRIC_NO_AUTHENTICATION;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/keystore/java/android/security/KeyStoreAuthorization.java"
+ line="139"
+ column="39"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `BIOMETRIC_NO_AUTHENTICATION` is a flagged API and should be inside an `if (Flags.lastAuthenticationTime())` check (or annotate the surrounding method `getLastAuthTime` with `@FlaggedApi(Flags.FLAG_LAST_AUTHENTICATION_TIME) to transfer requirement to caller`)"
+ errorLine1=" return BiometricConstants.BIOMETRIC_NO_AUTHENTICATION;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/keystore/java/android/security/KeyStoreAuthorization.java"
+ line="145"
+ column="39"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `PERSISTENT_DATA_BLOCK_SERVICE` is a flagged API and should be inside an `if (Flags.frpEnforcement())` check (or annotate the surrounding method `createConfirmFactoryResetCredentialIntent` with `@FlaggedApi(Flags.FLAG_FRP_ENFORCEMENT) to transfer requirement to caller`)"
+ errorLine1=" ServiceManager.getService(Context.PERSISTENT_DATA_BLOCK_SERVICE));"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/KeyguardManager.java"
+ line="365"
+ column="55"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `isPrivateProfile()` is a flagged API and should be inside an `if (Flags.allowPrivateProfile())` check (or annotate the surrounding method `getProfiles` with `@FlaggedApi(Flags.FLAG_ALLOW_PRIVATE_PROFILE) to transfer requirement to caller`)"
+ errorLine1=" && mUserManager.isPrivateProfile())) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/content/pm/LauncherApps.java"
+ line="712"
+ column="24"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `computeDrawingBoundingBox()` is a flagged API and should be inside an `if (Flags.useBoundsForWidth())` check (or annotate the surrounding method `draw` with `@FlaggedApi(Flags.FLAG_USE_BOUNDS_FOR_WIDTH) to transfer requirement to caller`)"
+ errorLine1=" RectF drawingRect = computeDrawingBoundingBox();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/text/Layout.java"
+ line="498"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getLineSpacingMultiplier()` is a flagged API and should be inside an `if (Flags.useBoundsForWidth())` check (or annotate the surrounding method `getSpacingMultiplier` with `@FlaggedApi(Flags.FLAG_USE_BOUNDS_FOR_WIDTH) to transfer requirement to caller`)"
+ errorLine1=" return getLineSpacingMultiplier();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/text/Layout.java"
+ line="4341"
+ column="16"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getLineSpacingAmount()` is a flagged API and should be inside an `if (Flags.useBoundsForWidth())` check (or annotate the surrounding method `getSpacingAdd` with `@FlaggedApi(Flags.FLAG_USE_BOUNDS_FOR_WIDTH) to transfer requirement to caller`)"
+ errorLine1=" return getLineSpacingAmount();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/text/Layout.java"
+ line="4368"
+ column="16"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `LINE_BREAK_STYLE_UNSPECIFIED` is a flagged API and should be inside an `if (Flags.noBreakNoHyphenationSpan())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_NO_BREAK_NO_HYPHENATION_SPAN) to transfer requirement to caller`)"
+ errorLine1=" private @LineBreakStyle int mLineBreakStyle = LineBreakConfig.LINE_BREAK_STYLE_UNSPECIFIED;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/graphics/java/android/graphics/text/LineBreakConfig.java"
+ line="276"
+ column="71"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `LINE_BREAK_WORD_STYLE_UNSPECIFIED` is a flagged API and should be inside an `if (Flags.noBreakNoHyphenationSpan())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_NO_BREAK_NO_HYPHENATION_SPAN) to transfer requirement to caller`)"
+ errorLine1=" LineBreakConfig.LINE_BREAK_WORD_STYLE_UNSPECIFIED;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/graphics/java/android/graphics/text/LineBreakConfig.java"
+ line="280"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `HYPHENATION_UNSPECIFIED` is a flagged API and should be inside an `if (Flags.noBreakNoHyphenationSpan())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_NO_BREAK_NO_HYPHENATION_SPAN) to transfer requirement to caller`)"
+ errorLine1=" private @Hyphenation int mHyphenation = LineBreakConfig.HYPHENATION_UNSPECIFIED;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/graphics/java/android/graphics/text/LineBreakConfig.java"
+ line="282"
+ column="65"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `LINE_BREAK_STYLE_UNSPECIFIED` is a flagged API and should be inside an `if (Flags.noBreakNoHyphenationSpan())` check (or annotate the surrounding method `reset` with `@FlaggedApi(Flags.FLAG_NO_BREAK_NO_HYPHENATION_SPAN) to transfer requirement to caller`)"
+ errorLine1=" mLineBreakStyle = LINE_BREAK_STYLE_UNSPECIFIED;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/graphics/java/android/graphics/text/LineBreakConfig.java"
+ line="343"
+ column="35"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `LINE_BREAK_WORD_STYLE_UNSPECIFIED` is a flagged API and should be inside an `if (Flags.noBreakNoHyphenationSpan())` check (or annotate the surrounding method `reset` with `@FlaggedApi(Flags.FLAG_NO_BREAK_NO_HYPHENATION_SPAN) to transfer requirement to caller`)"
+ errorLine1=" mLineBreakWordStyle = LINE_BREAK_WORD_STYLE_UNSPECIFIED;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/graphics/java/android/graphics/text/LineBreakConfig.java"
+ line="344"
+ column="39"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `HYPHENATION_UNSPECIFIED` is a flagged API and should be inside an `if (Flags.noBreakNoHyphenationSpan())` check (or annotate the surrounding method `reset` with `@FlaggedApi(Flags.FLAG_NO_BREAK_NO_HYPHENATION_SPAN) to transfer requirement to caller`)"
+ errorLine1=" mHyphenation = HYPHENATION_UNSPECIFIED;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/graphics/java/android/graphics/text/LineBreakConfig.java"
+ line="345"
+ column="32"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `LINE_BREAK_STYLE_AUTO` is a flagged API and should be inside an `if (Flags.wordStyleAuto())` check (or annotate the surrounding method `getResolvedLineBreakStyle` with `@FlaggedApi(Flags.FLAG_WORD_STYLE_AUTO) to transfer requirement to caller`)"
+ errorLine1=" defaultStyle = LINE_BREAK_STYLE_AUTO;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/graphics/java/android/graphics/text/LineBreakConfig.java"
+ line="492"
+ column="28"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `LINE_BREAK_STYLE_UNSPECIFIED` is a flagged API and should be inside an `if (Flags.noBreakNoHyphenationSpan())` check (or annotate the surrounding method `getResolvedLineBreakStyle` with `@FlaggedApi(Flags.FLAG_NO_BREAK_NO_HYPHENATION_SPAN) to transfer requirement to caller`)"
+ errorLine1=" return config.mLineBreakStyle == LINE_BREAK_STYLE_UNSPECIFIED"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/graphics/java/android/graphics/text/LineBreakConfig.java"
+ line="499"
+ column="42"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `LINE_BREAK_WORD_STYLE_AUTO` is a flagged API and should be inside an `if (Flags.wordStyleAuto())` check (or annotate the surrounding method `getResolvedLineBreakWordStyle` with `@FlaggedApi(Flags.FLAG_WORD_STYLE_AUTO) to transfer requirement to caller`)"
+ errorLine1=" defaultWordStyle = LINE_BREAK_WORD_STYLE_AUTO;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/graphics/java/android/graphics/text/LineBreakConfig.java"
+ line="527"
+ column="32"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `LINE_BREAK_WORD_STYLE_UNSPECIFIED` is a flagged API and should be inside an `if (Flags.noBreakNoHyphenationSpan())` check (or annotate the surrounding method `getResolvedLineBreakWordStyle` with `@FlaggedApi(Flags.FLAG_NO_BREAK_NO_HYPHENATION_SPAN) to transfer requirement to caller`)"
+ errorLine1=" return config.mLineBreakWordStyle == LINE_BREAK_WORD_STYLE_UNSPECIFIED"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/graphics/java/android/graphics/text/LineBreakConfig.java"
+ line="534"
+ column="46"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `HYPHENATION_ENABLED` is a flagged API and should be inside an `if (Flags.noBreakNoHyphenationSpan())` check (or annotate the surrounding method `getResolvedHyphenation` with `@FlaggedApi(Flags.FLAG_NO_BREAK_NO_HYPHENATION_SPAN) to transfer requirement to caller`)"
+ errorLine1=" return HYPHENATION_ENABLED;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/graphics/java/android/graphics/text/LineBreakConfig.java"
+ line="559"
+ column="20"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `HYPHENATION_UNSPECIFIED` is a flagged API and should be inside an `if (Flags.noBreakNoHyphenationSpan())` check (or annotate the surrounding method `getResolvedHyphenation` with `@FlaggedApi(Flags.FLAG_NO_BREAK_NO_HYPHENATION_SPAN) to transfer requirement to caller`)"
+ errorLine1=" return config.mHyphenation == HYPHENATION_UNSPECIFIED"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/graphics/java/android/graphics/text/LineBreakConfig.java"
+ line="561"
+ column="39"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `HYPHENATION_ENABLED` is a flagged API and should be inside an `if (Flags.noBreakNoHyphenationSpan())` check (or annotate the surrounding method `getResolvedHyphenation` with `@FlaggedApi(Flags.FLAG_NO_BREAK_NO_HYPHENATION_SPAN) to transfer requirement to caller`)"
+ errorLine1=" ? HYPHENATION_ENABLED : config.mHyphenation;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/graphics/java/android/graphics/text/LineBreakConfig.java"
+ line="562"
+ column="19"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getSessionId()` is a flagged API and should be inside an `if (Flags.loudnessConfiguratorApi())` check (or annotate the surrounding method `dispatchLoudnessCodecParameterChange` with `@FlaggedApi(Flags.FLAG_LOUDNESS_CONFIGURATOR_API) to transfer requirement to caller`)"
+ errorLine1=" if (lcConfig.getSessionId() == sessionId) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/media/java/android/media/LoudnessCodecDispatcher.java"
+ line="85"
+ column="29"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `mediaCodecsConsume()` is a flagged API and should be inside an `if (Flags.loudnessConfiguratorApi())` check (or annotate the surrounding method `dispatchLoudnessCodecParameterChange` with `@FlaggedApi(Flags.FLAG_LOUDNESS_CONFIGURATOR_API) to transfer requirement to caller`)"
+ errorLine1=" lcConfig.mediaCodecsConsume(mcEntry -> {"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/media/java/android/media/LoudnessCodecDispatcher.java"
+ line="86"
+ column="29"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `onLoudnessCodecUpdate()` is a flagged API and should be inside an `if (Flags.loudnessConfiguratorApi())` check (or annotate the surrounding method `dispatchLoudnessCodecParameterChange` with `@FlaggedApi(Flags.FLAG_LOUDNESS_CONFIGURATOR_API) to transfer requirement to caller`)"
+ errorLine1=" l.onLoudnessCodecUpdate(mediaCodec,"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/media/java/android/media/LoudnessCodecDispatcher.java"
+ line="110"
+ column="53"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.provider.user_keys")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="29"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.provider.user_keys")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="29"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.provider.user_keys")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="29"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.provider.user_keys")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="29"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("com.android.internal.camera.flags.camera_hsum_permission")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="552"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("com.android.internal.camera.flags.camera_privacy_allowlist")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="561"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("com.android.net.thread.platform.flags.thread_enabled_platform")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="992"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.net.platform.flags.register_nsd_offload_engine")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="1055"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.content.pm.quarantined_enabled")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="1101"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.content.pm.quarantined_enabled")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="1101"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("com.android.window.flags.screen_recording_callbacks")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="1310"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("com.android.window.flags.screen_recording_callbacks")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="1310"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("com.android.window.flags.screen_recording_callbacks")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="1310"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("com.android.window.flags.screen_recording_callbacks")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="1310"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("com.android.window.flags.screen_recording_callbacks")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="1310"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.security.frp_enforcement")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="1434"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.security.frp_enforcement")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="1434"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("com.android.internal.telephony.flags.use_oem_domain_selection_service")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="1639"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("com.android.server.telecom.flags.telecom_resolve_hidden_dependencies")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="1726"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("com.android.server.telecom.flags.telecom_resolve_hidden_dependencies")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="1726"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("com.android.server.telecom.flags.telecom_resolve_hidden_dependencies")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="1726"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("com.android.server.telecom.flags.telecom_resolve_hidden_dependencies")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="1726"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.multiuser.enable_permission_to_access_hidden_profiles")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="1839"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.multiuser.enable_permission_to_access_hidden_profiles")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="1839"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.multiuser.enable_permission_to_access_hidden_profiles")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="1839"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.multiuser.enable_permission_to_access_hidden_profiles")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="1839"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.multiuser.enable_permission_to_access_hidden_profiles")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="1839"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.multiuser.enable_permission_to_access_hidden_profiles")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="1839"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.multiuser.enable_permission_to_access_hidden_profiles")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="1839"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.multiuser.enable_permission_to_access_hidden_profiles")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="1839"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.multiuser.enable_permission_to_access_hidden_profiles")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="1839"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.multiuser.enable_permission_to_access_hidden_profiles")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="1839"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.multiuser.enable_permission_to_access_hidden_profiles")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="1839"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.multiuser.enable_permission_to_access_hidden_profiles")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="1839"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.multiuser.enable_permission_to_access_hidden_profiles")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="1839"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.multiuser.enable_permission_to_access_hidden_profiles")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="1839"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.multiuser.enable_permission_to_access_hidden_profiles")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="1839"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.multiuser.enable_permission_to_access_hidden_profiles")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="1839"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.multiuser.enable_permission_to_access_hidden_profiles")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="1839"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.multiuser.enable_permission_to_access_hidden_profiles")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="1839"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.multiuser.enable_permission_to_access_hidden_profiles")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="1848"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.multiuser.enable_permission_to_access_hidden_profiles")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="1848"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.multiuser.enable_permission_to_access_hidden_profiles")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="1848"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.multiuser.enable_permission_to_access_hidden_profiles")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="1848"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.multiuser.enable_permission_to_access_hidden_profiles")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="1848"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.multiuser.enable_permission_to_access_hidden_profiles")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="1848"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.multiuser.enable_permission_to_access_hidden_profiles")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="1848"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.multiuser.enable_permission_to_access_hidden_profiles")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="1848"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.multiuser.enable_permission_to_access_hidden_profiles")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="1848"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.multiuser.enable_permission_to_access_hidden_profiles")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="1848"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.multiuser.enable_permission_to_access_hidden_profiles")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="1848"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.multiuser.enable_permission_to_access_hidden_profiles")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="1848"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.multiuser.enable_permission_to_access_hidden_profiles")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="1848"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.multiuser.enable_permission_to_access_hidden_profiles")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="1848"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.multiuser.enable_permission_to_access_hidden_profiles")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="1848"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.multiuser.enable_permission_to_access_hidden_profiles")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="1848"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.multiuser.enable_permission_to_access_hidden_profiles")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="1848"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.multiuser.enable_permission_to_access_hidden_profiles")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="1848"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("com.android.net.thread.platform.flags.thread_user_restriction_enabled")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="2292"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.app.admin.flags.assist_content_user_restriction_enabled")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="2300"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.app.admin.flags.security_log_v2_enabled")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="2363"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.app.admin.flags.security_log_v2_enabled")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="2363"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.app.admin.flags.security_log_v2_enabled")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="2363"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.app.admin.flags.security_log_v2_enabled")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="2363"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.app.admin.flags.security_log_v2_enabled")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="2363"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.app.admin.flags.device_theft_api_enabled")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="2489"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.app.admin.flags.device_theft_api_enabled")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="2489"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.view.contentprotection.flags.manage_device_policy_enabled")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="2523"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.view.contentprotection.flags.manage_device_policy_enabled")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="2523"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.view.contentprotection.flags.manage_device_policy_enabled")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="2523"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.app.admin.flags.esim_management_enabled")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="2532"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.app.admin.flags.esim_management_enabled")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="2532"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.app.admin.flags.esim_management_enabled")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="2532"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.app.admin.flags.esim_management_enabled")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="2532"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.app.admin.flags.dedicated_device_control_api_enabled")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="2539"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.app.admin.flags.dedicated_device_control_api_enabled")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="2546"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.app.admin.flags.dedicated_device_control_api_enabled")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="2553"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.permission.flags.enhanced_confirmation_mode_apis_enabled")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="2596"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.permission.flags.enhanced_confirmation_mode_apis_enabled")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="2596"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.permission.flags.enhanced_confirmation_mode_apis_enabled")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="2596"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("com.android.window.flags.untrusted_embedding_any_app_permission")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="2661"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("com.android.window.flags.always_update_wallpaper_permission")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="2904"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("com.android.window.flags.always_update_wallpaper_permission")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="2904"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("com.android.server.feature.flags.enable_read_dropbox_permission")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="3364"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("com.android.server.feature.flags.enable_read_dropbox_permission")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="3364"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("com.android.server.feature.flags.enable_read_dropbox_permission")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="3364"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("com.android.server.accessibility.motion_event_observing")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="3584"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.media.tv.flags.enable_ad_service_fw")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="3971"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.content.pm.get_resolved_apk_path")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="4252"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.content.pm.get_resolved_apk_path")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="4252"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.companion.device_presence")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="4465"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.companion.device_presence")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="4465"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.companion.flags.companion_transport_apis")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="4475"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.companion.flags.companion_transport_apis")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="4475"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.companion.flags.companion_transport_apis")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="4475"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.companion.flags.companion_transport_apis")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="4475"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.companion.flags.companion_transport_apis")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="4475"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.companion.flags.companion_transport_apis")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="4475"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("com.android.media.flags.enable_privileged_routing_for_media_routing_control")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="4780"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("com.android.media.flags.enable_privileged_routing_for_media_routing_control")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="4780"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("com.android.media.flags.enable_privileged_routing_for_media_routing_control")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="4780"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("com.android.media.flags.enable_privileged_routing_for_media_routing_control")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="4780"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("com.android.media.flags.enable_privileged_routing_for_media_routing_control")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="4780"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("com.android.media.flags.enable_privileged_routing_for_media_routing_control")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="4780"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("com.android.media.flags.enable_privileged_routing_for_media_routing_control")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="4780"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.app.usage.report_usage_stats_permission")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="4938"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.app.usage.report_usage_stats_permission")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="4938"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.app.usage.report_usage_stats_permission")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="4938"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.app.usage.report_usage_stats_permission")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="4938"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.hardware.biometrics.custom_biometric_prompt")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="5392"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.hardware.biometrics.custom_biometric_prompt")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="5392"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.hardware.biometrics.custom_biometric_prompt")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="5392"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.hardware.biometrics.custom_biometric_prompt")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="5392"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.hardware.biometrics.custom_biometric_prompt")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="5392"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.hardware.biometrics.custom_biometric_prompt")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="5392"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.hardware.biometrics.custom_biometric_prompt")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="5392"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.hardware.biometrics.custom_biometric_prompt")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="5392"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.hardware.biometrics.custom_biometric_prompt")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="5392"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.hardware.biometrics.custom_biometric_prompt")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="5392"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.hardware.biometrics.custom_biometric_prompt")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="5392"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.hardware.biometrics.custom_biometric_prompt")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="5392"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.permission.flags.sensitive_notification_app_protection")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="5535"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("com.android.server.telecom.flags.telecom_resolve_hidden_dependencies")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="5706"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("com.android.server.telecom.flags.telecom_resolve_hidden_dependencies")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="5706"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("com.android.server.telecom.flags.telecom_resolve_hidden_dependencies")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="5706"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("com.android.server.telecom.flags.telecom_resolve_hidden_dependencies")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="5706"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("com.android.server.telecom.flags.telecom_resolve_hidden_dependencies")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="5706"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("com.android.server.telecom.flags.telecom_resolve_hidden_dependencies")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="5706"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("com.android.server.telecom.flags.telecom_resolve_hidden_dependencies")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="5706"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("com.android.server.telecom.flags.telecom_resolve_hidden_dependencies")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="5706"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("com.android.server.telecom.flags.telecom_resolve_hidden_dependencies")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="5706"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("com.android.server.telecom.flags.telecom_resolve_hidden_dependencies")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="5714"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("com.android.server.telecom.flags.telecom_resolve_hidden_dependencies")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="5714"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("com.android.server.telecom.flags.telecom_resolve_hidden_dependencies")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="5714"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("com.android.server.telecom.flags.telecom_resolve_hidden_dependencies")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="5714"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("com.android.server.telecom.flags.telecom_resolve_hidden_dependencies")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="5714"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("com.android.server.telecom.flags.telecom_resolve_hidden_dependencies")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="5714"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("com.android.server.telecom.flags.telecom_resolve_hidden_dependencies")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="5714"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("com.android.server.telecom.flags.telecom_resolve_hidden_dependencies")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="5714"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("com.android.server.telecom.flags.telecom_resolve_hidden_dependencies")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="5714"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.app.contextualsearch.flags.enable_service")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="5829"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.app.contextualsearch.flags.enable_service")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="5829"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.content.pm.introduce_media_processing_type")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="5935"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.content.pm.introduce_media_processing_type")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="5935"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.content.pm.introduce_media_processing_type")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="5935"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.permission.flags.voice_activation_permission_apis")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="6084"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.permission.flags.voice_activation_permission_apis")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="6084"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.nfc.enable_nfc_mainline")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="6304"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.app.ondeviceintelligence.flags.enable_on_device_intelligence")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="6544"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.app.ondeviceintelligence.flags.enable_on_device_intelligence")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="6544"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.app.ondeviceintelligence.flags.enable_on_device_intelligence")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="6544"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.app.ondeviceintelligence.flags.enable_on_device_intelligence")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="6544"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.app.ondeviceintelligence.flags.enable_on_device_intelligence")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="6544"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.app.ondeviceintelligence.flags.enable_on_device_intelligence")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="6544"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.app.ondeviceintelligence.flags.enable_on_device_intelligence")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="6544"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.app.ondeviceintelligence.flags.enable_on_device_intelligence")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="6544"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.app.ondeviceintelligence.flags.enable_on_device_intelligence")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="6544"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.app.ondeviceintelligence.flags.enable_on_device_intelligence")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="6544"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.app.ondeviceintelligence.flags.enable_on_device_intelligence")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="6552"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.app.ondeviceintelligence.flags.enable_on_device_intelligence")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="6560"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.app.get_binding_uid_importance")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="6660"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.app.get_binding_uid_importance")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="6660"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.permission.flags.factory_reset_prep_permission_apis")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="6676"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("com.android.input.flags.override_key_behavior_permission_apis")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="6693"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.view.flags.sensitive_content_app_protection_api")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="6704"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.app.bic_client")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="6715"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.app.bic_client")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="6715"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.app.system_terms_of_address_enabled")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="6723"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.app.system_terms_of_address_enabled")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="6723"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.app.system_terms_of_address_enabled")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="6723"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.content.pm.emergency_install_permission")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="6732"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("com.android.server.power.feature.flags.enable_early_screen_timeout_detector")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="6747"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.security.fsverity_api")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/Manifest.java"
+ line="6755"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Class `LineBreakConfigSpan` is a flagged API and should be inside an `if (Flags.noBreakNoHyphenationSpan())` check (or annotate the surrounding method `buildForMeasurement` with `@FlaggedApi(Flags.FLAG_NO_BREAK_NO_HYPHENATION_SPAN) to transfer requirement to caller`)"
+ errorLine1=" LineBreakConfigSpan.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/text/MeasuredParagraph.java"
+ line="471"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Class `LineBreakConfigSpan` is a flagged API and should be inside an `if (Flags.noBreakNoHyphenationSpan())` check (or annotate the surrounding method `buildForMeasurement` with `@FlaggedApi(Flags.FLAG_NO_BREAK_NO_HYPHENATION_SPAN) to transfer requirement to caller`)"
+ errorLine1=" LineBreakConfigSpan.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/text/MeasuredParagraph.java"
+ line="476"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Class `LineBreakConfigSpan` is a flagged API and should be inside an `if (Flags.noBreakNoHyphenationSpan())` check (or annotate the surrounding method `buildForMeasurement` with `@FlaggedApi(Flags.FLAG_NO_BREAK_NO_HYPHENATION_SPAN) to transfer requirement to caller`)"
+ errorLine1=" LineBreakConfigSpan.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/text/MeasuredParagraph.java"
+ line="479"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Class `LineBreakConfigSpan` is a flagged API and should be inside an `if (Flags.noBreakNoHyphenationSpan())` check (or annotate the surrounding method `buildForStaticLayoutInternal` with `@FlaggedApi(Flags.FLAG_NO_BREAK_NO_HYPHENATION_SPAN) to transfer requirement to caller`)"
+ errorLine1=" LineBreakConfigSpan.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/text/MeasuredParagraph.java"
+ line="625"
+ column="29"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Class `LineBreakConfigSpan` is a flagged API and should be inside an `if (Flags.noBreakNoHyphenationSpan())` check (or annotate the surrounding method `buildForStaticLayoutInternal` with `@FlaggedApi(Flags.FLAG_NO_BREAK_NO_HYPHENATION_SPAN) to transfer requirement to caller`)"
+ errorLine1=" LineBreakConfigSpan.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/text/MeasuredParagraph.java"
+ line="630"
+ column="29"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Class `LineBreakConfigSpan` is a flagged API and should be inside an `if (Flags.noBreakNoHyphenationSpan())` check (or annotate the surrounding method `buildForStaticLayoutInternal` with `@FlaggedApi(Flags.FLAG_NO_BREAK_NO_HYPHENATION_SPAN) to transfer requirement to caller`)"
+ errorLine1=" LineBreakConfigSpan.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/text/MeasuredParagraph.java"
+ line="634"
+ column="56"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `onAppendReplacementRun()` is a flagged API and should be inside an `if (Flags.noBreakNoHyphenationSpan())` check (or annotate the surrounding method `applyReplacementRun` with `@FlaggedApi(Flags.FLAG_NO_BREAK_NO_HYPHENATION_SPAN) to transfer requirement to caller`)"
+ errorLine1=" testCallback.onAppendReplacementRun(paint, end - start, width);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/text/MeasuredParagraph.java"
+ line="784"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `TEXT_RUN_FLAG_LEFT_EDGE` is a flagged API and should be inside an `if (Flags.letterSpacingJustification())` check (or annotate the surrounding method `applyStyleRun` with `@FlaggedApi(Flags.FLAG_LETTER_SPACING_JUSTIFICATION) to transfer requirement to caller`)"
+ errorLine1=" | (Paint.TEXT_RUN_FLAG_LEFT_EDGE | Paint.TEXT_RUN_FLAG_RIGHT_EDGE));"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/text/MeasuredParagraph.java"
+ line="802"
+ column="34"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `TEXT_RUN_FLAG_RIGHT_EDGE` is a flagged API and should be inside an `if (Flags.letterSpacingJustification())` check (or annotate the surrounding method `applyStyleRun` with `@FlaggedApi(Flags.FLAG_LETTER_SPACING_JUSTIFICATION) to transfer requirement to caller`)"
+ errorLine1=" | (Paint.TEXT_RUN_FLAG_LEFT_EDGE | Paint.TEXT_RUN_FLAG_RIGHT_EDGE));"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/text/MeasuredParagraph.java"
+ line="802"
+ column="66"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `onAppendStyleRun()` is a flagged API and should be inside an `if (Flags.noBreakNoHyphenationSpan())` check (or annotate the surrounding method `applyStyleRun` with `@FlaggedApi(Flags.FLAG_NO_BREAK_NO_HYPHENATION_SPAN) to transfer requirement to caller`)"
+ errorLine1=" testCallback.onAppendStyleRun(paint, config, end - start, false);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/text/MeasuredParagraph.java"
+ line="814"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `TEXT_RUN_FLAG_LEFT_EDGE` is a flagged API and should be inside an `if (Flags.letterSpacingJustification())` check (or annotate the surrounding method `applyStyleRun` with `@FlaggedApi(Flags.FLAG_LETTER_SPACING_JUSTIFICATION) to transfer requirement to caller`)"
+ errorLine1=" | (Paint.TEXT_RUN_FLAG_LEFT_EDGE | Paint.TEXT_RUN_FLAG_RIGHT_EDGE));"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/text/MeasuredParagraph.java"
+ line="828"
+ column="42"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `TEXT_RUN_FLAG_RIGHT_EDGE` is a flagged API and should be inside an `if (Flags.letterSpacingJustification())` check (or annotate the surrounding method `applyStyleRun` with `@FlaggedApi(Flags.FLAG_LETTER_SPACING_JUSTIFICATION) to transfer requirement to caller`)"
+ errorLine1=" | (Paint.TEXT_RUN_FLAG_LEFT_EDGE | Paint.TEXT_RUN_FLAG_RIGHT_EDGE));"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/text/MeasuredParagraph.java"
+ line="828"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `onAppendStyleRun()` is a flagged API and should be inside an `if (Flags.noBreakNoHyphenationSpan())` check (or annotate the surrounding method `applyStyleRun` with `@FlaggedApi(Flags.FLAG_NO_BREAK_NO_HYPHENATION_SPAN) to transfer requirement to caller`)"
+ errorLine1=" testCallback.onAppendStyleRun(paint, config, levelEnd - levelStart, isRtl);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/text/MeasuredParagraph.java"
+ line="840"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getLineBreakConfig()` is a flagged API and should be inside an `if (Flags.noBreakNoHyphenationSpan())` check (or annotate the surrounding method `applyMetricsAffectingSpan` with `@FlaggedApi(Flags.FLAG_NO_BREAK_NO_HYPHENATION_SPAN) to transfer requirement to caller`)"
+ errorLine1=" mLineBreakConfigBuilder.merge(lbcSpan.getLineBreakConfig());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/text/MeasuredParagraph.java"
+ line="888"
+ column="47"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `merge()` is a flagged API and should be inside an `if (Flags.noBreakNoHyphenationSpan())` check (or annotate the surrounding method `applyMetricsAffectingSpan` with `@FlaggedApi(Flags.FLAG_NO_BREAK_NO_HYPHENATION_SPAN) to transfer requirement to caller`)"
+ errorLine1=" mLineBreakConfigBuilder.merge(lbcSpan.getLineBreakConfig());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/text/MeasuredParagraph.java"
+ line="888"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `HYPHENATION_ENABLED` is a flagged API and should be inside an `if (Flags.noBreakNoHyphenationSpan())` check (or annotate the surrounding method `appendStyleRun` with `@FlaggedApi(Flags.FLAG_NO_BREAK_NO_HYPHENATION_SPAN) to transfer requirement to caller`)"
+ errorLine1=" == LineBreakConfig.HYPHENATION_ENABLED;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/graphics/java/android/graphics/text/MeasuredText.java"
+ line="319"
+ column="40"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `onOutputBuffersAvailable()` is a flagged API and should be inside an `if (Flags.largeAudioFrame())` check (or annotate the surrounding method `handleCallback` with `@FlaggedApi(Flags.FLAG_LARGE_AUDIO_FRAME) to transfer requirement to caller`)"
+ errorLine1=" mCallback.onOutputBuffersAvailable("
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/media/java/android/media/MediaCodec.java"
+ line="1985"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `CONFIGURE_FLAG_DETACHED_SURFACE` is a flagged API and should be inside an `if (Flags.nullOutputSurface())` check (or annotate the surrounding method `configure` with `@FlaggedApi(Flags.FLAG_NULL_OUTPUT_SURFACE) to transfer requirement to caller`)"
+ errorLine1=" if (surface == null && (flags & CONFIGURE_FLAG_DETACHED_SURFACE) != 0 && !canDetach) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/media/java/android/media/MediaCodec.java"
+ line="2371"
+ column="45"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `CONFIGURE_FLAG_DETACHED_SURFACE` is a flagged API and should be inside an `if (Flags.nullOutputSurface())` check (or annotate the surrounding method `configure` with `@FlaggedApi(Flags.FLAG_NULL_OUTPUT_SURFACE) to transfer requirement to caller`)"
+ errorLine1=" if (surface == null && (flags & CONFIGURE_FLAG_DETACHED_SURFACE) != 0) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/media/java/android/media/MediaCodec.java"
+ line="2422"
+ column="45"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `FEATURE_DynamicColorAspects` is a flagged API and should be inside an `if (Flags.dynamicColorAspects())` check (or annotate the surrounding method `getDecoderFeatures` with `@FlaggedApi(Flags.FLAG_DYNAMIC_COLOR_ASPECTS) to transfer requirement to caller`)"
+ errorLine1=" features.add(new Feature(FEATURE_DynamicColorAspects, (1 << 8), true));"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/media/java/android/media/MediaCodecInfo.java"
+ line="832"
+ column="46"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `FEATURE_DetachedSurface` is a flagged API and should be inside an `if (Flags.nullOutputSurface())` check (or annotate the surrounding method `getDecoderFeatures` with `@FlaggedApi(Flags.FLAG_NULL_OUTPUT_SURFACE) to transfer requirement to caller`)"
+ errorLine1=" features.add(new Feature(FEATURE_DetachedSurface, (1 << 9), true));"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/media/java/android/media/MediaCodecInfo.java"
+ line="835"
+ column="46"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `FEATURE_HlgEditing` is a flagged API and should be inside an `if (Flags.hlgEditing())` check (or annotate the surrounding method `getEncoderFeatures` with `@FlaggedApi(Flags.FLAG_HLG_EDITING) to transfer requirement to caller`)"
+ errorLine1=" features.add(new Feature(FEATURE_HlgEditing, (1 << 6), true));"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/media/java/android/media/MediaCodecInfo.java"
+ line="856"
+ column="46"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `FEATURE_Roi` is a flagged API and should be inside an `if (Flags.regionOfInterest())` check (or annotate the surrounding method `getEncoderFeatures` with `@FlaggedApi(Flags.FLAG_REGION_OF_INTEREST) to transfer requirement to caller`)"
+ errorLine1=" features.add(new Feature(FEATURE_Roi, (1 << 7), true));"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="frameworks/base/media/java/android/media/MediaCodecInfo.java"
+ line="859"
+ column="46"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `TYPE_HDMI_ARC` is a flagged API and should be inside an `if (Flags.enableAudioPoliciesDeviceAndBluetoothController())` check (or annotate the surrounding method `getDeviceTypeString` with `@FlaggedApi(Flags.FLAG_ENABLE_AUDIO_POLICIES_DEVICE_AND_BLUETOOTH_CONTROLLER) to transfer requirement to caller`)"
+ errorLine1=" case TYPE_HDMI_ARC:"
+ errorLine2=" ~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/media/java/android/media/MediaRoute2Info.java"
+ line="1030"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `TYPE_HDMI_EARC` is a flagged API and should be inside an `if (Flags.enableAudioPoliciesDeviceAndBluetoothController())` check (or annotate the surrounding method `getDeviceTypeString` with `@FlaggedApi(Flags.FLAG_ENABLE_AUDIO_POLICIES_DEVICE_AND_BLUETOOTH_CONTROLLER) to transfer requirement to caller`)"
+ errorLine1=" case TYPE_HDMI_EARC:"
+ errorLine2=" ~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/media/java/android/media/MediaRoute2Info.java"
+ line="1032"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `TYPE_REMOTE_TABLET` is a flagged API and should be inside an `if (Flags.enableNewMediaRoute2InfoTypes())` check (or annotate the surrounding method `getDeviceTypeString` with `@FlaggedApi(Flags.FLAG_ENABLE_NEW_MEDIA_ROUTE_2_INFO_TYPES) to transfer requirement to caller`)"
+ errorLine1=" case TYPE_REMOTE_TABLET:"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/media/java/android/media/MediaRoute2Info.java"
+ line="1050"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `TYPE_REMOTE_TABLET_DOCKED` is a flagged API and should be inside an `if (Flags.enableNewMediaRoute2InfoTypes())` check (or annotate the surrounding method `getDeviceTypeString` with `@FlaggedApi(Flags.FLAG_ENABLE_NEW_MEDIA_ROUTE_2_INFO_TYPES) to transfer requirement to caller`)"
+ errorLine1=" case TYPE_REMOTE_TABLET_DOCKED:"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/media/java/android/media/MediaRoute2Info.java"
+ line="1052"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `TYPE_REMOTE_COMPUTER` is a flagged API and should be inside an `if (Flags.enableNewMediaRoute2InfoTypes())` check (or annotate the surrounding method `getDeviceTypeString` with `@FlaggedApi(Flags.FLAG_ENABLE_NEW_MEDIA_ROUTE_2_INFO_TYPES) to transfer requirement to caller`)"
+ errorLine1=" case TYPE_REMOTE_COMPUTER:"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/media/java/android/media/MediaRoute2Info.java"
+ line="1054"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `TYPE_REMOTE_GAME_CONSOLE` is a flagged API and should be inside an `if (Flags.enableNewMediaRoute2InfoTypes())` check (or annotate the surrounding method `getDeviceTypeString` with `@FlaggedApi(Flags.FLAG_ENABLE_NEW_MEDIA_ROUTE_2_INFO_TYPES) to transfer requirement to caller`)"
+ errorLine1=" case TYPE_REMOTE_GAME_CONSOLE:"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/media/java/android/media/MediaRoute2Info.java"
+ line="1056"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `TYPE_REMOTE_CAR` is a flagged API and should be inside an `if (Flags.enableNewMediaRoute2InfoTypes())` check (or annotate the surrounding method `getDeviceTypeString` with `@FlaggedApi(Flags.FLAG_ENABLE_NEW_MEDIA_ROUTE_2_INFO_TYPES) to transfer requirement to caller`)"
+ errorLine1=" case TYPE_REMOTE_CAR:"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/media/java/android/media/MediaRoute2Info.java"
+ line="1058"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `TYPE_REMOTE_SMARTWATCH` is a flagged API and should be inside an `if (Flags.enableNewMediaRoute2InfoTypes())` check (or annotate the surrounding method `getDeviceTypeString` with `@FlaggedApi(Flags.FLAG_ENABLE_NEW_MEDIA_ROUTE_2_INFO_TYPES) to transfer requirement to caller`)"
+ errorLine1=" case TYPE_REMOTE_SMARTWATCH:"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/media/java/android/media/MediaRoute2Info.java"
+ line="1060"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `TYPE_REMOTE_SMARTPHONE` is a flagged API and should be inside an `if (Flags.enableNewMediaRoute2InfoTypes())` check (or annotate the surrounding method `getDeviceTypeString` with `@FlaggedApi(Flags.FLAG_ENABLE_NEW_MEDIA_ROUTE_2_INFO_TYPES) to transfer requirement to caller`)"
+ errorLine1=" case TYPE_REMOTE_SMARTPHONE:"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/media/java/android/media/MediaRoute2Info.java"
+ line="1062"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `SUITABILITY_STATUS_SUITABLE_FOR_DEFAULT_TRANSFER` is a flagged API and should be inside an `if (Flags.enableBuiltInSpeakerRouteSuitabilityStatuses())` check (or annotate the surrounding method `Builder` with `@FlaggedApi(Flags.FLAG_ENABLE_BUILT_IN_SPEAKER_ROUTE_SUITABILITY_STATUSES) to transfer requirement to caller`)"
+ errorLine1=" mSuitabilityStatus = SUITABILITY_STATUS_SUITABLE_FOR_DEFAULT_TRANSFER;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/media/java/android/media/MediaRoute2Info.java"
+ line="1122"
+ column="34"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `OPSTR_MEDIA_ROUTING_CONTROL` is a flagged API and should be inside an `if (Flags.enablePrivilegedRoutingForMediaRoutingControl())` check (or annotate the surrounding method `checkCallerHasOnlyRevocablePermissions` with `@FlaggedApi(Flags.FLAG_ENABLE_PRIVILEGED_ROUTING_FOR_MEDIA_ROUTING_CONTROL) to transfer requirement to caller`)"
+ errorLine1=" AppOpsManager.OPSTR_MEDIA_ROUTING_CONTROL,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/media/java/android/media/MediaRouter2.java"
+ line="457"
+ column="47"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `CAPABILITY_TYPE_CALL_COMPOSER_BUSINESS_ONLY` is a flagged API and should be inside an `if (Flags.businessCallComposer())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_BUSINESS_CALL_COMPOSER) to transfer requirement to caller`)"
+ errorLine1=" CAPABILITY_TYPE_CALL_COMPOSER_BUSINESS_ONLY + 1;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/ims/feature/MmTelFeature.java"
+ line="574"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `CAPABILITY_TYPE_CALL_COMPOSER_BUSINESS_ONLY` is a flagged API and should be inside an `if (Flags.businessCallComposer())` check (or annotate the surrounding method `toString` with `@FlaggedApi(Flags.FLAG_BUSINESS_CALL_COMPOSER) to transfer requirement to caller`)"
+ errorLine1=" builder.append(isCapable(CAPABILITY_TYPE_CALL_COMPOSER_BUSINESS_ONLY));"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/ims/feature/MmTelFeature.java"
+ line="622"
+ column="38"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `isReliable()` is a flagged API and should be inside an `if (Flags.reliableMessage())` check (or annotate the surrounding method `equals` with `@FlaggedApi(Flags.FLAG_RELIABLE_MESSAGE) to transfer requirement to caller`)"
+ errorLine1=" || (other.isReliable() == mIsReliable))"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/hardware/location/NanoAppMessage.java"
+ line="269"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getMessageSequenceNumber()` is a flagged API and should be inside an `if (Flags.reliableMessage())` check (or annotate the surrounding method `equals` with `@FlaggedApi(Flags.FLAG_RELIABLE_MESSAGE) to transfer requirement to caller`)"
+ errorLine1=" || (other.getMessageSequenceNumber() == mMessageSequenceNumber));"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/hardware/location/NanoAppMessage.java"
+ line="271"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `SERVICE_TYPE_MMS` is a flagged API and should be inside an `if (Flags.carrierEnabledSatelliteFlag())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG) to transfer requirement to caller`)"
+ errorLine1=" public static final int LAST_SERVICE_TYPE = SERVICE_TYPE_MMS;"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/NetworkRegistrationInfo.java"
+ line="219"
+ column="49"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `SERVICE_TYPE_MMS` is a flagged API and should be inside an `if (Flags.carrierEnabledSatelliteFlag())` check (or annotate the surrounding method `serviceTypeToString` with `@FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG) to transfer requirement to caller`)"
+ errorLine1=" case SERVICE_TYPE_MMS: return "MMS";"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/NetworkRegistrationInfo.java"
+ line="759"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getVibrationEffect()` is a flagged API and should be inside an `if (Flags.notificationChannelVibrationEffectApi())` check (or annotate the surrounding method `writeXml` with `@FlaggedApi(Flags.FLAG_NOTIFICATION_CHANNEL_VIBRATION_EFFECT_API) to transfer requirement to caller`)"
+ errorLine1=" if (getVibrationEffect() != null) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/NotificationChannel.java"
+ line="1333"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getVibrationEffect()` is a flagged API and should be inside an `if (Flags.notificationChannelVibrationEffectApi())` check (or annotate the surrounding method `writeXml` with `@FlaggedApi(Flags.FLAG_NOTIFICATION_CHANNEL_VIBRATION_EFFECT_API) to transfer requirement to caller`)"
+ errorLine1=" out.attribute(null, ATT_VIBRATION_EFFECT, vibrationToString(getVibrationEffect()));"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/NotificationChannel.java"
+ line="1334"
+ column="73"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getVibrationEffect()` is a flagged API and should be inside an `if (Flags.notificationChannelVibrationEffectApi())` check (or annotate the surrounding method `toJson` with `@FlaggedApi(Flags.FLAG_NOTIFICATION_CHANNEL_VIBRATION_EFFECT_API) to transfer requirement to caller`)"
+ errorLine1=" if (getVibrationEffect() != null) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/NotificationChannel.java"
+ line="1416"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getVibrationEffect()` is a flagged API and should be inside an `if (Flags.notificationChannelVibrationEffectApi())` check (or annotate the surrounding method `toJson` with `@FlaggedApi(Flags.FLAG_NOTIFICATION_CHANNEL_VIBRATION_EFFECT_API) to transfer requirement to caller`)"
+ errorLine1=" record.put(ATT_VIBRATION_EFFECT, vibrationToString(getVibrationEffect()));"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/NotificationChannel.java"
+ line="1417"
+ column="64"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getVibrationEffect()` is a flagged API and should be inside an `if (Flags.notificationChannelVibrationEffectApi())` check (or annotate the surrounding method `equals` with `@FlaggedApi(Flags.FLAG_NOTIFICATION_CHANNEL_VIBRATION_EFFECT_API) to transfer requirement to caller`)"
+ errorLine1=" && Objects.equals(getVibrationEffect(), that.getVibrationEffect())"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/NotificationChannel.java"
+ line="1545"
+ column="35"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getVibrationEffect()` is a flagged API and should be inside an `if (Flags.notificationChannelVibrationEffectApi())` check (or annotate the surrounding method `equals` with `@FlaggedApi(Flags.FLAG_NOTIFICATION_CHANNEL_VIBRATION_EFFECT_API) to transfer requirement to caller`)"
+ errorLine1=" && Objects.equals(getVibrationEffect(), that.getVibrationEffect())"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/NotificationChannel.java"
+ line="1545"
+ column="57"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getVibrationEffect()` is a flagged API and should be inside an `if (Flags.notificationChannelVibrationEffectApi())` check (or annotate the surrounding method `hashCode` with `@FlaggedApi(Flags.FLAG_NOTIFICATION_CHANNEL_VIBRATION_EFFECT_API) to transfer requirement to caller`)"
+ errorLine1=" mImportanceLockedDefaultApp, mOriginalImportance, getVibrationEffect(),"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/NotificationChannel.java"
+ line="1563"
+ column="67"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `addAutomaticZenRule()` is a flagged API and should be inside an `if (Flags.modesApi())` check (or annotate the surrounding method `addAutomaticZenRule` with `@FlaggedApi(Flags.FLAG_MODES_API) to transfer requirement to caller`)"
+ errorLine1=" return addAutomaticZenRule(automaticZenRule, /* fromUser= */ false);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/NotificationManager.java"
+ line="1368"
+ column="16"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `updateAutomaticZenRule()` is a flagged API and should be inside an `if (Flags.modesApi())` check (or annotate the surrounding method `updateAutomaticZenRule` with `@FlaggedApi(Flags.FLAG_MODES_API) to transfer requirement to caller`)"
+ errorLine1=" return updateAutomaticZenRule(id, automaticZenRule, /* fromUser= */ false);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/NotificationManager.java"
+ line="1404"
+ column="16"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `removeAutomaticZenRule()` is a flagged API and should be inside an `if (Flags.modesApi())` check (or annotate the surrounding method `removeAutomaticZenRule` with `@FlaggedApi(Flags.FLAG_MODES_API) to transfer requirement to caller`)"
+ errorLine1=" return removeAutomaticZenRule(id, /* fromUser= */ false);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/NotificationManager.java"
+ line="1473"
+ column="16"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `ROLLBACK_USER_IMPACT_LOW` is a flagged API and should be inside an `if (Flags.recoverabilityDetection())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_RECOVERABILITY_DETECTION) to transfer requirement to caller`)"
+ errorLine1=" public int rollbackImpactLevel = PackageManager.ROLLBACK_USER_IMPACT_LOW;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/content/pm/PackageInstaller.java"
+ line="2789"
+ column="57"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `isArchived` is a flagged API and should be inside an `if (Flags.archiving())` check (or annotate the surrounding method `PackageItemInfo` with `@FlaggedApi(Flags.FLAG_ARCHIVING) to transfer requirement to caller`)"
+ errorLine1=" isArchived = orig.isArchived;"
+ errorLine2=" ~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/content/pm/PackageItemInfo.java"
+ line="204"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `isArchived` is a flagged API and should be inside an `if (Flags.archiving())` check (or annotate the surrounding method `PackageItemInfo` with `@FlaggedApi(Flags.FLAG_ARCHIVING) to transfer requirement to caller`)"
+ errorLine1=" isArchived = orig.isArchived;"
+ errorLine2=" ~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/content/pm/PackageItemInfo.java"
+ line="204"
+ column="27"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `isArchived` is a flagged API and should be inside an `if (Flags.archiving())` check (or annotate the surrounding method `writeToParcel` with `@FlaggedApi(Flags.FLAG_ARCHIVING) to transfer requirement to caller`)"
+ errorLine1=" dest.writeBoolean(isArchived);"
+ errorLine2=" ~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/content/pm/PackageItemInfo.java"
+ line="470"
+ column="27"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `isArchived` is a flagged API and should be inside an `if (Flags.archiving())` check (or annotate the surrounding method `dumpDebug` with `@FlaggedApi(Flags.FLAG_ARCHIVING) to transfer requirement to caller`)"
+ errorLine1=" proto.write(PackageItemInfoProto.IS_ARCHIVED, isArchived);"
+ errorLine2=" ~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/content/pm/PackageItemInfo.java"
+ line="488"
+ column="55"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `isArchived` is a flagged API and should be inside an `if (Flags.archiving())` check (or annotate the surrounding method `PackageItemInfo` with `@FlaggedApi(Flags.FLAG_ARCHIVING) to transfer requirement to caller`)"
+ errorLine1=" isArchived = source.readBoolean();"
+ errorLine2=" ~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/content/pm/PackageItemInfo.java"
+ line="503"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `PERSISTENT_DEVICE_ID_DEFAULT` is a flagged API and should be inside an `if (Flags.persistentDeviceIdApi())` check (or annotate the surrounding method `onPermissionsChanged` with `@FlaggedApi(Flags.FLAG_PERSISTENT_DEVICE_ID_API) to transfer requirement to caller`)"
+ errorLine1=" VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT)) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/content/pm/PackageManager.java"
+ line="766"
+ column="42"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `EXTRA_ARCHIVAL` is a flagged API and should be inside an `if (Flags.archiving())` check (or annotate the surrounding method `doHandlePackageEvent` with `@FlaggedApi(Flags.FLAG_ARCHIVING) to transfer requirement to caller`)"
+ errorLine1=" if (intent.getBooleanExtra(Intent.EXTRA_ARCHIVAL, false)) {"
+ errorLine2=" ~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/com/android/internal/content/PackageMonitor.java"
+ line="491"
+ column="55"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `ACTION_PACKAGE_UNSTOPPED` is a flagged API and should be inside an `if (Flags.stayStopped())` check (or annotate the surrounding method `doHandlePackageEvent` with `@FlaggedApi(Flags.FLAG_STAY_STOPPED) to transfer requirement to caller`)"
+ errorLine1=" } else if (Intent.ACTION_PACKAGE_UNSTOPPED.equals(action)) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/com/android/internal/content/PackageMonitor.java"
+ line="582"
+ column="27"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `TEXT_RUN_FLAG_LEFT_EDGE` is a flagged API and should be inside an `if (Flags.letterSpacingJustification())` check (or annotate the surrounding method `measureText` with `@FlaggedApi(Flags.FLAG_LETTER_SPACING_JUSTIFICATION) to transfer requirement to caller`)"
+ errorLine1=" setFlags(getFlags() | (TEXT_RUN_FLAG_LEFT_EDGE | TEXT_RUN_FLAG_RIGHT_EDGE));"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/graphics/java/android/graphics/Paint.java"
+ line="2587"
+ column="32"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `TEXT_RUN_FLAG_RIGHT_EDGE` is a flagged API and should be inside an `if (Flags.letterSpacingJustification())` check (or annotate the surrounding method `measureText` with `@FlaggedApi(Flags.FLAG_LETTER_SPACING_JUSTIFICATION) to transfer requirement to caller`)"
+ errorLine1=" setFlags(getFlags() | (TEXT_RUN_FLAG_LEFT_EDGE | TEXT_RUN_FLAG_RIGHT_EDGE));"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/graphics/java/android/graphics/Paint.java"
+ line="2587"
+ column="58"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `TEXT_RUN_FLAG_LEFT_EDGE` is a flagged API and should be inside an `if (Flags.letterSpacingJustification())` check (or annotate the surrounding method `measureText` with `@FlaggedApi(Flags.FLAG_LETTER_SPACING_JUSTIFICATION) to transfer requirement to caller`)"
+ errorLine1=" setFlags(getFlags() | (TEXT_RUN_FLAG_LEFT_EDGE | TEXT_RUN_FLAG_RIGHT_EDGE));"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/graphics/java/android/graphics/Paint.java"
+ line="2626"
+ column="32"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `TEXT_RUN_FLAG_RIGHT_EDGE` is a flagged API and should be inside an `if (Flags.letterSpacingJustification())` check (or annotate the surrounding method `measureText` with `@FlaggedApi(Flags.FLAG_LETTER_SPACING_JUSTIFICATION) to transfer requirement to caller`)"
+ errorLine1=" setFlags(getFlags() | (TEXT_RUN_FLAG_LEFT_EDGE | TEXT_RUN_FLAG_RIGHT_EDGE));"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/graphics/java/android/graphics/Paint.java"
+ line="2626"
+ column="58"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `TEXT_RUN_FLAG_LEFT_EDGE` is a flagged API and should be inside an `if (Flags.letterSpacingJustification())` check (or annotate the surrounding method `getTextWidths` with `@FlaggedApi(Flags.FLAG_LETTER_SPACING_JUSTIFICATION) to transfer requirement to caller`)"
+ errorLine1=" setFlags(getFlags() | (TEXT_RUN_FLAG_LEFT_EDGE | TEXT_RUN_FLAG_RIGHT_EDGE));"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/graphics/java/android/graphics/Paint.java"
+ line="2846"
+ column="32"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `TEXT_RUN_FLAG_RIGHT_EDGE` is a flagged API and should be inside an `if (Flags.letterSpacingJustification())` check (or annotate the surrounding method `getTextWidths` with `@FlaggedApi(Flags.FLAG_LETTER_SPACING_JUSTIFICATION) to transfer requirement to caller`)"
+ errorLine1=" setFlags(getFlags() | (TEXT_RUN_FLAG_LEFT_EDGE | TEXT_RUN_FLAG_RIGHT_EDGE));"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/graphics/java/android/graphics/Paint.java"
+ line="2846"
+ column="58"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `TEXT_RUN_FLAG_LEFT_EDGE` is a flagged API and should be inside an `if (Flags.letterSpacingJustification())` check (or annotate the surrounding method `getTextWidths` with `@FlaggedApi(Flags.FLAG_LETTER_SPACING_JUSTIFICATION) to transfer requirement to caller`)"
+ errorLine1=" setFlags(getFlags() | (TEXT_RUN_FLAG_LEFT_EDGE | TEXT_RUN_FLAG_RIGHT_EDGE));"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/graphics/java/android/graphics/Paint.java"
+ line="2936"
+ column="32"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `TEXT_RUN_FLAG_RIGHT_EDGE` is a flagged API and should be inside an `if (Flags.letterSpacingJustification())` check (or annotate the surrounding method `getTextWidths` with `@FlaggedApi(Flags.FLAG_LETTER_SPACING_JUSTIFICATION) to transfer requirement to caller`)"
+ errorLine1=" setFlags(getFlags() | (TEXT_RUN_FLAG_LEFT_EDGE | TEXT_RUN_FLAG_RIGHT_EDGE));"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/graphics/java/android/graphics/Paint.java"
+ line="2936"
+ column="58"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `isMgf1DigestsSpecified()` is a flagged API and should be inside an `if (Flags.mgf1DigestSetterV2())` check (or annotate the surrounding method `writeToParcel` with `@FlaggedApi(Flags.FLAG_MGF1_DIGEST_SETTER_V2) to transfer requirement to caller`)"
+ errorLine1=" if (mSpec.isMgf1DigestsSpecified()) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/keystore/java/android/security/keystore/ParcelableKeyGenParameterSpec.java"
+ line="98"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getMgf1Digests()` is a flagged API and should be inside an `if (Flags.mgf1DigestSetterV2())` check (or annotate the surrounding method `writeToParcel` with `@FlaggedApi(Flags.FLAG_MGF1_DIGEST_SETTER_V2) to transfer requirement to caller`)"
+ errorLine1=" out.writeStringList(List.copyOf(mSpec.getMgf1Digests()));"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/keystore/java/android/security/keystore/ParcelableKeyGenParameterSpec.java"
+ line="99"
+ column="45"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `computeBounds()` is a flagged API and should be inside an `if (Flags.exactComputeBounds())` check (or annotate the surrounding method `computeBounds` with `@FlaggedApi(Flags.FLAG_EXACT_COMPUTE_BOUNDS) to transfer requirement to caller`)"
+ errorLine1=" computeBounds(bounds);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/graphics/java/android/graphics/Path.java"
+ line="310"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `onOneTimePermissionSessionTimeout()` is a flagged API and should be inside an `if (Flags.deviceAwarePermissionApisEnabled())` check (or annotate the surrounding method `notifyOneTimePermissionSessionTimeout` with `@FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) to transfer requirement to caller`)"
+ errorLine1=" onOneTimePermissionSessionTimeout(packageName, deviceId);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/permission/PermissionControllerService.java"
+ line="672"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `onRevokeSelfPermissionsOnKill()` is a flagged API and should be inside an `if (Flags.deviceAwarePermissionApisEnabled())` check (or annotate the surrounding method `revokeSelfPermissionsOnKill` with `@FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) to transfer requirement to caller`)"
+ errorLine1=" onRevokeSelfPermissionsOnKill(packageName, permissions, deviceId,"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/core/java/android/permission/PermissionControllerService.java"
+ line="776"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `PERSISTENT_DEVICE_ID_DEFAULT` is a flagged API and should be inside an `if (Flags.persistentDeviceIdApi())` check (or annotate the surrounding method `getIndicatorAppOpUsageData` with `@FlaggedApi(Flags.FLAG_PERSISTENT_DEVICE_ID_API) to transfer requirement to caller`)"
+ errorLine1=" VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/permission/PermissionManager.java"
+ line="1342"
+ column="38"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `PERSISTENT_DEVICE_ID_DEFAULT` is a flagged API and should be inside an `if (Flags.persistentDeviceIdApi())` check (or annotate the surrounding method `getPersistentDeviceId` with `@FlaggedApi(Flags.FLAG_PERSISTENT_DEVICE_ID_API) to transfer requirement to caller`)"
+ errorLine1=" persistentDeviceId = VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/permission/PermissionManager.java"
+ line="1951"
+ column="55"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `onPermissionsChanged()` is a flagged API and should be inside an `if (Flags.deviceAwarePermissionApisEnabled())` check (or annotate the surrounding method `handleMessage` with `@FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) to transfer requirement to caller`)"
+ errorLine1=" mListener.onPermissionsChanged(uid, persistentDeviceId);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/permission/PermissionManager.java"
+ line="2040"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getPersistentDeviceId()` is a flagged API and should be inside an `if (Flags.vdmPublicApis())` check (or annotate the surrounding method `getOpUsageDataForAllDevices` with `@FlaggedApi(Flags.FLAG_VDM_PUBLIC_APIS) to transfer requirement to caller`)"
+ errorLine1=" persistentDeviceIds.add(virtualDevices.get(num).getPersistentDeviceId());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/permission/PermissionUsageHelper.java"
+ line="381"
+ column="37"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `PERSISTENT_DEVICE_ID_DEFAULT` is a flagged API and should be inside an `if (Flags.persistentDeviceIdApi())` check (or annotate the surrounding method `getOpUsageDataForAllDevices` with `@FlaggedApi(Flags.FLAG_PERSISTENT_DEVICE_ID_API) to transfer requirement to caller`)"
+ errorLine1=" persistentDeviceIds.add(VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/permission/PermissionUsageHelper.java"
+ line="383"
+ column="54"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `PERSISTENT_DEVICE_ID_DEFAULT` is a flagged API and should be inside an `if (Flags.persistentDeviceIdApi())` check (or annotate the surrounding method `getOpUsagesByDevice` with `@FlaggedApi(Flags.FLAG_PERSISTENT_DEVICE_ID_API) to transfer requirement to caller`)"
+ errorLine1=" VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT)) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/permission/PermissionUsageHelper.java"
+ line="492"
+ column="42"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `hasSimultaneousCallingRestriction()` is a flagged API and should be inside an `if (Flags.simultaneousCallingIndications())` check (or annotate the surrounding method `Builder` with `@FlaggedApi(Flags.FLAG_SIMULTANEOUS_CALLING_INDICATIONS) to transfer requirement to caller`)"
+ errorLine1=" if (phoneAccount.hasSimultaneousCallingRestriction()) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telecomm/java/android/telecom/PhoneAccount.java"
+ line="585"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getSimultaneousCallingRestriction()` is a flagged API and should be inside an `if (Flags.simultaneousCallingIndications())` check (or annotate the surrounding method `Builder` with `@FlaggedApi(Flags.FLAG_SIMULTANEOUS_CALLING_INDICATIONS) to transfer requirement to caller`)"
+ errorLine1=" mSimultaneousCallingRestriction = phoneAccount.getSimultaneousCallingRestriction();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telecomm/java/android/telecom/PhoneAccount.java"
+ line="586"
+ column="51"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `hasSimultaneousCallingRestriction()` is a flagged API and should be inside an `if (Flags.simultaneousCallingIndications())` check (or annotate the surrounding method `toString` with `@FlaggedApi(Flags.FLAG_SIMULTANEOUS_CALLING_INDICATIONS) to transfer requirement to caller`)"
+ errorLine1=" if (hasSimultaneousCallingRestriction()) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telecomm/java/android/telecom/PhoneAccount.java"
+ line="1292"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `STATE_PLAYBACK_SUPPRESSED` is a flagged API and should be inside an `if (Flags.enableNotifyingActivityManagerWithMediaSessionStatusChange())` check (or annotate the surrounding method `isActive` with `@FlaggedApi(Flags.FLAG_ENABLE_NOTIFYING_ACTIVITY_MANAGER_WITH_MEDIA_SESSION_STATUS_CHANGE) to transfer requirement to caller`)"
+ errorLine1=" case PlaybackState.STATE_PLAYBACK_SUPPRESSED:"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/media/java/android/media/session/PlaybackState.java"
+ line="541"
+ column="32"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `STATE_PLAYBACK_SUPPRESSED` is a flagged API and should be inside an `if (Flags.enableNotifyingActivityManagerWithMediaSessionStatusChange())` check (or annotate the surrounding method `getStringForStateInt` with `@FlaggedApi(Flags.FLAG_ENABLE_NOTIFYING_ACTIVITY_MANAGER_WITH_MEDIA_SESSION_STATUS_CHANGE) to transfer requirement to caller`)"
+ errorLine1=" case STATE_PLAYBACK_SUPPRESSED:"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/media/java/android/media/session/PlaybackState.java"
+ line="587"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1="@FlaggedApi("com.android.server.power.optimization.power_monitor_api")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/os/PowerMonitor.java"
+ line="39"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1="@FlaggedApi("com.android.server.power.optimization.power_monitor_api")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/os/PowerMonitor.java"
+ line="39"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1="@FlaggedApi("com.android.server.power.optimization.power_monitor_api")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/os/PowerMonitor.java"
+ line="39"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1="@FlaggedApi("com.android.server.power.optimization.power_monitor_api")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/os/PowerMonitor.java"
+ line="39"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1="@FlaggedApi("com.android.server.power.optimization.power_monitor_api")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/os/PowerMonitor.java"
+ line="39"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1="@FlaggedApi("com.android.server.power.optimization.power_monitor_api")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/os/PowerMonitor.java"
+ line="39"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1="@FlaggedApi("com.android.server.power.optimization.power_monitor_api")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/os/PowerMonitor.java"
+ line="39"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1="@FlaggedApi("com.android.server.power.optimization.power_monitor_api")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/os/PowerMonitor.java"
+ line="39"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1="@FlaggedApi("com.android.server.power.optimization.power_monitor_api")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/os/PowerMonitor.java"
+ line="39"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1="@FlaggedApi("com.android.server.power.optimization.power_monitor_api")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/os/PowerMonitor.java"
+ line="39"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1="@FlaggedApi("com.android.server.power.optimization.power_monitor_api")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/os/PowerMonitor.java"
+ line="39"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1="@FlaggedApi("com.android.server.power.optimization.power_monitor_api")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/os/PowerMonitor.java"
+ line="39"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1="@FlaggedApi("com.android.server.power.optimization.power_monitor_api")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/os/PowerMonitor.java"
+ line="39"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1="@FlaggedApi("com.android.server.power.optimization.power_monitor_api")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/os/PowerMonitor.java"
+ line="39"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1="@FlaggedApi("com.android.server.power.optimization.power_monitor_api")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/os/PowerMonitor.java"
+ line="39"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1="@FlaggedApi("com.android.server.power.optimization.power_monitor_api")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/os/PowerMonitor.java"
+ line="39"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1="@FlaggedApi("com.android.server.power.optimization.power_monitor_api")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/os/PowerMonitor.java"
+ line="39"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1="@FlaggedApi("com.android.server.power.optimization.power_monitor_api")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/os/PowerMonitor.java"
+ line="39"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1="@FlaggedApi("com.android.server.power.optimization.power_monitor_api")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/os/PowerMonitor.java"
+ line="39"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @FlaggedApi("com.android.server.power.optimization.power_monitor_api")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/os/PowerMonitor.java"
+ line="49"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @FlaggedApi("com.android.server.power.optimization.power_monitor_api")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/os/PowerMonitor.java"
+ line="49"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @FlaggedApi("com.android.server.power.optimization.power_monitor_api")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/os/PowerMonitor.java"
+ line="57"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @FlaggedApi("com.android.server.power.optimization.power_monitor_api")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/os/PowerMonitor.java"
+ line="57"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @FlaggedApi("com.android.server.power.optimization.power_monitor_api")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/os/PowerMonitor.java"
+ line="94"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @FlaggedApi("com.android.server.power.optimization.power_monitor_api")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/os/PowerMonitor.java"
+ line="103"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @FlaggedApi("com.android.server.power.optimization.power_monitor_api")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/os/PowerMonitor.java"
+ line="103"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @FlaggedApi("com.android.server.power.optimization.power_monitor_api")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/os/PowerMonitor.java"
+ line="115"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @FlaggedApi("com.android.server.power.optimization.power_monitor_api")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/os/PowerMonitor.java"
+ line="123"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @FlaggedApi("com.android.server.power.optimization.power_monitor_api")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/os/PowerMonitor.java"
+ line="129"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1="@FlaggedApi("com.android.server.power.optimization.power_monitor_api")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/os/PowerMonitorReadings.java"
+ line="29"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1="@FlaggedApi("com.android.server.power.optimization.power_monitor_api")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/os/PowerMonitorReadings.java"
+ line="29"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1="@FlaggedApi("com.android.server.power.optimization.power_monitor_api")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/os/PowerMonitorReadings.java"
+ line="29"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1="@FlaggedApi("com.android.server.power.optimization.power_monitor_api")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/os/PowerMonitorReadings.java"
+ line="29"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1="@FlaggedApi("com.android.server.power.optimization.power_monitor_api")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/os/PowerMonitorReadings.java"
+ line="29"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1="@FlaggedApi("com.android.server.power.optimization.power_monitor_api")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/os/PowerMonitorReadings.java"
+ line="29"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1="@FlaggedApi("com.android.server.power.optimization.power_monitor_api")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/os/PowerMonitorReadings.java"
+ line="29"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1="@FlaggedApi("com.android.server.power.optimization.power_monitor_api")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/os/PowerMonitorReadings.java"
+ line="29"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1="@FlaggedApi("com.android.server.power.optimization.power_monitor_api")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/os/PowerMonitorReadings.java"
+ line="29"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1="@FlaggedApi("com.android.server.power.optimization.power_monitor_api")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/os/PowerMonitorReadings.java"
+ line="29"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1="@FlaggedApi("com.android.server.power.optimization.power_monitor_api")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/os/PowerMonitorReadings.java"
+ line="29"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1="@FlaggedApi("com.android.server.power.optimization.power_monitor_api")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/os/PowerMonitorReadings.java"
+ line="29"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1="@FlaggedApi("com.android.server.power.optimization.power_monitor_api")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/os/PowerMonitorReadings.java"
+ line="29"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1="@FlaggedApi("com.android.server.power.optimization.power_monitor_api")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/os/PowerMonitorReadings.java"
+ line="29"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1="@FlaggedApi("com.android.server.power.optimization.power_monitor_api")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/os/PowerMonitorReadings.java"
+ line="29"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @FlaggedApi("com.android.server.power.optimization.power_monitor_api")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/os/PowerMonitorReadings.java"
+ line="31"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @FlaggedApi("com.android.server.power.optimization.power_monitor_api")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/os/PowerMonitorReadings.java"
+ line="31"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @FlaggedApi("com.android.server.power.optimization.power_monitor_api")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/os/PowerMonitorReadings.java"
+ line="60"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @FlaggedApi("com.android.server.power.optimization.power_monitor_api")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/os/PowerMonitorReadings.java"
+ line="72"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `NETWORK_VALIDATION_UNSUPPORTED` is a flagged API and should be inside an `if (Flags.networkValidation())` check (or annotate the surrounding method `PreciseDataConnectionState` with `@FlaggedApi(Flags.FLAG_NETWORK_VALIDATION) to transfer requirement to caller`)"
+ errorLine1=" .build(), null, NETWORK_VALIDATION_UNSUPPORTED);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/PreciseDataConnectionState.java"
+ line="143"
+ column="41"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `NETWORK_VALIDATION_UNSUPPORTED` is a flagged API and should be inside an `if (Flags.networkValidation())` check (or annotate the surrounding method `networkValidationStatusToString` with `@FlaggedApi(Flags.FLAG_NETWORK_VALIDATION) to transfer requirement to caller`)"
+ errorLine1=" case NETWORK_VALIDATION_UNSUPPORTED: return "unsupported";"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/PreciseDataConnectionState.java"
+ line="456"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `NETWORK_VALIDATION_NOT_REQUESTED` is a flagged API and should be inside an `if (Flags.networkValidation())` check (or annotate the surrounding method `networkValidationStatusToString` with `@FlaggedApi(Flags.FLAG_NETWORK_VALIDATION) to transfer requirement to caller`)"
+ errorLine1=" case NETWORK_VALIDATION_NOT_REQUESTED: return "not requested";"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/PreciseDataConnectionState.java"
+ line="457"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `NETWORK_VALIDATION_IN_PROGRESS` is a flagged API and should be inside an `if (Flags.networkValidation())` check (or annotate the surrounding method `networkValidationStatusToString` with `@FlaggedApi(Flags.FLAG_NETWORK_VALIDATION) to transfer requirement to caller`)"
+ errorLine1=" case NETWORK_VALIDATION_IN_PROGRESS: return "in progress";"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/PreciseDataConnectionState.java"
+ line="458"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `NETWORK_VALIDATION_SUCCESS` is a flagged API and should be inside an `if (Flags.networkValidation())` check (or annotate the surrounding method `networkValidationStatusToString` with `@FlaggedApi(Flags.FLAG_NETWORK_VALIDATION) to transfer requirement to caller`)"
+ errorLine1=" case NETWORK_VALIDATION_SUCCESS: return "success";"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/PreciseDataConnectionState.java"
+ line="459"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `NETWORK_VALIDATION_FAILURE` is a flagged API and should be inside an `if (Flags.networkValidation())` check (or annotate the surrounding method `networkValidationStatusToString` with `@FlaggedApi(Flags.FLAG_NETWORK_VALIDATION) to transfer requirement to caller`)"
+ errorLine1=" case NETWORK_VALIDATION_FAILURE: return "failure";"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/PreciseDataConnectionState.java"
+ line="460"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `NETWORK_VALIDATION_UNSUPPORTED` is a flagged API and should be inside an `if (Flags.networkValidation())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_NETWORK_VALIDATION) to transfer requirement to caller`)"
+ errorLine1=" NETWORK_VALIDATION_UNSUPPORTED;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/PreciseDataConnectionState.java"
+ line="508"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `LINE_BREAK_WORD_STYLE_AUTO` is a flagged API and should be inside an `if (Flags.wordStyleAuto())` check (or annotate the surrounding method `createMeasuredParagraphsFromPrecomputedText` with `@FlaggedApi(Flags.FLAG_WORD_STYLE_AUTO) to transfer requirement to caller`)"
+ errorLine1=" if (config.getLineBreakWordStyle() == LineBreakConfig.LINE_BREAK_WORD_STYLE_AUTO"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/text/PrecomputedText.java"
+ line="461"
+ column="63"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `merge()` is a flagged API and should be inside an `if (Flags.noBreakNoHyphenationSpan())` check (or annotate the surrounding method `createMeasuredParagraphsFromPrecomputedText` with `@FlaggedApi(Flags.FLAG_NO_BREAK_NO_HYPHENATION_SPAN) to transfer requirement to caller`)"
+ errorLine1=" config = new LineBreakConfig.Builder()"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/core/java/android/text/PrecomputedText.java"
+ line="464"
+ column="22"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `LINE_BREAK_WORD_STYLE_AUTO` is a flagged API and should be inside an `if (Flags.wordStyleAuto())` check (or annotate the surrounding method `createMeasuredParagraphs` with `@FlaggedApi(Flags.FLAG_WORD_STYLE_AUTO) to transfer requirement to caller`)"
+ errorLine1=" if (config.getLineBreakWordStyle() == LineBreakConfig.LINE_BREAK_WORD_STYLE_AUTO"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/text/PrecomputedText.java"
+ line="515"
+ column="71"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `isResumed()` is a flagged API and should be inside an `if (Flags.enableNfcMainline())` check (or annotate the surrounding method `onListItemClick` with `@FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) to transfer requirement to caller`)"
+ errorLine1=" if (!isResumed()) {"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/preference/PreferenceActivity.java"
+ line="1071"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Class `PromptContentViewParcelable` is a flagged API and should be inside an `if (Flags.customBiometricPrompt())` check (or annotate the surrounding method `PromptInfo` with `@FlaggedApi(Flags.FLAG_CUSTOM_BIOMETRIC_PROMPT) to transfer requirement to caller`)"
+ errorLine1=" mContentView = in.readParcelable(PromptContentViewParcelable.class.getClassLoader(),"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/hardware/biometrics/PromptInfo.java"
+ line="75"
+ column="42"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Class `PromptContentViewParcelable` is a flagged API and should be inside an `if (Flags.customBiometricPrompt())` check (or annotate the surrounding method `PromptInfo` with `@FlaggedApi(Flags.FLAG_CUSTOM_BIOMETRIC_PROMPT) to transfer requirement to caller`)"
+ errorLine1=" PromptContentViewParcelable.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/hardware/biometrics/PromptInfo.java"
+ line="76"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="This is a flagged API and should be inside an `if (Flags.customBiometricPrompt())` check (or annotate the surrounding method `isContentViewMoreOptionsButtonUsed` with `@FlaggedApi(Flags.FLAG_CUSTOM_BIOMETRIC_PROMPT) to transfer requirement to caller`)"
+ errorLine1=" && mContentView instanceof PromptContentViewWithMoreOptionsButton;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/hardware/biometrics/PromptInfo.java"
+ line="214"
+ column="44"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="This is a flagged API and should be inside an `if (Flags.customBiometricPrompt())` check (or annotate the surrounding method `setContentView` with `@FlaggedApi(Flags.FLAG_CUSTOM_BIOMETRIC_PROMPT) to transfer requirement to caller`)"
+ errorLine1=" mContentView = (PromptContentViewParcelable) view;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/hardware/biometrics/PromptInfo.java"
+ line="258"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.media.tv.flags.enable_ad_service_fw")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/R.java"
+ line="610"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.media.tv.flags.enable_ad_service_fw")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/R.java"
+ line="610"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.media.tv.flags.enable_ad_service_fw")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/R.java"
+ line="610"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.media.tv.flags.enable_ad_service_fw")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/R.java"
+ line="610"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.content.pm.relative_reference_intent_filters")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/R.java"
+ line="693"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.security.asm_restrictions_enabled")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/R.java"
+ line="759"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.nfc.nfc_read_polling_loop")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/R.java"
+ line="1300"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.view.flags.sensitive_content_app_protection_api")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/R.java"
+ line="2782"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.content.res.default_locale")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/R.java"
+ line="3023"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.service.controls.flags.Flags.FLAG_HOME_PANEL_DREAM")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/R.java"
+ line="3599"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.service.controls.flags.Flags.FLAG_HOME_PANEL_DREAM")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/R.java"
+ line="3599"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.service.controls.flags.Flags.FLAG_HOME_PANEL_DREAM")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/R.java"
+ line="3599"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.service.controls.flags.Flags.FLAG_HOME_PANEL_DREAM")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/R.java"
+ line="3599"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.content.res.manifest_flagging")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/R.java"
+ line="4290"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.content.pm.relative_reference_intent_filters")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/R.java"
+ line="4870"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.content.pm.relative_reference_intent_filters")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/R.java"
+ line="4970"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.content.pm.relative_reference_intent_filters")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/R.java"
+ line="4979"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.content.pm.relative_reference_intent_filters")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/R.java"
+ line="5032"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.companion.virtual.flags.vdm_custom_ime")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/R.java"
+ line="6857"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.view.inputmethod.ime_switcher_revamp")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/R.java"
+ line="7587"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.view.inputmethod.ime_switcher_revamp")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/R.java"
+ line="7587"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.view.inputmethod.ime_switcher_revamp")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/R.java"
+ line="7587"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.view.inputmethod.ime_switcher_revamp")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/R.java"
+ line="7587"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.content.pm.sdk_lib_independence")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/R.java"
+ line="9481"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.content.pm.sdk_lib_independence")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/R.java"
+ line="9481"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.content.pm.sdk_lib_independence")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/R.java"
+ line="9481"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.content.pm.sdk_lib_independence")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/R.java"
+ line="9481"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.content.pm.relative_reference_intent_filters")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/R.java"
+ line="10701"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.content.pm.relative_reference_intent_filters")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/R.java"
+ line="10727"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.content.pm.relative_reference_intent_filters")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/R.java"
+ line="10767"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.content.pm.relative_reference_intent_filters")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/R.java"
+ line="10776"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.content.pm.relative_reference_intent_filters")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/R.java"
+ line="10785"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.security.content_uri_permission_apis")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/R.java"
+ line="11122"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("com.android.text.flags.use_bounds_for_width")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/R.java"
+ line="12404"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.nfc.nfc_observe_mode")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/R.java"
+ line="12438"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.view.inputmethod.connectionless_handwriting")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/R.java"
+ line="13485"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.multiuser.enable_system_user_only_for_services_and_providers")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/R.java"
+ line="13672"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("com.android.text.flags.use_bounds_for_width")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/R.java"
+ line="15472"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("com.android.text.flags.fix_line_height_for_locale")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/R.java"
+ line="15520"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.view.flags.toolkit_set_frame_rate_read_only")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/R.java"
+ line="16364"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("com.android.window.flags.enforce_edge_to_edge")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/R.java"
+ line="16561"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.permission.flags.retail_demo_role_enabled")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/R.java"
+ line="18455"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.permission.flags.wallet_role_enabled")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/R.java"
+ line="18473"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.security.content_uri_permission_apis")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/R.java"
+ line="25110"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.security.asm_restrictions_enabled")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/R.java"
+ line="25837"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.security.asm_restrictions_enabled")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/R.java"
+ line="27173"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.view.inputmethod.ime_switcher_revamp")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/R.java"
+ line="41370"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.companion.virtual.flags.vdm_custom_ime")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/R.java"
+ line="41608"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.view.inputmethod.ime_switcher_revamp")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/R.java"
+ line="41645"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.content.res.default_locale")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/R.java"
+ line="44145"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.nfc.nfc_read_polling_loop")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/R.java"
+ line="45932"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.nfc.nfc_read_polling_loop")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/R.java"
+ line="45956"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.nfc.nfc_read_polling_loop")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/R.java"
+ line="45970"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.nfc.nfc_read_polling_loop")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/R.java"
+ line="45996"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("com.android.text.flags.use_bounds_for_width")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/R.java"
+ line="53416"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("com.android.text.flags.use_bounds_for_width")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/R.java"
+ line="53416"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("com.android.text.flags.use_bounds_for_width")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/R.java"
+ line="53416"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("com.android.text.flags.use_bounds_for_width")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/R.java"
+ line="53416"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("com.android.text.flags.use_bounds_for_width")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/R.java"
+ line="55227"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("com.android.text.flags.fix_line_height_for_locale")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/R.java"
+ line="55238"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("com.android.text.flags.use_bounds_for_width")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/R.java"
+ line="55249"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.view.flags.sensitive_content_app_protection_api")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/R.java"
+ line="62287"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @android.annotation.FlaggedApi("android.view.flags.sensitive_content_app_protection_api")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/android/R.srcjar!/android/R.java"
+ line="64240"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `METADATA_KEY_COMMENT_SHORT_DESCRIPTION` is a flagged API and should be inside an `if (Flags.hdRadioImproved())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_HD_RADIO_IMPROVED) to transfer requirement to caller`)"
+ errorLine1=" METADATA_KEYS_TYPE.put(METADATA_KEY_COMMENT_SHORT_DESCRIPTION, METADATA_TYPE_TEXT);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/hardware/radio/RadioMetadata.java"
+ line="249"
+ column="32"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `METADATA_KEY_COMMENT_ACTUAL_TEXT` is a flagged API and should be inside an `if (Flags.hdRadioImproved())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_HD_RADIO_IMPROVED) to transfer requirement to caller`)"
+ errorLine1=" METADATA_KEYS_TYPE.put(METADATA_KEY_COMMENT_ACTUAL_TEXT, METADATA_TYPE_TEXT);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/hardware/radio/RadioMetadata.java"
+ line="250"
+ column="32"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `METADATA_KEY_COMMERCIAL` is a flagged API and should be inside an `if (Flags.hdRadioImproved())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_HD_RADIO_IMPROVED) to transfer requirement to caller`)"
+ errorLine1=" METADATA_KEYS_TYPE.put(METADATA_KEY_COMMERCIAL, METADATA_TYPE_TEXT);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/hardware/radio/RadioMetadata.java"
+ line="251"
+ column="32"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `METADATA_KEY_UFIDS` is a flagged API and should be inside an `if (Flags.hdRadioImproved())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_HD_RADIO_IMPROVED) to transfer requirement to caller`)"
+ errorLine1=" METADATA_KEYS_TYPE.put(METADATA_KEY_UFIDS, METADATA_TYPE_TEXT_ARRAY);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/hardware/radio/RadioMetadata.java"
+ line="252"
+ column="32"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `METADATA_KEY_HD_STATION_NAME_SHORT` is a flagged API and should be inside an `if (Flags.hdRadioImproved())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_HD_RADIO_IMPROVED) to transfer requirement to caller`)"
+ errorLine1=" METADATA_KEYS_TYPE.put(METADATA_KEY_HD_STATION_NAME_SHORT, METADATA_TYPE_TEXT);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/hardware/radio/RadioMetadata.java"
+ line="253"
+ column="32"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `METADATA_KEY_HD_STATION_NAME_LONG` is a flagged API and should be inside an `if (Flags.hdRadioImproved())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_HD_RADIO_IMPROVED) to transfer requirement to caller`)"
+ errorLine1=" METADATA_KEYS_TYPE.put(METADATA_KEY_HD_STATION_NAME_LONG, METADATA_TYPE_TEXT);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/hardware/radio/RadioMetadata.java"
+ line="254"
+ column="32"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `METADATA_KEY_HD_SUBCHANNELS_AVAILABLE` is a flagged API and should be inside an `if (Flags.hdRadioImproved())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_HD_RADIO_IMPROVED) to transfer requirement to caller`)"
+ errorLine1=" METADATA_KEYS_TYPE.put(METADATA_KEY_HD_SUBCHANNELS_AVAILABLE, METADATA_TYPE_INT);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/hardware/radio/RadioMetadata.java"
+ line="255"
+ column="32"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `isPrivateProfile()` is a flagged API and should be inside an `if (Flags.allowPrivateProfile())` check (or annotate the surrounding method `fetchPrivateProfileUserHandle` with `@FlaggedApi(Flags.FLAG_ALLOW_PRIVATE_PROFILE) to transfer requirement to caller`)"
+ errorLine1=" if (userInfo.isPrivateProfile()) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/com/android/internal/app/ResolverActivity.java"
+ line="827"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getDefaultLocale()` is a flagged API and should be inside an `if (Flags.defaultLocale())` check (or annotate the surrounding method `updateConfigurationImpl` with `@FlaggedApi(Flags.FLAG_DEFAULT_LOCALE) to transfer requirement to caller`)"
+ errorLine1=" if (Flags.defaultLocale() && (lc.getDefaultLocale() != null)) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/content/res/ResourcesImpl.java"
+ line="474"
+ column="55"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getDefaultLocale()` is a flagged API and should be inside an `if (Flags.defaultLocale())` check (or annotate the surrounding method `updateConfigurationImpl` with `@FlaggedApi(Flags.FLAG_DEFAULT_LOCALE) to transfer requirement to caller`)"
+ errorLine1=" if (Flags.defaultLocale() && (lc.getDefaultLocale() != null)) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/content/res/ResourcesImpl.java"
+ line="515"
+ column="51"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `ROLLBACK_USER_IMPACT_LOW` is a flagged API and should be inside an `if (Flags.recoverabilityDetection())` check (or annotate the surrounding method `RollbackInfo` with `@FlaggedApi(Flags.FLAG_RECOVERABILITY_DETECTION) to transfer requirement to caller`)"
+ errorLine1=" PackageManager.ROLLBACK_USER_IMPACT_LOW);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/content/rollback/RollbackInfo.java"
+ line="80"
+ column="32"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getTransferReason()` is a flagged API and should be inside an `if (Flags.enableBuiltInSpeakerRouteSuitabilityStatuses())` check (or annotate the surrounding method `toString` with `@FlaggedApi(Flags.FLAG_ENABLE_BUILT_IN_SPEAKER_ROUTE_SUITABILITY_STATUSES) to transfer requirement to caller`)"
+ errorLine1=" .append(getTransferReason())"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/media/java/android/media/RoutingSessionInfo.java"
+ line="528"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `TRANSFER_REASON_FALLBACK` is a flagged API and should be inside an `if (Flags.enableBuiltInSpeakerRouteSuitabilityStatuses())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_ENABLE_BUILT_IN_SPEAKER_ROUTE_SUITABILITY_STATUSES) to transfer requirement to caller`)"
+ errorLine1=" @TransferReason private int mTransferReason = TRANSFER_REASON_FALLBACK;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/media/java/android/media/RoutingSessionInfo.java"
+ line="590"
+ column="55"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `SCREEN_RECORDING_STATE_NOT_VISIBLE` is a flagged API and should be inside an `if (Flags.screenRecordingCallbacks())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_SCREEN_RECORDING_CALLBACKS) to transfer requirement to caller`)"
+ errorLine1=" private @ScreenRecordingState int mState = SCREEN_RECORDING_STATE_NOT_VISIBLE;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/ScreenRecordingCallbacks.java"
+ line="54"
+ column="48"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `SCREEN_RECORDING_STATE_VISIBLE` is a flagged API and should be inside an `if (Flags.screenRecordingCallbacks())` check (or annotate the surrounding method `onScreenRecordingStateChanged` with `@FlaggedApi(Flags.FLAG_SCREEN_RECORDING_CALLBACKS) to transfer requirement to caller`)"
+ errorLine1=" ? SCREEN_RECORDING_STATE_VISIBLE"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/ScreenRecordingCallbacks.java"
+ line="85"
+ column="51"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `SCREEN_RECORDING_STATE_NOT_VISIBLE` is a flagged API and should be inside an `if (Flags.screenRecordingCallbacks())` check (or annotate the surrounding method `onScreenRecordingStateChanged` with `@FlaggedApi(Flags.FLAG_SCREEN_RECORDING_CALLBACKS) to transfer requirement to caller`)"
+ errorLine1=" : SCREEN_RECORDING_STATE_NOT_VISIBLE;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/ScreenRecordingCallbacks.java"
+ line="86"
+ column="51"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `SCREEN_RECORDING_STATE_VISIBLE` is a flagged API and should be inside an `if (Flags.screenRecordingCallbacks())` check (or annotate the surrounding method `addCallback` with `@FlaggedApi(Flags.FLAG_SCREEN_RECORDING_CALLBACKS) to transfer requirement to caller`)"
+ errorLine1=" ? SCREEN_RECORDING_STATE_VISIBLE"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/ScreenRecordingCallbacks.java"
+ line="96"
+ column="39"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `SCREEN_RECORDING_STATE_NOT_VISIBLE` is a flagged API and should be inside an `if (Flags.screenRecordingCallbacks())` check (or annotate the surrounding method `addCallback` with `@FlaggedApi(Flags.FLAG_SCREEN_RECORDING_CALLBACKS) to transfer requirement to caller`)"
+ errorLine1=" : SCREEN_RECORDING_STATE_NOT_VISIBLE;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/ScreenRecordingCallbacks.java"
+ line="97"
+ column="39"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `FOREGROUND_SERVICE_TYPE_MEDIA_PROCESSING` is a flagged API and should be inside an `if (Flags.introduceMediaProcessingType())` check (or annotate the surrounding method `foregroundServiceTypeToLabel` with `@FlaggedApi(Flags.FLAG_INTRODUCE_MEDIA_PROCESSING_TYPE) to transfer requirement to caller`)"
+ errorLine1=" case FOREGROUND_SERVICE_TYPE_MEDIA_PROCESSING:"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/content/pm/ServiceInfo.java"
+ line="707"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `isPrivateProfile()` is a flagged API and should be inside an `if (Flags.allowPrivateProfile())` check (or annotate the surrounding method `setLaunchUserSpecificMessage` with `@FlaggedApi(Flags.FLAG_ALLOW_PRIVATE_PROFILE) to transfer requirement to caller`)"
+ errorLine1=" if (userInfo != null && userInfo.isPrivateProfile()) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/com/android/internal/app/SetScreenLockDialogActivity.java"
+ line="146"
+ column="37"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @FlaggedApi("com.android.media.flags.enable_privileged_routing_for_media_routing_control")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/provider/Settings.java"
+ line="665"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @FlaggedApi("com.android.server.biometrics.face_vhal_feature")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/provider/Settings.java"
+ line="11022"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @FlaggedApi("com.android.server.biometrics.face_vhal_feature")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/provider/Settings.java"
+ line="11030"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @FlaggedApi("com.android.wifi.flags.shared_connectivity_broadcast_receiver_test_api")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/wifi/java/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityManager.java"
+ line="300"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getInputTransferToken()` is a flagged API and should be inside an `if (Flags.surfaceControlInputReceiver())` check (or annotate the surrounding method `createSurfaceView` with `@FlaggedApi(Flags.FLAG_SURFACE_CONTROL_INPUT_RECEIVER) to transfer requirement to caller`)"
+ errorLine1=" : attachedSurfaceControl.getInputTransferToken(),"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/window/SplashScreenView.java"
+ line="342"
+ column="35"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `uptimeNanos()` is a flagged API and should be inside an `if (Flags.adpfGpuReportActualWorkDuration())` check (or annotate the surrounding method `getTime` with `@FlaggedApi(Flags.FLAG_ADPF_GPU_REPORT_ACTUAL_WORK_DURATION) to transfer requirement to caller`)"
+ errorLine1=" return SystemClock.uptimeNanos() / 1000;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/com/android/internal/util/StatLogger.java"
+ line="94"
+ column="16"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `setUseBoundsForWidth()` is a flagged API and should be inside an `if (Flags.useBoundsForWidth())` check (or annotate the surrounding method `generate` with `@FlaggedApi(Flags.FLAG_USE_BOUNDS_FOR_WIDTH) to transfer requirement to caller`)"
+ errorLine1=" final LineBreaker lineBreaker = new LineBreaker.Builder()"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/core/java/android/text/StaticLayout.java"
+ line="823"
+ column="41"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `computeDrawingBoundingBox()` is a flagged API and should be inside an `if (Flags.useBoundsForWidth())` check (or annotate the surrounding method `computeDrawingBoundingBox` with `@FlaggedApi(Flags.FLAG_USE_BOUNDS_FOR_WIDTH) to transfer requirement to caller`)"
+ errorLine1=" mDrawingBounds = super.computeDrawingBoundingBox();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/text/StaticLayout.java"
+ line="1578"
+ column="30"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `createNoBreakSpan()` is a flagged API and should be inside an `if (Flags.noBreakNoHyphenationSpan())` check (or annotate the surrounding method `applyStyles` with `@FlaggedApi(Flags.FLAG_NO_BREAK_NO_HYPHENATION_SPAN) to transfer requirement to caller`)"
+ errorLine1=" buffer.setSpan(LineBreakConfigSpan.createNoBreakSpan(),"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/content/res/StringBlock.java"
+ line="297"
+ column="32"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `createNoHyphenationSpan()` is a flagged API and should be inside an `if (Flags.noBreakNoHyphenationSpan())` check (or annotate the surrounding method `applyStyles` with `@FlaggedApi(Flags.FLAG_NO_BREAK_NO_HYPHENATION_SPAN) to transfer requirement to caller`)"
+ errorLine1=" buffer.setSpan(LineBreakConfigSpan.createNoHyphenationSpan(),"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/content/res/StringBlock.java"
+ line="301"
+ column="32"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `LINE_BREAK_STYLE_UNSPECIFIED` is a flagged API and should be inside an `if (Flags.noBreakNoHyphenationSpan())` check (or annotate the surrounding method `applyStyles` with `@FlaggedApi(Flags.FLAG_NO_BREAK_NO_HYPHENATION_SPAN) to transfer requirement to caller`)"
+ errorLine1=" int lbStyle = LineBreakConfig.LINE_BREAK_STYLE_UNSPECIFIED;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/content/res/StringBlock.java"
+ line="387"
+ column="51"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `LINE_BREAK_STYLE_UNSPECIFIED` is a flagged API and should be inside an `if (Flags.noBreakNoHyphenationSpan())` check (or annotate the surrounding method `applyStyles` with `@FlaggedApi(Flags.FLAG_NO_BREAK_NO_HYPHENATION_SPAN) to transfer requirement to caller`)"
+ errorLine1=" int lbWordStyle = LineBreakConfig.LINE_BREAK_STYLE_UNSPECIFIED;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/content/res/StringBlock.java"
+ line="403"
+ column="55"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `LINE_BREAK_STYLE_UNSPECIFIED` is a flagged API and should be inside an `if (Flags.noBreakNoHyphenationSpan())` check (or annotate the surrounding method `applyStyles` with `@FlaggedApi(Flags.FLAG_NO_BREAK_NO_HYPHENATION_SPAN) to transfer requirement to caller`)"
+ errorLine1=" if (lbStyle != LineBreakConfig.LINE_BREAK_STYLE_UNSPECIFIED"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/content/res/StringBlock.java"
+ line="415"
+ column="52"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `LINE_BREAK_WORD_STYLE_UNSPECIFIED` is a flagged API and should be inside an `if (Flags.noBreakNoHyphenationSpan())` check (or annotate the surrounding method `applyStyles` with `@FlaggedApi(Flags.FLAG_NO_BREAK_NO_HYPHENATION_SPAN) to transfer requirement to caller`)"
+ errorLine1=" || lbWordStyle != LineBreakConfig.LINE_BREAK_WORD_STYLE_UNSPECIFIED) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/content/res/StringBlock.java"
+ line="416"
+ column="63"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `LineBreakConfigSpan()` is a flagged API and should be inside an `if (Flags.noBreakNoHyphenationSpan())` check (or annotate the surrounding method `applyStyles` with `@FlaggedApi(Flags.FLAG_NO_BREAK_NO_HYPHENATION_SPAN) to transfer requirement to caller`)"
+ errorLine1=" buffer.setSpan(new LineBreakConfigSpan("
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/core/java/android/content/res/StringBlock.java"
+ line="417"
+ column="40"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `HYPHENATION_UNSPECIFIED` is a flagged API and should be inside an `if (Flags.noBreakNoHyphenationSpan())` check (or annotate the surrounding method `applyStyles` with `@FlaggedApi(Flags.FLAG_NO_BREAK_NO_HYPHENATION_SPAN) to transfer requirement to caller`)"
+ errorLine1=" LineBreakConfig.HYPHENATION_UNSPECIFIED)),"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/content/res/StringBlock.java"
+ line="419"
+ column="57"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `setServiceCapabilities()` is a flagged API and should be inside an `if (Flags.dataOnlyCellularService())` check (or annotate the surrounding method `createFromParcel` with `@FlaggedApi(Flags.FLAG_DATA_ONLY_CELLULAR_SERVICE) to transfer requirement to caller`)"
+ errorLine1=" return new Builder()"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/SubscriptionInfo.java"
+ line="957"
+ column="20"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `setTransferStatus()` is a flagged API and should be inside an `if (Flags.supportPsimToEsimConversion())` check (or annotate the surrounding method `createFromParcel` with `@FlaggedApi(Flags.FLAG_SUPPORT_PSIM_TO_ESIM_CONVERSION) to transfer requirement to caller`)"
+ errorLine1=" return new Builder()"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/SubscriptionInfo.java"
+ line="957"
+ column="20"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `SERVICE_CAPABILITY_DATA` is a flagged API and should be inside an `if (Flags.dataOnlyCellularService())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_DATA_ONLY_CELLULAR_SERVICE) to transfer requirement to caller`)"
+ errorLine1=" public static final int SERVICE_CAPABILITY_MAX = SERVICE_CAPABILITY_DATA;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/SubscriptionManager.java"
+ line="1436"
+ column="54"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `SERVICE_CAPABILITY_VOICE` is a flagged API and should be inside an `if (Flags.dataOnlyCellularService())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_DATA_ONLY_CELLULAR_SERVICE) to transfer requirement to caller`)"
+ errorLine1=" serviceCapabilityToBitmask(SERVICE_CAPABILITY_VOICE);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/SubscriptionManager.java"
+ line="1443"
+ column="40"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `SERVICE_CAPABILITY_SMS` is a flagged API and should be inside an `if (Flags.dataOnlyCellularService())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_DATA_ONLY_CELLULAR_SERVICE) to transfer requirement to caller`)"
+ errorLine1=" serviceCapabilityToBitmask(SERVICE_CAPABILITY_SMS);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/SubscriptionManager.java"
+ line="1450"
+ column="40"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `SERVICE_CAPABILITY_DATA` is a flagged API and should be inside an `if (Flags.dataOnlyCellularService())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_DATA_ONLY_CELLULAR_SERVICE) to transfer requirement to caller`)"
+ errorLine1=" serviceCapabilityToBitmask(SERVICE_CAPABILITY_DATA);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/SubscriptionManager.java"
+ line="1457"
+ column="40"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="This is a flagged API and should be inside an `if (Flags.telecomResolveHiddenDependencies())` check (or annotate the surrounding method `addOnSubscriptionsChangedListener` with `@FlaggedApi(Flags.FLAG_TELECOM_RESOLVE_HIDDEN_DEPENDENCIES) to transfer requirement to caller`)"
+ errorLine1=" TelephonyRegistryManager telephonyRegistryManager = (TelephonyRegistryManager)"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/SubscriptionManager.java"
+ line="1696"
+ column="62"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `addOnSubscriptionsChangedListener()` is a flagged API and should be inside an `if (Flags.telecomResolveHiddenDependencies())` check (or annotate the surrounding method `addOnSubscriptionsChangedListener` with `@FlaggedApi(Flags.FLAG_TELECOM_RESOLVE_HIDDEN_DEPENDENCIES) to transfer requirement to caller`)"
+ errorLine1=" telephonyRegistryManager.addOnSubscriptionsChangedListener(listener,"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/SubscriptionManager.java"
+ line="1699"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="This is a flagged API and should be inside an `if (Flags.telecomResolveHiddenDependencies())` check (or annotate the surrounding method `removeOnSubscriptionsChangedListener` with `@FlaggedApi(Flags.FLAG_TELECOM_RESOLVE_HIDDEN_DEPENDENCIES) to transfer requirement to caller`)"
+ errorLine1=" TelephonyRegistryManager telephonyRegistryManager = (TelephonyRegistryManager)"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/SubscriptionManager.java"
+ line="1726"
+ column="62"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `removeOnSubscriptionsChangedListener()` is a flagged API and should be inside an `if (Flags.telecomResolveHiddenDependencies())` check (or annotate the surrounding method `removeOnSubscriptionsChangedListener` with `@FlaggedApi(Flags.FLAG_TELECOM_RESOLVE_HIDDEN_DEPENDENCIES) to transfer requirement to caller`)"
+ errorLine1=" telephonyRegistryManager.removeOnSubscriptionsChangedListener(listener);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/SubscriptionManager.java"
+ line="1729"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="This is a flagged API and should be inside an `if (Flags.telecomResolveHiddenDependencies())` check (or annotate the surrounding method `addOnOpportunisticSubscriptionsChangedListener` with `@FlaggedApi(Flags.FLAG_TELECOM_RESOLVE_HIDDEN_DEPENDENCIES) to transfer requirement to caller`)"
+ errorLine1=" TelephonyRegistryManager telephonyRegistryManager = (TelephonyRegistryManager)"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/SubscriptionManager.java"
+ line="1784"
+ column="62"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `addOnOpportunisticSubscriptionsChangedListener()` is a flagged API and should be inside an `if (Flags.telecomResolveHiddenDependencies())` check (or annotate the surrounding method `addOnOpportunisticSubscriptionsChangedListener` with `@FlaggedApi(Flags.FLAG_TELECOM_RESOLVE_HIDDEN_DEPENDENCIES) to transfer requirement to caller`)"
+ errorLine1=" telephonyRegistryManager.addOnOpportunisticSubscriptionsChangedListener("
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/SubscriptionManager.java"
+ line="1787"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="This is a flagged API and should be inside an `if (Flags.telecomResolveHiddenDependencies())` check (or annotate the surrounding method `removeOnOpportunisticSubscriptionsChangedListener` with `@FlaggedApi(Flags.FLAG_TELECOM_RESOLVE_HIDDEN_DEPENDENCIES) to transfer requirement to caller`)"
+ errorLine1=" TelephonyRegistryManager telephonyRegistryManager = (TelephonyRegistryManager)"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/SubscriptionManager.java"
+ line="1808"
+ column="62"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `removeOnOpportunisticSubscriptionsChangedListener()` is a flagged API and should be inside an `if (Flags.telecomResolveHiddenDependencies())` check (or annotate the surrounding method `removeOnOpportunisticSubscriptionsChangedListener` with `@FlaggedApi(Flags.FLAG_TELECOM_RESOLVE_HIDDEN_DEPENDENCIES) to transfer requirement to caller`)"
+ errorLine1=" telephonyRegistryManager.removeOnOpportunisticSubscriptionsChangedListener(listener);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/SubscriptionManager.java"
+ line="1811"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `SERVICE_CAPABILITY_VOICE` is a flagged API and should be inside an `if (Flags.dataOnlyCellularService())` check (or annotate the surrounding method `getServiceCapabilitiesSet` with `@FlaggedApi(Flags.FLAG_DATA_ONLY_CELLULAR_SERVICE) to transfer requirement to caller`)"
+ errorLine1=" for (int i = SERVICE_CAPABILITY_VOICE; i <= SERVICE_CAPABILITY_MAX; i++) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/SubscriptionManager.java"
+ line="4800"
+ column="22"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `CREATOR` is a flagged API and should be inside an `if (Flags.surfaceControlInputReceiver())` check (or annotate the surrounding method `SurfacePackage` with `@FlaggedApi(Flags.FLAG_SURFACE_CONTROL_INPUT_RECEIVER) to transfer requirement to caller`)"
+ errorLine1=" mInputTransferToken = InputTransferToken.CREATOR.createFromParcel(in);"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/SurfaceControlViewHost.java"
+ line="196"
+ column="54"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `writeToParcel()` is a flagged API and should be inside an `if (Flags.surfaceControlInputReceiver())` check (or annotate the surrounding method `writeToParcel` with `@FlaggedApi(Flags.FLAG_SURFACE_CONTROL_INPUT_RECEIVER) to transfer requirement to caller`)"
+ errorLine1=" mInputTransferToken.writeToParcel(out, flags);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/SurfaceControlViewHost.java"
+ line="276"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getInputTransferToken()` is a flagged API and should be inside an `if (Flags.surfaceControlInputReceiver())` check (or annotate the surrounding method `toString` with `@FlaggedApi(Flags.FLAG_SURFACE_CONTROL_INPUT_RECEIVER) to transfer requirement to caller`)"
+ errorLine1=" return "{inputTransferToken=" + getInputTransferToken() + " remoteInterface=""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/SurfaceControlViewHost.java"
+ line="309"
+ column="45"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `InputTransferToken()` is a flagged API and should be inside an `if (Flags.surfaceControlInputReceiver())` check (or annotate the surrounding method `SurfaceControlViewHost` with `@FlaggedApi(Flags.FLAG_SURFACE_CONTROL_INPUT_RECEIVER) to transfer requirement to caller`)"
+ errorLine1=" this(context, display, hostToken == null ? null : new InputTransferToken(hostToken),"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/SurfaceControlViewHost.java"
+ line="352"
+ column="59"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `transferTouchGesture()` is a flagged API and should be inside an `if (Flags.surfaceControlInputReceiver())` check (or annotate the surrounding method `transferTouchGestureToHost` with `@FlaggedApi(Flags.FLAG_SURFACE_CONTROL_INPUT_RECEIVER) to transfer requirement to caller`)"
+ errorLine1=" return wm.transferTouchGesture(getInputTransferToken(), mWm.mHostInputTransferToken);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/SurfaceControlViewHost.java"
+ line="602"
+ column="16"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getInputTransferToken()` is a flagged API and should be inside an `if (Flags.surfaceControlInputReceiver())` check (or annotate the surrounding method `requestEmbeddedFocus` with `@FlaggedApi(Flags.FLAG_SURFACE_CONTROL_INPUT_RECEIVER) to transfer requirement to caller`)"
+ errorLine1=" mSurfacePackage.getInputTransferToken(), gainFocus);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/SurfaceView.java"
+ line="2155"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `uptimeNanos()` is a flagged API and should be inside an `if (Flags.adpfGpuReportActualWorkDuration())` check (or annotate the surrounding method `uptimeMillis$ravenwood` with `@FlaggedApi(Flags.FLAG_ADPF_GPU_REPORT_ACTUAL_WORK_DURATION) to transfer requirement to caller`)"
+ errorLine1=" return uptimeNanos() / 1_000_000;"
+ errorLine2=" ~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/os/SystemClock.java"
+ line="202"
+ column="16"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `uptimeNanos()` is a flagged API and should be inside an `if (Flags.adpfGpuReportActualWorkDuration())` check (or annotate the surrounding method `elapsedRealtimeNanos$ravenwood` with `@FlaggedApi(Flags.FLAG_ADPF_GPU_REPORT_ACTUAL_WORK_DURATION) to transfer requirement to caller`)"
+ errorLine1=" return uptimeNanos() + (DateUtils.HOUR_IN_MILLIS * 1_000_000);"
+ errorLine2=" ~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/os/SystemClock.java"
+ line="276"
+ column="16"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @FlaggedApi("com.android.server.power.optimization.power_monitor_api")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/os/health/SystemHealthManager.java"
+ line="231"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="@FlaggedApi should specify an actual flag constant; raw strings are discouraged (and more importantly, **not enforced**)"
+ errorLine1=" @FlaggedApi("com.android.server.power.optimization.power_monitor_api")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/os/health/SystemHealthManager.java"
+ line="287"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `null()` is a flagged API and should be inside an `if (Flags.vdmPublicApis())` check (or annotate the surrounding method `setupVirtualDeviceListener` with `@FlaggedApi(Flags.FLAG_VDM_PUBLIC_APIS) to transfer requirement to caller`)"
+ errorLine1=" mVirtualDeviceListener = new VirtualDeviceManager.VirtualDeviceListener() {"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/core/java/android/hardware/SystemSensorManager.java"
+ line="612"
+ column="34"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="This is a flagged API and should be inside an `if (Flags.vdmPublicApis())` check (or annotate the surrounding method `setupVirtualDeviceListener` with `@FlaggedApi(Flags.FLAG_VDM_PUBLIC_APIS) to transfer requirement to caller`)"
+ errorLine1=" mVirtualDeviceListener = new VirtualDeviceManager.VirtualDeviceListener() {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/hardware/SystemSensorManager.java"
+ line="612"
+ column="38"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `registerVirtualDeviceListener()` is a flagged API and should be inside an `if (Flags.vdmPublicApis())` check (or annotate the surrounding method `setupVirtualDeviceListener` with `@FlaggedApi(Flags.FLAG_VDM_PUBLIC_APIS) to transfer requirement to caller`)"
+ errorLine1=" mVdm.registerVirtualDeviceListener(mContext.getMainExecutor(), mVirtualDeviceListener);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/hardware/SystemSensorManager.java"
+ line="627"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Class `SecurityStateManager` is a flagged API and should be inside an `if (Flags.securityStateService())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_SECURITY_STATE_SERVICE) to transfer requirement to caller`)"
+ errorLine1=" registerService(Context.SECURITY_STATE_SERVICE, SecurityStateManager.class,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/SystemServiceRegistry.java"
+ line="676"
+ column="57"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `SECURITY_STATE_SERVICE` is a flagged API and should be inside an `if (Flags.securityStateService())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_SECURITY_STATE_SERVICE) to transfer requirement to caller`)"
+ errorLine1=" registerService(Context.SECURITY_STATE_SERVICE, SecurityStateManager.class,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/SystemServiceRegistry.java"
+ line="676"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `SECURITY_STATE_SERVICE` is a flagged API and should be inside an `if (Flags.securityStateService())` check (or annotate the surrounding method `createService` with `@FlaggedApi(Flags.FLAG_SECURITY_STATE_SERVICE) to transfer requirement to caller`)"
+ errorLine1=" Context.SECURITY_STATE_SERVICE);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/SystemServiceRegistry.java"
+ line="682"
+ column="41"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `SecurityStateManager()` is a flagged API and should be inside an `if (Flags.securityStateService())` check (or annotate the surrounding method `createService` with `@FlaggedApi(Flags.FLAG_SECURITY_STATE_SERVICE) to transfer requirement to caller`)"
+ errorLine1=" return new SecurityStateManager(service);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/SystemServiceRegistry.java"
+ line="684"
+ column="32"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Class `TelephonyRegistryManager` is a flagged API and should be inside an `if (Flags.telecomResolveHiddenDependencies())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_TELECOM_RESOLVE_HIDDEN_DEPENDENCIES) to transfer requirement to caller`)"
+ errorLine1=" registerService(Context.TELEPHONY_REGISTRY_SERVICE, TelephonyRegistryManager.class,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/SystemServiceRegistry.java"
+ line="743"
+ column="61"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `TelephonyRegistryManager()` is a flagged API and should be inside an `if (Flags.telecomResolveHiddenDependencies())` check (or annotate the surrounding method `createService` with `@FlaggedApi(Flags.FLAG_TELECOM_RESOLVE_HIDDEN_DEPENDENCIES) to transfer requirement to caller`)"
+ errorLine1=" return new TelephonyRegistryManager(ctx);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/SystemServiceRegistry.java"
+ line="747"
+ column="28"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Class `TvAdManager` is a flagged API and should be inside an `if (Flags.enableAdServiceFw())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_ENABLE_AD_SERVICE_FW) to transfer requirement to caller`)"
+ errorLine1=" registerService(Context.TV_AD_SERVICE, TvAdManager.class,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/SystemServiceRegistry.java"
+ line="1019"
+ column="48"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `TV_AD_SERVICE` is a flagged API and should be inside an `if (Flags.enableAdServiceFw())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_ENABLE_AD_SERVICE_FW) to transfer requirement to caller`)"
+ errorLine1=" registerService(Context.TV_AD_SERVICE, TvAdManager.class,"
+ errorLine2=" ~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/SystemServiceRegistry.java"
+ line="1019"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `TV_AD_SERVICE` is a flagged API and should be inside an `if (Flags.enableAdServiceFw())` check (or annotate the surrounding method `createService` with `@FlaggedApi(Flags.FLAG_ENABLE_AD_SERVICE_FW) to transfer requirement to caller`)"
+ errorLine1=" ServiceManager.getServiceOrThrow(Context.TV_AD_SERVICE);"
+ errorLine2=" ~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/SystemServiceRegistry.java"
+ line="1025"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `TvAdManager()` is a flagged API and should be inside an `if (Flags.enableAdServiceFw())` check (or annotate the surrounding method `createService` with `@FlaggedApi(Flags.FLAG_ENABLE_AD_SERVICE_FW) to transfer requirement to caller`)"
+ errorLine1=" return new TvAdManager(service, ctx.getUserId());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/SystemServiceRegistry.java"
+ line="1028"
+ column="32"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Class `PersistentDataBlockManager` is a flagged API and should be inside an `if (Flags.frpEnforcement())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_FRP_ENFORCEMENT) to transfer requirement to caller`)"
+ errorLine1=" registerService(Context.PERSISTENT_DATA_BLOCK_SERVICE, PersistentDataBlockManager.class,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/SystemServiceRegistry.java"
+ line="1067"
+ column="64"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `PERSISTENT_DATA_BLOCK_SERVICE` is a flagged API and should be inside an `if (Flags.frpEnforcement())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_FRP_ENFORCEMENT) to transfer requirement to caller`)"
+ errorLine1=" registerService(Context.PERSISTENT_DATA_BLOCK_SERVICE, PersistentDataBlockManager.class,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/SystemServiceRegistry.java"
+ line="1067"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `PERSISTENT_DATA_BLOCK_SERVICE` is a flagged API and should be inside an `if (Flags.frpEnforcement())` check (or annotate the surrounding method `createService` with `@FlaggedApi(Flags.FLAG_FRP_ENFORCEMENT) to transfer requirement to caller`)"
+ errorLine1=" IBinder b = ServiceManager.getServiceOrThrow(Context.PERSISTENT_DATA_BLOCK_SERVICE);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/SystemServiceRegistry.java"
+ line="1071"
+ column="70"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `PersistentDataBlockManager()` is a flagged API and should be inside an `if (Flags.frpEnforcement())` check (or annotate the surrounding method `createService` with `@FlaggedApi(Flags.FLAG_FRP_ENFORCEMENT) to transfer requirement to caller`)"
+ errorLine1=" return new PersistentDataBlockManager(persistentDataBlockService);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/SystemServiceRegistry.java"
+ line="1075"
+ column="28"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Class `ContextualSearchManager` is a flagged API and should be inside an `if (Flags.enableService())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_ENABLE_SERVICE) to transfer requirement to caller`)"
+ errorLine1=" registerService(Context.CONTEXTUAL_SEARCH_SERVICE, ContextualSearchManager.class,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/SystemServiceRegistry.java"
+ line="1319"
+ column="60"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `CONTEXTUAL_SEARCH_SERVICE` is a flagged API and should be inside an `if (Flags.enableService())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_ENABLE_SERVICE) to transfer requirement to caller`)"
+ errorLine1=" registerService(Context.CONTEXTUAL_SEARCH_SERVICE, ContextualSearchManager.class,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/SystemServiceRegistry.java"
+ line="1319"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `CONTEXTUAL_SEARCH_SERVICE` is a flagged API and should be inside an `if (Flags.enableService())` check (or annotate the surrounding method `createService` with `@FlaggedApi(Flags.FLAG_ENABLE_SERVICE) to transfer requirement to caller`)"
+ errorLine1=" IBinder b = ServiceManager.getService(Context.CONTEXTUAL_SEARCH_SERVICE);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/SystemServiceRegistry.java"
+ line="1324"
+ column="71"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `ContextualSearchManager()` is a flagged API and should be inside an `if (Flags.enableService())` check (or annotate the surrounding method `createService` with `@FlaggedApi(Flags.FLAG_ENABLE_SERVICE) to transfer requirement to caller`)"
+ errorLine1=" return b == null ? null : new ContextualSearchManager();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/SystemServiceRegistry.java"
+ line="1325"
+ column="51"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Class `DeviceStateManager` is a flagged API and should be inside an `if (Flags.deviceStatePropertyApi())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_DEVICE_STATE_PROPERTY_API) to transfer requirement to caller`)"
+ errorLine1=" registerService(Context.DEVICE_STATE_SERVICE, DeviceStateManager.class,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/SystemServiceRegistry.java"
+ line="1564"
+ column="55"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `DeviceStateManager()` is a flagged API and should be inside an `if (Flags.deviceStatePropertyApi())` check (or annotate the surrounding method `createService` with `@FlaggedApi(Flags.FLAG_DEVICE_STATE_PROPERTY_API) to transfer requirement to caller`)"
+ errorLine1=" return new DeviceStateManager();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/SystemServiceRegistry.java"
+ line="1568"
+ column="32"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Class `OnDeviceIntelligenceManager` is a flagged API and should be inside an `if (Flags.enableOnDeviceIntelligence())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_ENABLE_ON_DEVICE_INTELLIGENCE) to transfer requirement to caller`)"
+ errorLine1=" registerService(Context.ON_DEVICE_INTELLIGENCE_SERVICE, OnDeviceIntelligenceManager.class,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/SystemServiceRegistry.java"
+ line="1638"
+ column="65"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `ON_DEVICE_INTELLIGENCE_SERVICE` is a flagged API and should be inside an `if (Flags.enableOnDeviceIntelligence())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_ENABLE_ON_DEVICE_INTELLIGENCE) to transfer requirement to caller`)"
+ errorLine1=" registerService(Context.ON_DEVICE_INTELLIGENCE_SERVICE, OnDeviceIntelligenceManager.class,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/SystemServiceRegistry.java"
+ line="1638"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `ON_DEVICE_INTELLIGENCE_SERVICE` is a flagged API and should be inside an `if (Flags.enableOnDeviceIntelligence())` check (or annotate the surrounding method `createService` with `@FlaggedApi(Flags.FLAG_ENABLE_ON_DEVICE_INTELLIGENCE) to transfer requirement to caller`)"
+ errorLine1=" Context.ON_DEVICE_INTELLIGENCE_SERVICE);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/SystemServiceRegistry.java"
+ line="1644"
+ column="41"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `OnDeviceIntelligenceManager()` is a flagged API and should be inside an `if (Flags.enableOnDeviceIntelligence())` check (or annotate the surrounding method `createService` with `@FlaggedApi(Flags.FLAG_ENABLE_ON_DEVICE_INTELLIGENCE) to transfer requirement to caller`)"
+ errorLine1=" return new OnDeviceIntelligenceManager(ctx.getOuterContext(), manager);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/SystemServiceRegistry.java"
+ line="1647"
+ column="32"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Class `E2eeContactKeysManager` is a flagged API and should be inside an `if (Flags.userKeys())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_USER_KEYS) to transfer requirement to caller`)"
+ errorLine1=" registerService(Context.CONTACT_KEYS_SERVICE, E2eeContactKeysManager.class,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/SystemServiceRegistry.java"
+ line="1670"
+ column="55"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `CONTACT_KEYS_SERVICE` is a flagged API and should be inside an `if (Flags.userKeys())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_USER_KEYS) to transfer requirement to caller`)"
+ errorLine1=" registerService(Context.CONTACT_KEYS_SERVICE, E2eeContactKeysManager.class,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/SystemServiceRegistry.java"
+ line="1670"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `addView()` is a flagged API and should be inside an `if (Flags.enableArrowIconOnHoverWhenClickable())` check (or annotate the surrounding method `addTab` with `@FlaggedApi(Flags.FLAG_ENABLE_ARROW_ICON_ON_HOVER_WHEN_CLICKABLE) to transfer requirement to caller`)"
+ errorLine1=" mTabWidget.addView(tabIndicator);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/widget/TabHost.java"
+ line="256"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="This is a flagged API and should be inside an `if (Flags.simultaneousCallingIndications())` check (or annotate the surrounding method `onSimultaneousCallingStateChanged` with `@FlaggedApi(Flags.FLAG_SIMULTANEOUS_CALLING_INDICATIONS) to transfer requirement to caller`)"
+ errorLine1=" (SimultaneousCellularCallingSupportListener) mTelephonyCallbackWeakRef.get();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/telephony/TelephonyCallback.java"
+ line="2065"
+ column="22"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `onSimultaneousCellularCallingSubscriptionsChanged()` is a flagged API and should be inside an `if (Flags.simultaneousCallingIndications())` check (or annotate the surrounding method `onSimultaneousCallingStateChanged` with `@FlaggedApi(Flags.FLAG_SIMULTANEOUS_CALLING_INDICATIONS) to transfer requirement to caller`)"
+ errorLine1=" () -> listener.onSimultaneousCellularCallingSubscriptionsChanged("
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/core/java/android/telephony/TelephonyCallback.java"
+ line="2070"
+ column="35"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Class `SatelliteManager` is a flagged API and should be inside an `if (Flags.oemEnabledSatelliteFlag())` check (or annotate the surrounding method `registerServiceWrappers` with `@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) to transfer requirement to caller`)"
+ errorLine1=" SatelliteManager.class,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/TelephonyFrameworkInitializer.java"
+ line="146"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `SatelliteManager()` is a flagged API and should be inside an `if (Flags.oemEnabledSatelliteFlag())` check (or annotate the surrounding method `registerServiceWrappers` with `@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) to transfer requirement to caller`)"
+ errorLine1=" ? new SatelliteManager(context) : null"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/TelephonyFrameworkInitializer.java"
+ line="148"
+ column="27"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="This is a flagged API and should be inside an `if (Flags.telecomResolveHiddenDependencies())` check (or annotate the surrounding method `listen` with `@FlaggedApi(Flags.FLAG_TELECOM_RESOLVE_HIDDEN_DEPENDENCIES) to transfer requirement to caller`)"
+ errorLine1=" (TelephonyRegistryManager)"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/TelephonyManager.java"
+ line="6726"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `listenFromListener()` is a flagged API and should be inside an `if (Flags.telecomResolveHiddenDependencies())` check (or annotate the surrounding method `listen` with `@FlaggedApi(Flags.FLAG_TELECOM_RESOLVE_HIDDEN_DEPENDENCIES) to transfer requirement to caller`)"
+ errorLine1=" telephonyRegistry.listenFromListener(mSubId, renounceFineLocationAccess,"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/TelephonyManager.java"
+ line="6734"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="This is a flagged API and should be inside an `if (Flags.telecomResolveHiddenDependencies())` check (or annotate the surrounding method `registerTelephonyCallback` with `@FlaggedApi(Flags.FLAG_TELECOM_RESOLVE_HIDDEN_DEPENDENCIES) to transfer requirement to caller`)"
+ errorLine1=" mTelephonyRegistryMgr = (TelephonyRegistryManager)"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/TelephonyManager.java"
+ line="17689"
+ column="34"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `registerTelephonyCallback()` is a flagged API and should be inside an `if (Flags.telecomResolveHiddenDependencies())` check (or annotate the surrounding method `registerTelephonyCallback` with `@FlaggedApi(Flags.FLAG_TELECOM_RESOLVE_HIDDEN_DEPENDENCIES) to transfer requirement to caller`)"
+ errorLine1=" mTelephonyRegistryMgr.registerTelephonyCallback("
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/TelephonyManager.java"
+ line="17692"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Class `TelephonyRegistryManager` is a flagged API and should be inside an `if (Flags.telecomResolveHiddenDependencies())` check (or annotate the surrounding method `unregisterTelephonyCallback` with `@FlaggedApi(Flags.FLAG_TELECOM_RESOLVE_HIDDEN_DEPENDENCIES) to transfer requirement to caller`)"
+ errorLine1=" mTelephonyRegistryMgr = mContext.getSystemService(TelephonyRegistryManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/TelephonyManager.java"
+ line="17717"
+ column="59"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `unregisterTelephonyCallback()` is a flagged API and should be inside an `if (Flags.telecomResolveHiddenDependencies())` check (or annotate the surrounding method `unregisterTelephonyCallback` with `@FlaggedApi(Flags.FLAG_TELECOM_RESOLVE_HIDDEN_DEPENDENCIES) to transfer requirement to caller`)"
+ errorLine1=" mTelephonyRegistryMgr.unregisterTelephonyCallback(mSubId, getOpPackageName(),"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/TelephonyManager.java"
+ line="17719"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Class `TelephonyRegistryManager` is a flagged API and should be inside an `if (Flags.telecomResolveHiddenDependencies())` check (or annotate the surrounding method `registerCarrierPrivilegesCallback` with `@FlaggedApi(Flags.FLAG_TELECOM_RESOLVE_HIDDEN_DEPENDENCIES) to transfer requirement to caller`)"
+ errorLine1=" mTelephonyRegistryMgr = mContext.getSystemService(TelephonyRegistryManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/TelephonyManager.java"
+ line="18688"
+ column="59"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `addCarrierPrivilegesCallback()` is a flagged API and should be inside an `if (Flags.telecomResolveHiddenDependencies())` check (or annotate the surrounding method `registerCarrierPrivilegesCallback` with `@FlaggedApi(Flags.FLAG_TELECOM_RESOLVE_HIDDEN_DEPENDENCIES) to transfer requirement to caller`)"
+ errorLine1=" mTelephonyRegistryMgr.addCarrierPrivilegesCallback(logicalSlotIndex, executor, callback);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/TelephonyManager.java"
+ line="18692"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Class `TelephonyRegistryManager` is a flagged API and should be inside an `if (Flags.telecomResolveHiddenDependencies())` check (or annotate the surrounding method `unregisterCarrierPrivilegesCallback` with `@FlaggedApi(Flags.FLAG_TELECOM_RESOLVE_HIDDEN_DEPENDENCIES) to transfer requirement to caller`)"
+ errorLine1=" mTelephonyRegistryMgr = mContext.getSystemService(TelephonyRegistryManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/TelephonyManager.java"
+ line="18708"
+ column="59"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `removeCarrierPrivilegesCallback()` is a flagged API and should be inside an `if (Flags.telecomResolveHiddenDependencies())` check (or annotate the surrounding method `unregisterCarrierPrivilegesCallback` with `@FlaggedApi(Flags.FLAG_TELECOM_RESOLVE_HIDDEN_DEPENDENCIES) to transfer requirement to caller`)"
+ errorLine1=" mTelephonyRegistryMgr.removeCarrierPrivilegesCallback(callback);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/telephony/java/android/telephony/TelephonyManager.java"
+ line="18712"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="This is a flagged API and should be inside an `if (Flags.simultaneousCallingIndications())` check (or annotate the surrounding method `getEventsFromCallback` with `@FlaggedApi(Flags.FLAG_SIMULTANEOUS_CALLING_INDICATIONS) to transfer requirement to caller`)"
+ errorLine1=" instanceof TelephonyCallback.SimultaneousCellularCallingSupportListener) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/telephony/TelephonyRegistryManager.java"
+ line="1241"
+ column="28"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `EVENT_SIMULTANEOUS_CELLULAR_CALLING_SUBSCRIPTIONS_CHANGED` is a flagged API and should be inside an `if (Flags.simultaneousCallingIndications())` check (or annotate the surrounding method `getEventsFromCallback` with `@FlaggedApi(Flags.FLAG_SIMULTANEOUS_CALLING_INDICATIONS) to transfer requirement to caller`)"
+ errorLine1=" TelephonyCallback.EVENT_SIMULTANEOUS_CELLULAR_CALLING_SUBSCRIPTIONS_CHANGED);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/telephony/TelephonyRegistryManager.java"
+ line="1243"
+ column="39"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `TEXT_RUN_FLAG_LEFT_EDGE` is a flagged API and should be inside an `if (Flags.letterSpacingJustification())` check (or annotate the surrounding method `calculateRunFlag` with `@FlaggedApi(Flags.FLAG_LETTER_SPACING_JUSTIFICATION) to transfer requirement to caller`)"
+ errorLine1=" return Paint.TEXT_RUN_FLAG_LEFT_EDGE | Paint.TEXT_RUN_FLAG_RIGHT_EDGE;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/text/TextLine.java"
+ line="342"
+ column="26"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `TEXT_RUN_FLAG_RIGHT_EDGE` is a flagged API and should be inside an `if (Flags.letterSpacingJustification())` check (or annotate the surrounding method `calculateRunFlag` with `@FlaggedApi(Flags.FLAG_LETTER_SPACING_JUSTIFICATION) to transfer requirement to caller`)"
+ errorLine1=" return Paint.TEXT_RUN_FLAG_LEFT_EDGE | Paint.TEXT_RUN_FLAG_RIGHT_EDGE;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/text/TextLine.java"
+ line="342"
+ column="58"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `TEXT_RUN_FLAG_LEFT_EDGE` is a flagged API and should be inside an `if (Flags.letterSpacingJustification())` check (or annotate the surrounding method `calculateRunFlag` with `@FlaggedApi(Flags.FLAG_LETTER_SPACING_JUSTIFICATION) to transfer requirement to caller`)"
+ errorLine1=" runFlag |= Paint.TEXT_RUN_FLAG_LEFT_EDGE;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/text/TextLine.java"
+ line="359"
+ column="34"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `TEXT_RUN_FLAG_RIGHT_EDGE` is a flagged API and should be inside an `if (Flags.letterSpacingJustification())` check (or annotate the surrounding method `calculateRunFlag` with `@FlaggedApi(Flags.FLAG_LETTER_SPACING_JUSTIFICATION) to transfer requirement to caller`)"
+ errorLine1=" runFlag |= Paint.TEXT_RUN_FLAG_RIGHT_EDGE;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/text/TextLine.java"
+ line="361"
+ column="34"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `TEXT_RUN_FLAG_RIGHT_EDGE` is a flagged API and should be inside an `if (Flags.letterSpacingJustification())` check (or annotate the surrounding method `calculateRunFlag` with `@FlaggedApi(Flags.FLAG_LETTER_SPACING_JUSTIFICATION) to transfer requirement to caller`)"
+ errorLine1=" runFlag |= Paint.TEXT_RUN_FLAG_RIGHT_EDGE;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/text/TextLine.java"
+ line="366"
+ column="34"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `TEXT_RUN_FLAG_LEFT_EDGE` is a flagged API and should be inside an `if (Flags.letterSpacingJustification())` check (or annotate the surrounding method `calculateRunFlag` with `@FlaggedApi(Flags.FLAG_LETTER_SPACING_JUSTIFICATION) to transfer requirement to caller`)"
+ errorLine1=" runFlag |= Paint.TEXT_RUN_FLAG_LEFT_EDGE;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/text/TextLine.java"
+ line="368"
+ column="34"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `TEXT_RUN_FLAG_LEFT_EDGE` is a flagged API and should be inside an `if (Flags.letterSpacingJustification())` check (or annotate the surrounding method `resolveRunFlagForSubSequence` with `@FlaggedApi(Flags.FLAG_LETTER_SPACING_JUSTIFICATION) to transfer requirement to caller`)"
+ errorLine1=" if ((runFlag & Paint.TEXT_RUN_FLAG_LEFT_EDGE) != 0) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/text/TextLine.java"
+ line="394"
+ column="30"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `TEXT_RUN_FLAG_LEFT_EDGE` is a flagged API and should be inside an `if (Flags.letterSpacingJustification())` check (or annotate the surrounding method `resolveRunFlagForSubSequence` with `@FlaggedApi(Flags.FLAG_LETTER_SPACING_JUSTIFICATION) to transfer requirement to caller`)"
+ errorLine1=" localRunFlag &= ~Paint.TEXT_RUN_FLAG_LEFT_EDGE;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/text/TextLine.java"
+ line="398"
+ column="44"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `TEXT_RUN_FLAG_LEFT_EDGE` is a flagged API and should be inside an `if (Flags.letterSpacingJustification())` check (or annotate the surrounding method `resolveRunFlagForSubSequence` with `@FlaggedApi(Flags.FLAG_LETTER_SPACING_JUSTIFICATION) to transfer requirement to caller`)"
+ errorLine1=" localRunFlag &= ~Paint.TEXT_RUN_FLAG_LEFT_EDGE;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/text/TextLine.java"
+ line="403"
+ column="44"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `TEXT_RUN_FLAG_RIGHT_EDGE` is a flagged API and should be inside an `if (Flags.letterSpacingJustification())` check (or annotate the surrounding method `resolveRunFlagForSubSequence` with `@FlaggedApi(Flags.FLAG_LETTER_SPACING_JUSTIFICATION) to transfer requirement to caller`)"
+ errorLine1=" if ((runFlag & Paint.TEXT_RUN_FLAG_RIGHT_EDGE) != 0) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/text/TextLine.java"
+ line="407"
+ column="30"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `TEXT_RUN_FLAG_RIGHT_EDGE` is a flagged API and should be inside an `if (Flags.letterSpacingJustification())` check (or annotate the surrounding method `resolveRunFlagForSubSequence` with `@FlaggedApi(Flags.FLAG_LETTER_SPACING_JUSTIFICATION) to transfer requirement to caller`)"
+ errorLine1=" localRunFlag &= ~Paint.TEXT_RUN_FLAG_RIGHT_EDGE;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/text/TextLine.java"
+ line="411"
+ column="44"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `TEXT_RUN_FLAG_RIGHT_EDGE` is a flagged API and should be inside an `if (Flags.letterSpacingJustification())` check (or annotate the surrounding method `resolveRunFlagForSubSequence` with `@FlaggedApi(Flags.FLAG_LETTER_SPACING_JUSTIFICATION) to transfer requirement to caller`)"
+ errorLine1=" localRunFlag &= ~Paint.TEXT_RUN_FLAG_RIGHT_EDGE;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/text/TextLine.java"
+ line="416"
+ column="44"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `TEXT_RUN_FLAG_LEFT_EDGE` is a flagged API and should be inside an `if (Flags.letterSpacingJustification())` check (or annotate the surrounding method `handleText` with `@FlaggedApi(Flags.FLAG_LETTER_SPACING_JUSTIFICATION) to transfer requirement to caller`)"
+ errorLine1=" if ((runFlag & Paint.TEXT_RUN_FLAG_LEFT_EDGE) == Paint.TEXT_RUN_FLAG_LEFT_EDGE) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/text/TextLine.java"
+ line="1345"
+ column="30"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `TEXT_RUN_FLAG_LEFT_EDGE` is a flagged API and should be inside an `if (Flags.letterSpacingJustification())` check (or annotate the surrounding method `handleText` with `@FlaggedApi(Flags.FLAG_LETTER_SPACING_JUSTIFICATION) to transfer requirement to caller`)"
+ errorLine1=" if ((runFlag & Paint.TEXT_RUN_FLAG_LEFT_EDGE) == Paint.TEXT_RUN_FLAG_LEFT_EDGE) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/text/TextLine.java"
+ line="1345"
+ column="64"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `TEXT_RUN_FLAG_LEFT_EDGE` is a flagged API and should be inside an `if (Flags.letterSpacingJustification())` check (or annotate the surrounding method `handleText` with `@FlaggedApi(Flags.FLAG_LETTER_SPACING_JUSTIFICATION) to transfer requirement to caller`)"
+ errorLine1=" wp.setFlags(wp.getFlags() | Paint.TEXT_RUN_FLAG_LEFT_EDGE);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/text/TextLine.java"
+ line="1346"
+ column="47"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `TEXT_RUN_FLAG_LEFT_EDGE` is a flagged API and should be inside an `if (Flags.letterSpacingJustification())` check (or annotate the surrounding method `handleText` with `@FlaggedApi(Flags.FLAG_LETTER_SPACING_JUSTIFICATION) to transfer requirement to caller`)"
+ errorLine1=" wp.setFlags(wp.getFlags() & ~Paint.TEXT_RUN_FLAG_LEFT_EDGE);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/text/TextLine.java"
+ line="1348"
+ column="48"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `TEXT_RUN_FLAG_RIGHT_EDGE` is a flagged API and should be inside an `if (Flags.letterSpacingJustification())` check (or annotate the surrounding method `handleText` with `@FlaggedApi(Flags.FLAG_LETTER_SPACING_JUSTIFICATION) to transfer requirement to caller`)"
+ errorLine1=" if ((runFlag & Paint.TEXT_RUN_FLAG_RIGHT_EDGE) == Paint.TEXT_RUN_FLAG_RIGHT_EDGE) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/text/TextLine.java"
+ line="1350"
+ column="30"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `TEXT_RUN_FLAG_RIGHT_EDGE` is a flagged API and should be inside an `if (Flags.letterSpacingJustification())` check (or annotate the surrounding method `handleText` with `@FlaggedApi(Flags.FLAG_LETTER_SPACING_JUSTIFICATION) to transfer requirement to caller`)"
+ errorLine1=" if ((runFlag & Paint.TEXT_RUN_FLAG_RIGHT_EDGE) == Paint.TEXT_RUN_FLAG_RIGHT_EDGE) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/text/TextLine.java"
+ line="1350"
+ column="65"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `TEXT_RUN_FLAG_RIGHT_EDGE` is a flagged API and should be inside an `if (Flags.letterSpacingJustification())` check (or annotate the surrounding method `handleText` with `@FlaggedApi(Flags.FLAG_LETTER_SPACING_JUSTIFICATION) to transfer requirement to caller`)"
+ errorLine1=" wp.setFlags(wp.getFlags() | Paint.TEXT_RUN_FLAG_RIGHT_EDGE);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/text/TextLine.java"
+ line="1351"
+ column="47"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `TEXT_RUN_FLAG_RIGHT_EDGE` is a flagged API and should be inside an `if (Flags.letterSpacingJustification())` check (or annotate the surrounding method `handleText` with `@FlaggedApi(Flags.FLAG_LETTER_SPACING_JUSTIFICATION) to transfer requirement to caller`)"
+ errorLine1=" wp.setFlags(wp.getFlags() & ~Paint.TEXT_RUN_FLAG_RIGHT_EDGE);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/text/TextLine.java"
+ line="1353"
+ column="48"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `CREATOR` is a flagged API and should be inside an `if (Flags.noBreakNoHyphenationSpan())` check (or annotate the surrounding method `createFromParcel` with `@FlaggedApi(Flags.FLAG_NO_BREAK_NO_HYPHENATION_SPAN) to transfer requirement to caller`)"
+ errorLine1=" span = LineBreakConfigSpan.CREATOR.createFromParcel(p);"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/text/TextUtils.java"
+ line="1023"
+ column="48"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getFontMetricsForLocale()` is a flagged API and should be inside an `if (Flags.fixLineHeightForLocale())` check (or annotate the surrounding method `getResolvedMinimumFontMetrics` with `@FlaggedApi(Flags.FLAG_FIX_LINE_HEIGHT_FOR_LOCALE) to transfer requirement to caller`)"
+ errorLine1=" mTextPaint.getFontMetricsForLocale(mLocalePreferredFontMetrics);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/widget/TextView.java"
+ line="10860"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `setMinimumFontMetrics()` is a flagged API and should be inside an `if (Flags.fixLineHeightForLocale())` check (or annotate the surrounding method `makeNewLayout` with `@FlaggedApi(Flags.FLAG_FIX_LINE_HEIGHT_FOR_LOCALE) to transfer requirement to caller`)"
+ errorLine1=" StaticLayout.Builder builder = StaticLayout.Builder.obtain(mHint, 0,"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/core/java/android/widget/TextView.java"
+ line="10965"
+ column="48"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `setUseBoundsForWidth()` is a flagged API and should be inside an `if (Flags.useBoundsForWidth())` check (or annotate the surrounding method `makeNewLayout` with `@FlaggedApi(Flags.FLAG_USE_BOUNDS_FOR_WIDTH) to transfer requirement to caller`)"
+ errorLine1=" StaticLayout.Builder builder = StaticLayout.Builder.obtain(mHint, 0,"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/core/java/android/widget/TextView.java"
+ line="10965"
+ column="48"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `setLineBreakConfig()` is a flagged API and should be inside an `if (Flags.noBreakNoHyphenationSpan())` check (or annotate the surrounding method `makeSingleLayout` with `@FlaggedApi(Flags.FLAG_NO_BREAK_NO_HYPHENATION_SPAN) to transfer requirement to caller`)"
+ errorLine1=" final DynamicLayout.Builder builder = DynamicLayout.Builder.obtain(mText, mTextPaint,"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/core/java/android/widget/TextView.java"
+ line="11029"
+ column="51"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `setMinimumFontMetrics()` is a flagged API and should be inside an `if (Flags.fixLineHeightForLocale())` check (or annotate the surrounding method `makeSingleLayout` with `@FlaggedApi(Flags.FLAG_FIX_LINE_HEIGHT_FOR_LOCALE) to transfer requirement to caller`)"
+ errorLine1=" final DynamicLayout.Builder builder = DynamicLayout.Builder.obtain(mText, mTextPaint,"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/core/java/android/widget/TextView.java"
+ line="11029"
+ column="51"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `setUseBoundsForWidth()` is a flagged API and should be inside an `if (Flags.useBoundsForWidth())` check (or annotate the surrounding method `makeSingleLayout` with `@FlaggedApi(Flags.FLAG_USE_BOUNDS_FOR_WIDTH) to transfer requirement to caller`)"
+ errorLine1=" final DynamicLayout.Builder builder = DynamicLayout.Builder.obtain(mText, mTextPaint,"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/core/java/android/widget/TextView.java"
+ line="11029"
+ column="51"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `setMinimumFontMetrics()` is a flagged API and should be inside an `if (Flags.fixLineHeightForLocale())` check (or annotate the surrounding method `makeSingleLayout` with `@FlaggedApi(Flags.FLAG_FIX_LINE_HEIGHT_FOR_LOCALE) to transfer requirement to caller`)"
+ errorLine1=" StaticLayout.Builder builder = StaticLayout.Builder.obtain(mTransformed,"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/core/java/android/widget/TextView.java"
+ line="11115"
+ column="44"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `setUseBoundsForWidth()` is a flagged API and should be inside an `if (Flags.useBoundsForWidth())` check (or annotate the surrounding method `makeSingleLayout` with `@FlaggedApi(Flags.FLAG_USE_BOUNDS_FOR_WIDTH) to transfer requirement to caller`)"
+ errorLine1=" StaticLayout.Builder builder = StaticLayout.Builder.obtain(mTransformed,"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/core/java/android/widget/TextView.java"
+ line="11115"
+ column="44"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `computeDrawingBoundingBox()` is a flagged API and should be inside an `if (Flags.useBoundsForWidth())` check (or annotate the surrounding method `desired` with `@FlaggedApi(Flags.FLAG_USE_BOUNDS_FOR_WIDTH) to transfer requirement to caller`)"
+ errorLine1=" max = Math.max(max, layout.computeDrawingBoundingBox().width());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/widget/TextView.java"
+ line="11181"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getDrawingBoundingBox()` is a flagged API and should be inside an `if (Flags.useBoundsForWidth())` check (or annotate the surrounding method `onMeasure` with `@FlaggedApi(Flags.FLAG_USE_BOUNDS_FOR_WIDTH) to transfer requirement to caller`)"
+ errorLine1=" RectF bbox = boring.getDrawingBoundingBox();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/widget/TextView.java"
+ line="11275"
+ column="34"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `setMinimumFontMetrics()` is a flagged API and should be inside an `if (Flags.fixLineHeightForLocale())` check (or annotate the surrounding method `suggestedSizeFitsInSpace` with `@FlaggedApi(Flags.FLAG_FIX_LINE_HEIGHT_FOR_LOCALE) to transfer requirement to caller`)"
+ errorLine1=" layoutBuilder.setAlignment(getLayoutAlignment())"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/core/java/android/widget/TextView.java"
+ line="11502"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `setUseBoundsForWidth()` is a flagged API and should be inside an `if (Flags.useBoundsForWidth())` check (or annotate the surrounding method `suggestedSizeFitsInSpace` with `@FlaggedApi(Flags.FLAG_USE_BOUNDS_FOR_WIDTH) to transfer requirement to caller`)"
+ errorLine1=" layoutBuilder.setAlignment(getLayoutAlignment())"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/core/java/android/widget/TextView.java"
+ line="11502"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `CONFIG_FORCE_ANALOG_FM` is a flagged API and should be inside an `if (Flags.hdRadioImproved())` check (or annotate the surrounding method `convertForceAnalogConfigFlag` with `@FlaggedApi(Flags.FLAG_HD_RADIO_IMPROVED) to transfer requirement to caller`)"
+ errorLine1=" && mTuner.isConfigFlagSupported(RadioManager.CONFIG_FORCE_ANALOG_FM)) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/hardware/radio/TunerAdapter.java"
+ line="427"
+ column="62"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `notifyTvInputSessionData()` is a flagged API and should be inside an `if (Flags.enableAdServiceFw())` check (or annotate the surrounding method `run` with `@FlaggedApi(Flags.FLAG_ENABLE_AD_SERVICE_FW) to transfer requirement to caller`)"
+ errorLine1=" mSession.getAdSession().notifyTvInputSessionData(type, data);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/media/java/android/media/tv/TvInputManager.java"
+ line="1498"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `onStopPlayback()` is a flagged API and should be inside an `if (Flags.tiafVApis())` check (or annotate the surrounding method `stopPlayback` with `@FlaggedApi(Flags.FLAG_TIAF_V_APIS) to transfer requirement to caller`)"
+ errorLine1=" onStopPlayback(mode);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/media/java/android/media/tv/TvInputService.java"
+ line="2113"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `onResumePlayback()` is a flagged API and should be inside an `if (Flags.tiafVApis())` check (or annotate the surrounding method `resumePlayback` with `@FlaggedApi(Flags.FLAG_TIAF_V_APIS) to transfer requirement to caller`)"
+ errorLine1=" onResumePlayback();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/media/java/android/media/tv/TvInputService.java"
+ line="2120"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `onTvAdSessionData()` is a flagged API and should be inside an `if (Flags.enableAdServiceFw())` check (or annotate the surrounding method `notifyTvAdSessionData` with `@FlaggedApi(Flags.FLAG_ENABLE_AD_SERVICE_FW) to transfer requirement to caller`)"
+ errorLine1=" onTvAdSessionData(type, data);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/media/java/android/media/tv/TvInputService.java"
+ line="2218"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `onCertificate()` is a flagged API and should be inside an `if (Flags.tiafVApis())` check (or annotate the surrounding method `sendCertificate` with `@FlaggedApi(Flags.FLAG_TIAF_V_APIS) to transfer requirement to caller`)"
+ errorLine1=" onCertificate(host, port, cert);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/media/java/android/media/tv/interactive/TvInteractiveAppService.java"
+ line="1824"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `onVideoFreezeUpdated()` is a flagged API and should be inside an `if (Flags.tiafVApis())` check (or annotate the surrounding method `notifyVideoFreezeUpdated` with `@FlaggedApi(Flags.FLAG_TIAF_V_APIS) to transfer requirement to caller`)"
+ errorLine1=" onVideoFreezeUpdated(isFrozen);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/media/java/android/media/tv/interactive/TvInteractiveAppService.java"
+ line="1889"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `onSelectedTrackInfo()` is a flagged API and should be inside an `if (Flags.tiafVApis())` check (or annotate the surrounding method `sendSelectedTrackInfo` with `@FlaggedApi(Flags.FLAG_TIAF_V_APIS) to transfer requirement to caller`)"
+ errorLine1=" onSelectedTrackInfo(tracks);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/media/java/android/media/tv/interactive/TvInteractiveAppService.java"
+ line="1945"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `onRequestSelectedTrackInfo()` is a flagged API and should be inside an `if (Flags.tiafVApis())` check (or annotate the surrounding method `onRequestSelectedTrackInfo` with `@FlaggedApi(Flags.FLAG_TIAF_V_APIS) to transfer requirement to caller`)"
+ errorLine1=" mCallback.onRequestSelectedTrackInfo(mIAppServiceId);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/media/java/android/media/tv/interactive/TvInteractiveAppView.java"
+ line="1822"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `onVideoFreezeUpdated()` is a flagged API and should be inside an `if (Flags.tiafVApis())` check (or annotate the surrounding method `onVideoFreezeUpdated` with `@FlaggedApi(Flags.FLAG_TIAF_V_APIS) to transfer requirement to caller`)"
+ errorLine1=" mCallback.onVideoFreezeUpdated(mInputId, isFrozen);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/media/java/android/media/tv/TvView.java"
+ line="1779"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `convertSpToDp()` is a flagged API and should be inside an `if (Flags.fontScaleConverterPublic())` check (or annotate the surrounding method `applyDimension` with `@FlaggedApi(Flags.FLAG_FONT_SCALE_CONVERTER_PUBLIC) to transfer requirement to caller`)"
+ errorLine1=" metrics.fontScaleConverter.convertSpToDp(value),"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/util/TypedValue.java"
+ line="433"
+ column="29"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `convertDpToSp()` is a flagged API and should be inside an `if (Flags.fontScaleConverterPublic())` check (or annotate the surrounding method `deriveDimension` with `@FlaggedApi(Flags.FLAG_FONT_SCALE_CONVERTER_PUBLIC) to transfer requirement to caller`)"
+ errorLine1=" return metrics.fontScaleConverter.convertDpToSp(dpValue);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/util/TypedValue.java"
+ line="479"
+ column="28"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `PERSISTENT_DEVICE_ID_DEFAULT` is a flagged API and should be inside an `if (Flags.persistentDeviceIdApi())` check (or annotate the surrounding method `grantRuntimePermission` with `@FlaggedApi(Flags.FLAG_PERSISTENT_DEVICE_ID_API) to transfer requirement to caller`)"
+ errorLine1=" VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT, userId);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/UiAutomationConnection.java"
+ line="367"
+ column="42"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `PERSISTENT_DEVICE_ID_DEFAULT` is a flagged API and should be inside an `if (Flags.persistentDeviceIdApi())` check (or annotate the surrounding method `revokeRuntimePermission` with `@FlaggedApi(Flags.FLAG_PERSISTENT_DEVICE_ID_API) to transfer requirement to caller`)"
+ errorLine1=" VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT, userId, null);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/app/UiAutomationConnection.java"
+ line="387"
+ column="42"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `isResumed()` is a flagged API and should be inside an `if (Flags.enableNfcMainline())` check (or annotate the surrounding method `dump` with `@FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) to transfer requirement to caller`)"
+ errorLine1=" pw.print(pfx); pw.print("resumed: "); pw.println(mActivity.isResumed());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/translation/UiTranslationController.java"
+ line="219"
+ column="58"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `COMPLIANCE_WARNING_INPUT_POWER_LIMITED` is a flagged API and should be inside an `if (Flags.enableUsbDataComplianceWarning())` check (or annotate the surrounding method `complianceWarningsToString` with `@FlaggedApi(Flags.FLAG_ENABLE_USB_DATA_COMPLIANCE_WARNING) to transfer requirement to caller`)"
+ errorLine1=" case UsbPortStatus.COMPLIANCE_WARNING_INPUT_POWER_LIMITED:"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/hardware/usb/UsbPort.java"
+ line="813"
+ column="40"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `COMPLIANCE_WARNING_MISSING_DATA_LINES` is a flagged API and should be inside an `if (Flags.enableUsbDataComplianceWarning())` check (or annotate the surrounding method `complianceWarningsToString` with `@FlaggedApi(Flags.FLAG_ENABLE_USB_DATA_COMPLIANCE_WARNING) to transfer requirement to caller`)"
+ errorLine1=" case UsbPortStatus.COMPLIANCE_WARNING_MISSING_DATA_LINES:"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/hardware/usb/UsbPort.java"
+ line="816"
+ column="40"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `COMPLIANCE_WARNING_ENUMERATION_FAIL` is a flagged API and should be inside an `if (Flags.enableUsbDataComplianceWarning())` check (or annotate the surrounding method `complianceWarningsToString` with `@FlaggedApi(Flags.FLAG_ENABLE_USB_DATA_COMPLIANCE_WARNING) to transfer requirement to caller`)"
+ errorLine1=" case UsbPortStatus.COMPLIANCE_WARNING_ENUMERATION_FAIL:"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/hardware/usb/UsbPort.java"
+ line="819"
+ column="40"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `COMPLIANCE_WARNING_FLAKY_CONNECTION` is a flagged API and should be inside an `if (Flags.enableUsbDataComplianceWarning())` check (or annotate the surrounding method `complianceWarningsToString` with `@FlaggedApi(Flags.FLAG_ENABLE_USB_DATA_COMPLIANCE_WARNING) to transfer requirement to caller`)"
+ errorLine1=" case UsbPortStatus.COMPLIANCE_WARNING_FLAKY_CONNECTION:"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/hardware/usb/UsbPort.java"
+ line="822"
+ column="40"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `COMPLIANCE_WARNING_UNRELIABLE_IO` is a flagged API and should be inside an `if (Flags.enableUsbDataComplianceWarning())` check (or annotate the surrounding method `complianceWarningsToString` with `@FlaggedApi(Flags.FLAG_ENABLE_USB_DATA_COMPLIANCE_WARNING) to transfer requirement to caller`)"
+ errorLine1=" case UsbPortStatus.COMPLIANCE_WARNING_UNRELIABLE_IO:"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/hardware/usb/UsbPort.java"
+ line="825"
+ column="40"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `USER_TYPE_PROFILE_MANAGED` is a flagged API and should be inside an `if (Flags.allowPrivateProfile())` check (or annotate the surrounding method `getDefaultUserType` with `@FlaggedApi(Flags.FLAG_ALLOW_PRIVATE_PROFILE) to transfer requirement to caller`)"
+ errorLine1=" case FLAG_MANAGED_PROFILE: return UserManager.USER_TYPE_PROFILE_MANAGED;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/content/pm/UserInfo.java"
+ line="350"
+ column="59"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `USER_TYPE_PROFILE_MANAGED` is a flagged API and should be inside an `if (Flags.allowPrivateProfile())` check (or annotate the surrounding method `isUserTypeManagedProfile` with `@FlaggedApi(Flags.FLAG_ALLOW_PRIVATE_PROFILE) to transfer requirement to caller`)"
+ errorLine1=" return USER_TYPE_PROFILE_MANAGED.equals(userType);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/os/UserManager.java"
+ line="3063"
+ column="16"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `USER_TYPE_PROFILE_CLONE` is a flagged API and should be inside an `if (Flags.allowPrivateProfile())` check (or annotate the surrounding method `isUserTypeCloneProfile` with `@FlaggedApi(Flags.FLAG_ALLOW_PRIVATE_PROFILE) to transfer requirement to caller`)"
+ errorLine1=" return USER_TYPE_PROFILE_CLONE.equals(userType);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/os/UserManager.java"
+ line="3100"
+ column="16"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `USER_TYPE_PROFILE_PRIVATE` is a flagged API and should be inside an `if (Flags.allowPrivateProfile())` check (or annotate the surrounding method `isUserTypePrivateProfile` with `@FlaggedApi(Flags.FLAG_ALLOW_PRIVATE_PROFILE) to transfer requirement to caller`)"
+ errorLine1=" return USER_TYPE_PROFILE_PRIVATE.equals(userType);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/os/UserManager.java"
+ line="3121"
+ column="16"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `CONTENT_SENSITIVITY_AUTO` is a flagged API and should be inside an `if (Flags.sensitiveContentAppProtectionApi())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_SENSITIVE_CONTENT_APP_PROTECTION_API) to transfer requirement to caller`)"
+ errorLine1=" (CONTENT_SENSITIVITY_AUTO | CONTENT_SENSITIVITY_SENSITIVE"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/View.java"
+ line="3929"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `CONTENT_SENSITIVITY_SENSITIVE` is a flagged API and should be inside an `if (Flags.sensitiveContentAppProtectionApi())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_SENSITIVE_CONTENT_APP_PROTECTION_API) to transfer requirement to caller`)"
+ errorLine1=" (CONTENT_SENSITIVITY_AUTO | CONTENT_SENSITIVITY_SENSITIVE"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/View.java"
+ line="3929"
+ column="41"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `CONTENT_SENSITIVITY_NOT_SENSITIVE` is a flagged API and should be inside an `if (Flags.sensitiveContentAppProtectionApi())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_SENSITIVE_CONTENT_APP_PROTECTION_API) to transfer requirement to caller`)"
+ errorLine1=" | CONTENT_SENSITIVITY_NOT_SENSITIVE) << PFLAG4_CONTENT_SENSITIVITY_SHIFT;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/View.java"
+ line="3930"
+ column="23"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `REQUESTED_FRAME_RATE_CATEGORY_DEFAULT` is a flagged API and should be inside an `if (Flags.toolkitSetFrameRateReadOnly())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY) to transfer requirement to caller`)"
+ errorLine1=" private float mPreferredFrameRate = REQUESTED_FRAME_RATE_CATEGORY_DEFAULT;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/View.java"
+ line="5784"
+ column="41"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `CONTENT_SENSITIVITY_AUTO` is a flagged API and should be inside an `if (Flags.sensitiveContentAppProtectionApi())` check (or annotate the surrounding method `View` with `@FlaggedApi(Flags.FLAG_SENSITIVE_CONTENT_APP_PROTECTION_API) to transfer requirement to caller`)"
+ errorLine1=" setContentSensitivity(a.getInt(attr, CONTENT_SENSITIVITY_AUTO));"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/View.java"
+ line="6528"
+ column="58"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `setContentSensitivity()` is a flagged API and should be inside an `if (Flags.sensitiveContentAppProtectionApi())` check (or annotate the surrounding method `View` with `@FlaggedApi(Flags.FLAG_SENSITIVE_CONTENT_APP_PROTECTION_API) to transfer requirement to caller`)"
+ errorLine1=" setContentSensitivity(a.getInt(attr, CONTENT_SENSITIVITY_AUTO));"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/View.java"
+ line="6528"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `setPendingCredentialRequest()` is a flagged API and should be inside an `if (Flags.autofillCredmanDevIntegration())` check (or annotate the surrounding method `onProvideStructure` with `@FlaggedApi(Flags.FLAG_AUTOFILL_CREDMAN_DEV_INTEGRATION) to transfer requirement to caller`)"
+ errorLine1=" structure.setPendingCredentialRequest("
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/core/java/android/view/View.java"
+ line="9665"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getPendingCredentialCallback()` is a flagged API and should be inside an `if (Flags.autofillCredmanDevIntegration())` check (or annotate the surrounding method `onGetCredentialResponse` with `@FlaggedApi(Flags.FLAG_AUTOFILL_CREDMAN_DEV_INTEGRATION) to transfer requirement to caller`)"
+ errorLine1=" if (getPendingCredentialCallback() == null) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/View.java"
+ line="10070"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getPendingCredentialCallback()` is a flagged API and should be inside an `if (Flags.autofillCredmanDevIntegration())` check (or annotate the surrounding method `onGetCredentialResponse` with `@FlaggedApi(Flags.FLAG_AUTOFILL_CREDMAN_DEV_INTEGRATION) to transfer requirement to caller`)"
+ errorLine1=" getPendingCredentialCallback().onResult(response);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/View.java"
+ line="10074"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getPendingCredentialCallback()` is a flagged API and should be inside an `if (Flags.autofillCredmanDevIntegration())` check (or annotate the surrounding method `onGetCredentialException` with `@FlaggedApi(Flags.FLAG_AUTOFILL_CREDMAN_DEV_INTEGRATION) to transfer requirement to caller`)"
+ errorLine1=" if (getPendingCredentialCallback() == null) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/View.java"
+ line="10081"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getPendingCredentialCallback()` is a flagged API and should be inside an `if (Flags.autofillCredmanDevIntegration())` check (or annotate the surrounding method `onGetCredentialException` with `@FlaggedApi(Flags.FLAG_AUTOFILL_CREDMAN_DEV_INTEGRATION) to transfer requirement to caller`)"
+ errorLine1=" getPendingCredentialCallback().onError(new GetCredentialException(errorType, errorMsg));"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/View.java"
+ line="10085"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `isContentSensitive()` is a flagged API and should be inside an `if (Flags.sensitiveContentAppProtectionApi())` check (or annotate the surrounding method `updateSensitiveViewsCountIfNeeded` with `@FlaggedApi(Flags.FLAG_SENSITIVE_CONTENT_APP_PROTECTION_API) to transfer requirement to caller`)"
+ errorLine1=" if (appeared && isContentSensitive()) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/View.java"
+ line="10597"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `setPendingCredentialRequest()` is a flagged API and should be inside an `if (Flags.autofillCredmanDevIntegration())` check (or annotate the surrounding method `populateVirtualStructure` with `@FlaggedApi(Flags.FLAG_AUTOFILL_CREDMAN_DEV_INTEGRATION) to transfer requirement to caller`)"
+ errorLine1=" structure.setPendingCredentialRequest("
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/core/java/android/view/View.java"
+ line="11106"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `CONTENT_SENSITIVITY_AUTO` is a flagged API and should be inside an `if (Flags.sensitiveContentAppProtectionApi())` check (or annotate the surrounding method `setAutofillHints` with `@FlaggedApi(Flags.FLAG_SENSITIVE_CONTENT_APP_PROTECTION_API) to transfer requirement to caller`)"
+ errorLine1=" if (getContentSensitivity() == CONTENT_SENSITIVITY_AUTO) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/View.java"
+ line="13689"
+ column="44"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getContentSensitivity()` is a flagged API and should be inside an `if (Flags.sensitiveContentAppProtectionApi())` check (or annotate the surrounding method `setAutofillHints` with `@FlaggedApi(Flags.FLAG_SENSITIVE_CONTENT_APP_PROTECTION_API) to transfer requirement to caller`)"
+ errorLine1=" if (getContentSensitivity() == CONTENT_SENSITIVITY_AUTO) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/View.java"
+ line="13689"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `DRAG_FLAG_GLOBAL_SAME_APPLICATION` is a flagged API and should be inside an `if (Flags.delegateUnhandledDrags())` check (or annotate the surrounding method `startDragAndDrop` with `@FlaggedApi(Flags.FLAG_DELEGATE_UNHANDLED_DRAGS) to transfer requirement to caller`)"
+ errorLine1=" if ((flags & DRAG_FLAG_GLOBAL) != 0 && ((flags & DRAG_FLAG_GLOBAL_SAME_APPLICATION) != 0)) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/View.java"
+ line="29019"
+ column="58"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getIntentSender()` is a flagged API and should be inside an `if (Flags.delegateUnhandledDrags())` check (or annotate the surrounding method `hasActivityPendingIntents` with `@FlaggedApi(Flags.FLAG_DELEGATE_UNHANDLED_DRAGS) to transfer requirement to caller`)"
+ errorLine1=" if (item.getIntentSender() != null) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/View.java"
+ line="29187"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getIntentSender()` is a flagged API and should be inside an `if (Flags.delegateUnhandledDrags())` check (or annotate the surrounding method `hasActivityPendingIntents` with `@FlaggedApi(Flags.FLAG_DELEGATE_UNHANDLED_DRAGS) to transfer requirement to caller`)"
+ errorLine1=" final PendingIntent pi = new PendingIntent(item.getIntentSender().getTarget());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/View.java"
+ line="29188"
+ column="60"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getIntentSender()` is a flagged API and should be inside an `if (Flags.delegateUnhandledDrags())` check (or annotate the surrounding method `cleanUpPendingIntents` with `@FlaggedApi(Flags.FLAG_DELEGATE_UNHANDLED_DRAGS) to transfer requirement to caller`)"
+ errorLine1=" if (item.getIntentSender() != null) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/View.java"
+ line="29205"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getIntentSender()` is a flagged API and should be inside an `if (Flags.delegateUnhandledDrags())` check (or annotate the surrounding method `cleanUpPendingIntents` with `@FlaggedApi(Flags.FLAG_DELEGATE_UNHANDLED_DRAGS) to transfer requirement to caller`)"
+ errorLine1=" final PendingIntent pi = new PendingIntent(item.getIntentSender().getTarget());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/View.java"
+ line="29206"
+ column="60"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `REQUESTED_FRAME_RATE_CATEGORY_NO_PREFERENCE` is a flagged API and should be inside an `if (Flags.toolkitSetFrameRateReadOnly())` check (or annotate the surrounding method `votePreferredFrameRate` with `@FlaggedApi(Flags.FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY) to transfer requirement to caller`)"
+ errorLine1=" case (int) REQUESTED_FRAME_RATE_CATEGORY_NO_PREFERENCE ->"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/View.java"
+ line="33991"
+ column="32"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `REQUESTED_FRAME_RATE_CATEGORY_LOW` is a flagged API and should be inside an `if (Flags.toolkitSetFrameRateReadOnly())` check (or annotate the surrounding method `votePreferredFrameRate` with `@FlaggedApi(Flags.FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY) to transfer requirement to caller`)"
+ errorLine1=" case (int) REQUESTED_FRAME_RATE_CATEGORY_LOW ->"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/View.java"
+ line="33994"
+ column="32"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `REQUESTED_FRAME_RATE_CATEGORY_NORMAL` is a flagged API and should be inside an `if (Flags.toolkitSetFrameRateReadOnly())` check (or annotate the surrounding method `votePreferredFrameRate` with `@FlaggedApi(Flags.FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY) to transfer requirement to caller`)"
+ errorLine1=" case (int) REQUESTED_FRAME_RATE_CATEGORY_NORMAL ->"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/View.java"
+ line="33997"
+ column="32"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `REQUESTED_FRAME_RATE_CATEGORY_HIGH` is a flagged API and should be inside an `if (Flags.toolkitSetFrameRateReadOnly())` check (or annotate the surrounding method `votePreferredFrameRate` with `@FlaggedApi(Flags.FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY) to transfer requirement to caller`)"
+ errorLine1=" case (int) REQUESTED_FRAME_RATE_CATEGORY_HIGH ->"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/View.java"
+ line="34000"
+ column="32"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getDesiredHdrHeadroom()` is a flagged API and should be inside an `if (Flags.limitedHdr())` check (or annotate the surrounding method `enableHardwareAcceleration` with `@FlaggedApi(Flags.FLAG_LIMITED_HDR) to transfer requirement to caller`)"
+ errorLine1=" updateColorModeIfNeeded(attrs.getColorMode(), attrs.getDesiredHdrHeadroom());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/ViewRootImpl.java"
+ line="2022"
+ column="63"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getDesiredHdrHeadroom()` is a flagged API and should be inside an `if (Flags.limitedHdr())` check (or annotate the surrounding method `performTraversals` with `@FlaggedApi(Flags.FLAG_LIMITED_HDR) to transfer requirement to caller`)"
+ errorLine1=" updateColorModeIfNeeded(lp.getColorMode(), lp.getDesiredHdrHeadroom());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/ViewRootImpl.java"
+ line="3748"
+ column="60"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getFrameTimeNanos()` is a flagged API and should be inside an `if (Flags.expectedPresentationTimeApi())` check (or annotate the surrounding method `draw` with `@FlaggedApi(Flags.FLAG_EXPECTED_PRESENTATION_TIME_API) to transfer requirement to caller`)"
+ errorLine1=" mChoreographer.getFrameTimeNanos() / TimeUtils.NANOS_PER_MS;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/ViewRootImpl.java"
+ line="5597"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `uptimeNanos()` is a flagged API and should be inside an `if (Flags.adpfGpuReportActualWorkDuration())` check (or annotate the surrounding method `draw` with `@FlaggedApi(Flags.FLAG_ADPF_GPU_REPORT_ACTUAL_WORK_DURATION) to transfer requirement to caller`)"
+ errorLine1=" long timeNs = SystemClock.uptimeNanos();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/ViewRootImpl.java"
+ line="5658"
+ column="31"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getFrameTimeNanos()` is a flagged API and should be inside an `if (Flags.expectedPresentationTimeApi())` check (or annotate the surrounding method `run` with `@FlaggedApi(Flags.FLAG_EXPECTED_PRESENTATION_TIME_API) to transfer requirement to caller`)"
+ errorLine1=" if (doConsumeBatchedInput(mChoreographer.getFrameTimeNanos())) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/ViewRootImpl.java"
+ line="10449"
+ column="43"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `InputTransferToken()` is a flagged API and should be inside an `if (Flags.surfaceControlInputReceiver())` check (or annotate the surrounding method `getInputTransferToken` with `@FlaggedApi(Flags.FLAG_SURFACE_CONTROL_INPUT_RECEIVER) to transfer requirement to caller`)"
+ errorLine1=" return new InputTransferToken(inputToken);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/ViewRootImpl.java"
+ line="11736"
+ column="16"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getFrameRateBoostOnTouchEnabled()` is a flagged API and should be inside an `if (Flags.toolkitSetFrameRateReadOnly())` check (or annotate the surrounding method `getFrameRateBoostOnTouchEnabled` with `@FlaggedApi(Flags.FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY) to transfer requirement to caller`)"
+ errorLine1=" return mWindowAttributes.getFrameRateBoostOnTouchEnabled();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/ViewRootImpl.java"
+ line="13161"
+ column="16"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `isFrameRatePowerSavingsBalanced()` is a flagged API and should be inside an `if (Flags.toolkitSetFrameRateReadOnly())` check (or annotate the surrounding method `isFrameRatePowerSavingsBalanced` with `@FlaggedApi(Flags.FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY) to transfer requirement to caller`)"
+ errorLine1=" return mWindowAttributes.isFrameRatePowerSavingsBalanced();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/ViewRootImpl.java"
+ line="13193"
+ column="20"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `POLICY_TYPE_CAMERA` is a flagged API and should be inside an `if (Flags.virtualCamera())` check (or annotate the surrounding method `hasCustomCameraSupport` with `@FlaggedApi(Flags.FLAG_VIRTUAL_CAMERA) to transfer requirement to caller`)"
+ errorLine1=" return mVirtualDevice.getDevicePolicy(POLICY_TYPE_CAMERA) == DEVICE_POLICY_CUSTOM;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/companion/virtual/VirtualDevice.java"
+ line="200"
+ column="51"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `VirtualStylus()` is a flagged API and should be inside an `if (Flags.virtualStylus())` check (or annotate the surrounding method `createVirtualStylus` with `@FlaggedApi(Flags.FLAG_VIRTUAL_STYLUS) to transfer requirement to caller`)"
+ errorLine1=" return new VirtualStylus(config, mVirtualDevice, token);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/companion/virtual/VirtualDeviceInternal.java"
+ line="332"
+ column="20"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `VirtualCamera()` is a flagged API and should be inside an `if (Flags.virtualCamera())` check (or annotate the surrounding method `createVirtualCamera` with `@FlaggedApi(Flags.FLAG_VIRTUAL_CAMERA) to transfer requirement to caller`)"
+ errorLine1=" return new VirtualCamera(mVirtualDevice, mVirtualDevice.getVirtualCameraId(config),"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/core/java/android/companion/virtual/VirtualDeviceInternal.java"
+ line="381"
+ column="20"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `onVirtualDeviceCreated()` is a flagged API and should be inside an `if (Flags.vdmPublicApis())` check (or annotate the surrounding method `onVirtualDeviceCreated` with `@FlaggedApi(Flags.FLAG_VDM_PUBLIC_APIS) to transfer requirement to caller`)"
+ errorLine1=" mExecutor.execute(() -> mListener.onVirtualDeviceCreated(deviceId));"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/companion/virtual/VirtualDeviceManager.java"
+ line="1225"
+ column="41"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `onVirtualDeviceClosed()` is a flagged API and should be inside an `if (Flags.vdmPublicApis())` check (or annotate the surrounding method `onVirtualDeviceClosed` with `@FlaggedApi(Flags.FLAG_VDM_PUBLIC_APIS) to transfer requirement to caller`)"
+ errorLine1=" mExecutor.execute(() -> mListener.onVirtualDeviceClosed(deviceId));"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/companion/virtual/VirtualDeviceManager.java"
+ line="1235"
+ column="41"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `POLICY_TYPE_CLIPBOARD` is a flagged API and should be inside an `if (Flags.crossDeviceClipboard())` check (or annotate the surrounding method `build` with `@FlaggedApi(Flags.FLAG_CROSS_DEVICE_CLIPBOARD) to transfer requirement to caller`)"
+ errorLine1=" mDevicePolicies.delete(POLICY_TYPE_CLIPBOARD);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/companion/virtual/VirtualDeviceParams.java"
+ line="1170"
+ column="40"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `POLICY_TYPE_CAMERA` is a flagged API and should be inside an `if (Flags.virtualCamera())` check (or annotate the surrounding method `build` with `@FlaggedApi(Flags.FLAG_VIRTUAL_CAMERA) to transfer requirement to caller`)"
+ errorLine1=" mDevicePolicies.delete(POLICY_TYPE_CAMERA);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/companion/virtual/VirtualDeviceParams.java"
+ line="1174"
+ column="40"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `onSecureConnectionProvided()` is a flagged API and should be inside an `if (Flags.enableProvideWearableConnectionApi())` check (or annotate the surrounding method `provideSecureConnection` with `@FlaggedApi(Flags.FLAG_ENABLE_PROVIDE_WEARABLE_CONNECTION_API) to transfer requirement to caller`)"
+ errorLine1=" WearableSensingService.this.onSecureConnectionProvided("
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/core/java/android/service/wearable/WearableSensingService.java"
+ line="142"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `onDataRequestObserverRegistered()` is a flagged API and should be inside an `if (Flags.enableDataRequestObserverApi())` check (or annotate the surrounding method `registerDataRequestObserver` with `@FlaggedApi(Flags.FLAG_ENABLE_DATA_REQUEST_OBSERVER_API) to transfer requirement to caller`)"
+ errorLine1=" WearableSensingService.this.onDataRequestObserverRegistered("
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/core/java/android/service/wearable/WearableSensingService.java"
+ line="193"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `onDataRequestObserverUnregistered()` is a flagged API and should be inside an `if (Flags.enableDataRequestObserverApi())` check (or annotate the surrounding method `unregisterDataRequestObserver` with `@FlaggedApi(Flags.FLAG_ENABLE_DATA_REQUEST_OBSERVER_API) to transfer requirement to caller`)"
+ errorLine1=" WearableSensingService.this.onDataRequestObserverUnregistered("
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/core/java/android/service/wearable/WearableSensingService.java"
+ line="217"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `onStartHotwordRecognition()` is a flagged API and should be inside an `if (Flags.enableHotwordWearableSensingApi())` check (or annotate the surrounding method `startHotwordRecognition` with `@FlaggedApi(Flags.FLAG_ENABLE_HOTWORD_WEARABLE_SENSING_API) to transfer requirement to caller`)"
+ errorLine1=" WearableSensingService.this.onStartHotwordRecognition("
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/core/java/android/service/wearable/WearableSensingService.java"
+ line="237"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `onStopHotwordRecognition()` is a flagged API and should be inside an `if (Flags.enableHotwordWearableSensingApi())` check (or annotate the surrounding method `stopHotwordRecognition` with `@FlaggedApi(Flags.FLAG_ENABLE_HOTWORD_WEARABLE_SENSING_API) to transfer requirement to caller`)"
+ errorLine1=" WearableSensingService.this.onStopHotwordRecognition(statusConsumer);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/service/wearable/WearableSensingService.java"
+ line="250"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `onValidatedByHotwordDetectionService()` is a flagged API and should be inside an `if (Flags.enableHotwordWearableSensingApi())` check (or annotate the surrounding method `onValidatedByHotwordDetectionService` with `@FlaggedApi(Flags.FLAG_ENABLE_HOTWORD_WEARABLE_SENSING_API) to transfer requirement to caller`)"
+ errorLine1=" WearableSensingService.this.onValidatedByHotwordDetectionService();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/service/wearable/WearableSensingService.java"
+ line="256"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `onStopHotwordAudioStream()` is a flagged API and should be inside an `if (Flags.enableHotwordWearableSensingApi())` check (or annotate the surrounding method `stopActiveHotwordAudio` with `@FlaggedApi(Flags.FLAG_ENABLE_HOTWORD_WEARABLE_SENSING_API) to transfer requirement to caller`)"
+ errorLine1=" WearableSensingService.this.onStopHotwordAudioStream();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/service/wearable/WearableSensingService.java"
+ line="262"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `STATUS_UNSUPPORTED_OPERATION` is a flagged API and should be inside an `if (Flags.enableUnsupportedOperationStatusCode())` check (or annotate the surrounding method `onSecureConnectionProvided` with `@FlaggedApi(Flags.FLAG_ENABLE_UNSUPPORTED_OPERATION_STATUS_CODE) to transfer requirement to caller`)"
+ errorLine1=" statusConsumer.accept(WearableSensingManager.STATUS_UNSUPPORTED_OPERATION);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/service/wearable/WearableSensingService.java"
+ line="361"
+ column="54"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `STATUS_UNSUPPORTED_OPERATION` is a flagged API and should be inside an `if (Flags.enableUnsupportedOperationStatusCode())` check (or annotate the surrounding method `onDataRequestObserverRegistered` with `@FlaggedApi(Flags.FLAG_ENABLE_UNSUPPORTED_OPERATION_STATUS_CODE) to transfer requirement to caller`)"
+ errorLine1=" statusConsumer.accept(WearableSensingManager.STATUS_UNSUPPORTED_OPERATION);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/service/wearable/WearableSensingService.java"
+ line="429"
+ column="54"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `STATUS_UNSUPPORTED_OPERATION` is a flagged API and should be inside an `if (Flags.enableUnsupportedOperationStatusCode())` check (or annotate the surrounding method `onDataRequestObserverUnregistered` with `@FlaggedApi(Flags.FLAG_ENABLE_UNSUPPORTED_OPERATION_STATUS_CODE) to transfer requirement to caller`)"
+ errorLine1=" statusConsumer.accept(WearableSensingManager.STATUS_UNSUPPORTED_OPERATION);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/service/wearable/WearableSensingService.java"
+ line="457"
+ column="54"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `REQUEST_BUNDLE_KEY` is a flagged API and should be inside an `if (Flags.enableDataRequestObserverApi())` check (or annotate the surrounding method `createDataRequester` with `@FlaggedApi(Flags.FLAG_ENABLE_DATA_REQUEST_OBSERVER_API) to transfer requirement to caller`)"
+ errorLine1=" bundle.putParcelable(WearableSensingDataRequest.REQUEST_BUNDLE_KEY, request);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/service/wearable/WearableSensingService.java"
+ line="673"
+ column="61"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `REQUEST_STATUS_CALLBACK_BUNDLE_KEY` is a flagged API and should be inside an `if (Flags.enableDataRequestObserverApi())` check (or annotate the surrounding method `createDataRequester` with `@FlaggedApi(Flags.FLAG_ENABLE_DATA_REQUEST_OBSERVER_API) to transfer requirement to caller`)"
+ errorLine1=" WearableSensingDataRequest.REQUEST_STATUS_CALLBACK_BUNDLE_KEY,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/service/wearable/WearableSensingService.java"
+ line="682"
+ column="48"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `status` is a flagged API and should be inside an `if (Flags.updateServiceIpcWrapper())` check (or annotate the surrounding method `loadWebViewNativeLibraryFromPackage` with `@FlaggedApi(Flags.FLAG_UPDATE_SERVICE_IPC_WRAPPER) to transfer requirement to caller`)"
+ errorLine1=" if (response.status != LIBLOAD_SUCCESS"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/webkit/WebViewFactory.java"
+ line="308"
+ column="22"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `status` is a flagged API and should be inside an `if (Flags.updateServiceIpcWrapper())` check (or annotate the surrounding method `loadWebViewNativeLibraryFromPackage` with `@FlaggedApi(Flags.FLAG_UPDATE_SERVICE_IPC_WRAPPER) to transfer requirement to caller`)"
+ errorLine1=" && response.status != LIBLOAD_FAILED_WAITING_FOR_RELRO) {"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/webkit/WebViewFactory.java"
+ line="309"
+ column="29"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `status` is a flagged API and should be inside an `if (Flags.updateServiceIpcWrapper())` check (or annotate the surrounding method `loadWebViewNativeLibraryFromPackage` with `@FlaggedApi(Flags.FLAG_UPDATE_SERVICE_IPC_WRAPPER) to transfer requirement to caller`)"
+ errorLine1=" return response.status;"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/webkit/WebViewFactory.java"
+ line="310"
+ column="29"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `packageInfo` is a flagged API and should be inside an `if (Flags.updateServiceIpcWrapper())` check (or annotate the surrounding method `loadWebViewNativeLibraryFromPackage` with `@FlaggedApi(Flags.FLAG_UPDATE_SERVICE_IPC_WRAPPER) to transfer requirement to caller`)"
+ errorLine1=" if (!response.packageInfo.packageName.equals(packageName)) {"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/webkit/WebViewFactory.java"
+ line="312"
+ column="23"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `status` is a flagged API and should be inside an `if (Flags.updateServiceIpcWrapper())` check (or annotate the surrounding method `loadWebViewNativeLibraryFromPackage` with `@FlaggedApi(Flags.FLAG_UPDATE_SERVICE_IPC_WRAPPER) to transfer requirement to caller`)"
+ errorLine1=" if (loadNativeRet == LIBLOAD_SUCCESS) return response.status;"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/webkit/WebViewFactory.java"
+ line="330"
+ column="63"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `status` is a flagged API and should be inside an `if (Flags.updateServiceIpcWrapper())` check (or annotate the surrounding method `getWebViewContextAndSetProvider` with `@FlaggedApi(Flags.FLAG_UPDATE_SERVICE_IPC_WRAPPER) to transfer requirement to caller`)"
+ errorLine1=" if (response.status != LIBLOAD_SUCCESS"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/webkit/WebViewFactory.java"
+ line="459"
+ column="26"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `status` is a flagged API and should be inside an `if (Flags.updateServiceIpcWrapper())` check (or annotate the surrounding method `getWebViewContextAndSetProvider` with `@FlaggedApi(Flags.FLAG_UPDATE_SERVICE_IPC_WRAPPER) to transfer requirement to caller`)"
+ errorLine1=" && response.status != LIBLOAD_FAILED_WAITING_FOR_RELRO) {"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/webkit/WebViewFactory.java"
+ line="460"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `status` is a flagged API and should be inside an `if (Flags.updateServiceIpcWrapper())` check (or annotate the surrounding method `getWebViewContextAndSetProvider` with `@FlaggedApi(Flags.FLAG_UPDATE_SERVICE_IPC_WRAPPER) to transfer requirement to caller`)"
+ errorLine1=" + getWebViewPreparationErrorReason(response.status));"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/webkit/WebViewFactory.java"
+ line="462"
+ column="69"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `packageInfo` is a flagged API and should be inside an `if (Flags.updateServiceIpcWrapper())` check (or annotate the surrounding method `getWebViewContextAndSetProvider` with `@FlaggedApi(Flags.FLAG_UPDATE_SERVICE_IPC_WRAPPER) to transfer requirement to caller`)"
+ errorLine1=" response.packageInfo.packageName);"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/webkit/WebViewFactory.java"
+ line="469"
+ column="34"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `packageInfo` is a flagged API and should be inside an `if (Flags.updateServiceIpcWrapper())` check (or annotate the surrounding method `getWebViewContextAndSetProvider` with `@FlaggedApi(Flags.FLAG_UPDATE_SERVICE_IPC_WRAPPER) to transfer requirement to caller`)"
+ errorLine1=" response.packageInfo.packageName,"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/webkit/WebViewFactory.java"
+ line="479"
+ column="30"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `packageInfo` is a flagged API and should be inside an `if (Flags.updateServiceIpcWrapper())` check (or annotate the surrounding method `getWebViewContextAndSetProvider` with `@FlaggedApi(Flags.FLAG_UPDATE_SERVICE_IPC_WRAPPER) to transfer requirement to caller`)"
+ errorLine1=" verifyPackageInfo(response.packageInfo, newPackageInfo);"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/webkit/WebViewFactory.java"
+ line="510"
+ column="40"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `InputTransferToken()` is a flagged API and should be inside an `if (Flags.surfaceControlInputReceiver())` check (or annotate the surrounding method `registerBatchedSurfaceControlInputReceiver` with `@FlaggedApi(Flags.FLAG_SURFACE_CONTROL_INPUT_RECEIVER) to transfer requirement to caller`)"
+ errorLine1=" InputTransferToken inputTransferToken = new InputTransferToken();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/WindowManagerGlobal.java"
+ line="874"
+ column="49"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `onInputEvent()` is a flagged API and should be inside an `if (Flags.surfaceControlInputReceiver())` check (or annotate the surrounding method `onInputEvent` with `@FlaggedApi(Flags.FLAG_SURFACE_CONTROL_INPUT_RECEIVER) to transfer requirement to caller`)"
+ errorLine1=" boolean handled = receiver.onInputEvent(event);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/WindowManagerGlobal.java"
+ line="885"
+ column="55"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `InputTransferToken()` is a flagged API and should be inside an `if (Flags.surfaceControlInputReceiver())` check (or annotate the surrounding method `registerUnbatchedSurfaceControlInputReceiver` with `@FlaggedApi(Flags.FLAG_SURFACE_CONTROL_INPUT_RECEIVER) to transfer requirement to caller`)"
+ errorLine1=" InputTransferToken inputTransferToken = new InputTransferToken();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/WindowManagerGlobal.java"
+ line="897"
+ column="49"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `onInputEvent()` is a flagged API and should be inside an `if (Flags.surfaceControlInputReceiver())` check (or annotate the surrounding method `onInputEvent` with `@FlaggedApi(Flags.FLAG_SURFACE_CONTROL_INPUT_RECEIVER) to transfer requirement to caller`)"
+ errorLine1=" boolean handled = receiver.onInputEvent(event);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/WindowManagerGlobal.java"
+ line="907"
+ column="55"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `SCREEN_RECORDING_STATE_NOT_VISIBLE` is a flagged API and should be inside an `if (Flags.screenRecordingCallbacks())` check (or annotate the surrounding method `addScreenRecordingCallback` with `@FlaggedApi(Flags.FLAG_SCREEN_RECORDING_CALLBACKS) to transfer requirement to caller`)"
+ errorLine1=" return SCREEN_RECORDING_STATE_NOT_VISIBLE;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/WindowManagerImpl.java"
+ line="594"
+ column="16"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `InputTransferToken()` is a flagged API and should be inside an `if (Flags.surfaceControlInputReceiver())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_SURFACE_CONTROL_INPUT_RECEIVER) to transfer requirement to caller`)"
+ errorLine1=" private final InputTransferToken mInputTransferToken = new InputTransferToken();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/WindowlessWindowManager.java"
+ line="94"
+ column="60"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `InputTransferToken()` is a flagged API and should be inside an `if (Flags.surfaceControlInputReceiver())` check (or annotate the surrounding method `addToDisplay` with `@FlaggedApi(Flags.FLAG_SURFACE_CONTROL_INPUT_RECEIVER) to transfer requirement to caller`)"
+ errorLine1=" state.mInputTransferToken = new InputTransferToken();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/view/WindowlessWindowManager.java"
+ line="214"
+ column="45"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `compressToJpegR()` is a flagged API and should be inside an `if (Flags.yuvImageCompressToUltraHdr())` check (or annotate the surrounding method `compressToJpegR` with `@FlaggedApi(Flags.FLAG_YUV_IMAGE_COMPRESS_TO_ULTRA_HDR) to transfer requirement to caller`)"
+ errorLine1=" return compressToJpegR(sdr, quality, stream, emptyExif);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/graphics/java/android/graphics/YuvImage.java"
+ line="276"
+ column="16"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `allowPriorityChannels()` is a flagged API and should be inside an `if (Flags.modesApi())` check (or annotate the surrounding method `getDefaultZenPolicy` with `@FlaggedApi(Flags.FLAG_MODES_API) to transfer requirement to caller`)"
+ errorLine1=" ZenPolicy policy = new ZenPolicy.Builder()"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/core/java/android/service/notification/ZenModeConfig.java"
+ line="379"
+ column="28"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `TYPE_OTHER` is a flagged API and should be inside an `if (Flags.modesApi())` check (or annotate the surrounding method `ensureManualZenRule` with `@FlaggedApi(Flags.FLAG_MODES_API) to transfer requirement to caller`)"
+ errorLine1=" newRule.type = AutomaticZenRule.TYPE_OTHER;"
+ errorLine2=" ~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/service/notification/ZenModeConfig.java"
+ line="435"
+ column="45"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `zenDeviceEffects` is a flagged API and should be inside an `if (Flags.modesApi())` check (or annotate the surrounding method `writeRuleXml` with `@FlaggedApi(Flags.FLAG_MODES_API) to transfer requirement to caller`)"
+ errorLine1=" if (Flags.modesApi() && rule.zenDeviceEffects != null) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/service/notification/ZenModeConfig.java"
+ line="1206"
+ column="38"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `policyState()` is a flagged API and should be inside an `if (Flags.modesApi())` check (or annotate the surrounding method `toNotificationPolicy` with `@FlaggedApi(Flags.FLAG_MODES_API) to transfer requirement to caller`)"
+ errorLine1=" state = Policy.policyState(areChannelsBypassingDnd,"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/core/java/android/service/notification/ZenModeConfig.java"
+ line="1842"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getPriorityChannelsAllowed()` is a flagged API and should be inside an `if (Flags.modesApi())` check (or annotate the surrounding method `toNotificationPolicy` with `@FlaggedApi(Flags.FLAG_MODES_API) to transfer requirement to caller`)"
+ errorLine1=" manualRule.zenPolicy.getPriorityChannelsAllowed() != STATE_DISALLOW);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/service/notification/ZenModeConfig.java"
+ line="1843"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `TYPE_UNKNOWN` is a flagged API and should be inside an `if (Flags.modesApi())` check (or annotate the surrounding method `?` with `@FlaggedApi(Flags.FLAG_MODES_API) to transfer requirement to caller`)"
+ errorLine1=" public int type = AutomaticZenRule.TYPE_UNKNOWN;"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/service/notification/ZenModeConfig.java"
+ line="2482"
+ column="44"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getPriorityChannelsAllowed()` is a flagged API and should be inside an `if (Flags.modesApi())` check (or annotate the surrounding method `areAllPriorityOnlyRingerSoundsMuted` with `@FlaggedApi(Flags.FLAG_MODES_API) to transfer requirement to caller`)"
+ errorLine1=" && !(config.areChannelsBypassingDnd && policy.getPriorityChannelsAllowed()"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/service/notification/ZenModeConfig.java"
+ line="2835"
+ column="60"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `mAllowChannels` is a flagged API and should be inside an `if (Flags.modesApi())` check (or annotate the surrounding method `getAllowedChannels` with `@FlaggedApi(Flags.FLAG_MODES_API) to transfer requirement to caller`)"
+ errorLine1=" return mAllowChannels;"
+ errorLine2=" ~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/service/notification/ZenPolicy.java"
+ line="576"
+ column="16"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `mAllowChannels` is a flagged API and should be inside an `if (Flags.modesApi())` check (or annotate the surrounding method `allowChannels` with `@FlaggedApi(Flags.FLAG_MODES_API) to transfer requirement to caller`)"
+ errorLine1=" mZenPolicy.mAllowChannels = channelType;"
+ errorLine2=" ~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/service/notification/ZenPolicy.java"
+ line="1019"
+ column="24"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `FIELD_MESSAGES` is a flagged API and should be inside an `if (Flags.modesApi())` check (or annotate the surrounding method `fieldsToString` with `@FlaggedApi(Flags.FLAG_MODES_API) to transfer requirement to caller`)"
+ errorLine1=" if ((bitmask & FIELD_MESSAGES) != 0) {"
+ errorLine2=" ~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/service/notification/ZenPolicy.java"
+ line="1095"
+ column="24"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `FIELD_CALLS` is a flagged API and should be inside an `if (Flags.modesApi())` check (or annotate the surrounding method `fieldsToString` with `@FlaggedApi(Flags.FLAG_MODES_API) to transfer requirement to caller`)"
+ errorLine1=" if ((bitmask & FIELD_CALLS) != 0) {"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/service/notification/ZenPolicy.java"
+ line="1098"
+ column="24"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `FIELD_CONVERSATIONS` is a flagged API and should be inside an `if (Flags.modesApi())` check (or annotate the surrounding method `fieldsToString` with `@FlaggedApi(Flags.FLAG_MODES_API) to transfer requirement to caller`)"
+ errorLine1=" if ((bitmask & FIELD_CONVERSATIONS) != 0) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/service/notification/ZenPolicy.java"
+ line="1101"
+ column="24"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `FIELD_ALLOW_CHANNELS` is a flagged API and should be inside an `if (Flags.modesApi())` check (or annotate the surrounding method `fieldsToString` with `@FlaggedApi(Flags.FLAG_MODES_API) to transfer requirement to caller`)"
+ errorLine1=" if ((bitmask & FIELD_ALLOW_CHANNELS) != 0) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/service/notification/ZenPolicy.java"
+ line="1104"
+ column="24"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `FIELD_PRIORITY_CATEGORY_REMINDERS` is a flagged API and should be inside an `if (Flags.modesApi())` check (or annotate the surrounding method `fieldsToString` with `@FlaggedApi(Flags.FLAG_MODES_API) to transfer requirement to caller`)"
+ errorLine1=" if ((bitmask & FIELD_PRIORITY_CATEGORY_REMINDERS) != 0) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/service/notification/ZenPolicy.java"
+ line="1107"
+ column="24"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `FIELD_PRIORITY_CATEGORY_EVENTS` is a flagged API and should be inside an `if (Flags.modesApi())` check (or annotate the surrounding method `fieldsToString` with `@FlaggedApi(Flags.FLAG_MODES_API) to transfer requirement to caller`)"
+ errorLine1=" if ((bitmask & FIELD_PRIORITY_CATEGORY_EVENTS) != 0) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/service/notification/ZenPolicy.java"
+ line="1110"
+ column="24"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `FIELD_PRIORITY_CATEGORY_REPEAT_CALLERS` is a flagged API and should be inside an `if (Flags.modesApi())` check (or annotate the surrounding method `fieldsToString` with `@FlaggedApi(Flags.FLAG_MODES_API) to transfer requirement to caller`)"
+ errorLine1=" if ((bitmask & FIELD_PRIORITY_CATEGORY_REPEAT_CALLERS) != 0) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/service/notification/ZenPolicy.java"
+ line="1113"
+ column="24"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `FIELD_PRIORITY_CATEGORY_ALARMS` is a flagged API and should be inside an `if (Flags.modesApi())` check (or annotate the surrounding method `fieldsToString` with `@FlaggedApi(Flags.FLAG_MODES_API) to transfer requirement to caller`)"
+ errorLine1=" if ((bitmask & FIELD_PRIORITY_CATEGORY_ALARMS) != 0) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/service/notification/ZenPolicy.java"
+ line="1116"
+ column="24"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `FIELD_PRIORITY_CATEGORY_MEDIA` is a flagged API and should be inside an `if (Flags.modesApi())` check (or annotate the surrounding method `fieldsToString` with `@FlaggedApi(Flags.FLAG_MODES_API) to transfer requirement to caller`)"
+ errorLine1=" if ((bitmask & FIELD_PRIORITY_CATEGORY_MEDIA) != 0) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/service/notification/ZenPolicy.java"
+ line="1119"
+ column="24"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `FIELD_PRIORITY_CATEGORY_SYSTEM` is a flagged API and should be inside an `if (Flags.modesApi())` check (or annotate the surrounding method `fieldsToString` with `@FlaggedApi(Flags.FLAG_MODES_API) to transfer requirement to caller`)"
+ errorLine1=" if ((bitmask & FIELD_PRIORITY_CATEGORY_SYSTEM) != 0) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/service/notification/ZenPolicy.java"
+ line="1122"
+ column="24"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `FIELD_VISUAL_EFFECT_FULL_SCREEN_INTENT` is a flagged API and should be inside an `if (Flags.modesApi())` check (or annotate the surrounding method `fieldsToString` with `@FlaggedApi(Flags.FLAG_MODES_API) to transfer requirement to caller`)"
+ errorLine1=" if ((bitmask & FIELD_VISUAL_EFFECT_FULL_SCREEN_INTENT) != 0) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/service/notification/ZenPolicy.java"
+ line="1125"
+ column="24"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `FIELD_VISUAL_EFFECT_LIGHTS` is a flagged API and should be inside an `if (Flags.modesApi())` check (or annotate the surrounding method `fieldsToString` with `@FlaggedApi(Flags.FLAG_MODES_API) to transfer requirement to caller`)"
+ errorLine1=" if ((bitmask & FIELD_VISUAL_EFFECT_LIGHTS) != 0) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/service/notification/ZenPolicy.java"
+ line="1128"
+ column="24"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `FIELD_VISUAL_EFFECT_PEEK` is a flagged API and should be inside an `if (Flags.modesApi())` check (or annotate the surrounding method `fieldsToString` with `@FlaggedApi(Flags.FLAG_MODES_API) to transfer requirement to caller`)"
+ errorLine1=" if ((bitmask & FIELD_VISUAL_EFFECT_PEEK) != 0) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/service/notification/ZenPolicy.java"
+ line="1131"
+ column="24"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `FIELD_VISUAL_EFFECT_STATUS_BAR` is a flagged API and should be inside an `if (Flags.modesApi())` check (or annotate the surrounding method `fieldsToString` with `@FlaggedApi(Flags.FLAG_MODES_API) to transfer requirement to caller`)"
+ errorLine1=" if ((bitmask & FIELD_VISUAL_EFFECT_STATUS_BAR) != 0) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/service/notification/ZenPolicy.java"
+ line="1134"
+ column="24"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `FIELD_VISUAL_EFFECT_BADGE` is a flagged API and should be inside an `if (Flags.modesApi())` check (or annotate the surrounding method `fieldsToString` with `@FlaggedApi(Flags.FLAG_MODES_API) to transfer requirement to caller`)"
+ errorLine1=" if ((bitmask & FIELD_VISUAL_EFFECT_BADGE) != 0) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/service/notification/ZenPolicy.java"
+ line="1137"
+ column="24"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `FIELD_VISUAL_EFFECT_AMBIENT` is a flagged API and should be inside an `if (Flags.modesApi())` check (or annotate the surrounding method `fieldsToString` with `@FlaggedApi(Flags.FLAG_MODES_API) to transfer requirement to caller`)"
+ errorLine1=" if ((bitmask & FIELD_VISUAL_EFFECT_AMBIENT) != 0) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/service/notification/ZenPolicy.java"
+ line="1140"
+ column="24"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `FIELD_VISUAL_EFFECT_NOTIFICATION_LIST` is a flagged API and should be inside an `if (Flags.modesApi())` check (or annotate the surrounding method `fieldsToString` with `@FlaggedApi(Flags.FLAG_MODES_API) to transfer requirement to caller`)"
+ errorLine1=" if ((bitmask & FIELD_VISUAL_EFFECT_NOTIFICATION_LIST) != 0) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/core/java/android/service/notification/ZenPolicy.java"
+ line="1143"
+ column="24"/>
+ </issue>
+
</issues>
\ No newline at end of file
diff --git a/location/Android.bp b/location/Android.bp
index 5ba35ac..e864689 100644
--- a/location/Android.bp
+++ b/location/Android.bp
@@ -39,6 +39,9 @@
"frameworks/base/core/java",
],
},
+ lint: {
+ baseline_filename: "lint-baseline.xml",
+ },
}
platform_compat_config {
diff --git a/location/lint-baseline.xml b/location/lint-baseline.xml
new file mode 100644
index 0000000..a5a2e25
--- /dev/null
+++ b/location/lint-baseline.xml
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<issues format="6" by="lint 8.4.0-alpha08" type="baseline" client="" dependencies="true" name="" variant="all" version="8.4.0-alpha08">
+
+ <issue
+ id="FlaggedApi"
+ message="Method `Builder()` is a flagged API and should be inside an `if (Flags.newGeocoder())` check (or annotate the surrounding method `getFromLocation` with `@FlaggedApi(Flags.FLAG_NEW_GEOCODER) to transfer requirement to caller`)"
+ errorLine1=" new ReverseGeocodeRequest.Builder("
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/location/java/android/location/Geocoder.java"
+ line="170"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `setCallingAttributionTag()` is a flagged API and should be inside an `if (Flags.newGeocoder())` check (or annotate the surrounding method `getFromLocation` with `@FlaggedApi(Flags.FLAG_NEW_GEOCODER) to transfer requirement to caller`)"
+ errorLine1=" b.setCallingAttributionTag(mContext.getAttributionTag());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/location/java/android/location/Geocoder.java"
+ line="178"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `build()` is a flagged API and should be inside an `if (Flags.newGeocoder())` check (or annotate the surrounding method `getFromLocation` with `@FlaggedApi(Flags.FLAG_NEW_GEOCODER) to transfer requirement to caller`)"
+ errorLine1=" mService.reverseGeocode(b.build(), new GeocodeCallbackImpl(listener));"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/location/java/android/location/Geocoder.java"
+ line="181"
+ column="37"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `Builder()` is a flagged API and should be inside an `if (Flags.newGeocoder())` check (or annotate the surrounding method `getFromLocationName` with `@FlaggedApi(Flags.FLAG_NEW_GEOCODER) to transfer requirement to caller`)"
+ errorLine1=" new ForwardGeocodeRequest.Builder("
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/location/java/android/location/Geocoder.java"
+ line="322"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `setCallingAttributionTag()` is a flagged API and should be inside an `if (Flags.newGeocoder())` check (or annotate the surrounding method `getFromLocationName` with `@FlaggedApi(Flags.FLAG_NEW_GEOCODER) to transfer requirement to caller`)"
+ errorLine1=" b.setCallingAttributionTag(mContext.getAttributionTag());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/location/java/android/location/Geocoder.java"
+ line="333"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `build()` is a flagged API and should be inside an `if (Flags.newGeocoder())` check (or annotate the surrounding method `getFromLocationName` with `@FlaggedApi(Flags.FLAG_NEW_GEOCODER) to transfer requirement to caller`)"
+ errorLine1=" mService.forwardGeocode(b.build(), new GeocodeCallbackImpl(listener));"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/location/java/android/location/Geocoder.java"
+ line="336"
+ column="37"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getWorkSource()` is a flagged API and should be inside an `if (Flags.gnssApiMeasurementRequestWorkSource())` check (or annotate the surrounding method `Builder` with `@FlaggedApi(Flags.FLAG_GNSS_API_MEASUREMENT_REQUEST_WORK_SOURCE) to transfer requirement to caller`)"
+ errorLine1=" mWorkSource = request.getWorkSource();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/location/java/android/location/GnssMeasurementRequest.java"
+ line="234"
+ column="27"/>
+ </issue>
+
+</issues>
diff --git a/nfc/lint-baseline.xml b/nfc/lint-baseline.xml
index 1dfdd29..dd7b03d 100644
--- a/nfc/lint-baseline.xml
+++ b/nfc/lint-baseline.xml
@@ -210,4 +210,81 @@
column="23"/>
</issue>
+ <issue
+ id="FlaggedApi"
+ message="Method `NfcOemExtension()` is a flagged API and should be inside an `if (Flags.nfcOemExtension())` check (or annotate the surrounding method `NfcAdapter` with `@FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION) to transfer requirement to caller`)"
+ errorLine1=" mNfcOemExtension = new NfcOemExtension(mContext, this);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/nfc/java/android/nfc/NfcAdapter.java"
+ line="909"
+ column="28"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `FLAG_SET_DEFAULT_TECH` is a flagged API and should be inside an `if (Flags.nfcSetDefaultDiscTech())` check (or annotate the surrounding method `setDiscoveryTechnology` with `@FlaggedApi(Flags.FLAG_NFC_SET_DEFAULT_DISC_TECH) to transfer requirement to caller`)"
+ errorLine1=" && ((pollTechnology & FLAG_SET_DEFAULT_TECH) == FLAG_SET_DEFAULT_TECH"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/nfc/java/android/nfc/NfcAdapter.java"
+ line="1917"
+ column="39"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `FLAG_SET_DEFAULT_TECH` is a flagged API and should be inside an `if (Flags.nfcSetDefaultDiscTech())` check (or annotate the surrounding method `setDiscoveryTechnology` with `@FlaggedApi(Flags.FLAG_NFC_SET_DEFAULT_DISC_TECH) to transfer requirement to caller`)"
+ errorLine1=" && ((pollTechnology & FLAG_SET_DEFAULT_TECH) == FLAG_SET_DEFAULT_TECH"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/nfc/java/android/nfc/NfcAdapter.java"
+ line="1917"
+ column="65"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `FLAG_SET_DEFAULT_TECH` is a flagged API and should be inside an `if (Flags.nfcSetDefaultDiscTech())` check (or annotate the surrounding method `setDiscoveryTechnology` with `@FlaggedApi(Flags.FLAG_NFC_SET_DEFAULT_DISC_TECH) to transfer requirement to caller`)"
+ errorLine1=" || (listenTechnology & FLAG_SET_DEFAULT_TECH) == FLAG_SET_DEFAULT_TECH)) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/nfc/java/android/nfc/NfcAdapter.java"
+ line="1918"
+ column="40"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Field `FLAG_SET_DEFAULT_TECH` is a flagged API and should be inside an `if (Flags.nfcSetDefaultDiscTech())` check (or annotate the surrounding method `setDiscoveryTechnology` with `@FlaggedApi(Flags.FLAG_NFC_SET_DEFAULT_DISC_TECH) to transfer requirement to caller`)"
+ errorLine1=" || (listenTechnology & FLAG_SET_DEFAULT_TECH) == FLAG_SET_DEFAULT_TECH)) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/nfc/java/android/nfc/NfcAdapter.java"
+ line="1918"
+ column="66"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `onVendorNciResponse()` is a flagged API and should be inside an `if (Flags.nfcVendorCmd())` check (or annotate the surrounding method `onVendorResponseReceived` with `@FlaggedApi(Flags.FLAG_NFC_VENDOR_CMD) to transfer requirement to caller`)"
+ errorLine1=" executor.execute(() -> callback.onVendorNciResponse(gid, oid, payload));"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/nfc/java/android/nfc/NfcVendorNciCallbackListener.java"
+ line="88"
+ column="44"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `onVendorNciNotification()` is a flagged API and should be inside an `if (Flags.nfcVendorCmd())` check (or annotate the surrounding method `onVendorNotificationReceived` with `@FlaggedApi(Flags.FLAG_NFC_VENDOR_CMD) to transfer requirement to caller`)"
+ errorLine1=" executor.execute(() -> callback.onVendorNciNotification(gid, oid, payload));"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/nfc/java/android/nfc/NfcVendorNciCallbackListener.java"
+ line="106"
+ column="44"/>
+ </issue>
+
</issues>
\ No newline at end of file
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionAssociationActivity.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionAssociationActivity.java
index f98908c..5770c51 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionAssociationActivity.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionAssociationActivity.java
@@ -27,6 +27,8 @@
import static com.android.companiondevicemanager.CompanionDeviceDiscoveryService.DiscoveryState;
import static com.android.companiondevicemanager.CompanionDeviceDiscoveryService.DiscoveryState.FINISHED_TIMEOUT;
+import static com.android.companiondevicemanager.CompanionDeviceDiscoveryService.LOCK;
+import static com.android.companiondevicemanager.CompanionDeviceDiscoveryService.sDiscoveryStarted;
import static com.android.companiondevicemanager.CompanionDeviceResources.PROFILE_ICONS;
import static com.android.companiondevicemanager.CompanionDeviceResources.PROFILE_NAMES;
import static com.android.companiondevicemanager.CompanionDeviceResources.PROFILE_PERMISSIONS;
@@ -326,8 +328,12 @@
private void onDiscoveryStateChanged(DiscoveryState newState) {
if (newState == FINISHED_TIMEOUT
&& CompanionDeviceDiscoveryService.getScanResult().getValue().isEmpty()) {
- cancel(/* discoveryTimeOut */ true,
- /* userRejected */ false, /* internalError */ false);
+ synchronized (LOCK) {
+ if (sDiscoveryStarted) {
+ cancel(/* discoveryTimeOut */ true,
+ /* userRejected */ false, /* internalError */ false);
+ }
+ }
}
}
@@ -568,6 +574,8 @@
updateSingleDeviceUi();
+ if (mRequest.isSkipPrompt()) return;
+
mSummary.setVisibility(View.VISIBLE);
mButtonAllow.setVisibility(View.VISIBLE);
mButtonNotAllow.setVisibility(View.VISIBLE);
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceDiscoveryService.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceDiscoveryService.java
index e809433..6c1bc4e 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceDiscoveryService.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceDiscoveryService.java
@@ -90,9 +90,6 @@
new MutableLiveData<>(Collections.emptyList());
private static MutableLiveData<DiscoveryState> sStateLiveData =
new MutableLiveData<>(DiscoveryState.NOT_STARTED);
- private static final Object LOCK = new Object();
- @GuardedBy("LOCK")
- private static boolean sDiscoveryStarted = false;
private BluetoothManager mBtManager;
private BluetoothAdapter mBtAdapter;
@@ -109,6 +106,10 @@
private boolean mStopAfterFirstMatch;
+ static final Object LOCK = new Object();
+ @GuardedBy("LOCK")
+ static boolean sDiscoveryStarted = false;
+
/**
* A state enum for devices' discovery.
*/
@@ -127,6 +128,7 @@
return false;
}
}
+ sScanResultsLiveData.setValue(Collections.emptyList());
requireNonNull(associationRequest);
final Intent intent = new Intent(context, CompanionDeviceDiscoveryService.class);
intent.setAction(ACTION_START_DISCOVERY);
@@ -192,7 +194,6 @@
sDiscoveryStarted = true;
}
mStopAfterFirstMatch = request.isSingleDevice();
- sScanResultsLiveData.setValue(Collections.emptyList());
sStateLiveData.setValue(DiscoveryState.IN_PROGRESS);
final List<DeviceFilter<?>> allFilters = request.getDeviceFilters();
diff --git a/packages/SettingsLib/Spa/testutils/src/com/android/settingslib/spa/testutils/ComposeContentTestRuleExt.kt b/packages/SettingsLib/Spa/testutils/src/com/android/settingslib/spa/testutils/ComposeContentTestRuleExt.kt
index 0436fc2..53d4531 100644
--- a/packages/SettingsLib/Spa/testutils/src/com/android/settingslib/spa/testutils/ComposeContentTestRuleExt.kt
+++ b/packages/SettingsLib/Spa/testutils/src/com/android/settingslib/spa/testutils/ComposeContentTestRuleExt.kt
@@ -17,6 +17,7 @@
package com.android.settingslib.spa.testutils
import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.safeDrawingPadding
import androidx.compose.foundation.layout.sizeIn
import androidx.compose.material3.Surface
import androidx.compose.runtime.Composable
@@ -75,7 +76,7 @@
setContent {
SettingsTheme {
Surface {
- Box {
+ Box(Modifier.safeDrawingPadding()) {
Box(
Modifier
.sizeIn(maxWidth = parentMaxWidth, maxHeight = parentMaxHeight)
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalBoolean.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalBoolean.kt
index 5d67f57..42528695 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalBoolean.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalBoolean.kt
@@ -21,16 +21,25 @@
import android.provider.Settings
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
+import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.conflate
import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
-fun Context.settingsGlobalBoolean(name: String, defaultValue: Boolean = false):
- ReadWriteProperty<Any?, Boolean> = SettingsGlobalBooleanDelegate(this, name, defaultValue)
+fun Context.settingsGlobalBoolean(
+ name: String,
+ defaultValue: Boolean = false,
+): ReadWriteProperty<Any?, Boolean> = SettingsGlobalBooleanDelegate(this, name, defaultValue)
fun Context.settingsGlobalBooleanFlow(name: String, defaultValue: Boolean = false): Flow<Boolean> {
val value by settingsGlobalBoolean(name, defaultValue)
- return settingsGlobalChangeFlow(name).map { value }.distinctUntilChanged()
+ return settingsGlobalChangeFlow(name)
+ .map { value }
+ .distinctUntilChanged()
+ .conflate()
+ .flowOn(Dispatchers.Default)
}
private class SettingsGlobalBooleanDelegate(
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsSecureBoolean.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsSecureBoolean.kt
index 25090a4..d5f4ec2 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsSecureBoolean.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsSecureBoolean.kt
@@ -22,16 +22,25 @@
import com.android.settingslib.spaprivileged.database.contentChangeFlow
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
+import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.conflate
import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
-fun Context.settingsSecureBoolean(name: String, defaultValue: Boolean = false):
- ReadWriteProperty<Any?, Boolean> = SettingsSecureBooleanDelegate(this, name, defaultValue)
+fun Context.settingsSecureBoolean(
+ name: String,
+ defaultValue: Boolean = false,
+): ReadWriteProperty<Any?, Boolean> = SettingsSecureBooleanDelegate(this, name, defaultValue)
fun Context.settingsSecureBooleanFlow(name: String, defaultValue: Boolean = false): Flow<Boolean> {
val value by settingsSecureBoolean(name, defaultValue)
- return contentChangeFlow(Settings.Secure.getUriFor(name)).map { value }.distinctUntilChanged()
+ return contentChangeFlow(Settings.Secure.getUriFor(name))
+ .map { value }
+ .distinctUntilChanged()
+ .conflate()
+ .flowOn(Dispatchers.Default)
}
private class SettingsSecureBooleanDelegate(
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsSecureString.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsSecureString.kt
new file mode 100644
index 0000000..a706308
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsSecureString.kt
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+package com.android.settingslib.spaprivileged.settingsprovider
+
+import android.content.ContentResolver
+import android.content.Context
+import android.provider.Settings
+import com.android.settingslib.spaprivileged.database.contentChangeFlow
+import kotlin.properties.ReadWriteProperty
+import kotlin.reflect.KProperty
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.conflate
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.flowOn
+import kotlinx.coroutines.flow.map
+
+fun Context.settingsSecureString(
+ name: String,
+ defaultValue: String = ""
+): ReadWriteProperty<Any?, String> = SettingsSecureStringDelegate(this, name, defaultValue)
+
+fun Context.settingsSecureStringFlow(name: String, defaultValue: String = ""): Flow<String> {
+ val value by settingsSecureString(name, defaultValue)
+ return contentChangeFlow(Settings.Secure.getUriFor(name))
+ .map { value }
+ .distinctUntilChanged()
+ .conflate()
+ .flowOn(Dispatchers.Default)
+}
+
+private class SettingsSecureStringDelegate(
+ context: Context,
+ private val name: String,
+ private val defaultValue: String = "",
+) : ReadWriteProperty<Any?, String> {
+
+ private val contentResolver: ContentResolver = context.contentResolver
+
+ override fun getValue(thisRef: Any?, property: KProperty<*>): String =
+ Settings.Secure.getString(contentResolver, name) ?: defaultValue
+
+ override fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
+ Settings.Secure.putString(contentResolver, name, value)
+ }
+}
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppList.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppList.kt
index 2a04424..627b248 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppList.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppList.kt
@@ -19,6 +19,7 @@
import android.content.Context
import android.content.pm.ApplicationInfo
import android.os.Process
+import android.os.UserHandle
import androidx.compose.runtime.Composable
import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
import com.android.settingslib.spa.framework.common.SettingsPageProvider
@@ -88,7 +89,8 @@
*
* If true, the app gets all permissions, so the permission toggle always not changeable.
*/
-fun AppRecord.isSystemOrRootUid(): Boolean = app.uid in listOf(Process.SYSTEM_UID, Process.ROOT_UID)
+fun AppRecord.isSystemOrRootUid(): Boolean =
+ UserHandle.getAppId(app.uid) in listOf(Process.SYSTEM_UID, Process.ROOT_UID)
/**
* Gets whether the permission on / off is changeable for the given app.
diff --git a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsSecureStringTest.kt b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsSecureStringTest.kt
new file mode 100644
index 0000000..e3d182b
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsSecureStringTest.kt
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+package com.android.settingslib.spaprivileged.settingsprovider
+
+import android.content.Context
+import android.provider.Settings
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.settingslib.spa.testutils.firstWithTimeoutOrNull
+import com.android.settingslib.spa.testutils.toListWithTimeout
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.async
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.runBlocking
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class SettingsSecureStringTest {
+
+ private val context: Context = ApplicationProvider.getApplicationContext()
+
+ @Test
+ fun getValue_returnCorrectValue() {
+ Settings.Secure.putString(context.contentResolver, TEST_NAME, VALUE)
+
+ val value by context.settingsSecureString(TEST_NAME)
+
+ assertThat(value).isEqualTo(VALUE)
+ }
+
+ @Test
+ fun setValue_correctValueSet() {
+ var value by context.settingsSecureString(TEST_NAME)
+
+ value = VALUE
+
+ assertThat(Settings.Secure.getString(context.contentResolver, TEST_NAME)).isEqualTo(VALUE)
+ }
+
+ @Test
+ fun settingsSecureStringFlow_valueNotChanged() = runBlocking {
+ var value by context.settingsSecureString(TEST_NAME)
+ value = VALUE
+
+ val flow = context.settingsSecureStringFlow(TEST_NAME)
+
+ assertThat(flow.firstWithTimeoutOrNull()).isEqualTo(VALUE)
+ }
+
+ @Test
+ fun settingsSecureStringFlow_collectAfterValueChanged_onlyKeepLatest() = runBlocking {
+ var value by context.settingsSecureString(TEST_NAME)
+ value = ""
+
+ val flow = context.settingsSecureStringFlow(TEST_NAME)
+ value = VALUE
+
+ assertThat(flow.firstWithTimeoutOrNull()).isEqualTo(VALUE)
+ }
+
+ @Test
+ fun settingsSecureStringFlow_collectBeforeValueChanged_getBoth() = runBlocking {
+ var value by context.settingsSecureString(TEST_NAME)
+ value = ""
+
+ val listDeferred = async { context.settingsSecureStringFlow(TEST_NAME).toListWithTimeout() }
+ delay(100)
+ value = VALUE
+
+ assertThat(listDeferred.await()).containsAtLeast("", VALUE).inOrder()
+ }
+
+ private companion object {
+ const val TEST_NAME = "test_string_delegate"
+ const val VALUE = "value"
+ }
+}
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
index 9f2ab69..8d02dbd 100644
--- a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
@@ -279,5 +279,6 @@
Settings.Secure.ON_DEVICE_INTELLIGENCE_UNBIND_TIMEOUT_MS,
Settings.Secure.ON_DEVICE_INFERENCE_UNBIND_TIMEOUT_MS,
Settings.Secure.ON_DEVICE_INTELLIGENCE_IDLE_TIMEOUT_MS,
+ Settings.Secure.MANDATORY_BIOMETRICS,
};
}
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
index cb7ac45..7169cf7 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
@@ -438,5 +438,6 @@
VALIDATORS.put(Secure.ON_DEVICE_INFERENCE_UNBIND_TIMEOUT_MS, ANY_LONG_VALIDATOR);
VALIDATORS.put(Secure.ON_DEVICE_INTELLIGENCE_UNBIND_TIMEOUT_MS, ANY_LONG_VALIDATOR);
VALIDATORS.put(Secure.ON_DEVICE_INTELLIGENCE_IDLE_TIMEOUT_MS, NONE_NEGATIVE_LONG_VALIDATOR);
+ VALIDATORS.put(Secure.MANDATORY_BIOMETRICS, new InclusiveIntegerRangeValidator(0, 1));
}
}
diff --git a/packages/SystemUI/aconfig/accessibility.aconfig b/packages/SystemUI/aconfig/accessibility.aconfig
index d201071..f63a896 100644
--- a/packages/SystemUI/aconfig/accessibility.aconfig
+++ b/packages/SystemUI/aconfig/accessibility.aconfig
@@ -73,6 +73,16 @@
}
flag {
+ name: "redesign_magnifier_window_size"
+ namespace: "accessibility"
+ description: "Redesigns the window magnification magnifier sizes provided in the settings panel."
+ bug: "288056772"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
name: "save_and_restore_magnification_settings_buttons"
namespace: "accessibility"
description: "Saves the selected button status in magnification settings and restore the status when revisiting the same smallest screen DP."
diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig
index ffa1db3..0ccaf18 100644
--- a/packages/SystemUI/aconfig/systemui.aconfig
+++ b/packages/SystemUI/aconfig/systemui.aconfig
@@ -867,6 +867,13 @@
}
flag {
+ name: "keyboard_touchpad_contextual_education"
+ namespace: "systemui"
+ description: "Allow showing education for physical keyboard and touchpad"
+ bug: "317496783"
+}
+
+flag {
name: "dream_overlay_bouncer_swipe_direction_filtering"
namespace: "systemui"
description: "do not initiate bouncer swipe when the direction is opposite of the expansion"
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt
index fbfe050..4dc801c 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt
@@ -602,10 +602,14 @@
removeEnabled: Boolean,
onRemoveClicked: () -> Unit,
setToolbarSize: (toolbarSize: IntSize) -> Unit,
- setRemoveButtonCoordinates: (coordinates: LayoutCoordinates) -> Unit,
+ setRemoveButtonCoordinates: (coordinates: LayoutCoordinates?) -> Unit,
onOpenWidgetPicker: () -> Unit,
onEditDone: () -> Unit
) {
+ if (!removeEnabled) {
+ // Clear any existing coordinates when remove is not enabled.
+ setRemoveButtonCoordinates(null)
+ }
val removeButtonAlpha: Float by
animateFloatAsState(
targetValue = if (removeEnabled) 1f else 0.5f,
@@ -645,7 +649,13 @@
contentPadding = Dimensions.ButtonPadding,
modifier =
Modifier.graphicsLayer { alpha = removeButtonAlpha }
- .onGloballyPositioned { setRemoveButtonCoordinates(it) }
+ .onGloballyPositioned {
+ // It's possible for this callback to fire after remove has been
+ // disabled. Check enabled state before setting.
+ if (removeEnabled) {
+ setRemoveButtonCoordinates(it)
+ }
+ }
) {
Row(
horizontalArrangement =
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/Notifications.kt b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/Notifications.kt
index 29223ce..6805888 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/Notifications.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/Notifications.kt
@@ -94,6 +94,7 @@
val HeadsUpNotificationPlaceholder =
ElementKey("HeadsUpNotificationPlaceholder", scenePicker = LowestZIndexScenePicker)
val ShelfSpace = ElementKey("ShelfSpace")
+ val NotificationStackCutoffGuideline = ElementKey("NotificationStackCutoffGuideline")
}
// Expansion fraction thresholds (between 0-1f) at which the corresponding value should be
@@ -410,18 +411,22 @@
* the notification contents (stack, footer, shelf) should be drawn.
*/
@Composable
-fun NotificationStackCutoffGuideline(
+fun SceneScope.NotificationStackCutoffGuideline(
stackScrollView: NotificationScrollView,
viewModel: NotificationsPlaceholderViewModel,
modifier: Modifier = Modifier,
) {
Spacer(
modifier =
- modifier.fillMaxWidth().height(0.dp).onGloballyPositioned { coordinates ->
- val positionY = coordinates.positionInWindow().y
- debugLog(viewModel) { "STACK cutoff onGloballyPositioned: y=$positionY" }
- stackScrollView.setStackCutoff(positionY)
- }
+ modifier
+ .element(key = Notifications.Elements.NotificationStackCutoffGuideline)
+ .fillMaxWidth()
+ .height(0.dp)
+ .onGloballyPositioned { coordinates ->
+ val positionY = coordinates.positionInWindow().y
+ debugLog(viewModel) { "STACK cutoff onGloballyPositioned: y=$positionY" }
+ stackScrollView.setStackCutoff(positionY)
+ }
)
}
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt
index bb17024..cfaed41 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt
@@ -543,7 +543,8 @@
_toScene = old._toScene,
userActionDistanceScope = old.userActionDistanceScope,
orientation = old.orientation,
- isUpOrLeft = old.isUpOrLeft
+ isUpOrLeft = old.isUpOrLeft,
+ lastDistance = old.lastDistance,
)
.apply {
_currentScene = old._currentScene
@@ -561,6 +562,7 @@
val userActionDistanceScope: UserActionDistanceScope,
override val orientation: Orientation,
override val isUpOrLeft: Boolean,
+ var lastDistance: Float = DistanceUnspecified,
) :
TransitionState.Transition(_fromScene.key, _toScene.key),
TransitionState.HasOverscrollProperties {
@@ -620,8 +622,6 @@
get() = distance().absoluteValue
}
- private var lastDistance = DistanceUnspecified
-
/** Whether [TransitionState.Transition.finish] was called on this transition. */
var isFinishing = false
private set
@@ -901,6 +901,7 @@
private val topOrLeftBehavior: NestedScrollBehavior,
private val bottomOrRightBehavior: NestedScrollBehavior,
private val isExternalOverscrollGesture: () -> Boolean,
+ private val pointersInfo: () -> PointersInfo,
) {
private val layoutState = layoutImpl.state
private val draggableHandler = layoutImpl.draggableHandler(orientation)
@@ -912,34 +913,36 @@
// moving on to the next scene.
var canChangeScene = false
- val actionUpOrLeft =
- Swipe(
- direction =
- when (orientation) {
- Orientation.Horizontal -> SwipeDirection.Left
- Orientation.Vertical -> SwipeDirection.Up
- },
- pointerCount = 1,
- )
-
- val actionDownOrRight =
- Swipe(
- direction =
- when (orientation) {
- Orientation.Horizontal -> SwipeDirection.Right
- Orientation.Vertical -> SwipeDirection.Down
- },
- pointerCount = 1,
- )
-
fun hasNextScene(amount: Float): Boolean {
val transitionState = layoutState.transitionState
val scene = transitionState.currentScene
val fromScene = layoutImpl.scene(scene)
val nextScene =
when {
- amount < 0f -> fromScene.userActions[actionUpOrLeft]
- amount > 0f -> fromScene.userActions[actionDownOrRight]
+ amount < 0f -> {
+ val actionUpOrLeft =
+ Swipe(
+ direction =
+ when (orientation) {
+ Orientation.Horizontal -> SwipeDirection.Left
+ Orientation.Vertical -> SwipeDirection.Up
+ },
+ pointerCount = pointersInfo().pointersDown,
+ )
+ fromScene.userActions[actionUpOrLeft]
+ }
+ amount > 0f -> {
+ val actionDownOrRight =
+ Swipe(
+ direction =
+ when (orientation) {
+ Orientation.Horizontal -> SwipeDirection.Right
+ Orientation.Vertical -> SwipeDirection.Down
+ },
+ pointerCount = pointersInfo().pointersDown,
+ )
+ fromScene.userActions[actionDownOrRight]
+ }
else -> null
}
if (nextScene != null) return true
@@ -1037,10 +1040,11 @@
canContinueScroll = { true },
canScrollOnFling = false,
onStart = { offsetAvailable ->
+ val pointers = pointersInfo()
dragController =
draggableHandler.onDragStarted(
- pointersDown = 1,
- startedPosition = null,
+ pointersDown = pointers.pointersDown,
+ startedPosition = pointers.startedPosition,
overSlop = if (isIntercepting) 0f else offsetAvailable,
)
},
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MultiPointerDraggable.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MultiPointerDraggable.kt
index 6001f1f..572b1d7 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MultiPointerDraggable.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MultiPointerDraggable.kt
@@ -138,11 +138,26 @@
}
}
+ private var _toFloat = orientation.toFunctionOffsetToFloat()
+
+ private fun Offset.toFloat(): Float = _toFloat(this)
+
+ private fun Orientation.toFunctionOffsetToFloat(): (Offset) -> Float =
+ when (this) {
+ Orientation.Vertical -> {
+ { it.y }
+ }
+ Orientation.Horizontal -> {
+ { it.x }
+ }
+ }
+
var orientation: Orientation = orientation
set(value) {
// Reset the pointer input whenever orientation changed.
if (value != field) {
field = value
+ _toFloat = field.toFunctionOffsetToFloat()
delegate.resetPointerInputHandler()
}
}
@@ -367,13 +382,6 @@
return event
}
- private fun Offset.toFloat(): Float {
- return when (orientation) {
- Orientation.Vertical -> y
- Orientation.Horizontal -> x
- }
- }
-
/**
* Continues to read drag events until all pointers are up or the drag event is canceled. The
* initial pointer to use for driving the drag is [initialPointerId]. [hasDragged] passes the
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/NestedScrollToScene.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/NestedScrollToScene.kt
index 1fa6b3f7..dd795cd 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/NestedScrollToScene.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/NestedScrollToScene.kt
@@ -18,12 +18,21 @@
import androidx.compose.foundation.gestures.Orientation
import androidx.compose.ui.Modifier
+import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.input.nestedscroll.nestedScrollModifierNode
+import androidx.compose.ui.input.pointer.PointerEventPass
+import androidx.compose.ui.input.pointer.PointerInputChange
+import androidx.compose.ui.input.pointer.PointerInputScope
+import androidx.compose.ui.input.pointer.SuspendingPointerInputModifierNode
import androidx.compose.ui.node.DelegatableNode
import androidx.compose.ui.node.DelegatingNode
import androidx.compose.ui.node.ModifierNodeElement
import androidx.compose.ui.platform.InspectorInfo
+import androidx.compose.ui.util.fastMap
+import androidx.compose.ui.util.fastReduce
import com.android.compose.nestedscroll.PriorityNestedScrollConnection
+import kotlinx.coroutines.coroutineScope
+import kotlinx.coroutines.isActive
/**
* Defines the behavior of the [SceneTransitionLayout] when a scrollable component is scrolled.
@@ -121,6 +130,11 @@
}
}
+internal data class PointersInfo(
+ val pointersDown: Int,
+ val startedPosition: Offset,
+)
+
private class NestedScrollToSceneNode(
layoutImpl: SceneTransitionLayoutImpl,
orientation: Orientation,
@@ -135,23 +149,49 @@
topOrLeftBehavior = topOrLeftBehavior,
bottomOrRightBehavior = bottomOrRightBehavior,
isExternalOverscrollGesture = isExternalOverscrollGesture,
+ pointersInfo = pointerInfo()
)
+ private var lastPointers: List<PointerInputChange>? = null
+
+ private fun pointerInfo(): () -> PointersInfo = {
+ val pointers =
+ requireNotNull(lastPointers) { "NestedScroll API was called before PointerInput API" }
+ PointersInfo(
+ pointersDown = pointers.size,
+ startedPosition = pointers.fastMap { it.position }.fastReduce { a, b -> (a + b) / 2f },
+ )
+ }
+
+ private val pointerInputHandler: suspend PointerInputScope.() -> Unit = {
+ coroutineScope {
+ awaitPointerEventScope {
+ // Await this scope to guarantee that the PointerInput API receives touch events
+ // before the NestedScroll API.
+ delegate(nestedScrollNode)
+
+ try {
+ while (isActive) {
+ // During the initial phase, we receive the event after our ancestors.
+ lastPointers = awaitPointerEvent(PointerEventPass.Initial).changes
+ }
+ } finally {
+ // Clean up the nested scroll connection
+ priorityNestedScrollConnection.reset()
+ undelegate(nestedScrollNode)
+ }
+ }
+ }
+ }
+
+ private val pointerInputNode = delegate(SuspendingPointerInputModifierNode(pointerInputHandler))
+
private var nestedScrollNode: DelegatableNode =
nestedScrollModifierNode(
connection = priorityNestedScrollConnection,
dispatcher = null,
)
- override fun onAttach() {
- delegate(nestedScrollNode)
- }
-
- override fun onDetach() {
- // Make sure we reset the scroll connection when this modifier is removed from composition
- priorityNestedScrollConnection.reset()
- }
-
fun update(
layoutImpl: SceneTransitionLayoutImpl,
orientation: Orientation,
@@ -161,7 +201,7 @@
) {
// Clean up the old nested scroll connection
priorityNestedScrollConnection.reset()
- undelegate(nestedScrollNode)
+ pointerInputNode.resetPointerInputHandler()
// Create a new nested scroll connection
priorityNestedScrollConnection =
@@ -171,13 +211,13 @@
topOrLeftBehavior = topOrLeftBehavior,
bottomOrRightBehavior = bottomOrRightBehavior,
isExternalOverscrollGesture = isExternalOverscrollGesture,
+ pointersInfo = pointerInfo(),
)
nestedScrollNode =
nestedScrollModifierNode(
connection = priorityNestedScrollConnection,
dispatcher = null,
)
- delegate(nestedScrollNode)
}
}
@@ -187,6 +227,7 @@
topOrLeftBehavior: NestedScrollBehavior,
bottomOrRightBehavior: NestedScrollBehavior,
isExternalOverscrollGesture: () -> Boolean,
+ pointersInfo: () -> PointersInfo,
) =
NestedScrollHandlerImpl(
layoutImpl = layoutImpl,
@@ -194,5 +235,6 @@
topOrLeftBehavior = topOrLeftBehavior,
bottomOrRightBehavior = bottomOrRightBehavior,
isExternalOverscrollGesture = isExternalOverscrollGesture,
+ pointersInfo = pointersInfo,
)
.connection
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt
index b925130..33063c8 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt
@@ -461,7 +461,7 @@
val transitionKey: TransitionKey? = null,
)
-interface UserActionDistance {
+fun interface UserActionDistance {
/**
* Return the **absolute** distance of the user action given the size of the scene we are
* animating from and the [orientation].
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/modifiers/SizeMatcher.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/modifiers/SizeMatcher.kt
new file mode 100644
index 0000000..a4bd2be
--- /dev/null
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/modifiers/SizeMatcher.kt
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+package com.android.compose.animation.scene.modifiers
+
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.layout.Measurable
+import androidx.compose.ui.layout.MeasureResult
+import androidx.compose.ui.layout.MeasureScope
+import androidx.compose.ui.node.LayoutModifierNode
+import androidx.compose.ui.node.ModifierNodeElement
+import androidx.compose.ui.node.invalidateMeasurement
+import androidx.compose.ui.unit.Constraints
+import androidx.compose.ui.unit.IntSize
+import androidx.compose.ui.unit.constrain
+
+/**
+ * An object to make one or more destination node be the same size as a source node.
+ *
+ * Important: Most of the time, you should not use this class and instead use `Box` together with
+ * `Modifier.matchParentSize()`. Use this only if you need to use both `Modifier.element()` and
+ * `Modifier.matchParentSize()` (see b/347910697 for details).
+ *
+ * Example:
+ * ```
+ * Box {
+ * val sizeMatcher = remember { SizeMatcher() }
+ *
+ * // The content.
+ * Content(Modifier.sizeMatcherSource(sizeMatcher))
+ *
+ * // The background. Note that this has to be composed after Content() so that it
+ * // is measured after it. We set its zIndex to -1 so that it is still placed
+ * // (drawn) before/below it. We don't use BoxScope.matchParentSize() because it
+ * // does not play well with Modifier.element().
+ * Box(
+ * Modifier.zIndex(-1f)
+ * .element(Background)
+ * // Set the preferred size of this element.
+ * // Important: This must be *after* the Modifier.element() so that
+ * // Modifier.element() can override the size.
+ * .sizeMatcherDestination(sizeMatcher)
+ * .background(
+ * MaterialTheme.colorScheme.primaryContainer,
+ * RoundedCornerShape(32.dp),
+ * )
+ * )
+ * }
+ * ```
+ *
+ * @see sizeMatcherSource
+ * @see sizeMatcherDestination
+ */
+class SizeMatcher {
+ internal var source: LayoutModifierNode? = null
+ set(value) {
+ if (value != null && field != null && value != field) {
+ error("Exactly one Modifier.sizeMatcherSource() should be specified")
+ }
+ }
+
+ internal var destinations = mutableSetOf<LayoutModifierNode>()
+ internal var sourceSize: IntSize = InvalidSize
+ get() {
+ if (field == InvalidSize) {
+ error(
+ "SizeMatcher size was retrieved before it was set. You should make sure that " +
+ "all matcher destination are measured *after* the matcher source."
+ )
+ }
+ return field
+ }
+ set(value) {
+ if (value != field) {
+ field = value
+ destinations.forEach { it.invalidateMeasurement() }
+ }
+ }
+
+ companion object {
+ private val InvalidSize = IntSize(Int.MIN_VALUE, Int.MIN_VALUE)
+ }
+}
+
+/**
+ * Mark this node as the source of a [SizeMatcher].
+ *
+ * Important: There must be only a single source node associated to a [SizeMatcher] and it must be
+ * measured before any destination.
+ */
+fun Modifier.sizeMatcherSource(matcher: SizeMatcher): Modifier {
+ return this.then(SizeMatcherSourceNodeElement(matcher))
+}
+
+/**
+ * Mark this node as the destination of a [SizeMatcher] so that its *preferred* size is the same
+ * size as the source size.
+ *
+ * Important: Destination nodes must be measured *after* the source node, otherwise it might cause
+ * crashes or 1-frame flickers. For most simple layouts (like Box, Row or Column), this usually
+ * means that the destinations nodes must be composed *after* the source node. If doing so is
+ * causing layering issues, you can use `Modifier.zIndex` to explicitly set the placement order of
+ * your composables.
+ */
+fun Modifier.sizeMatcherDestination(matcher: SizeMatcher): Modifier {
+ return this.then(SizeMatcherDestinationElement(matcher))
+}
+
+private data class SizeMatcherSourceNodeElement(
+ private val matcher: SizeMatcher,
+) : ModifierNodeElement<SizeMatcherSourceNode>() {
+ override fun create(): SizeMatcherSourceNode = SizeMatcherSourceNode(matcher)
+
+ override fun update(node: SizeMatcherSourceNode) {
+ node.update(matcher)
+ }
+}
+
+private class SizeMatcherSourceNode(
+ private var matcher: SizeMatcher,
+) : Modifier.Node(), LayoutModifierNode {
+ override fun onAttach() {
+ matcher.source = this
+ }
+
+ override fun onDetach() {
+ matcher.source = null
+ }
+
+ fun update(matcher: SizeMatcher) {
+ val previous = this.matcher
+ this.matcher = matcher
+
+ previous.source = null
+ matcher.source = this
+ }
+
+ override fun MeasureScope.measure(
+ measurable: Measurable,
+ constraints: Constraints
+ ): MeasureResult {
+ return measurable.measure(constraints).run {
+ matcher.sourceSize = IntSize(width, height)
+ layout(width, height) { place(0, 0) }
+ }
+ }
+}
+
+private data class SizeMatcherDestinationElement(
+ private val matcher: SizeMatcher,
+) : ModifierNodeElement<SizeMatcherDestinationNode>() {
+ override fun create(): SizeMatcherDestinationNode = SizeMatcherDestinationNode(matcher)
+
+ override fun update(node: SizeMatcherDestinationNode) {
+ node.update(matcher)
+ }
+}
+
+private class SizeMatcherDestinationNode(
+ private var matcher: SizeMatcher,
+) : Modifier.Node(), LayoutModifierNode {
+ override fun onAttach() {
+ this.matcher.destinations.add(this)
+ }
+
+ override fun onDetach() {
+ this.matcher.destinations.remove(this)
+ }
+
+ fun update(matcher: SizeMatcher) {
+ val previous = this.matcher
+ this.matcher = matcher
+
+ previous.destinations.remove(this)
+ matcher.destinations.add(this)
+ }
+
+ override fun MeasureScope.measure(
+ measurable: Measurable,
+ constraints: Constraints
+ ): MeasureResult {
+ val preferredSize = matcher.sourceSize
+ val preferredConstraints = Constraints.fixed(preferredSize.width, preferredSize.height)
+
+ // Make sure we still respect the incoming constraints.
+ val placeable = measurable.measure(constraints.constrain(preferredConstraints))
+ return layout(placeable.width, placeable.height) { placeable.place(0, 0) }
+ }
+}
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt
index f532e2e..be3bca7 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt
@@ -113,7 +113,8 @@
orientation = draggableHandler.orientation,
topOrLeftBehavior = nestedScrollBehavior,
bottomOrRightBehavior = nestedScrollBehavior,
- isExternalOverscrollGesture = { isExternalOverscrollGesture }
+ isExternalOverscrollGesture = { isExternalOverscrollGesture },
+ pointersInfo = { PointersInfo(pointersDown = 1, startedPosition = Offset.Zero) }
)
.connection
@@ -1195,4 +1196,23 @@
assertThat(transition).hasProgress(0f)
assertThat(transition).hasOverscrollSpec()
}
+
+ @Test
+ fun interceptingTransitionKeepsDistance() = runGestureTest {
+ var swipeDistance = 75f
+ layoutState.transitions = transitions {
+ from(SceneA, to = SceneB) { distance = UserActionDistance { _, _ -> swipeDistance } }
+ }
+
+ // Start transition.
+ val controller = onDragStarted(overSlop = -50f)
+ assertTransition(fromScene = SceneA, toScene = SceneB, progress = 50f / 75f)
+
+ // Intercept the transition and change the swipe distance. The original distance and
+ // progress should be the same.
+ swipeDistance = 50f
+ controller.onDragStopped(0f)
+ onDragStartedImmediately()
+ assertTransition(fromScene = SceneA, toScene = SceneB, progress = 50f / 75f)
+ }
}
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementTest.kt
index a18da73..615a42f 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementTest.kt
@@ -731,7 +731,7 @@
onAnimatedFloat = { animatedFloat = it },
)
- val fooElement = rule.onNodeWithTag(TestElements.Foo.testTag, useUnmergedTree = true)
+ val fooElement = rule.onNodeWithTag(TestElements.Foo.testTag)
fooElement.assertTopPositionInRootIsEqualTo(0.dp)
val transition = assertThat(state.transitionState).isTransition()
assertThat(transition).isNotNull()
@@ -811,7 +811,7 @@
}
assertThat(state.transitionState).isIdle()
- val fooElement = rule.onNodeWithTag(TestElements.Foo.testTag, useUnmergedTree = true)
+ val fooElement = rule.onNodeWithTag(TestElements.Foo.testTag)
fooElement.assertTopPositionInRootIsEqualTo(0.dp)
// Swipe by half of verticalSwipeDistance.
@@ -839,6 +839,79 @@
}
@Test
+ fun elementTransitionDuringNestedScrollWith2Pointers() {
+ // The draggable touch slop, i.e. the min px distance a touch pointer must move before it is
+ // detected as a drag event.
+ var touchSlop = 0f
+ val translateY = 10.dp
+ val layoutWidth = 200.dp
+ val layoutHeight = 400.dp
+
+ val state =
+ rule.runOnUiThread {
+ MutableSceneTransitionLayoutState(
+ initialScene = SceneA,
+ transitions = transitions {
+ from(SceneA, to = SceneB) {
+ translate(TestElements.Foo, y = translateY)
+ }
+ },
+ )
+ as MutableSceneTransitionLayoutStateImpl
+ }
+
+ rule.setContent {
+ touchSlop = LocalViewConfiguration.current.touchSlop
+ SceneTransitionLayout(
+ state = state,
+ modifier = Modifier.size(layoutWidth, layoutHeight)
+ ) {
+ scene(
+ SceneA,
+ userActions = mapOf(Swipe(SwipeDirection.Down, pointerCount = 2) to SceneB)
+ ) {
+ Box(
+ Modifier
+ // Unconsumed scroll gesture will be intercepted by STL
+ .verticalNestedScrollToScene()
+ // A scrollable that does not consume the scroll gesture
+ .scrollable(
+ rememberScrollableState(consumeScrollDelta = { 0f }),
+ Orientation.Vertical
+ )
+ .fillMaxSize()
+ ) {
+ Spacer(Modifier.element(TestElements.Foo).fillMaxSize())
+ }
+ }
+ scene(SceneB) { Spacer(Modifier.fillMaxSize()) }
+ }
+ }
+
+ assertThat(state.transitionState).isIdle()
+ val fooElement = rule.onNodeWithTag(TestElements.Foo.testTag)
+ fooElement.assertTopPositionInRootIsEqualTo(0.dp)
+
+ // Swipe down with 2 pointers by half of verticalSwipeDistance.
+ rule.onRoot().performTouchInput {
+ val middleTop = Offset((layoutWidth / 2).toPx(), 0f)
+ repeat(2) { i -> down(pointerId = i, middleTop) }
+ repeat(2) { i ->
+ // Scroll 50%
+ moveBy(
+ pointerId = i,
+ delta = Offset(0f, touchSlop + layoutHeight.toPx() * 0.5f),
+ delayMillis = 1_000,
+ )
+ }
+ }
+
+ val transition = assertThat(state.transitionState).isTransition()
+ assertThat(transition).hasProgress(0.5f)
+ fooElement.assertTopPositionInRootIsEqualTo(translateY * 0.5f)
+ }
+
+ @Test
fun elementTransitionWithDistanceDuringOverscroll() {
val layoutWidth = 200.dp
val layoutHeight = 400.dp
@@ -858,7 +931,7 @@
onAnimatedFloat = { animatedFloat = it },
)
- val fooElement = rule.onNodeWithTag(TestElements.Foo.testTag, useUnmergedTree = true)
+ val fooElement = rule.onNodeWithTag(TestElements.Foo.testTag)
fooElement.assertTopPositionInRootIsEqualTo(0.dp)
assertThat(animatedFloat).isEqualTo(100f)
@@ -914,7 +987,7 @@
onAnimatedFloat = { animatedFloat = it },
)
- val fooElement = rule.onNodeWithTag(TestElements.Foo.testTag, useUnmergedTree = true)
+ val fooElement = rule.onNodeWithTag(TestElements.Foo.testTag)
fooElement.assertTopPositionInRootIsEqualTo(0.dp)
assertThat(animatedFloat).isEqualTo(100f)
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/modifiers/SizeMatcherTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/modifiers/SizeMatcherTest.kt
new file mode 100644
index 0000000..fa24966
--- /dev/null
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/modifiers/SizeMatcherTest.kt
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+package com.android.compose.animation.scene.modifiers
+
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.size
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.testTag
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.onNodeWithTag
+import androidx.compose.ui.unit.DpSize
+import androidx.compose.ui.unit.dp
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.compose.test.assertSizeIsEqualTo
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class SizeMatcherTest {
+ @get:Rule val rule = createComposeRule()
+
+ @Test
+ fun sizeMatcher() {
+ val contentSize = DpSize(200.dp, 100.dp)
+ val sizeMatcher = SizeMatcher()
+ val backgroundTag = "background"
+
+ rule.setContent {
+ Box {
+ Box(Modifier.sizeMatcherSource(sizeMatcher).size(contentSize))
+ Box(Modifier.testTag(backgroundTag).sizeMatcherDestination(sizeMatcher))
+ }
+ }
+
+ rule.onNodeWithTag(backgroundTag).assertSizeIsEqualTo(contentSize.width, contentSize.height)
+ }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/StatusBarStartableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/StatusBarStartableTest.kt
new file mode 100644
index 0000000..9601f20
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/StatusBarStartableTest.kt
@@ -0,0 +1,365 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+@file:OptIn(ExperimentalCoroutinesApi::class)
+
+package com.android.systemui.scene.domain.startable
+
+import android.app.StatusBarManager
+import android.provider.DeviceConfig
+import android.view.WindowManagerPolicyConstants
+import androidx.test.filters.SmallTest
+import com.android.compose.animation.scene.ObservableTransitionState
+import com.android.compose.animation.scene.SceneKey
+import com.android.internal.config.sysui.SystemUiDeviceConfigFlags
+import com.android.internal.statusbar.statusBarService
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.authentication.data.repository.fakeAuthenticationRepository
+import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
+import com.android.systemui.concurrency.fakeExecutor
+import com.android.systemui.flags.EnableSceneContainer
+import com.android.systemui.keyguard.data.repository.fakeBiometricSettingsRepository
+import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFingerprintAuthRepository
+import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticationStatus
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.navigationbar.NavigationModeController
+import com.android.systemui.navigationbar.navigationModeController
+import com.android.systemui.power.data.repository.fakePowerRepository
+import com.android.systemui.power.shared.model.WakeSleepReason
+import com.android.systemui.power.shared.model.WakefulnessState
+import com.android.systemui.scene.data.repository.setSceneTransition
+import com.android.systemui.scene.domain.interactor.sceneInteractor
+import com.android.systemui.scene.shared.model.Scenes
+import com.android.systemui.statusbar.domain.interactor.keyguardOcclusionInteractor
+import com.android.systemui.testKosmos
+import com.android.systemui.util.fakeDeviceConfigProxy
+import com.google.common.truth.Truth.assertThat
+import com.google.common.truth.Truth.assertWithMessage
+import kotlin.reflect.full.memberProperties
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.BeforeClass
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.kotlin.any
+import org.mockito.kotlin.argumentCaptor
+import org.mockito.kotlin.atLeastOnce
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.verify
+import org.mockito.kotlin.whenever
+import platform.test.runner.parameterized.Parameter
+import platform.test.runner.parameterized.ParameterizedAndroidJunit4
+import platform.test.runner.parameterized.Parameters
+
+@SmallTest
+@RunWith(ParameterizedAndroidJunit4::class)
+@EnableSceneContainer
+class StatusBarStartableTest : SysuiTestCase() {
+
+ companion object {
+ @Parameters(name = "{0}")
+ @JvmStatic
+ fun testSpecs(): List<TestSpec> {
+ return listOf(
+ TestSpec(
+ id = 0,
+ expectedFlags = StatusBarManager.DISABLE_NONE,
+ Preconditions(
+ isForceHideHomeAndRecents = false,
+ isKeyguardShowing = false,
+ isPowerGestureIntercepted = false,
+ ),
+ ),
+ TestSpec(
+ id = 1,
+ expectedFlags = StatusBarManager.DISABLE_NONE,
+ Preconditions(
+ isForceHideHomeAndRecents = false,
+ isKeyguardShowing = true,
+ isOccluded = true,
+ isPowerGestureIntercepted = false,
+ ),
+ ),
+ TestSpec(
+ id = 2,
+ expectedFlags = StatusBarManager.DISABLE_NONE,
+ Preconditions(
+ isForceHideHomeAndRecents = false,
+ isKeyguardShowing = false,
+ isPowerGestureIntercepted = true,
+ isOccluded = false,
+ ),
+ ),
+ TestSpec(
+ id = 3,
+ expectedFlags = StatusBarManager.DISABLE_NONE,
+ Preconditions(
+ isForceHideHomeAndRecents = false,
+ isKeyguardShowing = true,
+ isOccluded = true,
+ isPowerGestureIntercepted = true,
+ isAuthenticationMethodSecure = false,
+ ),
+ ),
+ TestSpec(
+ id = 4,
+ expectedFlags = StatusBarManager.DISABLE_NONE,
+ Preconditions(
+ isForceHideHomeAndRecents = false,
+ isKeyguardShowing = true,
+ isOccluded = true,
+ isPowerGestureIntercepted = true,
+ isAuthenticationMethodSecure = true,
+ isFaceEnrolledAndEnabled = false,
+ ),
+ ),
+ TestSpec(
+ id = 5,
+ expectedFlags = StatusBarManager.DISABLE_RECENT,
+ Preconditions(
+ isForceHideHomeAndRecents = false,
+ isKeyguardShowing = true,
+ isOccluded = true,
+ isPowerGestureIntercepted = true,
+ isAuthenticationMethodSecure = true,
+ isFaceEnrolledAndEnabled = true,
+ ),
+ ),
+ TestSpec(
+ id = 6,
+ expectedFlags = StatusBarManager.DISABLE_RECENT,
+ Preconditions(
+ isForceHideHomeAndRecents = true,
+ isShowHomeOverLockscreen = true,
+ isGesturalMode = true,
+ isPowerGestureIntercepted = false,
+ ),
+ ),
+ TestSpec(
+ id = 7,
+ expectedFlags = StatusBarManager.DISABLE_RECENT,
+ Preconditions(
+ isForceHideHomeAndRecents = false,
+ isKeyguardShowing = true,
+ isOccluded = false,
+ isShowHomeOverLockscreen = true,
+ isGesturalMode = true,
+ isPowerGestureIntercepted = false,
+ ),
+ ),
+ TestSpec(
+ id = 8,
+ expectedFlags =
+ StatusBarManager.DISABLE_RECENT or StatusBarManager.DISABLE_HOME,
+ Preconditions(
+ isForceHideHomeAndRecents = true,
+ isShowHomeOverLockscreen = true,
+ isGesturalMode = false,
+ isPowerGestureIntercepted = false,
+ ),
+ ),
+ TestSpec(
+ id = 9,
+ expectedFlags =
+ StatusBarManager.DISABLE_RECENT or StatusBarManager.DISABLE_HOME,
+ Preconditions(
+ isForceHideHomeAndRecents = false,
+ isKeyguardShowing = true,
+ isOccluded = false,
+ isShowHomeOverLockscreen = false,
+ isPowerGestureIntercepted = false,
+ ),
+ ),
+ )
+ }
+
+ @BeforeClass
+ @JvmStatic
+ fun setUpClass() {
+ val seenIds = mutableSetOf<Int>()
+ testSpecs().forEach { testSpec ->
+ assertWithMessage("Duplicate TestSpec id=${testSpec.id}")
+ .that(seenIds)
+ .doesNotContain(testSpec.id)
+ seenIds.add(testSpec.id)
+ }
+ }
+ }
+
+ private val kosmos = testKosmos()
+ private val testScope = kosmos.testScope
+
+ private val statusBarServiceMock = kosmos.statusBarService
+ private val flagsCaptor = argumentCaptor<Int>()
+
+ private val navigationModeControllerMock = kosmos.navigationModeController
+ private var currentNavigationMode = WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON
+ set(value) {
+ field = value
+ modeChangedListeners.forEach { listener -> listener.onNavigationModeChanged(field) }
+ }
+
+ private val modeChangedListeners = mutableListOf<NavigationModeController.ModeChangedListener>()
+
+ private val underTest = kosmos.statusBarStartable
+
+ @JvmField @Parameter(0) var testSpec: TestSpec? = null
+
+ @Before
+ fun setUp() {
+ whenever(navigationModeControllerMock.addListener(any())).thenAnswer { invocation ->
+ val listener = invocation.arguments[0] as NavigationModeController.ModeChangedListener
+ modeChangedListeners.add(listener)
+ currentNavigationMode
+ }
+
+ underTest.start()
+ }
+
+ @Test
+ fun test() =
+ testScope.runTest {
+ val preconditions = checkNotNull(testSpec).preconditions
+ preconditions.assertValid()
+
+ setUpWith(preconditions)
+
+ runCurrent()
+
+ verify(statusBarServiceMock, atLeastOnce())
+ .disableForUser(flagsCaptor.capture(), any(), any(), anyInt())
+ assertThat(flagsCaptor.lastValue).isEqualTo(checkNotNull(testSpec).expectedFlags)
+ }
+
+ /** Sets up the state to match what's specified in the given [preconditions]. */
+ private fun TestScope.setUpWith(
+ preconditions: Preconditions,
+ ) {
+ if (!preconditions.isKeyguardShowing) {
+ kosmos.fakeDeviceEntryFingerprintAuthRepository.setAuthenticationStatus(
+ SuccessFingerprintAuthenticationStatus(0, true)
+ )
+ }
+ if (preconditions.isForceHideHomeAndRecents) {
+ whenIdle(Scenes.Bouncer)
+ } else if (preconditions.isKeyguardShowing) {
+ whenIdle(Scenes.Lockscreen)
+ } else {
+ whenIdle(Scenes.Gone)
+ }
+ runCurrent()
+
+ kosmos.keyguardOcclusionInteractor.setWmNotifiedShowWhenLockedActivityOnTop(
+ showWhenLockedActivityOnTop = preconditions.isOccluded,
+ taskInfo = if (preconditions.isOccluded) mock() else null,
+ )
+
+ kosmos.fakeDeviceConfigProxy.setProperty(
+ DeviceConfig.NAMESPACE_SYSTEMUI,
+ SystemUiDeviceConfigFlags.NAV_BAR_HANDLE_SHOW_OVER_LOCKSCREEN,
+ preconditions.isShowHomeOverLockscreen.toString(),
+ /* makeDefault= */ false,
+ )
+ kosmos.fakeExecutor.runAllReady()
+
+ currentNavigationMode =
+ if (preconditions.isGesturalMode) {
+ WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL
+ } else {
+ WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON
+ }
+
+ kosmos.fakeAuthenticationRepository.setAuthenticationMethod(
+ if (preconditions.isAuthenticationMethodSecure) {
+ AuthenticationMethodModel.Pin
+ } else {
+ AuthenticationMethodModel.None
+ }
+ )
+
+ kosmos.fakePowerRepository.updateWakefulness(
+ rawState =
+ if (preconditions.isPowerGestureIntercepted) WakefulnessState.AWAKE
+ else WakefulnessState.ASLEEP,
+ lastWakeReason = WakeSleepReason.POWER_BUTTON,
+ lastSleepReason = WakeSleepReason.POWER_BUTTON,
+ powerButtonLaunchGestureTriggered = preconditions.isPowerGestureIntercepted,
+ )
+
+ kosmos.fakeBiometricSettingsRepository.setIsFaceAuthEnrolledAndEnabled(
+ preconditions.isFaceEnrolledAndEnabled
+ )
+
+ runCurrent()
+ }
+
+ /** Sets up an idle state on the given [on] scene. */
+ private fun whenIdle(on: SceneKey) {
+ kosmos.setSceneTransition(ObservableTransitionState.Idle(on))
+ kosmos.sceneInteractor.changeScene(on, "")
+ }
+
+ data class Preconditions(
+ val isForceHideHomeAndRecents: Boolean = false,
+ val isKeyguardShowing: Boolean = true,
+ val isOccluded: Boolean = false,
+ val isPowerGestureIntercepted: Boolean = false,
+ val isShowHomeOverLockscreen: Boolean = false,
+ val isGesturalMode: Boolean = true,
+ val isAuthenticationMethodSecure: Boolean = true,
+ val isFaceEnrolledAndEnabled: Boolean = false,
+ ) {
+ override fun toString(): String {
+ // Only include values set to true:
+ return buildString {
+ append("(")
+ append(
+ Preconditions::class
+ .memberProperties
+ .filter { it.get(this@Preconditions) == true }
+ .joinToString(", ") { "${it.name}=true" }
+ )
+ append(")")
+ }
+ }
+
+ fun assertValid() {
+ assertWithMessage(
+ "isForceHideHomeAndRecents means that the bouncer is showing so keyguard must" +
+ " be showing"
+ )
+ .that(!isForceHideHomeAndRecents || isKeyguardShowing)
+ .isTrue()
+ assertWithMessage("Cannot be occluded if the keyguard isn't showing")
+ .that(!isOccluded || isKeyguardShowing)
+ .isTrue()
+ }
+ }
+
+ data class TestSpec(
+ val id: Int,
+ val expectedFlags: Int,
+ val preconditions: Preconditions,
+ ) {
+ override fun toString(): String {
+ return "id=$id, expected=$expectedFlags, preconditions=$preconditions"
+ }
+ }
+}
diff --git a/packages/SystemUI/res-keyguard/layout/alternate_bouncer.xml b/packages/SystemUI/res-keyguard/layout/alternate_bouncer.xml
index cf9ca15..c9850f2 100644
--- a/packages/SystemUI/res-keyguard/layout/alternate_bouncer.xml
+++ b/packages/SystemUI/res-keyguard/layout/alternate_bouncer.xml
@@ -19,8 +19,6 @@
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:sysui="http://schemas.android.com/apk/res-auto"
android:id="@+id/alternate_bouncer"
- android:focusable="true"
- android:clickable="true"
android:layout_width="match_parent"
android:layout_height="match_parent">
diff --git a/packages/SystemUI/res/drawable/placeholder_touchpad_back_gesture.png b/packages/SystemUI/res/drawable/placeholder_touchpad_back_gesture.png
new file mode 100644
index 0000000..526b585
--- /dev/null
+++ b/packages/SystemUI/res/drawable/placeholder_touchpad_back_gesture.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable/placeholder_touchpad_tablet_back_gesture.png b/packages/SystemUI/res/drawable/placeholder_touchpad_tablet_back_gesture.png
new file mode 100644
index 0000000..cba2d20
--- /dev/null
+++ b/packages/SystemUI/res/drawable/placeholder_touchpad_tablet_back_gesture.png
Binary files differ
diff --git a/packages/SystemUI/res/layout/sidefps_view.xml b/packages/SystemUI/res/layout/sidefps_view.xml
index fc4bf8a..e80ed26 100644
--- a/packages/SystemUI/res/layout/sidefps_view.xml
+++ b/packages/SystemUI/res/layout/sidefps_view.xml
@@ -22,5 +22,4 @@
android:layout_height="wrap_content"
app:lottie_autoPlay="true"
app:lottie_loop="true"
- app:lottie_rawRes="@raw/sfps_pulse"
- android:importantForAccessibility="no"/>
\ No newline at end of file
+ app:lottie_rawRes="@raw/sfps_pulse"/>
\ No newline at end of file
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 8381812..82dafc3 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -3577,6 +3577,12 @@
<string name="touchpad_tutorial_action_key_button">Action key</string>
<!-- Label for button finishing touchpad tutorial [CHAR LIMIT=NONE] -->
<string name="touchpad_tutorial_done_button">Done</string>
+ <!-- Touchpad back gesture action name in tutorial [CHAR LIMIT=NONE] -->
+ <string name="touchpad_back_gesture_action_title">Go back</string>
+ <!-- Touchpad back gesture guidance in gestures tutorial [CHAR LIMIT=NONE] -->
+ <string name="touchpad_back_gesture_guidance">To go back, swipe left or right using three fingers anywhere on the touchpad.</string>
+ <string name="touchpad_back_gesture_animation_content_description">Touchpad showing three fingers moving right and left</string>
+ <string name="touchpad_back_gesture_screen_animation_content_description">Device screen showing animation for back gesture</string>
<!-- Content description for keyboard backlight brightness dialog [CHAR LIMIT=NONE] -->
<string name="keyboard_backlight_dialog_title">Keyboard backlight</string>
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
index 5458ab1..25ad385 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
@@ -1631,8 +1631,23 @@
boolean bRTL = isRTL(mContext);
final int initSize = Math.min(mWindowBounds.width(), mWindowBounds.height()) / 3;
- final int maxHeightSize = mWindowBounds.height() - 2 * mMirrorSurfaceMargin;
- final int maxWidthSize = mWindowBounds.width() - 2 * mMirrorSurfaceMargin;
+ int maxHeightSize;
+ int maxWidthSize;
+ if (Flags.redesignMagnifierWindowSize()) {
+ // mOuterBorderSize = transparent margin area
+ // mMirrorSurfaceMargin = transparent margin area + orange border width
+ // We would like to allow the width and height to be full size. Therefore, the max
+ // frame size could be calculated as (window bounds - 2 * orange border width).
+ maxHeightSize =
+ mWindowBounds.height() - 2 * (mMirrorSurfaceMargin - mOuterBorderSize);
+ maxWidthSize =
+ mWindowBounds.width() - 2 * (mMirrorSurfaceMargin - mOuterBorderSize);
+ } else {
+ maxHeightSize =
+ mWindowBounds.height() - 2 * mMirrorSurfaceMargin;
+ maxWidthSize =
+ mWindowBounds.width() - 2 * mMirrorSurfaceMargin;
+ }
Rect tempRect = new Rect();
tempRect.set(mMagnificationFrame);
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayer.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayer.java
index ae9775a0..9d573d3 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayer.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayer.java
@@ -205,8 +205,9 @@
return;
}
- setAccessibilityServiceState(getContext(), serviceComponentName, /* enabled= */
- false);
+ setAccessibilityServiceState(
+ getContext(), serviceComponentName, /* enabled= */ false,
+ mSecureSettings.getRealUserHandle(UserHandle.USER_CURRENT));
});
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinder.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinder.kt
index 9cc4650..9578da4 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinder.kt
@@ -139,6 +139,11 @@
overlayView!!.visibility = View.INVISIBLE
Log.d(TAG, "show(): adding overlayView $overlayView")
windowManager.get().addView(overlayView, overlayViewModel.defaultOverlayViewParams)
+ overlayView!!.announceForAccessibility(
+ applicationContext.resources.getString(
+ R.string.accessibility_side_fingerprint_indicator_label
+ )
+ )
}
/** Hide the side fingerprint sensor indicator */
diff --git a/packages/SystemUI/src/com/android/systemui/communal/widgets/EditWidgetsActivity.kt b/packages/SystemUI/src/com/android/systemui/communal/widgets/EditWidgetsActivity.kt
index 40df6cec..46f802f 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/widgets/EditWidgetsActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/widgets/EditWidgetsActivity.kt
@@ -96,7 +96,8 @@
run { Log.w(TAG, "No AppWidgetProviderInfo found in result.") }
}
}
- } ?: run { Log.w(TAG, "No data in result.") }
+ }
+ ?: run { Log.w(TAG, "No data in result.") }
}
else ->
Log.w(
@@ -127,7 +128,7 @@
Box(
modifier =
Modifier.fillMaxSize()
- .background(LocalAndroidColorScheme.current.outlineVariant),
+ .background(LocalAndroidColorScheme.current.onSecondaryFixed),
) {
CommunalHub(
viewModel = communalViewModel,
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 2d60fcc..b70dbe2 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -151,6 +151,7 @@
import com.android.systemui.navigationbar.NavigationModeController;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.res.R;
+import com.android.systemui.scene.shared.flag.SceneContainerFlag;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.shade.ShadeController;
import com.android.systemui.shade.ShadeExpansionStateManager;
@@ -178,6 +179,8 @@
import dagger.Lazy;
+import kotlinx.coroutines.CoroutineDispatcher;
+
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -187,8 +190,6 @@
import java.util.concurrent.Executor;
import java.util.function.Consumer;
-import kotlinx.coroutines.CoroutineDispatcher;
-
/**
* Mediates requests related to the keyguard. This includes queries about the
* state of the keyguard, power management events that effect whether the keyguard
@@ -3502,12 +3503,14 @@
+ " --> flags=0x" + Integer.toHexString(flags));
}
- try {
- mStatusBarService.disableForUser(flags, mStatusBarDisableToken,
- mContext.getPackageName(),
- mSelectedUserInteractor.getSelectedUserId(true));
- } catch (RemoteException e) {
- Log.d(TAG, "Failed to set disable flags: " + flags, e);
+ if (!SceneContainerFlag.isEnabled()) {
+ try {
+ mStatusBarService.disableForUser(flags, mStatusBarDisableToken,
+ mContext.getPackageName(),
+ mSelectedUserInteractor.getSelectedUserId(true));
+ } catch (RemoteException e) {
+ Log.d(TAG, "Failed to set disable flags: " + flags, e);
+ }
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinder.kt
index 6550937..f8063c9 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinder.kt
@@ -86,7 +86,10 @@
privateFlags =
WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY or
WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION
+ // Avoid announcing window title.
+ accessibilityTitle = " "
}
+
private var alternateBouncerView: ConstraintLayout? = null
override fun start() {
@@ -304,6 +307,7 @@
}
}
}
+
companion object {
private const val TAG = "AlternateBouncerViewBinder"
private const val swipeTag = "AlternateBouncer-SWIPE"
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDeviceManager.kt b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDeviceManager.kt
index 8b2f619..eab0d48 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDeviceManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDeviceManager.kt
@@ -354,10 +354,21 @@
activeDevice =
routingSession?.let {
+ val icon = if (it.selectedRoutes.size > 1) {
+ context.getDrawable(
+ com.android.settingslib.R.drawable.ic_media_group_device)
+ } else {
+ connectedDevice?.icon // Single route. We don't change the icon.
+ }
// For a remote session, always use the current device from
- // LocalMediaManager. Override with routing session name if available to
- // show dynamic group name.
- connectedDevice?.copy(name = it.name ?: connectedDevice.name)
+ // LocalMediaManager. Override with routing session information if
+ // available:
+ // - Name: To show the dynamic group name.
+ // - Icon: To show the group icon if there's more than one selected
+ // route.
+ connectedDevice?.copy(
+ name = it.name ?: connectedDevice.name,
+ icon = icon)
} ?: MediaDeviceData(
enabled = false,
icon = context.getDrawable(R.drawable.ic_media_home_devices),
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
index 1e86563..b48b409 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
@@ -85,6 +85,7 @@
import com.android.systemui.animation.DialogTransitionAnimator;
import com.android.systemui.broadcast.BroadcastSender;
import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.media.dialog.MediaItem.MediaItemType;
import com.android.systemui.media.nearby.NearbyMediaDevicesManager;
import com.android.systemui.monet.ColorScheme;
import com.android.systemui.plugins.ActivityStarter;
@@ -110,6 +111,7 @@
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Executor;
+import java.util.function.Function;
import java.util.stream.Collectors;
/**
@@ -661,28 +663,38 @@
/* connectedMediaDevice */ null,
devices,
needToHandleMutingExpectedDevice);
+ } else {
+ // selected device exist
+ return categorizeMediaItemsLocked(
+ connectedMediaDevice,
+ devices,
+ /* needToHandleMutingExpectedDevice */ false);
}
- // selected device exist
- return categorizeMediaItemsLocked(
- connectedMediaDevice,
- devices,
- /* needToHandleMutingExpectedDevice */ false);
}
// To keep the same list order
final List<MediaDevice> targetMediaDevices = new ArrayList<>();
final Map<Integer, MediaItem> dividerItems = new HashMap<>();
+
+ Map<String, MediaDevice> idToMediaDeviceMap =
+ devices.stream()
+ .collect(Collectors.toMap(MediaDevice::getId, Function.identity()));
+
for (MediaItem originalMediaItem : oldMediaItems) {
- for (MediaDevice newDevice : devices) {
- if (originalMediaItem.getMediaDevice().isPresent()
- && TextUtils.equals(originalMediaItem.getMediaDevice().get().getId(),
- newDevice.getId())) {
- targetMediaDevices.add(newDevice);
- break;
+ switch (originalMediaItem.getMediaItemType()) {
+ case MediaItemType.TYPE_GROUP_DIVIDER -> {
+ dividerItems.put(
+ oldMediaItems.indexOf(originalMediaItem), originalMediaItem);
}
- }
- if (originalMediaItem.getMediaItemType()
- == MediaItem.MediaItemType.TYPE_GROUP_DIVIDER) {
- dividerItems.put(oldMediaItems.indexOf(originalMediaItem), originalMediaItem);
+ case MediaItemType.TYPE_DEVICE -> {
+ String originalMediaItemId =
+ originalMediaItem.getMediaDevice().orElseThrow().getId();
+ if (idToMediaDeviceMap.containsKey(originalMediaItemId)) {
+ targetMediaDevices.add(idToMediaDeviceMap.get(originalMediaItemId));
+ }
+ }
+ case MediaItemType.TYPE_PAIR_NEW_DEVICE -> {
+ // Do nothing.
+ }
}
}
if (targetMediaDevices.size() != devices.size()) {
@@ -723,12 +735,10 @@
finalMediaItems.add(0, MediaItem.createDeviceMediaItem(device));
} else {
if (device.isSuggestedDevice() && !suggestedDeviceAdded) {
- attachGroupDivider(finalMediaItems, mContext.getString(
- R.string.media_output_group_title_suggested_device));
+ addSuggestedDeviceGroupDivider(finalMediaItems);
suggestedDeviceAdded = true;
} else if (!device.isSuggestedDevice() && !displayGroupAdded) {
- attachGroupDivider(finalMediaItems, mContext.getString(
- R.string.media_output_group_title_speakers_and_displays));
+ addSpeakersAndDisplaysGroupDivider(finalMediaItems);
displayGroupAdded = true;
}
finalMediaItems.add(MediaItem.createDeviceMediaItem(device));
@@ -738,8 +748,17 @@
return finalMediaItems;
}
- private void attachGroupDivider(List<MediaItem> mediaItems, String title) {
- mediaItems.add(MediaItem.createGroupDividerMediaItem(title));
+ private void addSuggestedDeviceGroupDivider(List<MediaItem> mediaItems) {
+ mediaItems.add(
+ MediaItem.createGroupDividerMediaItem(
+ mContext.getString(R.string.media_output_group_title_suggested_device)));
+ }
+
+ private void addSpeakersAndDisplaysGroupDivider(List<MediaItem> mediaItems) {
+ mediaItems.add(
+ MediaItem.createGroupDividerMediaItem(
+ mContext.getString(
+ R.string.media_output_group_title_speakers_and_displays)));
}
private void attachConnectNewDeviceItemIfNeeded(List<MediaItem> mediaItems) {
diff --git a/packages/SystemUI/src/com/android/systemui/scene/KeyguardlessSceneContainerFrameworkModule.kt b/packages/SystemUI/src/com/android/systemui/scene/KeyguardlessSceneContainerFrameworkModule.kt
index 323ca87..08462d7 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/KeyguardlessSceneContainerFrameworkModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/KeyguardlessSceneContainerFrameworkModule.kt
@@ -25,6 +25,7 @@
import com.android.systemui.scene.domain.resolver.QuickSettingsSceneFamilyResolverModule
import com.android.systemui.scene.domain.startable.SceneContainerStartable
import com.android.systemui.scene.domain.startable.ScrimStartable
+import com.android.systemui.scene.domain.startable.StatusBarStartable
import com.android.systemui.scene.shared.model.SceneContainerConfig
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.shade.shared.flag.DualShade
@@ -66,6 +67,11 @@
@Binds
@IntoMap
+ @ClassKey(StatusBarStartable::class)
+ fun statusBarStartable(impl: StatusBarStartable): CoreStartable
+
+ @Binds
+ @IntoMap
@ClassKey(WindowRootViewVisibilityInteractor::class)
fun bindWindowRootViewVisibilityInteractor(
impl: WindowRootViewVisibilityInteractor
diff --git a/packages/SystemUI/src/com/android/systemui/scene/SceneContainerFrameworkModule.kt b/packages/SystemUI/src/com/android/systemui/scene/SceneContainerFrameworkModule.kt
index 4691eba..17dc9a5 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/SceneContainerFrameworkModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/SceneContainerFrameworkModule.kt
@@ -26,6 +26,7 @@
import com.android.systemui.scene.domain.resolver.QuickSettingsSceneFamilyResolverModule
import com.android.systemui.scene.domain.startable.SceneContainerStartable
import com.android.systemui.scene.domain.startable.ScrimStartable
+import com.android.systemui.scene.domain.startable.StatusBarStartable
import com.android.systemui.scene.shared.model.SceneContainerConfig
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.shade.shared.flag.DualShade
@@ -72,6 +73,11 @@
@Binds
@IntoMap
+ @ClassKey(StatusBarStartable::class)
+ fun statusBarStartable(impl: StatusBarStartable): CoreStartable
+
+ @Binds
+ @IntoMap
@ClassKey(WindowRootViewVisibilityInteractor::class)
fun bindWindowRootViewVisibilityInteractor(
impl: WindowRootViewVisibilityInteractor
diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/StatusBarStartable.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/StatusBarStartable.kt
new file mode 100644
index 0000000..893f030
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/StatusBarStartable.kt
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+@file:OptIn(ExperimentalCoroutinesApi::class)
+
+package com.android.systemui.scene.domain.startable
+
+import android.annotation.SuppressLint
+import android.app.StatusBarManager
+import android.content.Context
+import android.os.Binder
+import android.os.IBinder
+import android.os.RemoteException
+import android.provider.DeviceConfig
+import android.util.Log
+import com.android.compose.animation.scene.SceneKey
+import com.android.internal.config.sysui.SystemUiDeviceConfigFlags
+import com.android.internal.statusbar.IStatusBarService
+import com.android.systemui.CoreStartable
+import com.android.systemui.authentication.domain.interactor.AuthenticationInteractor
+import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.deviceconfig.domain.interactor.DeviceConfigInteractor
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor
+import com.android.systemui.navigation.domain.interactor.NavigationInteractor
+import com.android.systemui.power.domain.interactor.PowerInteractor
+import com.android.systemui.power.shared.model.WakeSleepReason
+import com.android.systemui.power.shared.model.WakefulnessModel
+import com.android.systemui.scene.domain.interactor.SceneContainerOcclusionInteractor
+import com.android.systemui.scene.domain.interactor.SceneInteractor
+import com.android.systemui.scene.shared.flag.SceneContainerFlag
+import com.android.systemui.scene.shared.model.Scenes
+import com.android.systemui.user.domain.interactor.SelectedUserInteractor
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+
+@SysUISingleton
+class StatusBarStartable
+@Inject
+constructor(
+ @Application private val applicationScope: CoroutineScope,
+ @Background private val backgroundDispatcher: CoroutineDispatcher,
+ @Application private val applicationContext: Context,
+ private val selectedUserInteractor: SelectedUserInteractor,
+ private val sceneInteractor: SceneInteractor,
+ private val deviceEntryInteractor: DeviceEntryInteractor,
+ private val sceneContainerOcclusionInteractor: SceneContainerOcclusionInteractor,
+ private val deviceConfigInteractor: DeviceConfigInteractor,
+ private val navigationInteractor: NavigationInteractor,
+ private val authenticationInteractor: AuthenticationInteractor,
+ private val powerInteractor: PowerInteractor,
+ private val deviceEntryFaceAuthInteractor: DeviceEntryFaceAuthInteractor,
+ private val statusBarService: IStatusBarService,
+) : CoreStartable {
+
+ private val disableToken: IBinder = Binder()
+
+ override fun start() {
+ if (!SceneContainerFlag.isEnabled) {
+ return
+ }
+
+ applicationScope.launch {
+ combine(
+ selectedUserInteractor.selectedUser,
+ sceneInteractor.currentScene,
+ deviceEntryInteractor.isDeviceEntered,
+ sceneContainerOcclusionInteractor.invisibleDueToOcclusion,
+ deviceConfigInteractor.property(
+ namespace = DeviceConfig.NAMESPACE_SYSTEMUI,
+ name = SystemUiDeviceConfigFlags.NAV_BAR_HANDLE_SHOW_OVER_LOCKSCREEN,
+ default = true,
+ ),
+ navigationInteractor.isGesturalMode,
+ authenticationInteractor.authenticationMethod,
+ powerInteractor.detailedWakefulness,
+ ) { values ->
+ val selectedUserId = values[0] as Int
+ val currentScene = values[1] as SceneKey
+ val isDeviceEntered = values[2] as Boolean
+ val isOccluded = values[3] as Boolean
+ val isShowHomeOverLockscreen = values[4] as Boolean
+ val isGesturalMode = values[5] as Boolean
+ val authenticationMethod = values[6] as AuthenticationMethodModel
+ val wakefulnessModel = values[7] as WakefulnessModel
+
+ val isForceHideHomeAndRecents = currentScene == Scenes.Bouncer
+ val isKeyguardShowing = !isDeviceEntered
+ val isPowerGestureIntercepted =
+ with(wakefulnessModel) {
+ isAwake() &&
+ powerButtonLaunchGestureTriggered &&
+ lastSleepReason == WakeSleepReason.POWER_BUTTON
+ }
+
+ var flags = StatusBarManager.DISABLE_NONE
+
+ if (isForceHideHomeAndRecents || (isKeyguardShowing && !isOccluded)) {
+ if (!isShowHomeOverLockscreen || !isGesturalMode) {
+ flags = flags or StatusBarManager.DISABLE_HOME
+ }
+ flags = flags or StatusBarManager.DISABLE_RECENT
+ }
+
+ if (
+ isPowerGestureIntercepted &&
+ isOccluded &&
+ authenticationMethod.isSecure &&
+ deviceEntryFaceAuthInteractor.isFaceAuthEnabledAndEnrolled()
+ ) {
+ flags = flags or StatusBarManager.DISABLE_RECENT
+ }
+
+ selectedUserId to flags
+ }
+ .distinctUntilChanged()
+ .collect { (selectedUserId, flags) ->
+ @SuppressLint("WrongConstant", "NonInjectedService")
+ if (applicationContext.getSystemService(Context.STATUS_BAR_SERVICE) == null) {
+ Log.w(TAG, "Could not get status bar manager")
+ return@collect
+ }
+
+ withContext(backgroundDispatcher) {
+ try {
+ statusBarService.disableForUser(
+ flags,
+ disableToken,
+ applicationContext.packageName,
+ selectedUserId,
+ )
+ } catch (e: RemoteException) {
+ Log.d(TAG, "Failed to set disable flags: $flags", e)
+ }
+ }
+ }
+ }
+ }
+
+ override fun onBootCompleted() {
+ applicationScope.launch(backgroundDispatcher) {
+ try {
+ statusBarService.disableForUser(
+ StatusBarManager.DISABLE_NONE,
+ disableToken,
+ applicationContext.packageName,
+ selectedUserInteractor.getSelectedUserId(true),
+ )
+ } catch (e: RemoteException) {
+ Log.d(TAG, "Failed to clear flags", e)
+ }
+ }
+ }
+
+ companion object {
+ private const val TAG = "StatusBarStartable"
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
index 9624e0f..71fe371 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
@@ -3390,7 +3390,9 @@
/** Updates the views to the initial state for the fold to AOD animation. */
@Override
public void prepareFoldToAodAnimation() {
- if (!MigrateClocksToBlueprint.isEnabled()) {
+ if (MigrateClocksToBlueprint.isEnabled()) {
+ setDozing(true /* dozing */, false /* animate */);
+ } else {
// Force show AOD UI even if we are not locked
showAodUi();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/call/ui/viewmodel/CallChipViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/call/ui/viewmodel/CallChipViewModel.kt
index ad09aa3..ba3fde6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/call/ui/viewmodel/CallChipViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/call/ui/viewmodel/CallChipViewModel.kt
@@ -24,6 +24,7 @@
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.res.R
import com.android.systemui.statusbar.chips.call.domain.interactor.CallChipInteractor
+import com.android.systemui.statusbar.chips.ui.model.ColorsModel
import com.android.systemui.statusbar.chips.ui.model.OngoingActivityChipModel
import com.android.systemui.statusbar.chips.ui.view.ChipBackgroundContainer
import com.android.systemui.statusbar.chips.ui.viewmodel.OngoingActivityChipViewModel
@@ -65,6 +66,7 @@
com.android.internal.R.drawable.ic_phone,
contentDescription = null,
),
+ colors = ColorsModel.Themed,
startTimeMs = startTimeInElapsedRealtime,
) {
if (state.intent != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/casttootherdevice/ui/viewmodel/CastToOtherDeviceChipViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/casttootherdevice/ui/viewmodel/CastToOtherDeviceChipViewModel.kt
index a1678bf..53b1e75 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/casttootherdevice/ui/viewmodel/CastToOtherDeviceChipViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/casttootherdevice/ui/viewmodel/CastToOtherDeviceChipViewModel.kt
@@ -27,6 +27,7 @@
import com.android.systemui.statusbar.chips.mediaprojection.domain.interactor.MediaProjectionChipInteractor
import com.android.systemui.statusbar.chips.mediaprojection.domain.model.ProjectionChipModel
import com.android.systemui.statusbar.chips.mediaprojection.ui.view.EndMediaProjectionDialogHelper
+import com.android.systemui.statusbar.chips.ui.model.ColorsModel
import com.android.systemui.statusbar.chips.ui.model.OngoingActivityChipModel
import com.android.systemui.statusbar.chips.ui.viewmodel.OngoingActivityChipViewModel
import com.android.systemui.statusbar.chips.ui.viewmodel.OngoingActivityChipViewModel.Companion.createDialogLaunchOnClickListener
@@ -85,6 +86,7 @@
CAST_TO_OTHER_DEVICE_ICON,
ContentDescription.Resource(R.string.accessibility_casting),
),
+ colors = ColorsModel.Red,
// TODO(b/332662551): Maybe use a MediaProjection API to fetch this time.
startTimeMs = systemClock.elapsedRealtime(),
createDialogLaunchOnClickListener(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/screenrecord/ui/viewmodel/ScreenRecordChipViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/screenrecord/ui/viewmodel/ScreenRecordChipViewModel.kt
index d190cfd..9d54c75 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/screenrecord/ui/viewmodel/ScreenRecordChipViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/screenrecord/ui/viewmodel/ScreenRecordChipViewModel.kt
@@ -27,6 +27,7 @@
import com.android.systemui.statusbar.chips.screenrecord.domain.interactor.ScreenRecordChipInteractor
import com.android.systemui.statusbar.chips.screenrecord.domain.model.ScreenRecordChipModel
import com.android.systemui.statusbar.chips.screenrecord.ui.view.EndScreenRecordingDialogDelegate
+import com.android.systemui.statusbar.chips.ui.model.ColorsModel
import com.android.systemui.statusbar.chips.ui.model.OngoingActivityChipModel
import com.android.systemui.statusbar.chips.ui.viewmodel.OngoingActivityChipViewModel
import com.android.systemui.statusbar.chips.ui.viewmodel.OngoingActivityChipViewModel.Companion.createDialogLaunchOnClickListener
@@ -60,6 +61,7 @@
OngoingActivityChipModel.Shown(
// TODO(b/332662551): Also provide a content description.
icon = Icon.Resource(ICON, contentDescription = null),
+ colors = ColorsModel.Red,
startTimeMs = systemClock.elapsedRealtime(),
createDialogLaunchOnClickListener(
createDelegate(state.recordedTask),
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/sharetoapp/ui/viewmodel/ShareToAppChipViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/sharetoapp/ui/viewmodel/ShareToAppChipViewModel.kt
index dc41002..0c24a70 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/sharetoapp/ui/viewmodel/ShareToAppChipViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/sharetoapp/ui/viewmodel/ShareToAppChipViewModel.kt
@@ -26,6 +26,7 @@
import com.android.systemui.statusbar.chips.mediaprojection.domain.model.ProjectionChipModel
import com.android.systemui.statusbar.chips.mediaprojection.ui.view.EndMediaProjectionDialogHelper
import com.android.systemui.statusbar.chips.sharetoapp.ui.view.EndShareToAppDialogDelegate
+import com.android.systemui.statusbar.chips.ui.model.ColorsModel
import com.android.systemui.statusbar.chips.ui.model.OngoingActivityChipModel
import com.android.systemui.statusbar.chips.ui.viewmodel.OngoingActivityChipViewModel
import com.android.systemui.statusbar.chips.ui.viewmodel.OngoingActivityChipViewModel.Companion.createDialogLaunchOnClickListener
@@ -78,6 +79,7 @@
return OngoingActivityChipModel.Shown(
// TODO(b/332662551): Use the right content description.
icon = Icon.Resource(SHARE_TO_APP_ICON, contentDescription = null),
+ colors = ColorsModel.Red,
// TODO(b/332662551): Maybe use a MediaProjection API to fetch this time.
startTimeMs = systemClock.elapsedRealtime(),
createDialogLaunchOnClickListener(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/model/ColorsModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/model/ColorsModel.kt
new file mode 100644
index 0000000..b2140f7
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/model/ColorsModel.kt
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+package com.android.systemui.statusbar.chips.ui.model
+
+import android.content.Context
+import android.content.res.ColorStateList
+import androidx.annotation.ColorInt
+import com.android.settingslib.Utils
+import com.android.systemui.res.R
+
+/** Model representing how the chip in the status bar should be colored. */
+sealed interface ColorsModel {
+ /** The color for the background of the chip. */
+ fun background(context: Context): ColorStateList
+
+ /** The color for the text (and icon) on the chip. */
+ @ColorInt fun text(context: Context): Int
+
+ /** The chip should match the theme's primary color. */
+ data object Themed : ColorsModel {
+ override fun background(context: Context): ColorStateList =
+ Utils.getColorAttr(context, com.android.internal.R.attr.colorAccent)
+
+ override fun text(context: Context) =
+ Utils.getColorAttrDefaultColor(context, com.android.internal.R.attr.colorPrimary)
+ }
+
+ /** The chip should have a red background with white text. */
+ data object Red : ColorsModel {
+ override fun background(context: Context): ColorStateList =
+ ColorStateList.valueOf(context.getColor(R.color.GM2_red_600))
+
+ override fun text(context: Context) = context.getColor(android.R.color.white)
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/model/OngoingActivityChipModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/model/OngoingActivityChipModel.kt
index e63713b..4ea674a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/model/OngoingActivityChipModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/model/OngoingActivityChipModel.kt
@@ -28,6 +28,8 @@
data class Shown(
/** The icon to show on the chip. */
val icon: Icon,
+ /** What colors to use for the chip. */
+ val colors: ColorsModel,
/**
* The time this event started, used to show the timer.
*
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/VisualStabilityProvider.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/VisualStabilityProvider.kt
index 5adf31b..f166d32 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/VisualStabilityProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/VisualStabilityProvider.kt
@@ -13,12 +13,18 @@
/** The subset of active listeners which are temporary (will be removed after called) */
private val temporaryListeners = ArraySet<OnReorderingAllowedListener>()
+ private val banListeners = ListenerSet<OnReorderingBannedListener>()
+
var isReorderingAllowed = true
set(value) {
if (field != value) {
field = value
if (value) {
notifyReorderingAllowed()
+ } else {
+ banListeners.forEach { listener ->
+ listener.onReorderingBanned()
+ }
}
}
}
@@ -38,6 +44,10 @@
allListeners.addIfAbsent(listener)
}
+ fun addPersistentReorderingBannedListener(listener: OnReorderingBannedListener) {
+ banListeners.addIfAbsent(listener)
+ }
+
/** Add a listener which will be removed when it is called. */
fun addTemporaryReorderingAllowedListener(listener: OnReorderingAllowedListener) {
// Only add to the temporary set if it was added to the global set
@@ -57,3 +67,8 @@
fun interface OnReorderingAllowedListener {
fun onReorderingAllowed()
}
+
+fun interface OnReorderingBannedListener {
+ fun onReorderingBanned()
+}
+
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
index 62c139b..5c262f3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
@@ -1481,7 +1481,9 @@
return (v, event) -> {
mAutoHideController.checkUserAutoHide(event);
mRemoteInputManager.checkRemoteInputOutside(event);
- if (!MigrateClocksToBlueprint.isEnabled()) {
+ if (!MigrateClocksToBlueprint.isEnabled() || mQsController.isCustomizing()) {
+ // For migrate clocks flag, when the user is editing QS tiles they need to be able
+ // to touch outside the customizer to close it, such as on the status or nav bar.
mShadeController.onStatusBarTouch(event);
}
return getNotificationShadeWindowView().onTouchEvent(event);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
index 3925beb..c5dcb09 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
@@ -39,6 +39,7 @@
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.provider.OnReorderingAllowedListener;
+import com.android.systemui.statusbar.notification.collection.provider.OnReorderingBannedListener;
import com.android.systemui.statusbar.notification.collection.provider.VisualStabilityProvider;
import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
import com.android.systemui.statusbar.notification.data.repository.HeadsUpRepository;
@@ -86,7 +87,7 @@
private final List<OnHeadsUpPhoneListenerChange> mHeadsUpPhoneListeners = new ArrayList<>();
private final VisualStabilityProvider mVisualStabilityProvider;
- private final AvalancheController mAvalancheController;
+ private AvalancheController mAvalancheController;
// TODO(b/328393698) move the topHeadsUpRow logic to an interactor
private final MutableStateFlow<HeadsUpRowRepository> mTopHeadsUpRow =
@@ -175,6 +176,7 @@
javaAdapter.alwaysCollectFlow(shadeInteractor.isAnyExpanded(),
this::onShadeOrQsExpanded);
}
+ mVisualStabilityProvider.addPersistentReorderingBannedListener(mOnReorderingBannedListener);
}
public void setAnimationStateHandler(AnimationStateHandler handler) {
@@ -382,6 +384,8 @@
private final OnReorderingAllowedListener mOnReorderingAllowedListener = () -> {
mAnimationStateHandler.setHeadsUpGoingAwayAnimationsAllowed(false);
+ mAvalancheController.setEnableAtRuntime(true);
+
for (NotificationEntry entry : mEntriesToRemoveWhenReorderingAllowed) {
if (isHeadsUpEntry(entry.getKey())) {
// Maybe the heads-up was removed already
@@ -392,6 +396,28 @@
mAnimationStateHandler.setHeadsUpGoingAwayAnimationsAllowed(true);
};
+ private final OnReorderingBannedListener mOnReorderingBannedListener = () -> {
+ if (mAvalancheController != null) {
+ // Waiting HUNs in AvalancheController are still promoted to the HUN section and thus
+ // seen in open shade; clear them so we don't show them again when the shade closes and
+ // reordering is allowed again.
+ mAvalancheController.logDroppedHuns(mAvalancheController.getWaitingKeys().size());
+ mAvalancheController.clearNext();
+
+ // In open shade the first HUN is pinned, and visual stability logic prevents us from
+ // unpinning this first HUN as long as the shade remains open. AvalancheController only
+ // shows the next HUN when the currently showing HUN is unpinned, so we must disable
+ // throttling here so that the incoming HUN stream is not forever paused. This is reset
+ // when reorder becomes allowed.
+ mAvalancheController.setEnableAtRuntime(false);
+
+ // Note that we cannot do the above when
+ // 1) the remove runnable runs because its delay means it may not run before shade close
+ // 2) reordering is allowed again (when shade closes) because the HUN appear animation
+ // will have started by then
+ }
+ };
+
///////////////////////////////////////////////////////////////////////////////////////////////
// HeadsUpManager utility (protected) methods overrides:
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java
index 4b1ee58..0218784 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java
@@ -68,7 +68,7 @@
private final UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController;
private boolean mIsStatusBarExpanded = false;
- private boolean mIsIdleOnGone = false;
+ private boolean mIsIdleOnGone = true;
private boolean mShouldAdjustInsets = false;
private View mNotificationShadeWindowView;
private View mNotificationPanelView;
@@ -282,7 +282,7 @@
// since we don't want stray touches to go through the light reveal scrim to whatever is
// underneath.
return mIsStatusBarExpanded
- || !mIsIdleOnGone
+ || (SceneContainerFlag.isEnabled() && !mIsIdleOnGone)
|| mPrimaryBouncerInteractor.isShowing().getValue()
|| mAlternateBouncerInteractor.isVisibleState()
|| mUnlockedScreenOffAnimationController.isAnimationPlaying();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImpl.kt
index ec3af87..a7c5f78 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImpl.kt
@@ -345,32 +345,67 @@
orElse = flowOf(false),
retrySignal = telephonyProcessCrashedEvent,
)
- .stateIn(scope, SharingStarted.WhileSubscribed(), false)
+ .stateIn(scope, SharingStarted.Eagerly, false)
private fun satelliteProvisioned(sm: SupportedSatelliteManager): Flow<Boolean> =
conflatedCallbackFlow {
- val callback = SatelliteProvisionStateCallback { provisioned ->
- logBuffer.i {
- "onSatelliteProvisionStateChanged: " +
- if (provisioned) "provisioned" else "not provisioned"
+ // TODO(b/347992038): SatelliteManager should be sending the current provisioned
+ // status when we register a callback. Until then, we have to manually query here.
+
+ // First, check to see what the current status is, and send the result to the output
+ trySend(queryIsSatelliteProvisioned(sm))
+
+ val callback = SatelliteProvisionStateCallback { provisioned ->
+ logBuffer.i {
+ "onSatelliteProvisionStateChanged: " +
+ if (provisioned) "provisioned" else "not provisioned"
+ }
+ trySend(provisioned)
}
- trySend(provisioned)
- }
- var registered = false
- try {
- sm.registerForProvisionStateChanged(
- bgDispatcher.asExecutor(),
- callback,
- )
- registered = true
- } catch (e: Exception) {
- logBuffer.e("error registering for provisioning state callback", e)
- }
+ var registered = false
+ try {
+ logBuffer.i { "registerForProvisionStateChanged" }
+ sm.registerForProvisionStateChanged(
+ bgDispatcher.asExecutor(),
+ callback,
+ )
+ registered = true
+ } catch (e: Exception) {
+ logBuffer.e("error registering for provisioning state callback", e)
+ }
- awaitClose {
- if (registered) {
- sm.unregisterForProvisionStateChanged(callback)
+ awaitClose {
+ if (registered) {
+ sm.unregisterForProvisionStateChanged(callback)
+ }
+ }
+ }
+ .flowOn(bgDispatcher)
+
+ /** Check the current satellite provisioning status. */
+ private suspend fun queryIsSatelliteProvisioned(sm: SupportedSatelliteManager): Boolean =
+ withContext(bgDispatcher) {
+ suspendCancellableCoroutine { continuation ->
+ val receiver =
+ object : OutcomeReceiver<Boolean, SatelliteManager.SatelliteException> {
+ override fun onResult(result: Boolean) {
+ logBuffer.i { "requestIsProvisioned.onResult: $result" }
+ continuation.resume(result)
+ }
+
+ override fun onError(exception: SatelliteManager.SatelliteException) {
+ logBuffer.e("requestIsProvisioned.onError:", exception)
+ continuation.resume(false)
+ }
+ }
+
+ logBuffer.i { "Query for current satellite provisioned state." }
+ try {
+ sm.requestIsProvisioned(bgDispatcher.asExecutor(), receiver)
+ } catch (e: Exception) {
+ logBuffer.e("Exception while calling SatelliteManager.requestIsProvisioned:", e)
+ continuation.resume(false)
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/binder/CollapsedStatusBarViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/binder/CollapsedStatusBarViewBinder.kt
index 7644653..d607ce0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/binder/CollapsedStatusBarViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/binder/CollapsedStatusBarViewBinder.kt
@@ -18,6 +18,8 @@
import android.animation.Animator
import android.animation.AnimatorListenerAdapter
+import android.content.res.ColorStateList
+import android.graphics.drawable.GradientDrawable
import android.view.View
import android.widget.ImageView
import androidx.lifecycle.Lifecycle
@@ -29,6 +31,7 @@
import com.android.systemui.res.R
import com.android.systemui.statusbar.chips.ui.binder.ChipChronometerBinder
import com.android.systemui.statusbar.chips.ui.model.OngoingActivityChipModel
+import com.android.systemui.statusbar.chips.ui.view.ChipBackgroundContainer
import com.android.systemui.statusbar.chips.ui.view.ChipChronometer
import com.android.systemui.statusbar.notification.shared.NotificationsLiveDataStoreRefactor
import com.android.systemui.statusbar.pipeline.shared.ui.viewmodel.CollapsedStatusBarViewModel
@@ -84,18 +87,31 @@
if (Flags.statusBarScreenSharingChips()) {
val chipView: View = view.requireViewById(R.id.ongoing_activity_chip)
+ val chipContext = chipView.context
val chipIconView: ImageView =
chipView.requireViewById(R.id.ongoing_activity_chip_icon)
val chipTimeView: ChipChronometer =
chipView.requireViewById(R.id.ongoing_activity_chip_time)
+ val chipBackgroundView =
+ chipView.requireViewById<ChipBackgroundContainer>(
+ R.id.ongoing_activity_chip_background
+ )
launch {
viewModel.ongoingActivityChip.collect { chipModel ->
when (chipModel) {
is OngoingActivityChipModel.Shown -> {
+ // Data
IconViewBinder.bind(chipModel.icon, chipIconView)
ChipChronometerBinder.bind(chipModel.startTimeMs, chipTimeView)
chipView.setOnClickListener(chipModel.onClickListener)
+ // Colors
+ val textColor = chipModel.colors.text(chipContext)
+ chipIconView.imageTintList = ColorStateList.valueOf(textColor)
+ chipTimeView.setTextColor(textColor)
+ (chipBackgroundView.background as GradientDrawable).color =
+ chipModel.colors.background(chipContext)
+
listener.onOngoingActivityStatusChanged(
hasOngoingActivity = true
)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AvalancheController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AvalancheController.kt
index 32774e0..dbe54f3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AvalancheController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AvalancheController.kt
@@ -39,6 +39,7 @@
private val tag = "AvalancheController"
private val debug = Compile.IS_DEBUG && Log.isLoggable(tag, Log.DEBUG)
+ var enableAtRuntime = true
// HUN showing right now, in the floating state where full shade is hidden, on launcher or AOD
@VisibleForTesting var headsUpEntryShowing: HeadsUpEntry? = null
@@ -81,13 +82,17 @@
dumpManager.registerNormalDumpable(tag, /* module */ this)
}
+ fun isEnabled() : Boolean {
+ return NotificationThrottleHun.isEnabled && enableAtRuntime
+ }
+
fun getShowingHunKey(): String {
return getKey(headsUpEntryShowing)
}
/** Run or delay Runnable for given HeadsUpEntry */
fun update(entry: HeadsUpEntry?, runnable: Runnable, label: String) {
- if (!NotificationThrottleHun.isEnabled) {
+ if (!isEnabled()) {
runnable.run()
return
}
@@ -143,7 +148,7 @@
* all Runnables associated with that entry.
*/
fun delete(entry: HeadsUpEntry?, runnable: Runnable, label: String) {
- if (!NotificationThrottleHun.isEnabled) {
+ if (!isEnabled()) {
runnable.run()
return
}
@@ -184,7 +189,7 @@
* BaseHeadsUpManager.HeadsUpEntry.calculateFinishTime to shorten display duration.
*/
fun getDurationMs(entry: HeadsUpEntry, autoDismissMs: Int): Int {
- if (!NotificationThrottleHun.isEnabled) {
+ if (!isEnabled()) {
// Use default duration, like we did before AvalancheController existed
return autoDismissMs
}
@@ -233,7 +238,7 @@
/** Return true if entry is waiting to show. */
fun isWaiting(key: String): Boolean {
- if (!NotificationThrottleHun.isEnabled) {
+ if (!isEnabled()) {
return false
}
for (entry in nextMap.keys) {
@@ -246,7 +251,7 @@
/** Return list of keys for huns waiting */
fun getWaitingKeys(): MutableList<String> {
- if (!NotificationThrottleHun.isEnabled) {
+ if (!isEnabled()) {
return mutableListOf()
}
val keyList = mutableListOf<String>()
@@ -257,7 +262,7 @@
}
fun getWaitingEntry(key: String): HeadsUpEntry? {
- if (!NotificationThrottleHun.isEnabled) {
+ if (!isEnabled()) {
return null
}
for (headsUpEntry in nextMap.keys) {
@@ -269,7 +274,7 @@
}
fun getWaitingEntryList(): List<HeadsUpEntry> {
- if (!NotificationThrottleHun.isEnabled) {
+ if (!isEnabled()) {
return mutableListOf()
}
return nextMap.keys.toList()
@@ -310,11 +315,7 @@
// Remove runnable labels for dropped huns
val listToDrop = nextList.subList(1, nextList.size)
-
- // Log dropped HUNs
- for (e in listToDrop) {
- uiEventLogger.log(ThrottleEvent.AVALANCHE_THROTTLING_HUN_DROPPED)
- }
+ logDroppedHuns(listToDrop.size)
if (debug) {
// Clear runnable labels
@@ -331,6 +332,12 @@
showNow(headsUpEntryShowing!!, headsUpEntryShowingRunnableList)
}
+ fun logDroppedHuns(numDropped: Int) {
+ for (n in 1..numDropped) {
+ uiEventLogger.log(ThrottleEvent.AVALANCHE_THROTTLING_HUN_DROPPED)
+ }
+ }
+
fun clearNext() {
nextList.clear()
nextMap.clear()
diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/domain/interactor/TouchpadGesturesInteractor.kt b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/domain/interactor/TouchpadGesturesInteractor.kt
new file mode 100644
index 0000000..b6c2ae7
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/domain/interactor/TouchpadGesturesInteractor.kt
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+package com.android.systemui.touchpad.tutorial.domain.interactor
+
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.model.SysUiState
+import com.android.systemui.settings.DisplayTracker
+import com.android.systemui.shared.system.QuickStepContract
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.launch
+
+@SysUISingleton
+class TouchpadGesturesInteractor
+@Inject
+constructor(
+ private val sysUiState: SysUiState,
+ private val displayTracker: DisplayTracker,
+ @Background private val backgroundScope: CoroutineScope
+) {
+ fun disableGestures() {
+ setGesturesState(disabled = true)
+ }
+
+ fun enableGestures() {
+ setGesturesState(disabled = false)
+ }
+
+ private fun setGesturesState(disabled: Boolean) {
+ backgroundScope.launch {
+ sysUiState
+ .setFlag(QuickStepContract.SYSUI_STATE_TOUCHPAD_GESTURES_DISABLED, disabled)
+ .commitUpdate(displayTracker.defaultDisplayId)
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/TouchpadTutorialViewModel.kt b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/TouchpadTutorialViewModel.kt
index 11740a8..9e6553a 100644
--- a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/TouchpadTutorialViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/TouchpadTutorialViewModel.kt
@@ -18,11 +18,13 @@
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
+import com.android.systemui.touchpad.tutorial.domain.interactor.TouchpadGesturesInteractor
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import javax.inject.Inject
-class TouchpadTutorialViewModel : ViewModel() {
+class TouchpadTutorialViewModel(private val gesturesInteractor: TouchpadGesturesInteractor) :
+ ViewModel() {
private val _screen = MutableStateFlow(Screen.TUTORIAL_SELECTION)
val screen: StateFlow<Screen> = _screen
@@ -31,11 +33,20 @@
_screen.value = screen
}
- class Factory @Inject constructor() : ViewModelProvider.Factory {
+ fun onOpened() {
+ gesturesInteractor.disableGestures()
+ }
+
+ fun onClosed() {
+ gesturesInteractor.enableGestures()
+ }
+
+ class Factory @Inject constructor(private val gesturesInteractor: TouchpadGesturesInteractor) :
+ ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(modelClass: Class<T>): T {
- return TouchpadTutorialViewModel() as T
+ return TouchpadTutorialViewModel(gesturesInteractor) as T
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/view/BackGestureTutorialScreen.kt b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/view/BackGestureTutorialScreen.kt
new file mode 100644
index 0000000..2460761c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/view/BackGestureTutorialScreen.kt
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+package com.android.systemui.touchpad.tutorial.ui.view
+
+import androidx.activity.compose.BackHandler
+import androidx.compose.foundation.Image
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.width
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.unit.dp
+import com.android.systemui.res.R
+
+@Composable
+fun BackGestureTutorialScreen(
+ onDoneButtonClicked: () -> Unit,
+ onBack: () -> Unit,
+ modifier: Modifier = Modifier,
+) {
+ BackHandler { onBack() }
+ Column(
+ verticalArrangement = Arrangement.Center,
+ modifier =
+ modifier
+ .background(color = MaterialTheme.colorScheme.surfaceContainer)
+ .padding(start = 48.dp, top = 124.dp, end = 48.dp, bottom = 48.dp)
+ .fillMaxSize()
+ ) {
+ Row(modifier = Modifier.fillMaxWidth().weight(1f)) {
+ TutorialDescription(modifier = Modifier.weight(1f))
+ Spacer(modifier = Modifier.width(76.dp))
+ TutorialAnimation(modifier = Modifier.weight(1f).padding(top = 24.dp))
+ }
+ DoneButton(onDoneButtonClicked = onDoneButtonClicked)
+ }
+}
+
+@Composable
+fun TutorialDescription(modifier: Modifier = Modifier) {
+ Column(verticalArrangement = Arrangement.Top, modifier = modifier) {
+ Text(
+ text = stringResource(id = R.string.touchpad_back_gesture_action_title),
+ style = MaterialTheme.typography.displayLarge
+ )
+ Spacer(modifier = Modifier.height(16.dp))
+ Text(
+ text = stringResource(id = R.string.touchpad_back_gesture_guidance),
+ style = MaterialTheme.typography.bodyLarge
+ )
+ }
+}
+
+@Composable
+fun TutorialAnimation(modifier: Modifier = Modifier) {
+ // below are just placeholder images, will be substituted by animations soon
+ Column(modifier = modifier.fillMaxWidth()) {
+ Image(
+ painter = painterResource(id = R.drawable.placeholder_touchpad_tablet_back_gesture),
+ contentDescription =
+ stringResource(
+ id = R.string.touchpad_back_gesture_screen_animation_content_description
+ ),
+ modifier = Modifier.fillMaxWidth()
+ )
+ Spacer(modifier = Modifier.height(24.dp))
+ Image(
+ painter = painterResource(id = R.drawable.placeholder_touchpad_back_gesture),
+ contentDescription =
+ stringResource(id = R.string.touchpad_back_gesture_animation_content_description),
+ modifier = Modifier.fillMaxWidth()
+ )
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/view/TouchpadTutorialActivity.kt b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/view/TouchpadTutorialActivity.kt
index b7629c7..0c5c187 100644
--- a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/view/TouchpadTutorialActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/view/TouchpadTutorialActivity.kt
@@ -20,14 +20,13 @@
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
+import androidx.activity.viewModels
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.lifecycle.Lifecycle.State.STARTED
-import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.viewmodel.compose.viewModel
import com.android.compose.theme.PlatformTheme
-import com.android.systemui.touchpad.tutorial.ui.BackGestureTutorialViewModel
import com.android.systemui.touchpad.tutorial.ui.GestureViewModelFactory
import com.android.systemui.touchpad.tutorial.ui.HomeGestureTutorialViewModel
import com.android.systemui.touchpad.tutorial.ui.Screen.BACK_GESTURE
@@ -42,18 +41,27 @@
private val viewModelFactory: TouchpadTutorialViewModel.Factory,
) : ComponentActivity() {
+ private val vm by viewModels<TouchpadTutorialViewModel>(factoryProducer = { viewModelFactory })
+
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
- setContent {
- PlatformTheme { TouchpadTutorialScreen(viewModelFactory, closeTutorial = { finish() }) }
- }
+ setContent { PlatformTheme { TouchpadTutorialScreen(vm) { finish() } } }
+ }
+
+ override fun onResume() {
+ super.onResume()
+ vm.onOpened()
+ }
+
+ override fun onPause() {
+ super.onPause()
+ vm.onClosed()
}
}
@Composable
-fun TouchpadTutorialScreen(viewModelFactory: ViewModelProvider.Factory, closeTutorial: () -> Unit) {
- val vm = viewModel<TouchpadTutorialViewModel>(factory = viewModelFactory)
+fun TouchpadTutorialScreen(vm: TouchpadTutorialViewModel, closeTutorial: () -> Unit) {
val activeScreen by vm.screen.collectAsStateWithLifecycle(STARTED)
when (activeScreen) {
TUTORIAL_SELECTION ->
@@ -63,17 +71,16 @@
onActionKeyTutorialClicked = {},
onDoneButtonClicked = closeTutorial
)
- BACK_GESTURE -> BackGestureTutorialScreen()
+ BACK_GESTURE ->
+ BackGestureTutorialScreen(
+ onDoneButtonClicked = { vm.goTo(TUTORIAL_SELECTION) },
+ onBack = { vm.goTo(TUTORIAL_SELECTION) }
+ )
HOME_GESTURE -> HomeGestureTutorialScreen()
}
}
@Composable
-fun BackGestureTutorialScreen() {
- val vm = viewModel<BackGestureTutorialViewModel>(factory = GestureViewModelFactory())
-}
-
-@Composable
fun HomeGestureTutorialScreen() {
val vm = viewModel<HomeGestureTutorialViewModel>(factory = GestureViewModelFactory())
}
diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/view/TutorialComponents.kt b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/view/TutorialComponents.kt
new file mode 100644
index 0000000..16fa91d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/view/TutorialComponents.kt
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+package com.android.systemui.touchpad.tutorial.ui.view
+
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.material3.Button
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.stringResource
+import com.android.systemui.res.R
+
+@Composable
+fun DoneButton(onDoneButtonClicked: () -> Unit, modifier: Modifier = Modifier) {
+ Row(
+ horizontalArrangement = Arrangement.End,
+ verticalAlignment = Alignment.CenterVertically,
+ modifier = modifier.fillMaxWidth()
+ ) {
+ Button(onClick = onDoneButtonClicked) {
+ Text(stringResource(R.string.touchpad_tutorial_done_button))
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/view/TutorialSelectionScreen.kt b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/view/TutorialSelectionScreen.kt
index 532eb1b..877bbe1 100644
--- a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/view/TutorialSelectionScreen.kt
+++ b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/view/TutorialSelectionScreen.kt
@@ -22,7 +22,6 @@
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxSize
-import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Button
@@ -114,16 +113,3 @@
Text(text = text, style = MaterialTheme.typography.headlineLarge)
}
}
-
-@Composable
-private fun DoneButton(onDoneButtonClicked: () -> Unit, modifier: Modifier = Modifier) {
- Row(
- horizontalArrangement = Arrangement.End,
- verticalAlignment = Alignment.CenterVertically,
- modifier = modifier.fillMaxWidth()
- ) {
- Button(onClick = onDoneButtonClicked) {
- Text(stringResource(R.string.touchpad_tutorial_done_button))
- }
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/unfold/FoldLightRevealOverlayAnimation.kt b/packages/SystemUI/src/com/android/systemui/unfold/FoldLightRevealOverlayAnimation.kt
index aea739d..9faa84e 100644
--- a/packages/SystemUI/src/com/android/systemui/unfold/FoldLightRevealOverlayAnimation.kt
+++ b/packages/SystemUI/src/com/android/systemui/unfold/FoldLightRevealOverlayAnimation.kt
@@ -22,9 +22,12 @@
import android.annotation.BinderThread
import android.os.SystemProperties
import android.util.Log
+import android.view.View
import android.view.animation.DecelerateInterpolator
import com.android.app.tracing.TraceUtils.traceAsync
import com.android.internal.foldables.FoldLockSettingAvailabilityProvider
+import com.android.internal.jank.Cuj.CUJ_FOLD_ANIM
+import com.android.internal.jank.InteractionJankMonitor
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.display.data.repository.DeviceStateRepository
import com.android.systemui.power.domain.interactor.PowerInteractor
@@ -65,7 +68,8 @@
@Background private val applicationScope: CoroutineScope,
private val animationStatusRepository: AnimationStatusRepository,
private val controllerFactory: FullscreenLightRevealAnimationController.Factory,
- private val foldLockSettingAvailabilityProvider: FoldLockSettingAvailabilityProvider
+ private val foldLockSettingAvailabilityProvider: FoldLockSettingAvailabilityProvider,
+ private val interactionJankMonitor: InteractionJankMonitor
) : FullscreenLightRevealAnimation {
private val revealProgressValueAnimator: ValueAnimator =
@@ -149,13 +153,23 @@
private suspend fun waitForGoToSleep() =
traceAsync(TAG, "waitForGoToSleep()") { powerInteractor.isAsleep.filter { it }.first() }
- private suspend fun playFoldLightRevealOverlayAnimation() {
- revealProgressValueAnimator.duration = ANIMATION_DURATION
- revealProgressValueAnimator.interpolator = DecelerateInterpolator()
- revealProgressValueAnimator.addUpdateListener { animation ->
- controller.updateRevealAmount(animation.animatedFraction)
+ private suspend fun playFoldLightRevealOverlayAnimation() =
+ trackCuj(CUJ_FOLD_ANIM, controller.scrimView) {
+ revealProgressValueAnimator.duration = ANIMATION_DURATION
+ revealProgressValueAnimator.interpolator = DecelerateInterpolator()
+ revealProgressValueAnimator.addUpdateListener { animation ->
+ controller.updateRevealAmount(animation.animatedFraction)
+ }
+ revealProgressValueAnimator.startAndAwaitCompletion()
}
- revealProgressValueAnimator.startAndAwaitCompletion()
+
+ private suspend fun trackCuj(cuj: Int, view: View?, block: suspend () -> Unit) {
+ view?.let { interactionJankMonitor.begin(it, cuj) }
+ try {
+ block()
+ } finally {
+ if (view != null) interactionJankMonitor.end(cuj)
+ }
}
private suspend fun ValueAnimator.startAndAwaitCompletion(): Unit =
diff --git a/packages/SystemUI/src/com/android/systemui/unfold/FullscreenLightRevealAnimation.kt b/packages/SystemUI/src/com/android/systemui/unfold/FullscreenLightRevealAnimation.kt
index 135edfc..f368cac 100644
--- a/packages/SystemUI/src/com/android/systemui/unfold/FullscreenLightRevealAnimation.kt
+++ b/packages/SystemUI/src/com/android/systemui/unfold/FullscreenLightRevealAnimation.kt
@@ -81,7 +81,10 @@
private var currentRotation: Int = context.display.rotation
private var root: SurfaceControlViewHost? = null
- private var scrimView: LightRevealScrim? = null
+
+ /** The scrim view that is used to reveal the screen. */
+ var scrimView: LightRevealScrim? = null
+ private set
private val rotationWatcher = RotationWatcher()
private val internalDisplayInfos: List<DisplayInfo> =
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinderTest.kt
index 4238254..7fa165c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinderTest.kt
@@ -73,6 +73,7 @@
import org.mockito.Mockito.`when`
import org.mockito.junit.MockitoJUnit
import org.mockito.junit.MockitoRule
+import org.mockito.kotlin.argumentCaptor
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
@@ -218,6 +219,13 @@
verify(kosmos.windowManager).addView(any(), any())
+ var viewCaptor = argumentCaptor<View>()
+ verify(kosmos.windowManager).addView(viewCaptor.capture(), any())
+ verify(viewCaptor.firstValue)
+ .announceForAccessibility(
+ mContext.getText(R.string.accessibility_side_fingerprint_indicator_label)
+ )
+
// Hide alternate bouncer
kosmos.keyguardBouncerRepository.setAlternateVisible(false)
runCurrent()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/call/ui/viewmodel/CallChipViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/call/ui/viewmodel/CallChipViewModelTest.kt
index 6cac30a..3606b1b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/call/ui/viewmodel/CallChipViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/call/ui/viewmodel/CallChipViewModelTest.kt
@@ -26,6 +26,7 @@
import com.android.systemui.kosmos.testScope
import com.android.systemui.plugins.activityStarter
import com.android.systemui.res.R
+import com.android.systemui.statusbar.chips.ui.model.ColorsModel
import com.android.systemui.statusbar.chips.ui.model.OngoingActivityChipModel
import com.android.systemui.statusbar.chips.ui.view.ChipBackgroundContainer
import com.android.systemui.statusbar.phone.ongoingcall.data.repository.ongoingCallRepository
@@ -95,7 +96,7 @@
}
@Test
- fun chip_inCall_iconIsPhone() =
+ fun chip_iconIsPhone() =
testScope.runTest {
val latest by collectLastValue(underTest.chip)
@@ -106,6 +107,17 @@
}
@Test
+ fun chip_colorsAreThemed() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.chip)
+
+ repo.setOngoingCallState(OngoingCallModel.InCall(startTimeMs = 1000, intent = null))
+
+ assertThat((latest as OngoingActivityChipModel.Shown).colors)
+ .isEqualTo(ColorsModel.Themed)
+ }
+
+ @Test
fun chip_resetsCorrectly() =
testScope.runTest {
val latest by collectLastValue(underTest.chip)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/casttootherdevice/ui/viewmodel/CastToOtherDeviceChipViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/casttootherdevice/ui/viewmodel/CastToOtherDeviceChipViewModelTest.kt
index 93d781f..d7935e5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/casttootherdevice/ui/viewmodel/CastToOtherDeviceChipViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/casttootherdevice/ui/viewmodel/CastToOtherDeviceChipViewModelTest.kt
@@ -33,6 +33,7 @@
import com.android.systemui.statusbar.chips.mediaprojection.domain.interactor.MediaProjectionChipInteractorTest.Companion.CAST_TO_OTHER_DEVICES_PACKAGE
import com.android.systemui.statusbar.chips.mediaprojection.domain.interactor.MediaProjectionChipInteractorTest.Companion.NORMAL_PACKAGE
import com.android.systemui.statusbar.chips.mediaprojection.domain.interactor.MediaProjectionChipInteractorTest.Companion.setUpPackageManagerForMediaProjection
+import com.android.systemui.statusbar.chips.ui.model.ColorsModel
import com.android.systemui.statusbar.chips.ui.model.OngoingActivityChipModel
import com.android.systemui.statusbar.chips.ui.view.ChipBackgroundContainer
import com.android.systemui.statusbar.phone.SystemUIDialog
@@ -119,6 +120,17 @@
}
@Test
+ fun chip_colorsAreRed() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.chip)
+
+ mediaProjectionRepo.mediaProjectionState.value =
+ MediaProjectionState.Projecting.EntireScreen(CAST_TO_OTHER_DEVICES_PACKAGE)
+
+ assertThat((latest as OngoingActivityChipModel.Shown).colors).isEqualTo(ColorsModel.Red)
+ }
+
+ @Test
fun chip_singleTaskState_normalPackage_isHidden() =
testScope.runTest {
val latest by collectLastValue(underTest.chip)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/screenrecord/ui/viewmodel/ScreenRecordChipViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/screenrecord/ui/viewmodel/ScreenRecordChipViewModelTest.kt
index 45044f7..fdf0e5d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/screenrecord/ui/viewmodel/ScreenRecordChipViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/screenrecord/ui/viewmodel/ScreenRecordChipViewModelTest.kt
@@ -32,6 +32,7 @@
import com.android.systemui.screenrecord.data.model.ScreenRecordModel
import com.android.systemui.screenrecord.data.repository.screenRecordRepository
import com.android.systemui.statusbar.chips.screenrecord.ui.view.EndScreenRecordingDialogDelegate
+import com.android.systemui.statusbar.chips.ui.model.ColorsModel
import com.android.systemui.statusbar.chips.ui.model.OngoingActivityChipModel
import com.android.systemui.statusbar.chips.ui.view.ChipBackgroundContainer
import com.android.systemui.statusbar.phone.SystemUIDialog
@@ -109,6 +110,16 @@
}
@Test
+ fun chip_colorsAreRed() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.chip)
+
+ screenRecordRepo.screenRecordState.value = ScreenRecordModel.Recording
+
+ assertThat((latest as OngoingActivityChipModel.Shown).colors).isEqualTo(ColorsModel.Red)
+ }
+
+ @Test
fun chip_timeResetsOnEachNewRecording() =
testScope.runTest {
val latest by collectLastValue(underTest.chip)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/sharetoapp/ui/viewmodel/ShareToAppChipViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/sharetoapp/ui/viewmodel/ShareToAppChipViewModelTest.kt
index 9aef526..8ea3f4a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/sharetoapp/ui/viewmodel/ShareToAppChipViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/sharetoapp/ui/viewmodel/ShareToAppChipViewModelTest.kt
@@ -33,6 +33,7 @@
import com.android.systemui.statusbar.chips.mediaprojection.domain.interactor.MediaProjectionChipInteractorTest.Companion.NORMAL_PACKAGE
import com.android.systemui.statusbar.chips.mediaprojection.domain.interactor.MediaProjectionChipInteractorTest.Companion.setUpPackageManagerForMediaProjection
import com.android.systemui.statusbar.chips.sharetoapp.ui.view.EndShareToAppDialogDelegate
+import com.android.systemui.statusbar.chips.ui.model.ColorsModel
import com.android.systemui.statusbar.chips.ui.model.OngoingActivityChipModel
import com.android.systemui.statusbar.chips.ui.view.ChipBackgroundContainer
import com.android.systemui.statusbar.phone.SystemUIDialog
@@ -144,6 +145,17 @@
}
@Test
+ fun chip_colorsAreRed() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.chip)
+
+ mediaProjectionRepo.mediaProjectionState.value =
+ MediaProjectionState.Projecting.EntireScreen(NORMAL_PACKAGE)
+
+ assertThat((latest as OngoingActivityChipModel.Shown).colors).isEqualTo(ColorsModel.Red)
+ }
+
+ @Test
fun chip_timeResetsOnEachNewShare() =
testScope.runTest {
val latest by collectLastValue(underTest.chip)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImplTest.kt
index 890a2e4..f7ff568 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImplTest.kt
@@ -32,6 +32,7 @@
import android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_OFF
import android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_UNAVAILABLE
import android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_UNKNOWN
+import android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_ERROR
import android.telephony.satellite.SatelliteManager.SatelliteException
import android.telephony.satellite.SatelliteModemStateCallback
import android.telephony.satellite.SatelliteProvisionStateCallback
@@ -62,6 +63,7 @@
import org.junit.Before
import org.mockito.Mock
import org.mockito.Mockito
+import org.mockito.Mockito.atLeastOnce
import org.mockito.Mockito.doAnswer
import org.mockito.Mockito.never
import org.mockito.Mockito.times
@@ -354,13 +356,142 @@
}
@Test
- fun satelliteProvisioned_supported_tracksCallback() =
+ fun satelliteProvisioned_returnsException_defaultsToFalse() =
+ testScope.runTest {
+ // GIVEN satellite is supported on device
+ doAnswer {
+ val callback: OutcomeReceiver<Boolean, SatelliteException> =
+ it.getArgument(1) as OutcomeReceiver<Boolean, SatelliteException>
+ callback.onResult(true)
+ }
+ .whenever(satelliteManager)
+ .requestIsSupported(any(), any())
+
+ // GIVEN satellite returns an error when asked if provisioned
+ doAnswer {
+ val receiver = it.arguments[1] as OutcomeReceiver<Boolean, SatelliteException>
+ receiver.onError(SatelliteException(SATELLITE_RESULT_ERROR))
+ null
+ }
+ .whenever(satelliteManager)
+ .requestIsProvisioned(
+ any(),
+ any<OutcomeReceiver<Boolean, SatelliteException>>()
+ )
+
+ // GIVEN we've been up long enough to start querying
+ systemClock.setUptimeMillis(Process.getStartUptimeMillis() + MIN_UPTIME)
+
+ underTest =
+ DeviceBasedSatelliteRepositoryImpl(
+ Optional.of(satelliteManager),
+ telephonyManager,
+ dispatcher,
+ testScope.backgroundScope,
+ logBuffer = FakeLogBuffer.Factory.create(),
+ verboseLogBuffer = FakeLogBuffer.Factory.create(),
+ systemClock,
+ )
+
+ // WHEN we try to check for provisioned status
+ val provisioned by collectLastValue(underTest.isSatelliteProvisioned)
+
+ // THEN well, first we don't throw...
+ // AND THEN we assume that it's not provisioned
+ assertThat(provisioned).isFalse()
+ }
+
+ @Test
+ fun satelliteProvisioned_throwsWhenQuerying_defaultsToFalse() =
+ testScope.runTest {
+ // GIVEN satellite is supported on device
+ doAnswer {
+ val callback: OutcomeReceiver<Boolean, SatelliteException> =
+ it.getArgument(1) as OutcomeReceiver<Boolean, SatelliteException>
+ callback.onResult(true)
+ }
+ .whenever(satelliteManager)
+ .requestIsSupported(any(), any())
+
+ // GIVEN satellite throws when asked if provisioned
+ whenever(satelliteManager.requestIsProvisioned(any(), any()))
+ .thenThrow(SecurityException())
+
+ // GIVEN we've been up long enough to start querying
+ systemClock.setUptimeMillis(Process.getStartUptimeMillis() + MIN_UPTIME)
+
+ underTest =
+ DeviceBasedSatelliteRepositoryImpl(
+ Optional.of(satelliteManager),
+ telephonyManager,
+ dispatcher,
+ testScope.backgroundScope,
+ logBuffer = FakeLogBuffer.Factory.create(),
+ verboseLogBuffer = FakeLogBuffer.Factory.create(),
+ systemClock,
+ )
+
+ // WHEN we try to check for provisioned status
+ val provisioned by collectLastValue(underTest.isSatelliteProvisioned)
+
+ // THEN well, first we don't throw...
+ // AND THEN we assume that it's not provisioned
+ assertThat(provisioned).isFalse()
+ }
+
+ @Test
+ fun satelliteProvisioned_supported_provisioned_queriesInitialStateBeforeCallbacks() =
+ testScope.runTest {
+ // GIVEN satellite is supported, and provisioned
+ setUpRepo(
+ uptime = MIN_UPTIME,
+ satMan = satelliteManager,
+ satelliteSupported = true,
+ initialSatelliteIsProvisioned = true,
+ )
+
+ val provisioned by collectLastValue(underTest.isSatelliteProvisioned)
+
+ runCurrent()
+
+ // THEN the current state is requested
+ verify(satelliteManager, atLeastOnce()).requestIsProvisioned(any(), any())
+
+ // AND the state is correct
+ assertThat(provisioned).isTrue()
+ }
+
+ @Test
+ fun satelliteProvisioned_supported_notProvisioned_queriesInitialStateBeforeCallbacks() =
+ testScope.runTest {
+ // GIVEN satellite is supported, and provisioned
+ setUpRepo(
+ uptime = MIN_UPTIME,
+ satMan = satelliteManager,
+ satelliteSupported = true,
+ initialSatelliteIsProvisioned = false,
+ )
+
+ val provisioned by collectLastValue(underTest.isSatelliteProvisioned)
+
+ runCurrent()
+
+ // THEN the current state is requested
+ verify(satelliteManager, atLeastOnce()).requestIsProvisioned(any(), any())
+
+ // AND the state is correct
+ assertThat(provisioned).isFalse()
+ }
+
+ @Test
+ fun satelliteProvisioned_supported_notInitiallyProvisioned_tracksCallback() =
testScope.runTest {
// GIVEN satellite is not supported
setUpRepo(
uptime = MIN_UPTIME,
satMan = satelliteManager,
satelliteSupported = true,
+ initialSatelliteIsProvisioned = false,
)
val provisioned by collectLastValue(underTest.isSatelliteProvisioned)
@@ -416,6 +547,8 @@
// THEN listeners are re-registered
verify(satelliteManager, times(2)).registerForProvisionStateChanged(any(), any())
+ // AND the state is queried again
+ verify(satelliteManager, times(2)).requestIsProvisioned(any(), any())
}
@Test
@@ -632,6 +765,7 @@
uptime: Long = MIN_UPTIME,
satMan: SatelliteManager? = satelliteManager,
satelliteSupported: Boolean = true,
+ initialSatelliteIsProvisioned: Boolean = true,
) {
doAnswer {
val callback: OutcomeReceiver<Boolean, SatelliteException> =
@@ -641,6 +775,14 @@
.whenever(satelliteManager)
.requestIsSupported(any(), any())
+ doAnswer {
+ val callback: OutcomeReceiver<Boolean, SatelliteException> =
+ it.getArgument(1) as OutcomeReceiver<Boolean, SatelliteException>
+ callback.onResult(initialSatelliteIsProvisioned)
+ }
+ .whenever(satelliteManager)
+ .requestIsProvisioned(any(), any())
+
systemClock.setUptimeMillis(Process.getStartUptimeMillis() + uptime)
underTest =
diff --git a/packages/SystemUI/tests/src/com/android/systemui/touchpad/tutorial/ui/TouchpadTutorialViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/touchpad/tutorial/ui/TouchpadTutorialViewModelTest.kt
new file mode 100644
index 0000000..2300a1f
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/touchpad/tutorial/ui/TouchpadTutorialViewModelTest.kt
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+package com.android.systemui.touchpad.tutorial.ui
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.model.sysUiState
+import com.android.systemui.settings.displayTracker
+import com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_TOUCHPAD_GESTURES_DISABLED
+import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags
+import com.android.systemui.testKosmos
+import com.android.systemui.touchpad.tutorial.domain.interactor.TouchpadGesturesInteractor
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class TouchpadTutorialViewModelTest : SysuiTestCase() {
+
+ private val kosmos = testKosmos()
+ private val testScope = TestScope()
+ private val sysUiState = kosmos.sysUiState
+ private val viewModel =
+ TouchpadTutorialViewModel(
+ TouchpadGesturesInteractor(sysUiState, kosmos.displayTracker, testScope.backgroundScope)
+ )
+
+ @Test
+ fun sysUiStateFlag_disabledByDefault() =
+ testScope.runTest {
+ assertThat(isFlagEnabled(SYSUI_STATE_TOUCHPAD_GESTURES_DISABLED)).isFalse()
+ }
+
+ @Test
+ fun sysUiStateFlag_enabledAfterTutorialOpened() =
+ testScope.runTest {
+ viewModel.onOpened()
+
+ assertThat(isFlagEnabled(SYSUI_STATE_TOUCHPAD_GESTURES_DISABLED)).isTrue()
+ }
+
+ @Test
+ fun sysUiStateFlag_disabledAfterTutorialClosed() =
+ testScope.runTest {
+ viewModel.onOpened()
+ viewModel.onClosed()
+
+ assertThat(isFlagEnabled(SYSUI_STATE_TOUCHPAD_GESTURES_DISABLED)).isFalse()
+ }
+
+ private fun TestScope.isFlagEnabled(@SystemUiStateFlags flag: Long): Boolean {
+ // sysui state is changed on background scope so let's make sure it's executed
+ runCurrent()
+ return sysUiState.isFlagEnabled(flag)
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/FoldLightRevealOverlayAnimationTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/FoldLightRevealOverlayAnimationTest.kt
index dddc712..a56507a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/unfold/FoldLightRevealOverlayAnimationTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/FoldLightRevealOverlayAnimationTest.kt
@@ -22,7 +22,10 @@
import android.testing.TestableLooper
import androidx.test.filters.SmallTest
import com.android.internal.foldables.FoldLockSettingAvailabilityProvider
+import com.android.internal.jank.Cuj.CUJ_FOLD_ANIM
+import com.android.internal.jank.InteractionJankMonitor
import com.android.systemui.SysuiTestCase
+import com.android.systemui.animation.AnimatorTestRule
import com.android.systemui.display.data.repository.DeviceStateRepository.DeviceState
import com.android.systemui.display.data.repository.fakeDeviceStateRepository
import com.android.systemui.kosmos.Kosmos
@@ -32,27 +35,34 @@
import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setScreenPowerState
import com.android.systemui.power.domain.interactor.powerInteractor
import com.android.systemui.power.shared.model.ScreenPowerState
+import com.android.systemui.statusbar.LightRevealScrim
import com.android.systemui.util.animation.data.repository.fakeAnimationStatusRepository
-import com.android.systemui.util.mockito.any
-import com.android.systemui.util.mockito.mock
-import com.android.systemui.util.mockito.whenever
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.advanceTimeBy
import kotlinx.coroutines.test.runTest
import org.junit.Before
+import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mockito.atLeast
import org.mockito.Mockito.never
+import org.mockito.Mockito.times
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
+import org.mockito.kotlin.any
+import org.mockito.kotlin.clearInvocations
+import org.mockito.kotlin.eq
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.whenever
@SmallTest
@TestableLooper.RunWithLooper(setAsMainLooper = true)
@RunWith(AndroidTestingRunner::class)
@OptIn(ExperimentalCoroutinesApi::class)
class FoldLightRevealOverlayAnimationTest : SysuiTestCase() {
+ @get:Rule val animatorTestRule = AnimatorTestRule(this)
+
private val kosmos = Kosmos()
private val testScope: TestScope = kosmos.testScope
private val fakeDeviceStateRepository = kosmos.fakeDeviceStateRepository
@@ -63,6 +73,8 @@
private val mockFoldLockSettingAvailabilityProvider =
mock<FoldLockSettingAvailabilityProvider>()
private val onOverlayReady = mock<Runnable>()
+ private val mockJankMonitor = mock<InteractionJankMonitor>()
+ private val mockScrimView = mock<LightRevealScrim>()
private lateinit var foldLightRevealAnimation: FoldLightRevealOverlayAnimation
@Before
@@ -71,6 +83,8 @@
whenever(mockFoldLockSettingAvailabilityProvider.isFoldLockBehaviorAvailable)
.thenReturn(true)
fakeAnimationStatusRepository.onAnimationStatusChanged(true)
+ whenever(mockFullScreenController.scrimView).thenReturn(mockScrimView)
+ whenever(mockJankMonitor.begin(any(), eq(CUJ_FOLD_ANIM))).thenReturn(true)
foldLightRevealAnimation =
FoldLightRevealOverlayAnimation(
@@ -80,7 +94,8 @@
testScope.backgroundScope,
fakeAnimationStatusRepository,
mockControllerFactory,
- mockFoldLockSettingAvailabilityProvider
+ mockFoldLockSettingAvailabilityProvider,
+ mockJankMonitor
)
foldLightRevealAnimation.init()
}
@@ -99,9 +114,9 @@
testScope.runTest {
foldDeviceToScreenOff()
emitLastWakefulnessEventStartingToSleep()
- advanceTimeBy(SHORT_DELAY_MS)
+ advanceTime(SHORT_DELAY_MS)
turnScreenOn()
- advanceTimeBy(ANIMATION_DURATION)
+ advanceTime(ANIMATION_DURATION)
verifyFoldAnimationDidNotPlay()
}
@@ -111,8 +126,8 @@
testScope.runTest {
foldDeviceToScreenOff()
emitLastWakefulnessEventStartingToSleep()
- advanceTimeBy(SHORT_DELAY_MS)
- advanceTimeBy(ANIMATION_DURATION)
+ advanceTime(SHORT_DELAY_MS)
+ advanceTime(ANIMATION_DURATION)
verifyFoldAnimationDidNotPlay()
}
@@ -122,10 +137,10 @@
testScope.runTest {
foldDeviceToScreenOff()
foldLightRevealAnimation.onScreenTurningOn {}
- advanceTimeBy(WAIT_FOR_ANIMATION_TIMEOUT_MS)
+ advanceTime(WAIT_FOR_ANIMATION_TIMEOUT_MS)
powerInteractor.setScreenPowerState(ScreenPowerState.SCREEN_ON)
- advanceTimeBy(SHORT_DELAY_MS)
- advanceTimeBy(ANIMATION_DURATION)
+ advanceTime(SHORT_DELAY_MS)
+ advanceTime(ANIMATION_DURATION)
verifyFoldAnimationDidNotPlay()
}
@@ -135,10 +150,12 @@
testScope.runTest {
foldDeviceToScreenOff()
foldLightRevealAnimation.onScreenTurningOn {}
- advanceTimeBy(SHORT_DELAY_MS)
- advanceTimeBy(ANIMATION_DURATION)
+ advanceTime(SHORT_DELAY_MS)
+ clearInvocations(mockFullScreenController)
+
+ // Unfold the device
fakeDeviceStateRepository.emit(DeviceState.HALF_FOLDED)
- advanceTimeBy(SHORT_DELAY_MS)
+ advanceTime(SHORT_DELAY_MS)
powerInteractor.setScreenPowerState(ScreenPowerState.SCREEN_ON)
verifyOverlayWasRemoved()
@@ -149,12 +166,38 @@
testScope.runTest {
foldDeviceToScreenOff()
turnScreenOn()
- advanceTimeBy(ANIMATION_DURATION)
+ clearInvocations(mockFullScreenController)
+ advanceTime(ANIMATION_DURATION)
verifyOverlayWasRemoved()
}
@Test
+ fun foldToScreenOn_jankCujIsStarted() =
+ testScope.runTest {
+ foldDeviceToScreenOff()
+ turnScreenOn()
+ // Cuj has started but not ended
+ verify(mockJankMonitor, times(1)).begin(any(), eq(CUJ_FOLD_ANIM))
+ verify(mockJankMonitor, never()).end(eq(CUJ_FOLD_ANIM))
+ }
+
+ @Test
+ fun foldToScreenOn_animationFinished_jankCujIsFinished() =
+ testScope.runTest {
+ foldDeviceToScreenOff()
+ turnScreenOn()
+
+ advanceTime(ANIMATION_DURATION)
+ verify(mockJankMonitor, times(1)).end(eq(CUJ_FOLD_ANIM))
+ }
+
+ private fun TestScope.advanceTime(timeMs: Long) {
+ animatorTestRule.advanceTimeBy(timeMs)
+ advanceTimeBy(timeMs)
+ }
+
+ @Test
fun unfold_immediatelyRunRunnable() =
testScope.runTest {
foldLightRevealAnimation.onScreenTurningOn(onOverlayReady)
@@ -165,18 +208,18 @@
private suspend fun TestScope.foldDeviceToScreenOff() {
fakeDeviceStateRepository.emit(DeviceState.HALF_FOLDED)
powerInteractor.setScreenPowerState(ScreenPowerState.SCREEN_ON)
- advanceTimeBy(SHORT_DELAY_MS)
+ advanceTime(SHORT_DELAY_MS)
fakeDeviceStateRepository.emit(DeviceState.FOLDED)
- advanceTimeBy(SHORT_DELAY_MS)
+ advanceTime(SHORT_DELAY_MS)
powerInteractor.setScreenPowerState(ScreenPowerState.SCREEN_OFF)
- advanceTimeBy(SHORT_DELAY_MS)
+ advanceTime(SHORT_DELAY_MS)
}
private fun TestScope.turnScreenOn() {
foldLightRevealAnimation.onScreenTurningOn {}
- advanceTimeBy(SHORT_DELAY_MS)
+ advanceTime(SHORT_DELAY_MS)
powerInteractor.setScreenPowerState(ScreenPowerState.SCREEN_ON)
- advanceTimeBy(SHORT_DELAY_MS)
+ advanceTime(SHORT_DELAY_MS)
}
private fun emitLastWakefulnessEventStartingToSleep() =
@@ -195,6 +238,7 @@
const val WAIT_FOR_ANIMATION_TIMEOUT_MS = 2000L
val ANIMATION_DURATION: Long
get() = SystemProperties.getLong("persist.fold_animation_duration", 200L)
+
const val SHORT_DELAY_MS = 50L
}
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestCase.java b/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestCase.java
index 8eef930..78d8abe 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestCase.java
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestCase.java
@@ -21,7 +21,6 @@
import android.app.Instrumentation;
import android.content.Context;
import android.content.res.Resources;
-import android.os.Build;
import android.os.Handler;
import android.os.HandlerExecutor;
import android.os.Looper;
@@ -297,7 +296,7 @@
}
public static boolean isRobolectricTest() {
- return !isRavenwoodTest() && Build.FINGERPRINT.contains("robolectric");
+ return !isRavenwoodTest() && !System.getProperty("java.vm.name").equals("Dalvik");
}
protected boolean isScreenshotTest() {
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/startable/StatusBarStartableKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/startable/StatusBarStartableKosmos.kt
new file mode 100644
index 0000000..ee69c30
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/startable/StatusBarStartableKosmos.kt
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+@file:OptIn(ExperimentalCoroutinesApi::class)
+
+package com.android.systemui.scene.domain.startable
+
+import android.content.applicationContext
+import com.android.internal.statusbar.statusBarService
+import com.android.systemui.authentication.domain.interactor.authenticationInteractor
+import com.android.systemui.deviceconfig.domain.interactor.deviceConfigInteractor
+import com.android.systemui.deviceentry.domain.interactor.deviceEntryFaceAuthInteractor
+import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.Kosmos.Fixture
+import com.android.systemui.kosmos.applicationCoroutineScope
+import com.android.systemui.kosmos.testDispatcher
+import com.android.systemui.navigation.domain.interactor.navigationInteractor
+import com.android.systemui.power.domain.interactor.powerInteractor
+import com.android.systemui.scene.domain.interactor.sceneContainerOcclusionInteractor
+import com.android.systemui.scene.domain.interactor.sceneInteractor
+import com.android.systemui.user.domain.interactor.selectedUserInteractor
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+
+val Kosmos.statusBarStartable by Fixture {
+ StatusBarStartable(
+ applicationScope = applicationCoroutineScope,
+ backgroundDispatcher = testDispatcher,
+ applicationContext = applicationContext,
+ selectedUserInteractor = selectedUserInteractor,
+ sceneInteractor = sceneInteractor,
+ deviceEntryInteractor = deviceEntryInteractor,
+ sceneContainerOcclusionInteractor = sceneContainerOcclusionInteractor,
+ deviceConfigInteractor = deviceConfigInteractor,
+ navigationInteractor = navigationInteractor,
+ authenticationInteractor = authenticationInteractor,
+ powerInteractor = powerInteractor,
+ deviceEntryFaceAuthInteractor = deviceEntryFaceAuthInteractor,
+ statusBarService = statusBarService,
+ )
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/user/data/repository/FakeUserRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/user/data/repository/FakeUserRepository.kt
index 1f2ecb7..ed335f9 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/user/data/repository/FakeUserRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/user/data/repository/FakeUserRepository.kt
@@ -39,7 +39,7 @@
// User id to represent a non system (human) user id. We presume this is the main user.
const val MAIN_USER_ID = 10
- private const val DEFAULT_SELECTED_USER = 0
+ const val DEFAULT_SELECTED_USER = 0
private val DEFAULT_SELECTED_USER_INFO =
UserInfo(
/* id= */ DEFAULT_SELECTED_USER,
diff --git a/services/OWNERS b/services/OWNERS
index 3ce5ae1..69e4e24 100644
--- a/services/OWNERS
+++ b/services/OWNERS
@@ -1,7 +1,7 @@
per-file Android.bp = file:platform/build/soong:/OWNERS #{LAST_RESORT_SUGGESTION}
# art-team@ manages the system server profile
-per-file art-profile* = calin@google.com, ngeoffray@google.com, vmarko@google.com
+per-file art-profile* = file:platform/art:main:/OWNERS_boot_profile
per-file java/com/android/server/HsumBootUserInitializer.java = file:/MULTIUSER_OWNERS
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index 5567707..d7649dc 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -17,6 +17,7 @@
package com.android.server.appwidget;
import static android.appwidget.flags.Flags.removeAppWidgetServiceIoFromCriticalPath;
+import static android.appwidget.flags.Flags.supportResumeRestoreAfterReboot;
import static android.content.Context.KEYGUARD_SERVICE;
import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
@@ -166,6 +167,8 @@
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.atomic.AtomicLong;
+import java.util.function.BiConsumer;
+import java.util.function.Function;
import java.util.function.LongSupplier;
class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBackupProvider,
@@ -457,7 +460,7 @@
break;
case Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE:
added = true;
- // Follow through
+ // fall through
case Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE:
pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
break;
@@ -3571,6 +3574,13 @@
}
out.endTag(null, "gs");
+
+ if (supportResumeRestoreAfterReboot()
+ && mBackupRestoreController.requiresPersistenceLocked()) {
+ AppWidgetXmlUtil.writeBackupRestoreControllerState(
+ out, mBackupRestoreController.getStateLocked(userId));
+ }
+
out.endDocument();
return true;
} catch (IOException e) {
@@ -3717,6 +3727,32 @@
LoadedWidgetState loadedWidgets = new LoadedWidgetState(widget,
hostTag, providerTag);
outLoadedWidgets.add(loadedWidgets);
+ } else if (supportResumeRestoreAfterReboot()
+ && AppWidgetXmlUtil.TAG_BACKUP_RESTORE_CONTROLLER_STATE.equals(tag)) {
+ final BackupRestoreController.State s =
+ AppWidgetXmlUtil.readBackupRestoreControllerState(parser);
+ if (s == null) {
+ continue;
+ }
+ final Set<String> prunedAppsInFile = s.getPrunedApps();
+ if (prunedAppsInFile != null) {
+ final Set<String> prunedAppsInMemory = mBackupRestoreController
+ .mPrunedAppsPerUser.get(userId);
+ if (prunedAppsInMemory == null) {
+ mBackupRestoreController.mPrunedAppsPerUser.put(
+ userId, prunedAppsInFile);
+ } else {
+ prunedAppsInMemory.addAll(prunedAppsInFile);
+ }
+ }
+ loadUpdateRecords(s.getUpdatesByProvider(),
+ this::findProviderByTag,
+ mBackupRestoreController.mUpdatesByProvider::get,
+ mBackupRestoreController.mUpdatesByProvider::put);
+ loadUpdateRecords(s.getUpdatesByHost(),
+ this::findHostByTag,
+ mBackupRestoreController.mUpdatesByHost::get,
+ mBackupRestoreController.mUpdatesByHost::put);
}
}
} while (type != XmlPullParser.END_DOCUMENT);
@@ -3732,6 +3768,36 @@
return version;
}
+ private <T> void loadUpdateRecords(
+ @Nullable final SparseArray<
+ List<BackupRestoreController.RestoreUpdateRecord>> updatesOnFile,
+ @NonNull final Function<Integer, T> findKeyByTagCb,
+ @NonNull final Function<T, List<
+ BackupRestoreController.RestoreUpdateRecord>> findRecordsCb,
+ @NonNull final BiConsumer<T, List<
+ BackupRestoreController.RestoreUpdateRecord>> newRecordsCb) {
+ if (updatesOnFile == null) {
+ return;
+ }
+ for (int i = 0; i < updatesOnFile.size(); i++) {
+ final int tag = updatesOnFile.keyAt(i);
+ final List<
+ BackupRestoreController.RestoreUpdateRecord
+ > recordsOnFile = updatesOnFile.get(tag);
+ if (recordsOnFile == null || recordsOnFile.isEmpty()) {
+ continue;
+ }
+ final T key = findKeyByTagCb.apply(tag);
+ final List<BackupRestoreController.RestoreUpdateRecord> recordsInMemory =
+ findRecordsCb.apply(key);
+ if (recordsInMemory != null) {
+ recordsInMemory.addAll(recordsOnFile);
+ } else {
+ newRecordsCb.accept(key, recordsOnFile);
+ }
+ }
+ }
+
private void performUpgradeLocked(int fromVersion) {
if (fromVersion < CURRENT_VERSION) {
Slog.v(TAG, "Upgrading widget database from " + fromVersion + " to "
@@ -4674,7 +4740,7 @@
}
}
- private static final class Provider {
+ static final class Provider {
ProviderId id;
AppWidgetProviderInfo info;
@@ -4931,7 +4997,7 @@
}
}
- private static final class Host {
+ static final class Host {
HostId id;
ArrayList<Widget> widgets = new ArrayList<>();
IAppWidgetHost callbacks;
@@ -5250,10 +5316,10 @@
/**
* This class encapsulates the backup and restore logic for a user group state.
*/
- private final class BackupRestoreController {
+ final class BackupRestoreController {
private static final String TAG = "BackupRestoreController";
- private static final boolean DEBUG = true;
+ private static final boolean DEBUG = AppWidgetServiceImpl.DEBUG;
// Version of backed-up widget state.
private static final int WIDGET_STATE_VERSION = 2;
@@ -5262,16 +5328,31 @@
// a given package. Keep track of what we've done so far here; the list is
// cleared at the start of every system restore pass, but preserved through
// any install-time restore operations.
+ @GuardedBy("AppWidgetServiceImpl.this.mLock")
private final SparseArray<Set<String>> mPrunedAppsPerUser = new SparseArray<>();
- private final HashMap<Provider, ArrayList<RestoreUpdateRecord>> mUpdatesByProvider =
- new HashMap<>();
- private final HashMap<Host, ArrayList<RestoreUpdateRecord>> mUpdatesByHost =
- new HashMap<>();
+ @GuardedBy("AppWidgetServiceImpl.this.mLock")
+ final Map<Provider, List<RestoreUpdateRecord>> mUpdatesByProvider =
+ new ArrayMap<>();
- @GuardedBy("mLock")
+ @GuardedBy("AppWidgetServiceImpl.this.mLock")
+ private final Map<Host, List<RestoreUpdateRecord>> mUpdatesByHost =
+ new ArrayMap<>();
+
+ @GuardedBy("AppWidgetServiceImpl.this.mLock")
private boolean mHasSystemRestoreFinished;
+ @GuardedBy("AppWidgetServiceImpl.this.mLock")
+ public boolean requiresPersistenceLocked() {
+ if (mHasSystemRestoreFinished) {
+ // No need to persist intermediate states if system restore is already finished.
+ return false;
+ }
+ // If either of the internal states is non-empty, then we need to persist that
+ return !(mPrunedAppsPerUser.size() == 0 && mUpdatesByProvider.isEmpty()
+ && mUpdatesByHost.isEmpty());
+ }
+
public List<String> getWidgetParticipants(int userId) {
if (DEBUG) {
Slog.i(TAG, "Getting widget participants for user: " + userId);
@@ -5436,7 +5517,7 @@
// If there's no live entry for this provider, add an inactive one
// so that widget IDs referring to them can be properly allocated
- // Backup and resotre only for the parent profile.
+ // Backup and restore only for the parent profile.
ComponentName componentName = new ComponentName(pkg, cl);
Provider p = findProviderLocked(componentName, userId);
@@ -5579,9 +5660,9 @@
final UserHandle userHandle = new UserHandle(userId);
// Build the providers' broadcasts and send them off
- Set<Map.Entry<Provider, ArrayList<RestoreUpdateRecord>>> providerEntries
+ Set<Map.Entry<Provider, List<RestoreUpdateRecord>>> providerEntries
= mUpdatesByProvider.entrySet();
- for (Map.Entry<Provider, ArrayList<RestoreUpdateRecord>> e : providerEntries) {
+ for (Map.Entry<Provider, List<RestoreUpdateRecord>> e : providerEntries) {
// For each provider there's a list of affected IDs
Provider provider = e.getKey();
if (provider.zombie) {
@@ -5589,7 +5670,7 @@
// We'll be called again when the provider is installed.
continue;
}
- ArrayList<RestoreUpdateRecord> updates = e.getValue();
+ List<RestoreUpdateRecord> updates = e.getValue();
final int pending = countPendingUpdates(updates);
if (DEBUG) {
Slog.i(TAG, "Provider " + provider + " pending: " + pending);
@@ -5618,12 +5699,12 @@
}
// same thing per host
- Set<Map.Entry<Host, ArrayList<RestoreUpdateRecord>>> hostEntries
+ Set<Map.Entry<Host, List<RestoreUpdateRecord>>> hostEntries
= mUpdatesByHost.entrySet();
- for (Map.Entry<Host, ArrayList<RestoreUpdateRecord>> e : hostEntries) {
+ for (Map.Entry<Host, List<RestoreUpdateRecord>> e : hostEntries) {
Host host = e.getKey();
if (host.id.uid != UNKNOWN_UID) {
- ArrayList<RestoreUpdateRecord> updates = e.getValue();
+ List<RestoreUpdateRecord> updates = e.getValue();
final int pending = countPendingUpdates(updates);
if (DEBUG) {
Slog.i(TAG, "Host " + host + " pending: " + pending);
@@ -5714,8 +5795,9 @@
return false;
}
+ @GuardedBy("mLock")
private void stashProviderRestoreUpdateLocked(Provider provider, int oldId, int newId) {
- ArrayList<RestoreUpdateRecord> r = mUpdatesByProvider.get(provider);
+ List<RestoreUpdateRecord> r = mUpdatesByProvider.get(provider);
if (r == null) {
r = new ArrayList<>();
mUpdatesByProvider.put(provider, r);
@@ -5732,7 +5814,7 @@
r.add(new RestoreUpdateRecord(oldId, newId));
}
- private boolean alreadyStashed(ArrayList<RestoreUpdateRecord> stash,
+ private boolean alreadyStashed(List<RestoreUpdateRecord> stash,
final int oldId, final int newId) {
final int N = stash.size();
for (int i = 0; i < N; i++) {
@@ -5744,8 +5826,9 @@
return false;
}
+ @GuardedBy("mLock")
private void stashHostRestoreUpdateLocked(Host host, int oldId, int newId) {
- ArrayList<RestoreUpdateRecord> r = mUpdatesByHost.get(host);
+ List<RestoreUpdateRecord> r = mUpdatesByHost.get(host);
if (r == null) {
r = new ArrayList<>();
mUpdatesByHost.put(host, r);
@@ -5835,7 +5918,7 @@
|| widget.provider.getUserId() == userId);
}
- private int countPendingUpdates(ArrayList<RestoreUpdateRecord> updates) {
+ private int countPendingUpdates(List<RestoreUpdateRecord> updates) {
int pending = 0;
final int N = updates.size();
for (int i = 0; i < N; i++) {
@@ -5847,9 +5930,28 @@
return pending;
}
+ @GuardedBy("mLock")
+ @NonNull
+ private State getStateLocked(final int userId) {
+ final Set<String> prunedApps = mPrunedAppsPerUser.get(userId);
+ final SparseArray<List<RestoreUpdateRecord>> updatesByProvider = new SparseArray<>();
+ final SparseArray<List<RestoreUpdateRecord>> updatesByHost = new SparseArray<>();
+ mUpdatesByProvider.forEach((p, updates) -> {
+ if (p.getUserId() == userId) {
+ updatesByProvider.put(p.tag, new ArrayList<>(updates));
+ }
+ });
+ mUpdatesByHost.forEach((h, updates) -> {
+ if (h.getUserId() == userId) {
+ updatesByHost.put(h.tag, new ArrayList<>(updates));
+ }
+ });
+ return new State(prunedApps, updatesByProvider, updatesByHost);
+ }
+
// Accumulate a list of updates that affect the given provider for a final
// coalesced notification broadcast once restore is over.
- private class RestoreUpdateRecord {
+ static class RestoreUpdateRecord {
public int oldId;
public int newId;
public boolean notified;
@@ -5860,6 +5962,45 @@
notified = false;
}
}
+
+ static final class State {
+ // We need to make sure to wipe the pre-restore widget state only once for
+ // a given package. Keep track of what we've done so far here; the list is
+ // cleared at the start of every system restore pass, but preserved through
+ // any install-time restore operations.
+ @Nullable
+ private final Set<String> mPrunedApps;
+
+ @Nullable
+ private final SparseArray<List<RestoreUpdateRecord>> mUpdatesByProvider;
+
+ @Nullable
+ private final SparseArray<List<RestoreUpdateRecord>> mUpdatesByHost;
+
+ State(
+ @Nullable final Set<String> prunedApps,
+ @Nullable final SparseArray<List<RestoreUpdateRecord>> updatesByProvider,
+ @Nullable final SparseArray<List<RestoreUpdateRecord>> updatesByHost) {
+ mPrunedApps = prunedApps;
+ mUpdatesByProvider = updatesByProvider;
+ mUpdatesByHost = updatesByHost;
+ }
+
+ @Nullable
+ Set<String> getPrunedApps() {
+ return mPrunedApps;
+ }
+
+ @Nullable
+ SparseArray<List<BackupRestoreController.RestoreUpdateRecord>> getUpdatesByProvider() {
+ return mUpdatesByProvider;
+ }
+
+ @Nullable
+ SparseArray<List<BackupRestoreController.RestoreUpdateRecord>> getUpdatesByHost() {
+ return mUpdatesByHost;
+ }
+ }
}
private class AppWidgetManagerLocal extends AppWidgetManagerInternal {
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetXmlUtil.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetXmlUtil.java
index d781cd8..ce9130a 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetXmlUtil.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetXmlUtil.java
@@ -22,17 +22,24 @@
import android.content.ComponentName;
import android.os.Build;
import android.text.TextUtils;
+import android.util.ArraySet;
+import android.util.Log;
import android.util.SizeF;
import android.util.Slog;
+import android.util.SparseArray;
import com.android.modules.utils.TypedXmlPullParser;
import com.android.modules.utils.TypedXmlSerializer;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
+import java.util.Set;
import java.util.stream.Collectors;
/**
@@ -65,6 +72,16 @@
private static final String ATTR_DESCRIPTION_RES = "description_res";
private static final String ATTR_PROVIDER_INHERITANCE = "provider_inheritance";
private static final String ATTR_OS_FINGERPRINT = "os_fingerprint";
+ static final String TAG_BACKUP_RESTORE_CONTROLLER_STATE = "br";
+ private static final String TAG_PRUNED_APPS = "pruned_apps";
+ private static final String ATTR_TAG = "tag";
+ private static final String ATTR_PACKAGE_NAMES = "pkgs";
+ private static final String TAG_PROVIDER_UPDATES = "provider_updates";
+ private static final String TAG_HOST_UPDATES = "host_updates";
+ private static final String TAG_RECORD = "record";
+ private static final String ATTR_OLD_ID = "old_id";
+ private static final String ATTR_NEW_ID = "new_id";
+ private static final String ATTR_NOTIFIED = "notified";
private static final String SIZE_SEPARATOR = ",";
/**
@@ -165,4 +182,168 @@
return null;
}
}
+
+ /**
+ * Persists {@link AppWidgetServiceImpl.BackupRestoreController.State} to disk as XML.
+ * See {@link #readBackupRestoreControllerState(TypedXmlPullParser)} for example XML.
+ *
+ * @param out XML serializer
+ * @param state {@link AppWidgetServiceImpl.BackupRestoreController.State} of
+ * intermediate states to be persisted as xml to resume restore after reboot.
+ */
+ static void writeBackupRestoreControllerState(
+ @NonNull final TypedXmlSerializer out,
+ @NonNull final AppWidgetServiceImpl.BackupRestoreController.State state)
+ throws IOException {
+ Objects.requireNonNull(out);
+ Objects.requireNonNull(state);
+ out.startTag(null, TAG_BACKUP_RESTORE_CONTROLLER_STATE);
+ final Set<String> prunedApps = state.getPrunedApps();
+ if (prunedApps != null && !prunedApps.isEmpty()) {
+ out.startTag(null, TAG_PRUNED_APPS);
+ out.attribute(null, ATTR_PACKAGE_NAMES, String.join(",", prunedApps));
+ out.endTag(null, TAG_PRUNED_APPS);
+ }
+ final SparseArray<List<AppWidgetServiceImpl.BackupRestoreController.RestoreUpdateRecord>>
+ updatesByProvider = state.getUpdatesByProvider();
+ if (updatesByProvider != null) {
+ writeUpdateRecords(out, TAG_PROVIDER_UPDATES, updatesByProvider);
+ }
+ final SparseArray<List<AppWidgetServiceImpl.BackupRestoreController.RestoreUpdateRecord>>
+ updatesByHost = state.getUpdatesByHost();
+ if (updatesByHost != null) {
+ writeUpdateRecords(out, TAG_HOST_UPDATES, updatesByHost);
+ }
+ out.endTag(null, TAG_BACKUP_RESTORE_CONTROLLER_STATE);
+ }
+
+ private static void writeUpdateRecords(@NonNull final TypedXmlSerializer out,
+ @NonNull final String outerTag, @NonNull final SparseArray<List<
+ AppWidgetServiceImpl.BackupRestoreController.RestoreUpdateRecord>> records)
+ throws IOException {
+ for (int i = 0; i < records.size(); i++) {
+ final int tag = records.keyAt(i);
+ out.startTag(null, outerTag);
+ out.attributeInt(null, ATTR_TAG, tag);
+ final List<AppWidgetServiceImpl.BackupRestoreController.RestoreUpdateRecord> entries =
+ records.get(tag);
+ for (AppWidgetServiceImpl.BackupRestoreController.RestoreUpdateRecord entry : entries) {
+ out.startTag(null, TAG_RECORD);
+ out.attributeInt(null, ATTR_OLD_ID, entry.oldId);
+ out.attributeInt(null, ATTR_NEW_ID, entry.newId);
+ out.attributeBoolean(null, ATTR_NOTIFIED, entry.notified);
+ out.endTag(null, TAG_RECORD);
+ }
+ out.endTag(null, outerTag);
+ }
+ }
+
+ /**
+ * Parses {@link AppWidgetServiceImpl.BackupRestoreController.State} from xml.
+ *
+ * <pre>
+ * {@code
+ * <?xml version="1.0"?>
+ * <br>
+ * <pruned_apps pkgs="com.example.app1,com.example.app2,com.example.app3" />
+ * <provider_updates tag="0">
+ * <record old_id="10" new_id="0" notified="false" />
+ * </provider_updates>
+ * <provider_updates tag="1">
+ * <record old_id="9" new_id="1" notified="true" />
+ * </provider_updates>
+ * <provider_updates tag="2">
+ * <record old_id="8" new_id="2" notified="false" />
+ * </provider_updates>
+ * <host_updates tag="0">
+ * <record old_id="10" new_id="0" notified="false" />
+ * </host_updates>
+ * <host_updates tag="1">
+ * <record old_id="9" new_id="1" notified="true" />
+ * </host_updates>
+ * <host_updates tag="2">
+ * <record old_id="8" new_id="2" notified="false" />
+ * </host_updates>
+ * </br>
+ * }
+ * </pre>
+ *
+ * @param parser XML parser
+ * @return {@link AppWidgetServiceImpl.BackupRestoreController.State} of intermediate states
+ * in {@link AppWidgetServiceImpl.BackupRestoreController}, so that backup & restore can be
+ * resumed after reboot.
+ */
+ @Nullable
+ static AppWidgetServiceImpl.BackupRestoreController.State
+ readBackupRestoreControllerState(@NonNull final TypedXmlPullParser parser) {
+ Objects.requireNonNull(parser);
+ int type;
+ String tag = null;
+ final Set<String> prunedApps = new ArraySet<>(1);
+ final SparseArray<List<AppWidgetServiceImpl.BackupRestoreController.RestoreUpdateRecord>>
+ updatesByProviders = new SparseArray<>();
+ final SparseArray<List<AppWidgetServiceImpl.BackupRestoreController.RestoreUpdateRecord>>
+ updatesByHosts = new SparseArray<>();
+
+ try {
+ do {
+ type = parser.next();
+ if (type != XmlPullParser.START_TAG) {
+ continue;
+ }
+ tag = parser.getName();
+ switch (tag) {
+ case TAG_PRUNED_APPS:
+ final String packages =
+ parser.getAttributeValue(null, ATTR_PACKAGE_NAMES);
+ prunedApps.addAll(Arrays.asList(packages.split(",")));
+ break;
+ case TAG_PROVIDER_UPDATES:
+ updatesByProviders.put(parser.getAttributeInt(null, ATTR_TAG),
+ parseRestoreUpdateRecords(parser));
+ break;
+ case TAG_HOST_UPDATES:
+ updatesByHosts.put(parser.getAttributeInt(null, ATTR_TAG),
+ parseRestoreUpdateRecords(parser));
+ break;
+ default:
+ break;
+ }
+ } while (type != XmlPullParser.END_DOCUMENT
+ && (!TAG_BACKUP_RESTORE_CONTROLLER_STATE.equals(tag)
+ || type != XmlPullParser.END_TAG));
+ } catch (IOException | XmlPullParserException e) {
+ Log.e(TAG, "error parsing state", e);
+ return null;
+ }
+ return new AppWidgetServiceImpl.BackupRestoreController.State(
+ prunedApps, updatesByProviders, updatesByHosts);
+ }
+
+ @NonNull
+ private static List<
+ AppWidgetServiceImpl.BackupRestoreController.RestoreUpdateRecord
+ > parseRestoreUpdateRecords(@NonNull final TypedXmlPullParser parser)
+ throws XmlPullParserException, IOException {
+ int type;
+ String tag;
+ final List<AppWidgetServiceImpl.BackupRestoreController.RestoreUpdateRecord> ret =
+ new ArrayList<>();
+ do {
+ type = parser.next();
+ tag = parser.getName();
+ if (tag.equals(TAG_RECORD) && type == XmlPullParser.START_TAG) {
+ final int oldId = parser.getAttributeInt(null, ATTR_OLD_ID);
+ final int newId = parser.getAttributeInt(null, ATTR_NEW_ID);
+ final boolean notified = parser.getAttributeBoolean(
+ null, ATTR_NOTIFIED);
+ final AppWidgetServiceImpl.BackupRestoreController.RestoreUpdateRecord record =
+ new AppWidgetServiceImpl.BackupRestoreController.RestoreUpdateRecord(
+ oldId, newId);
+ record.notified = notified;
+ ret.add(record);
+ }
+ } while (tag.equals(TAG_RECORD));
+ return ret;
+ }
}
diff --git a/services/core/java/com/android/server/EventLogTags.logtags b/services/core/java/com/android/server/EventLogTags.logtags
index 256f2b3..361b818 100644
--- a/services/core/java/com/android/server/EventLogTags.logtags
+++ b/services/core/java/com/android/server/EventLogTags.logtags
@@ -63,7 +63,7 @@
# NotificationManagerService.java
# ---------------------------
# when a NotificationManager.notify is called. status: 0=post, 1=update, 2=ignored
-2750 notification_enqueue (uid|1|5),(pid|1|5),(pkg|3),(id|1|5),(tag|3),(userid|1|5),(notification|3),(status|1)
+2750 notification_enqueue (uid|1|5),(pid|1|5),(pkg|3),(id|1|5),(tag|3),(userid|1|5),(notification|3),(status|1),(app_provided|1)
# when someone tries to cancel a notification, the notification manager sometimes
# calls this with flags too
2751 notification_cancel (uid|1|5),(pid|1|5),(pkg|3),(id|1|5),(tag|3),(userid|1|5),(required_flags|1),(forbidden_flags|1),(reason|1|5),(listener|3)
diff --git a/services/core/java/com/android/server/am/AppExitInfoTracker.java b/services/core/java/com/android/server/am/AppExitInfoTracker.java
index 666e560..47b65eb 100644
--- a/services/core/java/com/android/server/am/AppExitInfoTracker.java
+++ b/services/core/java/com/android/server/am/AppExitInfoTracker.java
@@ -88,6 +88,7 @@
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Consumer;
+import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.zip.GZIPOutputStream;
@@ -104,9 +105,9 @@
private static final long APP_EXIT_INFO_PERSIST_INTERVAL = TimeUnit.MINUTES.toMillis(30);
/** These are actions that the forEach* should take after each iteration */
- private static final int FOREACH_ACTION_NONE = 0;
- private static final int FOREACH_ACTION_REMOVE_ITEM = 1;
- private static final int FOREACH_ACTION_STOP_ITERATION = 2;
+ @VisibleForTesting static final int FOREACH_ACTION_NONE = 0;
+ @VisibleForTesting static final int FOREACH_ACTION_REMOVE_ITEM = 1;
+ @VisibleForTesting static final int FOREACH_ACTION_STOP_ITERATION = 2;
private static final int APP_EXIT_RAW_INFO_POOL_SIZE = 8;
@@ -125,7 +126,7 @@
private static final String APP_TRACE_FILE_SUFFIX = ".gz";
- private final Object mLock = new Object();
+ @VisibleForTesting final Object mLock = new Object();
/**
* Initialized in {@link #init} and read-only after that.
@@ -410,6 +411,23 @@
}
/**
+ * Certain types of crashes should not be updated. This could end up deleting valuable
+ * information, for example, if a test application crashes and then the `am instrument`
+ * finishes, then the crash whould be replaced with a `reason == USER_REQUESTED`
+ * ApplicationExitInfo from ActivityManager, and the original crash would be lost.
+ */
+ private boolean preventExitInfoUpdate(final ApplicationExitInfo exitInfo) {
+ switch (exitInfo.getReason()) {
+ case ApplicationExitInfo.REASON_ANR:
+ case ApplicationExitInfo.REASON_CRASH:
+ case ApplicationExitInfo.REASON_CRASH_NATIVE:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ /**
* Make note when ActivityManagerService decides to kill an application process.
*/
@VisibleForTesting
@@ -418,10 +436,10 @@
ApplicationExitInfo info = getExitInfoLocked(
raw.getPackageName(), raw.getPackageUid(), raw.getPid());
- if (info == null) {
+ if (info == null || preventExitInfoUpdate(info)) {
info = addExitInfoLocked(raw);
} else {
- // always override the existing info since we are now more informational.
+ // Override the existing info since we have more information.
info.setReason(raw.getReason());
info.setSubReason(raw.getSubReason());
info.setStatus(0);
@@ -431,24 +449,8 @@
scheduleLogToStatsdLocked(info, true);
}
- /**
- * Make note when ActivityManagerService gets a recoverable native crash, as the process isn't
- * being killed but the crash should still be added to AppExitInfo. Also, because we're not
- * crashing, don't log out to statsd.
- */
- @VisibleForTesting
- @GuardedBy("mLock")
- void handleNoteAppRecoverableCrashLocked(final ApplicationExitInfo raw) {
- addExitInfoLocked(raw, /* recoverable */ true);
- }
-
@GuardedBy("mLock")
private ApplicationExitInfo addExitInfoLocked(ApplicationExitInfo raw) {
- return addExitInfoLocked(raw, /* recoverable */ false);
- }
-
- @GuardedBy("mLock")
- private ApplicationExitInfo addExitInfoLocked(ApplicationExitInfo raw, boolean recoverable) {
if (!mAppExitInfoLoaded.get()) {
Slog.w(TAG, "Skipping saving the exit info due to ongoing loading from storage");
return null;
@@ -464,13 +466,13 @@
}
}
for (int i = 0; i < packages.length; i++) {
- addExitInfoInnerLocked(packages[i], uid, info, recoverable);
+ addExitInfoInnerLocked(packages[i], uid, info);
}
// SDK sandbox exits are stored under both real and package UID
if (Process.isSdkSandboxUid(uid)) {
for (int i = 0; i < packages.length; i++) {
- addExitInfoInnerLocked(packages[i], raw.getPackageUid(), info, recoverable);
+ addExitInfoInnerLocked(packages[i], raw.getPackageUid(), info);
}
}
@@ -526,72 +528,77 @@
if (k != null) {
uid = k;
}
- ArrayList<ApplicationExitInfo> tlist = mTmpInfoList;
- tlist.clear();
final int targetUid = uid;
+ // Launder the modification bit through a `final` array, as Java doesn't allow you to mutate
+ // a captured boolean inside of a lambda.
+ final boolean[] isModified = {false};
forEachPackageLocked((packageName, records) -> {
AppExitInfoContainer container = records.get(targetUid);
if (container == null) {
return FOREACH_ACTION_NONE;
}
- tlist.clear();
- container.getExitInfoLocked(pid, 1, tlist);
- if (tlist.size() == 0) {
+ mTmpInfoList.clear();
+ container.getExitInfosLocked(pid, /* maxNum */ 0, mTmpInfoList);
+ if (mTmpInfoList.size() == 0) {
return FOREACH_ACTION_NONE;
}
- ApplicationExitInfo info = tlist.get(0);
- if (info.getRealUid() != targetUid) {
- tlist.clear();
- return FOREACH_ACTION_NONE;
- }
- // Okay found it, update its reason.
- updateExistingExitInfoRecordLocked(info, status, reason);
- return FOREACH_ACTION_STOP_ITERATION;
+ for (int i = 0, size = mTmpInfoList.size(); i < size; i++) {
+ ApplicationExitInfo info = mTmpInfoList.get(i);
+ if (info.getRealUid() != targetUid) {
+ continue;
+ }
+ // We only update the most recent `ApplicationExitInfo` for this pid, which will
+ // always be the first one we se as `getExitInfosLocked()` returns them sorted
+ // by most-recent-first.
+ isModified[0] = true;
+ updateExistingExitInfoRecordLocked(info, status, reason);
+ return FOREACH_ACTION_STOP_ITERATION;
+ }
+ return FOREACH_ACTION_NONE;
});
- return tlist.size() > 0;
+ mTmpInfoList.clear();
+ return isModified[0];
}
/**
* Get the exit info with matching package name, filterUid and filterPid (if > 0)
*/
@VisibleForTesting
- void getExitInfo(final String packageName, final int filterUid,
- final int filterPid, final int maxNum, final ArrayList<ApplicationExitInfo> results) {
+ void getExitInfo(final String packageName, final int filterUid, final int filterPid,
+ final int maxNum, final List<ApplicationExitInfo> results) {
final long identity = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
- boolean emptyPackageName = TextUtils.isEmpty(packageName);
- if (!emptyPackageName) {
- // fast path
+ if (!TextUtils.isEmpty(packageName)) {
+ // Fast path - just a single package.
AppExitInfoContainer container = mData.get(packageName, filterUid);
if (container != null) {
- container.getExitInfoLocked(filterPid, maxNum, results);
+ container.getExitInfosLocked(filterPid, maxNum, results);
}
- } else {
- // slow path
- final ArrayList<ApplicationExitInfo> list = mTmpInfoList2;
- list.clear();
- // get all packages
- forEachPackageLocked((name, records) -> {
- AppExitInfoContainer container = records.get(filterUid);
- if (container != null) {
- mTmpInfoList.clear();
- list.addAll(container.toListLocked(mTmpInfoList, filterPid));
- }
- return AppExitInfoTracker.FOREACH_ACTION_NONE;
- });
+ return;
+ }
- Collections.sort(list,
- (a, b) -> Long.compare(b.getTimestamp(), a.getTimestamp()));
- int size = list.size();
- if (maxNum > 0) {
- size = Math.min(size, maxNum);
+ // Slow path - get all the packages.
+ forEachPackageLocked((name, records) -> {
+ AppExitInfoContainer container = records.get(filterUid);
+ if (container != null) {
+ container.getExitInfosLocked(filterPid, /* maxNum */ 0, results);
}
- for (int i = 0; i < size; i++) {
- results.add(list.get(i));
- }
- list.clear();
+ return AppExitInfoTracker.FOREACH_ACTION_NONE;
+ });
+
+ // And while the results for each package are sorted, we should
+ // sort over and trim the quantity of global results as well.
+ Collections.sort(
+ results, (a, b) -> Long.compare(b.getTimestamp(), a.getTimestamp()));
+ if (maxNum <= 0) {
+ return;
+ }
+
+ int elementsToRemove = results.size() - maxNum;
+ for (int i = 0; i < elementsToRemove; i++) {
+ results.removeLast();
}
}
} finally {
@@ -606,12 +613,10 @@
@GuardedBy("mLock")
private ApplicationExitInfo getExitInfoLocked(final String packageName,
final int filterUid, final int filterPid) {
- ArrayList<ApplicationExitInfo> list = mTmpInfoList;
- list.clear();
- getExitInfo(packageName, filterUid, filterPid, 1, list);
-
- ApplicationExitInfo info = list.size() > 0 ? list.get(0) : null;
- list.clear();
+ mTmpInfoList.clear();
+ getExitInfo(packageName, filterUid, filterPid, 1, mTmpInfoList);
+ ApplicationExitInfo info = mTmpInfoList.size() > 0 ? mTmpInfoList.getFirst() : null;
+ mTmpInfoList.clear();
return info;
}
@@ -878,8 +883,7 @@
}
@GuardedBy("mLock")
- private void addExitInfoInnerLocked(String packageName, int uid, ApplicationExitInfo info,
- boolean recoverable) {
+ private void addExitInfoInnerLocked(String packageName, int uid, ApplicationExitInfo info) {
AppExitInfoContainer container = mData.get(packageName, uid);
if (container == null) {
container = new AppExitInfoContainer(mAppExitInfoHistoryListSize);
@@ -893,11 +897,7 @@
}
mData.put(packageName, uid, container);
}
- if (recoverable) {
- container.addRecoverableCrashLocked(info);
- } else {
- container.addExitInfoLocked(info);
- }
+ container.addExitInfoLocked(info);
}
@GuardedBy("mLock")
@@ -1205,7 +1205,7 @@
forEachPackageLocked((name, records) -> {
for (int i = records.size() - 1; i >= 0; i--) {
final AppExitInfoContainer container = records.valueAt(i);
- container.forEachRecordLocked((pid, info) -> {
+ container.forEachRecordLocked((info) -> {
final File traceFile = info.getTraceFile();
if (traceFile != null) {
allFiles.remove(traceFile.getName());
@@ -1322,90 +1322,72 @@
* A container class of {@link android.app.ApplicationExitInfo}
*/
final class AppExitInfoContainer {
- private SparseArray<ApplicationExitInfo> mInfos; // index is a pid
- private SparseArray<ApplicationExitInfo> mRecoverableCrashes; // index is a pid
+ private ArrayList<ApplicationExitInfo> mExitInfos;
private int mMaxCapacity;
private int mUid; // Application uid, not isolated uid.
AppExitInfoContainer(final int maxCapacity) {
- mInfos = new SparseArray<ApplicationExitInfo>();
- mRecoverableCrashes = new SparseArray<ApplicationExitInfo>();
+ mExitInfos = new ArrayList<ApplicationExitInfo>();
mMaxCapacity = maxCapacity;
}
+ @VisibleForTesting
@GuardedBy("mLock")
- void getInfosLocked(SparseArray<ApplicationExitInfo> map, final int filterPid,
- final int maxNum, ArrayList<ApplicationExitInfo> results) {
- if (filterPid > 0) {
- ApplicationExitInfo r = map.get(filterPid);
- if (r != null) {
- results.add(r);
+ void getExitInfosLocked(
+ final int filterPid, final int maxNum, List<ApplicationExitInfo> results) {
+ if (mExitInfos.size() == 0) {
+ return;
+ }
+
+ // Most of the callers might only be interested with the most recent
+ // ApplicationExitInfo, and so we can special case an O(n) walk.
+ if (maxNum == 1) {
+ ApplicationExitInfo result = null;
+ for (int i = 0, size = mExitInfos.size(); i < size; i++) {
+ ApplicationExitInfo info = mExitInfos.get(i);
+ if (filterPid > 0 && info.getPid() != filterPid) {
+ continue;
+ }
+
+ if (result == null || result.getTimestamp() < info.getTimestamp()) {
+ result = info;
+ }
}
+ if (result != null) {
+ results.add(result);
+ }
+ return;
+ }
+
+ mTmpInfoList2.clear();
+ if (filterPid <= 0) {
+ mTmpInfoList2.addAll(mExitInfos);
} else {
- final int numRep = map.size();
- if (maxNum <= 0 || numRep <= maxNum) {
- // Return all records.
- for (int i = 0; i < numRep; i++) {
- results.add(map.valueAt(i));
- }
- Collections.sort(results,
- (a, b) -> Long.compare(b.getTimestamp(), a.getTimestamp()));
- } else {
- if (maxNum == 1) {
- // Most of the caller might be only interested with the most recent one
- ApplicationExitInfo r = map.valueAt(0);
- for (int i = 1; i < numRep; i++) {
- ApplicationExitInfo t = map.valueAt(i);
- if (r.getTimestamp() < t.getTimestamp()) {
- r = t;
- }
- }
- results.add(r);
- } else {
- // Huh, need to sort it out then.
- ArrayList<ApplicationExitInfo> list = mTmpInfoList2;
- list.clear();
- for (int i = 0; i < numRep; i++) {
- list.add(map.valueAt(i));
- }
- Collections.sort(list,
- (a, b) -> Long.compare(b.getTimestamp(), a.getTimestamp()));
- for (int i = 0; i < maxNum; i++) {
- results.add(list.get(i));
- }
- list.clear();
+ for (int i = 0, size = mExitInfos.size(); i < size; i++) {
+ ApplicationExitInfo info = mExitInfos.get(i);
+ if (info.getPid() == filterPid) {
+ mTmpInfoList2.add(info);
}
}
}
- }
- @GuardedBy("mLock")
- void getExitInfoLocked(final int filterPid, final int maxNum,
- ArrayList<ApplicationExitInfo> results) {
- getInfosLocked(mInfos, filterPid, maxNum, results);
- }
-
- @GuardedBy("mLock")
- void addInfoLocked(SparseArray<ApplicationExitInfo> map, ApplicationExitInfo info) {
- int size;
- if ((size = map.size()) >= mMaxCapacity) {
- int oldestIndex = -1;
- long oldestTimeStamp = Long.MAX_VALUE;
- for (int i = 0; i < size; i++) {
- ApplicationExitInfo r = map.valueAt(i);
- if (r.getTimestamp() < oldestTimeStamp) {
- oldestTimeStamp = r.getTimestamp();
- oldestIndex = i;
- }
- }
- if (oldestIndex >= 0) {
- final File traceFile = map.valueAt(oldestIndex).getTraceFile();
- if (traceFile != null) {
- traceFile.delete();
- }
- map.removeAt(oldestIndex);
- }
+ Collections.sort(
+ mTmpInfoList2, (a, b) -> Long.compare(b.getTimestamp(), a.getTimestamp()));
+ if (maxNum <= 0) {
+ results.addAll(mTmpInfoList2);
+ return;
}
+
+ int elementsToRemove = mTmpInfoList2.size() - maxNum;
+ for (int i = 0; i < elementsToRemove; i++) {
+ mTmpInfoList2.removeLast();
+ }
+ results.addAll(mTmpInfoList2);
+ }
+
+ @VisibleForTesting
+ @GuardedBy("mLock")
+ void addExitInfoLocked(ApplicationExitInfo info) {
// Claim the state information if there is any
int uid = info.getPackageUid();
// SDK sandbox app states and app traces are stored under real UID
@@ -1420,24 +1402,39 @@
if (info.getTraceFile() == null) {
info.setTraceFile(findAndRemoveFromSparse2dArray(mActiveAppTraces, uid, pid));
}
-
info.setAppTraceRetriever(mAppTraceRetriever);
- map.append(pid, info);
+
+ mExitInfos.add(info);
+ if (mExitInfos.size() <= mMaxCapacity) {
+ return;
+ }
+
+ ApplicationExitInfo oldest = null;
+ for (int i = 0, size = mExitInfos.size(); i < size; i++) {
+ ApplicationExitInfo info2 = mExitInfos.get(i);
+ if (oldest == null || info2.getTimestamp() < oldest.getTimestamp()) {
+ oldest = info2;
+ }
+ }
+ File traceFile = oldest.getTraceFile();
+ if (traceFile != null) {
+ traceFile.delete();
+ }
+ mExitInfos.remove(oldest);
}
@GuardedBy("mLock")
- void addExitInfoLocked(ApplicationExitInfo info) {
- addInfoLocked(mInfos, info);
- }
-
- @GuardedBy("mLock")
- void addRecoverableCrashLocked(ApplicationExitInfo info) {
- addInfoLocked(mRecoverableCrashes, info);
+ ApplicationExitInfo getLastExitInfoForPid(final int pid) {
+ mTmpInfoList.clear();
+ getExitInfosLocked(pid, /* maxNum */ 1, mTmpInfoList);
+ ApplicationExitInfo info = mTmpInfoList.size() == 0 ? null : mTmpInfoList.getFirst();
+ mTmpInfoList.clear();
+ return info;
}
@GuardedBy("mLock")
boolean appendTraceIfNecessaryLocked(final int pid, final File traceFile) {
- final ApplicationExitInfo r = mInfos.get(pid);
+ final ApplicationExitInfo r = getLastExitInfoForPid(pid);
if (r != null) {
r.setTraceFile(traceFile);
r.setAppTraceRetriever(mAppTraceRetriever);
@@ -1447,49 +1444,36 @@
}
@GuardedBy("mLock")
- void destroyLocked(SparseArray<ApplicationExitInfo> map) {
- for (int i = map.size() - 1; i >= 0; i--) {
- ApplicationExitInfo ai = map.valueAt(i);
- final File traceFile = ai.getTraceFile();
+ void destroyLocked() {
+ for (int i = 0, size = mExitInfos.size(); i < size; i++) {
+ ApplicationExitInfo info = mExitInfos.get(i);
+ final File traceFile = info.getTraceFile();
if (traceFile != null) {
traceFile.delete();
}
- ai.setTraceFile(null);
- ai.setAppTraceRetriever(null);
+ info.setTraceFile(null);
+ info.setAppTraceRetriever(null);
}
}
+ /**
+ * Go through each record in an *unspecified* order, execute `callback()` on each element,
+ * and potentially do some action (stopping iteration, removing the element, etc.) based on
+ * the return value of the callback.
+ */
@GuardedBy("mLock")
- void destroyLocked() {
- destroyLocked(mInfos);
- destroyLocked(mRecoverableCrashes);
- }
-
- @GuardedBy("mLock")
- void forEachRecordLocked(final BiFunction<Integer, ApplicationExitInfo, Integer> callback) {
+ void forEachRecordLocked(final Function<ApplicationExitInfo, Integer> callback) {
if (callback == null) return;
- for (int i = mInfos.size() - 1; i >= 0; i--) {
- switch (callback.apply(mInfos.keyAt(i), mInfos.valueAt(i))) {
+ for (int i = mExitInfos.size() - 1; i >= 0; i--) {
+ ApplicationExitInfo info = mExitInfos.get(i);
+ switch (callback.apply(info)) {
case FOREACH_ACTION_STOP_ITERATION: return;
case FOREACH_ACTION_REMOVE_ITEM:
- final File traceFile = mInfos.valueAt(i).getTraceFile();
- if (traceFile != null) {
+ File traceFile;
+ if ((traceFile = info.getTraceFile()) != null) {
traceFile.delete();
}
- mInfos.removeAt(i);
- break;
- }
- }
- for (int i = mRecoverableCrashes.size() - 1; i >= 0; i--) {
- switch (callback.apply(
- mRecoverableCrashes.keyAt(i), mRecoverableCrashes.valueAt(i))) {
- case FOREACH_ACTION_STOP_ITERATION: return;
- case FOREACH_ACTION_REMOVE_ITEM:
- final File traceFile = mRecoverableCrashes.valueAt(i).getTraceFile();
- if (traceFile != null) {
- traceFile.delete();
- }
- mRecoverableCrashes.removeAt(i);
+ mExitInfos.remove(info);
break;
}
}
@@ -1497,30 +1481,20 @@
@GuardedBy("mLock")
void dumpLocked(PrintWriter pw, String prefix, SimpleDateFormat sdf) {
- ArrayList<ApplicationExitInfo> list = new ArrayList<ApplicationExitInfo>();
- for (int i = mInfos.size() - 1; i >= 0; i--) {
- list.add(mInfos.valueAt(i));
+ mTmpInfoList.clear();
+ getExitInfosLocked(/* filterPid */ 0, /* maxNum */ 0, mTmpInfoList);
+ for (int i = 0, size = mTmpInfoList.size(); i < size; i++) {
+ mTmpInfoList.get(i).dump(pw, prefix + " ", "#" + i, sdf);
}
- for (int i = mRecoverableCrashes.size() - 1; i >= 0; i--) {
- list.add(mRecoverableCrashes.valueAt(i));
- }
- Collections.sort(list, (a, b) -> Long.compare(b.getTimestamp(), a.getTimestamp()));
- int size = list.size();
- for (int i = 0; i < size; i++) {
- list.get(i).dump(pw, prefix + " ", "#" + i, sdf);
- }
+ mTmpInfoList.clear();
}
@GuardedBy("mLock")
void writeToProto(ProtoOutputStream proto, long fieldId) {
long token = proto.start(fieldId);
proto.write(AppsExitInfoProto.Package.User.UID, mUid);
- for (int i = 0; i < mInfos.size(); i++) {
- mInfos.valueAt(i).writeToProto(proto, AppsExitInfoProto.Package.User.APP_EXIT_INFO);
- }
- for (int i = 0; i < mRecoverableCrashes.size(); i++) {
- mRecoverableCrashes.valueAt(i).writeToProto(
- proto, AppsExitInfoProto.Package.User.APP_RECOVERABLE_CRASH);
+ for (int i = 0, size = mExitInfos.size(); i < size; i++) {
+ mExitInfos.get(i).writeToProto(proto, AppsExitInfoProto.Package.User.APP_EXIT_INFO);
}
proto.end(token);
}
@@ -1539,14 +1513,7 @@
case (int) AppsExitInfoProto.Package.User.APP_EXIT_INFO: {
ApplicationExitInfo info = new ApplicationExitInfo();
info.readFromProto(proto, AppsExitInfoProto.Package.User.APP_EXIT_INFO);
- mInfos.put(info.getPid(), info);
- break;
- }
- case (int) AppsExitInfoProto.Package.User.APP_RECOVERABLE_CRASH: {
- ApplicationExitInfo info = new ApplicationExitInfo();
- info.readFromProto(
- proto, AppsExitInfoProto.Package.User.APP_RECOVERABLE_CRASH);
- mRecoverableCrashes.put(info.getPid(), info);
+ mExitInfos.add(info);
break;
}
}
@@ -1554,24 +1521,6 @@
proto.end(token);
return mUid;
}
-
- @GuardedBy("mLock")
- List<ApplicationExitInfo> toListLocked(List<ApplicationExitInfo> list, int filterPid) {
- if (list == null) {
- list = new ArrayList<ApplicationExitInfo>();
- }
- for (int i = mInfos.size() - 1; i >= 0; i--) {
- if (filterPid == 0 || filterPid == mInfos.keyAt(i)) {
- list.add(mInfos.valueAt(i));
- }
- }
- for (int i = mRecoverableCrashes.size() - 1; i >= 0; i--) {
- if (filterPid == 0 || filterPid == mRecoverableCrashes.keyAt(i)) {
- list.add(mRecoverableCrashes.valueAt(i));
- }
- }
- return list;
- }
}
/**
@@ -1750,7 +1699,11 @@
case MSG_APP_RECOVERABLE_CRASH: {
ApplicationExitInfo raw = (ApplicationExitInfo) msg.obj;
synchronized (mLock) {
- handleNoteAppRecoverableCrashLocked(raw);
+ // Unlike MSG_APP_KILL, this is a recoverable crash, and
+ // so we want to bypass the statsd app-kill logging.
+ // Hence, call `addExitInfoLocked()` directly instead of
+ // `handleNoteAppKillLocked()`.
+ addExitInfoLocked(raw);
}
recycleRawRecord(raw);
}
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 684cb24..6d1983e 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -783,9 +783,11 @@
AudioSystem.DEVICE_OUT_HDMI_EARC
));
+ private final Object mAbsoluteVolumeDeviceInfoMapLock = new Object();
// Devices where the framework sends a full scale audio signal, and controls the volume of
// the external audio system separately.
// For possible volume behaviors, see {@link AudioManager.AbsoluteDeviceVolumeBehavior}.
+ @GuardedBy("mAbsoluteVolumeDeviceInfoMapLock")
Map<Integer, AbsoluteVolumeDeviceInfo> mAbsoluteVolumeDeviceInfoMap = new ArrayMap<>();
/**
@@ -3715,9 +3717,8 @@
int oldIndex = mStreamStates[streamType].getIndex(device);
// Check if the volume adjustment should be handled by an absolute volume controller instead
- if (isAbsoluteVolumeDevice(device)
- && (flags & AudioManager.FLAG_ABSOLUTE_VOLUME) == 0) {
- AbsoluteVolumeDeviceInfo info = mAbsoluteVolumeDeviceInfoMap.get(device);
+ if (isAbsoluteVolumeDevice(device) && (flags & AudioManager.FLAG_ABSOLUTE_VOLUME) == 0) {
+ final AbsoluteVolumeDeviceInfo info = getAbsoluteVolumeDeviceInfo(device);
if (info.mHandlesVolumeAdjustment) {
dispatchAbsoluteVolumeAdjusted(streamType, info, oldIndex, direction,
keyEventMode);
@@ -3784,7 +3785,7 @@
mDeviceBroker.postSetAvrcpAbsoluteVolumeIndex(newIndex / 10);
} else if (isAbsoluteVolumeDevice(device)
&& (flags & AudioManager.FLAG_ABSOLUTE_VOLUME) == 0) {
- AbsoluteVolumeDeviceInfo info = mAbsoluteVolumeDeviceInfoMap.get(device);
+ final AbsoluteVolumeDeviceInfo info = getAbsoluteVolumeDeviceInfo(device);
dispatchAbsoluteVolumeChanged(streamType, info, newIndex);
}
@@ -4787,7 +4788,7 @@
mDeviceBroker.postSetAvrcpAbsoluteVolumeIndex(index / 10);
} else if (isAbsoluteVolumeDevice(device)
&& ((flags & AudioManager.FLAG_ABSOLUTE_VOLUME) == 0)) {
- AbsoluteVolumeDeviceInfo info = mAbsoluteVolumeDeviceInfoMap.get(device);
+ final AbsoluteVolumeDeviceInfo info = getAbsoluteVolumeDeviceInfo(device);
dispatchAbsoluteVolumeChanged(streamType, info, index);
}
@@ -7575,7 +7576,8 @@
if (register) {
AbsoluteVolumeDeviceInfo info = new AbsoluteVolumeDeviceInfo(
device, volumes, cb, handlesVolumeAdjustment, deviceVolumeBehavior);
- AbsoluteVolumeDeviceInfo oldInfo = mAbsoluteVolumeDeviceInfoMap.get(deviceOut);
+ final AbsoluteVolumeDeviceInfo oldInfo = getAbsoluteVolumeDeviceInfo(deviceOut);
+
boolean volumeBehaviorChanged = (oldInfo == null)
|| (oldInfo.mDeviceVolumeBehavior != deviceVolumeBehavior);
if (volumeBehaviorChanged) {
@@ -7735,8 +7737,10 @@
if (mAbsVolumeMultiModeCaseDevices.contains(audioSystemDeviceOut)) {
return AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_MULTI_MODE;
}
- if (mAbsoluteVolumeDeviceInfoMap.containsKey(audioSystemDeviceOut)) {
- return mAbsoluteVolumeDeviceInfoMap.get(audioSystemDeviceOut).mDeviceVolumeBehavior;
+ synchronized (mAbsoluteVolumeDeviceInfoMapLock) {
+ if (mAbsoluteVolumeDeviceInfoMap.containsKey(audioSystemDeviceOut)) {
+ return mAbsoluteVolumeDeviceInfoMap.get(audioSystemDeviceOut).mDeviceVolumeBehavior;
+ }
}
if (isA2dpAbsoluteVolumeDevice(audioSystemDeviceOut)
@@ -11774,10 +11778,12 @@
}
private Set<Integer> getAbsoluteVolumeDevicesWithBehavior(int behavior) {
- return mAbsoluteVolumeDeviceInfoMap.entrySet().stream()
- .filter(entry -> entry.getValue().mDeviceVolumeBehavior == behavior)
- .map(Map.Entry::getKey)
- .collect(Collectors.toSet());
+ synchronized (mAbsoluteVolumeDeviceInfoMapLock) {
+ return mAbsoluteVolumeDeviceInfoMap.entrySet().stream()
+ .filter(entry -> entry.getValue().mDeviceVolumeBehavior == behavior)
+ .map(Map.Entry::getKey)
+ .collect(Collectors.toSet());
+ }
}
private String dumpDeviceTypes(@NonNull Set<Integer> deviceTypes) {
@@ -14270,14 +14276,26 @@
}
/**
+ * Returns the input device which uses absolute volume behavior, including its variants,
+ * or {@code null} if there is no mapping for the device type
+ */
+ @Nullable
+ private AbsoluteVolumeDeviceInfo getAbsoluteVolumeDeviceInfo(int deviceType) {
+ synchronized (mAbsoluteVolumeDeviceInfoMapLock) {
+ return mAbsoluteVolumeDeviceInfoMap.get(deviceType);
+ }
+ }
+
+ /**
* Returns whether the input device uses absolute volume behavior, including its variants.
* For included volume behaviors, see {@link AudioManager.AbsoluteDeviceVolumeBehavior}.
- *
- * This is distinct from Bluetooth A2DP absolute volume behavior
+ * <p>This is distinct from Bluetooth A2DP absolute volume behavior
* ({@link #isA2dpAbsoluteVolumeDevice}).
*/
private boolean isAbsoluteVolumeDevice(int deviceType) {
- return mAbsoluteVolumeDeviceInfoMap.containsKey(deviceType);
+ synchronized (mAbsoluteVolumeDeviceInfoMapLock) {
+ return mAbsoluteVolumeDeviceInfoMap.containsKey(deviceType);
+ }
}
/**
@@ -14389,7 +14407,9 @@
+ AudioDeviceVolumeManager.volumeBehaviorName(info.mDeviceVolumeBehavior)
);
}
- mAbsoluteVolumeDeviceInfoMap.put(audioSystemDeviceOut, info);
+ synchronized (mAbsoluteVolumeDeviceInfoMapLock) {
+ mAbsoluteVolumeDeviceInfoMap.put(audioSystemDeviceOut, info);
+ }
}
private AbsoluteVolumeDeviceInfo removeAudioSystemDeviceOutFromAbsVolumeDevices(
@@ -14398,7 +14418,10 @@
Log.d(TAG, "Removing DeviceType: 0x" + Integer.toHexString(audioSystemDeviceOut)
+ " from mAbsoluteVolumeDeviceInfoMap");
}
- return mAbsoluteVolumeDeviceInfoMap.remove(audioSystemDeviceOut);
+
+ synchronized (mAbsoluteVolumeDeviceInfoMapLock) {
+ return mAbsoluteVolumeDeviceInfoMap.remove(audioSystemDeviceOut);
+ }
}
//====================
diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java
index 0e81eb9..8e8a037 100644
--- a/services/core/java/com/android/server/biometrics/BiometricService.java
+++ b/services/core/java/com/android/server/biometrics/BiometricService.java
@@ -31,8 +31,8 @@
import android.app.UserSwitchObserver;
import android.app.admin.DevicePolicyManager;
import android.app.trust.ITrustManager;
-import android.content.ContentResolver;
import android.content.ComponentName;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
@@ -233,6 +233,7 @@
private static final boolean DEFAULT_KEYGUARD_ENABLED = true;
private static final boolean DEFAULT_APP_ENABLED = true;
private static final boolean DEFAULT_ALWAYS_REQUIRE_CONFIRMATION = false;
+ private static final boolean DEFAULT_MANDATORY_BIOMETRICS_STATUS = false;
// Some devices that shipped before S already have face-specific settings. Instead of
// migrating, which is complicated, let's just keep using the existing settings.
@@ -253,6 +254,8 @@
Settings.Secure.getUriFor(Settings.Secure.BIOMETRIC_KEYGUARD_ENABLED);
private final Uri BIOMETRIC_APP_ENABLED =
Settings.Secure.getUriFor(Settings.Secure.BIOMETRIC_APP_ENABLED);
+ private final Uri MANDATORY_BIOMETRICS_ENABLED =
+ Settings.Secure.getUriFor(Settings.Secure.MANDATORY_BIOMETRICS);
private final ContentResolver mContentResolver;
private final List<BiometricService.EnabledOnKeyguardCallback> mCallbacks;
@@ -260,6 +263,7 @@
private final Map<Integer, Boolean> mBiometricEnabledOnKeyguard = new HashMap<>();
private final Map<Integer, Boolean> mBiometricEnabledForApps = new HashMap<>();
private final Map<Integer, Boolean> mFaceAlwaysRequireConfirmation = new HashMap<>();
+ private final Map<Integer, Boolean> mMandatoryBiometricsEnabled = new HashMap<>();
/**
* Creates a content observer.
@@ -281,6 +285,9 @@
mUseLegacyFaceOnlySettings =
Build.VERSION.DEVICE_INITIAL_SDK_INT <= Build.VERSION_CODES.Q
&& hasFace && !hasFingerprint;
+ mMandatoryBiometricsEnabled.put(context.getUserId(), Settings.Secure.getIntForUser(
+ mContentResolver, Settings.Secure.MANDATORY_BIOMETRICS,
+ DEFAULT_MANDATORY_BIOMETRICS_STATUS ? 1 : 0, context.getUserId()) != 0);
updateContentObserver();
}
@@ -311,6 +318,10 @@
false /* notifyForDescendants */,
this /* observer */,
UserHandle.USER_ALL);
+ mContentResolver.registerContentObserver(MANDATORY_BIOMETRICS_ENABLED,
+ false /* notifyForDescendants */,
+ this /* observer */,
+ UserHandle.USER_ALL);
}
@Override
@@ -353,6 +364,12 @@
Settings.Secure.BIOMETRIC_APP_ENABLED,
DEFAULT_APP_ENABLED ? 1 : 0 /* default */,
userId) != 0);
+ } else if (MANDATORY_BIOMETRICS_ENABLED.equals(uri)) {
+ mMandatoryBiometricsEnabled.put(userId, Settings.Secure.getIntForUser(
+ mContentResolver,
+ Settings.Secure.MANDATORY_BIOMETRICS,
+ DEFAULT_MANDATORY_BIOMETRICS_STATUS ? 1 : 0 /* default */,
+ userId) != 0);
}
}
@@ -394,6 +411,11 @@
}
}
+ public boolean getMandatoryBiometricsEnabledForUser(int userId) {
+ return mMandatoryBiometricsEnabled.getOrDefault(userId,
+ DEFAULT_MANDATORY_BIOMETRICS_STATUS);
+ }
+
void notifyEnabledOnKeyguardCallbacks(int userId) {
List<EnabledOnKeyguardCallback> callbacks = mCallbacks;
for (int i = 0; i < callbacks.size(); i++) {
diff --git a/services/core/java/com/android/server/biometrics/PreAuthInfo.java b/services/core/java/com/android/server/biometrics/PreAuthInfo.java
index f085647..b9e6563 100644
--- a/services/core/java/com/android/server/biometrics/PreAuthInfo.java
+++ b/services/core/java/com/android/server/biometrics/PreAuthInfo.java
@@ -29,11 +29,13 @@
import android.content.Context;
import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.biometrics.BiometricManager;
+import android.hardware.biometrics.Flags;
import android.hardware.biometrics.PromptInfo;
import android.os.RemoteException;
import android.util.Pair;
import android.util.Slog;
+import com.android.internal.R;
import com.android.server.biometrics.sensors.LockoutTracker;
import java.lang.annotation.Retention;
@@ -59,6 +61,7 @@
static final int BIOMETRIC_LOCKOUT_TIMED = 10;
static final int BIOMETRIC_LOCKOUT_PERMANENT = 11;
static final int BIOMETRIC_SENSOR_PRIVACY_ENABLED = 12;
+ static final int MANDATORY_BIOMETRIC_UNAVAILABLE_ERROR = 13;
private static final String TAG = "BiometricService/PreAuthInfo";
final boolean credentialRequested;
// Sensors that can be used for this request (e.g. strong enough, enrolled, enabled).
@@ -73,12 +76,14 @@
private final boolean mBiometricRequested;
private final int mBiometricStrengthRequested;
private final BiometricCameraManager mBiometricCameraManager;
+ private final boolean mOnlyMandatoryBiometricsRequested;
private PreAuthInfo(boolean biometricRequested, int biometricStrengthRequested,
boolean credentialRequested, List<BiometricSensor> eligibleSensors,
List<Pair<BiometricSensor, Integer>> ineligibleSensors, boolean credentialAvailable,
- boolean confirmationRequested, boolean ignoreEnrollmentState, int userId,
- Context context, BiometricCameraManager biometricCameraManager) {
+ PromptInfo promptInfo, int userId, Context context,
+ BiometricCameraManager biometricCameraManager,
+ boolean isOnlyMandatoryBiometricsRequested) {
mBiometricRequested = biometricRequested;
mBiometricStrengthRequested = biometricStrengthRequested;
mBiometricCameraManager = biometricCameraManager;
@@ -87,10 +92,11 @@
this.eligibleSensors = eligibleSensors;
this.ineligibleSensors = ineligibleSensors;
this.credentialAvailable = credentialAvailable;
- this.confirmationRequested = confirmationRequested;
- this.ignoreEnrollmentState = ignoreEnrollmentState;
+ this.confirmationRequested = promptInfo.isConfirmationRequested();
+ this.ignoreEnrollmentState = promptInfo.isIgnoreEnrollmentState();
this.userId = userId;
this.context = context;
+ this.mOnlyMandatoryBiometricsRequested = isOnlyMandatoryBiometricsRequested;
}
static PreAuthInfo create(ITrustManager trustManager,
@@ -102,7 +108,16 @@
BiometricCameraManager biometricCameraManager)
throws RemoteException {
- final boolean confirmationRequested = promptInfo.isConfirmationRequested();
+ final boolean isOnlyMandatoryBiometricsRequested = promptInfo.getAuthenticators()
+ == BiometricManager.Authenticators.MANDATORY_BIOMETRICS;
+
+ if (dropCredentialFallback(promptInfo.getAuthenticators(),
+ settingObserver.getMandatoryBiometricsEnabledForUser(userId),
+ trustManager)) {
+ promptInfo.setAuthenticators(BiometricManager.Authenticators.BIOMETRIC_STRONG);
+ promptInfo.setNegativeButtonText(context.getString(R.string.cancel));
+ }
+
final boolean biometricRequested = Utils.isBiometricRequested(promptInfo);
final int requestedStrength = Utils.getPublicBiometricStrength(promptInfo);
final boolean credentialRequested = Utils.isCredentialRequested(promptInfo);
@@ -150,8 +165,27 @@
}
return new PreAuthInfo(biometricRequested, requestedStrength, credentialRequested,
- eligibleSensors, ineligibleSensors, credentialAvailable, confirmationRequested,
- promptInfo.isIgnoreEnrollmentState(), userId, context, biometricCameraManager);
+ eligibleSensors, ineligibleSensors, credentialAvailable, promptInfo, userId,
+ context, biometricCameraManager, isOnlyMandatoryBiometricsRequested);
+ }
+
+ private static boolean dropCredentialFallback(int authenticators,
+ boolean isMandatoryBiometricsEnabled, ITrustManager trustManager) {
+ final boolean isMandatoryBiometricsRequested =
+ (authenticators & BiometricManager.Authenticators.MANDATORY_BIOMETRICS)
+ == BiometricManager.Authenticators.MANDATORY_BIOMETRICS;
+ if (Flags.mandatoryBiometrics() && isMandatoryBiometricsEnabled
+ && isMandatoryBiometricsRequested) {
+ try {
+ final boolean isInSignificantPlace = trustManager.isInSignificantPlace();
+ return !isInSignificantPlace;
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Remote exception while trying to check "
+ + "if user is in a trusted location.");
+ }
+ }
+
+ return false;
}
/**
@@ -353,6 +387,25 @@
status = CREDENTIAL_NOT_ENROLLED;
}
}
+ } else if (Flags.mandatoryBiometrics() && mOnlyMandatoryBiometricsRequested) {
+ if (!eligibleSensors.isEmpty()) {
+ for (BiometricSensor sensor : eligibleSensors) {
+ modality |= sensor.modality;
+ }
+
+ if (modality == TYPE_FACE && cameraPrivacyEnabled) {
+ // If the only modality requested is face, credential is unavailable,
+ // and the face sensor privacy is enabled then return
+ // BIOMETRIC_SENSOR_PRIVACY_ENABLED.
+ //
+ // Note: This sensor will not be eligible for calls to authenticate.
+ status = BIOMETRIC_SENSOR_PRIVACY_ENABLED;
+ } else {
+ status = AUTHENTICATOR_OK;
+ }
+ } else {
+ status = MANDATORY_BIOMETRIC_UNAVAILABLE_ERROR;
+ }
} else if (mBiometricRequested) {
if (!eligibleSensors.isEmpty()) {
for (BiometricSensor sensor : eligibleSensors) {
@@ -509,7 +562,8 @@
CREDENTIAL_NOT_ENROLLED,
BIOMETRIC_LOCKOUT_TIMED,
BIOMETRIC_LOCKOUT_PERMANENT,
- BIOMETRIC_SENSOR_PRIVACY_ENABLED})
+ BIOMETRIC_SENSOR_PRIVACY_ENABLED,
+ MANDATORY_BIOMETRIC_UNAVAILABLE_ERROR})
@Retention(RetentionPolicy.SOURCE)
@interface AuthenticatorStatus {
}
diff --git a/services/core/java/com/android/server/biometrics/Utils.java b/services/core/java/com/android/server/biometrics/Utils.java
index 4af30a9..df29ca4 100644
--- a/services/core/java/com/android/server/biometrics/Utils.java
+++ b/services/core/java/com/android/server/biometrics/Utils.java
@@ -140,6 +140,14 @@
}
/**
+ * @param authenticators composed of one or more values from {@link Authenticators}
+ * @return true if mandatory biometrics is requested
+ */
+ static boolean isMandatoryBiometricsRequested(@Authenticators.Types int authenticators) {
+ return (authenticators & Authenticators.MANDATORY_BIOMETRICS) != 0;
+ }
+
+ /**
* @param promptInfo should be first processed by
* {@link #combineAuthenticatorBundles(PromptInfo)}
* @return true if device credential is allowed.
@@ -242,7 +250,8 @@
// Check if any of the non-biometric and non-credential bits are set. If so, this is
// invalid.
final int testBits = ~(Authenticators.DEVICE_CREDENTIAL
- | Authenticators.BIOMETRIC_MIN_STRENGTH);
+ | Authenticators.BIOMETRIC_MIN_STRENGTH
+ | Authenticators.MANDATORY_BIOMETRICS);
if ((authenticators & testBits) != 0) {
Slog.e(BiometricService.TAG, "Non-biometric, non-credential bits found."
+ " Authenticators: " + authenticators);
@@ -259,6 +268,8 @@
return true;
} else if (biometricBits == Authenticators.BIOMETRIC_WEAK) {
return true;
+ } else if (isMandatoryBiometricsRequested(authenticators)) {
+ return true;
}
Slog.e(BiometricService.TAG, "Unsupported biometric flags. Authenticators: "
diff --git a/services/core/java/com/android/server/compat/PlatformCompat.java b/services/core/java/com/android/server/compat/PlatformCompat.java
index f8fd0a0..22b85d4 100644
--- a/services/core/java/com/android/server/compat/PlatformCompat.java
+++ b/services/core/java/com/android/server/compat/PlatformCompat.java
@@ -83,9 +83,10 @@
@VisibleForTesting
PlatformCompat(Context context, CompatConfig compatConfig,
- AndroidBuildClassifier buildClassifier) {
+ AndroidBuildClassifier buildClassifier,
+ ChangeReporter changeReporter) {
mContext = context;
- mChangeReporter = new ChangeReporter(ChangeReporter.SOURCE_SYSTEM_SERVER);
+ mChangeReporter = changeReporter;
mCompatConfig = compatConfig;
mBuildClassifier = buildClassifier;
@@ -96,8 +97,11 @@
@EnforcePermission(LOG_COMPAT_CHANGE)
public void reportChange(long changeId, ApplicationInfo appInfo) {
super.reportChange_enforcePermission();
-
- reportChangeInternal(changeId, appInfo.uid, ChangeReporter.STATE_LOGGED);
+ reportChangeInternal(
+ changeId,
+ appInfo.uid,
+ appInfo.isSystemApp(),
+ ChangeReporter.STATE_LOGGED);
}
@Override
@@ -108,7 +112,11 @@
ApplicationInfo appInfo = getApplicationInfo(packageName, userId);
if (appInfo != null) {
- reportChangeInternal(changeId, appInfo.uid, ChangeReporter.STATE_LOGGED);
+ reportChangeInternal(
+ changeId,
+ appInfo.uid,
+ appInfo.isSystemApp(),
+ ChangeReporter.STATE_LOGGED);
}
}
@@ -117,7 +125,7 @@
public void reportChangeByUid(long changeId, int uid) {
super.reportChangeByUid_enforcePermission();
- reportChangeInternal(changeId, uid, ChangeReporter.STATE_LOGGED);
+ reportChangeInternal(changeId, uid, false, ChangeReporter.STATE_LOGGED);
}
/**
@@ -128,8 +136,8 @@
* @param uid of the user
* @param state of the change - enabled/disabled/logged
*/
- private void reportChangeInternal(long changeId, int uid, int state) {
- mChangeReporter.reportChange(uid, changeId, state, true);
+ private void reportChangeInternal(long changeId, int uid, boolean isKnownSystemApp, int state) {
+ mChangeReporter.reportChange(uid, changeId, state, isKnownSystemApp, true);
}
@Override
@@ -190,7 +198,11 @@
if (appInfo != null) {
boolean isTargetingLatestSdk =
mCompatConfig.isChangeTargetingLatestSdk(c, appInfo.targetSdkVersion);
- mChangeReporter.reportChange(appInfo.uid, changeId, state, isTargetingLatestSdk);
+ mChangeReporter.reportChange(appInfo.uid,
+ changeId,
+ state,
+ appInfo.isSystemApp(),
+ isTargetingLatestSdk);
}
return enabled;
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index b436c8b..f297708 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -46,6 +46,10 @@
import static android.app.Notification.FLAG_ONLY_ALERT_ONCE;
import static android.app.Notification.FLAG_USER_INITIATED_JOB;
import static android.app.NotificationChannel.CONVERSATION_CHANNEL_ID_FORMAT;
+import static android.app.NotificationChannel.NEWS_ID;
+import static android.app.NotificationChannel.PROMOTIONS_ID;
+import static android.app.NotificationChannel.RECS_ID;
+import static android.app.NotificationChannel.SOCIAL_MEDIA_ID;
import static android.app.NotificationManager.ACTION_APP_BLOCK_STATE_CHANGED;
import static android.app.NotificationManager.ACTION_AUTOMATIC_ZEN_RULE_STATUS_CHANGED;
import static android.app.NotificationManager.ACTION_CONSOLIDATED_NOTIFICATION_POLICY_CHANGED;
@@ -98,6 +102,11 @@
import static android.os.UserHandle.USER_ALL;
import static android.os.UserHandle.USER_NULL;
import static android.os.UserHandle.USER_SYSTEM;
+import static android.service.notification.Adjustment.KEY_TYPE;
+import static android.service.notification.Adjustment.TYPE_CONTENT_RECOMMENDATION;
+import static android.service.notification.Adjustment.TYPE_NEWS;
+import static android.service.notification.Adjustment.TYPE_PROMOTION;
+import static android.service.notification.Adjustment.TYPE_SOCIAL_MEDIA;
import static android.service.notification.Flags.callstyleCallbackApi;
import static android.service.notification.Flags.redactSensitiveNotificationsFromUntrustedListeners;
import static android.service.notification.Flags.redactSensitiveNotificationsBigTextStyle;
@@ -458,7 +467,8 @@
Adjustment.KEY_IMPORTANCE_PROPOSAL,
Adjustment.KEY_SENSITIVE_CONTENT,
Adjustment.KEY_RANKING_SCORE,
- Adjustment.KEY_NOT_CONVERSATION
+ Adjustment.KEY_NOT_CONVERSATION,
+ Adjustment.KEY_TYPE
};
static final String[] NON_BLOCKABLE_DEFAULT_ROLES = new String[] {
@@ -1023,7 +1033,7 @@
summary.getSbn().getNotification().color = summaryAttr.iconColor;
summary.getSbn().getNotification().visibility = summaryAttr.visibility;
mHandler.post(new EnqueueNotificationRunnable(userId, summary, isAppForeground,
- mPostNotificationTrackerFactory.newTracker(null)));
+ /* isAppProvided= */ false, mPostNotificationTrackerFactory.newTracker(null)));
}
}
@@ -1650,7 +1660,7 @@
// Force isAppForeground true here, because for sysui's purposes we
// want to adjust the flag behaviour.
mHandler.post(new EnqueueNotificationRunnable(r.getUser().getIdentifier(),
- r, true /* isAppForeground*/,
+ r, /* isAppForeground= */ true , /* isAppProvided= */ false,
mPostNotificationTrackerFactory.newTracker(null)));
}
}
@@ -1681,7 +1691,7 @@
// want to be able to adjust the flag behaviour.
mHandler.post(
new EnqueueNotificationRunnable(r.getUser().getIdentifier(), r,
- /* foreground= */ true,
+ /* foreground= */ true, /* isAppProvided= */ false,
mPostNotificationTrackerFactory.newTracker(null)));
}
}
@@ -2706,7 +2716,7 @@
enqueueNotificationInternal(r.getSbn().getPackageName(), r.getSbn().getOpPkg(),
r.getSbn().getUid(), r.getSbn().getInitialPid(), r.getSbn().getTag(),
r.getSbn().getId(), r.getSbn().getNotification(), userId, muteOnReturn,
- false /* byForegroundService */);
+ /* byForegroundService= */ false, /* isAppProvided= */ false);
} catch (Exception e) {
Slog.e(TAG, "Cannot un-snooze notification", e);
}
@@ -2851,6 +2861,7 @@
final boolean isAppForeground =
mActivityManager.getPackageImportance(pkg) == IMPORTANCE_FOREGROUND;
mHandler.post(new EnqueueNotificationRunnable(userId, r, isAppForeground,
+ /* isAppProvided= */ false,
mPostNotificationTrackerFactory.newTracker(null)));
}
}
@@ -3763,7 +3774,7 @@
Notification notification, int userId) throws RemoteException {
enqueueNotificationInternal(pkg, opPkg, Binder.getCallingUid(),
Binder.getCallingPid(), tag, id, notification, userId,
- false /* byForegroundService */);
+ /* byForegroundService= */ false, /* isAppProvided= */ true);
}
@Override
@@ -6608,6 +6619,30 @@
for (String removeKey : toRemove) {
adjustments.remove(removeKey);
}
+ if (android.service.notification.Flags.notificationClassification()
+ && adjustments.containsKey(KEY_TYPE)) {
+ NotificationChannel newChannel = null;
+ int type = adjustments.getInt(KEY_TYPE);
+ if (TYPE_NEWS == type) {
+ newChannel = mPreferencesHelper.getNotificationChannel(
+ r.getSbn().getPackageName(), r.getUid(), NEWS_ID, false);
+ } else if (TYPE_PROMOTION == type) {
+ newChannel = mPreferencesHelper.getNotificationChannel(
+ r.getSbn().getPackageName(), r.getUid(), PROMOTIONS_ID, false);
+ } else if (TYPE_SOCIAL_MEDIA == type) {
+ newChannel = mPreferencesHelper.getNotificationChannel(
+ r.getSbn().getPackageName(), r.getUid(), SOCIAL_MEDIA_ID, false);
+ } else if (TYPE_CONTENT_RECOMMENDATION == type) {
+ newChannel = mPreferencesHelper.getNotificationChannel(
+ r.getSbn().getPackageName(), r.getUid(), RECS_ID, false);
+ }
+ if (newChannel == null) {
+ adjustments.remove(KEY_TYPE);
+ } else {
+ // swap app provided type with the real thing
+ adjustments.putParcelable(KEY_TYPE, newChannel);
+ }
+ }
r.addAdjustment(adjustment);
if (adjustment.getSignals().containsKey(Adjustment.KEY_SENSITIVE_CONTENT)) {
logSensitiveAdjustmentReceived(isPosted,
@@ -7025,7 +7060,7 @@
public void enqueueNotification(String pkg, String opPkg, int callingUid, int callingPid,
String tag, int id, Notification notification, int userId) {
enqueueNotificationInternal(pkg, opPkg, callingUid, callingPid, tag, id, notification,
- userId, false /* byForegroundService */);
+ userId, /* byForegroundService= */ false , /* isAppProvided= */ true);
}
@Override
@@ -7033,7 +7068,7 @@
String tag, int id, Notification notification, int userId,
boolean byForegroundService) {
enqueueNotificationInternal(pkg, opPkg, callingUid, callingPid, tag, id, notification,
- userId, byForegroundService);
+ userId, byForegroundService, /* isAppProvided= */ true);
}
@Override
@@ -7245,7 +7280,8 @@
r.getSbn().getInitialPid(), r.getSbn().getTag(),
r.getSbn().getId(), r.getNotification(),
r.getSbn().getUserId(), /* postSilently= */ true,
- /* byForegroundService= */ false);
+ /* byForegroundService= */ false,
+ /* isAppProvided= */ false);
}
int getNumNotificationChannelsForPackage(String pkg, int uid, boolean includeDeleted) {
@@ -7306,19 +7342,21 @@
void enqueueNotificationInternal(final String pkg, final String opPkg, final int callingUid,
final int callingPid, final String tag, final int id, final Notification notification,
- int incomingUserId, boolean byForegroundService) {
+ int incomingUserId, boolean byForegroundService, boolean isAppProvided) {
enqueueNotificationInternal(pkg, opPkg, callingUid, callingPid, tag, id, notification,
- incomingUserId, false /* postSilently */, byForegroundService);
+ incomingUserId, false /* postSilently */, byForegroundService, isAppProvided);
}
void enqueueNotificationInternal(final String pkg, final String opPkg, final int callingUid,
final int callingPid, final String tag, final int id, final Notification notification,
- int incomingUserId, boolean postSilently, boolean byForegroundService) {
+ int incomingUserId, boolean postSilently, boolean byForegroundService,
+ boolean isAppProvided) {
PostNotificationTracker tracker = acquireWakeLockForPost(pkg, callingUid);
boolean enqueued = false;
try {
enqueued = enqueueNotificationInternal(pkg, opPkg, callingUid, callingPid, tag, id,
- notification, incomingUserId, postSilently, tracker, byForegroundService);
+ notification, incomingUserId, postSilently, tracker, byForegroundService,
+ isAppProvided);
} finally {
if (!enqueued) {
tracker.cancel();
@@ -7344,7 +7382,7 @@
private boolean enqueueNotificationInternal(final String pkg, final String opPkg, //HUI
final int callingUid, final int callingPid, final String tag, final int id,
final Notification notification, int incomingUserId, boolean postSilently,
- PostNotificationTracker tracker, boolean byForegroundService) {
+ PostNotificationTracker tracker, boolean byForegroundService, boolean isAppProvided) {
if (DBG) {
Slog.v(TAG, "enqueueNotificationInternal: pkg=" + pkg + " id=" + id
+ " notification=" + notification);
@@ -7545,7 +7583,8 @@
// Need escalated privileges to get package importance.
final int packageImportance = getPackageImportanceWithIdentity(pkg);
boolean isAppForeground = packageImportance == IMPORTANCE_FOREGROUND;
- mHandler.post(new EnqueueNotificationRunnable(userId, r, isAppForeground, tracker));
+ mHandler.post(new EnqueueNotificationRunnable(userId, r, isAppForeground,
+ /* isAppProvided= */ isAppProvided, tracker));
return true;
}
@@ -7925,6 +7964,7 @@
mHandler.post(
new EnqueueNotificationRunnable(
r.getUser().getIdentifier(), r, isAppForeground,
+ /* isAppProvided= */ false,
mPostNotificationTrackerFactory.newTracker(null)));
}
}
@@ -8495,13 +8535,15 @@
private final NotificationRecord r;
private final int userId;
private final boolean isAppForeground;
+ private final boolean isAppProvided;
private final PostNotificationTracker mTracker;
EnqueueNotificationRunnable(int userId, NotificationRecord r, boolean foreground,
- PostNotificationTracker tracker) {
+ boolean isAppProvided, PostNotificationTracker tracker) {
this.userId = userId;
this.r = r;
this.isAppForeground = foreground;
+ this.isAppProvided = isAppProvided;
this.mTracker = checkNotNull(tracker);
}
@@ -8586,9 +8628,10 @@
if (old != null) {
enqueueStatus = EVENTLOG_ENQUEUE_STATUS_UPDATE;
}
+ int appProvided = isAppProvided ? 1 : 0;
EventLogTags.writeNotificationEnqueue(callingUid, callingPid,
pkg, id, tag, userId, notification.toString(),
- enqueueStatus);
+ enqueueStatus, appProvided);
}
// tell the assistant service about the notification
@@ -8748,7 +8791,7 @@
// was not autogrouped onPost, to avoid an unnecessary sort.
// We add the autogroup key to the notification without a
// sort here, and it'll be sorted below with extractSignals.
- addAutogroupKeyLocked(key, /*requestSort=*/false);
+ addAutogroupKeyLocked(key, /* requestSort= */false);
}
}
}
@@ -11373,7 +11416,7 @@
record.getNotification().flags |= FLAG_ONLY_ALERT_ONCE;
mHandler.post(new EnqueueNotificationRunnable(record.getUser().getIdentifier(),
- record, isAppForeground,
+ record, isAppForeground, /* isAppProvided= */ false,
mPostNotificationTrackerFactory.newTracker(null)));
}
}
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index 0c6a6c8..0d4bdf6 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -710,7 +710,8 @@
if (signals.containsKey(Adjustment.KEY_SNOOZE_CRITERIA)) {
final ArrayList<SnoozeCriterion> snoozeCriterionList =
adjustment.getSignals().getParcelableArrayList(
- Adjustment.KEY_SNOOZE_CRITERIA, android.service.notification.SnoozeCriterion.class);
+ Adjustment.KEY_SNOOZE_CRITERIA,
+ android.service.notification.SnoozeCriterion.class);
setSnoozeCriteria(snoozeCriterionList);
EventLogTags.writeNotificationAdjusted(getKey(), Adjustment.KEY_SNOOZE_CRITERIA,
snoozeCriterionList.toString());
@@ -736,7 +737,8 @@
}
if (signals.containsKey(Adjustment.KEY_CONTEXTUAL_ACTIONS)) {
setSystemGeneratedSmartActions(
- signals.getParcelableArrayList(Adjustment.KEY_CONTEXTUAL_ACTIONS, android.app.Notification.Action.class));
+ signals.getParcelableArrayList(Adjustment.KEY_CONTEXTUAL_ACTIONS,
+ android.app.Notification.Action.class));
EventLogTags.writeNotificationAdjusted(getKey(),
Adjustment.KEY_CONTEXTUAL_ACTIONS,
getSystemGeneratedSmartActions().toString());
@@ -778,6 +780,14 @@
Adjustment.KEY_SENSITIVE_CONTENT,
Boolean.toString(mSensitiveContent));
}
+ if (android.service.notification.Flags.notificationClassification()
+ && signals.containsKey(Adjustment.KEY_TYPE)) {
+ updateNotificationChannel(signals.getParcelable(Adjustment.KEY_TYPE,
+ NotificationChannel.class));
+ EventLogTags.writeNotificationAdjusted(getKey(),
+ Adjustment.KEY_TYPE,
+ mChannel.getId());
+ }
if (!signals.isEmpty() && adjustment.getIssuer() != null) {
mAdjustmentIssuer = adjustment.getIssuer();
}
diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java
index 309e945..9ee05d8 100644
--- a/services/core/java/com/android/server/notification/PreferencesHelper.java
+++ b/services/core/java/com/android/server/notification/PreferencesHelper.java
@@ -22,11 +22,14 @@
import static android.app.NotificationManager.BUBBLE_PREFERENCE_ALL;
import static android.app.NotificationManager.BUBBLE_PREFERENCE_NONE;
import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
+import static android.app.NotificationManager.IMPORTANCE_LOW;
import static android.app.NotificationManager.IMPORTANCE_MAX;
import static android.app.NotificationManager.IMPORTANCE_NONE;
import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
import static android.os.UserHandle.USER_SYSTEM;
+import static android.service.notification.Flags.notificationClassification;
+
import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_CHANNEL_GROUP_PREFERENCES;
import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_CHANNEL_PREFERENCES;
import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_PREFERENCES;
@@ -514,6 +517,10 @@
Slog.e(TAG, "createDefaultChannelIfNeededLocked - Exception: " + e);
}
+ if (notificationClassification()) {
+ addReservedChannelsLocked(r);
+ }
+
if (r.uid == UNKNOWN_UID) {
if (Flags.persistIncompleteRestoreData()) {
r.userId = userId;
@@ -603,6 +610,40 @@
return true;
}
+ private void addReservedChannelsLocked(PackagePreferences p) {
+ if (!p.channels.containsKey(NotificationChannel.PROMOTIONS_ID)) {
+ NotificationChannel channel = new NotificationChannel(
+ NotificationChannel.PROMOTIONS_ID,
+ mContext.getString(R.string.promotional_notification_channel_label),
+ IMPORTANCE_LOW);
+ p.channels.put(channel.getId(), channel);
+ }
+
+ if (!p.channels.containsKey(NotificationChannel.RECS_ID)) {
+ NotificationChannel channel = new NotificationChannel(
+ NotificationChannel.RECS_ID,
+ mContext.getString(R.string.recs_notification_channel_label),
+ IMPORTANCE_LOW);
+ p.channels.put(channel.getId(), channel);
+ }
+
+ if (!p.channels.containsKey(NotificationChannel.NEWS_ID)) {
+ NotificationChannel channel = new NotificationChannel(
+ NotificationChannel.NEWS_ID,
+ mContext.getString(R.string.news_notification_channel_label),
+ IMPORTANCE_LOW);
+ p.channels.put(channel.getId(), channel);
+ }
+
+ if (!p.channels.containsKey(NotificationChannel.SOCIAL_MEDIA_ID)) {
+ NotificationChannel channel = new NotificationChannel(
+ NotificationChannel.SOCIAL_MEDIA_ID,
+ mContext.getString(R.string.social_notification_channel_label),
+ IMPORTANCE_LOW);
+ p.channels.put(channel.getId(), channel);
+ }
+ }
+
public void writeXml(TypedXmlSerializer out, boolean forBackup, int userId) throws IOException {
out.startTag(null, TAG_RANKING);
out.attributeInt(null, ATT_VERSION, XML_VERSION);
@@ -1801,7 +1842,7 @@
public boolean onlyHasDefaultChannel(String pkg, int uid) {
synchronized (mPackagePreferences) {
PackagePreferences r = getOrCreatePackagePreferencesLocked(pkg, uid);
- if (r.channels.size() == 1
+ if (r.channels.size() == (notificationClassification() ? 5 : 1)
&& r.channels.containsKey(NotificationChannel.DEFAULT_CHANNEL_ID)) {
return true;
}
@@ -2611,6 +2652,7 @@
context.getResources().getString(
R.string.default_notification_channel_label));
}
+ // TODO (b/346396459): Localize all reserved channels
}
}
}
diff --git a/services/core/java/com/android/server/power/ShutdownThread.java b/services/core/java/com/android/server/power/ShutdownThread.java
index 6b7f2fa..4b4e442 100644
--- a/services/core/java/com/android/server/power/ShutdownThread.java
+++ b/services/core/java/com/android/server/power/ShutdownThread.java
@@ -48,6 +48,7 @@
import android.os.VibrationEffect;
import android.os.Vibrator;
import android.os.vibrator.persistence.VibrationXmlParser;
+import android.provider.Settings;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.ArrayMap;
@@ -743,6 +744,11 @@
*/
@VisibleForTesting // For testing vibrations without shutting down device
void playShutdownVibration(Context context) {
+ if (mInjector.isShutdownVibrationDisabled(context)) {
+ Log.i(TAG, "Vibration disabled in config");
+ return;
+ }
+
Vibrator vibrator = mInjector.getVibrator(context);
if (!vibrator.hasVibrator()) {
return;
@@ -920,5 +926,14 @@
return context.getResources().getString(
com.android.internal.R.string.config_defaultShutdownVibrationFile);
}
+
+ public boolean isShutdownVibrationDisabled(Context context) {
+ boolean disabledInConfig = context.getResources().getBoolean(
+ com.android.internal.R.bool.config_disableShutdownVibrationInZen);
+ boolean isZenMode = Settings.Global.getInt(context.getContentResolver(),
+ Settings.Global.ZEN_MODE, Settings.Global.ZEN_MODE_OFF)
+ != Settings.Global.ZEN_MODE_OFF;
+ return disabledInConfig && isZenMode;
+ }
}
}
diff --git a/services/core/java/com/android/server/power/stats/EnergyConsumerPowerStatsCollector.java b/services/core/java/com/android/server/power/stats/EnergyConsumerPowerStatsCollector.java
index 7f2f729..cace941 100644
--- a/services/core/java/com/android/server/power/stats/EnergyConsumerPowerStatsCollector.java
+++ b/services/core/java/com/android/server/power/stats/EnergyConsumerPowerStatsCollector.java
@@ -128,6 +128,16 @@
return null;
}
+ int voltageMv = mVoltageSupplier.getAsInt();
+ int averageVoltage = mLastVoltageMv != 0 ? (mLastVoltageMv + voltageMv) / 2 : voltageMv;
+ if (averageVoltage <= 0) {
+ Slog.wtf(TAG, "Unexpected battery voltage (" + voltageMv
+ + " mV) when querying energy consumers");
+ return null;
+ }
+
+ mLastVoltageMv = voltageMv;
+
EnergyConsumerResult[] energy =
mConsumedEnergyRetriever.getConsumedEnergy(mEnergyConsumerIds);
long consumedEnergy = 0;
@@ -151,15 +161,6 @@
return null;
}
- int voltageMv = mVoltageSupplier.getAsInt();
- if (voltageMv <= 0) {
- Slog.wtf(TAG, "Unexpected battery voltage (" + voltageMv
- + " mV) when querying energy consumers");
- voltageMv = 0;
- }
-
- int averageVoltage = mLastVoltageMv != 0 ? (mLastVoltageMv + voltageMv) / 2 : voltageMv;
- mLastVoltageMv = voltageMv;
mLayout.setConsumedEnergy(mPowerStats.stats, 0, uJtoUc(energyDelta, averageVoltage));
for (int i = mPowerStats.uidStats.size() - 1; i >= 0; i--) {
diff --git a/services/core/java/com/android/server/timezonedetector/OWNERS b/services/core/java/com/android/server/timezonedetector/OWNERS
index 485a0dd..dfa07d8 100644
--- a/services/core/java/com/android/server/timezonedetector/OWNERS
+++ b/services/core/java/com/android/server/timezonedetector/OWNERS
@@ -2,7 +2,7 @@
# This is the main list for platform time / time zone detection maintainers, for this dir and
# ultimately referenced by other OWNERS files for components maintained by the same team.
nfuller@google.com
+boullanger@google.com
jmorace@google.com
kanyinsola@google.com
-mingaleev@google.com
-narayan@google.com
+mingaleev@google.com
\ No newline at end of file
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 10243a7..9bc4389 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -158,7 +158,6 @@
import static com.android.internal.util.FrameworkStatsLog.APP_COMPAT_STATE_CHANGED__STATE__LETTERBOXED_FOR_SIZE_COMPAT_MODE;
import static com.android.internal.util.FrameworkStatsLog.APP_COMPAT_STATE_CHANGED__STATE__NOT_LETTERBOXED;
import static com.android.internal.util.FrameworkStatsLog.APP_COMPAT_STATE_CHANGED__STATE__NOT_VISIBLE;
-import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
import static com.android.server.wm.ActivityRecord.State.DESTROYED;
@@ -807,9 +806,10 @@
final LetterboxUiController mLetterboxUiController;
/**
- * The policy for transparent activities
+ * App Compat Facade
*/
- final TransparentPolicy mTransparentPolicy;
+ @NonNull
+ final AppCompatController mAppCompatController;
/**
* The scale to fit at least one side of the activity to its parent. If the activity uses
@@ -1706,7 +1706,7 @@
if (isState(RESUMED)) {
newParent.setResumedActivity(this, "onParentChanged");
}
- mTransparentPolicy.start();
+ mAppCompatController.getTransparentPolicy().start();
}
if (rootTask != null && rootTask.topRunningActivity() == this) {
@@ -1908,7 +1908,7 @@
}
void updateLetterboxSurfaceIfNeeded(WindowState winHint, Transaction t) {
- mLetterboxUiController.updateLetterboxSurfaceIfNeeded(winHint, t);
+ mLetterboxUiController.updateLetterboxSurfaceIfNeeded(winHint, t, getPendingTransaction());
}
void updateLetterboxSurfaceIfNeeded(WindowState winHint) {
@@ -2144,8 +2144,8 @@
// Don't move below setOrientation(info.screenOrientation) since it triggers
// getOverrideOrientation that requires having mLetterboxUiController
// initialised.
- mTransparentPolicy = new TransparentPolicy(this, mWmService.mLetterboxConfiguration);
mLetterboxUiController = new LetterboxUiController(mWmService, this);
+ mAppCompatController = new AppCompatController(mWmService, this);
mCameraCompatControlEnabled = mWmService.mContext.getResources()
.getBoolean(R.bool.config_isCameraCompatControlForStretchedIssuesEnabled);
mResolveConfigHint = new TaskFragment.ConfigOverrideHint();
@@ -4505,6 +4505,7 @@
mTaskSupervisor.getActivityMetricsLogger().notifyActivityRemoved(this);
mTaskSupervisor.mStoppingActivities.remove(this);
mLetterboxUiController.destroy();
+ mAppCompatController.getTransparentPolicy().stop();
// Defer removal of this activity when either a child is animating, or app transition is on
// going. App transition animation might be applied on the parent task not on the activity,
@@ -8108,13 +8109,13 @@
@Configuration.Orientation
int getRequestedConfigurationOrientation(boolean forDisplay,
@ActivityInfo.ScreenOrientation int requestedOrientation) {
- if (mTransparentPolicy.hasInheritedOrientation()) {
+ if (mAppCompatController.getTransparentPolicy().hasInheritedOrientation()) {
final RootDisplayArea root = getRootDisplayArea();
if (forDisplay && root != null && root.isOrientationDifferentFromDisplay()) {
return reverseConfigurationOrientation(
- mTransparentPolicy.getInheritedOrientation());
+ mAppCompatController.getTransparentPolicy().getInheritedOrientation());
} else {
- return mTransparentPolicy.getInheritedOrientation();
+ return mAppCompatController.getTransparentPolicy().getInheritedOrientation();
}
}
if (task != null && requestedOrientation == SCREEN_ORIENTATION_BEHIND) {
@@ -8187,7 +8188,9 @@
}
void setRequestedOrientation(@ActivityInfo.ScreenOrientation int requestedOrientation) {
- if (mLetterboxUiController.shouldIgnoreRequestedOrientation(requestedOrientation)) {
+ if (mAppCompatController.getAppCompatCapability()
+ .getAppCompatOrientationCapability()
+ .shouldIgnoreRequestedOrientation(requestedOrientation)) {
return;
}
final int originalRelaunchingCount = mPendingRelaunchCount;
@@ -8330,8 +8333,8 @@
@Nullable
CompatDisplayInsets getCompatDisplayInsets() {
- if (mTransparentPolicy.isRunning()) {
- return mTransparentPolicy.getInheritedCompatDisplayInsets();
+ if (mAppCompatController.getTransparentPolicy().isRunning()) {
+ return mAppCompatController.getTransparentPolicy().getInheritedCompatDisplayInsets();
}
return mCompatDisplayInsets;
}
@@ -8494,7 +8497,7 @@
}
mSizeCompatBounds = null;
mCompatDisplayInsets = null;
- mTransparentPolicy.clearInheritedCompatDisplayInsets();
+ mAppCompatController.getTransparentPolicy().clearInheritedCompatDisplayInsets();
}
@VisibleForTesting
@@ -8681,7 +8684,7 @@
}
@Nullable Rect getParentAppBoundsOverride() {
- return Rect.copyOrNull(mResolveConfigHint.mTmpParentAppBoundsOverride);
+ return Rect.copyOrNull(mResolveConfigHint.mParentAppBoundsOverride);
}
/**
@@ -8827,8 +8830,8 @@
return APP_COMPAT_STATE_CHANGED__STATE__NOT_VISIBLE;
}
// TODO(b/256564921): Investigate if we need new metrics for translucent activities
- if (mTransparentPolicy.isRunning()) {
- return mTransparentPolicy.getInheritedAppCompatState();
+ if (mAppCompatController.getTransparentPolicy().isRunning()) {
+ return mAppCompatController.getTransparentPolicy().getInheritedAppCompatState();
}
if (mInSizeCompatModeForBounds) {
return APP_COMPAT_STATE_CHANGED__STATE__LETTERBOXED_FOR_SIZE_COMPAT_MODE;
@@ -8866,7 +8869,7 @@
}
final Rect screenResolvedBounds =
mSizeCompatBounds != null ? mSizeCompatBounds : resolvedBounds;
- final Rect parentAppBounds = mResolveConfigHint.mTmpParentAppBoundsOverride;
+ final Rect parentAppBounds = mResolveConfigHint.mParentAppBoundsOverride;
final Rect parentBounds = newParentConfiguration.windowConfiguration.getBounds();
final float screenResolvedBoundsWidth = screenResolvedBounds.width();
final float parentAppBoundsWidth = parentAppBounds.width();
@@ -8981,7 +8984,7 @@
// We check if the current activity is transparent. In that case we need to
// recomputeConfiguration of the first opaque activity beneath, to allow a
// proper computation of the new bounds.
- if (!mTransparentPolicy.applyOnOpaqueActivityBelow(
+ if (!mAppCompatController.getTransparentPolicy().applyOnOpaqueActivityBelow(
ActivityRecord::recomputeConfiguration)) {
onRequestedOverrideConfigurationChanged(getRequestedOverrideConfiguration());
}
@@ -9275,7 +9278,7 @@
*/
private void resolveAspectRatioRestriction(Configuration newParentConfiguration) {
final Configuration resolvedConfig = getResolvedOverrideConfiguration();
- final Rect parentAppBounds = mResolveConfigHint.mTmpParentAppBoundsOverride;
+ final Rect parentAppBounds = mResolveConfigHint.mParentAppBoundsOverride;
final Rect parentBounds = newParentConfiguration.windowConfiguration.getBounds();
final Rect resolvedBounds = resolvedConfig.windowConfiguration.getBounds();
// Use tmp bounds to calculate aspect ratio so we can know whether the activity should use
@@ -9316,7 +9319,7 @@
: newParentConfiguration.windowConfiguration.getBounds();
final Rect containerAppBounds = useResolvedBounds
? new Rect(resolvedConfig.windowConfiguration.getAppBounds())
- : mResolveConfigHint.mTmpParentAppBoundsOverride;
+ : mResolveConfigHint.mParentAppBoundsOverride;
final int requestedOrientation = getRequestedConfigurationOrientation();
final boolean orientationRequested = requestedOrientation != ORIENTATION_UNDEFINED;
@@ -9441,7 +9444,8 @@
void updateSizeCompatScale(Rect resolvedAppBounds, Rect containerAppBounds) {
// Only allow to scale down.
- mSizeCompatScale = mTransparentPolicy.findOpaqueNotFinishingActivityBelow()
+ mSizeCompatScale = mAppCompatController.getTransparentPolicy()
+ .findOpaqueNotFinishingActivityBelow()
.map(activityRecord -> activityRecord.mSizeCompatScale)
.orElseGet(() -> {
final int contentW = resolvedAppBounds.width();
@@ -9454,7 +9458,7 @@
}
private boolean isInSizeCompatModeForBounds(final Rect appBounds, final Rect containerBounds) {
- if (mTransparentPolicy.isRunning()) {
+ if (mAppCompatController.getTransparentPolicy().isRunning()) {
// To avoid wrong app behaviour, we decided to disable SCM when a translucent activity
// is letterboxed.
return false;
@@ -9517,7 +9521,7 @@
public Rect getBounds() {
// TODO(b/268458693): Refactor configuration inheritance in case of translucent activities
final Rect superBounds = super.getBounds();
- return mTransparentPolicy.findOpaqueNotFinishingActivityBelow()
+ return mAppCompatController.getTransparentPolicy().findOpaqueNotFinishingActivityBelow()
.map(ActivityRecord::getBounds)
.orElseGet(() -> {
if (mSizeCompatBounds != null) {
@@ -9881,8 +9885,8 @@
* Returns the min aspect ratio of this activity.
*/
float getMinAspectRatio() {
- if (mTransparentPolicy.isRunning()) {
- return mTransparentPolicy.getInheritedMinAspectRatio();
+ if (mAppCompatController.getTransparentPolicy().isRunning()) {
+ return mAppCompatController.getTransparentPolicy().getInheritedMinAspectRatio();
}
if (info.applicationInfo == null) {
return info.getMinAspectRatio();
@@ -9932,8 +9936,8 @@
}
float getMaxAspectRatio() {
- if (mTransparentPolicy.isRunning()) {
- return mTransparentPolicy.getInheritedMaxAspectRatio();
+ if (mAppCompatController.getTransparentPolicy().isRunning()) {
+ return mAppCompatController.getTransparentPolicy().getInheritedMaxAspectRatio();
}
return info.getMaxAspectRatio();
}
diff --git a/services/core/java/com/android/server/wm/AppCompatCapability.java b/services/core/java/com/android/server/wm/AppCompatCapability.java
new file mode 100644
index 0000000..d4379e48
--- /dev/null
+++ b/services/core/java/com/android/server/wm/AppCompatCapability.java
@@ -0,0 +1,416 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+package com.android.server.wm;
+
+import static android.content.pm.ActivityInfo.FORCE_NON_RESIZE_APP;
+import static android.content.pm.ActivityInfo.FORCE_RESIZE_APP;
+import static android.content.pm.ActivityInfo.OVERRIDE_ANY_ORIENTATION_TO_USER;
+import static android.content.pm.ActivityInfo.OVERRIDE_CAMERA_COMPAT_DISABLE_FORCE_ROTATION;
+import static android.content.pm.ActivityInfo.OVERRIDE_CAMERA_COMPAT_DISABLE_FREEFORM_WINDOWING_TREATMENT;
+import static android.content.pm.ActivityInfo.OVERRIDE_CAMERA_COMPAT_DISABLE_REFRESH;
+import static android.content.pm.ActivityInfo.OVERRIDE_CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE;
+import static android.content.pm.ActivityInfo.OVERRIDE_ENABLE_COMPAT_FAKE_FOCUS;
+import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO;
+import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_ONLY_FOR_CAMERA;
+import static android.content.pm.ActivityInfo.OVERRIDE_ORIENTATION_ONLY_FOR_CAMERA;
+import static android.content.pm.ActivityInfo.OVERRIDE_RESPECT_REQUESTED_ORIENTATION;
+import static android.content.pm.ActivityInfo.OVERRIDE_USE_DISPLAY_LANDSCAPE_NATURAL_ORIENTATION;
+import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_FULLSCREEN;
+import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_UNSET;
+import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
+import static android.view.WindowManager.PROPERTY_CAMERA_COMPAT_ALLOW_FORCE_ROTATION;
+import static android.view.WindowManager.PROPERTY_CAMERA_COMPAT_ALLOW_REFRESH;
+import static android.view.WindowManager.PROPERTY_CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE;
+import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_DISPLAY_ORIENTATION_OVERRIDE;
+import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_MIN_ASPECT_RATIO_OVERRIDE;
+import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_ORIENTATION_OVERRIDE;
+import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_RESIZEABLE_ACTIVITY_OVERRIDES;
+import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_FULLSCREEN_OVERRIDE;
+import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_OVERRIDE;
+import static android.view.WindowManager.PROPERTY_COMPAT_ENABLE_FAKE_FOCUS;
+
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
+
+import android.annotation.NonNull;
+import android.content.pm.PackageManager;
+
+import com.android.server.wm.utils.OptPropFactory;
+import com.android.window.flags.Flags;
+
+import java.util.function.BooleanSupplier;
+
+/**
+ * Encapsulate logic related to operations guarded by an app override.
+ */
+public class AppCompatCapability {
+
+ private static final String TAG = TAG_WITH_CLASS_NAME ? "AppCompatCapability" : TAG_ATM;
+
+ @NonNull
+ private final LetterboxConfiguration mLetterboxConfiguration;
+
+ @NonNull
+ private final ActivityRecord mActivityRecord;
+
+ // Corresponds to OVERRIDE_ANY_ORIENTATION_TO_USER
+ private final boolean mIsSystemOverrideToFullscreenEnabled;
+ // Corresponds to OVERRIDE_RESPECT_REQUESTED_ORIENTATION
+ private final boolean mIsOverrideRespectRequestedOrientationEnabled;
+ // Corresponds to OVERRIDE_ORIENTATION_ONLY_FOR_CAMERA
+ private final boolean mIsOverrideOrientationOnlyForCameraEnabled;
+
+ @NonNull
+ private final OptPropFactory.OptProp mFakeFocusOptProp;
+ @NonNull
+ private final OptPropFactory.OptProp mCameraCompatAllowForceRotationOptProp;
+ @NonNull
+ private final OptPropFactory.OptProp mCameraCompatAllowRefreshOptProp;
+ @NonNull
+ private final OptPropFactory.OptProp mCameraCompatEnableRefreshViaPauseOptProp;
+ @NonNull
+ private final OptPropFactory.OptProp mAllowOrientationOverrideOptProp;
+ @NonNull
+ private final OptPropFactory.OptProp mAllowDisplayOrientationOverrideOptProp;
+ @NonNull
+ private final OptPropFactory.OptProp mAllowMinAspectRatioOverrideOptProp;
+ @NonNull
+ private final OptPropFactory.OptProp mAllowForceResizeOverrideOptProp;
+ @NonNull
+ private final OptPropFactory.OptProp mAllowUserAspectRatioOverrideOptProp;
+ @NonNull
+ private final OptPropFactory.OptProp mAllowUserAspectRatioFullscreenOverrideOptProp;
+
+ private final AppCompatOrientationCapability mAppCompatOrientationCapability;
+
+ AppCompatCapability(@NonNull WindowManagerService wmService,
+ @NonNull ActivityRecord activityRecord,
+ @NonNull LetterboxConfiguration letterboxConfiguration) {
+ mLetterboxConfiguration = letterboxConfiguration;
+ mActivityRecord = activityRecord;
+ final PackageManager packageManager = wmService.mContext.getPackageManager();
+
+ final OptPropFactory optPropBuilder = new OptPropFactory(packageManager,
+ activityRecord.packageName);
+
+ mAppCompatOrientationCapability =
+ new AppCompatOrientationCapability(optPropBuilder, mLetterboxConfiguration,
+ mActivityRecord);
+
+ mFakeFocusOptProp = optPropBuilder.create(PROPERTY_COMPAT_ENABLE_FAKE_FOCUS,
+ mLetterboxConfiguration::isCompatFakeFocusEnabled);
+
+ final BooleanSupplier isCameraCompatTreatmentEnabled = asLazy(
+ mLetterboxConfiguration::isCameraCompatTreatmentEnabled);
+ mCameraCompatAllowForceRotationOptProp = optPropBuilder.create(
+ PROPERTY_CAMERA_COMPAT_ALLOW_FORCE_ROTATION,
+ isCameraCompatTreatmentEnabled);
+ mCameraCompatAllowRefreshOptProp = optPropBuilder.create(
+ PROPERTY_CAMERA_COMPAT_ALLOW_REFRESH,
+ isCameraCompatTreatmentEnabled);
+ mCameraCompatEnableRefreshViaPauseOptProp = optPropBuilder.create(
+ PROPERTY_CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE,
+ isCameraCompatTreatmentEnabled);
+
+ mAllowOrientationOverrideOptProp = optPropBuilder.create(
+ PROPERTY_COMPAT_ALLOW_ORIENTATION_OVERRIDE);
+
+ mAllowDisplayOrientationOverrideOptProp = optPropBuilder.create(
+ PROPERTY_COMPAT_ALLOW_DISPLAY_ORIENTATION_OVERRIDE,
+ () -> mActivityRecord.mDisplayContent != null
+ && mActivityRecord.getTask() != null
+ && mActivityRecord.mDisplayContent.getIgnoreOrientationRequest()
+ && !mActivityRecord.getTask().inMultiWindowMode()
+ && mActivityRecord.mDisplayContent.getNaturalOrientation()
+ == ORIENTATION_LANDSCAPE
+ );
+
+ mAllowMinAspectRatioOverrideOptProp = optPropBuilder.create(
+ PROPERTY_COMPAT_ALLOW_MIN_ASPECT_RATIO_OVERRIDE);
+ mAllowForceResizeOverrideOptProp = optPropBuilder.create(
+ PROPERTY_COMPAT_ALLOW_RESIZEABLE_ACTIVITY_OVERRIDES);
+ mAllowUserAspectRatioOverrideOptProp = optPropBuilder.create(
+ PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_OVERRIDE,
+ mLetterboxConfiguration::isUserAppAspectRatioSettingsEnabled);
+ mAllowUserAspectRatioFullscreenOverrideOptProp = optPropBuilder.create(
+ PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_FULLSCREEN_OVERRIDE,
+ mLetterboxConfiguration::isUserAppAspectRatioFullscreenEnabled);
+
+ mIsSystemOverrideToFullscreenEnabled =
+ isCompatChangeEnabled(OVERRIDE_ANY_ORIENTATION_TO_USER);
+ mIsOverrideRespectRequestedOrientationEnabled =
+ isCompatChangeEnabled(OVERRIDE_RESPECT_REQUESTED_ORIENTATION);
+ mIsOverrideOrientationOnlyForCameraEnabled =
+ isCompatChangeEnabled(OVERRIDE_ORIENTATION_ONLY_FOR_CAMERA);
+ }
+
+ /**
+ * @return {@code true} if the App Compat Camera Policy is active for the current activity.
+ */
+ boolean isCameraCompatTreatmentActive() {
+ final DisplayContent displayContent = mActivityRecord.mDisplayContent;
+ if (displayContent == null) {
+ return false;
+ }
+ return displayContent.mDisplayRotationCompatPolicy != null
+ && displayContent.mDisplayRotationCompatPolicy
+ .isTreatmentEnabledForActivity(mActivityRecord);
+ }
+
+ @NonNull
+ AppCompatOrientationCapability getAppCompatOrientationCapability() {
+ return mAppCompatOrientationCapability;
+ }
+
+ /**
+ * Whether sending compat fake focus for split screen resumed activities is enabled. Needed
+ * because some game engines wait to get focus before drawing the content of the app which isn't
+ * guaranteed by default in multi-window modes.
+ *
+ * <p>This treatment is enabled when the following conditions are met:
+ * <ul>
+ * <li>Flag gating the treatment is enabled
+ * <li>Component property is NOT set to false
+ * <li>Component property is set to true or per-app override is enabled
+ * </ul>
+ */
+ boolean shouldSendFakeFocus() {
+ return mFakeFocusOptProp.shouldEnableWithOverrideAndProperty(
+ isCompatChangeEnabled(OVERRIDE_ENABLE_COMPAT_FAKE_FOCUS));
+ }
+
+ /**
+ * Whether activity is eligible for camera compat force rotation treatment. See {@link
+ * DisplayRotationCompatPolicy} for context.
+ *
+ * <p>This treatment is enabled when the following conditions are met:
+ * <ul>
+ * <li>Flag gating the camera compat treatment is enabled.
+ * <li>Activity isn't opted out by the device manufacturer with override or by the app
+ * developers with the component property.
+ * </ul>
+ */
+ boolean shouldForceRotateForCameraCompat() {
+ return mCameraCompatAllowForceRotationOptProp.shouldEnableWithOptOutOverrideAndProperty(
+ isCompatChangeEnabled(OVERRIDE_CAMERA_COMPAT_DISABLE_FORCE_ROTATION));
+ }
+
+ /**
+ * Whether activity is eligible for activity "refresh" after camera compat force rotation
+ * treatment. See {@link DisplayRotationCompatPolicy} for context.
+ *
+ * <p>This treatment is enabled when the following conditions are met:
+ * <ul>
+ * <li>Flag gating the camera compat treatment is enabled.
+ * <li>Activity isn't opted out by the device manufacturer with override or by the app
+ * developers with the component property.
+ * </ul>
+ */
+ boolean shouldRefreshActivityForCameraCompat() {
+ return mCameraCompatAllowRefreshOptProp.shouldEnableWithOptOutOverrideAndProperty(
+ isCompatChangeEnabled(OVERRIDE_CAMERA_COMPAT_DISABLE_REFRESH));
+ }
+
+ /**
+ * Whether activity should be "refreshed" after the camera compat force rotation treatment
+ * using the "resumed -> paused -> resumed" cycle rather than the "resumed -> ... -> stopped
+ * -> ... -> resumed" cycle. See {@link DisplayRotationCompatPolicy} for context.
+ *
+ * <p>This treatment is enabled when the following conditions are met:
+ * <ul>
+ * <li>Flag gating the camera compat treatment is enabled.
+ * <li>Activity "refresh" via "resumed -> paused -> resumed" cycle isn't disabled with the
+ * component property by the app developers.
+ * <li>Activity "refresh" via "resumed -> paused -> resumed" cycle is enabled by the device
+ * manufacturer with override / by the app developers with the component property.
+ * </ul>
+ */
+ boolean shouldRefreshActivityViaPauseForCameraCompat() {
+ return mCameraCompatEnableRefreshViaPauseOptProp.shouldEnableWithOverrideAndProperty(
+ isCompatChangeEnabled(OVERRIDE_CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE));
+ }
+
+ boolean isSystemOverrideToFullscreenEnabled(int userAspectRatio) {
+ return mIsSystemOverrideToFullscreenEnabled
+ && !mAllowOrientationOverrideOptProp.isFalse()
+ && (userAspectRatio == USER_MIN_ASPECT_RATIO_UNSET
+ || userAspectRatio == USER_MIN_ASPECT_RATIO_FULLSCREEN);
+ }
+
+ boolean isAllowOrientationOverrideOptOut() {
+ return mAllowOrientationOverrideOptProp.isFalse();
+ }
+
+ /**
+ * Whether we should apply the min aspect ratio per-app override. When this override is applied
+ * the min aspect ratio given in the app's manifest will be overridden to the largest enabled
+ * aspect ratio treatment unless the app's manifest value is higher. The treatment will also
+ * apply if no value is provided in the manifest.
+ *
+ * <p>This method returns {@code true} when the following conditions are met:
+ * <ul>
+ * <li>Opt-out component property isn't enabled
+ * <li>Per-app override is enabled
+ * </ul>
+ */
+ boolean shouldOverrideMinAspectRatio() {
+ return mAllowMinAspectRatioOverrideOptProp.shouldEnableWithOptInOverrideAndOptOutProperty(
+ isCompatChangeEnabled(OVERRIDE_MIN_ASPECT_RATIO));
+ }
+
+ boolean isOverrideRespectRequestedOrientationEnabled() {
+ return mIsOverrideRespectRequestedOrientationEnabled;
+ }
+
+ boolean isOverrideOrientationOnlyForCameraEnabled() {
+ return mIsOverrideOrientationOnlyForCameraEnabled;
+ }
+
+ /**
+ * Whether activity is eligible for camera compatibility free-form treatment.
+ *
+ * <p>The treatment is applied to a fixed-orientation camera activity in free-form windowing
+ * mode. The treatment letterboxes or pillarboxes the activity to the expected orientation and
+ * provides changes to the camera and display orientation signals to match those expected on a
+ * portrait device in that orientation (for example, on a standard phone).
+ *
+ * <p>The treatment is enabled when the following conditions are met:
+ * <ul>
+ * <li>Property gating the camera compatibility free-form treatment is enabled.
+ * <li>Activity isn't opted out by the device manufacturer with override.
+ * </ul>
+ */
+ boolean shouldApplyFreeformTreatmentForCameraCompat() {
+ return Flags.cameraCompatForFreeform() && !isCompatChangeEnabled(
+ OVERRIDE_CAMERA_COMPAT_DISABLE_FREEFORM_WINDOWING_TREATMENT);
+ }
+
+
+ /**
+ * Whether we should apply the min aspect ratio per-app override only when an app is connected
+ * to the camera.
+ * When this override is applied the min aspect ratio given in the app's manifest will be
+ * overridden to the largest enabled aspect ratio treatment unless the app's manifest value
+ * is higher. The treatment will also apply if no value is provided in the manifest.
+ *
+ * <p>This method returns {@code true} when the following conditions are met:
+ * <ul>
+ * <li>Opt-out component property isn't enabled
+ * <li>Per-app override is enabled
+ * </ul>
+ */
+ boolean shouldOverrideMinAspectRatioForCamera() {
+ return mActivityRecord.isCameraActive()
+ && mAllowMinAspectRatioOverrideOptProp
+ .shouldEnableWithOptInOverrideAndOptOutProperty(
+ isCompatChangeEnabled(OVERRIDE_MIN_ASPECT_RATIO_ONLY_FOR_CAMERA));
+ }
+
+ /**
+ * Whether should fix display orientation to landscape natural orientation when a task is
+ * fullscreen and the display is ignoring orientation requests.
+ *
+ * <p>This treatment is enabled when the following conditions are met:
+ * <ul>
+ * <li>Opt-out component property isn't enabled
+ * <li>Opt-in per-app override is enabled
+ * <li>Task is in fullscreen.
+ * <li>{@link DisplayContent#getIgnoreOrientationRequest} is enabled
+ * <li>Natural orientation of the display is landscape.
+ * </ul>
+ */
+ boolean shouldUseDisplayLandscapeNaturalOrientation() {
+ return mAllowDisplayOrientationOverrideOptProp
+ .shouldEnableWithOptInOverrideAndOptOutProperty(
+ isCompatChangeEnabled(OVERRIDE_USE_DISPLAY_LANDSCAPE_NATURAL_ORIENTATION));
+ }
+
+ /**
+ * Whether we should apply the force resize per-app override. When this override is applied it
+ * forces the packages it is applied to to be resizable. It won't change whether the app can be
+ * put into multi-windowing mode, but allow the app to resize without going into size-compat
+ * mode when the window container resizes, such as display size change or screen rotation.
+ *
+ * <p>This method returns {@code true} when the following conditions are met:
+ * <ul>
+ * <li>Opt-out component property isn't enabled
+ * <li>Per-app override is enabled
+ * </ul>
+ */
+ boolean shouldOverrideForceResizeApp() {
+ return mAllowForceResizeOverrideOptProp.shouldEnableWithOptInOverrideAndOptOutProperty(
+ isCompatChangeEnabled(FORCE_RESIZE_APP));
+ }
+
+ /**
+ * Whether we should enable users to resize the current app.
+ */
+ boolean shouldEnableUserAspectRatioSettings() {
+ // We use mBooleanPropertyAllowUserAspectRatioOverride to allow apps to opt-out which has
+ // effect only if explicitly false. If mBooleanPropertyAllowUserAspectRatioOverride is null,
+ // the current app doesn't opt-out so the first part of the predicate is true.
+ return !mAllowUserAspectRatioOverrideOptProp.isFalse()
+ && mLetterboxConfiguration.isUserAppAspectRatioSettingsEnabled()
+ && mActivityRecord.mDisplayContent != null
+ && mActivityRecord.mDisplayContent.getIgnoreOrientationRequest();
+ }
+
+ boolean isUserFullscreenOverrideEnabled() {
+ if (mAllowUserAspectRatioOverrideOptProp.isFalse()
+ || mAllowUserAspectRatioFullscreenOverrideOptProp.isFalse()
+ || !mLetterboxConfiguration.isUserAppAspectRatioFullscreenEnabled()) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Whether we should apply the force non resize per-app override. When this override is applied
+ * it forces the packages it is applied to to be non-resizable.
+ *
+ * <p>This method returns {@code true} when the following conditions are met:
+ * <ul>
+ * <li>Opt-out component property isn't enabled
+ * <li>Per-app override is enabled
+ * </ul>
+ */
+ boolean shouldOverrideForceNonResizeApp() {
+ return mAllowForceResizeOverrideOptProp.shouldEnableWithOptInOverrideAndOptOutProperty(
+ isCompatChangeEnabled(FORCE_NON_RESIZE_APP));
+ }
+
+ private boolean isCompatChangeEnabled(long overrideChangeId) {
+ return mActivityRecord.info.isChangeEnabled(overrideChangeId);
+ }
+
+ @NonNull
+ static BooleanSupplier asLazy(@NonNull BooleanSupplier supplier) {
+ return new BooleanSupplier() {
+ private boolean mRead;
+ private boolean mValue;
+
+ @Override
+ public boolean getAsBoolean() {
+ if (!mRead) {
+ mRead = true;
+ mValue = supplier.getAsBoolean();
+ }
+ return mValue;
+ }
+ };
+ }
+}
diff --git a/services/core/java/com/android/server/wm/AppCompatController.java b/services/core/java/com/android/server/wm/AppCompatController.java
new file mode 100644
index 0000000..3ff0fce
--- /dev/null
+++ b/services/core/java/com/android/server/wm/AppCompatController.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+package com.android.server.wm;
+
+import android.annotation.NonNull;
+
+/**
+ * Allows the interaction with all the app compat policies and configurations
+ */
+class AppCompatController {
+
+ @NonNull
+ private final TransparentPolicy mTransparentPolicy;
+ @NonNull
+ private final AppCompatOrientationPolicy mOrientationPolicy;
+ @NonNull
+ private final AppCompatCapability mAppCompatCapability;
+
+ AppCompatController(@NonNull WindowManagerService wmService,
+ @NonNull ActivityRecord activityRecord) {
+ mTransparentPolicy = new TransparentPolicy(activityRecord,
+ wmService.mLetterboxConfiguration);
+ mAppCompatCapability = new AppCompatCapability(wmService, activityRecord,
+ wmService.mLetterboxConfiguration);
+ // TODO(b/341903757) Remove BooleanSuppliers after fixing dependency with aspectRatio.
+ final LetterboxUiController tmpController = activityRecord.mLetterboxUiController;
+ mOrientationPolicy = new AppCompatOrientationPolicy(activityRecord,
+ mAppCompatCapability, tmpController::shouldApplyUserFullscreenOverride,
+ tmpController::shouldApplyUserMinAspectRatioOverride,
+ tmpController::isSystemOverrideToFullscreenEnabled);
+ }
+
+ @NonNull
+ TransparentPolicy getTransparentPolicy() {
+ return mTransparentPolicy;
+ }
+
+ @NonNull
+ AppCompatOrientationPolicy getOrientationPolicy() {
+ return mOrientationPolicy;
+ }
+
+ @NonNull
+ AppCompatCapability getAppCompatCapability() {
+ return mAppCompatCapability;
+ }
+}
diff --git a/services/core/java/com/android/server/wm/AppCompatOrientationCapability.java b/services/core/java/com/android/server/wm/AppCompatOrientationCapability.java
new file mode 100644
index 0000000..fbe90a2
--- /dev/null
+++ b/services/core/java/com/android/server/wm/AppCompatOrientationCapability.java
@@ -0,0 +1,251 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+package com.android.server.wm;
+
+import static android.content.pm.ActivityInfo.OVERRIDE_ANY_ORIENTATION;
+import static android.content.pm.ActivityInfo.OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED;
+import static android.content.pm.ActivityInfo.OVERRIDE_ENABLE_COMPAT_IGNORE_REQUESTED_ORIENTATION;
+import static android.content.pm.ActivityInfo.OVERRIDE_LANDSCAPE_ORIENTATION_TO_REVERSE_LANDSCAPE;
+import static android.content.pm.ActivityInfo.OVERRIDE_UNDEFINED_ORIENTATION_TO_NOSENSOR;
+import static android.content.pm.ActivityInfo.OVERRIDE_UNDEFINED_ORIENTATION_TO_PORTRAIT;
+import static android.content.pm.ActivityInfo.screenOrientationToString;
+import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_IGNORING_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED;
+import static android.view.WindowManager.PROPERTY_COMPAT_IGNORE_REQUESTED_ORIENTATION;
+
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.wm.AppCompatCapability.asLazy;
+
+import android.annotation.NonNull;
+import android.content.pm.ActivityInfo;
+import android.util.Slog;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.wm.utils.OptPropFactory;
+
+import java.util.function.BooleanSupplier;
+
+class AppCompatOrientationCapability {
+
+ private static final String TAG = TAG_WITH_CLASS_NAME ? "AppCompatCapability" : TAG_ATM;
+
+ @NonNull
+ private final ActivityRecord mActivityRecord;
+
+ @NonNull
+ private final OptPropFactory.OptProp mIgnoreRequestedOrientationOptProp;
+ @NonNull
+ private final OptPropFactory.OptProp mAllowIgnoringOrientationRequestWhenLoopDetectedOptProp;
+
+ @NonNull
+ final OrientationCapabilityState mOrientationCapabilityState;
+
+ AppCompatOrientationCapability(@NonNull OptPropFactory optPropBuilder,
+ @NonNull LetterboxConfiguration letterboxConfiguration,
+ @NonNull ActivityRecord activityRecord) {
+ mActivityRecord = activityRecord;
+ mOrientationCapabilityState = new OrientationCapabilityState(mActivityRecord);
+ final BooleanSupplier isPolicyForIgnoringRequestedOrientationEnabled = asLazy(
+ letterboxConfiguration::isPolicyForIgnoringRequestedOrientationEnabled);
+ mIgnoreRequestedOrientationOptProp = optPropBuilder.create(
+ PROPERTY_COMPAT_IGNORE_REQUESTED_ORIENTATION,
+ isPolicyForIgnoringRequestedOrientationEnabled);
+ mAllowIgnoringOrientationRequestWhenLoopDetectedOptProp = optPropBuilder.create(
+ PROPERTY_COMPAT_ALLOW_IGNORING_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED,
+ isPolicyForIgnoringRequestedOrientationEnabled);
+ }
+
+ /**
+ * Whether should ignore app requested orientation in response to an app
+ * calling {@link android.app.Activity#setRequestedOrientation}.
+ *
+ * <p>This is needed to avoid getting into {@link android.app.Activity#setRequestedOrientation}
+ * loop when {@link DisplayContent#getIgnoreOrientationRequest} is enabled or device has
+ * landscape natural orientation which app developers don't expect. For example, the loop can
+ * look like this:
+ * <ol>
+ * <li>App sets default orientation to "unspecified" at runtime
+ * <li>App requests to "portrait" after checking some condition (e.g. display rotation).
+ * <li>(2) leads to fullscreen -> letterboxed bounds change and activity relaunch because
+ * app can't handle the corresponding config changes.
+ * <li>Loop goes back to (1)
+ * </ol>
+ *
+ * <p>This treatment is enabled when the following conditions are met:
+ * <ul>
+ * <li>Flag gating the treatment is enabled
+ * <li>Opt-out component property isn't enabled
+ * <li>Opt-in component property or per-app override are enabled
+ * <li>Activity is relaunched after {@link android.app.Activity#setRequestedOrientation}
+ * call from an app or camera compat force rotation treatment is active for the activity.
+ * <li>Orientation request loop detected and is not letterboxed for fixed orientation
+ * </ul>
+ */
+ boolean shouldIgnoreRequestedOrientation(
+ @ActivityInfo.ScreenOrientation int requestedOrientation) {
+ if (mIgnoreRequestedOrientationOptProp.shouldEnableWithOverrideAndProperty(
+ isCompatChangeEnabled(OVERRIDE_ENABLE_COMPAT_IGNORE_REQUESTED_ORIENTATION))) {
+ if (mOrientationCapabilityState.mIsRelaunchingAfterRequestedOrientationChanged) {
+ Slog.w(TAG, "Ignoring orientation update to "
+ + screenOrientationToString(requestedOrientation)
+ + " due to relaunching after setRequestedOrientation for "
+ + mActivityRecord);
+ return true;
+ }
+ if (isCameraCompatTreatmentActive()) {
+ Slog.w(TAG, "Ignoring orientation update to "
+ + screenOrientationToString(requestedOrientation)
+ + " due to camera compat treatment for " + mActivityRecord);
+ return true;
+ }
+ }
+
+ if (shouldIgnoreOrientationRequestLoop()) {
+ Slog.w(TAG, "Ignoring orientation update to "
+ + screenOrientationToString(requestedOrientation)
+ + " as orientation request loop was detected for "
+ + mActivityRecord);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Whether an app is calling {@link android.app.Activity#setRequestedOrientation}
+ * in a loop and orientation request should be ignored.
+ *
+ * <p>This should only be called once in response to
+ * {@link android.app.Activity#setRequestedOrientation}. See
+ * {@link #shouldIgnoreRequestedOrientation} for more details.
+ *
+ * <p>This treatment is enabled when the following conditions are met:
+ * <ul>
+ * <li>Flag gating the treatment is enabled
+ * <li>Opt-out component property isn't enabled
+ * <li>Per-app override is enabled
+ * <li>App has requested orientation more than 2 times within 1-second
+ * timer and activity is not letterboxed for fixed orientation
+ * </ul>
+ */
+ boolean shouldIgnoreOrientationRequestLoop() {
+ final boolean loopDetectionEnabled = isCompatChangeEnabled(
+ OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED);
+ if (!mAllowIgnoringOrientationRequestWhenLoopDetectedOptProp
+ .shouldEnableWithOptInOverrideAndOptOutProperty(loopDetectionEnabled)) {
+ return false;
+ }
+ mOrientationCapabilityState.updateOrientationRequestLoopState();
+
+ return mOrientationCapabilityState.shouldIgnoreRequestInLoop()
+ && !mActivityRecord.isLetterboxedForFixedOrientationAndAspectRatio();
+ }
+
+ /**
+ * Sets whether an activity is relaunching after the app has called {@link
+ * android.app.Activity#setRequestedOrientation}.
+ */
+ void setRelaunchingAfterRequestedOrientationChanged(boolean isRelaunching) {
+ mOrientationCapabilityState
+ .mIsRelaunchingAfterRequestedOrientationChanged = isRelaunching;
+ }
+
+ boolean getIsRelaunchingAfterRequestedOrientationChanged() {
+ return mOrientationCapabilityState.mIsRelaunchingAfterRequestedOrientationChanged;
+ }
+
+ @VisibleForTesting
+ int getSetOrientationRequestCounter() {
+ return mOrientationCapabilityState.mSetOrientationRequestCounter;
+ }
+
+ private boolean isCompatChangeEnabled(long overrideChangeId) {
+ return mActivityRecord.info.isChangeEnabled(overrideChangeId);
+ }
+
+ /**
+ * @return {@code true} if the App Compat Camera Policy is active for the current activity.
+ */
+ // TODO(b/346253439): Remove after defining dependency with Camera capabilities.
+ private boolean isCameraCompatTreatmentActive() {
+ DisplayContent displayContent = mActivityRecord.mDisplayContent;
+ if (displayContent == null) {
+ return false;
+ }
+ return displayContent.mDisplayRotationCompatPolicy != null
+ && displayContent.mDisplayRotationCompatPolicy
+ .isTreatmentEnabledForActivity(mActivityRecord);
+ }
+
+ static class OrientationCapabilityState {
+ // Corresponds to OVERRIDE_UNDEFINED_ORIENTATION_TO_NOSENSOR
+ final boolean mIsOverrideToNosensorOrientationEnabled;
+ // Corresponds to OVERRIDE_UNDEFINED_ORIENTATION_TO_PORTRAIT
+ final boolean mIsOverrideToPortraitOrientationEnabled;
+ // Corresponds to OVERRIDE_ANY_ORIENTATION
+ final boolean mIsOverrideAnyOrientationEnabled;
+ // Corresponds to OVERRIDE_LANDSCAPE_ORIENTATION_TO_REVERSE_LANDSCAPE
+ final boolean mIsOverrideToReverseLandscapeOrientationEnabled;
+
+ private boolean mIsRelaunchingAfterRequestedOrientationChanged;
+
+ // Used to determine reset of mSetOrientationRequestCounter if next app requested
+ // orientation is after timeout value
+ @VisibleForTesting
+ static final int SET_ORIENTATION_REQUEST_COUNTER_TIMEOUT_MS = 1000;
+ // Minimum value of mSetOrientationRequestCounter before qualifying as orientation request
+ // loop
+ @VisibleForTesting
+ static final int MIN_COUNT_TO_IGNORE_REQUEST_IN_LOOP = 2;
+ // Updated when ActivityRecord#setRequestedOrientation is called
+ private long mTimeMsLastSetOrientationRequest = 0;
+ // Counter for ActivityRecord#setRequestedOrientation
+ private int mSetOrientationRequestCounter = 0;
+
+ OrientationCapabilityState(@NonNull ActivityRecord activityRecord) {
+ mIsOverrideToNosensorOrientationEnabled =
+ activityRecord.info.isChangeEnabled(OVERRIDE_UNDEFINED_ORIENTATION_TO_NOSENSOR);
+ mIsOverrideToPortraitOrientationEnabled =
+ activityRecord.info.isChangeEnabled(OVERRIDE_UNDEFINED_ORIENTATION_TO_PORTRAIT);
+ mIsOverrideAnyOrientationEnabled =
+ activityRecord.info.isChangeEnabled(OVERRIDE_ANY_ORIENTATION);
+ mIsOverrideToReverseLandscapeOrientationEnabled = activityRecord.info
+ .isChangeEnabled(OVERRIDE_LANDSCAPE_ORIENTATION_TO_REVERSE_LANDSCAPE);
+ }
+
+ /**
+ * @return {@code true} if we should start ignoring orientation in a orientation request
+ * loop.
+ */
+ boolean shouldIgnoreRequestInLoop() {
+ return mSetOrientationRequestCounter >= MIN_COUNT_TO_IGNORE_REQUEST_IN_LOOP;
+ }
+
+ /**
+ * Updates the orientation request counter using a specific timeout.
+ */
+ void updateOrientationRequestLoopState() {
+ final long currTimeMs = System.currentTimeMillis();
+ final long elapsedTime = currTimeMs - mTimeMsLastSetOrientationRequest;
+ if (elapsedTime < SET_ORIENTATION_REQUEST_COUNTER_TIMEOUT_MS) {
+ mSetOrientationRequestCounter++;
+ } else {
+ mSetOrientationRequestCounter = 0;
+ }
+ mTimeMsLastSetOrientationRequest = currTimeMs;
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/wm/AppCompatOrientationPolicy.java b/services/core/java/com/android/server/wm/AppCompatOrientationPolicy.java
new file mode 100644
index 0000000..c505ff9
--- /dev/null
+++ b/services/core/java/com/android/server/wm/AppCompatOrientationPolicy.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+package com.android.server.wm;
+
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LOCKED;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_USER;
+import static android.content.pm.ActivityInfo.isFixedOrientation;
+import static android.content.pm.ActivityInfo.isFixedOrientationLandscape;
+import static android.content.pm.ActivityInfo.screenOrientationToString;
+
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
+
+import android.annotation.NonNull;
+import android.content.pm.ActivityInfo;
+import android.util.Slog;
+
+import java.util.function.BooleanSupplier;
+
+/**
+ * Contains all the logic related to orientation in the context of app compatibility
+ */
+class AppCompatOrientationPolicy {
+
+ private static final String TAG = TAG_WITH_CLASS_NAME ? "AppCompatOrientationPolicy" : TAG_ATM;
+
+ @NonNull
+ private final ActivityRecord mActivityRecord;
+
+ @NonNull
+ private final AppCompatCapability mAppCompatCapability;
+
+ @NonNull
+ private final BooleanSupplier mShouldApplyUserFullscreenOverride;
+ @NonNull
+ private final BooleanSupplier mShouldApplyUserMinAspectRatioOverride;
+ @NonNull
+ private final BooleanSupplier mIsSystemOverrideToFullscreenEnabled;
+
+ // TODO(b/341903757) Remove BooleanSuppliers after fixing dependency with spectRatio component
+ AppCompatOrientationPolicy(@NonNull ActivityRecord activityRecord,
+ @NonNull AppCompatCapability appCompatCapability,
+ @NonNull BooleanSupplier shouldApplyUserFullscreenOverride,
+ @NonNull BooleanSupplier shouldApplyUserMinAspectRatioOverride,
+ @NonNull BooleanSupplier isSystemOverrideToFullscreenEnabled) {
+ mActivityRecord = activityRecord;
+ mAppCompatCapability = appCompatCapability;
+ mShouldApplyUserFullscreenOverride = shouldApplyUserFullscreenOverride;
+ mShouldApplyUserMinAspectRatioOverride = shouldApplyUserMinAspectRatioOverride;
+ mIsSystemOverrideToFullscreenEnabled = isSystemOverrideToFullscreenEnabled;
+ }
+
+ @ActivityInfo.ScreenOrientation
+ int overrideOrientationIfNeeded(@ActivityInfo.ScreenOrientation int candidate) {
+ final DisplayContent displayContent = mActivityRecord.mDisplayContent;
+ final boolean isIgnoreOrientationRequestEnabled = displayContent != null
+ && displayContent.getIgnoreOrientationRequest();
+ if (mShouldApplyUserFullscreenOverride.getAsBoolean() && isIgnoreOrientationRequestEnabled
+ // Do not override orientation to fullscreen for camera activities.
+ // Fixed-orientation activities are rarely tested in other orientations, and it
+ // often results in sideways or stretched previews. As the camera compat treatment
+ // targets fixed-orientation activities, overriding the orientation disables the
+ // treatment.
+ && !mActivityRecord.isCameraActive()) {
+ Slog.v(TAG, "Requested orientation " + screenOrientationToString(candidate)
+ + " for " + mActivityRecord + " is overridden to "
+ + screenOrientationToString(SCREEN_ORIENTATION_USER)
+ + " by user aspect ratio settings.");
+ return SCREEN_ORIENTATION_USER;
+ }
+
+ // In some cases (e.g. Kids app) we need to map the candidate orientation to some other
+ // orientation.
+ candidate = mActivityRecord.mWmService.mapOrientationRequest(candidate);
+
+ if (mShouldApplyUserMinAspectRatioOverride.getAsBoolean() && (!isFixedOrientation(candidate)
+ || candidate == SCREEN_ORIENTATION_LOCKED)) {
+ Slog.v(TAG, "Requested orientation " + screenOrientationToString(candidate)
+ + " for " + mActivityRecord + " is overridden to "
+ + screenOrientationToString(SCREEN_ORIENTATION_PORTRAIT)
+ + " by user aspect ratio settings.");
+ return SCREEN_ORIENTATION_PORTRAIT;
+ }
+
+ if (mAppCompatCapability.isAllowOrientationOverrideOptOut()) {
+ return candidate;
+ }
+
+ if (displayContent != null && mAppCompatCapability
+ .isOverrideOrientationOnlyForCameraEnabled()
+ && (displayContent.mDisplayRotationCompatPolicy == null
+ || !displayContent.mDisplayRotationCompatPolicy
+ .isActivityEligibleForOrientationOverride(mActivityRecord))) {
+ return candidate;
+ }
+
+ // mUserAspectRatio is always initialized first in shouldApplyUserFullscreenOverride(),
+ // which will always come first before this check as user override > device
+ // manufacturer override.
+ if (mIsSystemOverrideToFullscreenEnabled.getAsBoolean() && isIgnoreOrientationRequestEnabled
+ // Do not override orientation to fullscreen for camera activities.
+ // Fixed-orientation activities are rarely tested in other orientations, and it
+ // often results in sideways or stretched previews. As the camera compat treatment
+ // targets fixed-orientation activities, overriding the orientation disables the
+ // treatment.
+ && !mActivityRecord.isCameraActive()) {
+ Slog.v(TAG, "Requested orientation " + screenOrientationToString(candidate)
+ + " for " + mActivityRecord + " is overridden to "
+ + screenOrientationToString(SCREEN_ORIENTATION_USER));
+ return SCREEN_ORIENTATION_USER;
+ }
+
+ final AppCompatOrientationCapability.OrientationCapabilityState capabilityState =
+ mAppCompatCapability.getAppCompatOrientationCapability()
+ .mOrientationCapabilityState;
+
+ if (capabilityState.mIsOverrideToReverseLandscapeOrientationEnabled
+ && (isFixedOrientationLandscape(candidate)
+ || capabilityState.mIsOverrideAnyOrientationEnabled)) {
+ Slog.w(TAG, "Requested orientation " + screenOrientationToString(candidate) + " for "
+ + mActivityRecord + " is overridden to "
+ + screenOrientationToString(SCREEN_ORIENTATION_REVERSE_LANDSCAPE));
+ return SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
+ }
+
+ if (!capabilityState.mIsOverrideAnyOrientationEnabled && isFixedOrientation(candidate)) {
+ return candidate;
+ }
+
+ if (capabilityState.mIsOverrideToPortraitOrientationEnabled) {
+ Slog.w(TAG, "Requested orientation " + screenOrientationToString(candidate) + " for "
+ + mActivityRecord + " is overridden to "
+ + screenOrientationToString(SCREEN_ORIENTATION_PORTRAIT));
+ return SCREEN_ORIENTATION_PORTRAIT;
+ }
+
+ if (capabilityState.mIsOverrideToNosensorOrientationEnabled) {
+ Slog.w(TAG, "Requested orientation " + screenOrientationToString(candidate) + " for "
+ + mActivityRecord + " is overridden to "
+ + screenOrientationToString(SCREEN_ORIENTATION_NOSENSOR));
+ return SCREEN_ORIENTATION_NOSENSOR;
+ }
+
+ return candidate;
+ }
+
+}
diff --git a/services/core/java/com/android/server/wm/Letterbox.java b/services/core/java/com/android/server/wm/Letterbox.java
index 362d4ef..2aa7c0c 100644
--- a/services/core/java/com/android/server/wm/Letterbox.java
+++ b/services/core/java/com/android/server/wm/Letterbox.java
@@ -20,6 +20,7 @@
import static android.view.SurfaceControl.HIDDEN;
import static android.window.TaskConstants.TASK_CHILD_LAYER_LETTERBOX_BACKGROUND;
+import android.annotation.NonNull;
import android.graphics.Color;
import android.graphics.Point;
import android.graphics.Rect;
@@ -209,16 +210,18 @@
return false;
}
- public void applySurfaceChanges(SurfaceControl.Transaction t) {
+ /** Applies surface changes such as colour, window crop, position and input info. */
+ public void applySurfaceChanges(@NonNull SurfaceControl.Transaction t,
+ @NonNull SurfaceControl.Transaction inputT) {
if (useFullWindowSurface()) {
- mFullWindowSurface.applySurfaceChanges(t);
+ mFullWindowSurface.applySurfaceChanges(t, inputT);
for (LetterboxSurface surface : mSurfaces) {
surface.remove();
}
} else {
for (LetterboxSurface surface : mSurfaces) {
- surface.applySurfaceChanges(t);
+ surface.applySurfaceChanges(t, inputT);
}
mFullWindowSurface.remove();
@@ -418,7 +421,8 @@
return Math.max(0, mLayoutFrameGlobal.height());
}
- public void applySurfaceChanges(SurfaceControl.Transaction t) {
+ public void applySurfaceChanges(@NonNull SurfaceControl.Transaction t,
+ @NonNull SurfaceControl.Transaction inputT) {
if (!needsApplySurfaceChanges()) {
// Nothing changed.
return;
@@ -446,7 +450,7 @@
}
if (mSurface != null && mInputInterceptor != null) {
mInputInterceptor.updateTouchableRegion(mSurfaceFrameRelative);
- t.setInputWindowInfo(mSurface, mInputInterceptor.mWindowHandle);
+ inputT.setInputWindowInfo(mSurface, mInputInterceptor.mWindowHandle);
}
}
diff --git a/services/core/java/com/android/server/wm/LetterboxUiController.java b/services/core/java/com/android/server/wm/LetterboxUiController.java
index 14a0467..17547f5 100644
--- a/services/core/java/com/android/server/wm/LetterboxUiController.java
+++ b/services/core/java/com/android/server/wm/LetterboxUiController.java
@@ -18,33 +18,7 @@
import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_FREEFORM_NONE;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
-import static android.content.pm.ActivityInfo.FORCE_NON_RESIZE_APP;
-import static android.content.pm.ActivityInfo.FORCE_RESIZE_APP;
-import static android.content.pm.ActivityInfo.OVERRIDE_ANY_ORIENTATION;
-import static android.content.pm.ActivityInfo.OVERRIDE_ANY_ORIENTATION_TO_USER;
-import static android.content.pm.ActivityInfo.OVERRIDE_CAMERA_COMPAT_DISABLE_FORCE_ROTATION;
-import static android.content.pm.ActivityInfo.OVERRIDE_CAMERA_COMPAT_DISABLE_FREEFORM_WINDOWING_TREATMENT;
-import static android.content.pm.ActivityInfo.OVERRIDE_CAMERA_COMPAT_DISABLE_REFRESH;
-import static android.content.pm.ActivityInfo.OVERRIDE_CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE;
-import static android.content.pm.ActivityInfo.OVERRIDE_ENABLE_COMPAT_FAKE_FOCUS;
-import static android.content.pm.ActivityInfo.OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED;
-import static android.content.pm.ActivityInfo.OVERRIDE_ENABLE_COMPAT_IGNORE_REQUESTED_ORIENTATION;
-import static android.content.pm.ActivityInfo.OVERRIDE_LANDSCAPE_ORIENTATION_TO_REVERSE_LANDSCAPE;
-import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO;
-import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_ONLY_FOR_CAMERA;
-import static android.content.pm.ActivityInfo.OVERRIDE_ORIENTATION_ONLY_FOR_CAMERA;
-import static android.content.pm.ActivityInfo.OVERRIDE_RESPECT_REQUESTED_ORIENTATION;
-import static android.content.pm.ActivityInfo.OVERRIDE_UNDEFINED_ORIENTATION_TO_NOSENSOR;
-import static android.content.pm.ActivityInfo.OVERRIDE_UNDEFINED_ORIENTATION_TO_PORTRAIT;
-import static android.content.pm.ActivityInfo.OVERRIDE_USE_DISPLAY_LANDSCAPE_NATURAL_ORIENTATION;
-import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LOCKED;
-import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
-import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
-import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
-import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_USER;
-import static android.content.pm.ActivityInfo.isFixedOrientation;
import static android.content.pm.ActivityInfo.isFixedOrientationLandscape;
-import static android.content.pm.ActivityInfo.screenOrientationToString;
import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_16_9;
import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_3_2;
import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_4_3;
@@ -53,22 +27,9 @@
import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_FULLSCREEN;
import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_SPLIT_SCREEN;
import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_UNSET;
-import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
-import static android.view.WindowManager.PROPERTY_CAMERA_COMPAT_ALLOW_FORCE_ROTATION;
-import static android.view.WindowManager.PROPERTY_CAMERA_COMPAT_ALLOW_REFRESH;
-import static android.view.WindowManager.PROPERTY_CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE;
-import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_DISPLAY_ORIENTATION_OVERRIDE;
-import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_IGNORING_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED;
-import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_MIN_ASPECT_RATIO_OVERRIDE;
-import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_ORIENTATION_OVERRIDE;
-import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_RESIZEABLE_ACTIVITY_OVERRIDES;
-import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_FULLSCREEN_OVERRIDE;
-import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_OVERRIDE;
-import static android.view.WindowManager.PROPERTY_COMPAT_ENABLE_FAKE_FOCUS;
-import static android.view.WindowManager.PROPERTY_COMPAT_IGNORE_REQUESTED_ORIENTATION;
import static com.android.internal.util.FrameworkStatsLog.APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__BOTTOM;
import static com.android.internal.util.FrameworkStatsLog.APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__CENTER;
@@ -126,31 +87,17 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.statusbar.LetterboxDetails;
import com.android.server.wm.LetterboxConfiguration.LetterboxBackgroundType;
-import com.android.server.wm.utils.OptPropFactory;
-import com.android.server.wm.utils.OptPropFactory.OptProp;
import com.android.window.flags.Flags;
import java.io.PrintWriter;
-import java.util.function.BooleanSupplier;
/** Controls behaviour of the letterbox UI for {@link mActivityRecord}. */
// TODO(b/185262487): Improve test coverage of this class. Parts of it are tested in
// SizeCompatTests and LetterboxTests but not all.
-// TODO(b/185264020): Consider making LetterboxUiController applicable to any level of the
-// hierarchy in addition to ActivityRecord (Task, DisplayArea, ...).
-// TODO(b/263021211): Consider renaming to more generic CompatUIController.
final class LetterboxUiController {
private static final String TAG = TAG_WITH_CLASS_NAME ? "LetterboxUiController" : TAG_ATM;
- // Minimum value of mSetOrientationRequestCounter before qualifying as orientation request loop
- @VisibleForTesting
- static final int MIN_COUNT_TO_IGNORE_REQUEST_IN_LOOP = 2;
- // Used to determine reset of mSetOrientationRequestCounter if next app requested
- // orientation is after timeout value
- @VisibleForTesting
- static final int SET_ORIENTATION_REQUEST_COUNTER_TIMEOUT_MS = 1000;
-
private final Point mTmpPoint = new Point();
private final LetterboxConfiguration mLetterboxConfiguration;
@@ -159,43 +106,9 @@
// TODO(b/265576778): Cache other overrides as well.
- // Corresponds to OVERRIDE_ANY_ORIENTATION
- private final boolean mIsOverrideAnyOrientationEnabled;
- // Corresponds to OVERRIDE_ANY_ORIENTATION_TO_USER
- private final boolean mIsSystemOverrideToFullscreenEnabled;
- // Corresponds to OVERRIDE_UNDEFINED_ORIENTATION_TO_PORTRAIT
- private final boolean mIsOverrideToPortraitOrientationEnabled;
- // Corresponds to OVERRIDE_UNDEFINED_ORIENTATION_TO_NOSENSOR
- private final boolean mIsOverrideToNosensorOrientationEnabled;
- // Corresponds to OVERRIDE_LANDSCAPE_ORIENTATION_TO_REVERSE_LANDSCAPE
- private final boolean mIsOverrideToReverseLandscapeOrientationEnabled;
- // Corresponds to OVERRIDE_ORIENTATION_ONLY_FOR_CAMERA
- private final boolean mIsOverrideOrientationOnlyForCameraEnabled;
- // Corresponds to OVERRIDE_RESPECT_REQUESTED_ORIENTATION
- private final boolean mIsOverrideRespectRequestedOrientationEnabled;
-
- @NonNull
- private final OptProp mAllowOrientationOverrideOptProp;
- @NonNull
- private final OptProp mAllowDisplayOrientationOverrideOptProp;
- @NonNull
- private final OptProp mAllowMinAspectRatioOverrideOptProp;
- @NonNull
- private final OptProp mAllowForceResizeOverrideOptProp;
-
- @NonNull
- private final OptProp mAllowUserAspectRatioOverrideOptProp;
- @NonNull
- private final OptProp mAllowUserAspectRatioFullscreenOverrideOptProp;
private boolean mShowWallpaperForLetterboxBackground;
- // Updated when ActivityRecord#setRequestedOrientation is called
- private long mTimeMsLastSetOrientationRequest = 0;
-
- // Counter for ActivityRecord#setRequestedOrientation
- private int mSetOrientationRequestCounter = 0;
-
// TODO(b/315140179): Make mUserAspectRatio final
// The min aspect ratio override set by user
@PackageManager.UserMinAspectRatio
@@ -204,31 +117,11 @@
@Nullable
private Letterbox mLetterbox;
- @NonNull
- private final OptProp mCameraCompatAllowForceRotationOptProp;
-
- @NonNull
- private final OptProp mCameraCompatAllowRefreshOptProp;
-
- @NonNull
- private final OptProp mCameraCompatEnableRefreshViaPauseOptProp;
-
// Whether activity "refresh" was requested but not finished in
// ActivityRecord#activityResumedLocked following the camera compat force rotation in
// DisplayRotationCompatPolicy.
private boolean mIsRefreshRequested;
- @NonNull
- private final OptProp mIgnoreRequestedOrientationOptProp;
-
- @NonNull
- private final OptProp mAllowIgnoringOrientationRequestWhenLoopDetectedOptProp;
-
- @NonNull
- private final OptProp mFakeFocusOptProp;
-
- private boolean mIsRelaunchingAfterRequestedOrientationChanged;
-
private boolean mLastShouldShowLetterboxUi;
private boolean mDoubleTapEvent;
@@ -242,76 +135,6 @@
// is created in its constructor. It shouldn't be used in this constructor but it's safe
// to use it after since controller is only used in ActivityRecord.
mActivityRecord = activityRecord;
-
- PackageManager packageManager = wmService.mContext.getPackageManager();
-
- final OptPropFactory optPropBuilder = new OptPropFactory(packageManager,
- activityRecord.packageName);
-
- final BooleanSupplier isPolicyForIgnoringRequestedOrientationEnabled = asLazy(
- mLetterboxConfiguration::isPolicyForIgnoringRequestedOrientationEnabled);
- mIgnoreRequestedOrientationOptProp = optPropBuilder.create(
- PROPERTY_COMPAT_IGNORE_REQUESTED_ORIENTATION,
- isPolicyForIgnoringRequestedOrientationEnabled);
- mAllowIgnoringOrientationRequestWhenLoopDetectedOptProp = optPropBuilder.create(
- PROPERTY_COMPAT_ALLOW_IGNORING_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED,
- isPolicyForIgnoringRequestedOrientationEnabled);
-
- mFakeFocusOptProp = optPropBuilder.create(PROPERTY_COMPAT_ENABLE_FAKE_FOCUS,
- mLetterboxConfiguration::isCompatFakeFocusEnabled);
-
- final BooleanSupplier isCameraCompatTreatmentEnabled = asLazy(
- mLetterboxConfiguration::isCameraCompatTreatmentEnabled);
- mCameraCompatAllowForceRotationOptProp = optPropBuilder.create(
- PROPERTY_CAMERA_COMPAT_ALLOW_FORCE_ROTATION,
- isCameraCompatTreatmentEnabled);
- mCameraCompatAllowRefreshOptProp = optPropBuilder.create(
- PROPERTY_CAMERA_COMPAT_ALLOW_REFRESH,
- isCameraCompatTreatmentEnabled);
- mCameraCompatEnableRefreshViaPauseOptProp = optPropBuilder.create(
- PROPERTY_CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE,
- isCameraCompatTreatmentEnabled);
-
- mAllowOrientationOverrideOptProp = optPropBuilder.create(
- PROPERTY_COMPAT_ALLOW_ORIENTATION_OVERRIDE);
-
- mAllowDisplayOrientationOverrideOptProp = optPropBuilder.create(
- PROPERTY_COMPAT_ALLOW_DISPLAY_ORIENTATION_OVERRIDE,
- () -> mActivityRecord.mDisplayContent != null
- && mActivityRecord.getTask() != null
- && mActivityRecord.mDisplayContent.getIgnoreOrientationRequest()
- && !mActivityRecord.getTask().inMultiWindowMode()
- && mActivityRecord.mDisplayContent.getNaturalOrientation()
- == ORIENTATION_LANDSCAPE
- );
-
- mAllowMinAspectRatioOverrideOptProp = optPropBuilder.create(
- PROPERTY_COMPAT_ALLOW_MIN_ASPECT_RATIO_OVERRIDE);
-
- mAllowForceResizeOverrideOptProp = optPropBuilder.create(
- PROPERTY_COMPAT_ALLOW_RESIZEABLE_ACTIVITY_OVERRIDES);
-
- mAllowUserAspectRatioOverrideOptProp = optPropBuilder.create(
- PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_OVERRIDE,
- mLetterboxConfiguration::isUserAppAspectRatioSettingsEnabled);
-
- mAllowUserAspectRatioFullscreenOverrideOptProp = optPropBuilder.create(
- PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_FULLSCREEN_OVERRIDE,
- mLetterboxConfiguration::isUserAppAspectRatioFullscreenEnabled);
-
- mIsOverrideAnyOrientationEnabled = isCompatChangeEnabled(OVERRIDE_ANY_ORIENTATION);
- mIsSystemOverrideToFullscreenEnabled =
- isCompatChangeEnabled(OVERRIDE_ANY_ORIENTATION_TO_USER);
- mIsOverrideToPortraitOrientationEnabled =
- isCompatChangeEnabled(OVERRIDE_UNDEFINED_ORIENTATION_TO_PORTRAIT);
- mIsOverrideToReverseLandscapeOrientationEnabled =
- isCompatChangeEnabled(OVERRIDE_LANDSCAPE_ORIENTATION_TO_REVERSE_LANDSCAPE);
- mIsOverrideToNosensorOrientationEnabled =
- isCompatChangeEnabled(OVERRIDE_UNDEFINED_ORIENTATION_TO_NOSENSOR);
- mIsOverrideOrientationOnlyForCameraEnabled =
- isCompatChangeEnabled(OVERRIDE_ORIENTATION_ONLY_FOR_CAMERA);
- mIsOverrideRespectRequestedOrientationEnabled =
- isCompatChangeEnabled(OVERRIDE_RESPECT_REQUESTED_ORIENTATION);
}
/** Cleans up {@link Letterbox} if it exists.*/
@@ -320,7 +143,6 @@
mLetterbox.destroy();
mLetterbox = null;
}
- mActivityRecord.mTransparentPolicy.stop();
}
void onMovedToDisplay(int displayId) {
@@ -330,60 +152,6 @@
}
/**
- * Whether should ignore app requested orientation in response to an app
- * calling {@link android.app.Activity#setRequestedOrientation}.
- *
- * <p>This is needed to avoid getting into {@link android.app.Activity#setRequestedOrientation}
- * loop when {@link DisplayContent#getIgnoreOrientationRequest} is enabled or device has
- * landscape natural orientation which app developers don't expect. For example, the loop can
- * look like this:
- * <ol>
- * <li>App sets default orientation to "unspecified" at runtime
- * <li>App requests to "portrait" after checking some condition (e.g. display rotation).
- * <li>(2) leads to fullscreen -> letterboxed bounds change and activity relaunch because
- * app can't handle the corresponding config changes.
- * <li>Loop goes back to (1)
- * </ol>
- *
- * <p>This treatment is enabled when the following conditions are met:
- * <ul>
- * <li>Flag gating the treatment is enabled
- * <li>Opt-out component property isn't enabled
- * <li>Opt-in component property or per-app override are enabled
- * <li>Activity is relaunched after {@link android.app.Activity#setRequestedOrientation}
- * call from an app or camera compat force rotation treatment is active for the activity.
- * <li>Orientation request loop detected and is not letterboxed for fixed orientation
- * </ul>
- */
- boolean shouldIgnoreRequestedOrientation(@ScreenOrientation int requestedOrientation) {
- if (mIgnoreRequestedOrientationOptProp.shouldEnableWithOverrideAndProperty(
- isCompatChangeEnabled(OVERRIDE_ENABLE_COMPAT_IGNORE_REQUESTED_ORIENTATION))) {
- if (mIsRelaunchingAfterRequestedOrientationChanged) {
- Slog.w(TAG, "Ignoring orientation update to "
- + screenOrientationToString(requestedOrientation)
- + " due to relaunching after setRequestedOrientation for "
- + mActivityRecord);
- return true;
- }
- if (isCameraCompatTreatmentActive()) {
- Slog.w(TAG, "Ignoring orientation update to "
- + screenOrientationToString(requestedOrientation)
- + " due to camera compat treatment for " + mActivityRecord);
- return true;
- }
- }
-
- if (shouldIgnoreOrientationRequestLoop()) {
- Slog.w(TAG, "Ignoring orientation update to "
- + screenOrientationToString(requestedOrientation)
- + " as orientation request loop was detected for "
- + mActivityRecord);
- return true;
- }
- return false;
- }
-
- /**
* Whether an app is calling {@link android.app.Activity#setRequestedOrientation}
* in a loop and orientation request should be ignored.
*
@@ -401,31 +169,14 @@
* </ul>
*/
boolean shouldIgnoreOrientationRequestLoop() {
- final boolean loopDetectionEnabled = isCompatChangeEnabled(
- OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED);
- if (!mAllowIgnoringOrientationRequestWhenLoopDetectedOptProp
- .shouldEnableWithOptInOverrideAndOptOutProperty(loopDetectionEnabled)) {
- return false;
- }
-
- final long currTimeMs = System.currentTimeMillis();
- if (currTimeMs - mTimeMsLastSetOrientationRequest
- < SET_ORIENTATION_REQUEST_COUNTER_TIMEOUT_MS) {
- mSetOrientationRequestCounter += 1;
- } else {
- // Resets app setOrientationRequest counter if timed out
- mSetOrientationRequestCounter = 0;
- }
- // Update time last called
- mTimeMsLastSetOrientationRequest = currTimeMs;
-
- return mSetOrientationRequestCounter >= MIN_COUNT_TO_IGNORE_REQUEST_IN_LOOP
- && !mActivityRecord.isLetterboxedForFixedOrientationAndAspectRatio();
+ return getAppCompatCapability().getAppCompatOrientationCapability()
+ .shouldIgnoreOrientationRequestLoop();
}
@VisibleForTesting
int getSetOrientationRequestCounter() {
- return mSetOrientationRequestCounter;
+ return getAppCompatCapability().getAppCompatOrientationCapability()
+ .getSetOrientationRequestCounter();
}
/**
@@ -441,8 +192,7 @@
* </ul>
*/
boolean shouldSendFakeFocus() {
- return mFakeFocusOptProp.shouldEnableWithOverrideAndProperty(
- isCompatChangeEnabled(OVERRIDE_ENABLE_COMPAT_FAKE_FOCUS));
+ return getAppCompatCapability().shouldSendFakeFocus();
}
/**
@@ -458,8 +208,7 @@
* </ul>
*/
boolean shouldOverrideMinAspectRatio() {
- return mAllowMinAspectRatioOverrideOptProp.shouldEnableWithOptInOverrideAndOptOutProperty(
- isCompatChangeEnabled(OVERRIDE_MIN_ASPECT_RATIO));
+ return getAppCompatCapability().shouldOverrideMinAspectRatio();
}
/**
@@ -476,10 +225,7 @@
* </ul>
*/
boolean shouldOverrideMinAspectRatioForCamera() {
- return mActivityRecord.isCameraActive()
- && mAllowMinAspectRatioOverrideOptProp
- .shouldEnableWithOptInOverrideAndOptOutProperty(
- isCompatChangeEnabled(OVERRIDE_MIN_ASPECT_RATIO_ONLY_FOR_CAMERA));
+ return getAppCompatCapability().shouldOverrideMinAspectRatioForCamera();
}
/**
@@ -495,8 +241,7 @@
* </ul>
*/
boolean shouldOverrideForceResizeApp() {
- return mAllowForceResizeOverrideOptProp.shouldEnableWithOptInOverrideAndOptOutProperty(
- isCompatChangeEnabled(FORCE_RESIZE_APP));
+ return getAppCompatCapability().shouldOverrideForceResizeApp();
}
/**
@@ -510,8 +255,7 @@
* </ul>
*/
boolean shouldOverrideForceNonResizeApp() {
- return mAllowForceResizeOverrideOptProp.shouldEnableWithOptInOverrideAndOptOutProperty(
- isCompatChangeEnabled(FORCE_NON_RESIZE_APP));
+ return getAppCompatCapability().shouldOverrideForceNonResizeApp();
}
/**
@@ -519,7 +263,8 @@
* android.app.Activity#setRequestedOrientation}.
*/
void setRelaunchingAfterRequestedOrientationChanged(boolean isRelaunching) {
- mIsRelaunchingAfterRequestedOrientationChanged = isRelaunching;
+ getAppCompatCapability().getAppCompatOrientationCapability()
+ .setRelaunchingAfterRequestedOrientationChanged(isRelaunching);
}
/**
@@ -534,7 +279,7 @@
}
boolean isOverrideRespectRequestedOrientationEnabled() {
- return mIsOverrideRespectRequestedOrientationEnabled;
+ return getAppCompatCapability().isOverrideRespectRequestedOrientationEnabled();
}
/**
@@ -551,101 +296,17 @@
* </ul>
*/
boolean shouldUseDisplayLandscapeNaturalOrientation() {
- return mAllowDisplayOrientationOverrideOptProp
- .shouldEnableWithOptInOverrideAndOptOutProperty(
- isCompatChangeEnabled(OVERRIDE_USE_DISPLAY_LANDSCAPE_NATURAL_ORIENTATION));
+ return getAppCompatCapability().shouldUseDisplayLandscapeNaturalOrientation();
}
@ScreenOrientation
int overrideOrientationIfNeeded(@ScreenOrientation int candidate) {
- final DisplayContent displayContent = mActivityRecord.mDisplayContent;
- final boolean isIgnoreOrientationRequestEnabled = displayContent != null
- && displayContent.getIgnoreOrientationRequest();
- if (shouldApplyUserFullscreenOverride() && isIgnoreOrientationRequestEnabled
- // Do not override orientation to fullscreen for camera activities.
- // Fixed-orientation activities are rarely tested in other orientations, and it
- // often results in sideways or stretched previews. As the camera compat treatment
- // targets fixed-orientation activities, overriding the orientation disables the
- // treatment.
- && !mActivityRecord.isCameraActive()) {
- Slog.v(TAG, "Requested orientation " + screenOrientationToString(candidate) + " for "
- + mActivityRecord + " is overridden to "
- + screenOrientationToString(SCREEN_ORIENTATION_USER)
- + " by user aspect ratio settings.");
- return SCREEN_ORIENTATION_USER;
- }
-
- // In some cases (e.g. Kids app) we need to map the candidate orientation to some other
- // orientation.
- candidate = mActivityRecord.mWmService.mapOrientationRequest(candidate);
-
- if (shouldApplyUserMinAspectRatioOverride() && (!isFixedOrientation(candidate)
- || candidate == SCREEN_ORIENTATION_LOCKED)) {
- Slog.v(TAG, "Requested orientation " + screenOrientationToString(candidate) + " for "
- + mActivityRecord + " is overridden to "
- + screenOrientationToString(SCREEN_ORIENTATION_PORTRAIT)
- + " by user aspect ratio settings.");
- return SCREEN_ORIENTATION_PORTRAIT;
- }
-
- if (mAllowOrientationOverrideOptProp.isFalse()) {
- return candidate;
- }
-
- if (mIsOverrideOrientationOnlyForCameraEnabled && displayContent != null
- && (displayContent.mDisplayRotationCompatPolicy == null
- || !displayContent.mDisplayRotationCompatPolicy
- .isActivityEligibleForOrientationOverride(mActivityRecord))) {
- return candidate;
- }
-
- // mUserAspectRatio is always initialized first in shouldApplyUserFullscreenOverride(),
- // which will always come first before this check as user override > device
- // manufacturer override.
- if (isSystemOverrideToFullscreenEnabled() && isIgnoreOrientationRequestEnabled
- // Do not override orientation to fullscreen for camera activities.
- // Fixed-orientation activities are rarely tested in other orientations, and it
- // often results in sideways or stretched previews. As the camera compat treatment
- // targets fixed-orientation activities, overriding the orientation disables the
- // treatment.
- && !mActivityRecord.isCameraActive()) {
- Slog.v(TAG, "Requested orientation " + screenOrientationToString(candidate) + " for "
- + mActivityRecord + " is overridden to "
- + screenOrientationToString(SCREEN_ORIENTATION_USER));
- return SCREEN_ORIENTATION_USER;
- }
-
- if (mIsOverrideToReverseLandscapeOrientationEnabled
- && (isFixedOrientationLandscape(candidate) || mIsOverrideAnyOrientationEnabled)) {
- Slog.w(TAG, "Requested orientation " + screenOrientationToString(candidate) + " for "
- + mActivityRecord + " is overridden to "
- + screenOrientationToString(SCREEN_ORIENTATION_REVERSE_LANDSCAPE));
- return SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
- }
-
- if (!mIsOverrideAnyOrientationEnabled && isFixedOrientation(candidate)) {
- return candidate;
- }
-
- if (mIsOverrideToPortraitOrientationEnabled) {
- Slog.w(TAG, "Requested orientation " + screenOrientationToString(candidate) + " for "
- + mActivityRecord + " is overridden to "
- + screenOrientationToString(SCREEN_ORIENTATION_PORTRAIT));
- return SCREEN_ORIENTATION_PORTRAIT;
- }
-
- if (mIsOverrideToNosensorOrientationEnabled) {
- Slog.w(TAG, "Requested orientation " + screenOrientationToString(candidate) + " for "
- + mActivityRecord + " is overridden to "
- + screenOrientationToString(SCREEN_ORIENTATION_NOSENSOR));
- return SCREEN_ORIENTATION_NOSENSOR;
- }
-
- return candidate;
+ return mActivityRecord.mAppCompatController.getOrientationPolicy()
+ .overrideOrientationIfNeeded(candidate);
}
boolean isOverrideOrientationOnlyForCameraEnabled() {
- return mIsOverrideOrientationOnlyForCameraEnabled;
+ return getAppCompatCapability().isOverrideOrientationOnlyForCameraEnabled();
}
/**
@@ -660,8 +321,7 @@
* </ul>
*/
boolean shouldRefreshActivityForCameraCompat() {
- return mCameraCompatAllowRefreshOptProp.shouldEnableWithOptOutOverrideAndProperty(
- isCompatChangeEnabled(OVERRIDE_CAMERA_COMPAT_DISABLE_REFRESH));
+ return getAppCompatCapability().shouldRefreshActivityForCameraCompat();
}
/**
@@ -679,8 +339,7 @@
* </ul>
*/
boolean shouldRefreshActivityViaPauseForCameraCompat() {
- return mCameraCompatEnableRefreshViaPauseOptProp.shouldEnableWithOverrideAndProperty(
- isCompatChangeEnabled(OVERRIDE_CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE));
+ return getAppCompatCapability().shouldRefreshActivityViaPauseForCameraCompat();
}
/**
@@ -695,8 +354,7 @@
* </ul>
*/
boolean shouldForceRotateForCameraCompat() {
- return mCameraCompatAllowForceRotationOptProp.shouldEnableWithOptOutOverrideAndProperty(
- isCompatChangeEnabled(OVERRIDE_CAMERA_COMPAT_DISABLE_FORCE_ROTATION));
+ return getAppCompatCapability().shouldForceRotateForCameraCompat();
}
/**
@@ -714,18 +372,7 @@
* </ul>
*/
boolean shouldApplyFreeformTreatmentForCameraCompat() {
- return Flags.cameraCompatForFreeform() && !isCompatChangeEnabled(
- OVERRIDE_CAMERA_COMPAT_DISABLE_FREEFORM_WINDOWING_TREATMENT);
- }
-
- private boolean isCameraCompatTreatmentActive() {
- DisplayContent displayContent = mActivityRecord.mDisplayContent;
- if (displayContent == null) {
- return false;
- }
- return displayContent.mDisplayRotationCompatPolicy != null
- && displayContent.mDisplayRotationCompatPolicy
- .isTreatmentEnabledForActivity(mActivityRecord);
+ return getAppCompatCapability().shouldApplyFreeformTreatmentForCameraCompat();
}
@FreeformCameraCompatMode
@@ -785,16 +432,18 @@
}
void updateLetterboxSurfaceIfNeeded(WindowState winHint) {
- updateLetterboxSurfaceIfNeeded(winHint, mActivityRecord.getSyncTransaction());
+ updateLetterboxSurfaceIfNeeded(winHint, mActivityRecord.getSyncTransaction(),
+ mActivityRecord.getPendingTransaction());
}
- void updateLetterboxSurfaceIfNeeded(WindowState winHint, Transaction t) {
+ void updateLetterboxSurfaceIfNeeded(WindowState winHint, @NonNull Transaction t,
+ @NonNull Transaction inputT) {
if (shouldNotLayoutLetterbox(winHint)) {
return;
}
layoutLetterboxIfNeeded(winHint);
if (mLetterbox != null && mLetterbox.needsApplySurfaceChanges()) {
- mLetterbox.applySurfaceChanges(t);
+ mLetterbox.applySurfaceChanges(t, inputT);
}
}
@@ -850,7 +499,8 @@
// For this reason we use ActivityRecord#getBounds() that the translucent activity
// inherits from the first opaque activity beneath and also takes care of the scaling
// in case of activities in size compat mode.
- final Rect innerFrame = mActivityRecord.mTransparentPolicy.isRunning()
+ final Rect innerFrame = mActivityRecord.mAppCompatController
+ .getTransparentPolicy().isRunning()
? mActivityRecord.getBounds() : w.getFrame();
mLetterbox.layout(spaceToFill, innerFrame, mTmpPoint);
if (mDoubleTapEvent) {
@@ -987,7 +637,7 @@
// Don't resize to split screen size when in book mode if letterbox position is centered
return (isBookMode && isNotCenteredHorizontally || isTabletopMode && isLandscape)
|| isCameraCompatSplitScreenAspectRatioAllowed()
- && isCameraCompatTreatmentActive();
+ && getAppCompatCapability().isCameraCompatTreatmentActive();
}
private float getDefaultMinAspectRatioForUnresizableApps() {
@@ -1089,13 +739,7 @@
* Whether we should enable users to resize the current app.
*/
boolean shouldEnableUserAspectRatioSettings() {
- // We use mBooleanPropertyAllowUserAspectRatioOverride to allow apps to opt-out which has
- // effect only if explicitly false. If mBooleanPropertyAllowUserAspectRatioOverride is null,
- // the current app doesn't opt-out so the first part of the predicate is true.
- return !mAllowUserAspectRatioOverrideOptProp.isFalse()
- && mLetterboxConfiguration.isUserAppAspectRatioSettingsEnabled()
- && mActivityRecord.mDisplayContent != null
- && mActivityRecord.mDisplayContent.getIgnoreOrientationRequest();
+ return getAppCompatCapability().shouldEnableUserAspectRatioSettings();
}
/**
@@ -1114,15 +758,6 @@
&& mUserAspectRatio != USER_MIN_ASPECT_RATIO_FULLSCREEN;
}
- boolean isUserFullscreenOverrideEnabled() {
- if (mAllowUserAspectRatioOverrideOptProp.isFalse()
- || mAllowUserAspectRatioFullscreenOverrideOptProp.isFalse()
- || !mLetterboxConfiguration.isUserAppAspectRatioFullscreenEnabled()) {
- return false;
- }
- return true;
- }
-
boolean shouldApplyUserFullscreenOverride() {
if (isUserFullscreenOverrideEnabled()) {
mUserAspectRatio = getUserMinAspectRatioOverrideCode();
@@ -1133,11 +768,12 @@
return false;
}
+ boolean isUserFullscreenOverrideEnabled() {
+ return getAppCompatCapability().isUserFullscreenOverrideEnabled();
+ }
+
boolean isSystemOverrideToFullscreenEnabled() {
- return mIsSystemOverrideToFullscreenEnabled
- && !mAllowOrientationOverrideOptProp.isFalse()
- && (mUserAspectRatio == USER_MIN_ASPECT_RATIO_UNSET
- || mUserAspectRatio == USER_MIN_ASPECT_RATIO_FULLSCREEN);
+ return getAppCompatCapability().isSystemOverrideToFullscreenEnabled(mUserAspectRatio);
}
boolean hasFullscreenOverride() {
@@ -1311,8 +947,9 @@
? parentAppBoundsOverride : parentConfiguration.windowConfiguration.getAppBounds();
// Use screen resolved bounds which uses resolved bounds or size compat bounds
// as activity bounds can sometimes be empty
- final Rect opaqueActivityBounds = mActivityRecord.mTransparentPolicy
- .getFirstOpaqueActivity().map(ActivityRecord::getScreenResolvedBounds)
+ final Rect opaqueActivityBounds = mActivityRecord.mAppCompatController
+ .getTransparentPolicy().getFirstOpaqueActivity()
+ .map(ActivityRecord::getScreenResolvedBounds)
.orElse(mActivityRecord.getScreenResolvedBounds());
return mLetterboxConfiguration.getIsHorizontalReachabilityEnabled()
&& parentConfiguration.windowConfiguration.getWindowingMode()
@@ -1331,6 +968,11 @@
return isHorizontalReachabilityEnabled() || isVerticalReachabilityEnabled();
}
+ // TODO(b/346264992): Remove after AppCompatController refactoring
+ private AppCompatCapability getAppCompatCapability() {
+ return mActivityRecord.mAppCompatController.getAppCompatCapability();
+ }
+
/**
* Whether vertical reachability is enabled for an activity in the current configuration.
*
@@ -1350,8 +992,9 @@
? parentAppBoundsOverride : parentConfiguration.windowConfiguration.getAppBounds();
// Use screen resolved bounds which uses resolved bounds or size compat bounds
// as activity bounds can sometimes be empty.
- final Rect opaqueActivityBounds = mActivityRecord.mTransparentPolicy
- .getFirstOpaqueActivity().map(ActivityRecord::getScreenResolvedBounds)
+ final Rect opaqueActivityBounds = mActivityRecord.mAppCompatController
+ .getTransparentPolicy().getFirstOpaqueActivity()
+ .map(ActivityRecord::getScreenResolvedBounds)
.orElse(mActivityRecord.getScreenResolvedBounds());
return mLetterboxConfiguration.getIsVerticalReachabilityEnabled()
&& parentConfiguration.windowConfiguration.getWindowingMode()
@@ -1368,7 +1011,8 @@
@VisibleForTesting
boolean shouldShowLetterboxUi(WindowState mainWindow) {
- if (mIsRelaunchingAfterRequestedOrientationChanged) {
+ if (getAppCompatCapability().getAppCompatOrientationCapability()
+ .getIsRelaunchingAfterRequestedOrientationChanged()) {
return mLastShouldShowLetterboxUi;
}
@@ -1457,7 +1101,7 @@
// corners because we assume the specific layout would. This is the case when the layout
// of the translucent activity uses only a part of all the bounds because of the use of
// LayoutParams.WRAP_CONTENT.
- if (mActivityRecord.mTransparentPolicy.isRunning()
+ if (mActivityRecord.mAppCompatController.getTransparentPolicy().isRunning()
&& (cropBounds.width() != mainWindow.mRequestedWidth
|| cropBounds.height() != mainWindow.mRequestedHeight)) {
return null;
@@ -1528,7 +1172,8 @@
}
boolean getIsRelaunchingAfterRequestedOrientationChanged() {
- return mIsRelaunchingAfterRequestedOrientationChanged;
+ return getAppCompatCapability().getAppCompatOrientationCapability()
+ .getIsRelaunchingAfterRequestedOrientationChanged();
}
private void adjustBoundsForTaskbar(final WindowState mainWindow, final Rect bounds) {
@@ -1713,13 +1358,13 @@
int getLetterboxPositionForLogging() {
int positionToLog = APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__UNKNOWN_POSITION;
if (isHorizontalReachabilityEnabled()) {
- int letterboxPositionForHorizontalReachability = getLetterboxConfiguration()
+ int letterboxPositionForHorizontalReachability = mLetterboxConfiguration
.getLetterboxPositionForHorizontalReachability(
isDisplayFullScreenAndInPosture(/* isTabletop */ false));
positionToLog = letterboxHorizontalReachabilityPositionToLetterboxPosition(
letterboxPositionForHorizontalReachability);
} else if (isVerticalReachabilityEnabled()) {
- int letterboxPositionForVerticalReachability = getLetterboxConfiguration()
+ int letterboxPositionForVerticalReachability = mLetterboxConfiguration
.getLetterboxPositionForVerticalReachability(
isDisplayFullScreenAndInPosture(/* isTabletop */ true));
positionToLog = letterboxVerticalReachabilityPositionToLetterboxPosition(
@@ -1728,10 +1373,6 @@
return positionToLog;
}
- private LetterboxConfiguration getLetterboxConfiguration() {
- return mLetterboxConfiguration;
- }
-
/**
* Logs letterbox position changes via {@link ActivityMetricsLogger#logLetterboxPositionChange}.
*/
@@ -1761,21 +1402,4 @@
w.mAttrs.insetsFlags.appearance
);
}
-
- @NonNull
- private static BooleanSupplier asLazy(@NonNull BooleanSupplier supplier) {
- return new BooleanSupplier() {
- private boolean mRead;
- private boolean mValue;
-
- @Override
- public boolean getAsBoolean() {
- if (!mRead) {
- mRead = true;
- mValue = supplier.getAsBoolean();
- }
- return mValue;
- }
- };
- }
}
diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java
index ab72e3c..7f6499f 100644
--- a/services/core/java/com/android/server/wm/TaskFragment.java
+++ b/services/core/java/com/android/server/wm/TaskFragment.java
@@ -2241,13 +2241,13 @@
static class ConfigOverrideHint {
@Nullable DisplayInfo mTmpOverrideDisplayInfo;
@Nullable ActivityRecord.CompatDisplayInsets mTmpCompatInsets;
- @Nullable Rect mTmpParentAppBoundsOverride;
+ @Nullable Rect mParentAppBoundsOverride;
int mTmpOverrideConfigOrientation;
boolean mUseOverrideInsetsForConfig;
void resolveTmpOverrides(DisplayContent dc, Configuration parentConfig,
boolean isFixedRotationTransforming) {
- mTmpParentAppBoundsOverride = new Rect(parentConfig.windowConfiguration.getAppBounds());
+ mParentAppBoundsOverride = new Rect(parentConfig.windowConfiguration.getAppBounds());
final Insets insets;
if (mUseOverrideInsetsForConfig && dc != null) {
// Insets are decoupled from configuration by default from V+, use legacy
@@ -2269,13 +2269,12 @@
} else {
insets = Insets.NONE;
}
- mTmpParentAppBoundsOverride.inset(insets);
+ mParentAppBoundsOverride.inset(insets);
}
void resetTmpOverrides() {
mTmpOverrideDisplayInfo = null;
mTmpCompatInsets = null;
- mTmpParentAppBoundsOverride = null;
mTmpOverrideConfigOrientation = ORIENTATION_UNDEFINED;
}
}
@@ -2364,7 +2363,7 @@
final Rect containingAppBounds;
if (insideParentBounds) {
containingAppBounds = useOverrideInsetsForConfig
- ? overrideHint.mTmpParentAppBoundsOverride
+ ? overrideHint.mParentAppBoundsOverride
: parentConfig.windowConfiguration.getAppBounds();
} else {
// Restrict appBounds to display non-decor rather than parent because the
diff --git a/services/core/java/com/android/server/wm/TransparentPolicy.java b/services/core/java/com/android/server/wm/TransparentPolicy.java
index b408397..3044abd 100644
--- a/services/core/java/com/android/server/wm/TransparentPolicy.java
+++ b/services/core/java/com/android/server/wm/TransparentPolicy.java
@@ -260,8 +260,9 @@
private void start(@NonNull ActivityRecord firstOpaqueActivity) {
mFirstOpaqueActivity = firstOpaqueActivity;
- mFirstOpaqueActivity.mTransparentPolicy
- .mDestroyListeners.add(mActivityRecord.mTransparentPolicy);
+ mFirstOpaqueActivity.mAppCompatController.getTransparentPolicy()
+ .mDestroyListeners.add(mActivityRecord.mAppCompatController
+ .getTransparentPolicy());
inheritFromOpaque(firstOpaqueActivity);
final WindowContainer<?> parent = mActivityRecord.getParent();
mLetterboxConfigListener = WindowContainer.overrideConfigurationPropagation(
@@ -312,8 +313,9 @@
mInheritedAppCompatState = APP_COMPAT_STATE_CHANGED__STATE__UNKNOWN;
mInheritedCompatDisplayInsets = null;
if (mFirstOpaqueActivity != null) {
- mFirstOpaqueActivity.mTransparentPolicy
- .mDestroyListeners.remove(mActivityRecord.mTransparentPolicy);
+ mFirstOpaqueActivity.mAppCompatController.getTransparentPolicy()
+ .mDestroyListeners.remove(mActivityRecord.mAppCompatController
+ .getTransparentPolicy());
}
mFirstOpaqueActivity = null;
}
diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java
index 022c6ce..d26df7a 100644
--- a/services/core/java/com/android/server/wm/WindowOrganizerController.java
+++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java
@@ -612,10 +612,16 @@
mService.mTaskSupervisor.beginDeferResume();
boolean deferResume = true;
mService.mTaskSupervisor.setDeferRootVisibilityUpdate(true /* deferUpdate */);
- final boolean shouldDeferTransitionReady = transition != null && !t.isEmpty()
- && (transition.isCollecting() || Flags.alwaysDeferTransitionWhenApplyWct());
- if (shouldDeferTransitionReady) {
- transition.deferTransitionReady();
+ boolean deferTransitionReady = false;
+ if (transition != null && !t.isEmpty()) {
+ if (transition.isCollecting()) {
+ deferTransitionReady = true;
+ transition.deferTransitionReady();
+ } else if (Flags.alwaysDeferTransitionWhenApplyWct()) {
+ Slog.w(TAG, "Transition is not collecting when applyTransaction."
+ + " transition=" + transition + " state=" + transition.getState());
+ transition = null;
+ }
}
try {
final ArraySet<WindowContainer<?>> haveConfigChanges = new ArraySet<>();
@@ -771,7 +777,7 @@
mService.mWindowManager.mWindowPlacerLocked.requestTraversal();
}
} finally {
- if (shouldDeferTransitionReady) {
+ if (deferTransitionReady) {
transition.continueTransitionReady();
}
mService.mTaskSupervisor.setDeferRootVisibilityUpdate(false /* deferUpdate */);
diff --git a/services/core/lint-baseline.xml b/services/core/lint-baseline.xml
index 2ccd1e4..3b81f0a 100644
--- a/services/core/lint-baseline.xml
+++ b/services/core/lint-baseline.xml
@@ -145,4 +145,37 @@
line="7158"/>
</issue>
+ <issue
+ id="FlaggedApi"
+ message="Method `recordSmartReplied()` is a flagged API and should be inside an `if (Flags.lifetimeExtensionRefactor())` check (or annotate the surrounding method `onNotificationSmartReplySent` with `@FlaggedApi(Flags.FLAG_LIFETIME_EXTENSION_REFACTOR) to transfer requirement to caller`)"
+ errorLine1=" r.recordSmartReplied();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/services/core/java/com/android/server/notification/NotificationManagerService.java"
+ line="1591"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getPackageImportanceWithIdentity()` is a flagged API and should be inside an `if (Flags.lifetimeExtensionRefactor())` check (or annotate the surrounding method `enqueueNotificationInternal` with `@FlaggedApi(Flags.FLAG_LIFETIME_EXTENSION_REFACTOR) to transfer requirement to caller`)"
+ errorLine1=" final int packageImportance = getPackageImportanceWithIdentity(pkg);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/services/core/java/com/android/server/notification/NotificationManagerService.java"
+ line="7546"
+ column="39"/>
+ </issue>
+
+ <issue
+ id="FlaggedApi"
+ message="Method `getPackageImportanceWithIdentity()` is a flagged API and should be inside an `if (Flags.lifetimeExtensionRefactor())` check (or annotate the surrounding method `onShortcutRemoved` with `@FlaggedApi(Flags.FLAG_LIFETIME_EXTENSION_REFACTOR) to transfer requirement to caller`)"
+ errorLine1=" final int packageImportance = getPackageImportanceWithIdentity(packageName);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/services/core/java/com/android/server/notification/NotificationManagerService.java"
+ line="7916"
+ column="51"/>
+ </issue>
+
</issues>
\ No newline at end of file
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/ApplicationExitInfoTest.java b/services/tests/mockingservicestests/src/com/android/server/am/ApplicationExitInfoTest.java
index e15942b..adcbf5c 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/ApplicationExitInfoTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/ApplicationExitInfoTest.java
@@ -84,7 +84,11 @@
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
import java.util.Random;
+import java.util.function.Function;
import java.util.zip.GZIPInputStream;
/**
@@ -940,6 +944,228 @@
}
}
+ private ApplicationExitInfo createExitInfo(int i) {
+ ApplicationExitInfo info = new ApplicationExitInfo();
+ info.setPid(i);
+ info.setTimestamp(1000 + i);
+ info.setPackageUid(2000);
+ return info;
+ }
+
+ @SuppressWarnings("GuardedBy")
+ private ArrayList<ApplicationExitInfo> getExitInfosHelper(
+ AppExitInfoTracker.AppExitInfoContainer container, int filterPid, int maxNum) {
+ ArrayList<ApplicationExitInfo> infos = new ArrayList<ApplicationExitInfo>();
+ container.getExitInfosLocked(filterPid, maxNum, infos);
+ return infos;
+ }
+
+ @SuppressWarnings("GuardedBy")
+ private void checkAreHelper(AppExitInfoTracker.AppExitInfoContainer container, int filterPid,
+ int maxNum, List<Integer> expected, Function<ApplicationExitInfo, Integer> func) {
+ ArrayList<Integer> values = new ArrayList<Integer>();
+ getExitInfosHelper(container, filterPid, maxNum)
+ .forEach((exitInfo) -> values.add(func.apply(exitInfo)));
+ assertEquals(values, expected);
+
+ HashMap<Integer, Integer> expectedMultiset = new HashMap<Integer, Integer>();
+ expected.forEach(
+ (elem) -> expectedMultiset.put(elem, expectedMultiset.getOrDefault(elem, 0) + 1));
+ // `maxNum` isn't a parameter supported by `forEachRecordLocked()s`, but we can emulate it
+ // by stopping iteration when we've seen enough elements.
+ int[] numElementsToObserveWrapped = {maxNum};
+ container.forEachRecordLocked((exitInfo) -> {
+ // Same thing as above, `filterPid` isn't a parameter supported out of the box for
+ // `forEachRecordLocked()`, but we emulate it here.
+ if (filterPid > 0 && filterPid != exitInfo.getPid()) {
+ return AppExitInfoTracker.FOREACH_ACTION_NONE;
+ }
+
+ Integer key = func.apply(exitInfo);
+ assertTrue(expectedMultiset.toString(), expectedMultiset.containsKey(key));
+ Integer references = expectedMultiset.get(key);
+ if (references == 1) {
+ expectedMultiset.remove(key);
+ } else {
+ expectedMultiset.put(key, references - 1);
+ }
+ if (--numElementsToObserveWrapped[0] == 0) {
+ return AppExitInfoTracker.FOREACH_ACTION_STOP_ITERATION;
+ }
+ return AppExitInfoTracker.FOREACH_ACTION_NONE;
+ });
+ assertEquals(expectedMultiset.size(), 0);
+ }
+
+ private void checkPidsAre(AppExitInfoTracker.AppExitInfoContainer container, int filterPid,
+ int maxNum, List<Integer> expectedPids) {
+ checkAreHelper(container, filterPid, maxNum, expectedPids, (exitInfo) -> exitInfo.getPid());
+ }
+
+ private void checkPidsAre(
+ AppExitInfoTracker.AppExitInfoContainer container, List<Integer> expectedPids) {
+ checkPidsAre(container, 0, 0, expectedPids);
+ }
+
+ private void checkTimestampsAre(AppExitInfoTracker.AppExitInfoContainer container,
+ int filterPid, int maxNum, List<Integer> expectedTimestamps) {
+ checkAreHelper(container, filterPid, maxNum, expectedTimestamps,
+ (exitInfo) -> (int) exitInfo.getTimestamp());
+ }
+
+ private void checkTimestampsAre(
+ AppExitInfoTracker.AppExitInfoContainer container, List<Integer> expectedTimestamps) {
+ checkTimestampsAre(container, 0, 0, expectedTimestamps);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ private AppExitInfoTracker.AppExitInfoContainer createBasicContainer() {
+ AppExitInfoTracker.AppExitInfoContainer container =
+ mAppExitInfoTracker.new AppExitInfoContainer(3);
+ container.addExitInfoLocked(createExitInfo(10));
+ container.addExitInfoLocked(createExitInfo(30));
+ container.addExitInfoLocked(createExitInfo(20));
+ return container;
+ }
+
+ @Test
+ @SuppressWarnings("GuardedBy")
+ public void testContainerGetExitInfosIsSortedNewestFirst() throws Exception {
+ AppExitInfoTracker.AppExitInfoContainer container = createBasicContainer();
+ checkPidsAre(container, Arrays.asList(30, 20, 10));
+ }
+
+ @Test
+ @SuppressWarnings("GuardedBy")
+ public void testContainerRemovesOldestReports() throws Exception {
+ AppExitInfoTracker.AppExitInfoContainer container = createBasicContainer();
+ container.addExitInfoLocked(createExitInfo(40));
+ checkPidsAre(container, Arrays.asList(40, 30, 20));
+
+ container.addExitInfoLocked(createExitInfo(50));
+ checkPidsAre(container, Arrays.asList(50, 40, 30));
+
+ container.addExitInfoLocked(createExitInfo(45));
+ checkPidsAre(container, Arrays.asList(50, 45, 40));
+
+ // Adding an older report shouldn't remove the newer ones.
+ container.addExitInfoLocked(createExitInfo(15));
+ checkPidsAre(container, Arrays.asList(50, 45, 40));
+ }
+
+ @Test
+ @SuppressWarnings("GuardedBy")
+ public void testContainerFilterByPid() throws Exception {
+ AppExitInfoTracker.AppExitInfoContainer container = createBasicContainer();
+ assertEquals(1, getExitInfosHelper(container, 30, 0).size());
+ assertEquals(30, getExitInfosHelper(container, 0, 0).get(0).getPid());
+
+ assertEquals(1, getExitInfosHelper(container, 30, 0).size());
+ assertEquals(20, getExitInfosHelper(container, 20, 0).get(0).getPid());
+
+ assertEquals(1, getExitInfosHelper(container, 10, 0).size());
+ assertEquals(10, getExitInfosHelper(container, 10, 0).get(0).getPid());
+
+ assertEquals(0, getExitInfosHelper(container, 1337, 0).size());
+ }
+
+ @Test
+ @SuppressWarnings("GuardedBy")
+ public void testContainerLimitQuantityOfResults() throws Exception {
+ AppExitInfoTracker.AppExitInfoContainer container = createBasicContainer();
+ checkPidsAre(container, /* filterPid */ 30, /* maxNum */ 1, Arrays.asList(30));
+ checkPidsAre(container, /* filterPid */ 30, /* maxNum */ 1000, Arrays.asList(30));
+
+ checkPidsAre(container, /* filterPid */ 20, /* maxNum */ 1, Arrays.asList(20));
+ checkPidsAre(container, /* filterPid */ 20, /* maxNum */ 1000, Arrays.asList(20));
+
+ checkPidsAre(container, /* filterPid */ 10, /* maxNum */ 1, Arrays.asList(10));
+ checkPidsAre(container, /* filterPid */ 10, /* maxNum */ 1000, Arrays.asList(10));
+
+ checkPidsAre(container, /* filterPid */ 1337, /* maxNum */ 1, Arrays.asList());
+ checkPidsAre(container, /* filterPid */ 1337, /* maxNum */ 1000, Arrays.asList());
+ }
+
+ @Test
+ @SuppressWarnings("GuardedBy")
+ public void testContainerLastExitInfoForPid() throws Exception {
+ AppExitInfoTracker.AppExitInfoContainer container = createBasicContainer();
+ assertEquals(30, container.getLastExitInfoForPid(30).getPid());
+ assertEquals(20, container.getLastExitInfoForPid(20).getPid());
+ assertEquals(10, container.getLastExitInfoForPid(10).getPid());
+ assertEquals(null, container.getLastExitInfoForPid(1337));
+ }
+
+ @Test
+ @SuppressWarnings("GuardedBy")
+ public void testContainerCanHoldMultipleFromSamePid() throws Exception {
+ AppExitInfoTracker.AppExitInfoContainer container = createBasicContainer();
+ ApplicationExitInfo info = createExitInfo(100);
+ ApplicationExitInfo info2 = createExitInfo(100);
+ ApplicationExitInfo info3 = createExitInfo(100);
+ info2.setTimestamp(1337);
+ info3.setTimestamp(31337);
+
+ container.addExitInfoLocked(info);
+ assertEquals(1100, container.getLastExitInfoForPid(100).getTimestamp());
+ container.addExitInfoLocked(info2);
+ assertEquals(1337, container.getLastExitInfoForPid(100).getTimestamp());
+ container.addExitInfoLocked(info3);
+ assertEquals(31337, container.getLastExitInfoForPid(100).getTimestamp());
+
+ checkPidsAre(container, Arrays.asList(100, 100, 100));
+ checkTimestampsAre(container, Arrays.asList(31337, 1337, 1100));
+
+ checkPidsAre(container, /* filterPid */ 100, /* maxNum */ 0, Arrays.asList(100, 100, 100));
+ checkTimestampsAre(
+ container, /* filterPid */ 100, /* maxNum */ 0, Arrays.asList(31337, 1337, 1100));
+
+ checkPidsAre(container, /* filterPid */ 100, /* maxNum */ 2, Arrays.asList(100, 100));
+ checkTimestampsAre(
+ container, /* filterPid */ 100, /* maxNum */ 2, Arrays.asList(31337, 1337));
+ }
+
+ @Test
+ @SuppressWarnings("GuardedBy")
+ public void testContainerIteration() throws Exception {
+ AppExitInfoTracker.AppExitInfoContainer container = createBasicContainer();
+ checkPidsAre(container, Arrays.asList(30, 20, 10));
+
+ // Unfortunately relying on order for this test, which is implemented as "last inserted" ->
+ // "first inserted". Note that this is insertion order, not timestamp. Thus, it's 20 -> 30
+ // -> 10, as defined by `createBasicContainer()`.
+ List<Integer> elements = Arrays.asList(20, 30, 10);
+ for (int i = 0, size = elements.size(); i < size; i++) {
+ ArrayList<Integer> processedEntries = new ArrayList<Integer>();
+ final int finalIndex = i;
+ container.forEachRecordLocked((exitInfo) -> {
+ processedEntries.add(new Integer(exitInfo.getPid()));
+ if (exitInfo.getPid() == elements.get(finalIndex)) {
+ return AppExitInfoTracker.FOREACH_ACTION_STOP_ITERATION;
+ }
+ return AppExitInfoTracker.FOREACH_ACTION_NONE;
+ });
+ assertEquals(processedEntries, elements.subList(0, i + 1));
+ }
+ }
+
+ @Test
+ @SuppressWarnings("GuardedBy")
+ public void testContainerIterationRemove() throws Exception {
+ for (int pidToRemove : Arrays.asList(30, 20, 10)) {
+ AppExitInfoTracker.AppExitInfoContainer container = createBasicContainer();
+ container.forEachRecordLocked((exitInfo) -> {
+ if (exitInfo.getPid() == pidToRemove) {
+ return AppExitInfoTracker.FOREACH_ACTION_REMOVE_ITEM;
+ }
+ return AppExitInfoTracker.FOREACH_ACTION_NONE;
+ });
+ ArrayList<Integer> pidsRemaining = new ArrayList<Integer>(Arrays.asList(30, 20, 10));
+ pidsRemaining.remove(new Integer(pidToRemove));
+ checkPidsAre(container, pidsRemaining);
+ }
+ }
+
private static int makeExitStatus(int exitCode) {
return (exitCode << 8) & 0xff00;
}
diff --git a/services/tests/powerservicetests/src/com/android/server/power/ShutdownThreadTest.java b/services/tests/powerservicetests/src/com/android/server/power/ShutdownThreadTest.java
index 62075b8..ab1b0cc 100644
--- a/services/tests/powerservicetests/src/com/android/server/power/ShutdownThreadTest.java
+++ b/services/tests/powerservicetests/src/com/android/server/power/ShutdownThreadTest.java
@@ -17,11 +17,10 @@
package com.android.server.power;
import static com.android.server.power.ShutdownThread.DEFAULT_SHUTDOWN_VIBRATE_MS;
+
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -42,7 +41,6 @@
import java.io.File;
import java.io.FileOutputStream;
-import java.io.IOException;
/**
* Tests for {@link com.android.server.power.ShutdownThread}
@@ -88,6 +86,7 @@
@Mock private VibratorInfo mVibratorInfoMock;
private String mDefaultShutdownVibrationFilePath;
+ private boolean mShutdownVibrationDisabled;
private long mLastSleepDurationMs;
private ShutdownThread mShutdownThread;
@@ -168,6 +167,17 @@
.vibrate(any(VibrationEffect.class), any(VibrationAttributes.class));
}
+ @Test
+ public void testVibrationDisabled() throws Exception {
+ setShutdownVibrationFileContent(CLICK_VIB_SERIALIZATION);
+ mShutdownVibrationDisabled = true;
+
+ mShutdownThread.playShutdownVibration(mContextMock);
+
+ verify(mVibratorMock, never())
+ .vibrate(any(VibrationEffect.class), any(VibrationAttributes.class));
+ }
+
private void assertShutdownVibration(VibrationEffect effect, long vibrationSleepDuration)
throws Exception {
verify(mVibratorMock).vibrate(
@@ -214,5 +224,10 @@
public void sleep(long durationMs) {
mLastSleepDurationMs = durationMs;
}
+
+ @Override
+ public boolean isShutdownVibrationDisabled(Context context) {
+ return mShutdownVibrationDisabled;
+ }
}
}
diff --git a/services/tests/servicestests/src/com/android/server/appwidget/AppWidgetServiceImplTest.java b/services/tests/servicestests/src/com/android/server/appwidget/AppWidgetServiceImplTest.java
index 8a7815e..c34e28f 100644
--- a/services/tests/servicestests/src/com/android/server/appwidget/AppWidgetServiceImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/appwidget/AppWidgetServiceImplTest.java
@@ -47,7 +47,9 @@
import android.os.Handler;
import android.os.UserHandle;
import android.test.InstrumentationTestCase;
+import android.util.ArraySet;
import android.util.AtomicFile;
+import android.util.SparseArray;
import android.util.Xml;
import android.widget.RemoteViews;
@@ -67,10 +69,12 @@
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
+import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.Random;
+import java.util.Set;
import java.util.concurrent.CountDownLatch;
/**
@@ -388,6 +392,93 @@
assertThat(target.previewLayout).isEqualTo(original.previewLayout);
}
+ public void testBackupRestoreControllerStatePersistence() throws IOException {
+ // Setup mock data
+ final Set<String> mockPrunedApps = getMockPrunedApps();
+ final SparseArray<
+ List<AppWidgetServiceImpl.BackupRestoreController.RestoreUpdateRecord>
+ > mockUpdatesByProvider = getMockUpdates();
+ final SparseArray<
+ List<AppWidgetServiceImpl.BackupRestoreController.RestoreUpdateRecord>
+ > mockUpdatesByHost = getMockUpdates();
+ final AppWidgetServiceImpl.BackupRestoreController.State state =
+ new AppWidgetServiceImpl.BackupRestoreController.State(
+ mockPrunedApps, mockUpdatesByProvider, mockUpdatesByHost);
+
+ final File file = new File(mTestContext.getDataDir(), "state.xml");
+ saveBackupRestoreControllerState(file, state);
+ final AppWidgetServiceImpl.BackupRestoreController.State target =
+ loadStateLocked(file);
+ assertNotNull(target);
+ final SparseArray<List<AppWidgetServiceImpl.BackupRestoreController.RestoreUpdateRecord>>
+ actualUpdatesByProvider = target.getUpdatesByProvider();
+ assertNotNull(actualUpdatesByProvider);
+ final SparseArray<List<AppWidgetServiceImpl.BackupRestoreController.RestoreUpdateRecord>>
+ actualUpdatesByHost = target.getUpdatesByHost();
+ assertNotNull(actualUpdatesByHost);
+
+ assertEquals(mockPrunedApps, target.getPrunedApps());
+ for (int i = 0; i < mockUpdatesByProvider.size(); i++) {
+ final int key = mockUpdatesByProvider.keyAt(i);
+ verifyRestoreUpdateRecord(
+ actualUpdatesByProvider.get(key), mockUpdatesByProvider.get(key));
+ }
+ for (int i = 0; i < mockUpdatesByHost.size(); i++) {
+ final int key = mockUpdatesByHost.keyAt(i);
+ verifyRestoreUpdateRecord(
+ actualUpdatesByHost.get(key), mockUpdatesByHost.get(key));
+ }
+ }
+
+ private void verifyRestoreUpdateRecord(
+ @NonNull final List<AppWidgetServiceImpl.BackupRestoreController.RestoreUpdateRecord>
+ actualUpdates,
+ @NonNull final List<AppWidgetServiceImpl.BackupRestoreController.RestoreUpdateRecord>
+ expectedUpdates) {
+ assertEquals(expectedUpdates.size(), actualUpdates.size());
+ for (int i = 0; i < expectedUpdates.size(); i++) {
+ final AppWidgetServiceImpl.BackupRestoreController.RestoreUpdateRecord expected =
+ expectedUpdates.get(i);
+ final AppWidgetServiceImpl.BackupRestoreController.RestoreUpdateRecord actual =
+ actualUpdates.get(i);
+ assertEquals(expected.oldId, actual.oldId);
+ assertEquals(expected.newId, actual.newId);
+ assertEquals(expected.notified, actual.notified);
+ }
+ }
+
+ @NonNull
+ private static Set<String> getMockPrunedApps() {
+ final Set<String> mockPrunedApps = new ArraySet<>(10);
+ for (int i = 0; i < 10; i++) {
+ mockPrunedApps.add("com.example.app" + i);
+ }
+ return mockPrunedApps;
+ }
+
+ @NonNull
+ private static SparseArray<
+ List<AppWidgetServiceImpl.BackupRestoreController.RestoreUpdateRecord>
+ > getMockUpdates() {
+ final SparseArray<List<
+ AppWidgetServiceImpl.BackupRestoreController.RestoreUpdateRecord>> ret =
+ new SparseArray<>(4);
+ ret.put(0, new ArrayList<>());
+ for (int i = 0; i < 5; i++) {
+ final AppWidgetServiceImpl.BackupRestoreController.RestoreUpdateRecord record =
+ new AppWidgetServiceImpl.BackupRestoreController.RestoreUpdateRecord(
+ 5 - i, i);
+ record.notified = (i % 2 == 1);
+ final int key = (i < 3) ? 1 : 2;
+ if (!ret.contains(key)) {
+ ret.put(key, new ArrayList<>());
+ }
+ ret.get(key).add(record);
+ }
+ ret.put(3, new ArrayList<>());
+ return ret;
+ }
+
private int setupHostAndWidget() {
List<PendingHostUpdate> updates = mService.startListening(
mMockHost, mPkgName, HOST_ID, new int[0]).getList();
@@ -418,6 +509,40 @@
return mTestContext.getResources().getInteger(resId);
}
+ private static void saveBackupRestoreControllerState(
+ @NonNull final File dst,
+ @Nullable final AppWidgetServiceImpl.BackupRestoreController.State state)
+ throws IOException {
+ Objects.requireNonNull(dst);
+ if (state == null) {
+ return;
+ }
+ final AtomicFile file = new AtomicFile(dst);
+ final FileOutputStream stream = file.startWrite();
+ final TypedXmlSerializer out = Xml.resolveSerializer(stream);
+ out.startDocument(null, true);
+ AppWidgetXmlUtil.writeBackupRestoreControllerState(out, state);
+ out.endDocument();
+ file.finishWrite(stream);
+ }
+
+ private static AppWidgetServiceImpl.BackupRestoreController.State loadStateLocked(
+ @NonNull final File dst) {
+ Objects.requireNonNull(dst);
+ final AtomicFile file = new AtomicFile(dst);
+ try (FileInputStream stream = file.openRead()) {
+ final TypedXmlPullParser parser = Xml.resolvePullParser(stream);
+ int type;
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+ && type != XmlPullParser.START_TAG) {
+ // drain whitespace, comments, etc.
+ }
+ return AppWidgetXmlUtil.readBackupRestoreControllerState(parser);
+ } catch (IOException | XmlPullParserException e) {
+ return null;
+ }
+ }
+
private static void saveWidgetProviderInfoLocked(@NonNull final File dst,
@Nullable final AppWidgetProviderInfo info)
throws IOException {
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java b/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java
index 503ab8e..0f38532 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java
@@ -79,6 +79,9 @@
import android.os.RemoteException;
import android.os.UserManager;
import android.platform.test.annotations.Presubmit;
+import android.platform.test.annotations.RequiresFlagsEnabled;
+import android.platform.test.flag.junit.CheckFlagsRule;
+import android.platform.test.flag.junit.DeviceFlagsValueProvider;
import android.platform.test.flag.junit.SetFlagsRule;
import android.security.GateKeeper;
import android.security.KeyStoreAuthorization;
@@ -118,6 +121,8 @@
@Rule
public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+ @Rule
+ public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
private static final String TEST_PACKAGE_NAME = "test_package";
private static final long TEST_REQUEST_ID = 44;
@@ -1506,6 +1511,75 @@
}
@Test
+ @RequiresFlagsEnabled(Flags.FLAG_MANDATORY_BIOMETRICS)
+ public void testCanAuthenticate_whenMandatoryBiometricsRequested()
+ throws Exception {
+ mBiometricService = new BiometricService(mContext, mInjector, mBiometricHandlerProvider);
+ mBiometricService.onStart();
+
+ when(mTrustManager.isInSignificantPlace()).thenReturn(false);
+ when(mBiometricService.mSettingObserver.getMandatoryBiometricsEnabledForUser(anyInt()))
+ .thenReturn(true);
+
+ setupAuthForOnly(TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG);
+
+ assertEquals(BiometricManager.BIOMETRIC_SUCCESS,
+ invokeCanAuthenticate(mBiometricService, Authenticators.MANDATORY_BIOMETRICS));
+
+ when(mTrustManager.isInSignificantPlace()).thenReturn(true);
+
+ assertEquals(BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE,
+ invokeCanAuthenticate(mBiometricService, Authenticators.MANDATORY_BIOMETRICS));
+ }
+
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_MANDATORY_BIOMETRICS)
+ public void testCanAuthenticate_whenMandatoryBiometricsAndStrongAuthenticatorsRequested()
+ throws Exception {
+ mBiometricService = new BiometricService(mContext, mInjector, mBiometricHandlerProvider);
+ mBiometricService.onStart();
+
+ when(mTrustManager.isInSignificantPlace()).thenReturn(false);
+ when(mBiometricService.mSettingObserver.getMandatoryBiometricsEnabledForUser(anyInt()))
+ .thenReturn(true);
+
+ setupAuthForOnly(TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG);
+
+ assertEquals(BiometricManager.BIOMETRIC_SUCCESS,
+ invokeCanAuthenticate(mBiometricService, Authenticators.MANDATORY_BIOMETRICS
+ | Authenticators.BIOMETRIC_STRONG));
+
+ when(mTrustManager.isInSignificantPlace()).thenReturn(true);
+
+ assertEquals(BiometricManager.BIOMETRIC_SUCCESS,
+ invokeCanAuthenticate(mBiometricService, Authenticators.MANDATORY_BIOMETRICS
+ | Authenticators.BIOMETRIC_STRONG));
+ }
+
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_MANDATORY_BIOMETRICS)
+ public void testCanAuthenticate_whenMandatoryBiometricsRequestedAndDeviceCredentialAvailable()
+ throws Exception {
+ mBiometricService = new BiometricService(mContext, mInjector, mBiometricHandlerProvider);
+ mBiometricService.onStart();
+
+ when(mTrustManager.isInSignificantPlace()).thenReturn(false);
+ when(mBiometricService.mSettingObserver.getMandatoryBiometricsEnabledForUser(anyInt()))
+ .thenReturn(true);
+
+ setupAuthForOnly(TYPE_CREDENTIAL, Authenticators.DEVICE_CREDENTIAL);
+
+ assertEquals(BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE,
+ invokeCanAuthenticate(mBiometricService, Authenticators.MANDATORY_BIOMETRICS));
+
+ when(mTrustManager.isInSignificantPlace()).thenReturn(true);
+
+ assertEquals(BiometricManager.BIOMETRIC_SUCCESS,
+ invokeCanAuthenticate(mBiometricService, Authenticators.MANDATORY_BIOMETRICS
+ | Authenticators.DEVICE_CREDENTIAL));
+ }
+
+ @Test
public void testAuthenticatorActualStrength() {
// Tuple of OEM config, updatedStrength, and expectedStrength
final int[][] testCases = {
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/PreAuthInfoTest.java b/services/tests/servicestests/src/com/android/server/biometrics/PreAuthInfoTest.java
index b40d7ee..b831ef5 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/PreAuthInfoTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/PreAuthInfoTest.java
@@ -32,11 +32,16 @@
import android.app.admin.DevicePolicyManager;
import android.app.trust.ITrustManager;
import android.content.Context;
+import android.content.res.Resources;
import android.hardware.biometrics.BiometricManager;
+import android.hardware.biometrics.Flags;
import android.hardware.biometrics.IBiometricAuthenticator;
import android.hardware.biometrics.PromptInfo;
import android.os.RemoteException;
import android.platform.test.annotations.Presubmit;
+import android.platform.test.annotations.RequiresFlagsEnabled;
+import android.platform.test.flag.junit.CheckFlagsRule;
+import android.platform.test.flag.junit.DeviceFlagsValueProvider;
import androidx.test.filters.SmallTest;
@@ -54,6 +59,9 @@
public class PreAuthInfoTest {
@Rule
public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+ @Rule
+ public final CheckFlagsRule mCheckFlagsRule =
+ DeviceFlagsValueProvider.createCheckFlagsRule();
private static final int SENSOR_ID_FINGERPRINT = 0;
private static final int SENSOR_ID_FACE = 1;
@@ -66,6 +74,8 @@
@Mock
Context mContext;
@Mock
+ Resources mResources;
+ @Mock
ITrustManager mTrustManager;
@Mock
DevicePolicyManager mDevicePolicyManager;
@@ -80,6 +90,7 @@
when(mDevicePolicyManager.getKeyguardDisabledFeatures(any(), anyInt()))
.thenReturn(KEYGUARD_DISABLE_FEATURES_NONE);
when(mSettingObserver.getEnabledForApps(anyInt())).thenReturn(true);
+ when(mSettingObserver.getMandatoryBiometricsEnabledForUser(anyInt())).thenReturn(true);
when(mFaceAuthenticator.hasEnrolledTemplates(anyInt(), any())).thenReturn(true);
when(mFaceAuthenticator.isHardwareDetected(any())).thenReturn(true);
when(mFaceAuthenticator.getLockoutModeForUser(anyInt()))
@@ -91,6 +102,8 @@
.thenReturn(LOCKOUT_NONE);
when(mBiometricCameraManager.isCameraPrivacyEnabled()).thenReturn(false);
when(mBiometricCameraManager.isAnyCameraUnavailable()).thenReturn(false);
+ when(mContext.getResources()).thenReturn(mResources);
+ when(mResources.getString(anyInt())).thenReturn(TEST_PACKAGE_NAME);
}
@Test
@@ -184,6 +197,54 @@
assertThat(preAuthInfo.eligibleSensors.get(0).modality).isEqualTo(TYPE_FINGERPRINT);
}
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_MANDATORY_BIOMETRICS)
+ public void testMandatoryBiometricsStatus_whenAllRequirementsSatisfiedAndSensorAvailable()
+ throws Exception {
+ when(mTrustManager.isInSignificantPlace()).thenReturn(false);
+
+ final BiometricSensor sensor = getFaceSensor();
+ final PromptInfo promptInfo = new PromptInfo();
+ promptInfo.setAuthenticators(BiometricManager.Authenticators.MANDATORY_BIOMETRICS);
+ final PreAuthInfo preAuthInfo = PreAuthInfo.create(mTrustManager, mDevicePolicyManager,
+ mSettingObserver, List.of(sensor), 0 /* userId */, promptInfo, TEST_PACKAGE_NAME,
+ false /* checkDevicePolicyManager */, mContext, mBiometricCameraManager);
+
+ assertThat(preAuthInfo.eligibleSensors).hasSize(1);
+ }
+
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_MANDATORY_BIOMETRICS)
+ public void testMandatoryBiometricsStatus_whenAllRequirementsSatisfiedAndSensorUnavailable()
+ throws Exception {
+ when(mTrustManager.isInSignificantPlace()).thenReturn(false);
+
+ final PromptInfo promptInfo = new PromptInfo();
+ promptInfo.setAuthenticators(BiometricManager.Authenticators.MANDATORY_BIOMETRICS);
+ final PreAuthInfo preAuthInfo = PreAuthInfo.create(mTrustManager, mDevicePolicyManager,
+ mSettingObserver, List.of(), 0 /* userId */, promptInfo, TEST_PACKAGE_NAME,
+ false /* checkDevicePolicyManager */, mContext, mBiometricCameraManager);
+
+ assertThat(preAuthInfo.eligibleSensors).hasSize(0);
+ }
+
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_MANDATORY_BIOMETRICS)
+ public void testMandatoryBiometricsStatus_whenRequirementsNotSatisfiedAndSensorAvailable()
+ throws Exception {
+ when(mTrustManager.isInSignificantPlace()).thenReturn(true);
+
+ final BiometricSensor sensor = getFaceSensor();
+ final PromptInfo promptInfo = new PromptInfo();
+ promptInfo.setAuthenticators(BiometricManager.Authenticators.MANDATORY_BIOMETRICS
+ | BiometricManager.Authenticators.BIOMETRIC_STRONG);
+ final PreAuthInfo preAuthInfo = PreAuthInfo.create(mTrustManager, mDevicePolicyManager,
+ mSettingObserver, List.of(sensor), 0 /* userId */, promptInfo, TEST_PACKAGE_NAME,
+ false /* checkDevicePolicyManager */, mContext, mBiometricCameraManager);
+
+ assertThat(preAuthInfo.eligibleSensors).hasSize(1);
+ }
+
private BiometricSensor getFingerprintSensor() {
BiometricSensor sensor = new BiometricSensor(mContext, SENSOR_ID_FINGERPRINT,
TYPE_FINGERPRINT, BiometricManager.Authenticators.BIOMETRIC_STRONG,
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/UtilsTest.java b/services/tests/servicestests/src/com/android/server/biometrics/UtilsTest.java
index b05a819..cb75e1a 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/UtilsTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/UtilsTest.java
@@ -179,7 +179,8 @@
// The rest of the bits are not allowed to integrate with the public APIs
for (int i = 8; i < 32; i++) {
final int authenticator = 1 << i;
- if (authenticator == Authenticators.DEVICE_CREDENTIAL) {
+ if (authenticator == Authenticators.DEVICE_CREDENTIAL
+ || authenticator == Authenticators.MANDATORY_BIOMETRICS) {
continue;
}
assertFalse(Utils.isValidAuthenticatorConfig(1 << i));
diff --git a/services/tests/servicestests/src/com/android/server/compat/ApplicationInfoBuilder.java b/services/tests/servicestests/src/com/android/server/compat/ApplicationInfoBuilder.java
index c165c66..d8fd266a 100644
--- a/services/tests/servicestests/src/com/android/server/compat/ApplicationInfoBuilder.java
+++ b/services/tests/servicestests/src/com/android/server/compat/ApplicationInfoBuilder.java
@@ -21,8 +21,10 @@
class ApplicationInfoBuilder {
private boolean mIsDebuggable;
private int mTargetSdk;
+ private int mUid;
private String mPackageName;
private long mVersionCode;
+ private boolean mIsSystemApp;
private ApplicationInfoBuilder() {
mTargetSdk = -1;
@@ -42,6 +44,16 @@
return this;
}
+ ApplicationInfoBuilder systemApp() {
+ mIsSystemApp = true;
+ return this;
+ }
+
+ ApplicationInfoBuilder withUid(int uid) {
+ mUid = uid;
+ return this;
+ }
+
ApplicationInfoBuilder withPackageName(String packageName) {
mPackageName = packageName;
return this;
@@ -60,6 +72,10 @@
applicationInfo.packageName = mPackageName;
applicationInfo.targetSdkVersion = mTargetSdk;
applicationInfo.longVersionCode = mVersionCode;
+ applicationInfo.uid = mUid;
+ if (mIsSystemApp) {
+ applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
+ }
return applicationInfo;
}
}
diff --git a/services/tests/servicestests/src/com/android/server/compat/PlatformCompatTest.java b/services/tests/servicestests/src/com/android/server/compat/PlatformCompatTest.java
index 9accd49..9df7a36 100644
--- a/services/tests/servicestests/src/com/android/server/compat/PlatformCompatTest.java
+++ b/services/tests/servicestests/src/com/android/server/compat/PlatformCompatTest.java
@@ -29,6 +29,7 @@
import android.compat.Compatibility.ChangeConfig;
import android.content.Context;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
import android.os.Build;
@@ -36,6 +37,7 @@
import androidx.test.runner.AndroidJUnit4;
import com.android.internal.compat.AndroidBuildClassifier;
+import com.android.internal.compat.ChangeReporter;
import com.android.internal.compat.CompatibilityChangeConfig;
import com.android.internal.compat.CompatibilityChangeInfo;
import com.android.server.LocalServices;
@@ -65,6 +67,8 @@
CompatConfig mCompatConfig;
@Mock
private AndroidBuildClassifier mBuildClassifier;
+ @Mock
+ private ChangeReporter mChangeReporter;
@Before
public void setUp() throws Exception {
@@ -78,7 +82,8 @@
when(mPackageManager.getApplicationInfo(eq(PACKAGE_NAME), anyInt()))
.thenThrow(new PackageManager.NameNotFoundException());
mCompatConfig = new CompatConfig(mBuildClassifier, mContext);
- mPlatformCompat = new PlatformCompat(mContext, mCompatConfig, mBuildClassifier);
+ mPlatformCompat =
+ new PlatformCompat(mContext, mCompatConfig, mBuildClassifier, mChangeReporter);
// Assume userdebug/eng non-final build
mCompatConfig.forceNonDebuggableFinalForTest(false);
when(mBuildClassifier.isDebuggableBuild()).thenReturn(true);
@@ -100,7 +105,8 @@
.addLoggingOnlyChangeWithId(7L)
.addDisabledOverridableChangeWithId(8L)
.build();
- mPlatformCompat = new PlatformCompat(mContext, mCompatConfig, mBuildClassifier);
+ mPlatformCompat =
+ new PlatformCompat(mContext, mCompatConfig, mBuildClassifier, mChangeReporter);
assertThat(mPlatformCompat.listAllChanges()).asList().containsExactly(
new CompatibilityChangeInfo(1L, "", -1, -1, false, false, "", false),
new CompatibilityChangeInfo(2L, "change2", -1, -1, true, false, "", false),
@@ -128,7 +134,8 @@
.addLoggingOnlyChangeWithId(7L)
.addEnableSinceSdkChangeWithId(31, 8L)
.build();
- mPlatformCompat = new PlatformCompat(mContext, mCompatConfig, mBuildClassifier);
+ mPlatformCompat =
+ new PlatformCompat(mContext, mCompatConfig, mBuildClassifier, mChangeReporter);
assertThat(mPlatformCompat.listUIChanges()).asList().containsExactly(
new CompatibilityChangeInfo(1L, "", -1, -1, false, false, "", false),
new CompatibilityChangeInfo(2L, "change2", -1, -1, true, false, "", false),
@@ -146,7 +153,8 @@
.addEnableAfterSdkChangeWithId(Build.VERSION_CODES.O, 3L)
.build();
mCompatConfig.forceNonDebuggableFinalForTest(true);
- mPlatformCompat = new PlatformCompat(mContext, mCompatConfig, mBuildClassifier);
+ mPlatformCompat =
+ new PlatformCompat(mContext, mCompatConfig, mBuildClassifier, mChangeReporter);
// Before adding overrides.
assertThat(mPlatformCompat.isChangeEnabledByPackageName(1, PACKAGE_NAME, 0)).isTrue();
@@ -369,4 +377,68 @@
// Listener not called when a non existing override is removed.
verify(mListener1, never()).onCompatChange(PACKAGE_NAME);
}
+
+ @Test
+ public void testReportChange() throws Exception {
+ ApplicationInfo appInfo = ApplicationInfoBuilder.create().withUid(123).build();
+ mPlatformCompat.reportChange(1L, appInfo);
+ verify(mChangeReporter).reportChange(123, 1L, ChangeReporter.STATE_LOGGED, false, true);
+
+ ApplicationInfo systemAppInfo =
+ ApplicationInfoBuilder.create().withUid(123).systemApp().build();
+ mPlatformCompat.reportChange(1L, systemAppInfo);
+ verify(mChangeReporter).reportChange(123, 1L, ChangeReporter.STATE_LOGGED, true, true);
+ }
+
+ @Test
+ public void testReportChangeByPackageName() throws Exception {
+ when(mPackageManagerInternal.getApplicationInfo(
+ eq(PACKAGE_NAME), eq(0L), anyInt(), anyInt()))
+ .thenReturn(
+ ApplicationInfoBuilder.create()
+ .withPackageName(PACKAGE_NAME)
+ .withUid(123)
+ .build());
+
+ mPlatformCompat.reportChangeByPackageName(1L, PACKAGE_NAME, 123);
+ verify(mChangeReporter).reportChange(123, 1L, ChangeReporter.STATE_LOGGED, false, true);
+
+ String SYSTEM_PACKAGE_NAME = "my.system.package";
+
+ when(mPackageManagerInternal.getApplicationInfo(
+ eq(SYSTEM_PACKAGE_NAME), eq(0L), anyInt(), anyInt()))
+ .thenReturn(
+ ApplicationInfoBuilder.create()
+ .withPackageName(SYSTEM_PACKAGE_NAME)
+ .withUid(123)
+ .systemApp()
+ .build());
+
+ mPlatformCompat.reportChangeByPackageName(1L, SYSTEM_PACKAGE_NAME, 123);
+ verify(mChangeReporter).reportChange(123, 1L, ChangeReporter.STATE_LOGGED, true, true);
+ }
+
+ @Test
+ public void testIsChangeEnabled() throws Exception {
+ mCompatConfig =
+ CompatConfigBuilder.create(mBuildClassifier, mContext)
+ .addEnabledChangeWithId(1L)
+ .addDisabledChangeWithId(2L)
+ .addEnabledChangeWithId(3L)
+ .build();
+ mCompatConfig.forceNonDebuggableFinalForTest(true);
+ mPlatformCompat =
+ new PlatformCompat(mContext, mCompatConfig, mBuildClassifier, mChangeReporter);
+
+ ApplicationInfo appInfo = ApplicationInfoBuilder.create().withUid(123).build();
+ assertThat(mPlatformCompat.isChangeEnabled(1L, appInfo)).isTrue();
+ verify(mChangeReporter).reportChange(123, 1L, ChangeReporter.STATE_ENABLED, false, false);
+ assertThat(mPlatformCompat.isChangeEnabled(2L, appInfo)).isFalse();
+ verify(mChangeReporter).reportChange(123, 2L, ChangeReporter.STATE_DISABLED, false, false);
+
+ ApplicationInfo systemAppInfo =
+ ApplicationInfoBuilder.create().withUid(123).systemApp().build();
+ assertThat(mPlatformCompat.isChangeEnabled(3L, systemAppInfo)).isTrue();
+ verify(mChangeReporter).reportChange(123, 3L, ChangeReporter.STATE_ENABLED, true, false);
+ }
}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 398dc281..c1d7afb 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -40,6 +40,7 @@
import static android.app.Notification.FLAG_ONLY_ALERT_ONCE;
import static android.app.Notification.FLAG_USER_INITIATED_JOB;
import static android.app.Notification.VISIBILITY_PRIVATE;
+import static android.app.NotificationChannel.NEWS_ID;
import static android.app.NotificationChannel.USER_LOCKED_ALLOW_BUBBLE;
import static android.app.NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED;
import static android.app.NotificationManager.BUBBLE_PREFERENCE_ALL;
@@ -91,7 +92,9 @@
import static android.service.notification.Adjustment.KEY_CONTEXTUAL_ACTIONS;
import static android.service.notification.Adjustment.KEY_IMPORTANCE;
import static android.service.notification.Adjustment.KEY_TEXT_REPLIES;
+import static android.service.notification.Adjustment.KEY_TYPE;
import static android.service.notification.Adjustment.KEY_USER_SENTIMENT;
+import static android.service.notification.Adjustment.TYPE_NEWS;
import static android.service.notification.Condition.SOURCE_CONTEXT;
import static android.service.notification.Condition.SOURCE_USER_ACTION;
import static android.service.notification.Condition.STATE_TRUE;
@@ -15778,4 +15781,27 @@
when(mPackageManagerInternal.isSameApp(anyString(), anyInt(), anyInt())).thenReturn(false);
assertThat(mBinderService.getEffectsSuppressor()).isEqualTo(mListener.component);
}
+
+ @Test
+ @EnableFlags(android.service.notification.Flags.FLAG_NOTIFICATION_CLASSIFICATION)
+ public void testApplyAdjustment_keyType_validType() throws Exception {
+ final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
+ mService.addNotification(r);
+ NotificationManagerService.WorkerHandler handler = mock(
+ NotificationManagerService.WorkerHandler.class);
+ mService.setHandler(handler);
+
+ Bundle signals = new Bundle();
+ signals.putInt(KEY_TYPE, TYPE_NEWS);
+ Adjustment adjustment = new Adjustment(
+ r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
+ when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
+ mBinderService.applyAdjustmentFromAssistant(null, adjustment);
+
+ waitForIdle();
+
+ r.applyAdjustments();
+
+ assertThat(r.getChannel().getId()).isEqualTo(NEWS_ID);
+ }
}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationVisitUrisTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationVisitUrisTest.java
index 594d6f2..6a99731 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationVisitUrisTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationVisitUrisTest.java
@@ -37,6 +37,7 @@
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
import android.util.Log;
+import android.util.proto.ProtoOutputStream;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.RemoteViews;
@@ -105,7 +106,7 @@
private static final ImmutableSet<Class<?>> UNUSABLE_TYPES =
ImmutableSet.of(Consumer.class, IBinder.class, MediaSession.Token.class, Parcel.class,
PrintWriter.class, Resources.Theme.class, View.class,
- LayoutInflater.Factory2.class);
+ LayoutInflater.Factory2.class, ProtoOutputStream.class);
// Maximum number of times we allow generating the same class recursively.
// E.g. new RemoteViews.addView(new RemoteViews()) but stop there.
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
index d1880d2..ff4bc21 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
@@ -23,6 +23,10 @@
import static android.app.NotificationChannel.ALLOW_BUBBLE_ON;
import static android.app.NotificationChannel.CONVERSATION_CHANNEL_ID_FORMAT;
import static android.app.NotificationChannel.DEFAULT_ALLOW_BUBBLE;
+import static android.app.NotificationChannel.NEWS_ID;
+import static android.app.NotificationChannel.PROMOTIONS_ID;
+import static android.app.NotificationChannel.RECS_ID;
+import static android.app.NotificationChannel.SOCIAL_MEDIA_ID;
import static android.app.NotificationChannel.USER_LOCKED_ALLOW_BUBBLE;
import static android.app.NotificationChannel.USER_LOCKED_IMPORTANCE;
import static android.app.NotificationChannel.USER_LOCKED_LIGHTS;
@@ -47,6 +51,9 @@
import static android.os.UserHandle.USER_SYSTEM;
import static android.platform.test.flag.junit.SetFlagsRule.DefaultInitValueType.DEVICE_DEFAULT;
+import static android.service.notification.Flags.FLAG_NOTIFICATION_CLASSIFICATION;
+import static android.service.notification.Flags.notificationClassification;
+
import static com.android.internal.config.sysui.SystemUiSystemPropertiesFlags.NotificationFlags.PROPAGATE_CHANNEL_UPDATES_TO_CONVERSATIONS;
import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_PREFERENCES__FSI_STATE__DENIED;
import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_PREFERENCES__FSI_STATE__GRANTED;
@@ -184,6 +191,7 @@
@SmallTest
@RunWith(ParameterizedAndroidJunit4.class)
+@EnableFlags(FLAG_PERSIST_INCOMPLETE_RESTORE_DATA)
public class PreferencesHelperTest extends UiServiceTestCase {
private static final int UID_HEADLESS = 1000000;
private static final UserHandle USER = UserHandle.of(0);
@@ -233,7 +241,7 @@
@Parameters(name = "{0}")
public static List<FlagsParameterization> getParams() {
return FlagsParameterization.allCombinationsOf(
- FLAG_PERSIST_INCOMPLETE_RESTORE_DATA);
+ FLAG_NOTIFICATION_CLASSIFICATION);
}
public PreferencesHelperTest(FlagsParameterization flags) {
@@ -582,6 +590,16 @@
assertTrue(mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel2, false, false,
UID_N_MR1, false));
+ NotificationChannel updateNews = null;
+ if (notificationClassification()) {
+ // change one of the reserved bundle channels to ensure changes are persisted across
+ // boot
+ updateNews = mHelper.getNotificationChannel(
+ PKG_N_MR1, UID_N_MR1, NEWS_ID, false).copy();
+ updateNews.setImportance(IMPORTANCE_NONE);
+ mHelper.updateNotificationChannel(PKG_N_MR1, UID_N_MR1, updateNews, true, 1000, true);
+ }
+
mHelper.setShowBadge(PKG_N_MR1, UID_N_MR1, true);
ByteArrayOutputStream baos = writeXmlAndPurge(PKG_N_MR1, UID_N_MR1, false,
@@ -597,6 +615,12 @@
mXmlHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1.getId(), false));
compareChannels(channel2,
mXmlHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel2.getId(), false));
+ if (notificationClassification()) {
+ assertThat(mXmlHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, updateNews.getId(),
+ false)).isNotNull();
+ assertThat(mXmlHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, updateNews.getId(),
+ false)).isEqualTo(updateNews);
+ }
List<NotificationChannelGroup> actualGroups = mXmlHelper.getNotificationChannelGroups(
PKG_N_MR1, UID_N_MR1, false, true, false, true, null).getList();
@@ -1130,9 +1154,22 @@
+ "app_user_locked_fields=\"0\" sent_invalid_msg=\"false\" "
+ "sent_valid_msg=\"false\" user_demote_msg_app=\"false\" sent_valid_bubble"
+ "=\"false\" uid=\"10002\">\n"
+ + (notificationClassification() ? "<channel id=\"android.app.social\" "
+ + "name=\"Social\" importance=\"2\" "
+ + "sound=\"content://settings/system/notification_sound\" "
+ + "usage=\"5\" content_type=\"4\" flags=\"0\" show_badge=\"true\" />\n" : "")
+ "<channel id=\"id\" name=\"name\" importance=\"2\" "
+ "sound=\"content://settings/system/notification_sound\" usage=\"5\" "
+ "content_type=\"4\" flags=\"0\" show_badge=\"true\" orig_imp=\"2\" />\n"
+ + (notificationClassification() ? "<channel id=\"android.app.news\" name=\"News\" "
+ + "importance=\"2\" sound=\"content://settings/system/notification_sound\" "
+ + "usage=\"5\" content_type=\"4\" flags=\"0\" show_badge=\"true\" />\n"
+ + "<channel id=\"android.app.recs\" name=\"Recommendations\" importance=\"2\" "
+ + "sound=\"content://settings/system/notification_sound\" usage=\"5\" "
+ + "content_type=\"4\" flags=\"0\" show_badge=\"true\" />\n"
+ + "<channel id=\"android.app.promotions\" name=\"Promotions\" importance=\"2\" "
+ + "sound=\"content://settings/system/notification_sound\" usage=\"5\" "
+ + "content_type=\"4\" flags=\"0\" show_badge=\"true\" />\n" : "")
+ "</package>\n"
+ "<package name=\"com.example.n_mr1\" show_badge=\"true\" "
+ "app_user_locked_fields=\"0\" sent_invalid_msg=\"false\" "
@@ -1140,6 +1177,10 @@
+ "=\"false\" uid=\"10001\">\n"
+ "<channelGroup id=\"1\" name=\"bye\" blocked=\"false\" locked=\"0\" />\n"
+ "<channelGroup id=\"2\" name=\"hello\" blocked=\"false\" locked=\"0\" />\n"
+ + (notificationClassification() ? "<channel id=\"android.app.social\" "
+ + "name=\"Social\" importance=\"2\" "
+ + "sound=\"content://settings/system/notification_sound\" "
+ + "usage=\"5\" content_type=\"4\" flags=\"0\" show_badge=\"true\" />\n" : "")
+ "<channel id=\"id1\" name=\"name1\" importance=\"4\" show_badge=\"true\" "
+ "orig_imp=\"4\" />\n"
+ "<channel id=\"id2\" name=\"name2\" desc=\"descriptions for all\" "
@@ -1149,14 +1190,22 @@
+ "sound=\"content://settings/system/notification_sound\" usage=\"5\" "
+ "content_type=\"4\" flags=\"0\" vibration_enabled=\"true\" show_badge=\"true\" "
+ "orig_imp=\"4\" />\n"
+ + (notificationClassification() ? "<channel id=\"android.app.news\" name=\"News\" "
+ + "importance=\"2\" sound=\"content://settings/system/notification_sound\" "
+ + "usage=\"5\" content_type=\"4\" flags=\"0\" show_badge=\"true\" />\n"
+ + "<channel id=\"android.app.recs\" name=\"Recommendations\" importance=\"2\" "
+ + "sound=\"content://settings/system/notification_sound\" usage=\"5\" "
+ + "content_type=\"4\" flags=\"0\" show_badge=\"true\" />\n"
+ + "<channel id=\"android.app.promotions\" name=\"Promotions\" importance=\"2\" "
+ + "sound=\"content://settings/system/notification_sound\" usage=\"5\" "
+ + "content_type=\"4\" flags=\"0\" show_badge=\"true\" />\n" : "")
+ "<channel id=\"miscellaneous\" name=\"Uncategorized\" "
+ "sound=\"content://settings/system/notification_sound\" usage=\"5\" "
+ "content_type=\"4\" flags=\"0\" show_badge=\"true\" />\n"
+ "</package>\n"
+ "<package name=\"com.example.p\" show_badge=\"true\" "
+ "app_user_locked_fields=\"0\" sent_invalid_msg=\"true\" sent_valid_msg=\"true\""
- + " user_demote_msg_app=\"true\" sent_valid_bubble=\"false\" uid=\"10003\" />\n"
- + "</ranking>";
+ + " user_demote_msg_app=\"true\" sent_valid_bubble=\"false\" uid=\"10003\"";
assertThat(baos.toString()).contains(expected);
}
@@ -1216,9 +1265,22 @@
+ "app_user_locked_fields=\"0\" sent_invalid_msg=\"false\" "
+ "sent_valid_msg=\"false\" user_demote_msg_app=\"false\" sent_valid_bubble"
+ "=\"false\">\n"
+ + (notificationClassification() ? "<channel id=\"android.app.social\" "
+ + "name=\"Social\" importance=\"2\" "
+ + "sound=\"content://settings/system/notification_sound\" "
+ + "usage=\"5\" content_type=\"4\" flags=\"0\" show_badge=\"true\" />\n" : "")
+ "<channel id=\"id\" name=\"name\" importance=\"2\" "
+ "sound=\"content://settings/system/notification_sound\" usage=\"5\" "
+ "content_type=\"4\" flags=\"0\" show_badge=\"true\" orig_imp=\"2\" />\n"
+ + (notificationClassification() ? "<channel id=\"android.app.news\" name=\"News\" "
+ + "importance=\"2\" sound=\"content://settings/system/notification_sound\" "
+ + "usage=\"5\" content_type=\"4\" flags=\"0\" show_badge=\"true\" />\n"
+ + "<channel id=\"android.app.recs\" name=\"Recommendations\" importance=\"2\" "
+ + "sound=\"content://settings/system/notification_sound\" usage=\"5\" "
+ + "content_type=\"4\" flags=\"0\" show_badge=\"true\" />\n"
+ + "<channel id=\"android.app.promotions\" name=\"Promotions\" importance=\"2\" "
+ + "sound=\"content://settings/system/notification_sound\" usage=\"5\" "
+ + "content_type=\"4\" flags=\"0\" show_badge=\"true\" />\n" : "")
+ "</package>\n"
// Importance default because on in permission helper
+ "<package name=\"com.example.n_mr1\" importance=\"3\" show_badge=\"true\" "
@@ -1227,6 +1289,10 @@
+ "=\"false\">\n"
+ "<channelGroup id=\"1\" name=\"bye\" blocked=\"false\" locked=\"0\" />\n"
+ "<channelGroup id=\"2\" name=\"hello\" blocked=\"false\" locked=\"0\" />\n"
+ + (notificationClassification() ? "<channel id=\"android.app.social\" "
+ + "name=\"Social\" importance=\"2\" "
+ + "sound=\"content://settings/system/notification_sound\" "
+ + "usage=\"5\" content_type=\"4\" flags=\"0\" show_badge=\"true\" />\n" : "")
+ "<channel id=\"id1\" name=\"name1\" importance=\"4\" show_badge=\"true\" "
+ "orig_imp=\"4\" />\n"
+ "<channel id=\"id2\" name=\"name2\" desc=\"descriptions for all\" "
@@ -1236,6 +1302,15 @@
+ "sound=\"content://settings/system/notification_sound\" usage=\"5\" "
+ "content_type=\"4\" flags=\"0\" vibration_enabled=\"true\" show_badge=\"true\" "
+ "orig_imp=\"4\" />\n"
+ + (notificationClassification() ? "<channel id=\"android.app.news\" name=\"News\" "
+ + "importance=\"2\" sound=\"content://settings/system/notification_sound\" "
+ + "usage=\"5\" content_type=\"4\" flags=\"0\" show_badge=\"true\" />\n"
+ + "<channel id=\"android.app.recs\" name=\"Recommendations\" importance=\"2\" "
+ + "sound=\"content://settings/system/notification_sound\" usage=\"5\" "
+ + "content_type=\"4\" flags=\"0\" show_badge=\"true\" />\n"
+ + "<channel id=\"android.app.promotions\" name=\"Promotions\" importance=\"2\" "
+ + "sound=\"content://settings/system/notification_sound\" usage=\"5\" "
+ + "content_type=\"4\" flags=\"0\" show_badge=\"true\" />\n" : "")
+ "<channel id=\"miscellaneous\" name=\"Uncategorized\" "
+ "sound=\"content://settings/system/notification_sound\" usage=\"5\" "
+ "content_type=\"4\" flags=\"0\" show_badge=\"true\" />\n"
@@ -1243,12 +1318,11 @@
// Importance default because on in permission helper
+ "<package name=\"com.example.p\" importance=\"3\" show_badge=\"true\" "
+ "app_user_locked_fields=\"0\" sent_invalid_msg=\"true\" sent_valid_msg=\"true\""
- + " user_demote_msg_app=\"true\" sent_valid_bubble=\"false\" />\n"
- // Packages that exist solely in permissionhelper
- + "<package name=\"first\" importance=\"3\" />\n"
- + "<package name=\"third\" importance=\"0\" />\n"
- + "</ranking>";
+ + " user_demote_msg_app=\"true\" sent_valid_bubble=\"false\"";
assertThat(baos.toString()).contains(expected);
+ // Packages that exist solely in permissionhelper
+ assertThat(baos.toString()).contains("<package name=\"first\" importance=\"3\"");
+ assertThat(baos.toString()).contains("<package name=\"third\" importance=\"0\"");
}
@Test
@@ -1303,9 +1377,22 @@
+ "app_user_locked_fields=\"0\" sent_invalid_msg=\"false\" "
+ "sent_valid_msg=\"false\" user_demote_msg_app=\"false\" sent_valid_bubble"
+ "=\"false\">\n"
+ + (notificationClassification() ? "<channel id=\"android.app.social\" "
+ + "name=\"Social\" importance=\"2\" "
+ + "sound=\"content://settings/system/notification_sound\" usage=\"5\" "
+ + "content_type=\"4\" flags=\"0\" show_badge=\"true\" />\n" : "")
+ "<channel id=\"id\" name=\"name\" importance=\"2\" "
+ "sound=\"content://settings/system/notification_sound\" usage=\"5\" "
+ "content_type=\"4\" flags=\"0\" show_badge=\"true\" orig_imp=\"2\" />\n"
+ + (notificationClassification() ? "<channel id=\"android.app.news\" name=\"News\" "
+ + "importance=\"2\" sound=\"content://settings/system/notification_sound\" "
+ + "usage=\"5\" content_type=\"4\" flags=\"0\" show_badge=\"true\" />\n"
+ + "<channel id=\"android.app.recs\" name=\"Recommendations\" importance=\"2\" "
+ + "sound=\"content://settings/system/notification_sound\" usage=\"5\" "
+ + "content_type=\"4\" flags=\"0\" show_badge=\"true\" />\n"
+ + "<channel id=\"android.app.promotions\" name=\"Promotions\" importance=\"2\" "
+ + "sound=\"content://settings/system/notification_sound\" usage=\"5\" "
+ + "content_type=\"4\" flags=\"0\" show_badge=\"true\" />\n" : "")
+ "</package>\n"
// Importance 0 because missing from permission helper
+ "<package name=\"com.example.n_mr1\" importance=\"0\" show_badge=\"true\" "
@@ -1314,6 +1401,10 @@
+ "=\"false\">\n"
+ "<channelGroup id=\"1\" name=\"bye\" blocked=\"false\" locked=\"0\" />\n"
+ "<channelGroup id=\"2\" name=\"hello\" blocked=\"false\" locked=\"0\" />\n"
+ + (notificationClassification() ? "<channel id=\"android.app.social\" "
+ + "name=\"Social\" importance=\"2\" "
+ + "sound=\"content://settings/system/notification_sound\" usage=\"5\" "
+ + "content_type=\"4\" flags=\"0\" show_badge=\"true\" />\n" : "")
+ "<channel id=\"id1\" name=\"name1\" importance=\"4\" show_badge=\"true\" "
+ "orig_imp=\"4\" />\n"
+ "<channel id=\"id2\" name=\"name2\" desc=\"descriptions for all\" "
@@ -1323,6 +1414,15 @@
+ "sound=\"content://settings/system/notification_sound\" usage=\"5\" "
+ "content_type=\"4\" flags=\"0\" vibration_enabled=\"true\" show_badge=\"true\" "
+ "orig_imp=\"4\" />\n"
+ + (notificationClassification() ? "<channel id=\"android.app.news\" name=\"News\" "
+ + "importance=\"2\" sound=\"content://settings/system/notification_sound\" "
+ + "usage=\"5\" content_type=\"4\" flags=\"0\" show_badge=\"true\" />\n"
+ + "<channel id=\"android.app.recs\" name=\"Recommendations\" importance=\"2\" "
+ + "sound=\"content://settings/system/notification_sound\" usage=\"5\" "
+ + "content_type=\"4\" flags=\"0\" show_badge=\"true\" />\n"
+ + "<channel id=\"android.app.promotions\" name=\"Promotions\" importance=\"2\" "
+ + "sound=\"content://settings/system/notification_sound\" usage=\"5\" "
+ + "content_type=\"4\" flags=\"0\" show_badge=\"true\" />\n" : "")
+ "<channel id=\"miscellaneous\" name=\"Uncategorized\" "
+ "sound=\"content://settings/system/notification_sound\" usage=\"5\" "
+ "content_type=\"4\" flags=\"0\" show_badge=\"true\" />\n"
@@ -1330,8 +1430,7 @@
// Importance default because on in permission helper
+ "<package name=\"com.example.p\" importance=\"3\" show_badge=\"true\" "
+ "app_user_locked_fields=\"0\" sent_invalid_msg=\"true\" sent_valid_msg=\"true\""
- + " user_demote_msg_app=\"true\" sent_valid_bubble=\"false\" />\n"
- + "</ranking>";
+ + " user_demote_msg_app=\"true\" sent_valid_bubble=\"false\"";
assertThat(baos.toString()).contains(expected);
}
@@ -1851,8 +1950,8 @@
parser.nextTag();
mHelper.readXml(parser, false, UserHandle.USER_ALL);
- final NotificationChannel updated1 =
- mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, NotificationChannel.DEFAULT_CHANNEL_ID, false);
+ final NotificationChannel updated1 = mHelper.getNotificationChannel(
+ PKG_N_MR1, UID_N_MR1, NotificationChannel.DEFAULT_CHANNEL_ID, false);
assertEquals(NotificationManager.IMPORTANCE_HIGH, updated1.getImportance());
assertTrue(updated1.canBypassDnd());
assertEquals(VISIBILITY_SECRET, updated1.getLockscreenVisibility());
@@ -2392,18 +2491,20 @@
// Returns only non-deleted channels
List<NotificationChannel> channels =
mHelper.getNotificationChannels(PKG_N_MR1, UID_N_MR1, false).getList();
- assertEquals(2, channels.size()); // Default channel + non-deleted channel
+ // Default channel + non-deleted channel + system defaults
+ assertEquals(notificationClassification() ? 6 : 2, channels.size());
for (NotificationChannel nc : channels) {
- if (!NotificationChannel.DEFAULT_CHANNEL_ID.equals(nc.getId())) {
+ if (channel2.getId().equals(nc.getId())) {
compareChannels(channel2, nc);
}
}
// Returns deleted channels too
channels = mHelper.getNotificationChannels(PKG_N_MR1, UID_N_MR1, true).getList();
- assertEquals(3, channels.size()); // Includes default channel
+ // Includes system channel(s)
+ assertEquals(notificationClassification() ? 7 : 3, channels.size());
for (NotificationChannel nc : channels) {
- if (!NotificationChannel.DEFAULT_CHANNEL_ID.equals(nc.getId())) {
+ if (channel2.getId().equals(nc.getId())) {
compareChannels(channelMap.get(nc.getId()), nc);
}
}
@@ -3013,7 +3114,8 @@
final ApplicationInfo legacy = new ApplicationInfo();
legacy.targetSdkVersion = Build.VERSION_CODES.N_MR1;
- when(mPm.getApplicationInfoAsUser(eq(PKG_N_MR1), anyInt(), anyInt())).thenReturn(legacy);
+ when(mPm.getApplicationInfoAsUser(eq(PKG_N_MR1), anyInt(), anyInt()))
+ .thenReturn(legacy);
// create records with the default channel for all user 0 and user 1 uids
mHelper.canShowBadge(PKG_N_MR1, user0Uids[i]);
@@ -3024,13 +3126,14 @@
// user 0 records remain
for (int i = 0; i < user0Uids.length; i++) {
- assertEquals(1,
- mHelper.getNotificationChannels(PKG_N_MR1, user0Uids[i], false).getList().size());
+ assertEquals(notificationClassification() ? 5 : 1,
+ mHelper.getNotificationChannels(PKG_N_MR1, user0Uids[i], false)
+ .getList().size());
}
// user 1 records are gone
for (int i = 0; i < user1Uids.length; i++) {
- assertEquals(0,
- mHelper.getNotificationChannels(PKG_N_MR1, user1Uids[i], false).getList().size());
+ assertEquals(0, mHelper.getNotificationChannels(PKG_N_MR1, user1Uids[i], false)
+ .getList().size());
}
}
@@ -3054,7 +3157,8 @@
assertFalse(mHelper.onPackagesChanged(false, USER_SYSTEM,
new String[]{PKG_N_MR1}, new int[]{UID_N_MR1}));
- assertEquals(2, mHelper.getNotificationChannels(PKG_N_MR1, UID_N_MR1, false).getList().size());
+ assertEquals(notificationClassification() ? 6 : 2,
+ mHelper.getNotificationChannels(PKG_N_MR1, UID_N_MR1, false).getList().size());
}
@Test
@@ -3126,7 +3230,8 @@
@Test
public void testRecordDefaults() throws Exception {
assertEquals(true, mHelper.canShowBadge(PKG_N_MR1, UID_N_MR1));
- assertEquals(1, mHelper.getNotificationChannels(PKG_N_MR1, UID_N_MR1, false).getList().size());
+ assertEquals(notificationClassification() ? 5 : 1,
+ mHelper.getNotificationChannels(PKG_N_MR1, UID_N_MR1, false).getList().size());
}
@Test
@@ -3212,7 +3317,9 @@
assertEquals(3, actual.size());
for (NotificationChannelGroup group : actual) {
if (group.getId() == null) {
- assertEquals(2, group.getChannels().size()); // misc channel too
+ assertEquals(
+ notificationClassification() ? 6 : 2,
+ group.getChannels().size()); // misc channel too
assertTrue(channel3.getId().equals(group.getChannels().get(0).getId())
|| channel3.getId().equals(group.getChannels().get(1).getId()));
} else if (group.getId().equals(ncg.getId())) {
@@ -3363,6 +3470,9 @@
new NotificationChannel("" + j, "a", IMPORTANCE_HIGH), true, false,
UID_N_MR1, false);
}
+ if (notificationClassification()) {
+ numChannels += 4;
+ }
expectedChannels.put(pkgName, numChannels);
}
@@ -4583,7 +4693,12 @@
@Test
public void testTooManyChannels() {
- for (int i = 0; i < NOTIFICATION_CHANNEL_COUNT_LIMIT; i++) {
+ int numToCreate = NOTIFICATION_CHANNEL_COUNT_LIMIT;
+ if (notificationClassification()) {
+ // reserved channels lower limit
+ numToCreate -= 4;
+ }
+ for (int i = 0; i < numToCreate; i++) {
NotificationChannel channel = new NotificationChannel(String.valueOf(i),
String.valueOf(i), NotificationManager.IMPORTANCE_HIGH);
mHelper.createNotificationChannel(PKG_O, UID_O, channel, true, true, UID_O, false);
@@ -4602,11 +4717,16 @@
@Test
public void testTooManyChannels_xml() throws Exception {
+ int numToCreate = NOTIFICATION_CHANNEL_COUNT_LIMIT;
+ if (notificationClassification()) {
+ // reserved channels lower limit
+ numToCreate -= 4;
+ }
String extraChannel = "EXTRA";
String extraChannel1 = "EXTRA1";
// create first... many... directly so we don't need a big xml blob in this test
- for (int i = 0; i < NOTIFICATION_CHANNEL_COUNT_LIMIT; i++) {
+ for (int i = 0; i < numToCreate; i++) {
NotificationChannel channel = new NotificationChannel(String.valueOf(i),
String.valueOf(i), NotificationManager.IMPORTANCE_HIGH);
mHelper.createNotificationChannel(PKG_O, UID_O, channel, true, true, UID_O, false);
@@ -5619,8 +5739,9 @@
ArrayList<StatsEvent> events = new ArrayList<>();
mHelper.pullPackageChannelPreferencesStats(events);
- // number of channels with preferences should be 3 total
- assertEquals("expected number of events", 3, events.size());
+ assertEquals("expected number of events",
+ notificationClassification() ? 7 : 3,
+ events.size());
for (StatsEvent ev : events) {
// all of these events should be of PackageNotificationChannelPreferences type,
// and therefore we expect the atom to have this field.
@@ -5643,7 +5764,7 @@
} else if (eventChannelId.equals("a")) {
assertEquals("channel name", "a", p.getChannelName());
assertEquals("importance", IMPORTANCE_LOW, p.getImportance());
- } else { // b
+ } else if (eventChannelId.equals("b")){ // b
assertEquals("channel name", "b", p.getChannelName());
assertEquals("importance", IMPORTANCE_HIGH, p.getImportance());
}
@@ -5661,11 +5782,17 @@
mHelper.createNotificationChannel(PKG_O, UID_O, channelC, true, false, UID_O, false);
List<String> channels = new LinkedList<>(Arrays.asList("a", "b", "c"));
+ if (notificationClassification()) {
+ channels.add(NEWS_ID);
+ channels.add(PROMOTIONS_ID);
+ channels.add(SOCIAL_MEDIA_ID);
+ channels.add(RECS_ID);
+ }
ArrayList<StatsEvent> events = new ArrayList<>();
mHelper.pullPackageChannelPreferencesStats(events);
- assertEquals("total events", 3, events.size());
+ assertEquals("total events", notificationClassification() ? 7 : 3, events.size());
for (StatsEvent ev : events) {
AtomsProto.Atom atom = StatsEventTestUtils.convertToAtom(ev);
assertTrue(atom.hasPackageNotificationChannelPreferences());
@@ -5699,7 +5826,7 @@
mHelper.pullPackageChannelPreferencesStats(events);
// In this case, we want to check the properties of the conversation channel (not parent)
- assertEquals("total events", 2, events.size());
+ assertEquals("total events", notificationClassification() ? 6 : 2, events.size());
for (StatsEvent ev : events) {
AtomsProto.Atom atom = StatsEventTestUtils.convertToAtom(ev);
assertTrue(atom.hasPackageNotificationChannelPreferences());
@@ -5731,7 +5858,9 @@
ArrayList<StatsEvent> events = new ArrayList<>();
mHelper.pullPackageChannelPreferencesStats(events);
- assertEquals("total events", 2, events.size());
+ assertEquals("total events",
+ notificationClassification() ? 6 : 2,
+ events.size());
for (StatsEvent ev : events) {
AtomsProto.Atom atom = StatsEventTestUtils.convertToAtom(ev);
assertTrue(atom.hasPackageNotificationChannelPreferences());
@@ -5762,7 +5891,9 @@
ArrayList<StatsEvent> events = new ArrayList<>();
mHelper.pullPackageChannelPreferencesStats(events);
- assertEquals("total events", 2, events.size());
+ assertEquals("total events",
+ notificationClassification() ? 6 : 2,
+ events.size());
for (StatsEvent ev : events) {
AtomsProto.Atom atom = StatsEventTestUtils.convertToAtom(ev);
assertTrue(atom.hasPackageNotificationChannelPreferences());
@@ -6044,6 +6175,23 @@
assertEquals(0, actual.getChannels().stream().filter(c -> c.getId().equals("id2")).count());
}
+ @Test
+ @EnableFlags(FLAG_NOTIFICATION_CLASSIFICATION)
+ public void testNotificationBundles() {
+ // do something that triggers settings creation for an app
+ mHelper.setShowBadge(PKG_O, UID_O, true);
+
+ // verify 4 reserved channels are created
+ assertThat(mHelper.getNotificationChannel(PKG_O, UID_O, NEWS_ID, false).getImportance())
+ .isEqualTo(IMPORTANCE_LOW);
+ assertThat(mHelper.getNotificationChannel(PKG_O, UID_O, PROMOTIONS_ID, false)
+ .getImportance()).isEqualTo(IMPORTANCE_LOW);
+ assertThat(mHelper.getNotificationChannel(PKG_O, UID_O, SOCIAL_MEDIA_ID, false)
+ .getImportance()).isEqualTo(IMPORTANCE_LOW);
+ assertThat(mHelper.getNotificationChannel(PKG_O, UID_O, RECS_ID, false).getImportance())
+ .isEqualTo(IMPORTANCE_LOW);
+ }
+
private static NotificationChannel cloneChannel(NotificationChannel original) {
Parcel parcel = Parcel.obtain();
try {
diff --git a/services/tests/wmtests/src/com/android/server/wm/LetterboxTest.java b/services/tests/wmtests/src/com/android/server/wm/LetterboxTest.java
index d2494ff..fbc4c7b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LetterboxTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LetterboxTest.java
@@ -172,14 +172,14 @@
@Test
public void testSurfaceOrigin_applied() {
mLetterbox.layout(new Rect(0, 0, 10, 10), new Rect(0, 1, 10, 10), new Point(1000, 2000));
- mLetterbox.applySurfaceChanges(mTransaction);
+ applySurfaceChanges();
verify(mTransaction).setPosition(mSurfaces.top, -1000, -2000);
}
@Test
public void testApplySurfaceChanges_setColor() {
mLetterbox.layout(new Rect(0, 0, 10, 10), new Rect(0, 1, 10, 10), new Point(1000, 2000));
- mLetterbox.applySurfaceChanges(mTransaction);
+ applySurfaceChanges();
verify(mTransaction).setColor(mSurfaces.top, new float[]{0, 0, 0});
@@ -187,7 +187,7 @@
assertTrue(mLetterbox.needsApplySurfaceChanges());
- mLetterbox.applySurfaceChanges(mTransaction);
+ applySurfaceChanges();
verify(mTransaction).setColor(mSurfaces.top, new float[]{0, 1, 0});
}
@@ -195,7 +195,7 @@
@Test
public void testNeedsApplySurfaceChanges_wallpaperBackgroundRequested() {
mLetterbox.layout(new Rect(0, 0, 10, 10), new Rect(0, 1, 10, 10), new Point(1000, 2000));
- mLetterbox.applySurfaceChanges(mTransaction);
+ applySurfaceChanges();
verify(mTransaction).setAlpha(mSurfaces.top, 1.0f);
assertFalse(mLetterbox.needsApplySurfaceChanges());
@@ -204,14 +204,14 @@
assertTrue(mLetterbox.needsApplySurfaceChanges());
- mLetterbox.applySurfaceChanges(mTransaction);
+ applySurfaceChanges();
verify(mTransaction).setAlpha(mSurfaces.fullWindowSurface, mDarkScrimAlpha);
}
@Test
public void testNeedsApplySurfaceChanges_setParentSurface() {
mLetterbox.layout(new Rect(0, 0, 10, 10), new Rect(0, 1, 10, 10), new Point(1000, 2000));
- mLetterbox.applySurfaceChanges(mTransaction);
+ applySurfaceChanges();
verify(mTransaction).reparent(mSurfaces.top, mParentSurface);
assertFalse(mLetterbox.needsApplySurfaceChanges());
@@ -220,14 +220,14 @@
assertTrue(mLetterbox.needsApplySurfaceChanges());
- mLetterbox.applySurfaceChanges(mTransaction);
+ applySurfaceChanges();
verify(mTransaction).reparent(mSurfaces.top, mParentSurface);
}
@Test
public void testApplySurfaceChanges_cornersNotRounded_surfaceFullWindowSurfaceNotCreated() {
mLetterbox.layout(new Rect(0, 0, 10, 10), new Rect(0, 1, 10, 10), new Point(1000, 2000));
- mLetterbox.applySurfaceChanges(mTransaction);
+ applySurfaceChanges();
assertNull(mSurfaces.fullWindowSurface);
}
@@ -236,7 +236,7 @@
public void testApplySurfaceChanges_cornersRounded_surfaceFullWindowSurfaceCreated() {
mAreCornersRounded = true;
mLetterbox.layout(new Rect(0, 0, 10, 10), new Rect(0, 1, 10, 10), new Point(1000, 2000));
- mLetterbox.applySurfaceChanges(mTransaction);
+ applySurfaceChanges();
assertNotNull(mSurfaces.fullWindowSurface);
}
@@ -245,7 +245,7 @@
public void testApplySurfaceChanges_wallpaperBackground_surfaceFullWindowSurfaceCreated() {
mHasWallpaperBackground = true;
mLetterbox.layout(new Rect(0, 0, 10, 10), new Rect(0, 1, 10, 10), new Point(1000, 2000));
- mLetterbox.applySurfaceChanges(mTransaction);
+ applySurfaceChanges();
assertNotNull(mSurfaces.fullWindowSurface);
}
@@ -254,7 +254,7 @@
public void testNotIntersectsOrFullyContains_cornersRounded() {
mAreCornersRounded = true;
mLetterbox.layout(new Rect(0, 0, 10, 10), new Rect(0, 1, 10, 10), new Point(0, 0));
- mLetterbox.applySurfaceChanges(mTransaction);
+ applySurfaceChanges();
assertTrue(mLetterbox.notIntersectsOrFullyContains(new Rect(1, 2, 9, 9)));
}
@@ -262,14 +262,19 @@
@Test
public void testSurfaceOrigin_changeCausesReapply() {
mLetterbox.layout(new Rect(0, 0, 10, 10), new Rect(0, 1, 10, 10), new Point(1000, 2000));
- mLetterbox.applySurfaceChanges(mTransaction);
+ applySurfaceChanges();
clearInvocations(mTransaction);
mLetterbox.layout(new Rect(0, 0, 10, 10), new Rect(0, 1, 10, 10), new Point(0, 0));
assertTrue(mLetterbox.needsApplySurfaceChanges());
- mLetterbox.applySurfaceChanges(mTransaction);
+ applySurfaceChanges();
verify(mTransaction).setPosition(mSurfaces.top, 0, 0);
}
+ private void applySurfaceChanges() {
+ mLetterbox.applySurfaceChanges(/* syncTransaction */ mTransaction,
+ /* pendingTransaction */ mTransaction);
+ }
+
class SurfaceControlMocker implements Supplier<SurfaceControl.Builder> {
private SurfaceControl.Builder mLeftBuilder;
public SurfaceControl left;
diff --git a/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java
index cd19449..0787052 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java
@@ -63,8 +63,8 @@
import static com.android.dx.mockito.inline.extended.ExtendedMockito.eq;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
-import static com.android.server.wm.LetterboxUiController.MIN_COUNT_TO_IGNORE_REQUEST_IN_LOOP;
-import static com.android.server.wm.LetterboxUiController.SET_ORIENTATION_REQUEST_COUNTER_TIMEOUT_MS;
+import static com.android.server.wm.AppCompatOrientationCapability.OrientationCapabilityState.MIN_COUNT_TO_IGNORE_REQUEST_IN_LOOP;
+import static com.android.server.wm.AppCompatOrientationCapability.OrientationCapabilityState.SET_ORIENTATION_REQUEST_COUNTER_TIMEOUT_MS;
import static com.android.window.flags.Flags.FLAG_CAMERA_COMPAT_FOR_FREEFORM;
import static org.junit.Assert.assertEquals;
@@ -156,7 +156,9 @@
public void testShouldIgnoreRequestedOrientation_activityRelaunching_returnsTrue() {
prepareActivityThatShouldIgnoreRequestedOrientationDuringRelaunch();
- assertTrue(mController.shouldIgnoreRequestedOrientation(SCREEN_ORIENTATION_UNSPECIFIED));
+ assertTrue(mActivity.mAppCompatController.getAppCompatCapability()
+ .getAppCompatOrientationCapability()
+ .shouldIgnoreRequestedOrientation(SCREEN_ORIENTATION_UNSPECIFIED));
}
@Test
@@ -176,14 +178,18 @@
doReturn(true).when(mDisplayContent.mDisplayRotationCompatPolicy)
.isTreatmentEnabledForActivity(eq(mActivity));
- assertTrue(mController.shouldIgnoreRequestedOrientation(SCREEN_ORIENTATION_UNSPECIFIED));
+ assertTrue(mActivity.mAppCompatController.getAppCompatCapability()
+ .getAppCompatOrientationCapability()
+ .shouldIgnoreRequestedOrientation(SCREEN_ORIENTATION_UNSPECIFIED));
}
@Test
public void testShouldIgnoreRequestedOrientation_overrideDisabled_returnsFalse() {
prepareActivityThatShouldIgnoreRequestedOrientationDuringRelaunch();
- assertFalse(mController.shouldIgnoreRequestedOrientation(SCREEN_ORIENTATION_UNSPECIFIED));
+ assertFalse(mActivity.mAppCompatController.getAppCompatCapability()
+ .getAppCompatOrientationCapability()
+ .shouldIgnoreRequestedOrientation(SCREEN_ORIENTATION_UNSPECIFIED));
}
@Test
@@ -195,7 +201,9 @@
mController = new LetterboxUiController(mWm, mActivity);
prepareActivityThatShouldIgnoreRequestedOrientationDuringRelaunch();
- assertTrue(mController.shouldIgnoreRequestedOrientation(SCREEN_ORIENTATION_UNSPECIFIED));
+ assertTrue(mActivity.mAppCompatController.getAppCompatCapability()
+ .getAppCompatOrientationCapability()
+ .shouldIgnoreRequestedOrientation(SCREEN_ORIENTATION_UNSPECIFIED));
}
@Test
@@ -209,7 +217,9 @@
mController = new LetterboxUiController(mWm, mActivity);
prepareActivityThatShouldIgnoreRequestedOrientationDuringRelaunch();
- assertFalse(mController.shouldIgnoreRequestedOrientation(SCREEN_ORIENTATION_UNSPECIFIED));
+ assertFalse(mActivity.mAppCompatController.getAppCompatCapability()
+ .getAppCompatOrientationCapability()
+ .shouldIgnoreRequestedOrientation(SCREEN_ORIENTATION_UNSPECIFIED));
}
@Test
@@ -315,7 +325,9 @@
doReturn(false).when(mLetterboxConfiguration)
.isPolicyForIgnoringRequestedOrientationEnabled();
- assertFalse(mController.shouldIgnoreRequestedOrientation(SCREEN_ORIENTATION_UNSPECIFIED));
+ assertFalse(mActivity.mAppCompatController.getAppCompatCapability()
+ .getAppCompatOrientationCapability()
+ .shouldIgnoreRequestedOrientation(SCREEN_ORIENTATION_UNSPECIFIED));
}
// shouldRefreshActivityForCameraCompat
@@ -522,8 +534,9 @@
final Rect opaqueBounds = new Rect(0, 0, 500, 300);
doReturn(opaqueBounds).when(mActivity).getBounds();
// Activity is translucent
- spyOn(mActivity.mTransparentPolicy);
- when(mActivity.mTransparentPolicy.isRunning()).thenReturn(true);
+ spyOn(mActivity.mAppCompatController.getTransparentPolicy());
+ when(mActivity.mAppCompatController.getTransparentPolicy()
+ .isRunning()).thenReturn(true);
// Makes requested sizes different
mainWindow.mRequestedWidth = opaqueBounds.width() - 1;
@@ -736,6 +749,7 @@
throws Exception {
mockThatProperty(PROPERTY_COMPAT_ALLOW_ORIENTATION_OVERRIDE, /* value */ false);
+ mActivity = setUpActivityWithComponent();
mController = new LetterboxUiController(mWm, mActivity);
mDisplayContent.setIgnoreOrientationRequest(true);
@@ -781,10 +795,14 @@
@EnableCompatChanges({OVERRIDE_ANY_ORIENTATION_TO_USER})
public void testOverrideOrientationIfNeeded_fullscreenAndUserOverrideEnabled_returnsUnchanged()
throws Exception {
- prepareActivityThatShouldApplyUserMinAspectRatioOverride();
+ doReturn(true).when(mLetterboxConfiguration).isUserAppAspectRatioSettingsEnabled();
+ mActivity = setUpActivityWithComponent();
+ spyOn(mActivity.mLetterboxUiController);
+ doReturn(USER_MIN_ASPECT_RATIO_3_2).when(mActivity.mLetterboxUiController)
+ .getUserMinAspectRatioOverrideCode();
- assertEquals(SCREEN_ORIENTATION_PORTRAIT, mController.overrideOrientationIfNeeded(
- /* candidate */ SCREEN_ORIENTATION_PORTRAIT));
+ assertEquals(SCREEN_ORIENTATION_PORTRAIT, mActivity.mLetterboxUiController
+ .overrideOrientationIfNeeded(/* candidate */ SCREEN_ORIENTATION_PORTRAIT));
}
@Test
@@ -852,6 +870,7 @@
throws Exception {
mockThatProperty(PROPERTY_COMPAT_ALLOW_ORIENTATION_OVERRIDE, /* value */ false);
+ mActivity = setUpActivityWithComponent();
mController = new LetterboxUiController(mWm, mActivity);
assertEquals(SCREEN_ORIENTATION_UNSPECIFIED, mController.overrideOrientationIfNeeded(
@@ -900,12 +919,14 @@
@Test
public void testOverrideOrientationIfNeeded_userFullscreenOverride_returnsUser() {
- spyOn(mController);
- doReturn(true).when(mController).shouldApplyUserFullscreenOverride();
+ spyOn(mActivity.mLetterboxUiController);
+ doReturn(true).when(mActivity.mLetterboxUiController)
+ .shouldApplyUserFullscreenOverride();
mDisplayContent.setIgnoreOrientationRequest(true);
- assertEquals(SCREEN_ORIENTATION_USER, mController.overrideOrientationIfNeeded(
- /* candidate */ SCREEN_ORIENTATION_UNSPECIFIED));
+ assertEquals(SCREEN_ORIENTATION_USER, mActivity.mAppCompatController
+ .getOrientationPolicy()
+ .overrideOrientationIfNeeded(/* candidate */ SCREEN_ORIENTATION_UNSPECIFIED));
}
@Test
@@ -961,12 +982,14 @@
@Test
@EnableCompatChanges({OVERRIDE_UNDEFINED_ORIENTATION_TO_PORTRAIT, OVERRIDE_ANY_ORIENTATION})
public void testOverrideOrientationIfNeeded_userFullScreenOverrideOverSystem_returnsUser() {
- spyOn(mController);
- doReturn(true).when(mController).shouldApplyUserFullscreenOverride();
+ spyOn(mActivity.mLetterboxUiController);
+ doReturn(true).when(mActivity.mLetterboxUiController)
+ .shouldApplyUserFullscreenOverride();
mDisplayContent.setIgnoreOrientationRequest(true);
- assertEquals(SCREEN_ORIENTATION_USER, mController.overrideOrientationIfNeeded(
- /* candidate */ SCREEN_ORIENTATION_PORTRAIT));
+ assertEquals(SCREEN_ORIENTATION_USER, mActivity.mAppCompatController
+ .getOrientationPolicy()
+ .overrideOrientationIfNeeded(/* candidate */ SCREEN_ORIENTATION_PORTRAIT));
}
@Test
@@ -991,18 +1014,19 @@
@Test
public void testOverrideOrientationIfNeeded_userAspectRatioApplied_unspecifiedOverridden() {
- spyOn(mController);
- doReturn(true).when(mController).shouldApplyUserMinAspectRatioOverride();
+ spyOn(mActivity.mLetterboxUiController);
+ doReturn(true).when(mActivity.mLetterboxUiController)
+ .shouldApplyUserMinAspectRatioOverride();
- assertEquals(SCREEN_ORIENTATION_PORTRAIT, mController.overrideOrientationIfNeeded(
- /* candidate */ SCREEN_ORIENTATION_UNSPECIFIED));
+ assertEquals(SCREEN_ORIENTATION_PORTRAIT, mActivity.mLetterboxUiController
+ .overrideOrientationIfNeeded(/* candidate */ SCREEN_ORIENTATION_UNSPECIFIED));
- assertEquals(SCREEN_ORIENTATION_PORTRAIT, mController.overrideOrientationIfNeeded(
- /* candidate */ SCREEN_ORIENTATION_LOCKED));
+ assertEquals(SCREEN_ORIENTATION_PORTRAIT, mActivity.mLetterboxUiController
+ .overrideOrientationIfNeeded(/* candidate */ SCREEN_ORIENTATION_LOCKED));
// unchanged if orientation is specified
- assertEquals(SCREEN_ORIENTATION_LANDSCAPE, mController.overrideOrientationIfNeeded(
- /* candidate */ SCREEN_ORIENTATION_LANDSCAPE));
+ assertEquals(SCREEN_ORIENTATION_LANDSCAPE, mActivity.mLetterboxUiController
+ .overrideOrientationIfNeeded(/* candidate */ SCREEN_ORIENTATION_LANDSCAPE));
}
@Test
@@ -1062,6 +1086,7 @@
prepareActivityThatShouldApplyUserMinAspectRatioOverride();
mockThatProperty(PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_OVERRIDE, /* value */ false);
+ mActivity = setUpActivityWithComponent();
mController = new LetterboxUiController(mWm, mActivity);
assertFalse(mController.shouldEnableUserAspectRatioSettings());
@@ -1344,6 +1369,8 @@
public void testshouldOverrideMinAspectRatio_propertyFalse_overrideEnabled_returnsFalse()
throws Exception {
mockThatProperty(PROPERTY_COMPAT_ALLOW_MIN_ASPECT_RATIO_OVERRIDE, /* value */ false);
+
+ mActivity = setUpActivityWithComponent();
mController = new LetterboxUiController(mWm, mActivity);
assertFalse(mController.shouldOverrideMinAspectRatio());
@@ -1472,6 +1499,8 @@
public void testshouldOverrideForceResizeApp_propertyFalse_overrideEnabled_returnsFalse()
throws Exception {
mockThatProperty(PROPERTY_COMPAT_ALLOW_RESIZEABLE_ACTIVITY_OVERRIDES, /* value */ false);
+
+ mActivity = setUpActivityWithComponent();
mController = new LetterboxUiController(mWm, mActivity);
assertFalse(mController.shouldOverrideForceResizeApp());
@@ -1528,6 +1557,8 @@
public void testshouldOverrideForceNonResizeApp_propertyFalse_overrideEnabled_returnsFalse()
throws Exception {
mockThatProperty(PROPERTY_COMPAT_ALLOW_RESIZEABLE_ACTIVITY_OVERRIDES, /* value */ false);
+
+ mActivity = setUpActivityWithComponent();
mController = new LetterboxUiController(mWm, mActivity);
assertFalse(mController.shouldOverrideForceNonResizeApp());
diff --git a/services/tests/wmtests/src/com/android/server/wm/TransparentPolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/TransparentPolicyTest.java
index 1d6e307..78cea95 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TransparentPolicyTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TransparentPolicyTest.java
@@ -332,7 +332,7 @@
mTask = task;
mActivityStack = new ActivityStackTest();
mActivityStack.pushActivity(opaqueActivity);
- spyOn(opaqueActivity.mTransparentPolicy);
+ spyOn(opaqueActivity.mAppCompatController.getTransparentPolicy());
}
void configureTopActivityAsEmbedded() {
@@ -360,7 +360,7 @@
if (addToTask) {
mTask.addChild(newActivity);
}
- spyOn(newActivity.mTransparentPolicy);
+ spyOn(newActivity.mAppCompatController.getTransparentPolicy());
mActivityStack.pushActivity(newActivity);
}
@@ -406,31 +406,34 @@
}
void checkTopActivityPolicyStateIsRunning() {
- assertTrue(mActivityStack.top().mTransparentPolicy.isRunning());
+ assertTrue(mActivityStack.top().mAppCompatController
+ .getTransparentPolicy().isRunning());
}
void checkTopActivityPolicyStateIsNotRunning() {
- assertFalse(mActivityStack.top().mTransparentPolicy.isRunning());
+ assertFalse(mActivityStack.top().mAppCompatController
+ .getTransparentPolicy().isRunning());
}
void checkTopActivityPolicyStopInvoked() {
- verify(mActivityStack.top().mTransparentPolicy).stop();
+ verify(mActivityStack.top().mAppCompatController.getTransparentPolicy()).stop();
}
void checkTopActivityPolicyStopNotInvoked() {
mActivityStack.applyToTop((activity) -> {
- verify(activity.mTransparentPolicy, never()).stop();
+ verify(activity.mAppCompatController.getTransparentPolicy(), never()).stop();
});
}
void checkTopActivityPolicyStartInvoked() {
mActivityStack.applyToTop((activity) -> {
- verify(activity.mTransparentPolicy).start();
+ verify(activity.mAppCompatController.getTransparentPolicy()).start();
});
}
void checkTopActivityPolicyStartNotInvoked() {
- verify(mActivityStack.top().mTransparentPolicy, never()).start();
+ verify(mActivityStack.top().mAppCompatController.getTransparentPolicy(),
+ never()).start();
}
void assertTrueOnActivity(int fromTop, Predicate<ActivityRecord> predicate) {
@@ -505,7 +508,7 @@
void clearInteractions() {
mActivityStack.applyToAll((activity) -> {
clearInvocations(activity);
- clearInvocations(activity.mTransparentPolicy);
+ clearInvocations(activity.mAppCompatController.getTransparentPolicy());
});
}
diff --git a/tests/BootImageProfileTest/OWNERS b/tests/BootImageProfileTest/OWNERS
index 57303e7..64775f8 100644
--- a/tests/BootImageProfileTest/OWNERS
+++ b/tests/BootImageProfileTest/OWNERS
@@ -1,4 +1 @@
-calin@google.com
-ngeoffray@google.com
-vmarko@google.com
-yawanng@google.com
+include platform/art:main:/OWNERS_boot_profile
diff --git a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/AppInfo.java b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/AppInfo.java
index 129733e..f397225 100644
--- a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/AppInfo.java
+++ b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/AppInfo.java
@@ -25,99 +25,42 @@
/** AppInfo representation */
public class AppInfo implements AslMarshallable {
- private final String mTitle;
- private final String mDescription;
- private final Boolean mContainsAds;
- private final Boolean mObeyAps;
- private final Boolean mAdsFingerprinting;
- private final Boolean mSecurityFingerprinting;
+ private final Boolean mApsCompliant;
private final String mPrivacyPolicy;
- private final List<String> mSecurityEndpoints;
private final List<String> mFirstPartyEndpoints;
private final List<String> mServiceProviderEndpoints;
- private final String mCategory;
- private final String mEmail;
- private final String mWebsite;
public AppInfo(
- String title,
- String description,
- Boolean containsAds,
- Boolean obeyAps,
- Boolean adsFingerprinting,
- Boolean securityFingerprinting,
+ Boolean apsCompliant,
String privacyPolicy,
- List<String> securityEndpoints,
List<String> firstPartyEndpoints,
- List<String> serviceProviderEndpoints,
- String category,
- String email,
- String website) {
- this.mTitle = title;
- this.mDescription = description;
- this.mContainsAds = containsAds;
- this.mObeyAps = obeyAps;
- this.mAdsFingerprinting = adsFingerprinting;
- this.mSecurityFingerprinting = securityFingerprinting;
+ List<String> serviceProviderEndpoints) {
+ this.mApsCompliant = apsCompliant;
this.mPrivacyPolicy = privacyPolicy;
- this.mSecurityEndpoints = securityEndpoints;
this.mFirstPartyEndpoints = firstPartyEndpoints;
this.mServiceProviderEndpoints = serviceProviderEndpoints;
- this.mCategory = category;
- this.mEmail = email;
- this.mWebsite = website;
}
/** Creates an on-device DOM element from the {@link SafetyLabels}. */
@Override
public List<Element> toOdDomElements(Document doc) {
Element appInfoEle = XmlUtils.createPbundleEleWithName(doc, XmlUtils.OD_NAME_APP_INFO);
- if (this.mTitle != null) {
- appInfoEle.appendChild(XmlUtils.createOdStringEle(doc, XmlUtils.OD_NAME_TITLE, mTitle));
- }
- if (this.mDescription != null) {
- appInfoEle.appendChild(
- XmlUtils.createOdStringEle(doc, XmlUtils.OD_NAME_DESCRIPTION, mDescription));
- }
- if (this.mContainsAds != null) {
- appInfoEle.appendChild(
- XmlUtils.createOdBooleanEle(doc, XmlUtils.OD_NAME_CONTAINS_ADS, mContainsAds));
- }
- if (this.mObeyAps != null) {
- appInfoEle.appendChild(
- XmlUtils.createOdBooleanEle(doc, XmlUtils.OD_NAME_OBEY_APS, mObeyAps));
- }
- if (this.mAdsFingerprinting != null) {
+ if (this.mApsCompliant != null) {
appInfoEle.appendChild(
XmlUtils.createOdBooleanEle(
- doc, XmlUtils.OD_NAME_ADS_FINGERPRINTING, mAdsFingerprinting));
- }
- if (this.mSecurityFingerprinting != null) {
- appInfoEle.appendChild(
- XmlUtils.createOdBooleanEle(
- doc,
- XmlUtils.OD_NAME_SECURITY_FINGERPRINTING,
- mSecurityFingerprinting));
+ doc, XmlUtils.OD_NAME_APS_COMPLIANT, mApsCompliant));
}
if (this.mPrivacyPolicy != null) {
appInfoEle.appendChild(
XmlUtils.createOdStringEle(
doc, XmlUtils.OD_NAME_PRIVACY_POLICY, mPrivacyPolicy));
}
- if (this.mSecurityEndpoints != null) {
- appInfoEle.appendChild(
- XmlUtils.createOdArray(
- doc,
- XmlUtils.OD_TAG_STRING_ARRAY,
- XmlUtils.OD_NAME_SECURITY_ENDPOINT,
- mSecurityEndpoints));
- }
if (this.mFirstPartyEndpoints != null) {
appInfoEle.appendChild(
XmlUtils.createOdArray(
doc,
XmlUtils.OD_TAG_STRING_ARRAY,
- XmlUtils.OD_NAME_FIRST_PARTY_ENDPOINT,
+ XmlUtils.OD_NAME_FIRST_PARTY_ENDPOINTS,
mFirstPartyEndpoints));
}
if (this.mServiceProviderEndpoints != null) {
@@ -125,21 +68,9 @@
XmlUtils.createOdArray(
doc,
XmlUtils.OD_TAG_STRING_ARRAY,
- XmlUtils.OD_NAME_SERVICE_PROVIDER_ENDPOINT,
+ XmlUtils.OD_NAME_SERVICE_PROVIDER_ENDPOINTS,
mServiceProviderEndpoints));
}
- if (this.mCategory != null) {
- appInfoEle.appendChild(
- XmlUtils.createOdStringEle(doc, XmlUtils.OD_NAME_CATEGORY, this.mCategory));
- }
- if (this.mEmail != null) {
- appInfoEle.appendChild(
- XmlUtils.createOdStringEle(doc, XmlUtils.OD_NAME_EMAIL, this.mEmail));
- }
- if (this.mWebsite != null) {
- appInfoEle.appendChild(
- XmlUtils.createOdStringEle(doc, XmlUtils.OD_NAME_WEBSITE, this.mWebsite));
- }
return XmlUtils.listOf(appInfoEle);
}
@@ -147,54 +78,28 @@
@Override
public List<Element> toHrDomElements(Document doc) {
Element appInfoEle = doc.createElement(XmlUtils.HR_TAG_APP_INFO);
- if (this.mTitle != null) {
- appInfoEle.setAttribute(XmlUtils.HR_ATTR_TITLE, this.mTitle);
- }
- if (this.mDescription != null) {
- appInfoEle.setAttribute(XmlUtils.HR_ATTR_DESCRIPTION, this.mDescription);
- }
- if (this.mContainsAds != null) {
+ if (this.mApsCompliant != null) {
appInfoEle.setAttribute(
- XmlUtils.HR_ATTR_CONTAINS_ADS, String.valueOf(this.mContainsAds));
- }
- if (this.mObeyAps != null) {
- appInfoEle.setAttribute(XmlUtils.HR_ATTR_OBEY_APS, String.valueOf(this.mObeyAps));
- }
- if (this.mAdsFingerprinting != null) {
- appInfoEle.setAttribute(
- XmlUtils.HR_ATTR_ADS_FINGERPRINTING, String.valueOf(this.mAdsFingerprinting));
- }
- if (this.mSecurityFingerprinting != null) {
- appInfoEle.setAttribute(
- XmlUtils.HR_ATTR_SECURITY_FINGERPRINTING,
- String.valueOf(this.mSecurityFingerprinting));
+ XmlUtils.HR_ATTR_APS_COMPLIANT, String.valueOf(this.mApsCompliant));
}
if (this.mPrivacyPolicy != null) {
appInfoEle.setAttribute(XmlUtils.HR_ATTR_PRIVACY_POLICY, this.mPrivacyPolicy);
}
- if (this.mSecurityEndpoints != null) {
- appInfoEle.setAttribute(
- XmlUtils.HR_ATTR_SECURITY_ENDPOINTS, String.join("|", this.mSecurityEndpoints));
- }
+
if (this.mFirstPartyEndpoints != null) {
- appInfoEle.setAttribute(
- XmlUtils.HR_ATTR_FIRST_PARTY_ENDPOINTS,
- String.join("|", this.mFirstPartyEndpoints));
+ appInfoEle.appendChild(
+ XmlUtils.createHrArray(
+ doc, XmlUtils.HR_TAG_FIRST_PARTY_ENDPOINTS, mFirstPartyEndpoints));
}
+
if (this.mServiceProviderEndpoints != null) {
- appInfoEle.setAttribute(
- XmlUtils.HR_ATTR_SERVICE_PROVIDER_ENDPOINTS,
- String.join("|", this.mServiceProviderEndpoints));
+ appInfoEle.appendChild(
+ XmlUtils.createHrArray(
+ doc,
+ XmlUtils.HR_TAG_SERVICE_PROVIDER_ENDPOINTS,
+ mServiceProviderEndpoints));
}
- if (this.mCategory != null) {
- appInfoEle.setAttribute(XmlUtils.HR_ATTR_CATEGORY, this.mCategory);
- }
- if (this.mEmail != null) {
- appInfoEle.setAttribute(XmlUtils.HR_ATTR_EMAIL, this.mEmail);
- }
- if (this.mWebsite != null) {
- appInfoEle.setAttribute(XmlUtils.HR_ATTR_WEBSITE, this.mWebsite);
- }
+
return XmlUtils.listOf(appInfoEle);
}
}
diff --git a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/AppInfoFactory.java b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/AppInfoFactory.java
index c506961..6ad2027 100644
--- a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/AppInfoFactory.java
+++ b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/AppInfoFactory.java
@@ -35,43 +35,19 @@
return null;
}
- String title = XmlUtils.getStringAttr(appInfoEle, XmlUtils.HR_ATTR_TITLE, true);
- String description = XmlUtils.getStringAttr(appInfoEle, XmlUtils.HR_ATTR_DESCRIPTION, true);
- Boolean containsAds = XmlUtils.getBoolAttr(appInfoEle, XmlUtils.HR_ATTR_CONTAINS_ADS, true);
- Boolean obeyAps = XmlUtils.getBoolAttr(appInfoEle, XmlUtils.HR_ATTR_OBEY_APS, true);
- Boolean adsFingerprinting =
- XmlUtils.getBoolAttr(appInfoEle, XmlUtils.HR_ATTR_ADS_FINGERPRINTING, true);
- Boolean securityFingerprinting =
- XmlUtils.getBoolAttr(appInfoEle, XmlUtils.HR_ATTR_SECURITY_FINGERPRINTING, true);
+ Boolean apsCompliant =
+ XmlUtils.getBoolAttr(appInfoEle, XmlUtils.HR_ATTR_APS_COMPLIANT, true);
String privacyPolicy =
XmlUtils.getStringAttr(appInfoEle, XmlUtils.HR_ATTR_PRIVACY_POLICY, true);
- List<String> securityEndpoints =
- XmlUtils.getPipelineSplitAttr(
- appInfoEle, XmlUtils.HR_ATTR_SECURITY_ENDPOINTS, true);
List<String> firstPartyEndpoints =
- XmlUtils.getPipelineSplitAttr(
- appInfoEle, XmlUtils.HR_ATTR_FIRST_PARTY_ENDPOINTS, true);
+ XmlUtils.getHrItemsAsStrings(
+ appInfoEle, XmlUtils.HR_TAG_FIRST_PARTY_ENDPOINTS, true);
List<String> serviceProviderEndpoints =
- XmlUtils.getPipelineSplitAttr(
- appInfoEle, XmlUtils.HR_ATTR_SERVICE_PROVIDER_ENDPOINTS, true);
- String category = XmlUtils.getStringAttr(appInfoEle, XmlUtils.HR_ATTR_CATEGORY, true);
- String email = XmlUtils.getStringAttr(appInfoEle, XmlUtils.HR_ATTR_EMAIL, true);
- String website = XmlUtils.getStringAttr(appInfoEle, XmlUtils.HR_ATTR_WEBSITE, false);
+ XmlUtils.getHrItemsAsStrings(
+ appInfoEle, XmlUtils.HR_TAG_SERVICE_PROVIDER_ENDPOINTS, true);
return new AppInfo(
- title,
- description,
- containsAds,
- obeyAps,
- adsFingerprinting,
- securityFingerprinting,
- privacyPolicy,
- securityEndpoints,
- firstPartyEndpoints,
- serviceProviderEndpoints,
- category,
- email,
- website);
+ apsCompliant, privacyPolicy, firstPartyEndpoints, serviceProviderEndpoints);
}
/** Creates an {@link AslMarshallableFactory} from on-device DOM elements */
@@ -83,42 +59,17 @@
return null;
}
- String title = XmlUtils.getOdStringEle(appInfoEle, XmlUtils.OD_NAME_TITLE, true);
- String description =
- XmlUtils.getOdStringEle(appInfoEle, XmlUtils.OD_NAME_DESCRIPTION, true);
- Boolean containsAds =
- XmlUtils.getOdBoolEle(appInfoEle, XmlUtils.OD_NAME_CONTAINS_ADS, true);
- Boolean obeyAps = XmlUtils.getOdBoolEle(appInfoEle, XmlUtils.OD_NAME_OBEY_APS, true);
- Boolean adsFingerprinting =
- XmlUtils.getOdBoolEle(appInfoEle, XmlUtils.OD_NAME_ADS_FINGERPRINTING, true);
- Boolean securityFingerprinting =
- XmlUtils.getOdBoolEle(appInfoEle, XmlUtils.OD_NAME_SECURITY_FINGERPRINTING, true);
+ Boolean apsCompliant =
+ XmlUtils.getOdBoolEle(appInfoEle, XmlUtils.OD_NAME_APS_COMPLIANT, true);
String privacyPolicy =
XmlUtils.getOdStringEle(appInfoEle, XmlUtils.OD_NAME_PRIVACY_POLICY, true);
- List<String> securityEndpoints =
- XmlUtils.getOdStringArray(appInfoEle, XmlUtils.OD_NAME_SECURITY_ENDPOINT, true);
List<String> firstPartyEndpoints =
- XmlUtils.getOdStringArray(appInfoEle, XmlUtils.OD_NAME_FIRST_PARTY_ENDPOINT, true);
+ XmlUtils.getOdStringArray(appInfoEle, XmlUtils.OD_NAME_FIRST_PARTY_ENDPOINTS, true);
List<String> serviceProviderEndpoints =
XmlUtils.getOdStringArray(
- appInfoEle, XmlUtils.OD_NAME_SERVICE_PROVIDER_ENDPOINT, true);
- String category = XmlUtils.getOdStringEle(appInfoEle, XmlUtils.OD_NAME_CATEGORY, true);
- String email = XmlUtils.getOdStringEle(appInfoEle, XmlUtils.OD_NAME_EMAIL, true);
- String website = XmlUtils.getOdStringEle(appInfoEle, XmlUtils.OD_NAME_WEBSITE, false);
+ appInfoEle, XmlUtils.OD_NAME_SERVICE_PROVIDER_ENDPOINTS, true);
return new AppInfo(
- title,
- description,
- containsAds,
- obeyAps,
- adsFingerprinting,
- securityFingerprinting,
- privacyPolicy,
- securityEndpoints,
- firstPartyEndpoints,
- serviceProviderEndpoints,
- category,
- email,
- website);
+ apsCompliant, privacyPolicy, firstPartyEndpoints, serviceProviderEndpoints);
}
}
diff --git a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/DeveloperInfo.java b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/DeveloperInfo.java
deleted file mode 100644
index 94fad96..0000000
--- a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/DeveloperInfo.java
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * Copyright (C) 2024 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.
- */
-
-package com.android.asllib.marshallable;
-
-import com.android.asllib.util.XmlUtils;
-
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-
-import java.util.List;
-
-/** DeveloperInfo representation */
-public class DeveloperInfo implements AslMarshallable {
- public enum DeveloperRelationship {
- OEM(0),
- ODM(1),
- SOC(2),
- OTA(3),
- CARRIER(4),
- AOSP(5),
- OTHER(6);
-
- private final int mValue;
-
- DeveloperRelationship(int value) {
- this.mValue = value;
- }
-
- /** Get the int value associated with the DeveloperRelationship. */
- public int getValue() {
- return mValue;
- }
-
- /** Get the DeveloperRelationship associated with the int value. */
- public static DeveloperInfo.DeveloperRelationship forValue(int value) {
- for (DeveloperInfo.DeveloperRelationship e : values()) {
- if (e.getValue() == value) {
- return e;
- }
- }
- throw new IllegalArgumentException("No DeveloperRelationship enum for value: " + value);
- }
-
- /** Get the DeveloperRelationship associated with the human-readable String. */
- public static DeveloperInfo.DeveloperRelationship forString(String s) {
- for (DeveloperInfo.DeveloperRelationship e : values()) {
- if (e.toString().equals(s)) {
- return e;
- }
- }
- throw new IllegalArgumentException("No DeveloperRelationship enum for str: " + s);
- }
-
- /** Human-readable String representation of DeveloperRelationship. */
- public String toString() {
- return this.name().toLowerCase();
- }
- }
-
- private final String mName;
- private final String mEmail;
- private final String mAddress;
- private final String mCountryRegion;
- private final DeveloperRelationship mDeveloperRelationship;
- private final String mWebsite;
- private final String mAppDeveloperRegistryId;
-
- public DeveloperInfo(
- String name,
- String email,
- String address,
- String countryRegion,
- DeveloperRelationship developerRelationship,
- String website,
- String appDeveloperRegistryId) {
- this.mName = name;
- this.mEmail = email;
- this.mAddress = address;
- this.mCountryRegion = countryRegion;
- this.mDeveloperRelationship = developerRelationship;
- this.mWebsite = website;
- this.mAppDeveloperRegistryId = appDeveloperRegistryId;
- }
-
- /** Creates an on-device DOM element from the {@link SafetyLabels}. */
- @Override
- public List<Element> toOdDomElements(Document doc) {
- Element developerInfoEle =
- XmlUtils.createPbundleEleWithName(doc, XmlUtils.OD_NAME_DEVELOPER_INFO);
- if (mName != null) {
- developerInfoEle.appendChild(
- XmlUtils.createOdStringEle(doc, XmlUtils.OD_NAME_NAME, mName));
- }
- if (mEmail != null) {
- developerInfoEle.appendChild(
- XmlUtils.createOdStringEle(doc, XmlUtils.OD_NAME_EMAIL, mEmail));
- }
- if (mAddress != null) {
- developerInfoEle.appendChild(
- XmlUtils.createOdStringEle(doc, XmlUtils.OD_NAME_ADDRESS, mAddress));
- }
- if (mCountryRegion != null) {
- developerInfoEle.appendChild(
- XmlUtils.createOdStringEle(
- doc, XmlUtils.OD_NAME_COUNTRY_REGION, mCountryRegion));
- }
- if (mDeveloperRelationship != null) {
- developerInfoEle.appendChild(
- XmlUtils.createOdLongEle(
- doc,
- XmlUtils.OD_NAME_DEVELOPER_RELATIONSHIP,
- mDeveloperRelationship.getValue()));
- }
- if (mWebsite != null) {
- developerInfoEle.appendChild(
- XmlUtils.createOdStringEle(doc, XmlUtils.OD_NAME_WEBSITE, mWebsite));
- }
- if (mAppDeveloperRegistryId != null) {
- developerInfoEle.appendChild(
- XmlUtils.createOdStringEle(
- doc,
- XmlUtils.OD_NAME_APP_DEVELOPER_REGISTRY_ID,
- mAppDeveloperRegistryId));
- }
-
- return XmlUtils.listOf(developerInfoEle);
- }
-
- /** Creates the human-readable DOM elements from the AslMarshallable Java Object. */
- @Override
- public List<Element> toHrDomElements(Document doc) {
- Element developerInfoEle = doc.createElement(XmlUtils.HR_TAG_DEVELOPER_INFO);
- if (mName != null) {
- developerInfoEle.setAttribute(XmlUtils.HR_ATTR_NAME, mName);
- }
- if (mEmail != null) {
- developerInfoEle.setAttribute(XmlUtils.HR_ATTR_EMAIL, mEmail);
- }
- if (mAddress != null) {
- developerInfoEle.setAttribute(XmlUtils.HR_ATTR_ADDRESS, mAddress);
- }
- if (mCountryRegion != null) {
- developerInfoEle.setAttribute(XmlUtils.HR_ATTR_COUNTRY_REGION, mCountryRegion);
- }
- if (mDeveloperRelationship != null) {
- developerInfoEle.setAttribute(
- XmlUtils.HR_ATTR_DEVELOPER_RELATIONSHIP, mDeveloperRelationship.toString());
- }
- if (mWebsite != null) {
- developerInfoEle.setAttribute(XmlUtils.HR_ATTR_WEBSITE, mWebsite);
- }
- if (mAppDeveloperRegistryId != null) {
- developerInfoEle.setAttribute(
- XmlUtils.HR_ATTR_APP_DEVELOPER_REGISTRY_ID, mAppDeveloperRegistryId);
- }
-
- return XmlUtils.listOf(developerInfoEle);
- }
-}
diff --git a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/DeveloperInfoFactory.java b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/DeveloperInfoFactory.java
deleted file mode 100644
index 0f3b41c..0000000
--- a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/DeveloperInfoFactory.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (C) 2024 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.
- */
-
-package com.android.asllib.marshallable;
-
-import com.android.asllib.util.AslgenUtil;
-import com.android.asllib.util.MalformedXmlException;
-import com.android.asllib.util.XmlUtils;
-
-import org.w3c.dom.Element;
-
-import java.util.List;
-
-public class DeveloperInfoFactory implements AslMarshallableFactory<DeveloperInfo> {
-
- /** Creates a {@link DeveloperInfo} from the human-readable DOM element. */
- @Override
- public DeveloperInfo createFromHrElements(List<Element> elements) throws MalformedXmlException {
- Element developerInfoEle = XmlUtils.getSingleElement(elements);
- if (developerInfoEle == null) {
- AslgenUtil.logI("No DeveloperInfo found in hr format.");
- return null;
- }
- String name = XmlUtils.getStringAttr(developerInfoEle, XmlUtils.HR_ATTR_NAME, true);
- String email = XmlUtils.getStringAttr(developerInfoEle, XmlUtils.HR_ATTR_EMAIL, true);
- String address = XmlUtils.getStringAttr(developerInfoEle, XmlUtils.HR_ATTR_ADDRESS, true);
- String countryRegion =
- XmlUtils.getStringAttr(developerInfoEle, XmlUtils.HR_ATTR_COUNTRY_REGION, true);
- DeveloperInfo.DeveloperRelationship developerRelationship =
- DeveloperInfo.DeveloperRelationship.forString(
- XmlUtils.getStringAttr(
- developerInfoEle, XmlUtils.HR_ATTR_DEVELOPER_RELATIONSHIP, true));
- String website = XmlUtils.getStringAttr(developerInfoEle, XmlUtils.HR_ATTR_WEBSITE, false);
- String appDeveloperRegistryId =
- XmlUtils.getStringAttr(
- developerInfoEle, XmlUtils.HR_ATTR_APP_DEVELOPER_REGISTRY_ID, false);
-
- return new DeveloperInfo(
- name,
- email,
- address,
- countryRegion,
- developerRelationship,
- website,
- appDeveloperRegistryId);
- }
-
- /** Creates an {@link AslMarshallableFactory} from on-device DOM elements */
- @Override
- public DeveloperInfo createFromOdElements(List<Element> elements) throws MalformedXmlException {
- Element developerInfoEle = XmlUtils.getSingleElement(elements);
- if (developerInfoEle == null) {
- AslgenUtil.logI("No DeveloperInfo found in od format.");
- return null;
- }
- String name = XmlUtils.getOdStringEle(developerInfoEle, XmlUtils.OD_NAME_NAME, true);
- String email = XmlUtils.getOdStringEle(developerInfoEle, XmlUtils.OD_NAME_EMAIL, true);
- String address = XmlUtils.getOdStringEle(developerInfoEle, XmlUtils.OD_NAME_ADDRESS, true);
- String countryRegion =
- XmlUtils.getOdStringEle(developerInfoEle, XmlUtils.OD_NAME_COUNTRY_REGION, true);
- DeveloperInfo.DeveloperRelationship developerRelationship =
- DeveloperInfo.DeveloperRelationship.forValue(
- (int)
- (long)
- XmlUtils.getOdLongEle(
- developerInfoEle,
- XmlUtils.OD_NAME_DEVELOPER_RELATIONSHIP,
- true));
- String website = XmlUtils.getOdStringEle(developerInfoEle, XmlUtils.OD_NAME_WEBSITE, false);
- String appDeveloperRegistryId =
- XmlUtils.getOdStringEle(
- developerInfoEle, XmlUtils.OD_NAME_APP_DEVELOPER_REGISTRY_ID, false);
-
- return new DeveloperInfo(
- name,
- email,
- address,
- countryRegion,
- developerRelationship,
- website,
- appDeveloperRegistryId);
- }
-}
diff --git a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/SafetyLabels.java b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/SafetyLabels.java
index 6af8071..2a4e130 100644
--- a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/SafetyLabels.java
+++ b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/SafetyLabels.java
@@ -25,21 +25,10 @@
/** Safety Label representation containing zero or more {@link DataCategory} for data shared */
public class SafetyLabels implements AslMarshallable {
-
- private final Long mVersion;
private final DataLabels mDataLabels;
- private final SecurityLabels mSecurityLabels;
- private final ThirdPartyVerification mThirdPartyVerification;
- public SafetyLabels(
- Long version,
- DataLabels dataLabels,
- SecurityLabels securityLabels,
- ThirdPartyVerification thirdPartyVerification) {
- this.mVersion = version;
+ public SafetyLabels(DataLabels dataLabels) {
this.mDataLabels = dataLabels;
- this.mSecurityLabels = securityLabels;
- this.mThirdPartyVerification = thirdPartyVerification;
}
/** Returns the data label for the safety label */
@@ -47,27 +36,14 @@
return mDataLabels;
}
- /** Gets the version of the {@link SafetyLabels}. */
- public Long getVersion() {
- return mVersion;
- }
-
/** Creates an on-device DOM element from the {@link SafetyLabels}. */
@Override
public List<Element> toOdDomElements(Document doc) {
Element safetyLabelsEle =
XmlUtils.createPbundleEleWithName(doc, XmlUtils.OD_NAME_SAFETY_LABELS);
- safetyLabelsEle.appendChild(
- XmlUtils.createOdLongEle(doc, XmlUtils.OD_NAME_VERSION, mVersion));
if (mDataLabels != null) {
XmlUtils.appendChildren(safetyLabelsEle, mDataLabels.toOdDomElements(doc));
}
- if (mSecurityLabels != null) {
- XmlUtils.appendChildren(safetyLabelsEle, mSecurityLabels.toOdDomElements(doc));
- }
- if (mThirdPartyVerification != null) {
- XmlUtils.appendChildren(safetyLabelsEle, mThirdPartyVerification.toOdDomElements(doc));
- }
return XmlUtils.listOf(safetyLabelsEle);
}
@@ -75,17 +51,10 @@
@Override
public List<Element> toHrDomElements(Document doc) {
Element safetyLabelsEle = doc.createElement(XmlUtils.HR_TAG_SAFETY_LABELS);
- safetyLabelsEle.setAttribute(XmlUtils.HR_ATTR_VERSION, String.valueOf(mVersion));
if (mDataLabels != null) {
XmlUtils.appendChildren(safetyLabelsEle, mDataLabels.toHrDomElements(doc));
}
- if (mSecurityLabels != null) {
- XmlUtils.appendChildren(safetyLabelsEle, mSecurityLabels.toHrDomElements(doc));
- }
- if (mThirdPartyVerification != null) {
- XmlUtils.appendChildren(safetyLabelsEle, mThirdPartyVerification.toHrDomElements(doc));
- }
return XmlUtils.listOf(safetyLabelsEle);
}
}
diff --git a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/SafetyLabelsFactory.java b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/SafetyLabelsFactory.java
index 2644b43..2738337 100644
--- a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/SafetyLabelsFactory.java
+++ b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/SafetyLabelsFactory.java
@@ -34,7 +34,6 @@
AslgenUtil.logI("No SafetyLabels found in hr format.");
return null;
}
- long version = XmlUtils.tryGetVersion(safetyLabelsEle);
DataLabels dataLabels =
new DataLabelsFactory()
@@ -44,23 +43,7 @@
safetyLabelsEle,
XmlUtils.HR_TAG_DATA_LABELS,
false)));
- SecurityLabels securityLabels =
- new SecurityLabelsFactory()
- .createFromHrElements(
- XmlUtils.listOf(
- XmlUtils.getSingleChildElement(
- safetyLabelsEle,
- XmlUtils.HR_TAG_SECURITY_LABELS,
- false)));
- ThirdPartyVerification thirdPartyVerification =
- new ThirdPartyVerificationFactory()
- .createFromHrElements(
- XmlUtils.listOf(
- XmlUtils.getSingleChildElement(
- safetyLabelsEle,
- XmlUtils.HR_TAG_THIRD_PARTY_VERIFICATION,
- false)));
- return new SafetyLabels(version, dataLabels, securityLabels, thirdPartyVerification);
+ return new SafetyLabels(dataLabels);
}
/** Creates an {@link AslMarshallableFactory} from on-device DOM elements */
@@ -71,7 +54,6 @@
AslgenUtil.logI("No SafetyLabels found in od format.");
return null;
}
- Long version = XmlUtils.getOdLongEle(safetyLabelsEle, XmlUtils.OD_NAME_VERSION, true);
DataLabels dataLabels =
new DataLabelsFactory()
@@ -81,22 +63,7 @@
safetyLabelsEle,
XmlUtils.OD_NAME_DATA_LABELS,
false)));
- SecurityLabels securityLabels =
- new SecurityLabelsFactory()
- .createFromOdElements(
- XmlUtils.listOf(
- XmlUtils.getOdPbundleWithName(
- safetyLabelsEle,
- XmlUtils.OD_NAME_SECURITY_LABELS,
- false)));
- ThirdPartyVerification thirdPartyVerification =
- new ThirdPartyVerificationFactory()
- .createFromOdElements(
- XmlUtils.listOf(
- XmlUtils.getOdPbundleWithName(
- safetyLabelsEle,
- XmlUtils.OD_NAME_THIRD_PARTY_VERIFICATION,
- false)));
- return new SafetyLabels(version, dataLabels, securityLabels, thirdPartyVerification);
+
+ return new SafetyLabels(dataLabels);
}
}
diff --git a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/TransparencyInfo.java b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/TransparencyInfo.java
index 6a8700a..9f789f0 100644
--- a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/TransparencyInfo.java
+++ b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/TransparencyInfo.java
@@ -23,22 +23,14 @@
import java.util.List;
-/** TransparencyInfo representation containing {@link DeveloperInfo} and {@link AppInfo} */
+/** TransparencyInfo representation containing {@link AppInfo} */
public class TransparencyInfo implements AslMarshallable {
-
- private final DeveloperInfo mDeveloperInfo;
private final AppInfo mAppInfo;
- public TransparencyInfo(DeveloperInfo developerInfo, AppInfo appInfo) {
- this.mDeveloperInfo = developerInfo;
+ public TransparencyInfo(AppInfo appInfo) {
this.mAppInfo = appInfo;
}
- /** Gets the {@link DeveloperInfo} of the {@link TransparencyInfo}. */
- public DeveloperInfo getDeveloperInfo() {
- return mDeveloperInfo;
- }
-
/** Gets the {@link AppInfo} of the {@link TransparencyInfo}. */
public AppInfo getAppInfo() {
return mAppInfo;
@@ -49,9 +41,6 @@
public List<Element> toOdDomElements(Document doc) {
Element transparencyInfoEle =
XmlUtils.createPbundleEleWithName(doc, XmlUtils.OD_NAME_TRANSPARENCY_INFO);
- if (mDeveloperInfo != null) {
- XmlUtils.appendChildren(transparencyInfoEle, mDeveloperInfo.toOdDomElements(doc));
- }
if (mAppInfo != null) {
XmlUtils.appendChildren(transparencyInfoEle, mAppInfo.toOdDomElements(doc));
}
@@ -62,9 +51,6 @@
@Override
public List<Element> toHrDomElements(Document doc) {
Element transparencyInfoEle = doc.createElement(XmlUtils.HR_TAG_TRANSPARENCY_INFO);
- if (mDeveloperInfo != null) {
- XmlUtils.appendChildren(transparencyInfoEle, mDeveloperInfo.toHrDomElements(doc));
- }
if (mAppInfo != null) {
XmlUtils.appendChildren(transparencyInfoEle, mAppInfo.toHrDomElements(doc));
}
diff --git a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/TransparencyInfoFactory.java b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/TransparencyInfoFactory.java
index 94c5640..40f2872 100644
--- a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/TransparencyInfoFactory.java
+++ b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/marshallable/TransparencyInfoFactory.java
@@ -36,18 +36,11 @@
return null;
}
- Element developerInfoEle =
- XmlUtils.getSingleChildElement(
- transparencyInfoEle, XmlUtils.HR_TAG_DEVELOPER_INFO, false);
- DeveloperInfo developerInfo =
- new DeveloperInfoFactory().createFromHrElements(XmlUtils.listOf(developerInfoEle));
-
Element appInfoEle =
- XmlUtils.getSingleChildElement(
- transparencyInfoEle, XmlUtils.HR_TAG_APP_INFO, false);
+ XmlUtils.getSingleChildElement(transparencyInfoEle, XmlUtils.HR_TAG_APP_INFO, true);
AppInfo appInfo = new AppInfoFactory().createFromHrElements(XmlUtils.listOf(appInfoEle));
- return new TransparencyInfo(developerInfo, appInfo);
+ return new TransparencyInfo(appInfo);
}
/** Creates an {@link AslMarshallableFactory} from on-device DOM elements */
@@ -60,17 +53,10 @@
return null;
}
- Element developerInfoEle =
- XmlUtils.getOdPbundleWithName(
- transparencyInfoEle, XmlUtils.OD_NAME_DEVELOPER_INFO, false);
- DeveloperInfo developerInfo =
- new DeveloperInfoFactory().createFromOdElements(XmlUtils.listOf(developerInfoEle));
-
Element appInfoEle =
- XmlUtils.getOdPbundleWithName(
- transparencyInfoEle, XmlUtils.OD_NAME_APP_INFO, false);
+ XmlUtils.getOdPbundleWithName(transparencyInfoEle, XmlUtils.OD_NAME_APP_INFO, true);
AppInfo appInfo = new AppInfoFactory().createFromOdElements(XmlUtils.listOf(appInfoEle));
- return new TransparencyInfo(developerInfo, appInfo);
+ return new TransparencyInfo(appInfo);
}
}
diff --git a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/util/XmlUtils.java b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/util/XmlUtils.java
index 97cbc39..26b5639 100644
--- a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/util/XmlUtils.java
+++ b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/util/XmlUtils.java
@@ -42,6 +42,7 @@
public static final String HR_TAG_DATA_COLLECTED = "data-collected";
public static final String HR_TAG_DATA_COLLECTED_EPHEMERAL = "data-collected-ephemeral";
public static final String HR_TAG_DATA_SHARED = "data-shared";
+ public static final String HR_TAG_ITEM = "item";
public static final String HR_ATTR_NAME = "name";
public static final String HR_ATTR_EMAIL = "email";
public static final String HR_ATTR_ADDRESS = "address";
@@ -64,12 +65,13 @@
public static final String HR_ATTR_DESCRIPTION = "description";
public static final String HR_ATTR_CONTAINS_ADS = "containsAds";
public static final String HR_ATTR_OBEY_APS = "obeyAps";
+ public static final String HR_ATTR_APS_COMPLIANT = "apsCompliant";
public static final String HR_ATTR_ADS_FINGERPRINTING = "adsFingerprinting";
public static final String HR_ATTR_SECURITY_FINGERPRINTING = "securityFingerprinting";
public static final String HR_ATTR_PRIVACY_POLICY = "privacyPolicy";
public static final String HR_ATTR_SECURITY_ENDPOINTS = "securityEndpoints";
- public static final String HR_ATTR_FIRST_PARTY_ENDPOINTS = "firstPartyEndpoints";
- public static final String HR_ATTR_SERVICE_PROVIDER_ENDPOINTS = "serviceProviderEndpoints";
+ public static final String HR_TAG_FIRST_PARTY_ENDPOINTS = "first-party-endpoints";
+ public static final String HR_TAG_SERVICE_PROVIDER_ENDPOINTS = "service-provider-endpoints";
public static final String HR_ATTR_CATEGORY = "category";
public static final String OD_TAG_BUNDLE = "bundle";
@@ -98,12 +100,13 @@
public static final String OD_NAME_DESCRIPTION = "description";
public static final String OD_NAME_CONTAINS_ADS = "contains_ads";
public static final String OD_NAME_OBEY_APS = "obey_aps";
+ public static final String OD_NAME_APS_COMPLIANT = "aps_compliant";
public static final String OD_NAME_ADS_FINGERPRINTING = "ads_fingerprinting";
public static final String OD_NAME_SECURITY_FINGERPRINTING = "security_fingerprinting";
public static final String OD_NAME_PRIVACY_POLICY = "privacy_policy";
- public static final String OD_NAME_SECURITY_ENDPOINT = "security_endpoint";
- public static final String OD_NAME_FIRST_PARTY_ENDPOINT = "first_party_endpoint";
- public static final String OD_NAME_SERVICE_PROVIDER_ENDPOINT = "service_provider_endpoint";
+ public static final String OD_NAME_SECURITY_ENDPOINT = "security_endpoints";
+ public static final String OD_NAME_FIRST_PARTY_ENDPOINTS = "first_party_endpoints";
+ public static final String OD_NAME_SERVICE_PROVIDER_ENDPOINTS = "service_provider_endpoints";
public static final String OD_NAME_CATEGORY = "category";
public static final String OD_NAME_VERSION = "version";
public static final String OD_NAME_URL = "url";
@@ -237,7 +240,18 @@
return ele;
}
- /** Create OD style array DOM Element, which can represent any time but is stored as Strings. */
+ /** Create HR style array DOM Element. */
+ public static Element createHrArray(Document doc, String arrayTagName, List<String> arrayVals) {
+ Element arrEle = doc.createElement(arrayTagName);
+ for (String s : arrayVals) {
+ Element itemEle = doc.createElement(XmlUtils.HR_TAG_ITEM);
+ itemEle.setTextContent(s);
+ arrEle.appendChild(itemEle);
+ }
+ return arrEle;
+ }
+
+ /** Create OD style array DOM Element, which can represent any type but is stored as Strings. */
public static Element createOdArray(
Document doc, String arrayTag, String arrayName, List<String> arrayVals) {
Element arrEle = doc.createElement(arrayTag);
@@ -456,6 +470,32 @@
return ints;
}
+ /** Gets human-readable style String array. */
+ public static List<String> getHrItemsAsStrings(
+ Element parent, String elementName, boolean required) throws MalformedXmlException {
+
+ List<Element> arrayEles = XmlUtils.getChildrenByTagName(parent, elementName);
+ if (arrayEles.size() > 1) {
+ throw new MalformedXmlException(
+ String.format(
+ "Found more than one %s in %s.", elementName, parent.getTagName()));
+ }
+ if (arrayEles.isEmpty()) {
+ if (required) {
+ throw new MalformedXmlException(
+ String.format("Found no %s in %s.", elementName, parent.getTagName()));
+ }
+ return null;
+ }
+ Element arrayEle = arrayEles.get(0);
+ List<Element> itemEles = XmlUtils.getChildrenByTagName(arrayEle, XmlUtils.HR_TAG_ITEM);
+ List<String> strs = new ArrayList<String>();
+ for (Element itemEle : itemEles) {
+ strs.add(itemEle.getTextContent());
+ }
+ return strs;
+ }
+
/** Gets on-device style String array. */
public static List<String> getOdStringArray(Element ele, String nameName, boolean required)
throws MalformedXmlException {
diff --git a/tools/app_metadata_bundles/src/test/java/com/android/asllib/AllTests.java b/tools/app_metadata_bundles/src/test/java/com/android/asllib/AllTests.java
index dbeeb49..14e65e5 100644
--- a/tools/app_metadata_bundles/src/test/java/com/android/asllib/AllTests.java
+++ b/tools/app_metadata_bundles/src/test/java/com/android/asllib/AllTests.java
@@ -20,11 +20,8 @@
import com.android.asllib.marshallable.AppInfoTest;
import com.android.asllib.marshallable.DataLabelsTest;
import com.android.asllib.marshallable.DataTypeEqualityTest;
-import com.android.asllib.marshallable.DeveloperInfoTest;
import com.android.asllib.marshallable.SafetyLabelsTest;
-import com.android.asllib.marshallable.SecurityLabelsTest;
import com.android.asllib.marshallable.SystemAppSafetyLabelTest;
-import com.android.asllib.marshallable.ThirdPartyVerificationTest;
import com.android.asllib.marshallable.TransparencyInfoTest;
import org.junit.runner.RunWith;
@@ -35,14 +32,10 @@
AslgenTests.class,
AndroidSafetyLabelTest.class,
AppInfoTest.class,
- // DataCategoryTest.class,
DataLabelsTest.class,
DataTypeEqualityTest.class,
- DeveloperInfoTest.class,
SafetyLabelsTest.class,
- SecurityLabelsTest.class,
SystemAppSafetyLabelTest.class,
- ThirdPartyVerificationTest.class,
TransparencyInfoTest.class
})
public class AllTests {}
diff --git a/tools/app_metadata_bundles/src/test/java/com/android/asllib/marshallable/AppInfoTest.java b/tools/app_metadata_bundles/src/test/java/com/android/asllib/marshallable/AppInfoTest.java
index 9e91c6f..d823c48 100644
--- a/tools/app_metadata_bundles/src/test/java/com/android/asllib/marshallable/AppInfoTest.java
+++ b/tools/app_metadata_bundles/src/test/java/com/android/asllib/marshallable/AppInfoTest.java
@@ -20,6 +20,7 @@
import com.android.asllib.testutils.TestUtils;
import com.android.asllib.util.MalformedXmlException;
+import com.android.asllib.util.XmlUtils;
import org.junit.Before;
import org.junit.Test;
@@ -34,35 +35,15 @@
private static final String APP_INFO_HR_PATH = "com/android/asllib/appinfo/hr";
private static final String APP_INFO_OD_PATH = "com/android/asllib/appinfo/od";
public static final List<String> REQUIRED_FIELD_NAMES =
- List.of(
- "title",
- "description",
- "containsAds",
- "obeyAps",
- "adsFingerprinting",
- "securityFingerprinting",
- "privacyPolicy",
- "securityEndpoints",
- "firstPartyEndpoints",
- "serviceProviderEndpoints",
- "category",
- "email");
+ List.of("apsCompliant", "privacyPolicy");
public static final List<String> REQUIRED_FIELD_NAMES_OD =
- List.of(
- "title",
- "description",
- "contains_ads",
- "obey_aps",
- "ads_fingerprinting",
- "security_fingerprinting",
- "privacy_policy",
- "security_endpoint",
- "first_party_endpoint",
- "service_provider_endpoint",
- "category",
- "email");
- public static final List<String> OPTIONAL_FIELD_NAMES = List.of("website");
- public static final List<String> OPTIONAL_FIELD_NAMES_OD = List.of("website");
+ List.of("aps_compliant", "privacy_policy");
+ public static final List<String> REQUIRED_CHILD_NAMES =
+ List.of("first-party-endpoints", "service-provider-endpoints");
+ public static final List<String> REQUIRED_CHILD_NAMES_OD =
+ List.of("first_party_endpoints", "service_provider_endpoints");
+ public static final List<String> OPTIONAL_FIELD_NAMES = List.of();
+ public static final List<String> OPTIONAL_FIELD_NAMES_OD = List.of();
private static final String ALL_FIELDS_VALID_FILE_NAME = "all-fields-valid.xml";
@@ -110,6 +91,34 @@
}
}
+ /** Tests missing required child fails. */
+ @Test
+ public void testMissingRequiredChild() throws Exception {
+ System.out.println("Starting testMissingRequiredFields");
+ for (String reqChildName : REQUIRED_CHILD_NAMES) {
+ System.out.println("testing missing required child hr: " + reqChildName);
+ var appInfoEle =
+ TestUtils.getElementsFromResource(
+ Paths.get(APP_INFO_HR_PATH, ALL_FIELDS_VALID_FILE_NAME));
+ var child = XmlUtils.getChildrenByTagName(appInfoEle.get(0), reqChildName).get(0);
+ appInfoEle.get(0).removeChild(child);
+ assertThrows(
+ MalformedXmlException.class,
+ () -> new AppInfoFactory().createFromHrElements(appInfoEle));
+ }
+
+ for (String reqField : REQUIRED_CHILD_NAMES_OD) {
+ System.out.println("testing missing required child od: " + reqField);
+ var appInfoEle =
+ TestUtils.getElementsFromResource(
+ Paths.get(APP_INFO_OD_PATH, ALL_FIELDS_VALID_FILE_NAME));
+ TestUtils.removeOdChildEleWithName(appInfoEle.get(0), reqField);
+ assertThrows(
+ MalformedXmlException.class,
+ () -> new AppInfoFactory().createFromOdElements(appInfoEle));
+ }
+ }
+
/** Tests missing optional fields passes. */
@Test
public void testMissingOptionalFields() throws Exception {
diff --git a/tools/app_metadata_bundles/src/test/java/com/android/asllib/marshallable/DeveloperInfoTest.java b/tools/app_metadata_bundles/src/test/java/com/android/asllib/marshallable/DeveloperInfoTest.java
deleted file mode 100644
index 72e8d65..0000000
--- a/tools/app_metadata_bundles/src/test/java/com/android/asllib/marshallable/DeveloperInfoTest.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright (C) 2017 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.
- */
-
-package com.android.asllib.marshallable;
-
-import static org.junit.Assert.assertThrows;
-
-import com.android.asllib.testutils.TestUtils;
-import com.android.asllib.util.MalformedXmlException;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-import java.nio.file.Paths;
-import java.util.List;
-
-@RunWith(JUnit4.class)
-public class DeveloperInfoTest {
- private static final String DEVELOPER_INFO_HR_PATH = "com/android/asllib/developerinfo/hr";
- private static final String DEVELOPER_INFO_OD_PATH = "com/android/asllib/developerinfo/od";
- public static final List<String> REQUIRED_FIELD_NAMES =
- List.of("address", "countryRegion", "email", "name", "relationship");
- public static final List<String> REQUIRED_FIELD_NAMES_OD =
- List.of("address", "country_region", "email", "name", "relationship");
- public static final List<String> OPTIONAL_FIELD_NAMES = List.of("website", "registryId");
- public static final List<String> OPTIONAL_FIELD_NAMES_OD =
- List.of("website", "app_developer_registry_id");
-
- private static final String ALL_FIELDS_VALID_FILE_NAME = "all-fields-valid.xml";
-
- /** Logic for setting up tests (empty if not yet needed). */
- public static void main(String[] params) throws Exception {}
-
- @Before
- public void setUp() throws Exception {
- System.out.println("set up.");
- }
-
- /** Test for all fields valid. */
- @Test
- public void testAllFieldsValid() throws Exception {
- System.out.println("starting testAllFieldsValid.");
- testHrToOdDeveloperInfo(ALL_FIELDS_VALID_FILE_NAME);
- testOdToHrDeveloperInfo(ALL_FIELDS_VALID_FILE_NAME);
- }
-
- /** Tests missing required fields fails. */
- @Test
- public void testMissingRequiredFields() throws Exception {
- System.out.println("Starting testMissingRequiredFields");
- for (String reqField : REQUIRED_FIELD_NAMES) {
- System.out.println("testing missing required field: " + reqField);
- var developerInfoEle =
- TestUtils.getElementsFromResource(
- Paths.get(DEVELOPER_INFO_HR_PATH, ALL_FIELDS_VALID_FILE_NAME));
- developerInfoEle.get(0).removeAttribute(reqField);
-
- assertThrows(
- MalformedXmlException.class,
- () -> new DeveloperInfoFactory().createFromHrElements(developerInfoEle));
- }
-
- for (String reqField : REQUIRED_FIELD_NAMES_OD) {
- System.out.println("testing missing required field od: " + reqField);
- var developerInfoEle =
- TestUtils.getElementsFromResource(
- Paths.get(DEVELOPER_INFO_OD_PATH, ALL_FIELDS_VALID_FILE_NAME));
- TestUtils.removeOdChildEleWithName(developerInfoEle.get(0), reqField);
-
- assertThrows(
- MalformedXmlException.class,
- () -> new DeveloperInfoFactory().createFromOdElements(developerInfoEle));
- }
- }
-
- /** Tests missing optional fields passes. */
- @Test
- public void testMissingOptionalFields() throws Exception {
- for (String optField : OPTIONAL_FIELD_NAMES) {
- var developerInfoEle =
- TestUtils.getElementsFromResource(
- Paths.get(DEVELOPER_INFO_HR_PATH, ALL_FIELDS_VALID_FILE_NAME));
- developerInfoEle.get(0).removeAttribute(optField);
- DeveloperInfo developerInfo =
- new DeveloperInfoFactory().createFromHrElements(developerInfoEle);
- developerInfo.toOdDomElements(TestUtils.document());
- }
-
- for (String optField : OPTIONAL_FIELD_NAMES_OD) {
- var developerInfoEle =
- TestUtils.getElementsFromResource(
- Paths.get(DEVELOPER_INFO_OD_PATH, ALL_FIELDS_VALID_FILE_NAME));
- TestUtils.removeOdChildEleWithName(developerInfoEle.get(0), optField);
- DeveloperInfo developerInfo =
- new DeveloperInfoFactory().createFromOdElements(developerInfoEle);
- developerInfo.toHrDomElements(TestUtils.document());
- }
- }
-
- private void testHrToOdDeveloperInfo(String fileName) throws Exception {
- TestUtils.testHrToOd(
- TestUtils.document(),
- new DeveloperInfoFactory(),
- DEVELOPER_INFO_HR_PATH,
- DEVELOPER_INFO_OD_PATH,
- fileName);
- }
-
- private void testOdToHrDeveloperInfo(String fileName) throws Exception {
- TestUtils.testOdToHr(
- TestUtils.document(),
- new DeveloperInfoFactory(),
- DEVELOPER_INFO_OD_PATH,
- DEVELOPER_INFO_HR_PATH,
- fileName);
- }
-}
diff --git a/tools/app_metadata_bundles/src/test/java/com/android/asllib/marshallable/SafetyLabelsTest.java b/tools/app_metadata_bundles/src/test/java/com/android/asllib/marshallable/SafetyLabelsTest.java
index bba6b54..19d1626 100644
--- a/tools/app_metadata_bundles/src/test/java/com/android/asllib/marshallable/SafetyLabelsTest.java
+++ b/tools/app_metadata_bundles/src/test/java/com/android/asllib/marshallable/SafetyLabelsTest.java
@@ -28,26 +28,14 @@
private static final String SAFETY_LABELS_HR_PATH = "com/android/asllib/safetylabels/hr";
private static final String SAFETY_LABELS_OD_PATH = "com/android/asllib/safetylabels/od";
- private static final String MISSING_VERSION_FILE_NAME = "missing-version.xml";
private static final String VALID_EMPTY_FILE_NAME = "valid-empty.xml";
private static final String WITH_DATA_LABELS_FILE_NAME = "with-data-labels.xml";
- private static final String WITH_SECURITY_LABELS_FILE_NAME = "with-security-labels.xml";
- private static final String WITH_THIRD_PARTY_VERIFICATION_FILE_NAME =
- "with-third-party-verification.xml";
@Before
public void setUp() throws Exception {
System.out.println("set up.");
}
- /** Test for safety labels missing version. */
- @Test
- public void testSafetyLabelsMissingVersion() throws Exception {
- System.out.println("starting testSafetyLabelsMissingVersion.");
- hrToOdExpectException(MISSING_VERSION_FILE_NAME);
- odToHrExpectException(MISSING_VERSION_FILE_NAME);
- }
-
/** Test for safety labels valid empty. */
@Test
public void testSafetyLabelsValidEmptyFile() throws Exception {
@@ -64,22 +52,6 @@
testOdToHrSafetyLabels(WITH_DATA_LABELS_FILE_NAME);
}
- /** Test for safety labels with security labels. */
- @Test
- public void testSafetyLabelsWithSecurityLabels() throws Exception {
- System.out.println("starting testSafetyLabelsWithSecurityLabels.");
- testHrToOdSafetyLabels(WITH_SECURITY_LABELS_FILE_NAME);
- testOdToHrSafetyLabels(WITH_SECURITY_LABELS_FILE_NAME);
- }
-
- /** Test for safety labels with third party verification. */
- @Test
- public void testSafetyLabelsWithThirdPartyVerification() throws Exception {
- System.out.println("starting testSafetyLabelsWithThirdPartyVerification.");
- testHrToOdSafetyLabels(WITH_THIRD_PARTY_VERIFICATION_FILE_NAME);
- testOdToHrSafetyLabels(WITH_THIRD_PARTY_VERIFICATION_FILE_NAME);
- }
-
private void hrToOdExpectException(String fileName) {
TestUtils.hrToOdExpectException(new SafetyLabelsFactory(), SAFETY_LABELS_HR_PATH, fileName);
}
diff --git a/tools/app_metadata_bundles/src/test/java/com/android/asllib/marshallable/SecurityLabelsTest.java b/tools/app_metadata_bundles/src/test/java/com/android/asllib/marshallable/SecurityLabelsTest.java
deleted file mode 100644
index a940bc6..0000000
--- a/tools/app_metadata_bundles/src/test/java/com/android/asllib/marshallable/SecurityLabelsTest.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (C) 2017 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.
- */
-
-package com.android.asllib.marshallable;
-
-
-import com.android.asllib.testutils.TestUtils;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-import java.nio.file.Paths;
-import java.util.List;
-
-@RunWith(JUnit4.class)
-public class SecurityLabelsTest {
- private static final String SECURITY_LABELS_HR_PATH = "com/android/asllib/securitylabels/hr";
- private static final String SECURITY_LABELS_OD_PATH = "com/android/asllib/securitylabels/od";
-
- public static final List<String> OPTIONAL_FIELD_NAMES =
- List.of("isDataDeletable", "isDataEncrypted");
- public static final List<String> OPTIONAL_FIELD_NAMES_OD =
- List.of("is_data_deletable", "is_data_encrypted");
-
- private static final String ALL_FIELDS_VALID_FILE_NAME = "all-fields-valid.xml";
-
- /** Logic for setting up tests (empty if not yet needed). */
- public static void main(String[] params) throws Exception {}
-
- @Before
- public void setUp() throws Exception {
- System.out.println("set up.");
- }
-
- /** Test for all fields valid. */
- @Test
- public void testAllFieldsValid() throws Exception {
- System.out.println("starting testAllFieldsValid.");
- testHrToOdSecurityLabels(ALL_FIELDS_VALID_FILE_NAME);
- testOdToHrSecurityLabels(ALL_FIELDS_VALID_FILE_NAME);
- }
-
- /** Tests missing optional fields passes. */
- @Test
- public void testMissingOptionalFields() throws Exception {
- for (String optField : OPTIONAL_FIELD_NAMES) {
- var ele =
- TestUtils.getElementsFromResource(
- Paths.get(SECURITY_LABELS_HR_PATH, ALL_FIELDS_VALID_FILE_NAME));
- ele.get(0).removeAttribute(optField);
- SecurityLabels securityLabels = new SecurityLabelsFactory().createFromHrElements(ele);
- securityLabels.toOdDomElements(TestUtils.document());
- }
- for (String optField : OPTIONAL_FIELD_NAMES_OD) {
- var ele =
- TestUtils.getElementsFromResource(
- Paths.get(SECURITY_LABELS_OD_PATH, ALL_FIELDS_VALID_FILE_NAME));
- TestUtils.removeOdChildEleWithName(ele.get(0), optField);
- SecurityLabels securityLabels = new SecurityLabelsFactory().createFromOdElements(ele);
- securityLabels.toHrDomElements(TestUtils.document());
- }
- }
-
- private void testHrToOdSecurityLabels(String fileName) throws Exception {
- TestUtils.testHrToOd(
- TestUtils.document(),
- new SecurityLabelsFactory(),
- SECURITY_LABELS_HR_PATH,
- SECURITY_LABELS_OD_PATH,
- fileName);
- }
-
- private void testOdToHrSecurityLabels(String fileName) throws Exception {
- TestUtils.testOdToHr(
- TestUtils.document(),
- new SecurityLabelsFactory(),
- SECURITY_LABELS_OD_PATH,
- SECURITY_LABELS_HR_PATH,
- fileName);
- }
-}
diff --git a/tools/app_metadata_bundles/src/test/java/com/android/asllib/marshallable/ThirdPartyVerificationTest.java b/tools/app_metadata_bundles/src/test/java/com/android/asllib/marshallable/ThirdPartyVerificationTest.java
deleted file mode 100644
index ec86d0f..0000000
--- a/tools/app_metadata_bundles/src/test/java/com/android/asllib/marshallable/ThirdPartyVerificationTest.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2017 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.
- */
-
-package com.android.asllib.marshallable;
-
-import com.android.asllib.testutils.TestUtils;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-@RunWith(JUnit4.class)
-public class ThirdPartyVerificationTest {
- private static final String THIRD_PARTY_VERIFICATION_HR_PATH =
- "com/android/asllib/thirdpartyverification/hr";
- private static final String THIRD_PARTY_VERIFICATION_OD_PATH =
- "com/android/asllib/thirdpartyverification/od";
-
- private static final String VALID_FILE_NAME = "valid.xml";
- private static final String MISSING_URL_FILE_NAME = "missing-url.xml";
-
- /** Logic for setting up tests (empty if not yet needed). */
- public static void main(String[] params) throws Exception {}
-
- @Before
- public void setUp() throws Exception {
- System.out.println("set up.");
- }
-
- /** Test for valid. */
- @Test
- public void testValid() throws Exception {
- System.out.println("starting testValid.");
- testHrToOdThirdPartyVerification(VALID_FILE_NAME);
- testOdToHrThirdPartyVerification(VALID_FILE_NAME);
- }
-
- /** Tests missing url. */
- @Test
- public void testMissingUrl() throws Exception {
- System.out.println("starting testMissingUrl.");
- hrToOdExpectException(MISSING_URL_FILE_NAME);
- odToHrExpectException(MISSING_URL_FILE_NAME);
- }
-
- private void hrToOdExpectException(String fileName) {
- TestUtils.hrToOdExpectException(
- new ThirdPartyVerificationFactory(), THIRD_PARTY_VERIFICATION_HR_PATH, fileName);
- }
-
- private void odToHrExpectException(String fileName) {
- TestUtils.odToHrExpectException(
- new ThirdPartyVerificationFactory(), THIRD_PARTY_VERIFICATION_OD_PATH, fileName);
- }
-
- private void testHrToOdThirdPartyVerification(String fileName) throws Exception {
- TestUtils.testHrToOd(
- TestUtils.document(),
- new ThirdPartyVerificationFactory(),
- THIRD_PARTY_VERIFICATION_HR_PATH,
- THIRD_PARTY_VERIFICATION_OD_PATH,
- fileName);
- }
-
- private void testOdToHrThirdPartyVerification(String fileName) throws Exception {
- TestUtils.testOdToHr(
- TestUtils.document(),
- new ThirdPartyVerificationFactory(),
- THIRD_PARTY_VERIFICATION_OD_PATH,
- THIRD_PARTY_VERIFICATION_HR_PATH,
- fileName);
- }
-}
diff --git a/tools/app_metadata_bundles/src/test/java/com/android/asllib/marshallable/TransparencyInfoTest.java b/tools/app_metadata_bundles/src/test/java/com/android/asllib/marshallable/TransparencyInfoTest.java
index f494240..8a0b35e 100644
--- a/tools/app_metadata_bundles/src/test/java/com/android/asllib/marshallable/TransparencyInfoTest.java
+++ b/tools/app_metadata_bundles/src/test/java/com/android/asllib/marshallable/TransparencyInfoTest.java
@@ -29,9 +29,6 @@
"com/android/asllib/transparencyinfo/hr";
private static final String TRANSPARENCY_INFO_OD_PATH =
"com/android/asllib/transparencyinfo/od";
-
- private static final String VALID_EMPTY_FILE_NAME = "valid-empty.xml";
- private static final String WITH_DEVELOPER_INFO_FILE_NAME = "with-developer-info.xml";
private static final String WITH_APP_INFO_FILE_NAME = "with-app-info.xml";
@Before
@@ -39,22 +36,6 @@
System.out.println("set up.");
}
- /** Test for transparency info valid empty. */
- @Test
- public void testTransparencyInfoValidEmptyFile() throws Exception {
- System.out.println("starting testTransparencyInfoValidEmptyFile.");
- testHrToOdTransparencyInfo(VALID_EMPTY_FILE_NAME);
- testOdToHrTransparencyInfo(VALID_EMPTY_FILE_NAME);
- }
-
- /** Test for transparency info with developer info. */
- @Test
- public void testTransparencyInfoWithDeveloperInfo() throws Exception {
- System.out.println("starting testTransparencyInfoWithDeveloperInfo.");
- testHrToOdTransparencyInfo(WITH_DEVELOPER_INFO_FILE_NAME);
- testOdToHrTransparencyInfo(WITH_DEVELOPER_INFO_FILE_NAME);
- }
-
/** Test for transparency info with app info. */
@Test
public void testTransparencyInfoWithAppInfo() throws Exception {
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/androidsafetylabel/hr/with-safety-labels.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/androidsafetylabel/hr/with-safety-labels.xml
index 53794a1..03e71d2 100644
--- a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/androidsafetylabel/hr/with-safety-labels.xml
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/androidsafetylabel/hr/with-safety-labels.xml
@@ -1,4 +1,4 @@
<app-metadata-bundles version="123456">
- <safety-labels version="12345">
+ <safety-labels>
</safety-labels>
</app-metadata-bundles>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/androidsafetylabel/hr/with-transparency-info.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/androidsafetylabel/hr/with-transparency-info.xml
index 00bcfa8..a00ef65 100644
--- a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/androidsafetylabel/hr/with-transparency-info.xml
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/androidsafetylabel/hr/with-transparency-info.xml
@@ -1,4 +1,15 @@
<app-metadata-bundles version="123456">
-<transparency-info>
-</transparency-info>
+ <transparency-info>
+ <app-info
+ apsCompliant="false"
+ privacyPolicy="www.example.com">
+ <first-party-endpoints>
+ <item>url1</item>
+ </first-party-endpoints>
+ <service-provider-endpoints>
+ <item>url55</item>
+ <item>url56</item>
+ </service-provider-endpoints>
+ </app-info>
+ </transparency-info>
</app-metadata-bundles>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/androidsafetylabel/od/with-safety-labels.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/androidsafetylabel/od/with-safety-labels.xml
index 74644ed..f00fb26 100644
--- a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/androidsafetylabel/od/with-safety-labels.xml
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/androidsafetylabel/od/with-safety-labels.xml
@@ -1,6 +1,5 @@
<bundle>
<long name="version" value="123456"/>
<pbundle_as_map name="safety_labels">
- <long name="version" value="12345"/>
</pbundle_as_map>
</bundle>
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/androidsafetylabel/od/with-transparency-info.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/androidsafetylabel/od/with-transparency-info.xml
index 63c5094..d0c8668 100644
--- a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/androidsafetylabel/od/with-transparency-info.xml
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/androidsafetylabel/od/with-transparency-info.xml
@@ -1,4 +1,16 @@
<bundle>
<long name="version" value="123456"/>
- <pbundle_as_map name="transparency_info"/>
+ <pbundle_as_map name="transparency_info">
+ <pbundle_as_map name="app_info">
+ <boolean name="aps_compliant" value="false"/>
+ <string name="privacy_policy" value="www.example.com"/>
+ <string-array name="first_party_endpoints" num="1">
+ <item value="url1"/>
+ </string-array>
+ <string-array name="service_provider_endpoints" num="2">
+ <item value="url55"/>
+ <item value="url56"/>
+ </string-array>
+ </pbundle_as_map>
+ </pbundle_as_map>
</bundle>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/appinfo/hr/all-fields-valid.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/appinfo/hr/all-fields-valid.xml
index 883170a2..0d15efc 100644
--- a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/appinfo/hr/all-fields-valid.xml
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/appinfo/hr/all-fields-valid.xml
@@ -1,14 +1,11 @@
<app-info
- title="beervision"
- description="a beer app"
- containsAds="true"
- obeyAps="false"
- adsFingerprinting="false"
- securityFingerprinting="false"
- privacyPolicy="www.example.com"
- securityEndpoints="url1|url2|url3"
- firstPartyEndpoints="url1"
- serviceProviderEndpoints="url55|url56"
- category="Food and drink"
- email="max@maxloh.com"
- website="www.example.com" />
\ No newline at end of file
+ apsCompliant="false"
+ privacyPolicy="www.example.com">
+ <first-party-endpoints>
+ <item>url1</item>
+ </first-party-endpoints>
+ <service-provider-endpoints>
+ <item>url55</item>
+ <item>url56</item>
+ </service-provider-endpoints>
+</app-info>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/appinfo/od/all-fields-valid.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/appinfo/od/all-fields-valid.xml
index 6e976a3..bce5179 100644
--- a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/appinfo/od/all-fields-valid.xml
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/appinfo/od/all-fields-valid.xml
@@ -1,25 +1,12 @@
<pbundle_as_map name="app_info">
- <string name="title" value="beervision"/>
- <string name="description" value="a beer app"/>
- <boolean name="contains_ads" value="true"/>
- <boolean name="obey_aps" value="false"/>
- <boolean name="ads_fingerprinting" value="false"/>
- <boolean name="security_fingerprinting" value="false"/>
+ <boolean name="aps_compliant" value="false"/>
<string name="privacy_policy" value="www.example.com"/>
- <string-array name="security_endpoint" num="3">
- <item value="url1"/>
- <item value="url2"/>
- <item value="url3"/>
- </string-array>
- <string-array name="first_party_endpoint" num="1">
+ <string-array name="first_party_endpoints" num="1">
<item value="url1"/>
</string-array>
- <string-array name="service_provider_endpoint" num="2">
+ <string-array name="service_provider_endpoints" num="2">
<item value="url55"/>
<item value="url56"/>
</string-array>
- <string name="category" value="Food and drink"/>
- <string name="email" value="max@maxloh.com"/>
- <string name="website" value="www.example.com"/>
</pbundle_as_map>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/safetylabels/hr/missing-version.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/safetylabels/hr/missing-version.xml
deleted file mode 100644
index 762f3bd..0000000
--- a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/safetylabels/hr/missing-version.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-<safety-labels>
-</safety-labels>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/safetylabels/hr/valid-empty.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/safetylabels/hr/valid-empty.xml
index 7decfd4..92d10ca 100644
--- a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/safetylabels/hr/valid-empty.xml
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/safetylabels/hr/valid-empty.xml
@@ -1 +1 @@
-<safety-labels version="12345"></safety-labels>
\ No newline at end of file
+<safety-labels></safety-labels>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/safetylabels/hr/with-data-labels.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/safetylabels/hr/with-data-labels.xml
index 84456da..ca3d9f0 100644
--- a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/safetylabels/hr/with-data-labels.xml
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/safetylabels/hr/with-data-labels.xml
@@ -1,4 +1,4 @@
-<safety-labels version="12345">
+<safety-labels>
<data-labels>
<data-shared dataType="location_data_type_approx_location"
isSharingOptional="false"
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/safetylabels/hr/with-security-labels.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/safetylabels/hr/with-security-labels.xml
index 940e48a..c962785 100644
--- a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/safetylabels/hr/with-security-labels.xml
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/safetylabels/hr/with-security-labels.xml
@@ -1,4 +1,4 @@
-<safety-labels version="12345">
+<safety-labels>
<security-labels
isDataDeletable="true"
isDataEncrypted="false"
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/safetylabels/hr/with-third-party-verification.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/safetylabels/hr/with-third-party-verification.xml
index bfbc5ae..0805290 100644
--- a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/safetylabels/hr/with-third-party-verification.xml
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/safetylabels/hr/with-third-party-verification.xml
@@ -1,4 +1,4 @@
-<safety-labels version="12345">
+<safety-labels>
<third-party-verification url="www.example.com">
</third-party-verification>
</safety-labels>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/safetylabels/od/missing-version.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/safetylabels/od/missing-version.xml
deleted file mode 100644
index 3fbe359..0000000
--- a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/safetylabels/od/missing-version.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-<pbundle_as_map name="safety_labels">
-</pbundle_as_map>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/safetylabels/od/valid-empty.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/safetylabels/od/valid-empty.xml
index 4f03d88..3fbe359 100644
--- a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/safetylabels/od/valid-empty.xml
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/safetylabels/od/valid-empty.xml
@@ -1,3 +1,2 @@
<pbundle_as_map name="safety_labels">
- <long name="version" value="12345"/>
</pbundle_as_map>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/safetylabels/od/with-data-labels.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/safetylabels/od/with-data-labels.xml
index fa2a3f8..db92e02 100644
--- a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/safetylabels/od/with-data-labels.xml
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/safetylabels/od/with-data-labels.xml
@@ -1,5 +1,4 @@
<pbundle_as_map name="safety_labels">
- <long name="version" value="12345"/>
<pbundle_as_map name="data_labels">
<pbundle_as_map name="data_shared">
<pbundle_as_map name="location">
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/safetylabels/od/with-security-labels.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/safetylabels/od/with-security-labels.xml
index b39c562b..9246180 100644
--- a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/safetylabels/od/with-security-labels.xml
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/safetylabels/od/with-security-labels.xml
@@ -1,5 +1,4 @@
<pbundle_as_map name="safety_labels">
- <long name="version" value="12345"/>
<pbundle_as_map name="security_labels">
<boolean name="is_data_deletable" value="true" />
<boolean name="is_data_encrypted" value="false" />
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/safetylabels/od/with-third-party-verification.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/safetylabels/od/with-third-party-verification.xml
index 10653ff..fd435c5 100644
--- a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/safetylabels/od/with-third-party-verification.xml
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/safetylabels/od/with-third-party-verification.xml
@@ -1,5 +1,4 @@
<pbundle_as_map name="safety_labels">
- <long name="version" value="12345"/>
<pbundle_as_map name="third_party_verification">
<string name="url" value="www.example.com"/>
</pbundle_as_map>
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/transparencyinfo/hr/with-app-info.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/transparencyinfo/hr/with-app-info.xml
index a7c48fc..2512ca4 100644
--- a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/transparencyinfo/hr/with-app-info.xml
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/transparencyinfo/hr/with-app-info.xml
@@ -1,4 +1,14 @@
<transparency-info>
- <app-info title="beervision" description="a beer app" containsAds="true" obeyAps="false" adsFingerprinting="false" securityFingerprinting="false" privacyPolicy="www.example.com" securityEndpoints="url1|url2|url3" firstPartyEndpoints="url1" serviceProviderEndpoints="url55|url56" category="Food and drink" email="max@maxloh.com" />
+ <app-info
+ apsCompliant="false"
+ privacyPolicy="www.example.com">
+ <first-party-endpoints>
+ <item>url1</item>
+ </first-party-endpoints>
+ <service-provider-endpoints>
+ <item>url55</item>
+ <item>url56</item>
+ </service-provider-endpoints>
+ </app-info>
</transparency-info>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/transparencyinfo/od/with-app-info.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/transparencyinfo/od/with-app-info.xml
index b813641..c7bdd97 100644
--- a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/transparencyinfo/od/with-app-info.xml
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/transparencyinfo/od/with-app-info.xml
@@ -1,26 +1,14 @@
<pbundle_as_map name="transparency_info">
<pbundle_as_map name="app_info">
- <string name="title" value="beervision"/>
- <string name="description" value="a beer app"/>
- <boolean name="contains_ads" value="true"/>
- <boolean name="obey_aps" value="false"/>
- <boolean name="ads_fingerprinting" value="false"/>
- <boolean name="security_fingerprinting" value="false"/>
+ <boolean name="aps_compliant" value="false"/>
<string name="privacy_policy" value="www.example.com"/>
- <string-array name="security_endpoint" num="3">
- <item value="url1"/>
- <item value="url2"/>
- <item value="url3"/>
- </string-array>
- <string-array name="first_party_endpoint" num="1">
+ <string-array name="first_party_endpoints" num="1">
<item value="url1"/>
</string-array>
- <string-array name="service_provider_endpoint" num="2">
+ <string-array name="service_provider_endpoints" num="2">
<item value="url55"/>
<item value="url56"/>
</string-array>
- <string name="category" value="Food and drink"/>
- <string name="email" value="max@maxloh.com"/>
</pbundle_as_map>
</pbundle_as_map>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/validmappings/contacts/hr.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/validmappings/contacts/hr.xml
index b2ff449..cadf213 100644
--- a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/validmappings/contacts/hr.xml
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/validmappings/contacts/hr.xml
@@ -1,5 +1,5 @@
<app-metadata-bundles version="123">
- <safety-labels version="12345">
+ <safety-labels>
<data-labels>
<data-shared dataCategory="contacts"
dataType="contacts"
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/validmappings/contacts/od.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/validmappings/contacts/od.xml
index 81277bf..7aafd23 100644
--- a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/validmappings/contacts/od.xml
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/validmappings/contacts/od.xml
@@ -1,7 +1,6 @@
<bundle>
<long name="version" value="123"/>
<pbundle_as_map name="safety_labels">
- <long name="version" value="12345"/>
<pbundle_as_map name="data_labels">
<pbundle_as_map name="data_shared">
<pbundle_as_map name="contacts">
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/validmappings/general/hr.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/validmappings/general/hr.xml
index 41b32b5..5923079 100644
--- a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/validmappings/general/hr.xml
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/validmappings/general/hr.xml
@@ -1,5 +1,5 @@
<app-metadata-bundles version="123">
- <safety-labels version="12345">
+ <safety-labels>
<data-labels>
<data-shared
dataType="location_data_type_approx_location"
@@ -10,24 +10,18 @@
isSharingOptional="true"
purposes="app_functionality|analytics" />
</data-labels>
- <security-labels
- isDataDeletable="true"
- isDataEncrypted="false"
- />
- <third-party-verification url="www.example.com">
- </third-party-verification>
</safety-labels>
<system-app-safety-label declaration="true">
</system-app-safety-label>
<transparency-info>
- <developer-info
- name="max"
- email="max@example.com"
- address="111 blah lane"
- countryRegion="US"
- relationship="aosp"
- website="example.com"
- registryId="registry_id" />
- <app-info title="beervision" description="a beer app" containsAds="true" obeyAps="false" adsFingerprinting="false" securityFingerprinting="false" privacyPolicy="www.example.com" securityEndpoints="url1|url2|url3" firstPartyEndpoints="url1" serviceProviderEndpoints="url55|url56" category="Food and drink" email="max@maxloh.com" />
+ <app-info apsCompliant="false" privacyPolicy="www.example.com">
+ <first-party-endpoints>
+ <item>url1</item>
+ </first-party-endpoints>
+ <service-provider-endpoints>
+ <item>url55</item>
+ <item>url56</item>
+ </service-provider-endpoints>
+ </app-info>
</transparency-info>
</app-metadata-bundles>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/validmappings/general/od.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/validmappings/general/od.xml
index c11ac43..c24087e 100644
--- a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/validmappings/general/od.xml
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/validmappings/general/od.xml
@@ -1,7 +1,6 @@
<bundle>
<long name="version" value="123"/>
<pbundle_as_map name="safety_labels">
- <long name="version" value="12345"/>
<pbundle_as_map name="data_labels">
<pbundle_as_map name="data_shared">
<pbundle_as_map name="location">
@@ -21,49 +20,21 @@
</pbundle_as_map>
</pbundle_as_map>
</pbundle_as_map>
- <pbundle_as_map name="security_labels">
- <boolean name="is_data_deletable" value="true"/>
- <boolean name="is_data_encrypted" value="false"/>
- </pbundle_as_map>
- <pbundle_as_map name="third_party_verification">
- <string name="url" value="www.example.com"/>
- </pbundle_as_map>
</pbundle_as_map>
<pbundle_as_map name="system_app_safety_label">
<boolean name="declaration" value="true"/>
</pbundle_as_map>
<pbundle_as_map name="transparency_info">
- <pbundle_as_map name="developer_info">
- <string name="name" value="max"/>
- <string name="email" value="max@example.com"/>
- <string name="address" value="111 blah lane"/>
- <string name="country_region" value="US"/>
- <long name="relationship" value="5"/>
- <string name="website" value="example.com"/>
- <string name="app_developer_registry_id" value="registry_id"/>
- </pbundle_as_map>
<pbundle_as_map name="app_info">
- <string name="title" value="beervision"/>
- <string name="description" value="a beer app"/>
- <boolean name="contains_ads" value="true"/>
- <boolean name="obey_aps" value="false"/>
- <boolean name="ads_fingerprinting" value="false"/>
- <boolean name="security_fingerprinting" value="false"/>
+ <boolean name="aps_compliant" value="false"/>
<string name="privacy_policy" value="www.example.com"/>
- <string-array name="security_endpoint" num="3">
- <item value="url1"/>
- <item value="url2"/>
- <item value="url3"/>
- </string-array>
- <string-array name="first_party_endpoint" num="1">
+ <string-array name="first_party_endpoints" num="1">
<item value="url1"/>
</string-array>
- <string-array name="service_provider_endpoint" num="2">
+ <string-array name="service_provider_endpoints" num="2">
<item value="url55"/>
<item value="url56"/>
</string-array>
- <string name="category" value="Food and drink"/>
- <string name="email" value="max@maxloh.com"/>
</pbundle_as_map>
</pbundle_as_map>
</bundle>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/validmappings/location/hr.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/validmappings/location/hr.xml
index ac844b3..a4242d0 100644
--- a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/validmappings/location/hr.xml
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/validmappings/location/hr.xml
@@ -1,5 +1,5 @@
<app-metadata-bundles version="123">
- <safety-labels version="12345">
+ <safety-labels>
<data-labels>
<data-shared dataCategory="location"
dataType="precise_location"
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/validmappings/location/od.xml b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/validmappings/location/od.xml
index d0a3bfa..79afaf7 100644
--- a/tools/app_metadata_bundles/src/test/resources/com/android/asllib/validmappings/location/od.xml
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/asllib/validmappings/location/od.xml
@@ -1,7 +1,6 @@
<bundle>
<long name="version" value="123"/>
<pbundle_as_map name="safety_labels">
- <long name="version" value="12345"/>
<pbundle_as_map name="data_labels">
<pbundle_as_map name="data_shared">
<pbundle_as_map name="location">
diff --git a/tools/lint/framework/checks/src/main/java/com/google/android/lint/AndroidFrameworkIssueRegistry.kt b/tools/lint/framework/checks/src/main/java/com/google/android/lint/AndroidFrameworkIssueRegistry.kt
index 624a198..5c64697 100644
--- a/tools/lint/framework/checks/src/main/java/com/google/android/lint/AndroidFrameworkIssueRegistry.kt
+++ b/tools/lint/framework/checks/src/main/java/com/google/android/lint/AndroidFrameworkIssueRegistry.kt
@@ -41,6 +41,7 @@
PermissionAnnotationDetector.ISSUE_MISSING_PERMISSION_ANNOTATION,
PermissionMethodDetector.ISSUE_PERMISSION_METHOD_USAGE,
PermissionMethodDetector.ISSUE_CAN_BE_PERMISSION_METHOD,
+ FeatureAutomotiveDetector.ISSUE,
)
override val api: Int
diff --git a/tools/lint/framework/checks/src/main/java/com/google/android/lint/FeatureAutomotiveDetector.kt b/tools/lint/framework/checks/src/main/java/com/google/android/lint/FeatureAutomotiveDetector.kt
new file mode 100644
index 0000000..972b0c9
--- /dev/null
+++ b/tools/lint/framework/checks/src/main/java/com/google/android/lint/FeatureAutomotiveDetector.kt
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+package com.google.android.lint
+
+import com.android.tools.lint.detector.api.Category
+import com.android.tools.lint.detector.api.ConstantEvaluator
+import com.android.tools.lint.detector.api.Detector
+import com.android.tools.lint.detector.api.Implementation
+import com.android.tools.lint.detector.api.Issue
+import com.android.tools.lint.detector.api.JavaContext
+import com.android.tools.lint.detector.api.Scope
+import com.android.tools.lint.detector.api.Severity
+import com.android.tools.lint.detector.api.SourceCodeScanner
+import com.intellij.psi.PsiMethod
+import java.util.EnumSet
+import org.jetbrains.uast.UCallExpression
+import org.jetbrains.uast.ULiteralExpression
+import org.jetbrains.uast.UReferenceExpression
+
+/**
+ * A detector to check the usage of PackageManager.hasSystemFeature("
+ * android.hardware.type.automotive") in CTS tests.
+ */
+class FeatureAutomotiveDetector : Detector(), SourceCodeScanner {
+
+ companion object {
+
+ val EXPLANATION =
+ """
+ This class uses PackageManager.hasSystemFeature(\"android.hardware.type.automotive\") \
+ or other equivalent methods. \
+ If it is used to make a CTS test behave differently on AAOS, you should use \
+ @RequireAutomotive or @RequireNotAutomotive instead; otherwise, please ignore this \
+ warning. See https://g3doc.corp.google.com/wireless/android/partner/compatibility/\
+ g3doc/dev/write-a-test/index.md#write-a-test-that-behaves-differently-on-aaos
+ """
+
+ val ISSUE: Issue =
+ Issue.create(
+ id = "UsingFeatureAutomotiveInCTS",
+ briefDescription =
+ "PackageManager.hasSystemFeature(\"" +
+ " android.hardware.type.automotive\") is used in CTS tests",
+ explanation = EXPLANATION,
+ category = Category.TESTING,
+ priority = 8,
+ severity = Severity.WARNING,
+ implementation =
+ Implementation(
+ FeatureAutomotiveDetector::class.java,
+ EnumSet.of(Scope.JAVA_FILE, Scope.TEST_SOURCES)
+ )
+ )
+ }
+
+ override fun getApplicableMethodNames() =
+ listOf("hasSystemFeature", "hasFeature", "hasDeviceFeature", "bypassTestForFeatures")
+
+ override fun visitMethodCall(context: JavaContext, node: UCallExpression, method: PsiMethod) {
+ node.valueArguments.forEach {
+ val value =
+ when (it) {
+ is ULiteralExpression -> it.value
+ is UReferenceExpression -> ConstantEvaluator.evaluate(context, it)
+ else -> null
+ }
+ if (value is String && value == "android.hardware.type.automotive") {
+ context.report(
+ issue = ISSUE,
+ location = context.getNameLocation(method),
+ message = EXPLANATION
+ )
+ }
+ }
+ }
+}
diff --git a/tools/lint/framework/checks/src/test/java/com/google/android/lint/FeatureAutomotiveDetectorTest.kt b/tools/lint/framework/checks/src/test/java/com/google/android/lint/FeatureAutomotiveDetectorTest.kt
new file mode 100644
index 0000000..b5e2c00
--- /dev/null
+++ b/tools/lint/framework/checks/src/test/java/com/google/android/lint/FeatureAutomotiveDetectorTest.kt
@@ -0,0 +1,366 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+package com.google.android.lint
+
+import com.android.tools.lint.checks.infrastructure.LintDetectorTest
+import com.android.tools.lint.checks.infrastructure.TestFile
+import com.android.tools.lint.checks.infrastructure.TestLintTask
+import com.android.tools.lint.detector.api.Detector
+import com.android.tools.lint.detector.api.Issue
+import org.junit.Test
+
+@Suppress("UnstableApiUsage")
+class FeatureAutomotiveDetectorTest : LintDetectorTest() {
+ val explanation =
+ FeatureAutomotiveDetector.EXPLANATION.replace("\\", "").replace("\n ", "") +
+ " [UsingFeatureAutomotiveInCTS]"
+
+ override fun getDetector(): Detector = FeatureAutomotiveDetector()
+ override fun getIssues(): List<Issue> = listOf(FeatureAutomotiveDetector.ISSUE)
+ override fun lint(): TestLintTask = super.lint().allowMissingSdk(true)
+
+ @Test
+ fun testWarning1() {
+ lint()
+ .files(
+ java(
+ """
+ import android.content.pm.PackageManager;
+
+ public class Foo {
+
+ private void fun() {
+ PackageManager.getInstance().hasSystemFeature(
+ "android.hardware.type.automotive");
+ }
+ }
+ """
+ )
+ .indented(),
+ *stubs
+ )
+ .issues(FeatureAutomotiveDetector.ISSUE)
+ .run()
+ .expect(
+ """
+ src/android/content/pm/PackageManager.java:13: Warning: $explanation
+ public boolean hasSystemFeature(String feature) {
+ ~~~~~~~~~~~~~~~~
+ 0 errors, 1 warnings
+ """
+ )
+ }
+
+ @Test
+ fun testWarning2() {
+ lint()
+ .files(
+ java(
+ """
+ import android.content.pm.PackageManager;
+
+ public class Foo {
+
+ private void fun() {
+ String featureName = "android.hardware.type.automotive";
+ PackageManager.getInstance().hasSystemFeature(featureName);
+ }
+ }
+ """
+ )
+ .indented(),
+ *stubs
+ )
+ .issues(FeatureAutomotiveDetector.ISSUE)
+ .run()
+ .expect(
+ """
+ src/android/content/pm/PackageManager.java:13: Warning: $explanation
+ public boolean hasSystemFeature(String feature) {
+ ~~~~~~~~~~~~~~~~
+ 0 errors, 1 warnings
+ """
+ )
+ }
+
+ @Test
+ fun testWarning3() {
+ lint()
+ .files(
+ java(
+ """
+ import android.content.pm.PackageManager;
+
+ public class Foo {
+
+ private void fun() {
+ PackageManager.getInstance().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
+ }
+ }
+ """
+ )
+ .indented(),
+ *stubs
+ )
+ .issues(FeatureAutomotiveDetector.ISSUE)
+ .run()
+ .expect(
+ """
+ src/android/content/pm/PackageManager.java:13: Warning: $explanation
+ public boolean hasSystemFeature(String feature) {
+ ~~~~~~~~~~~~~~~~
+ 0 errors, 1 warnings
+ """
+ )
+ }
+
+ @Test
+ fun testWarning4() {
+ lint()
+ .files(
+ java(
+ """
+ import android.content.pm.PackageManager;
+
+ public class Foo {
+
+ private void fun() {
+ String featureName = PackageManager.FEATURE_AUTOMOTIVE;
+ PackageManager.getInstance().hasSystemFeature(featureName);
+ }
+ }
+ """
+ )
+ .indented(),
+ *stubs
+ )
+ .issues(FeatureAutomotiveDetector.ISSUE)
+ .run()
+ .expect(
+ """
+ src/android/content/pm/PackageManager.java:13: Warning: $explanation
+ public boolean hasSystemFeature(String feature) {
+ ~~~~~~~~~~~~~~~~
+ 0 errors, 1 warnings
+ """
+ )
+ }
+
+ @Test
+ fun testWarning5() {
+ lint()
+ .files(
+ java(
+ """
+ import com.android.example.Utils;
+
+ public class Foo {
+
+ private void fun() {
+ Utils.hasFeature("android.hardware.type.automotive");
+ }
+ }
+ """
+ )
+ .indented(),
+ *stubs
+ )
+ .issues(FeatureAutomotiveDetector.ISSUE)
+ .run()
+ .expect(
+ """
+ src/com/android/example/Utils.java:7: Warning: $explanation
+ public static boolean hasFeature(String feature) {
+ ~~~~~~~~~~
+ 0 errors, 1 warnings
+ """
+ )
+ }
+
+ @Test
+ fun testWarning6() {
+ lint()
+ .files(
+ java(
+ """
+ import com.android.example.Utils;
+
+ public class Foo {
+
+ private void fun() {
+ Utils.hasDeviceFeature("android.hardware.type.automotive");
+ }
+ }
+ """
+ )
+ .indented(),
+ *stubs
+ )
+ .issues(FeatureAutomotiveDetector.ISSUE)
+ .run()
+ .expect(
+ """
+ src/com/android/example/Utils.java:11: Warning: $explanation
+ public static boolean hasDeviceFeature(String feature) {
+ ~~~~~~~~~~~~~~~~
+ 0 errors, 1 warnings
+ """
+ )
+ }
+
+ @Test
+ fun testWarning7() {
+ lint()
+ .files(
+ java(
+ """
+ import com.android.example.Utils;
+
+ public class Foo {
+
+ private void fun() {
+ Utils.hasFeature(new Object(), "android.hardware.type.automotive");
+ }
+ }
+ """
+ )
+ .indented(),
+ *stubs
+ )
+ .issues(FeatureAutomotiveDetector.ISSUE)
+ .run()
+ .expect(
+ """
+ src/com/android/example/Utils.java:15: Warning: $explanation
+ public static boolean hasFeature(Object object, String feature) {
+ ~~~~~~~~~~
+ 0 errors, 1 warnings
+ """
+ )
+ }
+
+ @Test
+ fun testWarning8() {
+ lint()
+ .files(
+ java(
+ """
+ import com.android.example.Utils;
+
+ public class Foo {
+
+ private void fun() {
+ Utils.bypassTestForFeatures("android.hardware.type.automotive");
+ }
+ }
+ """
+ )
+ .indented(),
+ *stubs
+ )
+ .issues(FeatureAutomotiveDetector.ISSUE)
+ .run()
+ .expect(
+ """
+ src/com/android/example/Utils.java:19: Warning: $explanation
+ public static boolean bypassTestForFeatures(String feature) {
+ ~~~~~~~~~~~~~~~~~~~~~
+ 0 errors, 1 warnings
+ """
+ )
+ }
+
+ @Test
+ fun testNoWarning() {
+ lint()
+ .files(
+ java(
+ """
+ import android.content.pm.PackageManager;
+
+ public class Foo {
+ private void fun() {
+ String featureName1 = "android.hardware.type.automotive";
+ String featureName2 = PackageManager.FEATURE_AUTOMOTIVE;
+ String notFeatureName = "FEATURE_AUTOMOTIVE";
+ PackageManager.getInstance().hasSystemFeature(notFeatureName);
+ /*
+ PackageManager.getInstance().hasSystemFeature(
+ "android.hardware.type.automotive");
+ */
+ }
+ }
+ """
+ )
+ .indented(),
+ *stubs
+ )
+ .issues(FeatureAutomotiveDetector.ISSUE)
+ .run()
+ .expectClean()
+ }
+
+ private val pmStub: TestFile =
+ java(
+ """
+ package android.content.pm;
+
+ import java.lang.String;
+
+ public class PackageManager {
+ public static final String FEATURE_AUTOMOTIVE = "android.hardware.type.automotive";
+
+ public static PackageManager getInstance() {
+ return new PackageManager();
+ }
+
+ public boolean hasSystemFeature(String feature) {
+ return true;
+ }
+ }
+ """
+ )
+
+ private val exampleStub: TestFile =
+ java(
+ """
+ package com.android.example;
+
+ import java.lang.String;
+
+ public class Utils {
+ public static boolean hasFeature(String feature) {
+ return true;
+ }
+
+ public static boolean hasDeviceFeature(String feature) {
+ return true;
+ }
+
+ public static boolean hasFeature(Object object, String feature) {
+ return true;
+ }
+
+ public static boolean bypassTestForFeatures(String feature) {
+ return true;
+ }
+ }
+ """
+ )
+
+ private val stubs = arrayOf(pmStub, exampleStub)
+}