summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/api/current.txt1
-rw-r--r--core/api/system-current.txt3
-rw-r--r--core/java/android/content/res/Resources.java40
-rw-r--r--core/java/android/provider/Telephony.java88
-rw-r--r--core/java/android/service/dreams/DreamService.java174
-rw-r--r--core/java/android/util/FeatureFlagUtils.java8
-rw-r--r--core/java/android/view/InsetsFrameProvider.java47
-rw-r--r--core/java/android/view/View.java2
-rw-r--r--core/java/android/view/accessibility/AccessibilityEvent.java14
-rw-r--r--core/java/android/view/inputmethod/InputMethodManager.java6
-rw-r--r--core/java/com/android/internal/util/ObservableServiceConnection.java258
-rw-r--r--core/java/com/android/internal/util/PersistentServiceConnection.java200
-rw-r--r--core/res/res/values/config.xml8
-rw-r--r--core/res/res/values/symbols.xml3
-rw-r--r--core/tests/utiltests/Android.bp1
-rw-r--r--core/tests/utiltests/src/com/android/internal/util/ObservableServiceConnectionTest.java226
-rw-r--r--core/tests/utiltests/src/com/android/internal/util/PersistentServiceConnectionTest.java215
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java4
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppTransition.kt4
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java9
-rw-r--r--libs/androidfw/AssetManager2.cpp7
-rw-r--r--media/java/android/media/tv/tuner/TunerVersionChecker.java4
-rw-r--r--media/java/android/media/tv/tuner/dvr/DvrPlayback.java31
-rw-r--r--media/java/android/media/tv/tuner/dvr/DvrRecorder.java31
-rw-r--r--media/jni/Android.bp2
-rw-r--r--media/jni/android_media_tv_Tuner.cpp15
-rw-r--r--media/jni/tuner/DvrClient.cpp10
-rw-r--r--media/jni/tuner/DvrClient.h5
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java2
-rw-r--r--packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt9
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/flags/Flags.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarTransitions.java27
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowController.java18
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java32
-rw-r--r--services/core/java/com/android/server/inputmethod/InputMethodManagerService.java84
-rw-r--r--services/core/java/com/android/server/inputmethod/InputMethodUtils.java14
-rw-r--r--services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java174
-rw-r--r--services/core/java/com/android/server/wm/DisplayPolicy.java168
-rw-r--r--services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java40
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java42
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java8
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java8
-rw-r--r--services/translation/java/com/android/server/translation/TranslationManagerServiceImpl.java27
-rw-r--r--telephony/common/com/android/internal/telephony/util/TelephonyUtils.java56
-rw-r--r--telephony/java/android/telephony/SubscriptionInfo.java206
-rw-r--r--telephony/java/android/telephony/SubscriptionManager.java7
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/ReOpenImeWindowTest.kt81
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdFromIcon.kt54
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt12
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest_ShellTransit.kt15
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt7
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest_ShellTransit.kt14
-rw-r--r--tools/processors/immutability/Android.bp1
-rw-r--r--tools/processors/immutability/AndroidTestTemplate.xml32
-rw-r--r--tools/sdkparcelables/src/com/android/sdkparcelables/Main.kt2
-rw-r--r--tools/traceinjection/src/com/android/traceinjection/TraceInjectionClassVisitor.java2
-rw-r--r--tools/traceinjection/src/com/android/traceinjection/TraceInjectionMethodAdapter.java4
59 files changed, 2039 insertions, 531 deletions
diff --git a/core/api/current.txt b/core/api/current.txt
index b06374615730..815ccfe0b1c6 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -52022,6 +52022,7 @@ package android.view.accessibility {
field public static final int CONTENT_CHANGE_TYPE_DRAG_CANCELLED = 512; // 0x200
field public static final int CONTENT_CHANGE_TYPE_DRAG_DROPPED = 256; // 0x100
field public static final int CONTENT_CHANGE_TYPE_DRAG_STARTED = 128; // 0x80
+ field public static final int CONTENT_CHANGE_TYPE_ENABLED = 4096; // 0x1000
field public static final int CONTENT_CHANGE_TYPE_ERROR = 2048; // 0x800
field public static final int CONTENT_CHANGE_TYPE_PANE_APPEARED = 16; // 0x10
field public static final int CONTENT_CHANGE_TYPE_PANE_DISAPPEARED = 32; // 0x20
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 87960d70fa25..5e1c2347664b 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -7132,6 +7132,7 @@ package android.media.tv.tuner {
field public static final int TUNER_VERSION_1_0 = 65536; // 0x10000
field public static final int TUNER_VERSION_1_1 = 65537; // 0x10001
field public static final int TUNER_VERSION_2_0 = 131072; // 0x20000
+ field public static final int TUNER_VERSION_3_0 = 196608; // 0x30000
field public static final int TUNER_VERSION_UNKNOWN = 0; // 0x0
}
@@ -7149,6 +7150,7 @@ package android.media.tv.tuner.dvr {
method public long read(@NonNull byte[], long, long);
method public long seek(long);
method public void setFileDescriptor(@NonNull android.os.ParcelFileDescriptor);
+ method public int setPlaybackBufferStatusCheckIntervalHint(long);
method public int start();
method public int stop();
field public static final int PLAYBACK_STATUS_ALMOST_EMPTY = 2; // 0x2
@@ -7164,6 +7166,7 @@ package android.media.tv.tuner.dvr {
method public int detachFilter(@NonNull android.media.tv.tuner.filter.Filter);
method public int flush();
method public void setFileDescriptor(@NonNull android.os.ParcelFileDescriptor);
+ method public int setRecordBufferStatusCheckIntervalHint(long);
method public int start();
method public int stop();
method public long write(long);
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index a03286d3ec6f..fb1fcf8e2a06 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -173,6 +173,7 @@ public class Resources {
* mThemeRefNextFlushSize is reached.
*/
private static final int MIN_THEME_REFS_FLUSH_SIZE = 32;
+ private static final int MAX_THEME_REFS_FLUSH_SIZE = 512;
private int mThemeRefsNextFlushSize = MIN_THEME_REFS_FLUSH_SIZE;
private int mBaseApkAssetsSize;
@@ -364,10 +365,10 @@ public class Resources {
// Rebase the ThemeImpls using the new ResourcesImpl.
synchronized (mThemeRefs) {
+ cleanupThemeReferences();
final int count = mThemeRefs.size();
for (int i = 0; i < count; i++) {
- WeakReference<Theme> weakThemeRef = mThemeRefs.get(i);
- Theme theme = weakThemeRef != null ? weakThemeRef.get() : null;
+ Theme theme = mThemeRefs.get(i).get();
if (theme != null) {
theme.rebase(mResourcesImpl);
}
@@ -2001,6 +2002,15 @@ public class Resources {
private int mHashCode = 0;
+ private boolean containsValue(int resId, boolean force) {
+ for (int i = 0; i < mCount; ++i) {
+ if (mResId[i] == resId && mForce[i] == force) {
+ return true;
+ }
+ }
+ return false;
+ }
+
public void append(int resId, boolean force) {
if (mResId == null) {
mResId = new int[4];
@@ -2010,6 +2020,11 @@ public class Resources {
mForce = new boolean[4];
}
+ // Some apps tend to keep adding same resources over and over, let's protect from it.
+ if (containsValue(resId, force)) {
+ return;
+ }
+
mResId = GrowingArrayUtils.append(mResId, mCount, resId);
mForce = GrowingArrayUtils.append(mForce, mCount, force);
mCount++;
@@ -2073,6 +2088,19 @@ public class Resources {
}
}
+ static int nextPowerOf2(int number) {
+ return number < 2 ? 2 : 1 >> ((int) (Math.log(number - 1) / Math.log(2)) + 1);
+ }
+
+ private void cleanupThemeReferences() {
+ // Clean up references to garbage collected themes
+ if (mThemeRefs.size() > mThemeRefsNextFlushSize) {
+ mThemeRefs.removeIf(ref -> ref.refersTo(null));
+ mThemeRefsNextFlushSize = Math.min(Math.max(MIN_THEME_REFS_FLUSH_SIZE,
+ nextPowerOf2(mThemeRefs.size())), MAX_THEME_REFS_FLUSH_SIZE);
+ }
+ }
+
/**
* Generate a new Theme object for this set of Resources. It initially
* starts out empty.
@@ -2083,14 +2111,8 @@ public class Resources {
Theme theme = new Theme();
theme.setImpl(mResourcesImpl.newThemeImpl());
synchronized (mThemeRefs) {
+ cleanupThemeReferences();
mThemeRefs.add(new WeakReference<>(theme));
-
- // Clean up references to garbage collected themes
- if (mThemeRefs.size() > mThemeRefsNextFlushSize) {
- mThemeRefs.removeIf(ref -> ref.refersTo(null));
- mThemeRefsNextFlushSize = Math.max(MIN_THEME_REFS_FLUSH_SIZE,
- 2 * mThemeRefs.size());
- }
}
return theme;
}
diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java
index 194e1b553322..979c5a885c5e 100644
--- a/core/java/android/provider/Telephony.java
+++ b/core/java/android/provider/Telephony.java
@@ -53,6 +53,7 @@ import com.android.internal.telephony.SmsApplication;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.HashSet;
+import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -4358,6 +4359,12 @@ public final class Telephony {
*/
public static final String COLUMN_NAME_SOURCE = "name_source";
+ /**
+ * The name source is unknown.
+ * @hide
+ */
+ public static final int NAME_SOURCE_UNKNOWN = -1;
+
/** The name_source is from the carrier id. {@hide} */
public static final int NAME_SOURCE_CARRIER_ID = 0;
@@ -4839,5 +4846,86 @@ public final class Telephony {
* @hide
*/
public static final String COLUMN_USER_HANDLE = "user_handle";
+
+ /** All columns in {@link SimInfo} table. */
+ private static final List<String> ALL_COLUMNS = List.of(
+ COLUMN_UNIQUE_KEY_SUBSCRIPTION_ID,
+ COLUMN_ICC_ID,
+ COLUMN_SIM_SLOT_INDEX,
+ COLUMN_DISPLAY_NAME,
+ COLUMN_CARRIER_NAME,
+ COLUMN_NAME_SOURCE,
+ COLUMN_COLOR,
+ COLUMN_NUMBER,
+ COLUMN_DISPLAY_NUMBER_FORMAT,
+ COLUMN_DATA_ROAMING,
+ COLUMN_MCC,
+ COLUMN_MNC,
+ COLUMN_MCC_STRING,
+ COLUMN_MNC_STRING,
+ COLUMN_EHPLMNS,
+ COLUMN_HPLMNS,
+ COLUMN_SIM_PROVISIONING_STATUS,
+ COLUMN_IS_EMBEDDED,
+ COLUMN_CARD_ID,
+ COLUMN_ACCESS_RULES,
+ COLUMN_ACCESS_RULES_FROM_CARRIER_CONFIGS,
+ COLUMN_IS_REMOVABLE,
+ COLUMN_CB_EXTREME_THREAT_ALERT,
+ COLUMN_CB_SEVERE_THREAT_ALERT,
+ COLUMN_CB_AMBER_ALERT,
+ COLUMN_CB_EMERGENCY_ALERT,
+ COLUMN_CB_ALERT_SOUND_DURATION,
+ COLUMN_CB_ALERT_REMINDER_INTERVAL,
+ COLUMN_CB_ALERT_VIBRATE,
+ COLUMN_CB_ALERT_SPEECH,
+ COLUMN_CB_ETWS_TEST_ALERT,
+ COLUMN_CB_CHANNEL_50_ALERT,
+ COLUMN_CB_CMAS_TEST_ALERT,
+ COLUMN_CB_OPT_OUT_DIALOG,
+ COLUMN_ENHANCED_4G_MODE_ENABLED,
+ COLUMN_VT_IMS_ENABLED,
+ COLUMN_WFC_IMS_ENABLED,
+ COLUMN_WFC_IMS_MODE,
+ COLUMN_WFC_IMS_ROAMING_MODE,
+ COLUMN_WFC_IMS_ROAMING_ENABLED,
+ COLUMN_IS_OPPORTUNISTIC,
+ COLUMN_GROUP_UUID,
+ COLUMN_IS_METERED,
+ COLUMN_ISO_COUNTRY_CODE,
+ COLUMN_CARRIER_ID,
+ COLUMN_PROFILE_CLASS,
+ COLUMN_SUBSCRIPTION_TYPE,
+ COLUMN_GROUP_OWNER,
+ COLUMN_DATA_ENABLED_OVERRIDE_RULES,
+ COLUMN_ENABLED_MOBILE_DATA_POLICIES,
+ COLUMN_IMSI,
+ COLUMN_UICC_APPLICATIONS_ENABLED,
+ COLUMN_ALLOWED_NETWORK_TYPES,
+ COLUMN_IMS_RCS_UCE_ENABLED,
+ COLUMN_CROSS_SIM_CALLING_ENABLED,
+ COLUMN_RCS_CONFIG,
+ COLUMN_ALLOWED_NETWORK_TYPES_FOR_REASONS,
+ COLUMN_D2D_STATUS_SHARING,
+ COLUMN_VOIMS_OPT_IN_STATUS,
+ COLUMN_D2D_STATUS_SHARING_SELECTED_CONTACTS,
+ COLUMN_NR_ADVANCED_CALLING_ENABLED,
+ COLUMN_PHONE_NUMBER_SOURCE_CARRIER,
+ COLUMN_PHONE_NUMBER_SOURCE_IMS,
+ COLUMN_PORT_INDEX,
+ COLUMN_USAGE_SETTING,
+ COLUMN_TP_MESSAGE_REF,
+ COLUMN_USER_HANDLE
+ );
+
+ /**
+ * @return All columns in {@link SimInfo} table.
+ *
+ * @hide
+ */
+ @NonNull
+ public static List<String> getAllColumns() {
+ return ALL_COLUMNS;
+ }
}
}
diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java
index 13913268cad0..3b7698e3954b 100644
--- a/core/java/android/service/dreams/DreamService.java
+++ b/core/java/android/service/dreams/DreamService.java
@@ -31,9 +31,9 @@ import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
-import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.content.pm.ServiceInfo;
+import android.content.res.Resources;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
import android.graphics.drawable.Drawable;
@@ -68,6 +68,8 @@ import android.view.accessibility.AccessibilityEvent;
import com.android.internal.R;
import com.android.internal.util.DumpUtils;
+import com.android.internal.util.ObservableServiceConnection;
+import com.android.internal.util.PersistentServiceConnection;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -75,7 +77,8 @@ import org.xmlpull.v1.XmlPullParserException;
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.PrintWriter;
-import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.concurrent.Executor;
import java.util.function.Consumer;
/**
@@ -225,6 +228,7 @@ public class DreamService extends Service implements Window.Callback {
/**
* The default value for whether to show complications on the overlay.
+ *
* @hide
*/
public static final boolean DEFAULT_SHOW_COMPLICATIONS = false;
@@ -251,77 +255,66 @@ public class DreamService extends Service implements Window.Callback {
private DreamServiceWrapper mDreamServiceWrapper;
private Runnable mDispatchAfterOnAttachedToWindow;
- private final OverlayConnection mOverlayConnection;
+ private OverlayConnection mOverlayConnection;
- private static class OverlayConnection implements ServiceConnection {
+ private static class OverlayConnection extends PersistentServiceConnection<IDreamOverlay> {
// Overlay set during onBind.
private IDreamOverlay mOverlay;
- // A Queue of pending requests to execute on the overlay.
- private final ArrayDeque<Consumer<IDreamOverlay>> mRequests;
-
- private boolean mBound;
-
- OverlayConnection() {
- mRequests = new ArrayDeque<>();
- }
-
- public void bind(Context context, @Nullable ComponentName overlayService,
- ComponentName dreamService) {
- if (overlayService == null) {
- return;
+ // A list of pending requests to execute on the overlay.
+ private final ArrayList<Consumer<IDreamOverlay>> mConsumers = new ArrayList<>();
+
+ private final Callback<IDreamOverlay> mCallback = new Callback<IDreamOverlay>() {
+ @Override
+ public void onConnected(ObservableServiceConnection<IDreamOverlay> connection,
+ IDreamOverlay service) {
+ mOverlay = service;
+ for (Consumer<IDreamOverlay> consumer : mConsumers) {
+ consumer.accept(mOverlay);
+ }
}
- final ServiceInfo serviceInfo = fetchServiceInfo(context, dreamService);
-
- final Intent overlayIntent = new Intent();
- overlayIntent.setComponent(overlayService);
- overlayIntent.putExtra(EXTRA_SHOW_COMPLICATIONS,
- fetchShouldShowComplications(context, serviceInfo));
- overlayIntent.putExtra(EXTRA_DREAM_COMPONENT, dreamService);
-
- context.bindService(overlayIntent,
- this, Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE);
- mBound = true;
- }
-
- public void unbind(Context context) {
- if (!mBound) {
- return;
+ @Override
+ public void onDisconnected(ObservableServiceConnection<IDreamOverlay> connection,
+ int reason) {
+ mOverlay = null;
}
+ };
- context.unbindService(this);
- mBound = false;
+ OverlayConnection(Context context,
+ Executor executor,
+ Handler handler,
+ ServiceTransformer<IDreamOverlay> transformer,
+ Intent serviceIntent,
+ int flags,
+ int minConnectionDurationMs,
+ int maxReconnectAttempts,
+ int baseReconnectDelayMs) {
+ super(context, executor, handler, transformer, serviceIntent, flags,
+ minConnectionDurationMs,
+ maxReconnectAttempts, baseReconnectDelayMs);
}
- public void request(Consumer<IDreamOverlay> request) {
- mRequests.push(request);
- evaluate();
+ @Override
+ public boolean bind() {
+ addCallback(mCallback);
+ return super.bind();
}
- private void evaluate() {
- if (mOverlay == null) {
- return;
- }
-
- // Any new requests that arrive during this loop will be processed synchronously after
- // the loop exits.
- while (!mRequests.isEmpty()) {
- final Consumer<IDreamOverlay> request = mRequests.pop();
- request.accept(mOverlay);
- }
+ @Override
+ public void unbind() {
+ removeCallback(mCallback);
+ super.unbind();
}
- @Override
- public void onServiceConnected(ComponentName name, IBinder service) {
- // Store Overlay and execute pending requests.
- mOverlay = IDreamOverlay.Stub.asInterface(service);
- evaluate();
+ public void addConsumer(Consumer<IDreamOverlay> consumer) {
+ mConsumers.add(consumer);
+ if (mOverlay != null) {
+ consumer.accept(mOverlay);
+ }
}
- @Override
- public void onServiceDisconnected(ComponentName name) {
- // Clear Overlay binder to prevent further request processing.
- mOverlay = null;
+ public void removeConsumer(Consumer<IDreamOverlay> consumer) {
+ mConsumers.remove(consumer);
}
}
@@ -336,7 +329,6 @@ public class DreamService extends Service implements Window.Callback {
public DreamService() {
mDreamManager = IDreamManager.Stub.asInterface(ServiceManager.getService(DREAM_SERVICE));
- mOverlayConnection = new OverlayConnection();
}
/**
@@ -532,7 +524,7 @@ public class DreamService extends Service implements Window.Callback {
return mWindow;
}
- /**
+ /**
* Inflates a layout resource and set it to be the content view for this Dream.
* Behaves similarly to {@link android.app.Activity#setContentView(int)}.
*
@@ -996,13 +988,33 @@ public class DreamService extends Service implements Window.Callback {
public final IBinder onBind(Intent intent) {
if (mDebug) Slog.v(mTag, "onBind() intent = " + intent);
mDreamServiceWrapper = new DreamServiceWrapper();
+ final ComponentName overlayComponent = intent.getParcelableExtra(
+ EXTRA_DREAM_OVERLAY_COMPONENT, ComponentName.class);
// Connect to the overlay service if present.
- if (!mWindowless) {
- mOverlayConnection.bind(
+ if (!mWindowless && overlayComponent != null) {
+ final Resources resources = getResources();
+ final ComponentName dreamService = new ComponentName(this, getClass());
+
+ final ServiceInfo serviceInfo = fetchServiceInfo(this, dreamService);
+ final Intent overlayIntent = new Intent()
+ .setComponent(overlayComponent)
+ .putExtra(EXTRA_SHOW_COMPLICATIONS,
+ fetchShouldShowComplications(this, serviceInfo))
+ .putExtra(EXTRA_DREAM_COMPONENT, dreamService);
+
+ mOverlayConnection = new OverlayConnection(
/* context= */ this,
- intent.getParcelableExtra(EXTRA_DREAM_OVERLAY_COMPONENT, android.content.ComponentName.class),
- new ComponentName(this, getClass()));
+ getMainExecutor(),
+ mHandler,
+ IDreamOverlay.Stub::asInterface,
+ overlayIntent,
+ /* flags= */ Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE,
+ resources.getInteger(R.integer.config_minDreamOverlayDurationMs),
+ resources.getInteger(R.integer.config_dreamOverlayMaxReconnectAttempts),
+ resources.getInteger(R.integer.config_dreamOverlayReconnectTimeoutMs));
+
+ mOverlayConnection.bind();
}
return mDreamServiceWrapper;
@@ -1011,7 +1023,9 @@ public class DreamService extends Service implements Window.Callback {
@Override
public boolean onUnbind(Intent intent) {
// We must unbind from any overlay connection if we are unbound before finishing.
- mOverlayConnection.unbind(this);
+ if (mOverlayConnection != null) {
+ mOverlayConnection.unbind();
+ }
return super.onUnbind(intent);
}
@@ -1040,7 +1054,9 @@ public class DreamService extends Service implements Window.Callback {
}
mFinished = true;
- mOverlayConnection.unbind(this);
+ if (mOverlayConnection != null) {
+ mOverlayConnection.unbind();
+ }
if (mDreamToken == null) {
Slog.w(mTag, "Finish was called before the dream was attached.");
@@ -1337,19 +1353,24 @@ public class DreamService extends Service implements Window.Callback {
mWindow.getDecorView().addOnAttachStateChangeListener(
new View.OnAttachStateChangeListener() {
+ private Consumer<IDreamOverlay> mDreamStartOverlayConsumer;
+
@Override
public void onViewAttachedToWindow(View v) {
mDispatchAfterOnAttachedToWindow.run();
- // Request the DreamOverlay be told to dream with dream's window parameters
- // once the window has been attached.
- mOverlayConnection.request(overlay -> {
- try {
- overlay.startDream(mWindow.getAttributes(), mOverlayCallback);
- } catch (RemoteException e) {
- Log.e(mTag, "could not send window attributes:" + e);
- }
- });
+ if (mOverlayConnection != null) {
+ // Request the DreamOverlay be told to dream with dream's window
+ // parameters once the window has been attached.
+ mDreamStartOverlayConsumer = overlay -> {
+ try {
+ overlay.startDream(mWindow.getAttributes(), mOverlayCallback);
+ } catch (RemoteException e) {
+ Log.e(mTag, "could not send window attributes:" + e);
+ }
+ };
+ mOverlayConnection.addConsumer(mDreamStartOverlayConsumer);
+ }
}
@Override
@@ -1362,6 +1383,9 @@ public class DreamService extends Service implements Window.Callback {
mActivity = null;
finish();
}
+ if (mOverlayConnection != null && mDreamStartOverlayConsumer != null) {
+ mOverlayConnection.removeConsumer(mDreamStartOverlayConsumer);
+ }
}
});
}
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index cb8f0af10c47..d1f05ec0c05e 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -96,13 +96,6 @@ public class FeatureFlagUtils {
/** @hide */
public static final String SETTINGS_AUTO_TEXT_WRAPPING = "settings_auto_text_wrapping";
- /** Flag to enable / disable the Simple Cursor accessibility feature in
- * Settings.
- * @hide
- */
- public static final String SETTINGS_ACCESSIBILITY_SIMPLE_CURSOR =
- "settings_accessibility_simple_cursor";
-
/**
* Enable new language and keyboard settings UI
* @hide
@@ -149,7 +142,6 @@ public class FeatureFlagUtils {
DEFAULT_FLAGS.put(SETTINGS_APP_ALLOW_DARK_THEME_ACTIVATION_AT_BEDTIME, "true");
DEFAULT_FLAGS.put(SETTINGS_HIDE_SECOND_LAYER_PAGE_NAVIGATE_UP_BUTTON_IN_TWO_PANE, "true");
DEFAULT_FLAGS.put(SETTINGS_AUTO_TEXT_WRAPPING, "false");
- DEFAULT_FLAGS.put(SETTINGS_ACCESSIBILITY_SIMPLE_CURSOR, "false");
DEFAULT_FLAGS.put(SETTINGS_NEW_KEYBOARD_UI, "false");
DEFAULT_FLAGS.put(SETTINGS_ENABLE_SPA, "false");
DEFAULT_FLAGS.put(SETTINGS_ADB_METRICS_WRITER, "false");
diff --git a/core/java/android/view/InsetsFrameProvider.java b/core/java/android/view/InsetsFrameProvider.java
index eb8687c47bed..72757807169e 100644
--- a/core/java/android/view/InsetsFrameProvider.java
+++ b/core/java/android/view/InsetsFrameProvider.java
@@ -59,6 +59,7 @@ public class InsetsFrameProvider implements Parcelable {
private static final int HAS_INSETS_SIZE_OVERRIDE = 2;
private static Rect sTmpRect = new Rect();
+ private static Rect sTmpRect2 = new Rect();
/**
* The type of insets to provide.
@@ -88,6 +89,18 @@ public class InsetsFrameProvider implements Parcelable {
*/
public InsetsSizeOverride[] insetsSizeOverrides = null;
+ /**
+ * This field, if set, is indicating the insets needs to be at least the given size inside the
+ * display cutout safe area. This will be compared to the insets size calculated based on other
+ * attributes, and will be applied when this is larger. This is independent of the
+ * PRIVATE_FLAG_LAYOUT_SIZE_EXTENDED_BY_CUTOUT in LayoutParams, as this is not going to change
+ * the layout of the window, but only change the insets frame. This can be applied to insets
+ * calculated based on all three source frames.
+ *
+ * Be cautious, this will not be in effect for the window types whose insets size is overridden.
+ */
+ public Insets minimalInsetsSizeInDisplayCutoutSafe = null;
+
public InsetsFrameProvider(int type) {
this(type, SOURCE_FRAME, null, null);
}
@@ -202,7 +215,8 @@ public class InsetsFrameProvider implements Parcelable {
public static void calculateInsetsFrame(Rect displayFrame, Rect containerBounds,
Rect displayCutoutSafe, Rect inOutFrame, int source, Insets insetsSize,
- @WindowManager.LayoutParams.PrivateFlags int privateFlags) {
+ @WindowManager.LayoutParams.PrivateFlags int privateFlags,
+ Insets displayCutoutSafeInsetsSize) {
boolean extendByCutout = false;
if (source == InsetsFrameProvider.SOURCE_DISPLAY) {
inOutFrame.set(displayFrame);
@@ -214,6 +228,33 @@ public class InsetsFrameProvider implements Parcelable {
if (insetsSize == null) {
return;
}
+ if (displayCutoutSafeInsetsSize != null) {
+ sTmpRect2.set(inOutFrame);
+ }
+ calculateInsetsFrame(inOutFrame, insetsSize);
+
+ if (extendByCutout) {
+ WindowLayout.extendFrameByCutout(displayCutoutSafe, displayFrame, inOutFrame, sTmpRect);
+ }
+
+ if (displayCutoutSafeInsetsSize != null) {
+ // The insets is at least with the given size within the display cutout safe area.
+ // Calculate the smallest size.
+ calculateInsetsFrame(sTmpRect2, displayCutoutSafeInsetsSize);
+ WindowLayout.extendFrameByCutout(displayCutoutSafe, displayFrame, sTmpRect2, sTmpRect);
+ // If it's larger than previous calculation, use it.
+ if (sTmpRect2.contains(inOutFrame)) {
+ inOutFrame.set(sTmpRect2);
+ }
+ }
+ }
+
+ /**
+ * Calculate the insets frame given the insets size and the source frame.
+ * @param inOutFrame the source frame.
+ * @param insetsSize the insets size. Only the first non-zero value will be taken.
+ */
+ private static void calculateInsetsFrame(Rect inOutFrame, Insets insetsSize) {
// Only one side of the provider shall be applied. Check in the order of left - top -
// right - bottom, only the first non-zero value will be applied.
if (insetsSize.left != 0) {
@@ -227,10 +268,6 @@ public class InsetsFrameProvider implements Parcelable {
} else {
inOutFrame.setEmpty();
}
-
- if (extendByCutout) {
- WindowLayout.extendFrameByCutout(displayCutoutSafe, displayFrame, inOutFrame, sTmpRect);
- }
}
/**
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index bc665cf09652..5c899e489347 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -12538,6 +12538,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
if (!enabled) {
cancelPendingInputEvents();
}
+ notifyViewAccessibilityStateChangedIfNeeded(
+ AccessibilityEvent.CONTENT_CHANGE_TYPE_ENABLED);
}
/**
diff --git a/core/java/android/view/accessibility/AccessibilityEvent.java b/core/java/android/view/accessibility/AccessibilityEvent.java
index f86f51fc0022..b0cf504ec568 100644
--- a/core/java/android/view/accessibility/AccessibilityEvent.java
+++ b/core/java/android/view/accessibility/AccessibilityEvent.java
@@ -709,6 +709,18 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par
*/
public static final int CONTENT_CHANGE_TYPE_ERROR = 0x0000800;
+ /**
+ * Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event:
+ * The source node changed its ability to interact returned by
+ * {@link AccessibilityNodeInfo#isEnabled}.
+ * The view changing content's ability to interact should call
+ * {@link AccessibilityNodeInfo#setEnabled} and then send this event.
+ *
+ * @see AccessibilityNodeInfo#isEnabled
+ * @see AccessibilityNodeInfo#setEnabled
+ */
+ public static final int CONTENT_CHANGE_TYPE_ENABLED = 1 << 12;
+
/** Change type for {@link #TYPE_SPEECH_STATE_CHANGE} event: another service is speaking. */
public static final int SPEECH_STATE_SPEAKING_START = 0x00000001;
@@ -836,6 +848,7 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par
CONTENT_CHANGE_TYPE_DRAG_CANCELLED,
CONTENT_CHANGE_TYPE_CONTENT_INVALID,
CONTENT_CHANGE_TYPE_ERROR,
+ CONTENT_CHANGE_TYPE_ENABLED,
})
public @interface ContentChangeTypes {}
@@ -1105,6 +1118,7 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par
case CONTENT_CHANGE_TYPE_CONTENT_INVALID:
return "CONTENT_CHANGE_TYPE_CONTENT_INVALID";
case CONTENT_CHANGE_TYPE_ERROR: return "CONTENT_CHANGE_TYPE_ERROR";
+ case CONTENT_CHANGE_TYPE_ENABLED: return "CONTENT_CHANGE_TYPE_ENABLED";
default: return Integer.toHexString(type);
}
}
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 307c55cfc2e7..d0405f0e5991 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -267,6 +267,12 @@ import java.util.function.Consumer;
* they can switch to it, to confirm with the system that they know about it
* and want to make it available for use.</p>
* </ul>
+ *
+ * <p>If your app targets Android 11 (API level 30) or higher, the methods in
+ * this class each return a filtered result by the rules of
+ * <a href="/training/basics/intents/package-visibility">package visibility</a>,
+ * except for the currently connected IME. Apps having a query for the
+ * {@link InputMethod#SERVICE_INTERFACE} see all IMEs.</p>
*/
@SystemService(Context.INPUT_METHOD_SERVICE)
@RequiresFeature(PackageManager.FEATURE_INPUT_METHODS)
diff --git a/core/java/com/android/internal/util/ObservableServiceConnection.java b/core/java/com/android/internal/util/ObservableServiceConnection.java
new file mode 100644
index 000000000000..3165d293bd91
--- /dev/null
+++ b/core/java/com/android/internal/util/ObservableServiceConnection.java
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 2022 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.internal.util;
+
+import android.annotation.CallbackExecutor;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.IBinder;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.CallbackRegistry.NotifierCallback;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.concurrent.Executor;
+
+/**
+ * {@link ObservableServiceConnection} is a concrete implementation of {@link ServiceConnection}
+ * that enables monitoring the status of a binder connection. It also aides in automatically
+ * converting a proxy into an internal wrapper type.
+ *
+ * @param <T> The type of the wrapper over the resulting service.
+ */
+public class ObservableServiceConnection<T> implements ServiceConnection {
+ /**
+ * An interface for converting the service proxy into a given internal wrapper type.
+ *
+ * @param <T> The type of the wrapper over the resulting service.
+ */
+ public interface ServiceTransformer<T> {
+ /**
+ * Called to convert the service proxy to the wrapper type.
+ *
+ * @param service The service proxy to create the wrapper type from.
+ * @return The wrapper type.
+ */
+ T convert(IBinder service);
+ }
+
+ /**
+ * An interface for listening to the connection status.
+ *
+ * @param <T> The wrapper type.
+ */
+ public interface Callback<T> {
+ /**
+ * Invoked when the service has been successfully connected to.
+ *
+ * @param connection The {@link ObservableServiceConnection} instance that is now connected
+ * @param service The service proxy converted into the typed wrapper.
+ */
+ void onConnected(ObservableServiceConnection<T> connection, T service);
+
+ /**
+ * Invoked when the service has been disconnected.
+ *
+ * @param connection The {@link ObservableServiceConnection} that is now disconnected.
+ * @param reason The reason for the disconnection.
+ */
+ void onDisconnected(ObservableServiceConnection<T> connection,
+ @DisconnectReason int reason);
+ }
+
+ /**
+ * Default state, service has not yet disconnected.
+ */
+ public static final int DISCONNECT_REASON_NONE = 0;
+ /**
+ * Disconnection was due to the resulting binding being {@code null}.
+ */
+ public static final int DISCONNECT_REASON_NULL_BINDING = 1;
+ /**
+ * Disconnection was due to the remote end disconnecting.
+ */
+ public static final int DISCONNECT_REASON_DISCONNECTED = 2;
+ /**
+ * Disconnection due to the binder dying.
+ */
+ public static final int DISCONNECT_REASON_BINDING_DIED = 3;
+ /**
+ * Disconnection from an explicit unbinding.
+ */
+ public static final int DISCONNECT_REASON_UNBIND = 4;
+
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({
+ DISCONNECT_REASON_NONE,
+ DISCONNECT_REASON_NULL_BINDING,
+ DISCONNECT_REASON_DISCONNECTED,
+ DISCONNECT_REASON_BINDING_DIED,
+ DISCONNECT_REASON_UNBIND
+ })
+ public @interface DisconnectReason {
+ }
+
+ private final Object mLock = new Object();
+ private final Context mContext;
+ private final Executor mExecutor;
+ private final ServiceTransformer<T> mTransformer;
+ private final Intent mServiceIntent;
+ private final int mFlags;
+
+ @GuardedBy("mLock")
+ private T mService;
+ @GuardedBy("mLock")
+ private boolean mBoundCalled = false;
+ @GuardedBy("mLock")
+ private int mLastDisconnectReason = DISCONNECT_REASON_NONE;
+
+ private final CallbackRegistry<Callback<T>, ObservableServiceConnection<T>, T>
+ mCallbackRegistry = new CallbackRegistry<>(
+ new NotifierCallback<Callback<T>, ObservableServiceConnection<T>, T>() {
+ @Override
+ public void onNotifyCallback(Callback<T> callback,
+ ObservableServiceConnection<T> sender,
+ int disconnectReason, T service) {
+ mExecutor.execute(() -> {
+ synchronized (mLock) {
+ if (service != null) {
+ callback.onConnected(sender, service);
+ } else if (mLastDisconnectReason != DISCONNECT_REASON_NONE) {
+ callback.onDisconnected(sender, disconnectReason);
+ }
+ }
+ });
+ }
+ });
+
+ /**
+ * Default constructor for {@link ObservableServiceConnection}.
+ *
+ * @param context The context from which the service will be bound with.
+ * @param executor The executor for connection callbacks to be delivered on
+ * @param transformer A {@link ObservableServiceConnection.ServiceTransformer} for transforming
+ * the resulting service into a desired type.
+ */
+ public ObservableServiceConnection(@NonNull Context context,
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull ServiceTransformer<T> transformer,
+ Intent serviceIntent,
+ int flags) {
+ mContext = context;
+ mExecutor = executor;
+ mTransformer = transformer;
+ mServiceIntent = serviceIntent;
+ mFlags = flags;
+ }
+
+ /**
+ * Initiate binding to the service.
+ *
+ * @return {@code true} if initiating binding succeed, {@code false} if the binding failed or
+ * if this service is already bound. Regardless of the return value, you should later call
+ * {@link #unbind()} to release the connection.
+ */
+ public boolean bind() {
+ synchronized (mLock) {
+ if (mBoundCalled) {
+ return false;
+ }
+ final boolean bindResult =
+ mContext.bindService(mServiceIntent, mFlags, mExecutor, this);
+ mBoundCalled = true;
+ return bindResult;
+ }
+ }
+
+ /**
+ * Disconnect from the service if bound.
+ */
+ public void unbind() {
+ onDisconnected(DISCONNECT_REASON_UNBIND);
+ }
+
+ /**
+ * Adds a callback for receiving connection updates.
+ *
+ * @param callback The {@link Callback} to receive future updates.
+ */
+ public void addCallback(Callback<T> callback) {
+ mCallbackRegistry.add(callback);
+ mExecutor.execute(() -> {
+ synchronized (mLock) {
+ if (mService != null) {
+ callback.onConnected(this, mService);
+ } else if (mLastDisconnectReason != DISCONNECT_REASON_NONE) {
+ callback.onDisconnected(this, mLastDisconnectReason);
+ }
+ }
+ });
+ }
+
+ /**
+ * Removes previously added callback from receiving future connection updates.
+ *
+ * @param callback The {@link Callback} to be removed.
+ */
+ public void removeCallback(Callback<T> callback) {
+ synchronized (mLock) {
+ mCallbackRegistry.remove(callback);
+ }
+ }
+
+ private void onDisconnected(@DisconnectReason int reason) {
+ synchronized (mLock) {
+ if (!mBoundCalled) {
+ return;
+ }
+ mBoundCalled = false;
+ mLastDisconnectReason = reason;
+ mContext.unbindService(this);
+ mService = null;
+ mCallbackRegistry.notifyCallbacks(this, reason, null);
+ }
+ }
+
+ @Override
+ public final void onServiceConnected(ComponentName name, IBinder service) {
+ synchronized (mLock) {
+ mService = mTransformer.convert(service);
+ mLastDisconnectReason = DISCONNECT_REASON_NONE;
+ mCallbackRegistry.notifyCallbacks(this, mLastDisconnectReason, mService);
+ }
+ }
+
+ @Override
+ public final void onServiceDisconnected(ComponentName name) {
+ onDisconnected(DISCONNECT_REASON_DISCONNECTED);
+ }
+
+ @Override
+ public final void onBindingDied(ComponentName name) {
+ onDisconnected(DISCONNECT_REASON_BINDING_DIED);
+ }
+
+ @Override
+ public final void onNullBinding(ComponentName name) {
+ onDisconnected(DISCONNECT_REASON_NULL_BINDING);
+ }
+}
diff --git a/core/java/com/android/internal/util/PersistentServiceConnection.java b/core/java/com/android/internal/util/PersistentServiceConnection.java
new file mode 100644
index 000000000000..d2017347bd64
--- /dev/null
+++ b/core/java/com/android/internal/util/PersistentServiceConnection.java
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2022 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.internal.util;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.Handler;
+import android.os.SystemClock;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.concurrent.Executor;
+
+/**
+ * {@link PersistentServiceConnection} is a concrete implementation of {@link ServiceConnection}
+ * that maintains the binder connection by handling reconnection when a failure occurs.
+ *
+ * @param <T> The transformed connection type handled by the service.
+ *
+ * When the target process is killed (by OOM-killer, force-stopped, crash, etc..) then this class
+ * will trigger a reconnection to the target. This should be used carefully.
+ *
+ * NOTE: This class does *not* handle package-updates -- i.e. even if the binding dies due to
+ * the target package being updated, this class won't reconnect. This is because this class doesn't
+ * know what to do when the service component has gone missing, for example. If the user of this
+ * class wants to restore the connection, then it should call {@link #unbind()} and {@link #bind}
+ * explicitly.
+ */
+public class PersistentServiceConnection<T> extends ObservableServiceConnection<T> {
+ private final Callback<T> mConnectionCallback = new Callback<T>() {
+ private long mConnectedTime;
+
+ @Override
+ public void onConnected(ObservableServiceConnection<T> connection, T service) {
+ mConnectedTime = mInjector.uptimeMillis();
+ }
+
+ @Override
+ public void onDisconnected(ObservableServiceConnection<T> connection,
+ @DisconnectReason int reason) {
+ if (reason == DISCONNECT_REASON_UNBIND) return;
+ synchronized (mLock) {
+ if ((mInjector.uptimeMillis() - mConnectedTime) > mMinConnectionDurationMs) {
+ mReconnectAttempts = 0;
+ bindInternalLocked();
+ } else {
+ scheduleConnectionAttemptLocked();
+ }
+ }
+ }
+ };
+
+ private final Object mLock = new Object();
+ private final Injector mInjector;
+ private final Handler mHandler;
+ private final int mMinConnectionDurationMs;
+ private final int mMaxReconnectAttempts;
+ private final int mBaseReconnectDelayMs;
+ @GuardedBy("mLock")
+ private int mReconnectAttempts;
+ @GuardedBy("mLock")
+ private Object mCancelToken;
+
+ private final Runnable mConnectRunnable = new Runnable() {
+ @Override
+ public void run() {
+ synchronized (mLock) {
+ mCancelToken = null;
+ bindInternalLocked();
+ }
+ }
+ };
+
+ /**
+ * Default constructor for {@link PersistentServiceConnection}.
+ *
+ * @param context The context from which the service will be bound with.
+ * @param executor The executor for connection callbacks to be delivered on
+ * @param transformer A {@link ServiceTransformer} for transforming
+ */
+ public PersistentServiceConnection(Context context,
+ Executor executor,
+ Handler handler,
+ ServiceTransformer<T> transformer,
+ Intent serviceIntent,
+ int flags,
+ int minConnectionDurationMs,
+ int maxReconnectAttempts,
+ int baseReconnectDelayMs) {
+ this(context,
+ executor,
+ handler,
+ transformer,
+ serviceIntent,
+ flags,
+ minConnectionDurationMs,
+ maxReconnectAttempts,
+ baseReconnectDelayMs,
+ new Injector());
+ }
+
+ @VisibleForTesting
+ public PersistentServiceConnection(
+ Context context,
+ Executor executor,
+ Handler handler,
+ ServiceTransformer<T> transformer,
+ Intent serviceIntent,
+ int flags,
+ int minConnectionDurationMs,
+ int maxReconnectAttempts,
+ int baseReconnectDelayMs,
+ Injector injector) {
+ super(context, executor, transformer, serviceIntent, flags);
+ mHandler = handler;
+ mMinConnectionDurationMs = minConnectionDurationMs;
+ mMaxReconnectAttempts = maxReconnectAttempts;
+ mBaseReconnectDelayMs = baseReconnectDelayMs;
+ mInjector = injector;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean bind() {
+ synchronized (mLock) {
+ addCallback(mConnectionCallback);
+ mReconnectAttempts = 0;
+ return bindInternalLocked();
+ }
+ }
+
+ @GuardedBy("mLock")
+ private boolean bindInternalLocked() {
+ return super.bind();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void unbind() {
+ synchronized (mLock) {
+ removeCallback(mConnectionCallback);
+ cancelPendingConnectionAttemptLocked();
+ super.unbind();
+ }
+ }
+
+ @GuardedBy("mLock")
+ private void cancelPendingConnectionAttemptLocked() {
+ if (mCancelToken != null) {
+ mHandler.removeCallbacksAndMessages(mCancelToken);
+ mCancelToken = null;
+ }
+ }
+
+ @GuardedBy("mLock")
+ private void scheduleConnectionAttemptLocked() {
+ cancelPendingConnectionAttemptLocked();
+
+ if (mReconnectAttempts >= mMaxReconnectAttempts) {
+ return;
+ }
+
+ final long reconnectDelayMs =
+ (long) Math.scalb(mBaseReconnectDelayMs, mReconnectAttempts);
+
+ mCancelToken = new Object();
+ mHandler.postDelayed(mConnectRunnable, mCancelToken, reconnectDelayMs);
+ mReconnectAttempts++;
+ }
+
+ /**
+ * Injector for testing
+ */
+ @VisibleForTesting
+ public static class Injector {
+ /**
+ * Returns milliseconds since boot, not counting time spent in deep sleep. Can be overridden
+ * in tests with a fake clock.
+ */
+ public long uptimeMillis() {
+ return SystemClock.uptimeMillis();
+ }
+ }
+}
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 47faf2a2ebf7..38344788a100 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -553,6 +553,14 @@
<!-- If this is true, then keep dreaming when undocking. -->
<bool name="config_keepDreamingWhenUndocking">false</bool>
+ <!-- The timeout (in ms) to wait before attempting to reconnect to the dream overlay service if
+ it becomes disconnected -->
+ <integer name="config_dreamOverlayReconnectTimeoutMs">1000</integer> <!-- 1 second -->
+ <!-- The maximum number of times to attempt reconnecting to the dream overlay service -->
+ <integer name="config_dreamOverlayMaxReconnectAttempts">3</integer>
+ <!-- The duration after which the dream overlay connection should be considered stable -->
+ <integer name="config_minDreamOverlayDurationMs">10000</integer> <!-- 10 seconds -->
+
<!-- Auto-rotation behavior -->
<!-- If true, enables auto-rotation features using the accelerometer.
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index b42db13e1ac2..2fbf8034c27e 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2238,6 +2238,9 @@
<java-symbol type="array" name="config_supportedDreamComplications" />
<java-symbol type="array" name="config_disabledDreamComponents" />
<java-symbol type="bool" name="config_dismissDreamOnActivityStart" />
+ <java-symbol type="integer" name="config_dreamOverlayReconnectTimeoutMs" />
+ <java-symbol type="integer" name="config_dreamOverlayMaxReconnectAttempts" />
+ <java-symbol type="integer" name="config_minDreamOverlayDurationMs" />
<java-symbol type="string" name="config_loggable_dream_prefix" />
<java-symbol type="string" name="config_dozeComponent" />
<java-symbol type="string" name="enable_explore_by_touch_warning_title" />
diff --git a/core/tests/utiltests/Android.bp b/core/tests/utiltests/Android.bp
index adc3676f7b93..3798da592cd5 100644
--- a/core/tests/utiltests/Android.bp
+++ b/core/tests/utiltests/Android.bp
@@ -34,6 +34,7 @@ android_test {
"mockito-target-minus-junit4",
"androidx.test.ext.junit",
"truth-prebuilt",
+ "servicestests-utils",
],
libs: [
diff --git a/core/tests/utiltests/src/com/android/internal/util/ObservableServiceConnectionTest.java b/core/tests/utiltests/src/com/android/internal/util/ObservableServiceConnectionTest.java
new file mode 100644
index 000000000000..d124ad9ddfb0
--- /dev/null
+++ b/core/tests/utiltests/src/com/android/internal/util/ObservableServiceConnectionTest.java
@@ -0,0 +1,226 @@
+/*
+ * Copyright (C) 2022 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.internal.util;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.os.IBinder;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.util.ObservableServiceConnection.ServiceTransformer;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.ArrayDeque;
+import java.util.Objects;
+import java.util.Queue;
+import java.util.concurrent.Executor;
+
+@SmallTest
+public class ObservableServiceConnectionTest {
+ private static final ComponentName COMPONENT_NAME =
+ new ComponentName("test.package", "component");
+
+ public static class Foo {
+ int mValue;
+
+ Foo(int value) {
+ mValue = value;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof Foo)) return false;
+ Foo foo = (Foo) o;
+ return mValue == foo.mValue;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mValue);
+ }
+ }
+
+
+ @Mock
+ private Context mContext;
+ @Mock
+ private Intent mIntent;
+ @Mock
+ private Foo mResult;
+ @Mock
+ private IBinder mBinder;
+ @Mock
+ private ServiceTransformer<Foo> mTransformer;
+ @Mock
+ private ObservableServiceConnection.Callback<Foo> mCallback;
+ private final FakeExecutor mExecutor = new FakeExecutor();
+ private ObservableServiceConnection<Foo> mConnection;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ mConnection = new ObservableServiceConnection<>(
+ mContext,
+ mExecutor,
+ mTransformer,
+ mIntent,
+ /* flags= */ Context.BIND_AUTO_CREATE);
+ }
+
+ @After
+ public void tearDown() {
+ mExecutor.clearAll();
+ }
+
+ @Test
+ public void testConnect() {
+ // Register twice to ensure only one callback occurs.
+ mConnection.addCallback(mCallback);
+ mConnection.addCallback(mCallback);
+
+ mExecutor.runAll();
+ mConnection.bind();
+
+ // Ensure that no callbacks happen before connection.
+ verify(mCallback, never()).onConnected(any(), any());
+ verify(mCallback, never()).onDisconnected(any(), anyInt());
+
+ when(mTransformer.convert(mBinder)).thenReturn(mResult);
+ mConnection.onServiceConnected(COMPONENT_NAME, mBinder);
+
+ mExecutor.runAll();
+ verify(mCallback, times(1)).onConnected(mConnection, mResult);
+ }
+
+ @Test
+ public void testDisconnectBeforeBind() {
+ mConnection.addCallback(mCallback);
+ mExecutor.runAll();
+ mConnection.onServiceDisconnected(COMPONENT_NAME);
+ mExecutor.runAll();
+ // Disconnects before binds should be ignored.
+ verify(mCallback, never()).onDisconnected(eq(mConnection), anyInt());
+ }
+
+ @Test
+ public void testDisconnect() {
+ mConnection.addCallback(mCallback);
+ mExecutor.runAll();
+ mConnection.bind();
+ mConnection.onServiceDisconnected(COMPONENT_NAME);
+
+ // Ensure the callback doesn't get triggered until the executor runs.
+ verify(mCallback, never()).onDisconnected(eq(mConnection), anyInt());
+ mExecutor.runAll();
+ // Ensure proper disconnect reason reported.
+ verify(mCallback, times(1)).onDisconnected(mConnection,
+ ObservableServiceConnection.DISCONNECT_REASON_DISCONNECTED);
+ // Verify unbound from service.
+ verify(mContext, times(1)).unbindService(mConnection);
+
+ clearInvocations(mContext);
+ // Ensure unbind after disconnect has no effect on the connection
+ mConnection.unbind();
+ verify(mContext, never()).unbindService(mConnection);
+ }
+
+ @Test
+ public void testBindingDied() {
+ mConnection.addCallback(mCallback);
+ mExecutor.runAll();
+ mConnection.bind();
+ mConnection.onBindingDied(COMPONENT_NAME);
+
+ // Ensure the callback doesn't get triggered until the executor runs.
+ verify(mCallback, never()).onDisconnected(eq(mConnection), anyInt());
+ mExecutor.runAll();
+ // Ensure proper disconnect reason reported.
+ verify(mCallback, times(1)).onDisconnected(mConnection,
+ ObservableServiceConnection.DISCONNECT_REASON_BINDING_DIED);
+ // Verify unbound from service.
+ verify(mContext, times(1)).unbindService(mConnection);
+ }
+
+ @Test
+ public void testNullBinding() {
+ mConnection.addCallback(mCallback);
+ mExecutor.runAll();
+ mConnection.bind();
+ mConnection.onNullBinding(COMPONENT_NAME);
+
+ // Ensure the callback doesn't get triggered until the executor runs.
+ verify(mCallback, never()).onDisconnected(eq(mConnection), anyInt());
+ mExecutor.runAll();
+ // Ensure proper disconnect reason reported.
+ verify(mCallback, times(1)).onDisconnected(mConnection,
+ ObservableServiceConnection.DISCONNECT_REASON_NULL_BINDING);
+ // Verify unbound from service.
+ verify(mContext, times(1)).unbindService(mConnection);
+ }
+
+ @Test
+ public void testUnbind() {
+ mConnection.addCallback(mCallback);
+ mExecutor.runAll();
+ mConnection.bind();
+ mConnection.unbind();
+
+ // Ensure the callback doesn't get triggered until the executor runs.
+ verify(mCallback, never()).onDisconnected(eq(mConnection), anyInt());
+ mExecutor.runAll();
+ verify(mCallback).onDisconnected(mConnection,
+ ObservableServiceConnection.DISCONNECT_REASON_UNBIND);
+ }
+
+ static class FakeExecutor implements Executor {
+ private final Queue<Runnable> mQueue = new ArrayDeque<>();
+
+ @Override
+ public void execute(Runnable command) {
+ mQueue.add(command);
+ }
+
+ public void runAll() {
+ while (!mQueue.isEmpty()) {
+ mQueue.remove().run();
+ }
+ }
+
+ public void clearAll() {
+ while (!mQueue.isEmpty()) {
+ mQueue.remove();
+ }
+ }
+ }
+}
diff --git a/core/tests/utiltests/src/com/android/internal/util/PersistentServiceConnectionTest.java b/core/tests/utiltests/src/com/android/internal/util/PersistentServiceConnectionTest.java
new file mode 100644
index 000000000000..fee46545ac62
--- /dev/null
+++ b/core/tests/utiltests/src/com/android/internal/util/PersistentServiceConnectionTest.java
@@ -0,0 +1,215 @@
+/*
+ * Copyright (C) 2022 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.internal.util;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.os.IBinder;
+
+import com.android.internal.util.ObservableServiceConnection.ServiceTransformer;
+import com.android.server.testutils.OffsettableClock;
+import com.android.server.testutils.TestHandler;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.ArrayDeque;
+import java.util.Queue;
+import java.util.concurrent.Executor;
+
+public class PersistentServiceConnectionTest {
+ private static final ComponentName COMPONENT_NAME =
+ new ComponentName("test.package", "component");
+ private static final int MAX_RETRIES = 2;
+ private static final int RETRY_DELAY_MS = 1000;
+ private static final int CONNECTION_MIN_DURATION_MS = 5000;
+ private PersistentServiceConnection<Proxy> mConnection;
+
+ public static class Proxy {
+ }
+
+ @Mock
+ private Context mContext;
+ @Mock
+ private Intent mIntent;
+ @Mock
+ private Proxy mResult;
+ @Mock
+ private IBinder mBinder;
+ @Mock
+ private ServiceTransformer<Proxy> mTransformer;
+ @Mock
+ private ObservableServiceConnection.Callback<Proxy> mCallback;
+ private TestHandler mHandler;
+ private final FakeExecutor mFakeExecutor = new FakeExecutor();
+ private OffsettableClock mClock;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+
+ mClock = new OffsettableClock.Stopped();
+ mHandler = spy(new TestHandler(null, mClock));
+
+ mConnection = new PersistentServiceConnection<>(
+ mContext,
+ mFakeExecutor,
+ mHandler,
+ mTransformer,
+ mIntent,
+ /* flags= */ Context.BIND_AUTO_CREATE,
+ CONNECTION_MIN_DURATION_MS,
+ MAX_RETRIES,
+ RETRY_DELAY_MS,
+ new TestInjector(mClock));
+
+ mClock.fastForward(1000);
+ mConnection.addCallback(mCallback);
+ when(mTransformer.convert(mBinder)).thenReturn(mResult);
+ }
+
+ @After
+ public void tearDown() {
+ mFakeExecutor.clearAll();
+ }
+
+ @Test
+ public void testConnect() {
+ mConnection.bind();
+ mConnection.onServiceConnected(COMPONENT_NAME, mBinder);
+ mFakeExecutor.runAll();
+ // Ensure that we did not schedule a retry
+ verify(mHandler, never()).postDelayed(any(), anyLong());
+ }
+
+ @Test
+ public void testRetryOnBindFailure() {
+ mConnection.bind();
+
+ verify(mContext, times(1)).bindService(
+ eq(mIntent),
+ anyInt(),
+ eq(mFakeExecutor),
+ eq(mConnection));
+
+ // After disconnect, a reconnection should be attempted after the RETRY_DELAY_MS
+ mConnection.onServiceDisconnected(COMPONENT_NAME);
+ mFakeExecutor.runAll();
+ advanceTime(RETRY_DELAY_MS);
+ verify(mContext, times(2)).bindService(
+ eq(mIntent),
+ anyInt(),
+ eq(mFakeExecutor),
+ eq(mConnection));
+
+ // Reconnect attempt #2
+ mConnection.onServiceDisconnected(COMPONENT_NAME);
+ mFakeExecutor.runAll();
+ advanceTime(RETRY_DELAY_MS * 2);
+ verify(mContext, times(3)).bindService(
+ eq(mIntent),
+ anyInt(),
+ eq(mFakeExecutor),
+ eq(mConnection));
+
+ // There should be no more reconnect attempts, since the maximum is 2
+ mConnection.onServiceDisconnected(COMPONENT_NAME);
+ mFakeExecutor.runAll();
+ advanceTime(RETRY_DELAY_MS * 4);
+ verify(mContext, times(3)).bindService(
+ eq(mIntent),
+ anyInt(),
+ eq(mFakeExecutor),
+ eq(mConnection));
+ }
+
+ @Test
+ public void testManualUnbindDoesNotReconnect() {
+ mConnection.bind();
+
+ verify(mContext, times(1)).bindService(
+ eq(mIntent),
+ anyInt(),
+ eq(mFakeExecutor),
+ eq(mConnection));
+
+ mConnection.unbind();
+ // Ensure that disconnection after unbind does not reconnect.
+ mConnection.onServiceDisconnected(COMPONENT_NAME);
+ mFakeExecutor.runAll();
+ advanceTime(RETRY_DELAY_MS);
+
+ verify(mContext, times(1)).bindService(
+ eq(mIntent),
+ anyInt(),
+ eq(mFakeExecutor),
+ eq(mConnection));
+ }
+
+ private void advanceTime(long millis) {
+ mClock.fastForward(millis);
+ mHandler.timeAdvance();
+ }
+
+ static class TestInjector extends PersistentServiceConnection.Injector {
+ private final OffsettableClock mClock;
+
+ TestInjector(OffsettableClock clock) {
+ mClock = clock;
+ }
+
+ @Override
+ public long uptimeMillis() {
+ return mClock.now();
+ }
+ }
+
+ static class FakeExecutor implements Executor {
+ private final Queue<Runnable> mQueue = new ArrayDeque<>();
+
+ @Override
+ public void execute(Runnable command) {
+ mQueue.add(command);
+ }
+
+ public void runAll() {
+ while (!mQueue.isEmpty()) {
+ mQueue.remove().run();
+ }
+ }
+
+ public void clearAll() {
+ while (!mQueue.isEmpty()) {
+ mQueue.remove();
+ }
+ }
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
index 419e62daf586..c2ad1a98d167 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
@@ -118,6 +118,7 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
private boolean mFreezeDividerWindow = false;
private int mOrientation;
private int mRotation;
+ private int mDensity;
private final boolean mDimNonImeSide;
@@ -290,9 +291,11 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
final int rotation = configuration.windowConfiguration.getRotation();
final Rect rootBounds = configuration.windowConfiguration.getBounds();
final int orientation = configuration.orientation;
+ final int density = configuration.densityDpi;
if (mOrientation == orientation
&& mRotation == rotation
+ && mDensity == density
&& mRootBounds.equals(rootBounds)) {
return false;
}
@@ -303,6 +306,7 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
mTempRect.set(mRootBounds);
mRootBounds.set(rootBounds);
mRotation = rotation;
+ mDensity = density;
mDividerSnapAlgorithm = getSnapAlgorithm(mContext, mRootBounds, null);
initDividerPosition(mTempRect);
updateInvisibleRect();
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppTransition.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppTransition.kt
index 3d8525b3d4ad..1dc03b9b8900 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppTransition.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppTransition.kt
@@ -18,12 +18,12 @@ package com.android.wm.shell.flicker.pip
import android.platform.test.annotations.Presubmit
import com.android.server.wm.flicker.FlickerTestParameter
-import com.android.server.wm.flicker.helpers.FixedOrientationAppHelper
+import com.android.server.wm.flicker.helpers.SimpleAppHelper
import org.junit.Test
/** Base class for pip expand tests */
abstract class ExitPipToAppTransition(testSpec: FlickerTestParameter) : PipTransition(testSpec) {
- protected val testApp = FixedOrientationAppHelper(instrumentation)
+ protected val testApp = SimpleAppHelper(instrumentation)
/**
* Checks that the pip app window remains inside the display bounds throughout the whole
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java
index 695550dd8fa5..f6d6c03bc2ee 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java
@@ -16,6 +16,7 @@
package com.android.wm.shell.common.split;
+import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static com.google.common.truth.Truth.assertThat;
@@ -91,6 +92,14 @@ public class SplitLayoutTests extends ShellTestCase {
// Verify updateConfiguration returns true if the root bounds changed.
config.windowConfiguration.setBounds(new Rect(0, 0, 2160, 1080));
assertThat(mSplitLayout.updateConfiguration(config)).isTrue();
+
+ // Verify updateConfiguration returns true if the orientation changed.
+ config.orientation = ORIENTATION_LANDSCAPE;
+ assertThat(mSplitLayout.updateConfiguration(config)).isTrue();
+
+ // Verify updateConfiguration returns true if the density changed.
+ config.densityDpi = 123;
+ assertThat(mSplitLayout.updateConfiguration(config)).isTrue();
}
@Test
diff --git a/libs/androidfw/AssetManager2.cpp b/libs/androidfw/AssetManager2.cpp
index 235700b27c25..1381bdd6a50d 100644
--- a/libs/androidfw/AssetManager2.cpp
+++ b/libs/androidfw/AssetManager2.cpp
@@ -1068,7 +1068,7 @@ base::expected<const ResolvedBag*, NullOrIOError> AssetManager2::ResolveBag(
base::expected<const ResolvedBag*, NullOrIOError> AssetManager2::GetBag(uint32_t resid) const {
std::vector<uint32_t> found_resids;
const auto bag = GetBag(resid, found_resids);
- cached_bag_resid_stacks_.emplace(resid, found_resids);
+ cached_bag_resid_stacks_.emplace(resid, std::move(found_resids));
return bag;
}
@@ -1468,7 +1468,6 @@ base::expected<std::monostate, NullOrIOError> Theme::ApplyStyle(uint32_t resid,
continue;
}
- Theme::Entry new_entry{attr_res_id, it->cookie, (*bag)->type_spec_flags, it->value};
auto entry_it = std::lower_bound(entries_.begin(), entries_.end(), attr_res_id,
ThemeEntryKeyComparer{});
if (entry_it != entries_.end() && entry_it->attr_res_id == attr_res_id) {
@@ -1477,10 +1476,10 @@ base::expected<std::monostate, NullOrIOError> Theme::ApplyStyle(uint32_t resid,
/// true.
entries_.erase(entry_it);
} else if (force) {
- *entry_it = new_entry;
+ *entry_it = Entry{attr_res_id, it->cookie, (*bag)->type_spec_flags, it->value};
}
} else {
- entries_.insert(entry_it, new_entry);
+ entries_.insert(entry_it, Entry{attr_res_id, it->cookie, (*bag)->type_spec_flags, it->value});
}
}
return {};
diff --git a/media/java/android/media/tv/tuner/TunerVersionChecker.java b/media/java/android/media/tv/tuner/TunerVersionChecker.java
index 3e13bed0afbd..f29a93cbb228 100644
--- a/media/java/android/media/tv/tuner/TunerVersionChecker.java
+++ b/media/java/android/media/tv/tuner/TunerVersionChecker.java
@@ -59,6 +59,10 @@ public final class TunerVersionChecker {
* Tuner version 2.0.
*/
public static final int TUNER_VERSION_2_0 = (2 << 16);
+ /**
+ * Tuner version 3.0.
+ */
+ public static final int TUNER_VERSION_3_0 = (3 << 16);
/**
* Get the current running Tuner version.
diff --git a/media/java/android/media/tv/tuner/dvr/DvrPlayback.java b/media/java/android/media/tv/tuner/dvr/DvrPlayback.java
index 11e699981e80..06802409baf7 100644
--- a/media/java/android/media/tv/tuner/dvr/DvrPlayback.java
+++ b/media/java/android/media/tv/tuner/dvr/DvrPlayback.java
@@ -23,6 +23,7 @@ import android.annotation.SystemApi;
import android.media.tv.tuner.Tuner;
import android.media.tv.tuner.Tuner.Result;
import android.media.tv.tuner.TunerUtils;
+import android.media.tv.tuner.TunerVersionChecker;
import android.media.tv.tuner.filter.Filter;
import android.os.ParcelFileDescriptor;
import android.os.Process;
@@ -91,6 +92,7 @@ public class DvrPlayback implements AutoCloseable {
private native int nativeAttachFilter(Filter filter);
private native int nativeDetachFilter(Filter filter);
private native int nativeConfigureDvr(DvrSettings settings);
+ private native int nativeSetStatusCheckIntervalHint(long durationInMs);
private native int nativeStartDvr();
private native int nativeStopDvr();
private native int nativeFlushDvr();
@@ -177,6 +179,35 @@ public class DvrPlayback implements AutoCloseable {
}
/**
+ * Set playback buffer status check time interval.
+ *
+ * This status check time interval will be used by the Dvr to decide how often to evaluate
+ * data. The default value will be decided by HAL if it’s not set.
+ *
+ * <p>This functionality is only available in Tuner version 3.0 and higher and will otherwise
+ * return a {@link Tuner#RESULT_UNAVAILABLE}. Use {@link TunerVersionChecker#getTunerVersion()}
+ * to get the version information.
+ *
+ * @param durationInMs specifies the duration of the delay in milliseconds.
+ *
+ * @return one of the following results:
+ * {@link Tuner#RESULT_SUCCESS} if succeed,
+ * {@link Tuner#RESULT_UNAVAILABLE} if Dvr is unavailable or unsupported HAL versions,
+ * {@link Tuner#RESULT_NOT_INITIALIZED} if Dvr is not initialized,
+ * {@link Tuner#RESULT_INVALID_STATE} if Dvr is in a wrong state,
+ * {@link Tuner#RESULT_INVALID_ARGUMENT} if the input parameter is invalid.
+ */
+ @Result
+ public int setPlaybackBufferStatusCheckIntervalHint(long durationInMs) {
+ if (!TunerVersionChecker.checkHigherOrEqualVersionTo(
+ TunerVersionChecker.TUNER_VERSION_3_0, "Set status check interval hint")) {
+ // no-op
+ return Tuner.RESULT_UNAVAILABLE;
+ }
+ return nativeSetStatusCheckIntervalHint(durationInMs);
+ }
+
+ /**
* Starts DVR.
*
* <p>Starts consuming playback data or producing data for recording.
diff --git a/media/java/android/media/tv/tuner/dvr/DvrRecorder.java b/media/java/android/media/tv/tuner/dvr/DvrRecorder.java
index e72026aab992..1a658320a1a9 100644
--- a/media/java/android/media/tv/tuner/dvr/DvrRecorder.java
+++ b/media/java/android/media/tv/tuner/dvr/DvrRecorder.java
@@ -22,6 +22,7 @@ import android.annotation.SystemApi;
import android.media.tv.tuner.Tuner;
import android.media.tv.tuner.Tuner.Result;
import android.media.tv.tuner.TunerUtils;
+import android.media.tv.tuner.TunerVersionChecker;
import android.media.tv.tuner.filter.Filter;
import android.os.ParcelFileDescriptor;
import android.os.Process;
@@ -53,6 +54,7 @@ public class DvrRecorder implements AutoCloseable {
private native int nativeAttachFilter(Filter filter);
private native int nativeDetachFilter(Filter filter);
private native int nativeConfigureDvr(DvrSettings settings);
+ private native int nativeSetStatusCheckIntervalHint(long durationInMs);
private native int nativeStartDvr();
private native int nativeStopDvr();
private native int nativeFlushDvr();
@@ -131,6 +133,35 @@ public class DvrRecorder implements AutoCloseable {
}
/**
+ * Set record buffer status check time interval.
+ *
+ * This status check time interval will be used by the Dvr to decide how often to evaluate
+ * data. The default value will be decided by HAL if it’s not set.
+ *
+ * <p>This functionality is only available in Tuner version 3.0 and higher and will otherwise
+ * return a {@link Tuner#RESULT_UNAVAILABLE}. Use {@link TunerVersionChecker#getTunerVersion()}
+ * to get the version information.
+ *
+ * @param durationInMs specifies the duration of the delay in milliseconds.
+ *
+ * @return one of the following results:
+ * {@link Tuner#RESULT_SUCCESS} if succeed,
+ * {@link Tuner#RESULT_UNAVAILABLE} if Dvr is unavailable or unsupported HAL versions,
+ * {@link Tuner#RESULT_NOT_INITIALIZED} if Dvr is not initialized,
+ * {@link Tuner#RESULT_INVALID_STATE} if Dvr is in a wrong state,
+ * {@link Tuner#RESULT_INVALID_ARGUMENT} if the input parameter is invalid.
+ */
+ @Result
+ public int setRecordBufferStatusCheckIntervalHint(long durationInMs) {
+ if (!TunerVersionChecker.checkHigherOrEqualVersionTo(
+ TunerVersionChecker.TUNER_VERSION_3_0, "Set status check interval hint")) {
+ // no-op
+ return Tuner.RESULT_UNAVAILABLE;
+ }
+ return nativeSetStatusCheckIntervalHint(durationInMs);
+ }
+
+ /**
* Starts DVR.
*
* <p>Starts consuming playback data or producing data for recording.
diff --git a/media/jni/Android.bp b/media/jni/Android.bp
index 96a3781af3a8..a0304bb5c04b 100644
--- a/media/jni/Android.bp
+++ b/media/jni/Android.bp
@@ -175,7 +175,7 @@ cc_library_shared {
shared_libs: [
"android.hardware.graphics.bufferqueue@2.0",
- "android.hardware.tv.tuner-V1-ndk",
+ "android.hardware.tv.tuner-V2-ndk",
"libbinder_ndk",
"libandroid_runtime",
"libcutils",
diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp
index 244730b76df2..c18edcd8689b 100644
--- a/media/jni/android_media_tv_Tuner.cpp
+++ b/media/jni/android_media_tv_Tuner.cpp
@@ -4485,6 +4485,17 @@ static jint android_media_tv_Tuner_configure_dvr(JNIEnv *env, jobject dvr, jobje
return (jint)result;
}
+static jint android_media_tv_Tuner_set_status_check_interval_hint(JNIEnv *env, jobject dvr,
+ jlong durationInMs) {
+ sp<DvrClient> dvrClient = getDvrClient(env, dvr);
+ if (dvrClient == nullptr) {
+ ALOGD("Failed to set status check interval hint: dvr client not found");
+ return (int)Result::NOT_INITIALIZED;
+ }
+ Result result = dvrClient->setStatusCheckIntervalHint(durationInMs);
+ return (jint)result;
+}
+
static jint android_media_tv_Tuner_start_dvr(JNIEnv *env, jobject dvr) {
sp<DvrClient> dvrClient = getDvrClient(env, dvr);
if (dvrClient == nullptr) {
@@ -4828,6 +4839,8 @@ static const JNINativeMethod gDvrRecorderMethods[] = {
(void *)android_media_tv_Tuner_detach_filter },
{ "nativeConfigureDvr", "(Landroid/media/tv/tuner/dvr/DvrSettings;)I",
(void *)android_media_tv_Tuner_configure_dvr },
+ { "nativeSetStatusCheckIntervalHint", "(J)I",
+ (void *)android_media_tv_Tuner_set_status_check_interval_hint},
{ "nativeStartDvr", "()I", (void *)android_media_tv_Tuner_start_dvr },
{ "nativeStopDvr", "()I", (void *)android_media_tv_Tuner_stop_dvr },
{ "nativeFlushDvr", "()I", (void *)android_media_tv_Tuner_flush_dvr },
@@ -4844,6 +4857,8 @@ static const JNINativeMethod gDvrPlaybackMethods[] = {
(void *)android_media_tv_Tuner_detach_filter},
{ "nativeConfigureDvr", "(Landroid/media/tv/tuner/dvr/DvrSettings;)I",
(void *)android_media_tv_Tuner_configure_dvr},
+ { "nativeSetStatusCheckIntervalHint", "(J)I",
+ (void *)android_media_tv_Tuner_set_status_check_interval_hint},
{ "nativeStartDvr", "()I", (void *)android_media_tv_Tuner_start_dvr},
{ "nativeStopDvr", "()I", (void *)android_media_tv_Tuner_stop_dvr},
{ "nativeFlushDvr", "()I", (void *)android_media_tv_Tuner_flush_dvr},
diff --git a/media/jni/tuner/DvrClient.cpp b/media/jni/tuner/DvrClient.cpp
index 05683b661716..6e4705251724 100644
--- a/media/jni/tuner/DvrClient.cpp
+++ b/media/jni/tuner/DvrClient.cpp
@@ -303,7 +303,17 @@ Result DvrClient::close() {
return Result::INVALID_STATE;
}
+Result DvrClient::setStatusCheckIntervalHint(int64_t durationInMs) {
+ if (mTunerDvr == nullptr) {
+ return Result::INVALID_STATE;
+ }
+ if (durationInMs < 0) {
+ return Result::INVALID_ARGUMENT;
+ }
+ Status s = mTunerDvr->setStatusCheckIntervalHint(durationInMs);
+ return ClientHelper::getServiceSpecificErrorCode(s);
+}
/////////////// TunerDvrCallback ///////////////////////
TunerDvrCallback::TunerDvrCallback(sp<DvrClientCallback> dvrClientCallback)
: mDvrClientCallback(dvrClientCallback) {}
diff --git a/media/jni/tuner/DvrClient.h b/media/jni/tuner/DvrClient.h
index 61c0325813a4..40ed75b365c3 100644
--- a/media/jni/tuner/DvrClient.h
+++ b/media/jni/tuner/DvrClient.h
@@ -126,6 +126,11 @@ public:
*/
Result close();
+ /**
+ * Set status check time interval.
+ */
+ Result setStatusCheckIntervalHint(int64_t durationInMs);
+
private:
/**
* An AIDL Tuner Dvr Singleton assigned at the first time the Tuner Client
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 761aa7e9b09c..cd9f85111c2d 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -2333,7 +2333,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
*/
public void requestFaceAuth(boolean userInitiatedRequest,
@FaceAuthApiRequestReason String reason) {
- mLogger.logFaceAuthRequested(userInitiatedRequest);
+ mLogger.logFaceAuthRequested(userInitiatedRequest, reason);
updateFaceListeningState(BIOMETRIC_ACTION_START, apiRequestReasonToUiEvent(reason));
}
diff --git a/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt b/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt
index 54cec7132bfa..2eee95738b7b 100644
--- a/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt
+++ b/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt
@@ -108,10 +108,11 @@ class KeyguardUpdateMonitorLogger @Inject constructor(
}, { "Face help received, msgId: $int1 msg: $str1" })
}
- fun logFaceAuthRequested(userInitiatedRequest: Boolean) {
- logBuffer.log(TAG, DEBUG,
- { bool1 = userInitiatedRequest },
- { "requestFaceAuth() userInitiated=$bool1" })
+ fun logFaceAuthRequested(userInitiatedRequest: Boolean, reason: String) {
+ logBuffer.log(TAG, DEBUG, {
+ bool1 = userInitiatedRequest
+ str1 = reason
+ }, { "requestFaceAuth() userInitiated=$bool1 reason=$str1" })
}
fun logFaceAuthSuccess(userId: Int) {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
index 19ffa30324b8..3e796cd0c879 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
@@ -806,7 +806,7 @@ public class AuthContainerView extends LinearLayout
}
mContainerState = STATE_GONE;
if (isAttachedToWindow()) {
- mWindowManager.removeView(this);
+ mWindowManager.removeViewImmediate(this);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.java b/packages/SystemUI/src/com/android/systemui/flags/Flags.java
index fcf11ef350fd..8aaadeffae12 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.java
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.java
@@ -300,8 +300,8 @@ public class Flags {
public static final UnreleasedFlag SCREENSHOT_REQUEST_PROCESSOR = new UnreleasedFlag(1300);
public static final UnreleasedFlag SCREENSHOT_WORK_PROFILE_POLICY = new UnreleasedFlag(1301);
- // 1400 - columbus, b/242800729
- public static final UnreleasedFlag QUICK_TAP_IN_PCC = new UnreleasedFlag(1400);
+ // 1400 - columbus
+ public static final ReleasedFlag QUICK_TAP_IN_PCC = new ReleasedFlag(1400);
// 1500 - chooser
public static final UnreleasedFlag CHOOSER_UNBUNDLED = new UnreleasedFlag(1500);
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
index 0c5564b34b15..28aa19e18e80 100644
--- a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
@@ -322,7 +322,7 @@ public class LogModule {
@SysUISingleton
@KeyguardUpdateMonitorLog
public static LogBuffer provideKeyguardUpdateMonitorLogBuffer(LogBufferFactory factory) {
- return factory.create("KeyguardUpdateMonitorLog", 200);
+ return factory.create("KeyguardUpdateMonitorLog", 400);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarTransitions.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarTransitions.java
index 6793f0163c43..43cf6231aaf0 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarTransitions.java
@@ -36,6 +36,7 @@ import com.android.systemui.statusbar.phone.BarTransitions;
import com.android.systemui.statusbar.phone.LightBarTransitionsController;
import java.io.PrintWriter;
+import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
@@ -75,15 +76,27 @@ public final class NavigationBarTransitions extends BarTransitions implements
private List<DarkIntensityListener> mDarkIntensityListeners;
private final Handler mHandler = Handler.getMain();
- private final IWallpaperVisibilityListener mWallpaperVisibilityListener =
- new IWallpaperVisibilityListener.Stub() {
+
+ static final class WallpaperVisibilityListener extends IWallpaperVisibilityListener.Stub {
+ private final WeakReference<NavigationBarTransitions> mSelf;
+
+ WallpaperVisibilityListener(NavigationBarTransitions self) {
+ mSelf = new WeakReference<>(self);
+ }
+
@Override
public void onWallpaperVisibilityChanged(boolean newVisibility,
- int displayId) throws RemoteException {
- mWallpaperVisible = newVisibility;
- mHandler.post(() -> applyLightsOut(true, false));
+ int displayId) throws RemoteException {
+ NavigationBarTransitions self = mSelf.get();
+ if (self == null) {
+ return;
+ }
+ self.mWallpaperVisible = newVisibility;
+ self.mHandler.post(() -> self.applyLightsOut(true, false));
}
- };
+ }
+
+ private final IWallpaperVisibilityListener mWallpaperVisibilityListener;
@Inject
public NavigationBarTransitions(
@@ -91,6 +104,7 @@ public final class NavigationBarTransitions extends BarTransitions implements
IWindowManager windowManagerService,
LightBarTransitionsController.Factory lightBarTransitionsControllerFactory) {
super(view, R.drawable.nav_background);
+
mView = view;
mWindowManagerService = windowManagerService;
mLightTransitionsController = lightBarTransitionsControllerFactory.create(this);
@@ -98,6 +112,7 @@ public final class NavigationBarTransitions extends BarTransitions implements
.getBoolean(R.bool.config_navigation_bar_enable_auto_dim_no_visible_wallpaper);
mDarkIntensityListeners = new ArrayList();
+ mWallpaperVisibilityListener = new WallpaperVisibilityListener(this);
try {
mWallpaperVisible = mWindowManagerService.registerWallpaperVisibilityListener(
mWallpaperVisibilityListener, Display.DEFAULT_DISPLAY);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowController.java
index e0d780a5fcd5..afcf7a9ec66d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowController.java
@@ -16,6 +16,9 @@
package com.android.systemui.statusbar.window;
+import static android.view.InsetsState.ITYPE_STATUS_BAR;
+import static android.view.InsetsState.ITYPE_TOP_MANDATORY_GESTURES;
+import static android.view.InsetsState.ITYPE_TOP_TAPPABLE_ELEMENT;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR;
@@ -27,6 +30,7 @@ import static com.android.systemui.util.leak.RotationUtils.ROTATION_UPSIDE_DOWN;
import android.content.Context;
import android.content.res.Resources;
+import android.graphics.Insets;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.os.Binder;
@@ -36,6 +40,7 @@ import android.util.Log;
import android.view.DisplayCutout;
import android.view.Gravity;
import android.view.IWindowManager;
+import android.view.InsetsFrameProvider;
import android.view.Surface;
import android.view.View;
import android.view.ViewGroup;
@@ -221,6 +226,19 @@ public class StatusBarWindowController {
lp.setTitle("StatusBar");
lp.packageName = mContext.getPackageName();
lp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
+ final InsetsFrameProvider gestureInsetsProvider =
+ new InsetsFrameProvider(ITYPE_TOP_MANDATORY_GESTURES);
+ final int safeTouchRegionHeight = mContext.getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.display_cutout_touchable_region_size);
+ if (safeTouchRegionHeight > 0) {
+ gestureInsetsProvider.minimalInsetsSizeInDisplayCutoutSafe =
+ Insets.of(0, safeTouchRegionHeight, 0, 0);
+ }
+ lp.providedInsets = new InsetsFrameProvider[] {
+ new InsetsFrameProvider(ITYPE_STATUS_BAR),
+ new InsetsFrameProvider(ITYPE_TOP_TAPPABLE_ELEMENT),
+ gestureInsetsProvider
+ };
return lp;
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java
index b0cf0612b2d2..9bf27a26a682 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java
@@ -19,6 +19,8 @@ package com.android.systemui.navigationbar;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
+
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -30,20 +32,25 @@ import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import android.content.res.Configuration;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper.RunWithLooper;
import android.util.SparseArray;
import androidx.test.filters.SmallTest;
+import com.android.dx.mockito.inline.extended.StaticMockitoSession;
import com.android.systemui.Dependency;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.model.SysUiState;
import com.android.systemui.recents.OverviewProxyService;
+import com.android.systemui.shared.recents.utilities.Utilities;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.phone.AutoHideController;
import com.android.systemui.statusbar.phone.LightBarController;
@@ -72,11 +79,14 @@ public class NavigationBarControllerTest extends SysuiTestCase {
private NavigationBarController mNavigationBarController;
private NavigationBar mDefaultNavBar;
private NavigationBar mSecondaryNavBar;
+ private StaticMockitoSession mMockitoSession;
@Mock
private CommandQueue mCommandQueue;
@Mock
private NavigationBarComponent.Factory mNavigationBarFactory;
+ @Mock
+ TaskbarDelegate mTaskbarDelegate;
@Before
public void setUp() {
@@ -90,7 +100,7 @@ public class NavigationBarControllerTest extends SysuiTestCase {
Dependency.get(Dependency.MAIN_HANDLER),
mock(ConfigurationController.class),
mock(NavBarHelper.class),
- mock(TaskbarDelegate.class),
+ mTaskbarDelegate,
mNavigationBarFactory,
mock(StatusBarKeyguardViewManager.class),
mock(DumpManager.class),
@@ -100,6 +110,7 @@ public class NavigationBarControllerTest extends SysuiTestCase {
Optional.of(mock(BackAnimation.class)),
mock(FeatureFlags.class)));
initializeNavigationBars();
+ mMockitoSession = mockitoSession().mockStatic(Utilities.class).startMocking();
}
private void initializeNavigationBars() {
@@ -120,6 +131,7 @@ public class NavigationBarControllerTest extends SysuiTestCase {
mNavigationBarController = null;
mDefaultNavBar = null;
mSecondaryNavBar = null;
+ mMockitoSession.finishMocking();
}
@Test
@@ -268,4 +280,22 @@ public class NavigationBarControllerTest extends SysuiTestCase {
public void test3ButtonTaskbarFlagDisabledNoRegister() {
verify(mCommandQueue, never()).addCallback(any(TaskbarDelegate.class));
}
+
+
+ @Test
+ public void testConfigurationChange_taskbarNotInitialized() {
+ Configuration configuration = mContext.getResources().getConfiguration();
+ when(Utilities.isTablet(any())).thenReturn(true);
+ mNavigationBarController.onConfigChanged(configuration);
+ verify(mTaskbarDelegate, never()).onConfigurationChanged(configuration);
+ }
+
+ @Test
+ public void testConfigurationChange_taskbarInitialized() {
+ Configuration configuration = mContext.getResources().getConfiguration();
+ when(Utilities.isTablet(any())).thenReturn(true);
+ when(mTaskbarDelegate.isInitialized()).thenReturn(true);
+ mNavigationBarController.onConfigChanged(configuration);
+ verify(mTaskbarDelegate, times(1)).onConfigurationChanged(configuration);
+ }
}
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 00974e44e8bd..2be84d059286 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -2036,9 +2036,11 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
if (resolvedUserIds.length != 1) {
return Collections.emptyList();
}
+ final int callingUid = Binder.getCallingUid();
final long ident = Binder.clearCallingIdentity();
try {
- return getInputMethodListLocked(resolvedUserIds[0], directBootAwareness);
+ return getInputMethodListLocked(
+ resolvedUserIds[0], directBootAwareness, callingUid);
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -2057,9 +2059,10 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
if (resolvedUserIds.length != 1) {
return Collections.emptyList();
}
+ final int callingUid = Binder.getCallingUid();
final long ident = Binder.clearCallingIdentity();
try {
- return getEnabledInputMethodListLocked(resolvedUserIds[0]);
+ return getEnabledInputMethodListLocked(resolvedUserIds[0], callingUid);
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -2090,12 +2093,14 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
@GuardedBy("ImfLock.class")
private List<InputMethodInfo> getInputMethodListLocked(@UserIdInt int userId,
- @DirectBootAwareness int directBootAwareness) {
+ @DirectBootAwareness int directBootAwareness, int callingUid) {
final ArrayList<InputMethodInfo> methodList;
+ final InputMethodSettings settings;
if (userId == mSettings.getCurrentUserId()
&& directBootAwareness == DirectBootAwareness.AUTO) {
// Create a copy.
methodList = new ArrayList<>(mMethodList);
+ settings = mSettings;
} else {
final ArrayMap<String, InputMethodInfo> methodMap = new ArrayMap<>();
methodList = new ArrayList<>();
@@ -2104,19 +2109,31 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
AdditionalSubtypeUtils.load(additionalSubtypeMap, userId);
queryInputMethodServicesInternal(mContext, userId, additionalSubtypeMap, methodMap,
methodList, directBootAwareness);
+ settings = new InputMethodSettings(mContext, methodMap, userId, true /* copyOnWrite */);
}
+ // filter caller's access to input methods
+ methodList.removeIf(imi ->
+ !canCallerAccessInputMethod(imi.getPackageName(), callingUid, userId, settings));
return methodList;
}
@GuardedBy("ImfLock.class")
- private List<InputMethodInfo> getEnabledInputMethodListLocked(@UserIdInt int userId) {
+ private List<InputMethodInfo> getEnabledInputMethodListLocked(@UserIdInt int userId,
+ int callingUid) {
+ final ArrayList<InputMethodInfo> methodList;
+ final InputMethodSettings settings;
if (userId == mSettings.getCurrentUserId()) {
- return mSettings.getEnabledInputMethodListLocked();
+ methodList = mSettings.getEnabledInputMethodListLocked();
+ settings = mSettings;
+ } else {
+ final ArrayMap<String, InputMethodInfo> methodMap = queryMethodMapForUser(userId);
+ settings = new InputMethodSettings(mContext, methodMap, userId, true /* copyOnWrite */);
+ methodList = settings.getEnabledInputMethodListLocked();
}
- final ArrayMap<String, InputMethodInfo> methodMap = queryMethodMapForUser(userId);
- final InputMethodSettings settings = new InputMethodSettings(mContext, methodMap, userId,
- true);
- return settings.getEnabledInputMethodListLocked();
+ // filter caller's access to input methods
+ methodList.removeIf(imi ->
+ !canCallerAccessInputMethod(imi.getPackageName(), callingUid, userId, settings));
+ return methodList;
}
@GuardedBy("ImfLock.class")
@@ -2155,10 +2172,11 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
}
synchronized (ImfLock.class) {
+ final int callingUid = Binder.getCallingUid();
final long ident = Binder.clearCallingIdentity();
try {
return getEnabledInputMethodSubtypeListLocked(imiId,
- allowsImplicitlyEnabledSubtypes, userId);
+ allowsImplicitlyEnabledSubtypes, userId, callingUid);
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -2167,7 +2185,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
@GuardedBy("ImfLock.class")
private List<InputMethodSubtype> getEnabledInputMethodSubtypeListLocked(String imiId,
- boolean allowsImplicitlyEnabledSubtypes, @UserIdInt int userId) {
+ boolean allowsImplicitlyEnabledSubtypes, @UserIdInt int userId, int callingUid) {
if (userId == mSettings.getCurrentUserId()) {
final InputMethodInfo imi;
String selectedMethodId = getSelectedMethodIdLocked();
@@ -2176,7 +2194,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
} else {
imi = mMethodMap.get(imiId);
}
- if (imi == null) {
+ if (imi == null || !canCallerAccessInputMethod(
+ imi.getPackageName(), callingUid, userId, mSettings)) {
return Collections.emptyList();
}
return mSettings.getEnabledInputMethodSubtypeListLocked(
@@ -2189,6 +2208,9 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
}
final InputMethodSettings settings = new InputMethodSettings(mContext, methodMap, userId,
true);
+ if (!canCallerAccessInputMethod(imi.getPackageName(), callingUid, userId, settings)) {
+ return Collections.emptyList();
+ }
return settings.getEnabledInputMethodSubtypeListLocked(
imi, allowsImplicitlyEnabledSubtypes);
}
@@ -5438,6 +5460,34 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
return true;
}
+ /**
+ * Filter the access to the input method by rules of the package visibility. Return {@code true}
+ * if the given input method is the currently selected one or visible to the caller.
+ *
+ * @param targetPkgName The package name of input method to check.
+ * @param callingUid The caller that is going to access the input method.
+ * @param userId The user ID where the input method resides.
+ * @param settings The input method settings under the given user ID.
+ * @return {@code true} if caller is able to access the input method.
+ */
+ private boolean canCallerAccessInputMethod(@NonNull String targetPkgName, int callingUid,
+ @UserIdInt int userId, @NonNull InputMethodSettings settings) {
+ final String methodId = settings.getSelectedInputMethod();
+ final ComponentName selectedInputMethod = methodId != null
+ ? InputMethodUtils.convertIdToComponentName(methodId) : null;
+ if (selectedInputMethod != null
+ && selectedInputMethod.getPackageName().equals(targetPkgName)) {
+ return true;
+ }
+ final boolean canAccess = !mPackageManagerInternal.filterAppAccess(
+ targetPkgName, callingUid, userId);
+ if (DEBUG && !canAccess) {
+ Slog.d(TAG, "Input method " + targetPkgName
+ + " is not visible to the caller " + callingUid);
+ }
+ return canAccess;
+ }
+
private void publishLocalService() {
LocalServices.addService(InputMethodManagerInternal.class, new LocalServiceImpl());
}
@@ -5459,14 +5509,15 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
@Override
public List<InputMethodInfo> getInputMethodListAsUser(@UserIdInt int userId) {
synchronized (ImfLock.class) {
- return getInputMethodListLocked(userId, DirectBootAwareness.AUTO);
+ return getInputMethodListLocked(userId, DirectBootAwareness.AUTO,
+ Process.SYSTEM_UID);
}
}
@Override
public List<InputMethodInfo> getEnabledInputMethodListAsUser(@UserIdInt int userId) {
synchronized (ImfLock.class) {
- return getEnabledInputMethodListLocked(userId);
+ return getEnabledInputMethodListLocked(userId, Process.SYSTEM_UID);
}
}
@@ -6096,8 +6147,9 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
try (PrintWriter pr = shellCommand.getOutPrintWriter()) {
for (int userId : userIds) {
final List<InputMethodInfo> methods = all
- ? getInputMethodListLocked(userId, DirectBootAwareness.AUTO)
- : getEnabledInputMethodListLocked(userId);
+ ? getInputMethodListLocked(
+ userId, DirectBootAwareness.AUTO, Process.SHELL_UID)
+ : getEnabledInputMethodListLocked(userId, Process.SHELL_UID);
if (userIds.length > 1) {
pr.print("User #");
pr.print(userId);
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodUtils.java b/services/core/java/com/android/server/inputmethod/InputMethodUtils.java
index d12f1131acbe..c7ff8caf176b 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodUtils.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodUtils.java
@@ -20,11 +20,13 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserHandleAware;
import android.annotation.UserIdInt;
+import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
+import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.os.Build;
import android.os.UserHandle;
@@ -998,4 +1000,16 @@ final class InputMethodUtils {
}
return new int[]{sourceUserId};
}
+
+ /**
+ * Convert the input method ID to a component name
+ *
+ * @param id A unique ID for this input method.
+ * @return The component name of the input method.
+ * @see InputMethodInfo#computeId(ResolveInfo)
+ */
+ @Nullable
+ public static ComponentName convertIdToComponentName(@NonNull String id) {
+ return ComponentName.unflattenFromString(id);
+ }
}
diff --git a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
index 66bdadb185c1..ab69c3426d04 100644
--- a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
+++ b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
@@ -333,16 +333,25 @@ public class SyntheticPasswordManager {
byte scryptLogP;
public int credentialType;
byte[] salt;
- // If Weaver is available, then this field is empty. Otherwise, it is the Gatekeeper
- // password handle that resulted from enrolling the hashed LSKF.
+ // This is the Gatekeeper password handle that resulted from enrolling the stretched LSKF,
+ // when applicable. This field isn't used if Weaver is available, or in new protectors when
+ // the LSKF is empty.
public byte[] passwordHandle;
- public static PasswordData create(int passwordType) {
+ public static PasswordData create(int credentialType) {
PasswordData result = new PasswordData();
- result.scryptLogN = PASSWORD_SCRYPT_LOG_N;
- result.scryptLogR = PASSWORD_SCRYPT_LOG_R;
- result.scryptLogP = PASSWORD_SCRYPT_LOG_P;
- result.credentialType = passwordType;
+ if (credentialType == LockPatternUtils.CREDENTIAL_TYPE_NONE) {
+ // When the LSKF is empty, scrypt provides no security benefit, so just use the
+ // minimum parameters (N=2, r=1, p=1).
+ result.scryptLogN = 1;
+ result.scryptLogR = 0;
+ result.scryptLogP = 0;
+ } else {
+ result.scryptLogN = PASSWORD_SCRYPT_LOG_N;
+ result.scryptLogR = PASSWORD_SCRYPT_LOG_R;
+ result.scryptLogP = PASSWORD_SCRYPT_LOG_P;
+ }
+ result.credentialType = credentialType;
result.salt = secureRandom(PASSWORD_SALT_LENGTH);
return result;
}
@@ -776,11 +785,12 @@ public class SyntheticPasswordManager {
long protectorId = generateProtectorId();
PasswordData pwd = PasswordData.create(credential.getType());
byte[] stretchedLskf = stretchLskf(credential, pwd);
- final long sid;
+ long sid = GateKeeper.INVALID_SECURE_USER_ID;
final byte[] protectorSecret;
if (isWeaverAvailable()) {
- // Protector uses Weaver to verify the LSKF
+ // Weaver is available, so make the protector use it to verify the LSKF. Do this even
+ // if the LSKF is empty, as that gives us support for securely deleting the protector.
int weaverSlot = getNextAvailableWeaverSlot();
Slog.i(TAG, "Weaver enroll password to slot " + weaverSlot + " for user " + userId);
byte[] weaverSecret = weaverEnroll(weaverSlot, stretchedLskfToWeaverKey(stretchedLskf),
@@ -794,33 +804,34 @@ public class SyntheticPasswordManager {
// No need to pass in quality since the credential type already encodes sufficient info
synchronizeWeaverFrpPassword(pwd, 0, userId, weaverSlot);
- pwd.passwordHandle = null;
- sid = GateKeeper.INVALID_SECURE_USER_ID;
protectorSecret = transformUnderWeaverSecret(stretchedLskf, weaverSecret);
} else {
- // Protector uses Gatekeeper to verify the LSKF
-
- // In case GK enrollment leaves persistent state around (in RPMB), this will nuke them
- // to prevent them from accumulating and causing problems.
- try {
- gatekeeper.clearSecureUserId(fakeUserId(userId));
- } catch (RemoteException ignore) {
- Slog.w(TAG, "Failed to clear SID from gatekeeper");
- }
- GateKeeperResponse response;
- try {
- response = gatekeeper.enroll(fakeUserId(userId), null, null,
- stretchedLskfToGkPassword(stretchedLskf));
- } catch (RemoteException e) {
- throw new IllegalStateException("Failed to enroll LSKF for new SP protector for "
- + "user " + userId, e);
- }
- if (response.getResponseCode() != GateKeeperResponse.RESPONSE_OK) {
- throw new IllegalStateException("Failed to enroll LSKF for new SP protector for "
- + "user " + userId);
+ // Weaver is unavailable, so make the protector use Gatekeeper to verify the LSKF
+ // instead. However, skip Gatekeeper when the LSKF is empty, since it wouldn't give any
+ // benefit in that case as Gatekeeper isn't expected to provide secure deletion.
+ if (!credential.isNone()) {
+ // In case GK enrollment leaves persistent state around (in RPMB), this will nuke
+ // them to prevent them from accumulating and causing problems.
+ try {
+ gatekeeper.clearSecureUserId(fakeUserId(userId));
+ } catch (RemoteException ignore) {
+ Slog.w(TAG, "Failed to clear SID from gatekeeper");
+ }
+ GateKeeperResponse response;
+ try {
+ response = gatekeeper.enroll(fakeUserId(userId), null, null,
+ stretchedLskfToGkPassword(stretchedLskf));
+ } catch (RemoteException e) {
+ throw new IllegalStateException("Failed to enroll LSKF for new SP protector"
+ + " for user " + userId, e);
+ }
+ if (response.getResponseCode() != GateKeeperResponse.RESPONSE_OK) {
+ throw new IllegalStateException("Failed to enroll LSKF for new SP protector"
+ + " for user " + userId);
+ }
+ pwd.passwordHandle = response.getPayload();
+ sid = sidFromPasswordHandle(pwd.passwordHandle);
}
- pwd.passwordHandle = response.getPayload();
- sid = sidFromPasswordHandle(pwd.passwordHandle);
protectorSecret = transformUnderSecdiscardable(stretchedLskf,
createSecdiscardable(protectorId, userId));
// No need to pass in quality since the credential type already encodes sufficient info
@@ -1049,7 +1060,7 @@ public class SyntheticPasswordManager {
byte[] stretchedLskf = stretchLskf(credential, pwd);
final byte[] protectorSecret;
- final long sid;
+ long sid = GateKeeper.INVALID_SECURE_USER_ID;
int weaverSlot = loadWeaverSlot(protectorId, userId);
if (weaverSlot != INVALID_WEAVER_SLOT) {
// Protector uses Weaver to verify the LSKF
@@ -1062,54 +1073,62 @@ public class SyntheticPasswordManager {
if (result.gkResponse.getResponseCode() != VerifyCredentialResponse.RESPONSE_OK) {
return result;
}
- sid = GateKeeper.INVALID_SECURE_USER_ID;
protectorSecret = transformUnderWeaverSecret(stretchedLskf,
result.gkResponse.getGatekeeperHAT());
} else {
- // Protector uses Gatekeeper to verify the LSKF
- byte[] gkPassword = stretchedLskfToGkPassword(stretchedLskf);
- GateKeeperResponse response;
- try {
- response = gatekeeper.verifyChallenge(fakeUserId(userId), 0L,
- pwd.passwordHandle, gkPassword);
- } catch (RemoteException e) {
- Slog.e(TAG, "gatekeeper verify failed", e);
- result.gkResponse = VerifyCredentialResponse.ERROR;
- return result;
- }
- int responseCode = response.getResponseCode();
- if (responseCode == GateKeeperResponse.RESPONSE_OK) {
- result.gkResponse = VerifyCredentialResponse.OK;
- if (response.getShouldReEnroll()) {
- GateKeeperResponse reenrollResponse;
- try {
- reenrollResponse = gatekeeper.enroll(fakeUserId(userId),
- pwd.passwordHandle, gkPassword, gkPassword);
- } catch (RemoteException e) {
- Slog.w(TAG, "Fail to invoke gatekeeper.enroll", e);
- reenrollResponse = GateKeeperResponse.ERROR;
- // continue the flow anyway
- }
- if (reenrollResponse.getResponseCode() == GateKeeperResponse.RESPONSE_OK) {
- pwd.passwordHandle = reenrollResponse.getPayload();
- // Use the reenrollment opportunity to update credential type
- // (getting rid of CREDENTIAL_TYPE_PASSWORD_OR_PIN)
- pwd.credentialType = credential.getType();
- saveState(PASSWORD_DATA_NAME, pwd.toBytes(), protectorId, userId);
- synchronizeFrpPassword(pwd, 0, userId);
- } else {
- Slog.w(TAG, "Fail to re-enroll user password for user " + userId);
- // continue the flow anyway
+ // Weaver is unavailable, so the protector uses Gatekeeper to verify the LSKF, unless
+ // the LSKF is empty in which case Gatekeeper might not have been used at all.
+ if (pwd.passwordHandle == null) {
+ if (!credential.isNone()) {
+ Slog.e(TAG, "Missing Gatekeeper password handle for nonempty LSKF");
+ result.gkResponse = VerifyCredentialResponse.ERROR;
+ return result;
+ }
+ } else {
+ byte[] gkPassword = stretchedLskfToGkPassword(stretchedLskf);
+ GateKeeperResponse response;
+ try {
+ response = gatekeeper.verifyChallenge(fakeUserId(userId), 0L,
+ pwd.passwordHandle, gkPassword);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "gatekeeper verify failed", e);
+ result.gkResponse = VerifyCredentialResponse.ERROR;
+ return result;
+ }
+ int responseCode = response.getResponseCode();
+ if (responseCode == GateKeeperResponse.RESPONSE_OK) {
+ result.gkResponse = VerifyCredentialResponse.OK;
+ if (response.getShouldReEnroll()) {
+ GateKeeperResponse reenrollResponse;
+ try {
+ reenrollResponse = gatekeeper.enroll(fakeUserId(userId),
+ pwd.passwordHandle, gkPassword, gkPassword);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Fail to invoke gatekeeper.enroll", e);
+ reenrollResponse = GateKeeperResponse.ERROR;
+ // continue the flow anyway
+ }
+ if (reenrollResponse.getResponseCode() == GateKeeperResponse.RESPONSE_OK) {
+ pwd.passwordHandle = reenrollResponse.getPayload();
+ // Use the reenrollment opportunity to update credential type
+ // (getting rid of CREDENTIAL_TYPE_PASSWORD_OR_PIN)
+ pwd.credentialType = credential.getType();
+ saveState(PASSWORD_DATA_NAME, pwd.toBytes(), protectorId, userId);
+ synchronizeFrpPassword(pwd, 0, userId);
+ } else {
+ Slog.w(TAG, "Fail to re-enroll user password for user " + userId);
+ // continue the flow anyway
+ }
}
+ } else if (responseCode == GateKeeperResponse.RESPONSE_RETRY) {
+ result.gkResponse = VerifyCredentialResponse.fromTimeout(response.getTimeout());
+ return result;
+ } else {
+ result.gkResponse = VerifyCredentialResponse.ERROR;
+ return result;
}
- } else if (responseCode == GateKeeperResponse.RESPONSE_RETRY) {
- result.gkResponse = VerifyCredentialResponse.fromTimeout(response.getTimeout());
- return result;
- } else {
- result.gkResponse = VerifyCredentialResponse.ERROR;
- return result;
+ sid = sidFromPasswordHandle(pwd.passwordHandle);
}
- sid = sidFromPasswordHandle(pwd.passwordHandle);
protectorSecret = transformUnderSecdiscardable(stretchedLskf,
loadSecdiscardable(protectorId, userId));
}
@@ -1463,7 +1482,8 @@ public class SyntheticPasswordManager {
return result;
}
- private int fakeUserId(int userId) {
+ @VisibleForTesting
+ static int fakeUserId(int userId) {
return 100000 + userId;
}
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index b91d9433f3b6..442777a20281 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -28,8 +28,6 @@ import static android.view.InsetsState.ITYPE_LEFT_GESTURES;
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
import static android.view.InsetsState.ITYPE_RIGHT_GESTURES;
import static android.view.InsetsState.ITYPE_STATUS_BAR;
-import static android.view.InsetsState.ITYPE_TOP_MANDATORY_GESTURES;
-import static android.view.InsetsState.ITYPE_TOP_TAPPABLE_ELEMENT;
import static android.view.WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS;
import static android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS;
import static android.view.WindowInsetsController.APPEARANCE_LOW_PROFILE_BARS;
@@ -118,7 +116,6 @@ import android.util.ArraySet;
import android.util.PrintWriterPrinter;
import android.util.Slog;
import android.util.SparseArray;
-import android.view.DisplayCutout;
import android.view.DisplayInfo;
import android.view.Gravity;
import android.view.InsetsFlags;
@@ -1150,24 +1147,6 @@ public class DisplayPolicy {
break;
case TYPE_STATUS_BAR:
mStatusBar = win;
- final TriConsumer<DisplayFrames, WindowContainer, Rect> gestureFrameProvider =
- (displayFrames, windowContainer, rect) -> {
- rect.bottom = rect.top + getStatusBarHeight(displayFrames);
- final DisplayCutout cutout =
- displayFrames.mInsetsState.getDisplayCutout();
- if (cutout != null) {
- final Rect top = cutout.getBoundingRectTop();
- if (!top.isEmpty()) {
- rect.bottom = Math.max(rect.bottom,
- top.bottom + mDisplayCutoutTouchableRegionSize);
- }
- }
- };
- mDisplayContent.setInsetProvider(ITYPE_STATUS_BAR, win, null);
- mDisplayContent.setInsetProvider(
- ITYPE_TOP_MANDATORY_GESTURES, win, gestureFrameProvider);
- mDisplayContent.setInsetProvider(ITYPE_TOP_TAPPABLE_ELEMENT, win, null);
- mInsetsSourceWindowsExceptIme.add(win);
break;
case TYPE_NAVIGATION_BAR:
mNavigationBar = win;
@@ -1185,7 +1164,8 @@ public class DisplayPolicy {
displayFrames.mUnrestricted,
win.getBounds(), displayFrames.mDisplayCutoutSafe,
inOutFrame, provider.source,
- provider.insetsSize, lp.privateFlags);
+ provider.insetsSize, lp.privateFlags,
+ provider.minimalInsetsSizeInDisplayCutoutSafe);
}
}
inOutFrame.inset(win.mGivenContentInsets);
@@ -1231,85 +1211,91 @@ public class DisplayPolicy {
mInsetsSourceWindowsExceptIme.add(win);
if (DEBUG_LAYOUT) Slog.i(TAG, "NAVIGATION BAR: " + mNavigationBar);
break;
- default:
- if (attrs.providedInsets != null) {
- for (int i = attrs.providedInsets.length - 1; i >= 0; i--) {
- final InsetsFrameProvider provider = attrs.providedInsets[i];
- switch (provider.type) {
- case ITYPE_STATUS_BAR:
- mStatusBarAlt = win;
- mStatusBarAltPosition = getAltBarPosition(attrs);
- break;
- case ITYPE_NAVIGATION_BAR:
- mNavigationBarAlt = win;
- mNavigationBarAltPosition = getAltBarPosition(attrs);
- break;
- case ITYPE_CLIMATE_BAR:
- mClimateBarAlt = win;
- mClimateBarAltPosition = getAltBarPosition(attrs);
- break;
- case ITYPE_EXTRA_NAVIGATION_BAR:
- mExtraNavBarAlt = win;
- mExtraNavBarAltPosition = getAltBarPosition(attrs);
- break;
+ }
+ // TODO(b/239145252): Temporarily skip the navigation bar as it is still with the hard-coded
+ // logic.
+ if (attrs.providedInsets != null && attrs.type != TYPE_NAVIGATION_BAR) {
+ for (int i = attrs.providedInsets.length - 1; i >= 0; i--) {
+ final InsetsFrameProvider provider = attrs.providedInsets[i];
+ switch (provider.type) {
+ case ITYPE_STATUS_BAR:
+ if (attrs.type != TYPE_STATUS_BAR) {
+ mStatusBarAlt = win;
+ mStatusBarAltPosition = getAltBarPosition(attrs);
}
- // The index of the provider and corresponding insets types cannot change at
- // runtime as ensured in WMS. Make use of the index in the provider directly
- // to access the latest provided size at runtime.
- final int index = i;
- final TriConsumer<DisplayFrames, WindowContainer, Rect> frameProvider =
- provider.insetsSize != null
- ? (displayFrames, windowContainer, inOutFrame) -> {
- inOutFrame.inset(win.mGivenContentInsets);
+ break;
+ case ITYPE_NAVIGATION_BAR:
+ if (attrs.type != TYPE_NAVIGATION_BAR) {
+ mNavigationBarAlt = win;
+ mNavigationBarAltPosition = getAltBarPosition(attrs);
+ }
+ break;
+ case ITYPE_CLIMATE_BAR:
+ mClimateBarAlt = win;
+ mClimateBarAltPosition = getAltBarPosition(attrs);
+ break;
+ case ITYPE_EXTRA_NAVIGATION_BAR:
+ mExtraNavBarAlt = win;
+ mExtraNavBarAltPosition = getAltBarPosition(attrs);
+ break;
+ }
+ // The index of the provider and corresponding insets types cannot change at
+ // runtime as ensured in WMS. Make use of the index in the provider directly
+ // to access the latest provided size at runtime.
+ final int index = i;
+ final TriConsumer<DisplayFrames, WindowContainer, Rect> frameProvider =
+ provider.insetsSize != null
+ ? (displayFrames, windowContainer, inOutFrame) -> {
+ inOutFrame.inset(win.mGivenContentInsets);
+ final LayoutParams lp =
+ win.mAttrs.forRotation(displayFrames.mRotation);
+ final InsetsFrameProvider ifp =
+ win.mAttrs.forRotation(displayFrames.mRotation)
+ .providedInsets[index];
+ InsetsFrameProvider.calculateInsetsFrame(
+ displayFrames.mUnrestricted,
+ windowContainer.getBounds(),
+ displayFrames.mDisplayCutoutSafe,
+ inOutFrame, ifp.source,
+ ifp.insetsSize, lp.privateFlags,
+ ifp.minimalInsetsSizeInDisplayCutoutSafe);
+ } : null;
+ final InsetsFrameProvider.InsetsSizeOverride[] overrides =
+ provider.insetsSizeOverrides;
+ final SparseArray<TriConsumer<DisplayFrames, WindowContainer, Rect>>
+ overrideProviders;
+ if (overrides != null) {
+ overrideProviders = new SparseArray<>();
+ for (int j = overrides.length - 1; j >= 0; j--) {
+ final int overrideIndex = j;
+ final TriConsumer<DisplayFrames, WindowContainer, Rect>
+ overrideFrameProvider =
+ (displayFrames, windowContainer, inOutFrame) -> {
final LayoutParams lp =
- win.mAttrs.forRotation(displayFrames.mRotation);
+ win.mAttrs.forRotation(
+ displayFrames.mRotation);
final InsetsFrameProvider ifp =
- win.mAttrs.forRotation(displayFrames.mRotation)
- .providedInsets[index];
+ win.mAttrs.providedInsets[index];
InsetsFrameProvider.calculateInsetsFrame(
displayFrames.mUnrestricted,
windowContainer.getBounds(),
displayFrames.mDisplayCutoutSafe,
inOutFrame, ifp.source,
- ifp.insetsSize, lp.privateFlags);
- } : null;
- final InsetsFrameProvider.InsetsSizeOverride[] overrides =
- provider.insetsSizeOverrides;
- final SparseArray<TriConsumer<DisplayFrames, WindowContainer, Rect>>
- overrideProviders;
- if (overrides != null) {
- overrideProviders = new SparseArray<>();
- for (int j = overrides.length - 1; j >= 0; j--) {
- final int overrideIndex = j;
- final TriConsumer<DisplayFrames, WindowContainer, Rect>
- overrideFrameProvider =
- (displayFrames, windowContainer, inOutFrame) -> {
- final LayoutParams lp =
- win.mAttrs.forRotation(
- displayFrames.mRotation);
- final InsetsFrameProvider ifp =
- win.mAttrs.providedInsets[index];
- InsetsFrameProvider.calculateInsetsFrame(
- displayFrames.mUnrestricted,
- windowContainer.getBounds(),
- displayFrames.mDisplayCutoutSafe,
- inOutFrame, ifp.source,
- ifp.insetsSizeOverrides[
- overrideIndex].insetsSize,
- lp.privateFlags);
- };
- overrideProviders.put(overrides[j].windowType,
- overrideFrameProvider);
- }
- } else {
- overrideProviders = null;
- }
- mDisplayContent.setInsetProvider(provider.type, win, frameProvider,
- overrideProviders);
- mInsetsSourceWindowsExceptIme.add(win);
+ ifp.insetsSizeOverrides[
+ overrideIndex].insetsSize,
+ lp.privateFlags,
+ null);
+ };
+ overrideProviders.put(overrides[j].windowType,
+ overrideFrameProvider);
}
+ } else {
+ overrideProviders = null;
}
- break;
+ mDisplayContent.setInsetProvider(provider.type, win, frameProvider,
+ overrideProviders);
+ mInsetsSourceWindowsExceptIme.add(win);
+ }
}
}
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
index 5e6cccc07983..1e67c120b6e0 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
@@ -75,15 +75,34 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
}
@Test
- public void testLskfBasedProtector() throws RemoteException {
+ public void testNoneLskfBasedProtector() throws RemoteException {
+ final int USER_ID = 10;
+ MockSyntheticPasswordManager manager = new MockSyntheticPasswordManager(mContext, mStorage,
+ mGateKeeperService, mUserManager, mPasswordSlotManager);
+ SyntheticPassword sp = manager.newSyntheticPassword(USER_ID);
+ assertFalse(lskfGatekeeperHandleExists(USER_ID));
+ long protectorId = manager.createLskfBasedProtector(mGateKeeperService,
+ LockscreenCredential.createNone(), sp, USER_ID);
+ assertFalse(lskfGatekeeperHandleExists(USER_ID));
+
+ AuthenticationResult result = manager.unlockLskfBasedProtector(mGateKeeperService,
+ protectorId, LockscreenCredential.createNone(), USER_ID, null);
+ assertArrayEquals(result.syntheticPassword.deriveKeyStorePassword(),
+ sp.deriveKeyStorePassword());
+ }
+
+ @Test
+ public void testNonNoneLskfBasedProtector() throws RemoteException {
final int USER_ID = 10;
final LockscreenCredential password = newPassword("user-password");
final LockscreenCredential badPassword = newPassword("bad-password");
MockSyntheticPasswordManager manager = new MockSyntheticPasswordManager(mContext, mStorage,
mGateKeeperService, mUserManager, mPasswordSlotManager);
SyntheticPassword sp = manager.newSyntheticPassword(USER_ID);
+ assertFalse(lskfGatekeeperHandleExists(USER_ID));
long protectorId = manager.createLskfBasedProtector(mGateKeeperService, password, sp,
USER_ID);
+ assertTrue(lskfGatekeeperHandleExists(USER_ID));
AuthenticationResult result = manager.unlockLskfBasedProtector(mGateKeeperService,
protectorId, password, USER_ID, null);
@@ -95,6 +114,10 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
assertNull(result.syntheticPassword);
}
+ private boolean lskfGatekeeperHandleExists(int userId) throws RemoteException {
+ return mGateKeeperService.getSecureUserId(SyntheticPasswordManager.fakeUserId(userId)) != 0;
+ }
+
private boolean hasSyntheticPassword(int userId) throws RemoteException {
return mService.getLong(CURRENT_LSKF_BASED_PROTECTOR_ID_KEY, 0, userId) != 0;
}
@@ -430,6 +453,21 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
}
@Test
+ public void testPasswordData_scryptParams() {
+ // CREDENTIAL_TYPE_NONE should result in the minimum scrypt params being used.
+ PasswordData data = PasswordData.create(CREDENTIAL_TYPE_NONE);
+ assertEquals(1, data.scryptLogN);
+ assertEquals(0, data.scryptLogR);
+ assertEquals(0, data.scryptLogP);
+
+ // Any other credential type should result in the real scrypt params being used.
+ data = PasswordData.create(CREDENTIAL_TYPE_PASSWORD);
+ assertTrue(data.scryptLogN > 1);
+ assertTrue(data.scryptLogR > 0);
+ assertTrue(data.scryptLogP > 0);
+ }
+
+ @Test
public void testPasswordData_serializeDeserialize() {
PasswordData data = new PasswordData();
data.scryptLogN = 11;
diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
index 041f298d4aa2..f2bc47dfd6e9 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
@@ -21,6 +21,8 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
import static android.view.InsetsState.ITYPE_STATUS_BAR;
+import static android.view.InsetsState.ITYPE_TOP_MANDATORY_GESTURES;
+import static android.view.InsetsState.ITYPE_TOP_TAPPABLE_ELEMENT;
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR;
@@ -45,6 +47,7 @@ import static org.mockito.Mockito.verify;
import android.app.StatusBarManager;
import android.platform.test.annotations.Presubmit;
+import android.view.InsetsFrameProvider;
import android.view.InsetsSource;
import android.view.InsetsSourceControl;
import android.view.InsetsState;
@@ -70,7 +73,7 @@ public class InsetsPolicyTest extends WindowTestsBase {
@Test
public void testControlsForDispatch_regular() {
- addWindow(TYPE_STATUS_BAR, "statusBar");
+ addStatusBar();
addWindow(TYPE_NAVIGATION_BAR, "navBar");
final InsetsSourceControl[] controls = addAppWindowAndGetControlsForDispatch();
@@ -82,7 +85,7 @@ public class InsetsPolicyTest extends WindowTestsBase {
@Test
public void testControlsForDispatch_multiWindowTaskVisible() {
- addWindow(TYPE_STATUS_BAR, "statusBar");
+ addStatusBar();
addWindow(TYPE_NAVIGATION_BAR, "navBar");
final WindowState win = createWindow(null, WINDOWING_MODE_MULTI_WINDOW,
@@ -95,7 +98,7 @@ public class InsetsPolicyTest extends WindowTestsBase {
@Test
public void testControlsForDispatch_freeformTaskVisible() {
- addWindow(TYPE_STATUS_BAR, "statusBar");
+ addStatusBar();
addWindow(TYPE_NAVIGATION_BAR, "navBar");
final WindowState win = createWindow(null, WINDOWING_MODE_FREEFORM,
@@ -108,8 +111,7 @@ public class InsetsPolicyTest extends WindowTestsBase {
@Test
public void testControlsForDispatch_forceStatusBarVisible() {
- addWindow(TYPE_STATUS_BAR, "statusBar").mAttrs.privateFlags |=
- PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR;
+ addStatusBar().mAttrs.privateFlags |= PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR;
addWindow(TYPE_NAVIGATION_BAR, "navBar");
final InsetsSourceControl[] controls = addAppWindowAndGetControlsForDispatch();
@@ -123,7 +125,7 @@ public class InsetsPolicyTest extends WindowTestsBase {
public void testControlsForDispatch_statusBarForceShowNavigation() {
addWindow(TYPE_NOTIFICATION_SHADE, "notificationShade").mAttrs.privateFlags |=
PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION;
- addWindow(TYPE_STATUS_BAR, "statusBar");
+ addStatusBar();
addWindow(TYPE_NAVIGATION_BAR, "navBar");
final InsetsSourceControl[] controls = addAppWindowAndGetControlsForDispatch();
@@ -152,7 +154,7 @@ public class InsetsPolicyTest extends WindowTestsBase {
public void testControlsForDispatch_remoteInsetsControllerControlsBars_appHasNoControl() {
mDisplayContent.setRemoteInsetsController(createDisplayWindowInsetsController());
mDisplayContent.getInsetsPolicy().setRemoteInsetsControllerControlsSystemBars(true);
- addWindow(TYPE_STATUS_BAR, "statusBar");
+ addStatusBar();
addWindow(TYPE_NAVIGATION_BAR, "navBar");
final InsetsSourceControl[] controls = addAppWindowAndGetControlsForDispatch();
@@ -163,7 +165,7 @@ public class InsetsPolicyTest extends WindowTestsBase {
@Test
public void testControlsForDispatch_topAppHidesStatusBar() {
- addWindow(TYPE_STATUS_BAR, "statusBar");
+ addStatusBar();
addWindow(TYPE_NAVIGATION_BAR, "navBar");
// Add a fullscreen (MATCH_PARENT x MATCH_PARENT) app window which hides status bar.
@@ -256,7 +258,7 @@ public class InsetsPolicyTest extends WindowTestsBase {
@SetupWindows(addWindows = W_ACTIVITY)
@Test
public void testShowTransientBars_bothCanBeTransient_appGetsBothFakeControls() {
- final WindowState statusBar = addNonFocusableWindow(TYPE_STATUS_BAR, "statusBar");
+ final WindowState statusBar = addStatusBar();
statusBar.setHasSurface(true);
statusBar.getControllableInsetProvider().setServerVisible(true);
final WindowState navBar = addNonFocusableWindow(TYPE_NAVIGATION_BAR, "navBar");
@@ -298,8 +300,7 @@ public class InsetsPolicyTest extends WindowTestsBase {
@SetupWindows(addWindows = W_ACTIVITY)
@Test
public void testShowTransientBars_statusBarCanBeTransient_appGetsStatusBarFakeControl() {
- addNonFocusableWindow(TYPE_STATUS_BAR, "statusBar")
- .getControllableInsetProvider().getSource().setVisible(false);
+ addStatusBar().getControllableInsetProvider().getSource().setVisible(false);
addNonFocusableWindow(TYPE_NAVIGATION_BAR, "navBar")
.getControllableInsetProvider().setServerVisible(true);
@@ -328,8 +329,8 @@ public class InsetsPolicyTest extends WindowTestsBase {
@SetupWindows(addWindows = W_ACTIVITY)
@Test
public void testAbortTransientBars_bothCanBeAborted_appGetsBothRealControls() {
- final InsetsSource statusBarSource = addNonFocusableWindow(TYPE_STATUS_BAR, "statusBar")
- .getControllableInsetProvider().getSource();
+ final InsetsSource statusBarSource =
+ addStatusBar().getControllableInsetProvider().getSource();
final InsetsSource navBarSource = addNonFocusableWindow(TYPE_NAVIGATION_BAR, "navBar")
.getControllableInsetProvider().getSource();
statusBarSource.setVisible(false);
@@ -381,8 +382,7 @@ public class InsetsPolicyTest extends WindowTestsBase {
@Test
public void testShowTransientBars_abortsWhenControlTargetChanges() {
- addNonFocusableWindow(TYPE_STATUS_BAR, "statusBar")
- .getControllableInsetProvider().getSource().setVisible(false);
+ addStatusBar().getControllableInsetProvider().getSource().setVisible(false);
addNonFocusableWindow(TYPE_NAVIGATION_BAR, "navBar")
.getControllableInsetProvider().getSource().setVisible(false);
final WindowState app = addWindow(TYPE_APPLICATION, "app");
@@ -406,6 +406,18 @@ public class InsetsPolicyTest extends WindowTestsBase {
return win;
}
+ private WindowState addStatusBar() {
+ final WindowState win = createWindow(null, TYPE_STATUS_BAR, "statusBar");
+ win.mAttrs.flags |= FLAG_NOT_FOCUSABLE;
+ win.mAttrs.providedInsets = new InsetsFrameProvider[] {
+ new InsetsFrameProvider(ITYPE_STATUS_BAR),
+ new InsetsFrameProvider(ITYPE_TOP_TAPPABLE_ELEMENT),
+ new InsetsFrameProvider(ITYPE_TOP_MANDATORY_GESTURES)
+ };
+ mDisplayContent.getDisplayPolicy().addWindowLw(win, win.mAttrs);
+ return win;
+ }
+
private WindowState addWindow(int type, String name) {
final WindowState win = createWindow(null, type, name);
mDisplayContent.getDisplayPolicy().addWindowLw(win, win.mAttrs);
diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
index 54b33e9794b6..d59fce089292 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -26,6 +26,8 @@ import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.provider.DeviceConfig.NAMESPACE_CONSTRAIN_DISPLAY_APIS;
import static android.view.InsetsState.ITYPE_STATUS_BAR;
+import static android.view.InsetsState.ITYPE_TOP_MANDATORY_GESTURES;
+import static android.view.InsetsState.ITYPE_TOP_TAPPABLE_ELEMENT;
import static android.view.Surface.ROTATION_0;
import static android.view.Surface.ROTATION_180;
import static android.view.Surface.ROTATION_270;
@@ -84,6 +86,7 @@ import android.os.UserHandle;
import android.platform.test.annotations.Presubmit;
import android.provider.DeviceConfig;
import android.provider.DeviceConfig.Properties;
+import android.view.InsetsFrameProvider;
import android.view.InsetsVisibilities;
import android.view.WindowManager;
@@ -3079,6 +3082,11 @@ public class SizeCompatTests extends WindowTestsBase {
attrs.layoutInDisplayCutoutMode =
WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
attrs.setFitInsetsTypes(0 /* types */);
+ attrs.providedInsets = new InsetsFrameProvider[] {
+ new InsetsFrameProvider(ITYPE_STATUS_BAR),
+ new InsetsFrameProvider(ITYPE_TOP_TAPPABLE_ELEMENT),
+ new InsetsFrameProvider(ITYPE_TOP_MANDATORY_GESTURES)
+ };
final TestWindowState statusBar = new TestWindowState(
displayContent.mWmService, mock(Session.class), new TestIWindow(), attrs, token);
token.addWindow(statusBar);
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
index c597b46ff73f..40326e9ad7f6 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -27,6 +27,9 @@ import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.os.Process.SYSTEM_UID;
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
+import static android.view.InsetsState.ITYPE_STATUS_BAR;
+import static android.view.InsetsState.ITYPE_TOP_MANDATORY_GESTURES;
+import static android.view.InsetsState.ITYPE_TOP_TAPPABLE_ELEMENT;
import static android.view.View.VISIBLE;
import static android.view.WindowManager.DISPLAY_IME_POLICY_FALLBACK_DISPLAY;
import static android.view.WindowManager.DISPLAY_IME_POLICY_LOCAL;
@@ -324,6 +327,11 @@ class WindowTestsBase extends SystemServiceTestsBase {
mStatusBarWindow.mAttrs.layoutInDisplayCutoutMode =
LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
mStatusBarWindow.mAttrs.setFitInsetsTypes(0);
+ mStatusBarWindow.mAttrs.providedInsets = new InsetsFrameProvider[] {
+ new InsetsFrameProvider(ITYPE_STATUS_BAR),
+ new InsetsFrameProvider(ITYPE_TOP_TAPPABLE_ELEMENT),
+ new InsetsFrameProvider(ITYPE_TOP_MANDATORY_GESTURES)
+ };
}
if (addAll || ArrayUtils.contains(requestedWindows, W_NOTIFICATION_SHADE)) {
mNotificationShadeWindow = createCommonWindow(null, TYPE_NOTIFICATION_SHADE,
diff --git a/services/translation/java/com/android/server/translation/TranslationManagerServiceImpl.java b/services/translation/java/com/android/server/translation/TranslationManagerServiceImpl.java
index 1e74451a8d4d..2d382a27d747 100644
--- a/services/translation/java/com/android/server/translation/TranslationManagerServiceImpl.java
+++ b/services/translation/java/com/android/server/translation/TranslationManagerServiceImpl.java
@@ -17,6 +17,7 @@
package com.android.server.translation;
import static android.view.translation.TranslationManager.EXTRA_CAPABILITIES;
+import static android.view.translation.TranslationManager.STATUS_SYNC_CALL_FAIL;
import static android.view.translation.UiTranslationManager.EXTRA_PACKAGE_NAME;
import static android.view.translation.UiTranslationManager.EXTRA_SOURCE_LOCALE;
import static android.view.translation.UiTranslationManager.EXTRA_STATE;
@@ -32,7 +33,9 @@ import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
+import android.content.Intent;
import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.os.Bundle;
import android.os.IBinder;
@@ -40,6 +43,7 @@ import android.os.IRemoteCallback;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.ResultReceiver;
+import android.service.translation.TranslationService;
import android.service.translation.TranslationServiceInfo;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -156,12 +160,27 @@ final class TranslationManagerServiceImpl extends
return null;
}
final ComponentName serviceComponent = ComponentName.unflattenFromString(serviceName);
+ if (!isServiceAvailableForUser(serviceComponent)) {
+ if (mMaster.verbose) {
+ Slog.v(TAG, "ensureRemoteServiceLocked(): " + serviceComponent
+ + " is not available,");
+ }
+ return null;
+ }
mRemoteTranslationService = new RemoteTranslationService(getContext(), serviceComponent,
mUserId, /* isInstantAllowed= */ false, mRemoteServiceCallback);
}
return mRemoteTranslationService;
}
+ private boolean isServiceAvailableForUser(ComponentName serviceComponent) {
+ Intent intent = new Intent(TranslationService.SERVICE_INTERFACE)
+ .setComponent(serviceComponent);
+ final ResolveInfo resolveInfo = getContext().getPackageManager().resolveServiceAsUser(
+ intent, PackageManager.GET_SERVICES | PackageManager.GET_META_DATA, mUserId);
+ return resolveInfo != null && resolveInfo.serviceInfo != null;
+ }
+
@GuardedBy("mLock")
void onTranslationCapabilitiesRequestLocked(@TranslationSpec.DataFormat int sourceFormat,
@TranslationSpec.DataFormat int destFormat,
@@ -170,6 +189,9 @@ final class TranslationManagerServiceImpl extends
if (remoteService != null) {
remoteService.onTranslationCapabilitiesRequest(sourceFormat, destFormat,
resultReceiver);
+ } else {
+ Slog.v(TAG, "onTranslationCapabilitiesRequestLocked(): no remote service.");
+ resultReceiver.send(STATUS_SYNC_CALL_FAIL, null);
}
}
@@ -184,10 +206,13 @@ final class TranslationManagerServiceImpl extends
@GuardedBy("mLock")
void onSessionCreatedLocked(@NonNull TranslationContext translationContext, int sessionId,
- IResultReceiver resultReceiver) {
+ IResultReceiver resultReceiver) throws RemoteException {
final RemoteTranslationService remoteService = ensureRemoteServiceLocked();
if (remoteService != null) {
remoteService.onSessionCreated(translationContext, sessionId, resultReceiver);
+ } else {
+ Slog.v(TAG, "onSessionCreatedLocked(): no remote service.");
+ resultReceiver.send(STATUS_SYNC_CALL_FAIL, null);
}
}
diff --git a/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java b/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java
index de70dcb9b29c..79ab009d3b92 100644
--- a/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java
+++ b/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java
@@ -27,6 +27,7 @@ import android.os.Binder;
import android.os.Bundle;
import android.os.PersistableBundle;
import android.os.SystemProperties;
+import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import java.io.PrintWriter;
@@ -192,4 +193,59 @@ public final class TelephonyUtils {
// This is the error case. The well-defined value for UNKNOWN is -1.
return "UNKNOWN(" + state + ")";
}
+
+ /**
+ * Convert display name source to string.
+ *
+ * @param source The display name source.
+ * @return The display name source in string format.
+ */
+ @NonNull
+ public static String displayNameSourceToString(
+ @SubscriptionManager.SimDisplayNameSource int source) {
+ switch (source) {
+ case SubscriptionManager.NAME_SOURCE_UNKNOWN: return "UNKNOWN";
+ case SubscriptionManager.NAME_SOURCE_CARRIER_ID: return "CARRIER_ID";
+ case SubscriptionManager.NAME_SOURCE_SIM_SPN: return "SIM_SPN";
+ case SubscriptionManager.NAME_SOURCE_USER_INPUT: return "USER_INPUT";
+ case SubscriptionManager.NAME_SOURCE_CARRIER: return "CARRIER";
+ case SubscriptionManager.NAME_SOURCE_SIM_PNN: return "SIM_PNN";
+ default:
+ return "UNKNOWN(" + source + ")";
+ }
+ }
+
+ /**
+ * Convert subscription type to string.
+ *
+ * @param type The subscription type.
+ * @return The subscription type in string format.
+ */
+ @NonNull
+ public static String subscriptionTypeToString(@SubscriptionManager.SubscriptionType int type) {
+ switch (type) {
+ case SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM: return "LOCAL_SIM";
+ case SubscriptionManager.SUBSCRIPTION_TYPE_REMOTE_SIM: return "REMOTE_SIM";
+ default:
+ return "UNKNOWN(" + type + ")";
+ }
+ }
+
+ /**
+ * Convert usage setting to string.
+ *
+ * @param usageSetting Usage setting.
+ * @return The usage setting in string format.
+ */
+ @NonNull
+ public static String usageSettingToString(@SubscriptionManager.UsageSetting int usageSetting) {
+ switch (usageSetting) {
+ case SubscriptionManager.USAGE_SETTING_UNKNOWN: return "UNKNOWN";
+ case SubscriptionManager.USAGE_SETTING_DEFAULT: return "DEFAULT";
+ case SubscriptionManager.USAGE_SETTING_VOICE_CENTRIC: return "VOICE_CENTRIC";
+ case SubscriptionManager.USAGE_SETTING_DATA_CENTRIC: return "DATA_CENTRIC";
+ default:
+ return "UNKNOWN(" + usageSetting + ")";
+ }
+ }
}
diff --git a/telephony/java/android/telephony/SubscriptionInfo.java b/telephony/java/android/telephony/SubscriptionInfo.java
index 4d58b22080cd..0d3c80fd8887 100644
--- a/telephony/java/android/telephony/SubscriptionInfo.java
+++ b/telephony/java/android/telephony/SubscriptionInfo.java
@@ -96,13 +96,6 @@ public class SubscriptionInfo implements Parcelable {
private final CharSequence mCarrierName;
/**
- * The subscription carrier id.
- *
- * @see TelephonyManager#getSimCarrierId()
- */
- private final int mCarrierId;
-
- /**
* The source of the {@link #mDisplayName}.
*/
@SimDisplayNameSource
@@ -127,12 +120,6 @@ public class SubscriptionInfo implements Parcelable {
private final int mDataRoaming;
/**
- * SIM icon bitmap cache.
- */
- @Nullable
- private Bitmap mIconBitmap;
-
- /**
* Mobile Country Code.
*/
@Nullable
@@ -157,15 +144,16 @@ public class SubscriptionInfo implements Parcelable {
private final String[] mHplmns;
/**
- * ISO Country code for the subscription's provider.
+ * Whether the subscription is from eSIM.
*/
- @NonNull
- private final String mCountryIso;
+ private final boolean mIsEmbedded;
/**
- * Whether the subscription is from eSIM.
+ * The string ID of the SIM card. It is the ICCID of the active profile for a UICC card and the
+ * EID for an eUICC card.
*/
- private final boolean mIsEmbedded;
+ @NonNull
+ private final String mCardString;
/**
* The access rules for this subscription, if it is embedded and defines any. This does not
@@ -182,18 +170,6 @@ public class SubscriptionInfo implements Parcelable {
private final UiccAccessRule[] mCarrierConfigAccessRules;
/**
- * The string ID of the SIM card. It is the ICCID of the active profile for a UICC card and the
- * EID for an eUICC card.
- */
- @NonNull
- private final String mCardString;
-
- /**
- * The card ID of the SIM card. This maps uniquely to {@link #mCardString}.
- */
- private final int mCardId;
-
- /**
* Whether the subscription is opportunistic.
*/
private final boolean mIsOpportunistic;
@@ -207,18 +183,17 @@ public class SubscriptionInfo implements Parcelable {
private final ParcelUuid mGroupUuid;
/**
- * A package name that specifies who created the group. Empty if not available.
+ * ISO Country code for the subscription's provider.
*/
@NonNull
- private final String mGroupOwner;
+ private final String mCountryIso;
/**
- * Whether group of the subscription is disabled. This is only useful if it's a grouped
- * opportunistic subscription. In this case, if all primary (non-opportunistic) subscriptions
- * in the group are deactivated (unplugged pSIM or deactivated eSIM profile), we should disable
- * this opportunistic subscription.
+ * The subscription carrier id.
+ *
+ * @see TelephonyManager#getSimCarrierId()
*/
- private final boolean mIsGroupDisabled;
+ private final int mCarrierId;
/**
* The profile class populated from the profile metadata if present. Otherwise,
@@ -236,6 +211,12 @@ public class SubscriptionInfo implements Parcelable {
private final int mType;
/**
+ * A package name that specifies who created the group. Empty if not available.
+ */
+ @NonNull
+ private final String mGroupOwner;
+
+ /**
* Whether uicc applications are configured to enable or disable.
* By default it's true.
*/
@@ -252,6 +233,27 @@ public class SubscriptionInfo implements Parcelable {
@UsageSetting
private final int mUsageSetting;
+ // Below are the fields that do not exist in the database.
+
+ /**
+ * SIM icon bitmap cache.
+ */
+ @Nullable
+ private Bitmap mIconBitmap;
+
+ /**
+ * The card ID of the SIM card. This maps uniquely to {@link #mCardString}.
+ */
+ private final int mCardId;
+
+ /**
+ * Whether group of the subscription is disabled. This is only useful if it's a grouped
+ * opportunistic subscription. In this case, if all primary (non-opportunistic) subscriptions
+ * in the group are deactivated (unplugged pSIM or deactivated eSIM profile), we should disable
+ * this opportunistic subscription.
+ */
+ private final boolean mIsGroupDisabled;
+
/**
* @hide
*
@@ -665,7 +667,8 @@ public class SubscriptionInfo implements Parcelable {
*/
@NonNull
public List<String> getEhplmns() {
- return mEhplmns == null ? Collections.emptyList() : Arrays.asList(mEhplmns);
+ return Collections.unmodifiableList(mEhplmns == null
+ ? Collections.emptyList() : Arrays.asList(mEhplmns));
}
/**
@@ -673,7 +676,8 @@ public class SubscriptionInfo implements Parcelable {
*/
@NonNull
public List<String> getHplmns() {
- return mHplmns == null ? Collections.emptyList() : Arrays.asList(mHplmns);
+ return Collections.unmodifiableList(mHplmns == null
+ ? Collections.emptyList() : Arrays.asList(mHplmns));
}
/**
@@ -777,7 +781,7 @@ public class SubscriptionInfo implements Parcelable {
if (mCarrierConfigAccessRules != null) {
merged.addAll(Arrays.asList(mCarrierConfigAccessRules));
}
- return merged.isEmpty() ? null : merged;
+ return merged.isEmpty() ? null : Collections.unmodifiableList(merged);
}
/**
@@ -957,69 +961,75 @@ public class SubscriptionInfo implements Parcelable {
public String toString() {
String iccIdToPrint = givePrintableIccid(mIccId);
String cardStringToPrint = givePrintableIccid(mCardString);
- return "{id=" + mId + " iccId=" + iccIdToPrint + " simSlotIndex=" + mSimSlotIndex
- + " carrierId=" + mCarrierId + " displayName=" + mDisplayName
- + " carrierName=" + mCarrierName + " nameSource=" + mDisplayNameSource
- + " iconTint=" + mIconTint
- + " number=" + Rlog.pii(TelephonyUtils.IS_DEBUGGABLE, mNumber)
- + " dataRoaming=" + mDataRoaming + " iconBitmap=" + mIconBitmap + " mcc=" + mMcc
- + " mnc=" + mMnc + " countryIso=" + mCountryIso + " isEmbedded=" + mIsEmbedded
- + " nativeAccessRules=" + Arrays.toString(mNativeAccessRules)
- + " cardString=" + cardStringToPrint + " cardId=" + mCardId
+ return "[SubscriptionInfo: id=" + mId
+ + " iccId=" + iccIdToPrint
+ + " simSlotIndex=" + mSimSlotIndex
+ " portIndex=" + mPortIndex
- + " isOpportunistic=" + mIsOpportunistic + " groupUuid=" + mGroupUuid
+ + " isEmbedded=" + mIsEmbedded
+ + " carrierId=" + mCarrierId
+ + " displayName=" + mDisplayName
+ + " carrierName=" + mCarrierName
+ + " isOpportunistic=" + mIsOpportunistic
+ + " groupUuid=" + mGroupUuid
+ + " groupOwner=" + mGroupOwner
+ " isGroupDisabled=" + mIsGroupDisabled
- + " profileClass=" + mProfileClass
+ + " displayNameSource="
+ + TelephonyUtils.displayNameSourceToString(mDisplayNameSource)
+ + " iconTint=" + mIconTint
+ + " number=" + Rlog.pii(TelephonyUtils.IS_DEBUGGABLE, mNumber)
+ + " dataRoaming=" + mDataRoaming
+ + " mcc=" + mMcc
+ + " mnc=" + mMnc
+ " ehplmns=" + Arrays.toString(mEhplmns)
+ " hplmns=" + Arrays.toString(mHplmns)
- + " mType=" + mType
- + " groupOwner=" + mGroupOwner
+ + " cardString=" + cardStringToPrint
+ + " cardId=" + mCardId
+ + " nativeAccessRules=" + Arrays.toString(mNativeAccessRules)
+ " carrierConfigAccessRules=" + Arrays.toString(mCarrierConfigAccessRules)
+ + " countryIso=" + mCountryIso
+ + " profileClass=" + mProfileClass
+ + " mType=" + TelephonyUtils.subscriptionTypeToString(mType)
+ " areUiccApplicationsEnabled=" + mAreUiccApplicationsEnabled
- + " usageSetting=" + mUsageSetting + "}";
+ + " usageSetting=" + TelephonyUtils.usageSettingToString(mUsageSetting)
+ + "]";
}
@Override
- public int hashCode() {
- return Objects.hash(mId, mSimSlotIndex, mDisplayNameSource, mIconTint, mDataRoaming,
- mIsEmbedded, mIsOpportunistic, mGroupUuid, mIccId, mNumber, mMcc, mMnc, mCountryIso,
- mCardString, mCardId, mDisplayName, mCarrierName,
- Arrays.hashCode(mNativeAccessRules), mIsGroupDisabled, mCarrierId, mProfileClass,
- mGroupOwner, mAreUiccApplicationsEnabled, mPortIndex, mUsageSetting);
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ SubscriptionInfo that = (SubscriptionInfo) o;
+ return mId == that.mId && mSimSlotIndex == that.mSimSlotIndex
+ && mDisplayNameSource == that.mDisplayNameSource && mIconTint == that.mIconTint
+ && mDataRoaming == that.mDataRoaming && mIsEmbedded == that.mIsEmbedded
+ && mIsOpportunistic == that.mIsOpportunistic && mCarrierId == that.mCarrierId
+ && mProfileClass == that.mProfileClass && mType == that.mType
+ && mAreUiccApplicationsEnabled == that.mAreUiccApplicationsEnabled
+ && mPortIndex == that.mPortIndex && mUsageSetting == that.mUsageSetting
+ && mCardId == that.mCardId && mIsGroupDisabled == that.mIsGroupDisabled
+ && mIccId.equals(that.mIccId) && mDisplayName.equals(that.mDisplayName)
+ && mCarrierName.equals(that.mCarrierName) && mNumber.equals(that.mNumber)
+ && Objects.equals(mMcc, that.mMcc) && Objects.equals(mMnc,
+ that.mMnc) && Arrays.equals(mEhplmns, that.mEhplmns)
+ && Arrays.equals(mHplmns, that.mHplmns) && mCardString.equals(
+ that.mCardString) && Arrays.equals(mNativeAccessRules,
+ that.mNativeAccessRules) && Arrays.equals(mCarrierConfigAccessRules,
+ that.mCarrierConfigAccessRules) && Objects.equals(mGroupUuid, that.mGroupUuid)
+ && mCountryIso.equals(that.mCountryIso) && mGroupOwner.equals(that.mGroupOwner);
}
@Override
- public boolean equals(Object obj) {
- if (this == obj) return true;
- if (obj == null || getClass() != obj.getClass()) return false;
- SubscriptionInfo toCompare = (SubscriptionInfo) obj;
- return mId == toCompare.mId
- && mSimSlotIndex == toCompare.mSimSlotIndex
- && mDisplayNameSource == toCompare.mDisplayNameSource
- && mIconTint == toCompare.mIconTint
- && mDataRoaming == toCompare.mDataRoaming
- && mIsEmbedded == toCompare.mIsEmbedded
- && mIsOpportunistic == toCompare.mIsOpportunistic
- && mIsGroupDisabled == toCompare.mIsGroupDisabled
- && mAreUiccApplicationsEnabled == toCompare.mAreUiccApplicationsEnabled
- && mCarrierId == toCompare.mCarrierId
- && Objects.equals(mGroupUuid, toCompare.mGroupUuid)
- && Objects.equals(mIccId, toCompare.mIccId)
- && Objects.equals(mNumber, toCompare.mNumber)
- && Objects.equals(mMcc, toCompare.mMcc)
- && Objects.equals(mMnc, toCompare.mMnc)
- && Objects.equals(mCountryIso, toCompare.mCountryIso)
- && Objects.equals(mCardString, toCompare.mCardString)
- && Objects.equals(mCardId, toCompare.mCardId)
- && mPortIndex == toCompare.mPortIndex
- && Objects.equals(mGroupOwner, toCompare.mGroupOwner)
- && TextUtils.equals(mDisplayName, toCompare.mDisplayName)
- && TextUtils.equals(mCarrierName, toCompare.mCarrierName)
- && Arrays.equals(mNativeAccessRules, toCompare.mNativeAccessRules)
- && mProfileClass == toCompare.mProfileClass
- && Arrays.equals(mEhplmns, toCompare.mEhplmns)
- && Arrays.equals(mHplmns, toCompare.mHplmns)
- && mUsageSetting == toCompare.mUsageSetting;
+ public int hashCode() {
+ int result = Objects.hash(mId, mIccId, mSimSlotIndex, mDisplayName, mCarrierName,
+ mDisplayNameSource, mIconTint, mNumber, mDataRoaming, mMcc, mMnc, mIsEmbedded,
+ mCardString, mIsOpportunistic, mGroupUuid, mCountryIso, mCarrierId, mProfileClass,
+ mType, mGroupOwner, mAreUiccApplicationsEnabled, mPortIndex, mUsageSetting, mCardId,
+ mIsGroupDisabled);
+ result = 31 * result + Arrays.hashCode(mEhplmns);
+ result = 31 * result + Arrays.hashCode(mHplmns);
+ result = 31 * result + Arrays.hashCode(mNativeAccessRules);
+ result = 31 * result + Arrays.hashCode(mCarrierConfigAccessRules);
+ return result;
}
/**
@@ -1031,7 +1041,7 @@ public class SubscriptionInfo implements Parcelable {
/**
* The subscription id.
*/
- private int mId = 0;
+ private int mId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
/**
* The ICCID of the SIM that is associated with this subscription, empty if unknown.
@@ -1064,7 +1074,7 @@ public class SubscriptionInfo implements Parcelable {
* The source of the display name.
*/
@SimDisplayNameSource
- private int mDisplayNameSource = SubscriptionManager.NAME_SOURCE_CARRIER_ID;
+ private int mDisplayNameSource = SubscriptionManager.NAME_SOURCE_UNKNOWN;
/**
* The color to be used for tinting the icon when displaying to the user.
@@ -1141,7 +1151,7 @@ public class SubscriptionInfo implements Parcelable {
/**
* The card ID of the SIM card which contains the subscription.
*/
- private int mCardId = -1;
+ private int mCardId = TelephonyManager.UNINITIALIZED_CARD_ID;
/**
* Whether the subscription is opportunistic or not.
@@ -1205,7 +1215,7 @@ public class SubscriptionInfo implements Parcelable {
/**
* the port index of the Uicc card.
*/
- private int mPortIndex = 0;
+ private int mPortIndex = TelephonyManager.INVALID_PORT_INDEX;
/**
* Subscription's preferred usage setting.
@@ -1433,9 +1443,9 @@ public class SubscriptionInfo implements Parcelable {
}
/**
- * Set the ISO Country code for the subscription's provider.
+ * Set the ISO country code for the subscription's provider.
*
- * @param countryIso The ISO Country code for the subscription's provider.
+ * @param countryIso The ISO country code for the subscription's provider.
* @return The builder.
*/
@NonNull
@@ -1592,7 +1602,7 @@ public class SubscriptionInfo implements Parcelable {
* Set the carrier certificates for this subscription that are saved in carrier configs.
* This does not include access rules from the Uicc, whether embedded or non-embedded.
*
- * @param carrierConfigAccessRules The carrier certificates for this subscription
+ * @param carrierConfigAccessRules The carrier certificates for this subscription.
* @return The builder.
*/
@NonNull
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 193c2c143f98..6189b49bcf79 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -589,6 +589,12 @@ public class SubscriptionManager {
public static final String NAME_SOURCE = SimInfo.COLUMN_NAME_SOURCE;
/**
+ * The name_source is unknown. (for initialization)
+ * @hide
+ */
+ public static final int NAME_SOURCE_UNKNOWN = SimInfo.NAME_SOURCE_UNKNOWN;
+
+ /**
* The name_source is from the carrier id.
* @hide
*/
@@ -623,6 +629,7 @@ public class SubscriptionManager {
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = {"NAME_SOURCE_"},
value = {
+ NAME_SOURCE_UNKNOWN,
NAME_SOURCE_CARRIER_ID,
NAME_SOURCE_SIM_SPN,
NAME_SOURCE_USER_INPUT,
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ReOpenImeWindowTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ReOpenImeWindowTest.kt
index a27b2da1a19e..f810fbb2e3ec 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ReOpenImeWindowTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ReOpenImeWindowTest.kt
@@ -16,7 +16,7 @@
package com.android.server.wm.flicker.ime
-import android.platform.test.annotations.FlakyTest
+import android.platform.test.annotations.Presubmit
import android.view.Surface
import androidx.test.filters.RequiresDevice
import com.android.server.wm.flicker.BaseTest
@@ -47,6 +47,7 @@ open class ReOpenImeWindowTest(testSpec: FlickerTestParameter) : BaseTest(testSp
/** {@inheritDoc} */
override val transition: FlickerBuilder.() -> Unit = {
setup {
+ tapl.workspace.switchToOverview().dismissAllTasks()
testApp.launchViaIntent(wmHelper)
testApp.openIME(wmHelper)
this.setRotation(testSpec.startRotation)
@@ -61,7 +62,7 @@ open class ReOpenImeWindowTest(testSpec: FlickerTestParameter) : BaseTest(testSp
}
/** {@inheritDoc} */
- @FlakyTest(bugId = 251214932)
+ @Presubmit
@Test
override fun visibleLayersShownMoreThanOneConsecutiveEntry() {
// depends on how much of the animation transactions are sent to SF at once
@@ -79,23 +80,23 @@ open class ReOpenImeWindowTest(testSpec: FlickerTestParameter) : BaseTest(testSp
}
/** {@inheritDoc} */
- @FlakyTest(bugId = 251214932)
+ @Presubmit
@Test
override fun visibleWindowsShownMoreThanOneConsecutiveEntry() {
val component = ComponentNameMatcher("", "RecentTaskScreenshotSurface")
testSpec.assertWm {
this.visibleWindowsShownMoreThanOneConsecutiveEntry(
ignoreWindows =
- listOf(
- ComponentNameMatcher.SPLASH_SCREEN,
- ComponentNameMatcher.SNAPSHOT,
- component
- )
+ listOf(
+ ComponentNameMatcher.SPLASH_SCREEN,
+ ComponentNameMatcher.SNAPSHOT,
+ component
+ )
)
}
}
- @FlakyTest(bugId = 251214932)
+ @Presubmit
@Test
fun launcherWindowBecomesInvisible() {
testSpec.assertWm {
@@ -105,11 +106,11 @@ open class ReOpenImeWindowTest(testSpec: FlickerTestParameter) : BaseTest(testSp
}
}
- @FlakyTest(bugId = 251214932)
+ @Presubmit
@Test
fun imeWindowIsAlwaysVisible() = testSpec.imeWindowIsAlwaysVisible()
- @FlakyTest(bugId = 251214932)
+ @Presubmit
@Test
fun imeAppWindowIsAlwaysVisible() {
// the app starts visible in live tile, and stays visible for the duration of entering
@@ -119,13 +120,13 @@ open class ReOpenImeWindowTest(testSpec: FlickerTestParameter) : BaseTest(testSp
testSpec.assertWm { this.isAppWindowVisible(testApp) }
}
- @FlakyTest(bugId = 251214932)
+ @Presubmit
@Test
fun imeLayerBecomesVisible() {
testSpec.assertLayers { this.isVisible(ComponentNameMatcher.IME) }
}
- @FlakyTest(bugId = 251214932)
+ @Presubmit
@Test
fun appLayerReplacesLauncher() {
testSpec.assertLayers {
@@ -137,60 +138,6 @@ open class ReOpenImeWindowTest(testSpec: FlickerTestParameter) : BaseTest(testSp
}
}
- @FlakyTest(bugId = 251214932)
- @Test
- override fun navBarLayerPositionAtStartAndEnd() {
- super.navBarLayerPositionAtStartAndEnd()
- }
-
- @FlakyTest(bugId = 251214932)
- @Test
- override fun navBarWindowIsAlwaysVisible() {
- super.navBarWindowIsAlwaysVisible()
- }
-
- @FlakyTest(bugId = 251214932)
- @Test
- override fun statusBarLayerIsVisibleAtStartAndEnd() {
- super.statusBarLayerIsVisibleAtStartAndEnd()
- }
-
- @FlakyTest(bugId = 251214932)
- @Test
- override fun entireScreenCovered() {
- super.entireScreenCovered()
- }
-
- @FlakyTest(bugId = 251214932)
- @Test
- override fun navBarLayerIsVisibleAtStartAndEnd() {
- super.navBarLayerIsVisibleAtStartAndEnd()
- }
-
- @FlakyTest(bugId = 251214932)
- @Test
- override fun statusBarLayerPositionAtStartAndEnd() {
- super.statusBarLayerPositionAtStartAndEnd()
- }
-
- @FlakyTest(bugId = 251214932)
- @Test
- override fun statusBarWindowIsAlwaysVisible() {
- super.statusBarWindowIsAlwaysVisible()
- }
-
- @FlakyTest(bugId = 251214932)
- @Test
- override fun taskBarLayerIsVisibleAtStartAndEnd() {
- super.taskBarLayerIsVisibleAtStartAndEnd()
- }
-
- @FlakyTest(bugId = 251214932)
- @Test
- override fun taskBarWindowIsAlwaysVisible() {
- super.taskBarWindowIsAlwaysVisible()
- }
-
companion object {
@Parameterized.Parameters(name = "{0}")
@JvmStatic
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdFromIcon.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdFromIcon.kt
index 7ccfeb7f6edd..73e6d223f824 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdFromIcon.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdFromIcon.kt
@@ -16,7 +16,7 @@
package com.android.server.wm.flicker.launch
-import android.platform.test.annotations.Postsubmit
+import android.platform.test.annotations.FlakyTest
import android.platform.test.annotations.RequiresDevice
import android.view.Surface
import com.android.server.wm.flicker.FlickerParametersRunnerFactory
@@ -81,87 +81,101 @@ class OpenAppColdFromIcon(testSpec: FlickerTestParameter) :
}
/** {@inheritDoc} */
- @Postsubmit @Test override fun appWindowAsTopWindowAtEnd() = super.appWindowAsTopWindowAtEnd()
+ @FlakyTest(bugId = 240916028)
+ @Test
+ override fun appWindowAsTopWindowAtEnd() = super.appWindowAsTopWindowAtEnd()
/** {@inheritDoc} */
- @Postsubmit
+ @FlakyTest(bugId = 240916028)
@Test
override fun appWindowReplacesLauncherAsTopWindow() =
super.appWindowReplacesLauncherAsTopWindow()
/** {@inheritDoc} */
- @Postsubmit @Test override fun appLayerBecomesVisible() = super.appLayerBecomesVisible()
+ @FlakyTest(bugId = 240916028)
+ @Test
+ override fun appLayerBecomesVisible() = super.appLayerBecomesVisible()
/** {@inheritDoc} */
- @Postsubmit @Test override fun appLayerReplacesLauncher() = super.appLayerReplacesLauncher()
+ @FlakyTest(bugId = 240916028)
+ @Test
+ override fun appLayerReplacesLauncher() = super.appLayerReplacesLauncher()
/** {@inheritDoc} */
- @Postsubmit @Test override fun appWindowBecomesTopWindow() = super.appWindowBecomesTopWindow()
+ @FlakyTest(bugId = 240916028)
+ @Test
+ override fun appWindowBecomesTopWindow() = super.appWindowBecomesTopWindow()
/** {@inheritDoc} */
- @Postsubmit @Test override fun appWindowBecomesVisible() = super.appWindowBecomesVisible()
+ @FlakyTest(bugId = 240916028)
+ @Test
+ override fun appWindowBecomesVisible() = super.appWindowBecomesVisible()
/** {@inheritDoc} */
- @Postsubmit @Test override fun entireScreenCovered() = super.entireScreenCovered()
+ @FlakyTest(bugId = 240916028)
+ @Test
+ override fun entireScreenCovered() = super.entireScreenCovered()
/** {@inheritDoc} */
- @Postsubmit @Test override fun focusChanges() = super.focusChanges()
+ @FlakyTest(bugId = 240916028) @Test override fun focusChanges() = super.focusChanges()
/** {@inheritDoc} */
- @Postsubmit
+ @FlakyTest(bugId = 240916028)
@Test
override fun navBarLayerIsVisibleAtStartAndEnd() = super.navBarLayerIsVisibleAtStartAndEnd()
/** {@inheritDoc} */
- @Postsubmit
+ @FlakyTest(bugId = 240916028)
@Test
override fun taskBarLayerIsVisibleAtStartAndEnd() = super.taskBarLayerIsVisibleAtStartAndEnd()
/** {@inheritDoc} */
- @Postsubmit
+ @FlakyTest(bugId = 240916028)
@Test
override fun taskBarWindowIsAlwaysVisible() = super.taskBarWindowIsAlwaysVisible()
/** {@inheritDoc} */
- @Postsubmit
+ @FlakyTest(bugId = 240916028)
@Test
override fun navBarLayerPositionAtStartAndEnd() = super.navBarLayerPositionAtStartAndEnd()
/** {@inheritDoc} */
- @Postsubmit
+ @FlakyTest(bugId = 240916028)
@Test
override fun navBarWindowIsAlwaysVisible() = super.navBarWindowIsAlwaysVisible()
/** {@inheritDoc} */
- @Postsubmit
+ @FlakyTest(bugId = 240916028)
@Test
override fun statusBarLayerPositionAtStartAndEnd() = super.statusBarLayerPositionAtStartAndEnd()
/** {@inheritDoc} */
- @Postsubmit
+ @FlakyTest(bugId = 240916028)
@Test
override fun statusBarLayerIsVisibleAtStartAndEnd() =
super.statusBarLayerIsVisibleAtStartAndEnd()
/** {@inheritDoc} */
- @Postsubmit
+ @FlakyTest(bugId = 240916028)
@Test
override fun statusBarWindowIsAlwaysVisible() = super.statusBarWindowIsAlwaysVisible()
/** {@inheritDoc} */
- @Postsubmit
+ @FlakyTest(bugId = 240916028)
@Test
override fun visibleLayersShownMoreThanOneConsecutiveEntry() =
super.visibleLayersShownMoreThanOneConsecutiveEntry()
/** {@inheritDoc} */
- @Postsubmit
+ @FlakyTest(bugId = 240916028)
@Test
override fun visibleWindowsShownMoreThanOneConsecutiveEntry() =
super.visibleWindowsShownMoreThanOneConsecutiveEntry()
/** {@inheritDoc} */
- @Postsubmit @Test override fun appWindowIsTopWindowAtEnd() = super.appWindowIsTopWindowAtEnd()
+ @FlakyTest(bugId = 240916028)
+ @Test
+ override fun appWindowIsTopWindowAtEnd() = super.appWindowIsTopWindowAtEnd()
companion object {
/**
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt
index 46186bcb5edc..bc1f0d18d8f4 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt
@@ -16,7 +16,6 @@
package com.android.server.wm.flicker.quickswitch
-import android.platform.test.annotations.FlakyTest
import android.platform.test.annotations.Presubmit
import android.platform.test.annotations.RequiresDevice
import android.view.Surface
@@ -104,7 +103,7 @@ open class QuickSwitchBetweenTwoAppsBackTest(testSpec: FlickerTestParameter) : B
* Checks that the transition starts with [testApp2]'s layers filling/covering exactly the
* entirety of the display.
*/
- @FlakyTest(bugId = 250520840)
+ @Presubmit
@Test
open fun startsWithApp2LayersCoverFullScreen() {
testSpec.assertLayersStart {
@@ -236,15 +235,6 @@ open class QuickSwitchBetweenTwoAppsBackTest(testSpec: FlickerTestParameter) : B
}
}
- /** {@inheritDoc} */
- @Presubmit
- @Test
- override fun taskBarLayerIsVisibleAtStartAndEnd() = super.taskBarLayerIsVisibleAtStartAndEnd()
-
- @FlakyTest(bugId = 250518877)
- @Test
- override fun navBarLayerPositionAtStartAndEnd() = super.navBarLayerPositionAtStartAndEnd()
-
companion object {
private var startDisplayBounds = Rect.EMPTY
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest_ShellTransit.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest_ShellTransit.kt
index 7a1350e5bbfa..f988bb2f1bf1 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest_ShellTransit.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest_ShellTransit.kt
@@ -23,6 +23,7 @@ import com.android.server.wm.flicker.FlickerParametersRunnerFactory
import com.android.server.wm.flicker.FlickerTestParameter
import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
import com.android.server.wm.flicker.navBarWindowIsVisibleAtStartAndEnd
+import com.android.server.wm.traces.common.ComponentNameMatcher
import org.junit.Assume
import org.junit.Before
import org.junit.FixMethodOrder
@@ -61,8 +62,8 @@ open class QuickSwitchBetweenTwoAppsBackTest_ShellTransit(testSpec: FlickerTestP
override fun navBarWindowIsAlwaysVisible() = super.navBarWindowIsAlwaysVisible()
/**
- * Checks that [ComponentMatcher.NAV_BAR] window is visible and above the app windows at the
- * start and end of the WM trace
+ * Checks that [ComponentNameMatcher.NAV_BAR] window is visible and above the app windows at
+ * the start and end of the WM trace
*/
@Presubmit
@Test
@@ -71,8 +72,18 @@ open class QuickSwitchBetweenTwoAppsBackTest_ShellTransit(testSpec: FlickerTestP
testSpec.navBarWindowIsVisibleAtStartAndEnd()
}
+ /** {@inheritDoc} */
+ @FlakyTest(bugId = 250520840)
+ @Test
+ override fun startsWithApp2LayersCoverFullScreen() =
+ super.startsWithApp2LayersCoverFullScreen()
+
@FlakyTest(bugId = 246284708)
@Test
override fun visibleLayersShownMoreThanOneConsecutiveEntry() =
super.visibleLayersShownMoreThanOneConsecutiveEntry()
+
+ @FlakyTest(bugId = 250518877)
+ @Test
+ override fun navBarLayerPositionAtStartAndEnd() = super.navBarLayerPositionAtStartAndEnd()
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt
index 0a21044f6dda..7e4504bc7a48 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt
@@ -16,7 +16,6 @@
package com.android.server.wm.flicker.quickswitch
-import android.platform.test.annotations.FlakyTest
import android.platform.test.annotations.Presubmit
import android.platform.test.annotations.RequiresDevice
import android.view.Surface
@@ -116,7 +115,7 @@ open class QuickSwitchBetweenTwoAppsForwardTest(testSpec: FlickerTestParameter)
* Checks that the transition starts with [testApp1]'s layers filling/covering exactly the
* entirety of the display.
*/
- @FlakyTest(bugId = 250522691)
+ @Presubmit
@Test
open fun startsWithApp1LayersCoverFullScreen() {
testSpec.assertLayersStart {
@@ -255,10 +254,6 @@ open class QuickSwitchBetweenTwoAppsForwardTest(testSpec: FlickerTestParameter)
@Test
override fun taskBarLayerIsVisibleAtStartAndEnd() = super.taskBarLayerIsVisibleAtStartAndEnd()
- @FlakyTest(bugId = 250518877)
- @Test
- override fun navBarLayerPositionAtStartAndEnd() = super.navBarLayerPositionAtStartAndEnd()
-
companion object {
private var startDisplayBounds = Rect.EMPTY
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest_ShellTransit.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest_ShellTransit.kt
index 03647c9801c7..cc954ab6ee5d 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest_ShellTransit.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest_ShellTransit.kt
@@ -23,6 +23,7 @@ import com.android.server.wm.flicker.FlickerParametersRunnerFactory
import com.android.server.wm.flicker.FlickerTestParameter
import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
import com.android.server.wm.flicker.navBarWindowIsVisibleAtStartAndEnd
+import com.android.server.wm.traces.common.ComponentNameMatcher
import org.junit.Assume
import org.junit.Before
import org.junit.FixMethodOrder
@@ -62,8 +63,8 @@ open class QuickSwitchBetweenTwoAppsForwardTest_ShellTransit(testSpec: FlickerTe
override fun navBarWindowIsAlwaysVisible() = super.navBarWindowIsAlwaysVisible()
/**
- * Checks that [ComponentMatcher.NAV_BAR] window is visible and above the app windows at the
- * start and end of the WM trace
+ * Checks that [ComponentNameMatcher.NAV_BAR] window is visible and above the app windows at
+ * the start and end of the WM trace
*/
@Presubmit
@Test
@@ -76,4 +77,13 @@ open class QuickSwitchBetweenTwoAppsForwardTest_ShellTransit(testSpec: FlickerTe
@Test
override fun visibleLayersShownMoreThanOneConsecutiveEntry() =
super.visibleLayersShownMoreThanOneConsecutiveEntry()
+
+ @FlakyTest(bugId = 250518877)
+ @Test
+ override fun navBarLayerPositionAtStartAndEnd() = super.navBarLayerPositionAtStartAndEnd()
+
+ @FlakyTest(bugId = 250522691)
+ @Test
+ override fun startsWithApp1LayersCoverFullScreen() =
+ super.startsWithApp1LayersCoverFullScreen()
}
diff --git a/tools/processors/immutability/Android.bp b/tools/processors/immutability/Android.bp
index fe97a903bff8..2ce785f10a2c 100644
--- a/tools/processors/immutability/Android.bp
+++ b/tools/processors/immutability/Android.bp
@@ -67,6 +67,7 @@ java_test_host {
"--add-exports jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED",
"--add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED",
],
+ test_config_template: "AndroidTestTemplate.xml",
}
filegroup {
diff --git a/tools/processors/immutability/AndroidTestTemplate.xml b/tools/processors/immutability/AndroidTestTemplate.xml
new file mode 100644
index 000000000000..b9cf62f5ca5b
--- /dev/null
+++ b/tools/processors/immutability/AndroidTestTemplate.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2022 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.
+-->
+<!-- This test config file is auto-generated. -->
+<configuration description="Runs {MODULE}">
+ <option name="test-suite-tag" value="apct" />
+ <option name="test-suite-tag" value="apct-unit-tests" />
+ <option name="config-descriptor:metadata" key="component" value="{MODULE}" />
+
+ {EXTRA_CONFIGS}
+
+ <test class="com.android.tradefed.testtype.IsolatedHostTest" >
+ <option name="jar" value="{MODULE}.jar" />
+ <option name="java-flags" value="--add-modules=jdk.compiler"/>
+ <option name="java-flags" value="--add-exports=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED"/>
+ <option name="java-flags" value="--add-exports=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED"/>
+ <option name="java-flags" value="--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED"/>
+ <option name="java-flags" value="--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED"/>
+ </test>
+</configuration>
diff --git a/tools/sdkparcelables/src/com/android/sdkparcelables/Main.kt b/tools/sdkparcelables/src/com/android/sdkparcelables/Main.kt
index 0fb062f280e3..0b619488c49c 100644
--- a/tools/sdkparcelables/src/com/android/sdkparcelables/Main.kt
+++ b/tools/sdkparcelables/src/com/android/sdkparcelables/Main.kt
@@ -39,7 +39,7 @@ fun main(args: Array<String>) {
kotlin.system.exitProcess(2)
}
- val ancestorCollector = AncestorCollector(Opcodes.ASM7, null)
+ val ancestorCollector = AncestorCollector(Opcodes.ASM9, null)
for (entry in zipFile.entries()) {
if (entry.name.endsWith(".class")) {
diff --git a/tools/traceinjection/src/com/android/traceinjection/TraceInjectionClassVisitor.java b/tools/traceinjection/src/com/android/traceinjection/TraceInjectionClassVisitor.java
index 863f976b8aff..67c5561f348d 100644
--- a/tools/traceinjection/src/com/android/traceinjection/TraceInjectionClassVisitor.java
+++ b/tools/traceinjection/src/com/android/traceinjection/TraceInjectionClassVisitor.java
@@ -28,7 +28,7 @@ public class TraceInjectionClassVisitor extends ClassVisitor {
private final TraceInjectionConfiguration mParams;
public TraceInjectionClassVisitor(ClassVisitor classVisitor,
TraceInjectionConfiguration params) {
- super(Opcodes.ASM7, classVisitor);
+ super(Opcodes.ASM9, classVisitor);
mParams = params;
}
diff --git a/tools/traceinjection/src/com/android/traceinjection/TraceInjectionMethodAdapter.java b/tools/traceinjection/src/com/android/traceinjection/TraceInjectionMethodAdapter.java
index c2bbddcb5668..91e987dc72ee 100644
--- a/tools/traceinjection/src/com/android/traceinjection/TraceInjectionMethodAdapter.java
+++ b/tools/traceinjection/src/com/android/traceinjection/TraceInjectionMethodAdapter.java
@@ -61,7 +61,7 @@ public class TraceInjectionMethodAdapter extends AdviceAdapter {
public TraceInjectionMethodAdapter(MethodVisitor methodVisitor, int access,
String name, String descriptor, TraceInjectionConfiguration params) {
- super(Opcodes.ASM7, methodVisitor, access, name, descriptor);
+ super(Opcodes.ASM9, methodVisitor, access, name, descriptor);
mParams = params;
mIsConstructor = "<init>".equals(name);
}
@@ -157,7 +157,7 @@ public class TraceInjectionMethodAdapter extends AdviceAdapter {
class TracingAnnotationVisitor extends AnnotationVisitor {
TracingAnnotationVisitor(AnnotationVisitor annotationVisitor) {
- super(Opcodes.ASM7, annotationVisitor);
+ super(Opcodes.ASM9, annotationVisitor);
}
@Override