Merge "Create WindowWakeUpPolicy" into main
diff --git a/apct-tests/perftests/core/src/android/graphics/perftests/CanvasPerfTest.java b/apct-tests/perftests/core/src/android/graphics/perftests/CanvasPerfTest.java
index e5a06c9..3c361d7 100644
--- a/apct-tests/perftests/core/src/android/graphics/perftests/CanvasPerfTest.java
+++ b/apct-tests/perftests/core/src/android/graphics/perftests/CanvasPerfTest.java
@@ -16,12 +16,14 @@
package android.graphics.perftests;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Color;
+import android.graphics.ColorSpace;
import android.graphics.ImageDecoder;
import android.graphics.Paint;
import android.graphics.RecordingCanvas;
@@ -104,15 +106,36 @@
}
@Test
- public void testCreateScaledBitmap() throws IOException {
+ public void testCreateScaledSrgbBitmap() throws IOException {
BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
final Context context = InstrumentationRegistry.getContext();
Bitmap source = ImageDecoder.decodeBitmap(
ImageDecoder.createSource(context.getResources(), R.drawable.fountain_night),
(decoder, info, source1) -> {
decoder.setAllocator(ImageDecoder.ALLOCATOR_SOFTWARE);
+ decoder.setTargetColorSpace(ColorSpace.get(ColorSpace.Named.SRGB));
});
source.setGainmap(null);
+ assertEquals(source.getColorSpace().getId(), ColorSpace.Named.SRGB.ordinal());
+
+ while (state.keepRunning()) {
+ Bitmap.createScaledBitmap(source, source.getWidth() / 2, source.getHeight() / 2, true)
+ .recycle();
+ }
+ }
+
+ @Test
+ public void testCreateScaledP3Bitmap() throws IOException {
+ BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ final Context context = InstrumentationRegistry.getContext();
+ Bitmap source = ImageDecoder.decodeBitmap(
+ ImageDecoder.createSource(context.getResources(), R.drawable.fountain_night),
+ (decoder, info, source1) -> {
+ decoder.setAllocator(ImageDecoder.ALLOCATOR_SOFTWARE);
+ decoder.setTargetColorSpace(ColorSpace.get(ColorSpace.Named.DISPLAY_P3));
+ });
+ source.setGainmap(null);
+ assertEquals(source.getColorSpace().getId(), ColorSpace.Named.DISPLAY_P3.ordinal());
while (state.keepRunning()) {
Bitmap.createScaledBitmap(source, source.getWidth() / 2, source.getHeight() / 2, true)
diff --git a/core/api/current.txt b/core/api/current.txt
index ec8f070..df073dd 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -12932,6 +12932,7 @@
field public static final String FEATURE_MIDI = "android.software.midi";
field public static final String FEATURE_NFC = "android.hardware.nfc";
field public static final String FEATURE_NFC_BEAM = "android.sofware.nfc.beam";
+ field @FlaggedApi("android.nfc.enable_nfc_charging") public static final String FEATURE_NFC_CHARGING = "android.hardware.nfc.charging";
field public static final String FEATURE_NFC_HOST_CARD_EMULATION = "android.hardware.nfc.hce";
field public static final String FEATURE_NFC_HOST_CARD_EMULATION_NFCF = "android.hardware.nfc.hcef";
field public static final String FEATURE_NFC_OFF_HOST_CARD_EMULATION_ESE = "android.hardware.nfc.ese";
@@ -28813,6 +28814,7 @@
method public void enableReaderMode(android.app.Activity, android.nfc.NfcAdapter.ReaderCallback, int, android.os.Bundle);
method public static android.nfc.NfcAdapter getDefaultAdapter(android.content.Context);
method @Nullable public android.nfc.NfcAntennaInfo getNfcAntennaInfo();
+ method @FlaggedApi("android.nfc.enable_nfc_charging") @Nullable public android.nfc.WlcLDeviceInfo getWlcLDeviceInfo();
method public boolean ignore(android.nfc.Tag, int, android.nfc.NfcAdapter.OnTagRemovedListener, android.os.Handler);
method public boolean isEnabled();
method @FlaggedApi("android.nfc.nfc_observe_mode") public boolean isObserveModeSupported();
@@ -28820,6 +28822,7 @@
method @FlaggedApi("android.nfc.enable_nfc_reader_option") public boolean isReaderOptionSupported();
method public boolean isSecureNfcEnabled();
method public boolean isSecureNfcSupported();
+ method @FlaggedApi("android.nfc.enable_nfc_charging") public boolean isWlcEnabled();
field public static final String ACTION_ADAPTER_STATE_CHANGED = "android.nfc.action.ADAPTER_STATE_CHANGED";
field public static final String ACTION_NDEF_DISCOVERED = "android.nfc.action.NDEF_DISCOVERED";
field @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO) public static final String ACTION_PREFERRED_PAYMENT_CHANGED = "android.nfc.action.PREFERRED_PAYMENT_CHANGED";
@@ -28905,6 +28908,20 @@
ctor public TagLostException(String);
}
+ @FlaggedApi("android.nfc.enable_nfc_charging") public final class WlcLDeviceInfo implements android.os.Parcelable {
+ ctor public WlcLDeviceInfo(double, double, double, int);
+ method public int describeContents();
+ method public double getBatteryLevel();
+ method public double getProductId();
+ method public int getState();
+ method public double getTemperature();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field public static final int CONNECTED_CHARGING = 2; // 0x2
+ field public static final int CONNECTED_DISCHARGING = 3; // 0x3
+ field @NonNull public static final android.os.Parcelable.Creator<android.nfc.WlcLDeviceInfo> CREATOR;
+ field public static final int DISCONNECTED = 1; // 0x1
+ }
+
}
package android.nfc.cardemulation {
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index b15bc0e..0d4169f 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -9884,17 +9884,20 @@
method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean enable();
method @FlaggedApi("android.nfc.enable_nfc_reader_option") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean enableReaderOption(boolean);
method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean enableSecureNfc(boolean);
+ method @FlaggedApi("android.nfc.enable_nfc_charging") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean enableWlc(boolean);
method @FlaggedApi("android.nfc.enable_nfc_mainline") public int getAdapterState();
method @NonNull @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public java.util.Map<java.lang.String,java.lang.Boolean> getTagIntentAppPreferenceForUser(int);
method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public boolean isControllerAlwaysOn();
method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public boolean isControllerAlwaysOnSupported();
method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean isTagIntentAppPreferenceSupported();
method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public void registerControllerAlwaysOnListener(@NonNull java.util.concurrent.Executor, @NonNull android.nfc.NfcAdapter.ControllerAlwaysOnListener);
+ method @FlaggedApi("android.nfc.enable_nfc_charging") public void registerWlcStateListener(@NonNull java.util.concurrent.Executor, @NonNull android.nfc.NfcAdapter.WlcStateListener);
method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean removeNfcUnlockHandler(android.nfc.NfcAdapter.NfcUnlockHandler);
method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public boolean setControllerAlwaysOn(boolean);
method @FlaggedApi("android.nfc.enable_nfc_mainline") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void setReaderMode(boolean);
method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public int setTagIntentAppPreferenceForUser(int, @NonNull String, boolean);
method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public void unregisterControllerAlwaysOnListener(@NonNull android.nfc.NfcAdapter.ControllerAlwaysOnListener);
+ method @FlaggedApi("android.nfc.enable_nfc_charging") public void unregisterWlcStateListener(@NonNull android.nfc.NfcAdapter.WlcStateListener);
field @FlaggedApi("android.nfc.enable_nfc_mainline") public static final String ACTION_REQUIRE_UNLOCK_FOR_NFC = "android.nfc.action.REQUIRE_UNLOCK_FOR_NFC";
field public static final int TAG_INTENT_APP_PREF_RESULT_PACKAGE_NOT_FOUND = -1; // 0xffffffff
field public static final int TAG_INTENT_APP_PREF_RESULT_SUCCESS = 0; // 0x0
@@ -9909,6 +9912,10 @@
method public boolean onUnlockAttempted(android.nfc.Tag);
}
+ @FlaggedApi("android.nfc.enable_nfc_charging") public static interface NfcAdapter.WlcStateListener {
+ method public void onWlcStateChanged(@NonNull android.nfc.WlcLDeviceInfo);
+ }
+
}
package android.nfc.cardemulation {
diff --git a/core/java/android/app/servertransaction/ClientTransactionListenerController.java b/core/java/android/app/servertransaction/ClientTransactionListenerController.java
index 7418c06..9f97f6f 100644
--- a/core/java/android/app/servertransaction/ClientTransactionListenerController.java
+++ b/core/java/android/app/servertransaction/ClientTransactionListenerController.java
@@ -16,7 +16,7 @@
package android.app.servertransaction;
-import static com.android.window.flags.Flags.syncWindowConfigUpdateFlag;
+import static com.android.window.flags.Flags.bundleClientTransactionFlag;
import static java.util.Objects.requireNonNull;
@@ -67,7 +67,7 @@
* window configuration.
*/
public void onDisplayChanged(int displayId) {
- if (!isSyncWindowConfigUpdateFlagEnabled()) {
+ if (!isBundleClientTransactionFlagEnabled()) {
return;
}
if (ActivityThread.isSystem()) {
@@ -77,9 +77,9 @@
mDisplayManager.handleDisplayChangeFromWindowManager(displayId);
}
- /** Whether {@link #syncWindowConfigUpdateFlag} feature flag is enabled. */
- public boolean isSyncWindowConfigUpdateFlagEnabled() {
+ /** Whether {@link #bundleClientTransactionFlag} feature flag is enabled. */
+ public boolean isBundleClientTransactionFlagEnabled() {
// Can't read flag from isolated process.
- return !Process.isIsolated() && syncWindowConfigUpdateFlag();
+ return !Process.isIsolated() && bundleClientTransactionFlag();
}
}
diff --git a/core/java/android/app/servertransaction/TransactionExecutor.java b/core/java/android/app/servertransaction/TransactionExecutor.java
index 9f5e0dc..ee48e43 100644
--- a/core/java/android/app/servertransaction/TransactionExecutor.java
+++ b/core/java/android/app/servertransaction/TransactionExecutor.java
@@ -32,7 +32,7 @@
import static android.app.servertransaction.TransactionExecutorHelper.tId;
import static android.app.servertransaction.TransactionExecutorHelper.transactionToString;
-import static com.android.window.flags.Flags.syncWindowConfigUpdateFlag;
+import static com.android.window.flags.Flags.bundleClientTransactionFlag;
import android.annotation.NonNull;
import android.app.ActivityThread.ActivityClientRecord;
@@ -183,9 +183,9 @@
}
// Can't read flag from isolated process.
- final boolean isSyncWindowConfigUpdateFlagEnabled = !Process.isIsolated()
- && syncWindowConfigUpdateFlag();
- final Context configUpdatedContext = isSyncWindowConfigUpdateFlagEnabled
+ final boolean isBundleClientTransactionFlagEnabled = !Process.isIsolated()
+ && bundleClientTransactionFlag();
+ final Context configUpdatedContext = isBundleClientTransactionFlagEnabled
? item.getContextToUpdate(mTransactionHandler)
: null;
final Configuration preExecutedConfig = configUpdatedContext != null
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index b75c64d..fa76e39 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -3547,6 +3547,8 @@
*
* @param receiver The BroadcastReceiver to unregister.
*
+ * @throws IllegalArgumentException if the {@code receiver} was not previously registered or
+ * already unregistered.
* @see #registerReceiver
*/
public abstract void unregisterReceiver(BroadcastReceiver receiver);
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 69273df..8151a91 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -16,6 +16,8 @@
package android.content.pm;
+import static com.android.internal.pm.pkg.parsing.ParsingPackageUtils.PARSE_COLLECT_CERTIFICATES;
+
import android.Manifest;
import android.annotation.CallbackExecutor;
import android.annotation.CheckResult;
@@ -55,7 +57,6 @@
import android.content.IntentSender;
import android.content.pm.PackageInstaller.SessionParams;
import android.content.pm.dex.ArtManager;
-import android.content.pm.pkg.FrameworkPackageUserState;
import android.content.pm.verify.domain.DomainVerificationManager;
import android.content.res.Configuration;
import android.content.res.Resources;
@@ -91,6 +92,10 @@
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.pm.parsing.PackageInfoCommonUtils;
+import com.android.internal.pm.parsing.PackageParser2;
+import com.android.internal.pm.parsing.PackageParserException;
+import com.android.internal.pm.parsing.pkg.ParsedPackage;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.DataClass;
@@ -817,6 +822,8 @@
GET_DISABLED_UNTIL_USED_COMPONENTS,
GET_UNINSTALLED_PACKAGES,
MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS,
+ MATCH_DIRECT_BOOT_AWARE,
+ MATCH_DIRECT_BOOT_UNAWARE,
GET_ATTRIBUTIONS_LONG,
})
@Retention(RetentionPolicy.SOURCE)
@@ -3306,6 +3313,14 @@
/**
* Feature for {@link #getSystemAvailableFeatures} and
+ * {@link #hasSystemFeature}: The device supports NFC charging.
+ */
+ @SdkConstant(SdkConstantType.FEATURE)
+ @FlaggedApi(android.nfc.Flags.FLAG_ENABLE_NFC_CHARGING)
+ public static final String FEATURE_NFC_CHARGING = "android.hardware.nfc.charging";
+
+ /**
+ * Feature for {@link #getSystemAvailableFeatures} and
* {@link #hasSystemFeature}: The Beam API is enabled on the device.
*/
@SdkConstant(SdkConstantType.FEATURE)
@@ -3315,7 +3330,7 @@
* Feature for {@link #getSystemAvailableFeatures} and
* {@link #hasSystemFeature}: The device supports any
* one of the {@link #FEATURE_NFC}, {@link #FEATURE_NFC_HOST_CARD_EMULATION},
- * or {@link #FEATURE_NFC_HOST_CARD_EMULATION_NFCF} features.
+ * {@link #FEATURE_NFC_HOST_CARD_EMULATION_NFCF}, or {@link #FEATURE_NFC_CHARGING} features.
*
* @hide
*/
@@ -8620,28 +8635,56 @@
@Nullable
public PackageInfo getPackageArchiveInfo(@NonNull String archiveFilePath,
@NonNull PackageInfoFlags flags) {
- long flagsBits = flags.getValue();
- final PackageParser parser = new PackageParser();
- parser.setCallback(new PackageParser.CallbackImpl(this));
final File apkFile = new File(archiveFilePath);
- try {
- if ((flagsBits & (MATCH_DIRECT_BOOT_UNAWARE | MATCH_DIRECT_BOOT_AWARE)) != 0) {
- // Caller expressed an explicit opinion about what encryption
- // aware/unaware components they want to see, so fall through and
- // give them what they want
- } else {
- // Caller expressed no opinion, so match everything
- flagsBits |= MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE;
- }
- PackageParser.Package pkg = parser.parsePackage(apkFile, 0, false);
- if ((flagsBits & GET_SIGNATURES) != 0 || (flagsBits & GET_SIGNING_CERTIFICATES) != 0) {
- PackageParser.collectCertificates(pkg, false /* skipVerify */);
- }
- return PackageParser.generatePackageInfo(pkg, null, (int) flagsBits, 0, 0, null,
- FrameworkPackageUserState.DEFAULT);
- } catch (PackageParser.PackageParserException e) {
- Log.w(TAG, "Failure to parse package archive", e);
+ @PackageInfoFlagsBits long flagsBits = flags.getValue();
+ if ((flagsBits & (MATCH_DIRECT_BOOT_UNAWARE | MATCH_DIRECT_BOOT_AWARE)) != 0) {
+ // Caller expressed an explicit opinion about what encryption
+ // aware/unaware components they want to see, so fall through and
+ // give them what they want
+ } else {
+ // Caller expressed no opinion, so match everything
+ flagsBits |= MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE;
+ }
+
+ int parserFlags = 0;
+ if ((flagsBits & (GET_SIGNATURES | GET_SIGNING_CERTIFICATES)) != 0) {
+ parserFlags |= PARSE_COLLECT_CERTIFICATES;
+ }
+
+ final PackageParser2 parser2 = new PackageParser2(/*separateProcesses*/ null,
+ /*displayMetrics*/ null,/*cacher*/ null,
+ new PackageParser2.Callback() {
+ @Override
+ public boolean hasFeature(String feature) {
+ return PackageManager.this.hasSystemFeature(feature);
+ }
+
+ @NonNull
+ @Override
+ public Set<String> getHiddenApiWhitelistedApps() {
+ return Collections.emptySet();
+ }
+
+ @NonNull
+ @Override
+ public Set<String> getInstallConstraintsAllowlist() {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public boolean isChangeEnabled(long changeId,
+ @androidx.annotation.NonNull ApplicationInfo appInfo) {
+ return false;
+ }
+ });
+
+ try {
+ ParsedPackage pp = parser2.parsePackage(apkFile, parserFlags, false);
+
+ return PackageInfoCommonUtils.generate(pp, flagsBits, UserHandle.myUserId());
+ } catch (PackageParserException e) {
+ Log.w(TAG, "Failure to parse package archive apkFile= " +apkFile);
return null;
}
}
diff --git a/core/java/android/net/LocalSocket.java b/core/java/android/net/LocalSocket.java
index b69410c..a86396c 100644
--- a/core/java/android/net/LocalSocket.java
+++ b/core/java/android/net/LocalSocket.java
@@ -196,7 +196,8 @@
}
/**
- * Retrieves the input stream for this instance.
+ * Retrieves the input stream for this instance. Closing this stream is equivalent to closing
+ * the entire socket and its associated streams using {@link #close()}.
*
* @return input stream
* @throws IOException if socket has been closed or cannot be created.
@@ -207,7 +208,8 @@
}
/**
- * Retrieves the output stream for this instance.
+ * Retrieves the output stream for this instance. Closing this stream is equivalent to closing
+ * the entire socket and its associated streams using {@link #close()}.
*
* @return output stream
* @throws IOException if socket has been closed or cannot be created.
diff --git a/core/java/android/nfc/INfcAdapter.aidl b/core/java/android/nfc/INfcAdapter.aidl
index f6beec1..967a0cc 100644
--- a/core/java/android/nfc/INfcAdapter.aidl
+++ b/core/java/android/nfc/INfcAdapter.aidl
@@ -30,8 +30,10 @@
import android.nfc.INfcUnlockHandler;
import android.nfc.ITagRemovedCallback;
import android.nfc.INfcDta;
+import android.nfc.INfcWlcStateListener;
import android.nfc.NfcAntennaInfo;
import android.os.Bundle;
+import android.nfc.WlcLDeviceInfo;
/**
* @hide
@@ -86,4 +88,11 @@
boolean enableReaderOption(boolean enable);
boolean isObserveModeSupported();
boolean setObserveMode(boolean enabled);
+
+ @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)")
+ boolean enableWlc(boolean enable);
+ boolean isWlcEnabled();
+ void registerWlcStateListener(in INfcWlcStateListener listener);
+ void unregisterWlcStateListener(in INfcWlcStateListener listener);
+ WlcLDeviceInfo getWlcLDeviceInfo();
}
diff --git a/core/java/android/nfc/INfcWlcStateListener.aidl b/core/java/android/nfc/INfcWlcStateListener.aidl
new file mode 100644
index 0000000..c2b7075
--- /dev/null
+++ b/core/java/android/nfc/INfcWlcStateListener.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.nfc;
+
+import android.nfc.WlcLDeviceInfo;
+/**
+ * @hide
+ */
+oneway interface INfcWlcStateListener {
+ /**
+ * Called whenever NFC WLC state changes
+ *
+ * @param wlcLDeviceInfo NFC wlc listener information
+ */
+ void onWlcStateChanged(in WlcLDeviceInfo wlcLDeviceInfo);
+}
diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java
index f407fb7..21e23ae 100644
--- a/core/java/android/nfc/NfcAdapter.java
+++ b/core/java/android/nfc/NfcAdapter.java
@@ -75,6 +75,7 @@
static final String TAG = "NFC";
private final NfcControllerAlwaysOnListener mControllerAlwaysOnListener;
+ private final NfcWlcStateListener mNfcWlcStateListener;
/**
* Intent to start an activity when a tag with NDEF payload is discovered.
@@ -440,6 +441,7 @@
static boolean sIsInitialized = false;
static boolean sHasNfcFeature;
static boolean sHasCeFeature;
+ static boolean sHasNfcWlcFeature;
// Final after first constructor, except for
// attemptDeadServiceRecovery() when NFC crashes - we accept a best effort
@@ -650,8 +652,9 @@
|| pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION_NFCF)
|| pm.hasSystemFeature(PackageManager.FEATURE_NFC_OFF_HOST_CARD_EMULATION_UICC)
|| pm.hasSystemFeature(PackageManager.FEATURE_NFC_OFF_HOST_CARD_EMULATION_ESE);
+ sHasNfcWlcFeature = pm.hasSystemFeature(PackageManager.FEATURE_NFC_CHARGING);
/* is this device meant to have NFC */
- if (!sHasNfcFeature && !sHasCeFeature) {
+ if (!sHasNfcFeature && !sHasCeFeature && !sHasNfcWlcFeature) {
Log.v(TAG, "this device does not have NFC support");
throw new UnsupportedOperationException();
}
@@ -776,6 +779,7 @@
mTagRemovedListener = null;
mLock = new Object();
mControllerAlwaysOnListener = new NfcControllerAlwaysOnListener(getService());
+ mNfcWlcStateListener = new NfcWlcStateListener(getService());
}
/**
@@ -944,7 +948,8 @@
Log.e(TAG, "Failed to recover NFC Service.");
}
}
- return serviceState && (isTagReadingEnabled() || isCardEmulationEnabled());
+ return serviceState
+ && (isTagReadingEnabled() || isCardEmulationEnabled() || sHasNfcWlcFeature);
}
/**
@@ -2587,4 +2592,159 @@
return false;
}
}
+
+ /**
+ * Sets NFC charging feature.
+ * <p>This API is for the Settings application.
+ * @return True if successful
+ * @hide
+ */
+ @SystemApi
+ @FlaggedApi(Flags.FLAG_ENABLE_NFC_CHARGING)
+ @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
+ public boolean enableWlc(boolean enable) {
+ if (!sHasNfcWlcFeature) {
+ throw new UnsupportedOperationException();
+ }
+ try {
+ return sService.enableWlc(enable);
+ } catch (RemoteException e) {
+ attemptDeadServiceRecovery(e);
+ // Try one more time
+ if (sService == null) {
+ Log.e(TAG, "Failed to recover NFC Service.");
+ return false;
+ }
+ try {
+ return sService.enableWlc(enable);
+ } catch (RemoteException ee) {
+ Log.e(TAG, "Failed to recover NFC Service.");
+ }
+ return false;
+ }
+ }
+
+ /**
+ * Checks NFC charging feature is enabled.
+ *
+ * @return True if NFC charging is enabled, false otherwise
+ * @throws UnsupportedOperationException if FEATURE_NFC_CHARGING
+ * is unavailable
+ */
+ @FlaggedApi(Flags.FLAG_ENABLE_NFC_CHARGING)
+ public boolean isWlcEnabled() {
+ if (!sHasNfcWlcFeature) {
+ throw new UnsupportedOperationException();
+ }
+ try {
+ return sService.isWlcEnabled();
+ } catch (RemoteException e) {
+ attemptDeadServiceRecovery(e);
+ // Try one more time
+ if (sService == null) {
+ Log.e(TAG, "Failed to recover NFC Service.");
+ return false;
+ }
+ try {
+ return sService.isWlcEnabled();
+ } catch (RemoteException ee) {
+ Log.e(TAG, "Failed to recover NFC Service.");
+ }
+ return false;
+ }
+ }
+
+ /**
+ * A listener to be invoked when NFC controller always on state changes.
+ * <p>Register your {@code ControllerAlwaysOnListener} implementation with {@link
+ * NfcAdapter#registerWlcStateListener} and disable it with {@link
+ * NfcAdapter#unregisterWlcStateListenerListener}.
+ * @see #registerWlcStateListener
+ * @hide
+ */
+ @SystemApi
+ @FlaggedApi(Flags.FLAG_ENABLE_NFC_CHARGING)
+ public interface WlcStateListener {
+ /**
+ * Called on NFC WLC state changes
+ */
+ void onWlcStateChanged(@NonNull WlcLDeviceInfo wlcLDeviceInfo);
+ }
+
+ /**
+ * Register a {@link WlcStateListener} to listen for NFC WLC state changes
+ * <p>The provided listener will be invoked by the given {@link Executor}.
+ *
+ * @param executor an {@link Executor} to execute given listener
+ * @param listener user implementation of the {@link WlcStateListener}
+ * @throws UnsupportedOperationException if FEATURE_NFC_CHARGING
+ * is unavailable
+ *
+ * @hide
+ */
+ @SystemApi
+ @FlaggedApi(Flags.FLAG_ENABLE_NFC_CHARGING)
+ public void registerWlcStateListener(
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull WlcStateListener listener) {
+ if (!sHasNfcWlcFeature) {
+ throw new UnsupportedOperationException();
+ }
+ mNfcWlcStateListener.register(executor, listener);
+ }
+
+ /**
+ * Unregister the specified {@link WlcStateListener}
+ * <p>The same {@link WlcStateListener} object used when calling
+ * {@link #registerWlcStateListener(Executor, WlcStateListener)}
+ * must be used.
+ *
+ * <p>Listeners are automatically unregistered when application process goes away
+ *
+ * @param listener user implementation of the {@link WlcStateListener}a
+ * @throws UnsupportedOperationException if FEATURE_NFC_CHARGING
+ * is unavailable
+ *
+ * @hide
+ */
+ @SystemApi
+ @FlaggedApi(Flags.FLAG_ENABLE_NFC_CHARGING)
+ public void unregisterWlcStateListener(
+ @NonNull WlcStateListener listener) {
+ if (!sHasNfcWlcFeature) {
+ throw new UnsupportedOperationException();
+ }
+ mNfcWlcStateListener.unregister(listener);
+ }
+
+ /**
+ * Returns information on the NFC charging listener device
+ *
+ * @return Information on the NFC charging listener device
+ * @throws UnsupportedOperationException if FEATURE_NFC_CHARGING
+ * is unavailable
+ */
+ @FlaggedApi(Flags.FLAG_ENABLE_NFC_CHARGING)
+ @Nullable
+ public WlcLDeviceInfo getWlcLDeviceInfo() {
+ if (!sHasNfcWlcFeature) {
+ throw new UnsupportedOperationException();
+ }
+ try {
+ return sService.getWlcLDeviceInfo();
+ } catch (RemoteException e) {
+ attemptDeadServiceRecovery(e);
+ // Try one more time
+ if (sService == null) {
+ Log.e(TAG, "Failed to recover NFC Service.");
+ return null;
+ }
+ try {
+ return sService.getWlcLDeviceInfo();
+ } catch (RemoteException ee) {
+ Log.e(TAG, "Failed to recover NFC Service.");
+ }
+ return null;
+ }
+ }
}
diff --git a/core/java/android/nfc/NfcWlcStateListener.java b/core/java/android/nfc/NfcWlcStateListener.java
new file mode 100644
index 0000000..8d79310
--- /dev/null
+++ b/core/java/android/nfc/NfcWlcStateListener.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.nfc;
+
+import android.annotation.NonNull;
+import android.nfc.NfcAdapter.WlcStateListener;
+import android.os.Binder;
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.Executor;
+
+/**
+ * @hide
+ */
+public class NfcWlcStateListener extends INfcWlcStateListener.Stub {
+ private static final String TAG = NfcWlcStateListener.class.getSimpleName();
+
+ private final INfcAdapter mAdapter;
+
+ private final Map<WlcStateListener, Executor> mListenerMap = new HashMap<>();
+
+ private WlcLDeviceInfo mCurrentState = null;
+ private boolean mIsRegistered = false;
+
+ public NfcWlcStateListener(@NonNull INfcAdapter adapter) {
+ mAdapter = adapter;
+ }
+
+ /**
+ * Register a {@link WlcStateListener} with this
+ * {@link WlcStateListener}
+ *
+ * @param executor an {@link Executor} to execute given listener
+ * @param listener user implementation of the {@link WlcStateListener}
+ */
+ public void register(@NonNull Executor executor, @NonNull WlcStateListener listener) {
+ synchronized (this) {
+ if (mListenerMap.containsKey(listener)) {
+ return;
+ }
+
+ mListenerMap.put(listener, executor);
+
+ if (!mIsRegistered) {
+ try {
+ mAdapter.registerWlcStateListener(this);
+ mIsRegistered = true;
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed to register");
+ }
+ }
+ }
+ }
+
+ /**
+ * Unregister the specified {@link WlcStateListener}
+ *
+ * @param listener user implementation of the {@link WlcStateListener}
+ */
+ public void unregister(@NonNull WlcStateListener listener) {
+ synchronized (this) {
+ if (!mListenerMap.containsKey(listener)) {
+ return;
+ }
+
+ mListenerMap.remove(listener);
+
+ if (mListenerMap.isEmpty() && mIsRegistered) {
+ try {
+ mAdapter.unregisterWlcStateListener(this);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed to unregister");
+ }
+ mIsRegistered = false;
+ }
+ }
+ }
+
+ private void sendCurrentState(@NonNull WlcStateListener listener) {
+ synchronized (this) {
+ Executor executor = mListenerMap.get(listener);
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ executor.execute(() -> listener.onWlcStateChanged(
+ mCurrentState));
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+ }
+
+ @Override
+ public void onWlcStateChanged(@NonNull WlcLDeviceInfo wlcLDeviceInfo) {
+ synchronized (this) {
+ mCurrentState = wlcLDeviceInfo;
+
+ for (WlcStateListener cb : mListenerMap.keySet()) {
+ sendCurrentState(cb);
+ }
+ }
+ }
+}
+
diff --git a/core/java/android/nfc/WlcLDeviceInfo.aidl b/core/java/android/nfc/WlcLDeviceInfo.aidl
new file mode 100644
index 0000000..33143fe
--- /dev/null
+++ b/core/java/android/nfc/WlcLDeviceInfo.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.nfc;
+
+parcelable WlcLDeviceInfo;
diff --git a/core/java/android/nfc/WlcLDeviceInfo.java b/core/java/android/nfc/WlcLDeviceInfo.java
new file mode 100644
index 0000000..016431e
--- /dev/null
+++ b/core/java/android/nfc/WlcLDeviceInfo.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.nfc;
+
+import android.annotation.FlaggedApi;
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Contains information of the nfc wireless charging listener device information.
+ */
+@FlaggedApi(Flags.FLAG_ENABLE_NFC_CHARGING)
+public final class WlcLDeviceInfo implements Parcelable {
+ public static final int DISCONNECTED = 1;
+
+ public static final int CONNECTED_CHARGING = 2;
+
+ public static final int CONNECTED_DISCHARGING = 3;
+
+ private double mProductId;
+ private double mTemperature;
+ private double mBatteryLevel;
+ private int mState;
+
+ public WlcLDeviceInfo(double productId, double temperature, double batteryLevel, int state) {
+ this.mProductId = productId;
+ this.mTemperature = temperature;
+ this.mBatteryLevel = batteryLevel;
+ this.mState = state;
+ }
+
+ /**
+ * ProductId of the WLC listener device.
+ */
+ public double getProductId() {
+ return mProductId;
+ }
+
+ /**
+ * Temperature of the WLC listener device.
+ */
+ public double getTemperature() {
+ return mTemperature;
+ }
+
+ /**
+ * BatteryLevel of the WLC listener device.
+ */
+ public double getBatteryLevel() {
+ return mBatteryLevel;
+ }
+
+ /**
+ * State of the WLC listener device.
+ */
+ public int getState() {
+ return mState;
+ }
+
+ private WlcLDeviceInfo(Parcel in) {
+ this.mProductId = in.readDouble();
+ this.mTemperature = in.readDouble();
+ this.mBatteryLevel = in.readDouble();
+ this.mState = in.readInt();
+ }
+
+ public static final @NonNull Parcelable.Creator<WlcLDeviceInfo> CREATOR =
+ new Parcelable.Creator<WlcLDeviceInfo>() {
+ @Override
+ public WlcLDeviceInfo createFromParcel(Parcel in) {
+ return new WlcLDeviceInfo(in);
+ }
+
+ @Override
+ public WlcLDeviceInfo[] newArray(int size) {
+ return new WlcLDeviceInfo[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeDouble(mProductId);
+ dest.writeDouble(mTemperature);
+ dest.writeDouble(mBatteryLevel);
+ dest.writeDouble(mState);
+ }
+}
diff --git a/core/java/android/nfc/flags.aconfig b/core/java/android/nfc/flags.aconfig
index 0d073cc..ce4f777 100644
--- a/core/java/android/nfc/flags.aconfig
+++ b/core/java/android/nfc/flags.aconfig
@@ -55,3 +55,10 @@
description: "Enable sending broadcasts to Wallet role holder when a tag enters/leaves the field."
bug: "306203494"
}
+
+flag {
+ name: "enable_nfc_charging"
+ namespace: "nfc"
+ description: "Flag for NFC charging changes"
+ bug: "292143899"
+}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 1f81a64..fcdad66 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -11910,6 +11910,12 @@
if (syncBuffer) {
boolean result = mBlastBufferQueue.syncNextTransaction(transaction -> {
+ Runnable timeoutRunnable = () -> Log.e(mTag,
+ "Failed to submit the sync transaction after 4s. Likely to ANR "
+ + "soon");
+ mHandler.postDelayed(timeoutRunnable, 4L * Build.HW_TIMEOUT_MULTIPLIER);
+ transaction.addTransactionCommittedListener(mSimpleExecutor,
+ () -> mHandler.removeCallbacks(timeoutRunnable));
surfaceSyncGroup.addTransaction(transaction);
surfaceSyncGroup.markSyncReady();
});
diff --git a/core/java/android/window/flags/windowing_sdk.aconfig b/core/java/android/window/flags/windowing_sdk.aconfig
index 933cc49..59d7b0e 100644
--- a/core/java/android/window/flags/windowing_sdk.aconfig
+++ b/core/java/android/window/flags/windowing_sdk.aconfig
@@ -2,13 +2,6 @@
# Project link: https://gantry.corp.google.com/projects/android_platform_windowing_sdk/changes
-flag {
- namespace: "windowing_sdk"
- name: "sync_window_config_update_flag"
- description: "Whether the feature to sync different window-related config updates is enabled"
- bug: "260873529"
-}
-
# Using a fixed read only flag because there are ClientTransaction scheduling before
# WindowManagerService creation.
flag {
@@ -35,13 +28,6 @@
flag {
namespace: "windowing_sdk"
- name: "window_state_resize_item_flag"
- description: "Whether to dispatch window resize through ClientTransaction is enabled"
- bug: "301870955"
-}
-
-flag {
- namespace: "windowing_sdk"
name: "fullscreen_dim_flag"
description: "Whether to allow showing fullscreen dim on ActivityEmbedding split"
bug: "253533308"
diff --git a/core/java/com/android/internal/pm/parsing/PackageInfoCommonUtils.java b/core/java/com/android/internal/pm/parsing/PackageInfoCommonUtils.java
new file mode 100644
index 0000000..f05d9cb
--- /dev/null
+++ b/core/java/com/android/internal/pm/parsing/PackageInfoCommonUtils.java
@@ -0,0 +1,652 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.pm.parsing;
+
+import static com.android.internal.pm.pkg.SEInfoUtil.COMPLETE_STR;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.UserIdInt;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.Attribution;
+import android.content.pm.ComponentInfo;
+import android.content.pm.ConfigurationInfo;
+import android.content.pm.FallbackCategoryProvider;
+import android.content.pm.FeatureGroupInfo;
+import android.content.pm.FeatureInfo;
+import android.content.pm.InstrumentationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageItemInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PathPermission;
+import android.content.pm.PermissionInfo;
+import android.content.pm.ProviderInfo;
+import android.content.pm.ServiceInfo;
+import android.content.pm.Signature;
+import android.content.pm.SigningDetails;
+import android.content.pm.SigningInfo;
+import android.os.Debug;
+import android.os.PatternMatcher;
+import android.os.UserHandle;
+import android.util.DebugUtils;
+import android.util.Slog;
+
+import com.android.internal.pm.parsing.pkg.AndroidPackageHidden;
+import com.android.internal.pm.parsing.pkg.AndroidPackageLegacyUtils;
+import com.android.internal.pm.parsing.pkg.PackageImpl;
+import com.android.internal.pm.pkg.component.ComponentParseUtils;
+import com.android.internal.pm.pkg.component.ParsedActivity;
+import com.android.internal.pm.pkg.component.ParsedAttribution;
+import com.android.internal.pm.pkg.component.ParsedComponent;
+import com.android.internal.pm.pkg.component.ParsedInstrumentation;
+import com.android.internal.pm.pkg.component.ParsedMainComponent;
+import com.android.internal.pm.pkg.component.ParsedPermission;
+import com.android.internal.pm.pkg.component.ParsedProvider;
+import com.android.internal.pm.pkg.component.ParsedService;
+import com.android.internal.pm.pkg.component.ParsedUsesPermission;
+import com.android.internal.pm.pkg.parsing.ParsingPackageHidden;
+import com.android.internal.pm.pkg.parsing.ParsingPackageUtils;
+import com.android.internal.pm.pkg.parsing.ParsingUtils;
+import com.android.internal.util.ArrayUtils;
+import com.android.server.pm.pkg.AndroidPackage;
+
+import java.util.List;
+
+/**
+ * Method that use a {@link AndroidPackage} to generate a {@link PackageInfo} though
+ * the given {@link PackageManager.PackageInfoFlags}
+ * @hide
+ **/
+// TODO(b/317215254): refactor coped code from PackageInfoUtils
+public class PackageInfoCommonUtils {
+
+ private static final String TAG = ParsingUtils.TAG;
+ private static final boolean DEBUG = false;
+
+ /**
+ * Generates a {@link PackageInfo} from the given {@link AndroidPackage}
+ */
+ @Nullable
+ public static PackageInfo generate(@Nullable AndroidPackage pkg,
+ @PackageManager.PackageInfoFlagsBits long flags, int userId) {
+ if (pkg == null) {
+ return null;
+ }
+ ApplicationInfo applicationInfo = generateApplicationInfo(pkg, flags, userId);
+
+ PackageInfo info = new PackageInfo();
+ info.packageName = pkg.getPackageName();
+ info.splitNames = pkg.getSplitNames();
+ info.versionCode = ((ParsingPackageHidden) pkg).getVersionCode();
+ info.versionCodeMajor = ((ParsingPackageHidden) pkg).getVersionCodeMajor();
+ info.baseRevisionCode = pkg.getBaseRevisionCode();
+ info.splitRevisionCodes = pkg.getSplitRevisionCodes();
+ info.versionName = pkg.getVersionName();
+ info.sharedUserId = pkg.getSharedUserId();
+ info.sharedUserLabel = pkg.getSharedUserLabelResourceId();
+ info.applicationInfo = applicationInfo;
+ info.installLocation = pkg.getInstallLocation();
+ if ((info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0
+ || (info.applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
+ info.requiredForAllUsers = pkg.isRequiredForAllUsers();
+ }
+ info.restrictedAccountType = pkg.getRestrictedAccountType();
+ info.requiredAccountType = pkg.getRequiredAccountType();
+ info.overlayTarget = pkg.getOverlayTarget();
+ info.targetOverlayableName = pkg.getOverlayTargetOverlayableName();
+ info.overlayCategory = pkg.getOverlayCategory();
+ info.overlayPriority = pkg.getOverlayPriority();
+ info.mOverlayIsStatic = pkg.isOverlayIsStatic();
+ info.compileSdkVersion = pkg.getCompileSdkVersion();
+ info.compileSdkVersionCodename = pkg.getCompileSdkVersionCodeName();
+ info.isStub = pkg.isStub();
+ info.coreApp = pkg.isCoreApp();
+ info.isApex = pkg.isApex();
+
+ if ((flags & PackageManager.GET_CONFIGURATIONS) != 0) {
+ int size = pkg.getConfigPreferences().size();
+ if (size > 0) {
+ info.configPreferences = new ConfigurationInfo[size];
+ pkg.getConfigPreferences().toArray(info.configPreferences);
+ }
+ size = pkg.getRequestedFeatures().size();
+ if (size > 0) {
+ info.reqFeatures = new FeatureInfo[size];
+ pkg.getRequestedFeatures().toArray(info.reqFeatures);
+ }
+ size = pkg.getFeatureGroups().size();
+ if (size > 0) {
+ info.featureGroups = new FeatureGroupInfo[size];
+ pkg.getFeatureGroups().toArray(info.featureGroups);
+ }
+ }
+ if ((flags & PackageManager.GET_PERMISSIONS) != 0) {
+ int size = ArrayUtils.size(pkg.getPermissions());
+ if (size > 0) {
+ info.permissions = new PermissionInfo[size];
+ for (int i = 0; i < size; i++) {
+ final var permission = pkg.getPermissions().get(i);
+ final var permissionInfo = generatePermissionInfo(permission, flags);
+ info.permissions[i] = permissionInfo;
+ }
+ }
+ final List<ParsedUsesPermission> usesPermissions = pkg.getUsesPermissions();
+ size = usesPermissions.size();
+ if (size > 0) {
+ info.requestedPermissions = new String[size];
+ info.requestedPermissionsFlags = new int[size];
+ for (int i = 0; i < size; i++) {
+ final ParsedUsesPermission usesPermission = usesPermissions.get(i);
+ info.requestedPermissions[i] = usesPermission.getName();
+ // The notion of required permissions is deprecated but for compatibility.
+ info.requestedPermissionsFlags[i] |=
+ PackageInfo.REQUESTED_PERMISSION_REQUIRED;
+ if ((usesPermission.getUsesPermissionFlags()
+ & ParsedUsesPermission.FLAG_NEVER_FOR_LOCATION) != 0) {
+ info.requestedPermissionsFlags[i] |=
+ PackageInfo.REQUESTED_PERMISSION_NEVER_FOR_LOCATION;
+ }
+ if (pkg.getImplicitPermissions().contains(info.requestedPermissions[i])) {
+ info.requestedPermissionsFlags[i] |=
+ PackageInfo.REQUESTED_PERMISSION_IMPLICIT;
+ }
+ }
+ }
+ }
+ if ((flags & PackageManager.GET_ATTRIBUTIONS_LONG) != 0) {
+ int size = ArrayUtils.size(pkg.getAttributions());
+ if (size > 0) {
+ info.attributions = new Attribution[size];
+ for (int i = 0; i < size; i++) {
+ ParsedAttribution parsedAttribution = pkg.getAttributions().get(i);
+ if (parsedAttribution != null) {
+ info.attributions[i] = new Attribution(parsedAttribution.getTag(),
+ parsedAttribution.getLabel());
+ }
+ }
+ }
+ if (pkg.isAttributionsUserVisible()) {
+ info.applicationInfo.privateFlagsExt
+ |= ApplicationInfo.PRIVATE_FLAG_EXT_ATTRIBUTIONS_ARE_USER_VISIBLE;
+ } else {
+ info.applicationInfo.privateFlagsExt
+ &= ~ApplicationInfo.PRIVATE_FLAG_EXT_ATTRIBUTIONS_ARE_USER_VISIBLE;
+ }
+ } else {
+ info.applicationInfo.privateFlagsExt
+ &= ~ApplicationInfo.PRIVATE_FLAG_EXT_ATTRIBUTIONS_ARE_USER_VISIBLE;
+ }
+
+ final SigningDetails signingDetails = pkg.getSigningDetails();
+ // deprecated method of getting signing certificates
+ if ((flags & PackageManager.GET_SIGNATURES) != 0) {
+ if (signingDetails.hasPastSigningCertificates()) {
+ // Package has included signing certificate rotation information. Return the oldest
+ // cert so that programmatic checks keep working even if unaware of key rotation.
+ info.signatures = new Signature[1];
+ info.signatures[0] = signingDetails.getPastSigningCertificates()[0];
+ } else if (signingDetails.hasSignatures()) {
+ // otherwise keep old behavior
+ int numberOfSigs = signingDetails.getSignatures().length;
+ info.signatures = new Signature[numberOfSigs];
+ System.arraycopy(signingDetails.getSignatures(), 0, info.signatures, 0,
+ numberOfSigs);
+ }
+ }
+
+ // replacement for GET_SIGNATURES
+ if ((flags & PackageManager.GET_SIGNING_CERTIFICATES) != 0) {
+ if (signingDetails != SigningDetails.UNKNOWN) {
+ // only return a valid SigningInfo if there is signing information to report
+ info.signingInfo = new SigningInfo(signingDetails);
+ } else {
+ info.signingInfo = null;
+ }
+ }
+
+ if ((flags & PackageManager.GET_ACTIVITIES) != 0) {
+ final int size = pkg.getActivities().size();
+ if (size > 0) {
+ int num = 0;
+ final ActivityInfo[] res = new ActivityInfo[size];
+ for (int i = 0; i < size; i++) {
+ final ParsedActivity a = pkg.getActivities().get(i);
+ if (isMatch(pkg, a.isDirectBootAware(), flags)) {
+ if (PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME.equals(
+ a.getName())) {
+ continue;
+ }
+ res[num++] = generateActivityInfo(a, flags, applicationInfo);
+ }
+ }
+ info.activities = ArrayUtils.trimToSize(res, num);
+ }
+ }
+ if ((flags & PackageManager.GET_RECEIVERS) != 0) {
+ final int size = pkg.getReceivers().size();
+ if (size > 0) {
+ int num = 0;
+ final ActivityInfo[] res = new ActivityInfo[size];
+ for (int i = 0; i < size; i++) {
+ final ParsedActivity a = pkg.getReceivers().get(i);
+ if (isMatch(pkg, a.isDirectBootAware(), flags)) {
+ res[num++] = generateActivityInfo(a, flags, applicationInfo);
+ }
+ }
+ info.receivers = ArrayUtils.trimToSize(res, num);
+ }
+ }
+ if ((flags & PackageManager.GET_SERVICES) != 0) {
+ final int size = pkg.getServices().size();
+ if (size > 0) {
+ int num = 0;
+ final ServiceInfo[] res = new ServiceInfo[size];
+ for (int i = 0; i < size; i++) {
+ final ParsedService s = pkg.getServices().get(i);
+ if (isMatch(pkg, s.isDirectBootAware(), flags)) {
+ res[num++] = generateServiceInfo(s, flags, applicationInfo);
+ }
+ }
+ info.services = ArrayUtils.trimToSize(res, num);
+ }
+ }
+ if ((flags & PackageManager.GET_PROVIDERS) != 0) {
+ final int size = pkg.getProviders().size();
+ if (size > 0) {
+ int num = 0;
+ final ProviderInfo[] res = new ProviderInfo[size];
+ for (int i = 0; i < size; i++) {
+ final ParsedProvider pr = pkg.getProviders().get(i);
+ if (isMatch(pkg, pr.isDirectBootAware(), flags)) {
+ res[num++] = generateProviderInfo(pkg, pr, flags, applicationInfo, userId);
+ }
+ }
+ info.providers = ArrayUtils.trimToSize(res, num);
+ }
+ }
+ if ((flags & PackageManager.GET_INSTRUMENTATION) != 0) {
+ final int size = pkg.getInstrumentations().size();
+ if (size > 0) {
+ info.instrumentation = new InstrumentationInfo[size];
+ for (int i = 0; i < size; i++) {
+ info.instrumentation[i] = generateInstrumentationInfo(
+ pkg.getInstrumentations().get(i), pkg, flags, userId);
+ }
+ }
+ }
+
+ return info;
+ }
+
+ private static void updateApplicationInfo(ApplicationInfo ai, long flags) {
+ if ((flags & PackageManager.GET_META_DATA) == 0) {
+ ai.metaData = null;
+ }
+ if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) == 0) {
+ ai.sharedLibraryFiles = null;
+ ai.sharedLibraryInfos = null;
+ }
+
+ // CompatibilityMode is global state.
+ if (!ParsingPackageUtils.sCompatibilityModeEnabled) {
+ ai.disableCompatibilityMode();
+ }
+
+ if (ai.category == ApplicationInfo.CATEGORY_UNDEFINED) {
+ ai.category = FallbackCategoryProvider.getFallbackCategory(ai.packageName);
+ }
+ ai.seInfoUser = COMPLETE_STR;
+ }
+
+ @Nullable
+ private static ApplicationInfo generateApplicationInfo(@NonNull AndroidPackage pkg,
+ @PackageManager.ApplicationInfoFlagsBits long flags, @UserIdInt int userId) {
+
+ // Make shallow copy so we can store the metadata/libraries safely
+ ApplicationInfo info = ((AndroidPackageHidden) pkg).toAppInfoWithoutState();
+
+ updateApplicationInfo(info, flags);
+
+ initForUser(info, pkg, userId);
+
+ info.primaryCpuAbi = AndroidPackageLegacyUtils.getRawPrimaryCpuAbi(pkg);
+ info.secondaryCpuAbi = AndroidPackageLegacyUtils.getRawSecondaryCpuAbi(pkg);
+
+ if ((flags & PackageManager.GET_META_DATA) != 0) {
+ info.metaData = pkg.getMetaData();
+ }
+ if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0) {
+ List<String> usesLibraryFiles = pkg.getUsesLibraries();
+
+ info.sharedLibraryFiles = usesLibraryFiles.isEmpty()
+ ? null : usesLibraryFiles.toArray(new String[0]);
+ }
+
+ return info;
+ }
+
+ @Nullable
+ private static ActivityInfo generateActivityInfo(ParsedActivity a,
+ @PackageManager.ComponentInfoFlagsBits long flags,
+ @NonNull ApplicationInfo applicationInfo) {
+ if (a == null) return null;
+
+ // Make shallow copies so we can store the metadata safely
+ ActivityInfo ai = new ActivityInfo();
+ ai.targetActivity = a.getTargetActivity();
+ ai.processName = a.getProcessName();
+ ai.exported = a.isExported();
+ ai.theme = a.getTheme();
+ ai.uiOptions = a.getUiOptions();
+ ai.parentActivityName = a.getParentActivityName();
+ ai.permission = a.getPermission();
+ ai.taskAffinity = a.getTaskAffinity();
+ ai.flags = a.getFlags();
+ ai.privateFlags = a.getPrivateFlags();
+ ai.launchMode = a.getLaunchMode();
+ ai.documentLaunchMode = a.getDocumentLaunchMode();
+ ai.maxRecents = a.getMaxRecents();
+ ai.configChanges = a.getConfigChanges();
+ ai.softInputMode = a.getSoftInputMode();
+ ai.persistableMode = a.getPersistableMode();
+ ai.lockTaskLaunchMode = a.getLockTaskLaunchMode();
+ ai.screenOrientation = a.getScreenOrientation();
+ ai.resizeMode = a.getResizeMode();
+ ai.setMaxAspectRatio(a.getMaxAspectRatio());
+ ai.setMinAspectRatio(a.getMinAspectRatio());
+ ai.supportsSizeChanges = a.isSupportsSizeChanges();
+ ai.requestedVrComponent = a.getRequestedVrComponent();
+ ai.rotationAnimation = a.getRotationAnimation();
+ ai.colorMode = a.getColorMode();
+ ai.windowLayout = a.getWindowLayout();
+ ai.attributionTags = a.getAttributionTags();
+ if ((flags & PackageManager.GET_META_DATA) != 0) {
+ var metaData = a.getMetaData();
+ // Backwards compatibility, coerce to null if empty
+ ai.metaData = metaData.isEmpty() ? null : metaData;
+ } else {
+ ai.metaData = null;
+ }
+ ai.applicationInfo = applicationInfo;
+ ai.requiredDisplayCategory = a.getRequiredDisplayCategory();
+ ai.setKnownActivityEmbeddingCerts(a.getKnownActivityEmbeddingCerts());
+ assignFieldsComponentInfoParsedMainComponent(ai, a);
+ return ai;
+ }
+
+ @Nullable
+ private static ServiceInfo generateServiceInfo(ParsedService s,
+ @PackageManager.ComponentInfoFlagsBits long flags,
+ @NonNull ApplicationInfo applicationInfo) {
+ if (s == null) return null;
+
+ // Make shallow copies so we can store the metadata safely
+ ServiceInfo si = new ServiceInfo();
+ si.exported = s.isExported();
+ si.flags = s.getFlags();
+ si.permission = s.getPermission();
+ si.processName = s.getProcessName();
+ si.mForegroundServiceType = s.getForegroundServiceType();
+ si.applicationInfo = applicationInfo;
+ if ((flags & PackageManager.GET_META_DATA) != 0) {
+ var metaData = s.getMetaData();
+ // Backwards compatibility, coerce to null if empty
+ si.metaData = metaData.isEmpty() ? null : metaData;
+ }
+ assignFieldsComponentInfoParsedMainComponent(si, s);
+ return si;
+ }
+
+ @Nullable
+ private static ProviderInfo generateProviderInfo(AndroidPackage pkg, ParsedProvider p,
+ @PackageManager.ComponentInfoFlagsBits long flags,
+ @NonNull ApplicationInfo applicationInfo, int userId) {
+ if (p == null) return null;
+
+ if (!pkg.getPackageName().equals(applicationInfo.packageName)) {
+ Slog.wtf(TAG, "AppInfo's package name is different. Expected=" + pkg.getPackageName()
+ + " actual=" + applicationInfo.packageName);
+ applicationInfo = generateApplicationInfo(pkg, flags, userId);
+ }
+
+ // Make shallow copies so we can store the metadata safely
+ ProviderInfo pi = new ProviderInfo();
+ pi.exported = p.isExported();
+ pi.flags = p.getFlags();
+ pi.processName = p.getProcessName();
+ pi.authority = p.getAuthority();
+ pi.isSyncable = p.isSyncable();
+ pi.readPermission = p.getReadPermission();
+ pi.writePermission = p.getWritePermission();
+ pi.grantUriPermissions = p.isGrantUriPermissions();
+ pi.forceUriPermissions = p.isForceUriPermissions();
+ pi.multiprocess = p.isMultiProcess();
+ pi.initOrder = p.getInitOrder();
+ pi.uriPermissionPatterns = p.getUriPermissionPatterns().toArray(new PatternMatcher[0]);
+ pi.pathPermissions = p.getPathPermissions().toArray(new PathPermission[0]);
+ if ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) == 0) {
+ pi.uriPermissionPatterns = null;
+ }
+ if ((flags & PackageManager.GET_META_DATA) != 0) {
+ var metaData = p.getMetaData();
+ // Backwards compatibility, coerce to null if empty
+ pi.metaData = metaData.isEmpty() ? null : metaData;
+ }
+ pi.applicationInfo = applicationInfo;
+ assignFieldsComponentInfoParsedMainComponent(pi, p);
+ return pi;
+ }
+
+ @Nullable
+ private static InstrumentationInfo generateInstrumentationInfo(ParsedInstrumentation i,
+ AndroidPackage pkg, @PackageManager.ComponentInfoFlagsBits long flags, int userId) {
+ if (i == null) return null;
+
+ InstrumentationInfo info = new InstrumentationInfo();
+ info.targetPackage = i.getTargetPackage();
+ info.targetProcesses = i.getTargetProcesses();
+ info.handleProfiling = i.isHandleProfiling();
+ info.functionalTest = i.isFunctionalTest();
+
+ info.sourceDir = pkg.getBaseApkPath();
+ info.publicSourceDir = pkg.getBaseApkPath();
+ info.splitNames = pkg.getSplitNames();
+ info.splitSourceDirs = pkg.getSplitCodePaths().length == 0 ? null : pkg.getSplitCodePaths();
+ info.splitPublicSourceDirs = pkg.getSplitCodePaths().length == 0
+ ? null : pkg.getSplitCodePaths();
+ info.splitDependencies = pkg.getSplitDependencies().size() == 0
+ ? null : pkg.getSplitDependencies();
+
+ initForUser(info, pkg, userId);
+
+ info.primaryCpuAbi = AndroidPackageLegacyUtils.getRawPrimaryCpuAbi(pkg);
+ info.secondaryCpuAbi = AndroidPackageLegacyUtils.getRawSecondaryCpuAbi(pkg);
+ info.nativeLibraryDir = pkg.getNativeLibraryDir();
+ info.secondaryNativeLibraryDir = pkg.getSecondaryNativeLibraryDir();
+
+ assignFieldsPackageItemInfoParsedComponent(info, i);
+
+ if ((flags & PackageManager.GET_META_DATA) == 0) {
+ info.metaData = null;
+ } else {
+ var metaData = i.getMetaData();
+ // Backwards compatibility, coerce to null if empty
+ info.metaData = metaData.isEmpty() ? null : metaData;
+ }
+
+ return info;
+ }
+
+ @Nullable
+ private static PermissionInfo generatePermissionInfo(ParsedPermission p,
+ @PackageManager.ComponentInfoFlagsBits long flags) {
+ // TODO(b/135203078): Remove null checks and make all usages @NonNull
+ if (p == null) return null;
+
+ PermissionInfo pi = new PermissionInfo(p.getBackgroundPermission());
+
+ assignFieldsPackageItemInfoParsedComponent(pi, p);
+
+ pi.group = p.getGroup();
+ pi.requestRes = p.getRequestRes();
+ pi.protectionLevel = p.getProtectionLevel();
+ pi.descriptionRes = p.getDescriptionRes();
+ pi.flags = p.getFlags();
+ pi.knownCerts = p.getKnownCerts();
+
+ if ((flags & PackageManager.GET_META_DATA) == 0) {
+ pi.metaData = null;
+ } else {
+ var metaData = p.getMetaData();
+ // Backwards compatibility, coerce to null if empty
+ pi.metaData = metaData.isEmpty() ? null : metaData;
+ }
+ return pi;
+ }
+
+ private static void assignFieldsComponentInfoParsedMainComponent(
+ @NonNull ComponentInfo info, @NonNull ParsedMainComponent component) {
+ assignFieldsPackageItemInfoParsedComponent(info, component);
+ info.descriptionRes = component.getDescriptionRes();
+ info.directBootAware = component.isDirectBootAware();
+ info.enabled = component.isEnabled();
+ info.splitName = component.getSplitName();
+ info.attributionTags = component.getAttributionTags();
+ info.nonLocalizedLabel = component.getNonLocalizedLabel();
+ info.icon = component.getIcon();
+ }
+
+ private static void assignFieldsPackageItemInfoParsedComponent(
+ @NonNull PackageItemInfo packageItemInfo, @NonNull ParsedComponent component) {
+ packageItemInfo.nonLocalizedLabel = ComponentParseUtils.getNonLocalizedLabel(component);
+ packageItemInfo.icon = ComponentParseUtils.getIcon(component);
+ packageItemInfo.banner = component.getBanner();
+ packageItemInfo.labelRes = component.getLabelRes();
+ packageItemInfo.logo = component.getLogo();
+ packageItemInfo.name = component.getName();
+ packageItemInfo.packageName = component.getPackageName();
+ }
+
+ private static void initForUser(ApplicationInfo output, AndroidPackage input,
+ @UserIdInt int userId) {
+ PackageImpl pkg = ((PackageImpl) input);
+ String packageName = input.getPackageName();
+ output.uid = UserHandle.getUid(userId, UserHandle.getAppId(input.getUid()));
+
+ // For performance reasons, all these paths are built as strings
+ final String credentialDir = pkg.getBaseAppDataCredentialProtectedDirForSystemUser();
+ final String deviceDir = pkg.getBaseAppDataDeviceProtectedDirForSystemUser();
+ if (credentialDir != null && deviceDir != null) {
+ if (userId == UserHandle.USER_SYSTEM) {
+ output.credentialProtectedDataDir = credentialDir + packageName;
+ output.deviceProtectedDataDir = deviceDir + packageName;
+ } else {
+ // Convert /data/user/0/ -> /data/user/1/com.example.app
+ String userIdString = String.valueOf(userId);
+ int credentialLength = credentialDir.length();
+ output.credentialProtectedDataDir = new StringBuilder(credentialDir)
+ .replace(credentialLength - 2, credentialLength - 1, userIdString)
+ .append(packageName)
+ .toString();
+ int deviceLength = deviceDir.length();
+ output.deviceProtectedDataDir = new StringBuilder(deviceDir)
+ .replace(deviceLength - 2, deviceLength - 1, userIdString)
+ .append(packageName)
+ .toString();
+ }
+ }
+
+ if (input.isDefaultToDeviceProtectedStorage()
+ && PackageManager.APPLY_DEFAULT_TO_DEVICE_PROTECTED_STORAGE) {
+ output.dataDir = output.deviceProtectedDataDir;
+ } else {
+ output.dataDir = output.credentialProtectedDataDir;
+ }
+ }
+
+ // This duplicates the ApplicationInfo variant because it uses field assignment and the classes
+ // don't inherit from each other, unfortunately. Consolidating logic would introduce overhead.
+ private static void initForUser(InstrumentationInfo output, AndroidPackage input,
+ @UserIdInt int userId) {
+ PackageImpl pkg = ((PackageImpl) input);
+ String packageName = input.getPackageName();
+
+ // For performance reasons, all these paths are built as strings
+ final String credentialDir = pkg.getBaseAppDataCredentialProtectedDirForSystemUser();
+ final String deviceDir = pkg.getBaseAppDataDeviceProtectedDirForSystemUser();
+ if (credentialDir != null && deviceDir != null) {
+ if (userId == UserHandle.USER_SYSTEM) {
+ output.credentialProtectedDataDir = credentialDir + packageName;
+ output.deviceProtectedDataDir = deviceDir + packageName;
+ } else {
+ // Convert /data/user/0/ -> /data/user/1/com.example.app
+ String userIdString = String.valueOf(userId);
+ int credentialLength = credentialDir.length();
+ output.credentialProtectedDataDir = new StringBuilder(credentialDir)
+ .replace(credentialLength - 2, credentialLength - 1, userIdString)
+ .append(packageName)
+ .toString();
+ int deviceLength = deviceDir.length();
+ output.deviceProtectedDataDir = new StringBuilder(deviceDir)
+ .replace(deviceLength - 2, deviceLength - 1, userIdString)
+ .append(packageName)
+ .toString();
+ }
+ }
+
+ if (input.isDefaultToDeviceProtectedStorage()
+ && PackageManager.APPLY_DEFAULT_TO_DEVICE_PROTECTED_STORAGE) {
+ output.dataDir = output.deviceProtectedDataDir;
+ } else {
+ output.dataDir = output.credentialProtectedDataDir;
+ }
+ }
+
+ /**
+ * Test if the given component is considered system, enabled and a match for the given
+ * flags.
+ *
+ * <p>
+ * Expects at least one of {@link PackageManager#MATCH_DIRECT_BOOT_AWARE} and {@link
+ * PackageManager#MATCH_DIRECT_BOOT_UNAWARE} are specified in {@code flags}.
+ * </p>
+ */
+ private static boolean isMatch(AndroidPackage pkg,
+ boolean isComponentDirectBootAware, long flags) {
+ final boolean isSystem = ((AndroidPackageHidden) pkg).isSystem();
+ if ((flags & PackageManager.MATCH_SYSTEM_ONLY) != 0) {
+ if (!isSystem) {
+ return reportIfDebug(false, flags);
+ }
+ }
+
+ final boolean matchesUnaware = ((flags & PackageManager.MATCH_DIRECT_BOOT_UNAWARE) != 0)
+ && !isComponentDirectBootAware;
+ final boolean matchesAware = ((flags & PackageManager.MATCH_DIRECT_BOOT_AWARE) != 0)
+ && isComponentDirectBootAware;
+ return reportIfDebug(matchesUnaware || matchesAware, flags);
+ }
+
+ private static boolean reportIfDebug(boolean result, long flags) {
+ if (DEBUG && !result) {
+ Slog.i(TAG, "No match!; flags: "
+ + DebugUtils.flagsToString(PackageManager.class, "MATCH_", flags) + " "
+ + Debug.getCaller());
+ }
+ return result;
+ }
+}
diff --git a/core/java/com/android/internal/pm/parsing/PackageParser2.java b/core/java/com/android/internal/pm/parsing/PackageParser2.java
index e413293..2c54672 100644
--- a/core/java/com/android/internal/pm/parsing/PackageParser2.java
+++ b/core/java/com/android/internal/pm/parsing/PackageParser2.java
@@ -20,6 +20,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityThread;
+import android.app.Application;
import android.content.pm.ApplicationInfo;
import android.content.pm.parsing.PackageLite;
import android.content.pm.parsing.result.ParseInput;
@@ -40,6 +41,7 @@
import com.android.internal.util.ArrayUtils;
import java.io.File;
+import java.util.ArrayList;
import java.util.List;
/**
@@ -78,10 +80,19 @@
displayMetrics.setToDefaults();
}
- PermissionManager permissionManager = ActivityThread.currentApplication()
- .getSystemService(PermissionManager.class);
- List<PermissionManager.SplitPermissionInfo> splitPermissions = permissionManager
- .getSplitPermissions();
+ List<PermissionManager.SplitPermissionInfo> splitPermissions = null;
+
+ final Application application = ActivityThread.currentApplication();
+ if (application != null) {
+ final PermissionManager permissionManager =
+ application.getSystemService(PermissionManager.class);
+ if (permissionManager != null) {
+ splitPermissions = permissionManager.getSplitPermissions();
+ }
+ }
+ if (splitPermissions == null) {
+ splitPermissions = new ArrayList<>();
+ }
mCacher = cacher;
diff --git a/core/tests/coretests/src/android/app/servertransaction/ClientTransactionListenerControllerTest.java b/core/tests/coretests/src/android/app/servertransaction/ClientTransactionListenerControllerTest.java
index 930b1a4..95d5049 100644
--- a/core/tests/coretests/src/android/app/servertransaction/ClientTransactionListenerControllerTest.java
+++ b/core/tests/coretests/src/android/app/servertransaction/ClientTransactionListenerControllerTest.java
@@ -65,7 +65,7 @@
mHandler = getInstrumentation().getContext().getMainThreadHandler();
mController = spy(ClientTransactionListenerController.createInstanceForTesting(
mDisplayManager));
- doReturn(true).when(mController).isSyncWindowConfigUpdateFlagEnabled();
+ doReturn(true).when(mController).isBundleClientTransactionFlagEnabled();
}
@Test
diff --git a/core/tests/coretests/src/android/window/flags/WindowFlagsTest.java b/core/tests/coretests/src/android/window/flags/WindowFlagsTest.java
index a5bbeb5..9292f66 100644
--- a/core/tests/coretests/src/android/window/flags/WindowFlagsTest.java
+++ b/core/tests/coretests/src/android/window/flags/WindowFlagsTest.java
@@ -16,7 +16,6 @@
package android.window.flags;
-import static com.android.window.flags.Flags.syncWindowConfigUpdateFlag;
import static com.android.window.flags.Flags.taskFragmentSystemOrganizerFlag;
import android.platform.test.annotations.Presubmit;
@@ -39,12 +38,6 @@
public class WindowFlagsTest {
@Test
- public void testSyncWindowConfigUpdateFlag() {
- // No crash when accessing the flag.
- syncWindowConfigUpdateFlag();
- }
-
- @Test
public void testTaskFragmentSystemOrganizerFlag() {
// No crash when accessing the flag.
taskFragmentSystemOrganizerFlag();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java
index 662a5c4..a76bd26 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java
@@ -95,7 +95,6 @@
private int mMinimumFlyoutWidthLargeScreen;
private PointF mRestingStackPosition;
- private int[] mPaddings = new int[4];
private boolean mShowingInBubbleBar;
private final Point mBubbleBarPosition = new Point();
@@ -344,46 +343,44 @@
final int pointerTotalHeight = getPointerSize();
final int expandedViewLargeScreenInsetFurthestEdge =
getExpandedViewLargeScreenInsetFurthestEdge(isOverflow);
+ int[] paddings = new int[4];
if (mDeviceConfig.isLargeScreen()) {
// Note:
// If we're in portrait OR if we're a small tablet, then the two insets values will
// be equal. If we're landscape and a large tablet, the two values will be different.
// [left, top, right, bottom]
- mPaddings[0] = onLeft
+ paddings[0] = onLeft
? mExpandedViewLargeScreenInsetClosestEdge - pointerTotalHeight
: expandedViewLargeScreenInsetFurthestEdge;
- mPaddings[1] = 0;
- mPaddings[2] = onLeft
+ paddings[1] = 0;
+ paddings[2] = onLeft
? expandedViewLargeScreenInsetFurthestEdge
: mExpandedViewLargeScreenInsetClosestEdge - pointerTotalHeight;
// Overflow doesn't show manage button / get padding from it so add padding here
- mPaddings[3] = isOverflow ? mExpandedViewPadding : 0;
- return mPaddings;
+ paddings[3] = isOverflow ? mExpandedViewPadding : 0;
+ return paddings;
} else {
int leftPadding = mInsets.left + mExpandedViewPadding;
int rightPadding = mInsets.right + mExpandedViewPadding;
- final float expandedViewWidth = isOverflow
- ? mOverflowWidth
- : mExpandedViewLargeScreenWidth;
if (showBubblesVertically()) {
if (!onLeft) {
rightPadding += mBubbleSize - pointerTotalHeight;
leftPadding += isOverflow
- ? (mPositionRect.width() - rightPadding - expandedViewWidth)
+ ? (mPositionRect.width() - rightPadding - mOverflowWidth)
: 0;
} else {
leftPadding += mBubbleSize - pointerTotalHeight;
rightPadding += isOverflow
- ? (mPositionRect.width() - leftPadding - expandedViewWidth)
+ ? (mPositionRect.width() - leftPadding - mOverflowWidth)
: 0;
}
}
// [left, top, right, bottom]
- mPaddings[0] = leftPadding;
- mPaddings[1] = showBubblesVertically() ? 0 : mPointerMargin;
- mPaddings[2] = rightPadding;
- mPaddings[3] = 0;
- return mPaddings;
+ paddings[0] = leftPadding;
+ paddings[1] = showBubblesVertically() ? 0 : mPointerMargin;
+ paddings[2] = rightPadding;
+ paddings[3] = 0;
+ return paddings;
}
}
@@ -395,7 +392,7 @@
}
/** Gets the y position of the expanded view if it was top-aligned. */
- public float getExpandedViewYTopAligned() {
+ public int getExpandedViewYTopAligned() {
final int top = getAvailableRect().top;
if (showBubblesVertically()) {
return top - mPointerWidth + mExpandedViewPadding;
@@ -413,7 +410,7 @@
return getExpandedViewHeightForLargeScreen();
}
// Subtract top insets because availableRect.height would account for that
- int expandedContainerY = (int) getExpandedViewYTopAligned() - getInsets().top;
+ int expandedContainerY = getExpandedViewYTopAligned() - getInsets().top;
int paddingTop = showBubblesVertically()
? 0
: mPointerHeight;
@@ -474,11 +471,11 @@
public float getExpandedViewY(BubbleViewProvider bubble, float bubblePosition) {
boolean isOverflow = bubble == null || BubbleOverflow.KEY.equals(bubble.getKey());
float expandedViewHeight = getExpandedViewHeight(bubble);
- float topAlignment = getExpandedViewYTopAligned();
+ int topAlignment = getExpandedViewYTopAligned();
int manageButtonHeight =
isOverflow ? mExpandedViewPadding : mManageButtonHeightIncludingMargins;
- // On largescreen portrait bubbles are bottom aligned.
+ // On large screen portrait bubbles are bottom aligned.
if (areBubblesBottomAligned() && expandedViewHeight == MAX_HEIGHT) {
return mPositionRect.bottom - manageButtonHeight
- getExpandedViewHeightForLargeScreen() - mPointerWidth;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/ExpandedAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/ExpandedAnimationController.java
index 02af2d0..7798aa7 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/ExpandedAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/ExpandedAnimationController.java
@@ -420,7 +420,7 @@
bubbleView.setTranslationY(y);
}
- final float expandedY = mPositioner.getExpandedViewYTopAligned();
+ final int expandedY = mPositioner.getExpandedViewYTopAligned();
final boolean draggedOutEnough =
y > expandedY + mBubbleSizePx || y < expandedY - mBubbleSizePx;
if (draggedOutEnough != mBubbleDraggedOutEnough) {
diff --git a/media/TEST_MAPPING b/media/TEST_MAPPING
index f8176a1..8f5f1f6 100644
--- a/media/TEST_MAPPING
+++ b/media/TEST_MAPPING
@@ -50,7 +50,7 @@
]
}
],
- "presubmit": [
+ "postsubmit": [
{
"file_patterns": [
"[^/]*(LoudnessCodec)[^/]*\\.java"
diff --git a/packages/CredentialManager/res/drawable/autofill_light_selectable_item_background.xml b/packages/CredentialManager/res/drawable/autofill_light_selectable_item_background.xml
new file mode 100644
index 0000000..9d16f32d
--- /dev/null
+++ b/packages/CredentialManager/res/drawable/autofill_light_selectable_item_background.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ ~ Copyright (C) 2023 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<!-- Copied from //frameworks/base/core/res/res/drawable/item_background_material.xml -->
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+ android:color="@color/autofill_light_colorControlHighlight">
+ <item android:id="@android:id/mask">
+ <color android:color="@android:color/white"/>
+ </item>
+</ripple>
\ No newline at end of file
diff --git a/packages/CredentialManager/res/drawable/fill_dialog_dynamic_list_item_one.xml b/packages/CredentialManager/res/drawable/fill_dialog_dynamic_list_item_one.xml
new file mode 100644
index 0000000..2f0c83b
--- /dev/null
+++ b/packages/CredentialManager/res/drawable/fill_dialog_dynamic_list_item_one.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2023 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools" tools:ignore="NewApi"
+ android:color="@android:color/transparent">
+ <item
+ android:bottom="1dp"
+ android:shape="rectangle"
+ android:top="1dp">
+ <shape>
+ <corners android:radius="28dp" />
+ <solid android:color="@android:color/system_surface_container_high_light" />
+ </shape>
+ </item>
+</ripple>
\ No newline at end of file
diff --git a/packages/CredentialManager/res/drawable/fill_dialog_dynamic_list_item_one_dark.xml b/packages/CredentialManager/res/drawable/fill_dialog_dynamic_list_item_one_dark.xml
new file mode 100644
index 0000000..39f49ca
--- /dev/null
+++ b/packages/CredentialManager/res/drawable/fill_dialog_dynamic_list_item_one_dark.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2023 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools" tools:ignore="NewApi"
+ android:color="@android:color/transparent">
+ <item
+ android:bottom="1dp"
+ android:shape="rectangle"
+ android:top="1dp">
+ <shape>
+ <corners android:radius="28dp" />
+ <solid android:color="@android:color/system_surface_container_high_dark" />
+ </shape>
+ </item>
+</ripple>
\ No newline at end of file
diff --git a/packages/CredentialManager/res/layout/autofill_dataset_left_with_item_tag_hint.xml b/packages/CredentialManager/res/layout/autofill_dataset_left_with_item_tag_hint.xml
new file mode 100644
index 0000000..e4e9f7a
--- /dev/null
+++ b/packages/CredentialManager/res/layout/autofill_dataset_left_with_item_tag_hint.xml
@@ -0,0 +1,37 @@
+<!--
+ ~ Copyright (C) 2023 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@android:id/content"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ style="@style/autofill.Dataset">
+ <ImageView
+ android:id="@android:id/icon1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerVertical="true"
+ android:layout_alignParentStart="true"
+ android:background="@null"/>
+ <TextView
+ android:id="@android:id/text1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentTop="true"
+ android:layout_toEndOf="@android:id/icon1"
+ style="@style/autofill.TextAppearance"/>
+
+</RelativeLayout>
diff --git a/packages/CredentialManager/res/values/colors.xml b/packages/CredentialManager/res/values/colors.xml
new file mode 100644
index 0000000..63b9f24
--- /dev/null
+++ b/packages/CredentialManager/res/values/colors.xml
@@ -0,0 +1,38 @@
+<!--
+ ~ Copyright (C) 2023 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<!-- Color palette -->
+<resources>
+ <color name="autofill_light_colorPrimary">@color/primary_material_light</color>
+ <color name="autofill_light_colorAccent">@color/accent_material_light</color>
+ <color name="autofill_light_colorControlHighlight">@color/ripple_material_light</color>
+ <color name="autofill_light_colorButtonNormal">@color/button_material_light</color>
+
+ <!-- Text colors -->
+ <color name="autofill_light_textColorPrimary">@color/abc_primary_text_material_light</color>
+ <color name="autofill_light_textColorSecondary">@color/abc_secondary_text_material_light</color>
+ <color name="autofill_light_textColorHint">@color/abc_hint_foreground_material_light</color>
+ <color name="autofill_light_textColorHintInverse">@color/abc_hint_foreground_material_dark
+ </color>
+ <color name="autofill_light_textColorHighlight">@color/highlighted_text_material_light</color>
+ <color name="autofill_light_textColorLink">@color/autofill_light_colorAccent</color>
+
+ <!-- These colors are used for Remote Views. -->
+ <color name="background_dark_mode">#0E0C0B</color>
+ <color name="background">#F1F3F4</color>
+ <color name="text_primary_dark_mode">#DFDEDB</color>
+ <color name="text_primary">#202124</color>
+</resources>
\ No newline at end of file
diff --git a/packages/CredentialManager/res/values/dimens.xml b/packages/CredentialManager/res/values/dimens.xml
new file mode 100644
index 0000000..67003a3
--- /dev/null
+++ b/packages/CredentialManager/res/values/dimens.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ ~ Copyright (C) 2023 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources>
+ <dimen name="autofill_view_padding">16dp</dimen>
+ <dimen name="autofill_icon_size">16dp</dimen>
+</resources>
\ No newline at end of file
diff --git a/packages/CredentialManager/res/values/styles.xml b/packages/CredentialManager/res/values/styles.xml
new file mode 100644
index 0000000..4a5761a
--- /dev/null
+++ b/packages/CredentialManager/res/values/styles.xml
@@ -0,0 +1,38 @@
+<!--
+ ~ Copyright (C) 2023 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources>
+ <style name="autofill.TextAppearance.Small" parent="@style/autofill.TextAppearance">
+ <item name="android:textSize">12sp</item>
+ </style>
+
+
+ <style name="autofill.Dataset" parent="">
+ <item name="android:background">@drawable/autofill_light_selectable_item_background</item>
+ </style>
+
+ <style name="autofill.TextAppearance" parent="">
+ <item name="android:textColor">@color/autofill_light_textColorPrimary</item>
+ <item name="android:textColorHint">@color/autofill_light_textColorHint</item>
+ <item name="android:textColorHighlight">@color/autofill_light_textColorHighlight</item>
+ <item name="android:textColorLink">@color/autofill_light_textColorLink</item>
+ <item name="android:textSize">14sp</item>
+ </style>
+
+ <style name="autofill.TextAppearance.Primary">
+ <item name="android:textColor">@color/autofill_light_textColorPrimary</item>
+ </style>
+</resources>
\ No newline at end of file
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/autofill/CredentialAutofillService.kt b/packages/CredentialManager/src/com/android/credentialmanager/autofill/CredentialAutofillService.kt
index 20d2f09..0ff1c7f 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/autofill/CredentialAutofillService.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/autofill/CredentialAutofillService.kt
@@ -16,6 +16,7 @@
package com.android.credentialmanager.autofill
+import android.R
import android.app.assist.AssistStructure
import android.content.Context
import android.credentials.CredentialManager
@@ -41,18 +42,19 @@
import android.service.credentials.CredentialProviderService
import android.util.Log
import android.view.autofill.AutofillId
-import org.json.JSONException
import android.widget.inline.InlinePresentationSpec
import androidx.autofill.inline.v1.InlineSuggestionUi
import androidx.credentials.provider.CustomCredentialEntry
import androidx.credentials.provider.PasswordCredentialEntry
import androidx.credentials.provider.PublicKeyCredentialEntry
import com.android.credentialmanager.GetFlowUtils
-import com.android.credentialmanager.model.get.CredentialEntryInfo
+import com.android.credentialmanager.common.ui.RemoteViewsFactory
import com.android.credentialmanager.getflow.ProviderDisplayInfo
-import com.android.credentialmanager.model.get.ProviderInfo
import com.android.credentialmanager.getflow.toProviderDisplayInfo
import com.android.credentialmanager.ktx.credentialEntry
+import com.android.credentialmanager.model.get.CredentialEntryInfo
+import com.android.credentialmanager.model.get.ProviderInfo
+import org.json.JSONException
import org.json.JSONObject
import java.util.concurrent.Executors
@@ -127,9 +129,11 @@
is PasswordCredentialEntry -> {
entryIconMap[entry.key + entry.subkey] = credentialEntry.icon
}
+
is PublicKeyCredentialEntry -> {
entryIconMap[entry.key + entry.subkey] = credentialEntry.icon
}
+
is CustomCredentialEntry -> {
entryIconMap[entry.key + entry.subkey] = credentialEntry.icon
}
@@ -172,11 +176,11 @@
}
private fun processProvidersForAutofillId(
- filLRequest: FillRequest,
- autofillId: AutofillId,
- providerList: List<ProviderInfo>,
- entryIconMap: Map<String, Icon>,
- fillResponseBuilder: FillResponse.Builder
+ filLRequest: FillRequest,
+ autofillId: AutofillId,
+ providerList: List<ProviderInfo>,
+ entryIconMap: Map<String, Icon>,
+ fillResponseBuilder: FillResponse.Builder
): Boolean {
if (providerList.isEmpty()) {
return false
@@ -197,7 +201,7 @@
var i = 0
var datasetAdded = false
- providerDisplayInfo.sortedUserNameToCredentialEntryList.forEach usernameLoop@ {
+ providerDisplayInfo.sortedUserNameToCredentialEntryList.forEach usernameLoop@{
val primaryEntry = it.sortedCredentialEntryList.first()
val pendingIntent = primaryEntry.pendingIntent
val fillInIntent = primaryEntry.fillInIntent
@@ -206,37 +210,48 @@
Log.e(TAG, "PendingIntent was missing from the entry.")
return@usernameLoop
}
- if (inlinePresentationSpecs == null || i >= maxItemCount) {
+ if (inlinePresentationSpecs == null) {
+ Log.i(TAG, "Inline presentation spec is null, " +
+ "building dropdown presentation only")
+ }
+ if (i >= maxItemCount) {
Log.e(TAG, "Skipping because reached the max item count.")
return@usernameLoop
}
- // Create inline presentation
- val spec: InlinePresentationSpec
- if (i < inlinePresentationSpecsCount) {
- spec = inlinePresentationSpecs[i]
- } else {
- spec = inlinePresentationSpecs[inlinePresentationSpecsCount - 1]
- }
- val sliceBuilder = InlineSuggestionUi
- .newContentBuilder(pendingIntent)
- .setTitle(primaryEntry.userName)
- val icon: Icon
- if (primaryEntry.icon == null) {
+ val icon: Icon = if (primaryEntry.icon == null) {
// The empty entry icon has non-null icon reference but null drawable reference.
// If the drawable reference is null, then use the default icon.
- icon = getDefaultIcon()
+ getDefaultIcon()
} else {
- icon = entryIconMap[primaryEntry.entryKey + primaryEntry.entrySubkey]
+ entryIconMap[primaryEntry.entryKey + primaryEntry.entrySubkey]
?: getDefaultIcon()
}
- sliceBuilder.setStartIcon(icon)
- val inlinePresentation = InlinePresentation(
- sliceBuilder.build().slice, spec, /* pinned= */ false)
+ // Create inline presentation
+ var inlinePresentation: InlinePresentation? = null;
+ if (inlinePresentationSpecs != null) {
+ val spec: InlinePresentationSpec
+ if (i < inlinePresentationSpecsCount) {
+ spec = inlinePresentationSpecs[i]
+ } else {
+ spec = inlinePresentationSpecs[inlinePresentationSpecsCount - 1]
+ }
+ val sliceBuilder = InlineSuggestionUi
+ .newContentBuilder(pendingIntent)
+ .setTitle(primaryEntry.userName)
+ sliceBuilder.setStartIcon(icon)
+ inlinePresentation = InlinePresentation(
+ sliceBuilder.build().slice, spec, /* pinned= */ false)
+ }
+ val dropdownPresentation = RemoteViewsFactory.createDropdownPresentation(
+ this, icon, primaryEntry)
i++
val dataSetBuilder = Dataset.Builder()
val presentationBuilder = Presentations.Builder()
- .setInlinePresentation(inlinePresentation)
+ .setMenuPresentation(dropdownPresentation)
+ if (inlinePresentation != null) {
+ presentationBuilder.setInlinePresentation(inlinePresentation)
+ }
fillResponseBuilder.addDataset(
dataSetBuilder
@@ -305,7 +320,7 @@
): MutableMap<AutofillId, MutableList<CredentialEntryInfo>> {
val autofillIdToCredentialEntries:
MutableMap<AutofillId, MutableList<CredentialEntryInfo>> = mutableMapOf()
- credentialEntryList.forEach entryLoop@ { credentialEntry ->
+ credentialEntryList.forEach entryLoop@{ credentialEntry ->
val autofillId: AutofillId? = credentialEntry
.fillInIntent
?.getParcelableExtra(
@@ -323,8 +338,8 @@
}
private fun copyProviderInfo(
- providerInfo: ProviderInfo,
- credentialList: List<CredentialEntryInfo>
+ providerInfo: ProviderInfo,
+ credentialList: List<CredentialEntryInfo>
): ProviderInfo {
return ProviderInfo(
providerInfo.id,
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/RemoteViewsFactory.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/RemoteViewsFactory.kt
new file mode 100644
index 0000000..4dc7f00
--- /dev/null
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/RemoteViewsFactory.kt
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.credentialmanager.common.ui
+
+import android.content.Context
+import android.content.res.Configuration
+import android.widget.RemoteViews
+import androidx.core.content.ContextCompat
+import com.android.credentialmanager.model.get.CredentialEntryInfo
+import android.graphics.drawable.Icon
+
+class RemoteViewsFactory {
+
+ companion object {
+ private const val setAdjustViewBoundsMethodName = "setAdjustViewBounds"
+ private const val setMaxHeightMethodName = "setMaxHeight"
+ private const val setBackgroundResourceMethodName = "setBackgroundResource"
+
+ fun createDropdownPresentation(
+ context: Context,
+ icon: Icon,
+ credentialEntryInfo: CredentialEntryInfo
+ ): RemoteViews {
+ val padding = context.resources.getDimensionPixelSize(com.android
+ .credentialmanager.R.dimen.autofill_view_padding)
+ var layoutId: Int = com.android.credentialmanager.R.layout
+ .autofill_dataset_left_with_item_tag_hint
+ val remoteViews = RemoteViews(context.packageName, layoutId)
+ setRemoteViewsPaddings(remoteViews, padding)
+ val textColorPrimary = getTextColorPrimary(isDarkMode(context), context);
+ remoteViews.setTextColor(android.R.id.text1, textColorPrimary);
+ remoteViews.setTextViewText(android.R.id.text1, credentialEntryInfo.userName)
+
+ remoteViews.setImageViewIcon(android.R.id.icon1, icon);
+ remoteViews.setBoolean(
+ android.R.id.icon1, setAdjustViewBoundsMethodName, true);
+ remoteViews.setInt(
+ android.R.id.icon1,
+ setMaxHeightMethodName,
+ context.resources.getDimensionPixelSize(
+ com.android.credentialmanager.R.dimen.autofill_icon_size));
+ val drawableId = if (isDarkMode(context))
+ com.android.credentialmanager.R.drawable.fill_dialog_dynamic_list_item_one_dark
+ else com.android.credentialmanager.R.drawable.fill_dialog_dynamic_list_item_one
+ remoteViews.setInt(
+ android.R.id.content, setBackgroundResourceMethodName, drawableId);
+ return remoteViews
+ }
+
+ private fun setRemoteViewsPaddings(
+ remoteViews: RemoteViews,
+ padding: Int) {
+ val halfPadding = padding / 2
+ remoteViews.setViewPadding(
+ android.R.id.text1,
+ halfPadding,
+ halfPadding,
+ halfPadding,
+ halfPadding)
+ }
+
+ private fun isDarkMode(context: Context): Boolean {
+ val currentNightMode = context.resources.configuration.uiMode and
+ Configuration.UI_MODE_NIGHT_MASK
+ return currentNightMode == Configuration.UI_MODE_NIGHT_YES
+ }
+
+ private fun getTextColorPrimary(darkMode: Boolean, context: Context): Int {
+ return if (darkMode) ContextCompat.getColor(
+ context, com.android.credentialmanager.R.color.text_primary_dark_mode)
+ else ContextCompat.getColor(context, com.android.credentialmanager.R.color.text_primary)
+ }
+ }
+}
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml
index 557fbf2..e6122a0 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml
@@ -43,7 +43,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<FrameLayout
- android:id="@+id/status_view_media_container"
+ android:id="@id/status_view_media_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="@dimen/qs_media_padding"
diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml
index d511cab..80725c2 100644
--- a/packages/SystemUI/res/values/ids.xml
+++ b/packages/SystemUI/res/values/ids.xml
@@ -225,6 +225,8 @@
<item type="id" name="communal_tutorial_indicator" />
<item type="id" name="nssl_placeholder_barrier_bottom" />
<item type="id" name="ambient_indication_container" />
+ <item type="id" name="status_view_media_container" />
+ <item type="id" name="smart_space_barrier_bottom" />
<!-- Privacy dialog -->
<item type="id" name="privacy_dialog_close_app_button" />
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
index 83d415f..ab23564 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
@@ -403,13 +403,6 @@
final BiometricPromptLayout view = (BiometricPromptLayout) layoutInflater.inflate(
R.layout.biometric_prompt_layout, null, false);
- /**
- * View is only set visible in BiometricViewSizeBinder once PromptSize is determined
- * that accounts for iconView size, to prevent prompt resizing being visible to the
- * user.
- * TODO(b/288175072): May be able to remove this once constraint layout is implemented
- */
- view.setVisibility(View.INVISIBLE);
mBiometricView = BiometricViewBinder.bind(view, viewModel, mPanelController,
// TODO(b/201510778): This uses the wrong timeout in some cases
getJankListener(view, TRANSIT,
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt
index a7fb6f7..90e4a38 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt
@@ -97,13 +97,7 @@
val iconOverlayView = view.requireViewById<LottieAnimationView>(R.id.biometric_icon_overlay)
val iconView = view.requireViewById<LottieAnimationView>(R.id.biometric_icon)
- /**
- * View is only set visible in BiometricViewSizeBinder once PromptSize is determined that
- * accounts for iconView size, to prevent prompt resizing being visible to the user.
- *
- * TODO(b/288175072): May be able to remove this once constraint layout is implemented
- */
- iconView.addLottieOnCompositionLoadedListener { viewModel.setIsIconViewLoaded(true) }
+
PromptIconViewBinder.bind(
iconView,
iconOverlayView,
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewSizeBinder.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewSizeBinder.kt
index f340bd8..7e16d1e 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewSizeBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewSizeBinder.kt
@@ -30,6 +30,7 @@
import androidx.core.view.doOnLayout
import androidx.core.view.isGone
import androidx.lifecycle.lifecycleScope
+import com.android.systemui.res.R
import com.android.systemui.biometrics.AuthPanelController
import com.android.systemui.biometrics.Utils
import com.android.systemui.biometrics.ui.BiometricPromptLayout
@@ -40,8 +41,6 @@
import com.android.systemui.biometrics.ui.viewmodel.isNullOrNotSmall
import com.android.systemui.biometrics.ui.viewmodel.isSmall
import com.android.systemui.lifecycle.repeatWhenAttached
-import com.android.systemui.res.R
-import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.launch
/** Helper for [BiometricViewBinder] to handle resize transitions. */
@@ -93,22 +92,8 @@
// TODO(b/251476085): migrate the legacy panel controller and simplify this
view.repeatWhenAttached {
var currentSize: PromptSize? = null
-
lifecycleScope.launch {
- /**
- * View is only set visible in BiometricViewSizeBinder once PromptSize is
- * determined that accounts for iconView size, to prevent prompt resizing being
- * visible to the user.
- *
- * TODO(b/288175072): May be able to remove isIconViewLoaded once constraint
- * layout is implemented
- */
- combine(viewModel.isIconViewLoaded, viewModel.size, ::Pair).collect {
- (isIconViewLoaded, size) ->
- if (!isIconViewLoaded) {
- return@collect
- }
-
+ viewModel.size.collect { size ->
// prepare for animated size transitions
for (v in viewsToHideWhenSmall) {
v.showTextOrHide(forceHide = size.isSmall)
@@ -211,9 +196,8 @@
}
}
}
+
currentSize = size
- view.visibility = View.VISIBLE
- viewModel.setIsIconViewLoaded(false)
notifyAccessibilityChanged()
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt
index d899827e..6d0a58e 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt
@@ -192,28 +192,6 @@
val iconViewModel: PromptIconViewModel =
PromptIconViewModel(this, displayStateInteractor, promptSelectorInteractor)
- private val _isIconViewLoaded = MutableStateFlow(false)
-
- /**
- * For prompts with an iconView, false until the prompt's iconView animation has been loaded in
- * the view, otherwise true by default. Used for BiometricViewSizeBinder to wait for the icon
- * asset to be loaded before determining the prompt size.
- */
- val isIconViewLoaded: Flow<Boolean> =
- combine(credentialKind, _isIconViewLoaded.asStateFlow()) { credentialKind, isIconViewLoaded
- ->
- if (credentialKind is PromptKind.Biometric) {
- isIconViewLoaded
- } else {
- true
- }
- }
-
- // Sets whether the prompt's iconView animation has been loaded in the view yet.
- fun setIsIconViewLoaded(iconViewLoaded: Boolean) {
- _isIconViewLoaded.value = iconViewLoaded
- }
-
/** Padding for prompt UI elements */
val promptPadding: Flow<Rect> =
combine(size, displayStateInteractor.currentRotation) { size, rotation ->
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
index 1f69cc0..0d40511 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
@@ -397,8 +397,10 @@
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_DATE_CHANGED);
filter.addAction(Intent.ACTION_LOCALE_CHANGED);
- getContext().registerReceiver(mIntentReceiver, filter, null /* permission*/,
- null /* scheduler */);
+ mBgHandler.post(() -> {
+ getContext().registerReceiver(mIntentReceiver, filter, null /* permission*/,
+ null /* scheduler */);
+ });
mKeyguardUpdateMonitor.registerCallback(mKeyguardUpdateMonitorCallback);
mRegistered = true;
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/SplitShadeKeyguardBlueprint.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/SplitShadeKeyguardBlueprint.kt
index 16539db..5344696b 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/SplitShadeKeyguardBlueprint.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/SplitShadeKeyguardBlueprint.kt
@@ -33,6 +33,7 @@
import com.android.systemui.keyguard.ui.view.layout.sections.SmartspaceSection
import com.android.systemui.keyguard.ui.view.layout.sections.SplitShadeClockSection
import com.android.systemui.keyguard.ui.view.layout.sections.SplitShadeGuidelines
+import com.android.systemui.keyguard.ui.view.layout.sections.SplitShadeMediaSection
import com.android.systemui.keyguard.ui.view.layout.sections.SplitShadeNotificationStackScrollLayoutSection
import com.android.systemui.util.kotlin.getOrNull
import java.util.Optional
@@ -63,6 +64,7 @@
communalTutorialIndicatorSection: CommunalTutorialIndicatorSection,
smartspaceSection: SmartspaceSection,
clockSection: SplitShadeClockSection,
+ mediaSection: SplitShadeMediaSection,
) : KeyguardBlueprint {
override val id: String = ID
@@ -81,6 +83,7 @@
aodBurnInSection,
communalTutorialIndicatorSection,
clockSection,
+ mediaSection,
defaultDeviceEntrySection, // Add LAST: Intentionally has z-order above other views.
)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SplitShadeMediaSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SplitShadeMediaSection.kt
new file mode 100644
index 0000000..5afdbaa
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SplitShadeMediaSection.kt
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyguard.ui.view.layout.sections
+
+import android.content.Context
+import android.view.View
+import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
+import android.widget.FrameLayout
+import androidx.constraintlayout.widget.Barrier
+import androidx.constraintlayout.widget.ConstraintLayout
+import androidx.constraintlayout.widget.ConstraintSet
+import androidx.constraintlayout.widget.ConstraintSet.BOTTOM
+import androidx.constraintlayout.widget.ConstraintSet.END
+import androidx.constraintlayout.widget.ConstraintSet.MATCH_CONSTRAINT
+import androidx.constraintlayout.widget.ConstraintSet.PARENT_ID
+import androidx.constraintlayout.widget.ConstraintSet.START
+import androidx.constraintlayout.widget.ConstraintSet.TOP
+import com.android.systemui.Flags.migrateClocksToBlueprint
+import com.android.systemui.keyguard.shared.model.KeyguardSection
+import com.android.systemui.keyguard.ui.viewmodel.KeyguardSmartspaceViewModel
+import com.android.systemui.media.controls.ui.KeyguardMediaController
+import com.android.systemui.res.R
+import com.android.systemui.shade.NotificationPanelView
+import javax.inject.Inject
+
+/** Aligns media on left side for split shade, below smartspace, date, and weather. */
+class SplitShadeMediaSection
+@Inject
+constructor(
+ private val context: Context,
+ private val notificationPanelView: NotificationPanelView,
+ private val keyguardSmartspaceViewModel: KeyguardSmartspaceViewModel,
+ private val keyguardMediaController: KeyguardMediaController
+) : KeyguardSection() {
+ private val mediaContainerId = R.id.status_view_media_container
+ private val smartSpaceBarrier = R.id.smart_space_barrier_bottom
+
+ override fun addViews(constraintLayout: ConstraintLayout) {
+ if (!migrateClocksToBlueprint()) {
+ return
+ }
+
+ notificationPanelView.findViewById<View>(mediaContainerId)?.let {
+ notificationPanelView.removeView(it)
+ }
+
+ val mediaFrame =
+ FrameLayout(context, null).apply {
+ id = mediaContainerId
+ val padding = context.resources.getDimensionPixelSize(R.dimen.qs_media_padding)
+ val horizontalPadding =
+ padding +
+ context.resources.getDimensionPixelSize(
+ R.dimen.status_view_margin_horizontal
+ )
+
+ setPaddingRelative(horizontalPadding, padding, horizontalPadding, padding)
+ }
+ constraintLayout.addView(mediaFrame)
+ keyguardMediaController.attachSplitShadeContainer(mediaFrame)
+ }
+
+ override fun bindData(constraintLayout: ConstraintLayout) {}
+
+ override fun applyConstraints(constraintSet: ConstraintSet) {
+ if (!migrateClocksToBlueprint()) {
+ return
+ }
+
+ constraintSet.apply {
+ constrainWidth(mediaContainerId, MATCH_CONSTRAINT)
+ constrainHeight(mediaContainerId, WRAP_CONTENT)
+
+ createBarrier(
+ smartSpaceBarrier,
+ Barrier.BOTTOM,
+ 0,
+ *intArrayOf(
+ keyguardSmartspaceViewModel.smartspaceViewId,
+ keyguardSmartspaceViewModel.dateId,
+ keyguardSmartspaceViewModel.weatherId,
+ )
+ )
+ connect(mediaContainerId, TOP, smartSpaceBarrier, BOTTOM)
+ connect(mediaContainerId, START, PARENT_ID, START)
+ connect(mediaContainerId, END, R.id.split_shade_guideline, END)
+ }
+ }
+
+ override fun removeViews(constraintLayout: ConstraintLayout) {
+ if (!migrateClocksToBlueprint()) {
+ return
+ }
+
+ constraintLayout.removeView(mediaContainerId)
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/KeyguardMediaController.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/KeyguardMediaController.kt
index 945bf9a..e15e038 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/KeyguardMediaController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/KeyguardMediaController.kt
@@ -27,6 +27,7 @@
import android.view.ViewGroup
import androidx.annotation.VisibleForTesting
import com.android.systemui.Dumpable
+import com.android.systemui.Flags.migrateClocksToBlueprint
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.dump.DumpManager
@@ -180,7 +181,11 @@
/** Called whenever the media hosts visibility changes */
private fun onMediaHostVisibilityChanged(visible: Boolean) {
refreshMediaPosition(reason = "onMediaHostVisibilityChanged")
+
if (visible) {
+ if (migrateClocksToBlueprint() && useSplitShade) {
+ return
+ }
mediaHost.hostView.layoutParams.apply {
height = ViewGroup.LayoutParams.WRAP_CONTENT
width = ViewGroup.LayoutParams.MATCH_PARENT
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
index 17eb3c8..286037e 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
@@ -1160,9 +1160,9 @@
// Occluded->Lockscreen
collectFlow(mView, mKeyguardTransitionInteractor.getOccludedToLockscreenTransition(),
mOccludedToLockscreenTransition, mMainDispatcher);
- if (!KeyguardShadeMigrationNssl.isEnabled()) {
- collectFlow(mView, mOccludedToLockscreenTransitionViewModel.getLockscreenAlpha(),
+ collectFlow(mView, mOccludedToLockscreenTransitionViewModel.getLockscreenAlpha(),
setTransitionAlpha(mNotificationStackScrollLayoutController), mMainDispatcher);
+ if (!KeyguardShadeMigrationNssl.isEnabled()) {
collectFlow(mView,
mOccludedToLockscreenTransitionViewModel.getLockscreenTranslationY(),
setTransitionY(mNotificationStackScrollLayoutController), mMainDispatcher);
@@ -1192,8 +1192,10 @@
mLockscreenToOccludedTransition, mMainDispatcher);
collectFlow(mView, mLockscreenToOccludedTransitionViewModel.getLockscreenAlpha(),
setTransitionAlpha(mNotificationStackScrollLayoutController), mMainDispatcher);
- collectFlow(mView, mLockscreenToOccludedTransitionViewModel.getLockscreenTranslationY(),
- setTransitionY(mNotificationStackScrollLayoutController), mMainDispatcher);
+ if (!KeyguardShadeMigrationNssl.isEnabled()) {
+ collectFlow(mView, mLockscreenToOccludedTransitionViewModel.getLockscreenTranslationY(),
+ setTransitionY(mNotificationStackScrollLayoutController), mMainDispatcher);
+ }
// Primary bouncer->Gone (ensures lockscreen content is not visible on successful auth)
collectFlow(mView, mPrimaryBouncerToGoneTransitionViewModel.getLockscreenAlpha(),
@@ -1463,6 +1465,9 @@
}
private void attachSplitShadeMediaPlayerContainer(FrameLayout container) {
+ if (migrateClocksToBlueprint()) {
+ return;
+ }
mKeyguardMediaController.attachSplitShadeContainer(container);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java
index 70ccc4f..80ef14b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java
@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.notification.collection.inflation;
+import static com.android.systemui.Flags.screenshareNotificationHiding;
import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_CONTRACTED;
import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_EXPANDED;
import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_PUBLIC;
@@ -243,7 +244,11 @@
params.setUseIncreasedCollapsedHeight(useIncreasedCollapsedHeight);
params.setUseLowPriority(isLowPriority);
- if (mNotificationLockscreenUserManager.needsRedaction(entry)) {
+ // If screenshareNotificationHiding is enabled, both public and private views should be
+ // inflated to avoid any latency associated with reinflating all notification views when
+ // screen share starts and stops
+ if (screenshareNotificationHiding()
+ || mNotificationLockscreenUserManager.needsRedaction(entry)) {
params.requireContentViews(FLAG_CONTENT_VIEW_PUBLIC);
} else {
params.markContentViewsFreeable(FLAG_CONTENT_VIEW_PUBLIC);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt
index eff91e5..5ee38be 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt
@@ -25,6 +25,8 @@
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.StatusBarState.SHADE_LOCKED
+import com.android.systemui.keyguard.shared.model.TransitionState.RUNNING
+import com.android.systemui.keyguard.shared.model.TransitionState.STARTED
import com.android.systemui.keyguard.ui.viewmodel.LockscreenToOccludedTransitionViewModel
import com.android.systemui.keyguard.ui.viewmodel.OccludedToLockscreenTransitionViewModel
import com.android.systemui.shade.domain.interactor.ShadeInteractor
@@ -71,6 +73,20 @@
KeyguardState.PRIMARY_BOUNCER
)
+ private val lockscreenToOccludedRunning =
+ keyguardTransitionInteractor
+ .transition(KeyguardState.LOCKSCREEN, KeyguardState.OCCLUDED)
+ .map { it.transitionState == STARTED || it.transitionState == RUNNING }
+ .distinctUntilChanged()
+ .onStart { emit(false) }
+
+ private val occludedToLockscreenRunning =
+ keyguardTransitionInteractor
+ .transition(KeyguardState.OCCLUDED, KeyguardState.LOCKSCREEN)
+ .map { it.transitionState == STARTED || it.transitionState == RUNNING }
+ .distinctUntilChanged()
+ .onStart { emit(false) }
+
val shadeCollapseFadeInComplete = MutableStateFlow(false)
val configurationBasedDimensions: Flow<ConfigurationBasedDimensions> =
@@ -122,7 +138,11 @@
) { isKeyguard, isShadeVisible, qsExpansion ->
isKeyguard && !(isShadeVisible || qsExpansion)
}
- .distinctUntilChanged()
+ .stateIn(
+ scope = applicationScope,
+ started = SharingStarted.Eagerly,
+ initialValue = false,
+ )
/** Fade in only for use after the shade collapses */
val shadeCollpaseFadeIn: Flow<Boolean> =
@@ -182,26 +202,37 @@
)
val alpha: Flow<Float> =
- isOnLockscreenWithoutShade
- .flatMapLatest { isOnLockscreenWithoutShade ->
- combineTransform(
- merge(
- occludedToLockscreenTransitionViewModel.lockscreenAlpha,
- lockscreenToOccludedTransitionViewModel.lockscreenAlpha,
- keyguardInteractor.keyguardAlpha,
- ),
- shadeCollpaseFadeIn,
- ) { alpha, shadeCollpaseFadeIn ->
- if (isOnLockscreenWithoutShade) {
- if (!shadeCollpaseFadeIn) {
- emit(alpha)
- }
+ // Due to issues with the legacy shade, some shade expansion events are sent incorrectly,
+ // such as when the shade resets. This can happen while the LOCKSCREEN<->OCCLUDED transition
+ // is running. Therefore use a series of flatmaps to prevent unwanted interruptions while
+ // those transitions are in progress. Without this, the alpha value will produce a visible
+ // flicker.
+ lockscreenToOccludedRunning.flatMapLatest { isLockscreenToOccludedRunning ->
+ if (isLockscreenToOccludedRunning) {
+ lockscreenToOccludedTransitionViewModel.lockscreenAlpha
+ } else {
+ occludedToLockscreenRunning.flatMapLatest { isOccludedToLockscreenRunning ->
+ if (isOccludedToLockscreenRunning) {
+ occludedToLockscreenTransitionViewModel.lockscreenAlpha.onStart { emit(0f) }
} else {
- emit(1f)
+ isOnLockscreenWithoutShade.flatMapLatest { isOnLockscreenWithoutShade ->
+ combineTransform(
+ keyguardInteractor.keyguardAlpha,
+ shadeCollpaseFadeIn,
+ ) { alpha, shadeCollpaseFadeIn ->
+ if (isOnLockscreenWithoutShade) {
+ if (!shadeCollpaseFadeIn) {
+ emit(alpha)
+ }
+ } else {
+ emit(1f)
+ }
+ }
+ }
}
}
}
- .distinctUntilChanged()
+ }
/**
* Under certain scenarios, such as swiping up on the lockscreen, the container will need to be
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/plugins/PluginInstanceTest.java b/packages/SystemUI/tests/src/com/android/systemui/shared/plugins/PluginInstanceTest.java
index 5e57c83..bc50c25 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shared/plugins/PluginInstanceTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/plugins/PluginInstanceTest.java
@@ -198,7 +198,7 @@
AtomicBoolean isBgThreadFailed = new AtomicBoolean(false);
Thread bgThread = new Thread(() -> {
assertTrue(getLock(unloadLock, 10));
- assertTrue(getLock(loadLock, 3000)); // Wait for the foreground thread
+ assertTrue(getLock(loadLock, 4000)); // Wait for the foreground thread
assertNotNull(mPluginInstance.getPlugin());
// Attempt to delete the plugin, this should block until the load completes
mPluginInstance.unloadPlugin();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt
index 36a4712..20020f2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt
@@ -43,6 +43,7 @@
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Before
@@ -418,13 +419,13 @@
}
@Test
- fun shadeCollpaseFadeIn() =
+ fun shadeCollapseFadeIn() =
testScope.runTest {
+ val fadeIn by collectLastValue(underTest.shadeCollpaseFadeIn)
+
// Start on lockscreen without the shade
underTest.setShadeCollapseFadeInComplete(false)
showLockscreen()
-
- val fadeIn by collectLastValue(underTest.shadeCollpaseFadeIn)
assertThat(fadeIn).isEqualTo(false)
// ... then the shade expands
@@ -440,10 +441,12 @@
assertThat(fadeIn).isEqualTo(false)
}
- private suspend fun showLockscreen() {
+ private suspend fun TestScope.showLockscreen() {
shadeRepository.setLockscreenShadeExpansion(0f)
shadeRepository.setQsExpansion(0f)
+ runCurrent()
keyguardRepository.setStatusBarState(StatusBarState.KEYGUARD)
+ runCurrent()
keyguardTransitionRepository.sendTransitionSteps(
from = KeyguardState.AOD,
to = KeyguardState.LOCKSCREEN,
@@ -451,10 +454,12 @@
)
}
- private suspend fun showLockscreenWithShadeExpanded() {
+ private suspend fun TestScope.showLockscreenWithShadeExpanded() {
shadeRepository.setLockscreenShadeExpansion(1f)
shadeRepository.setQsExpansion(0f)
+ runCurrent()
keyguardRepository.setStatusBarState(StatusBarState.SHADE_LOCKED)
+ runCurrent()
keyguardTransitionRepository.sendTransitionSteps(
from = KeyguardState.AOD,
to = KeyguardState.LOCKSCREEN,
@@ -462,10 +467,12 @@
)
}
- private suspend fun showLockscreenWithQSExpanded() {
+ private suspend fun TestScope.showLockscreenWithQSExpanded() {
shadeRepository.setLockscreenShadeExpansion(0f)
shadeRepository.setQsExpansion(1f)
+ runCurrent()
keyguardRepository.setStatusBarState(StatusBarState.SHADE_LOCKED)
+ runCurrent()
keyguardTransitionRepository.sendTransitionSteps(
from = KeyguardState.AOD,
to = KeyguardState.LOCKSCREEN,
diff --git a/services/core/java/com/android/server/biometrics/AuthenticationStatsCollector.java b/services/core/java/com/android/server/biometrics/AuthenticationStatsCollector.java
index 4df2581..5d609bc 100644
--- a/services/core/java/com/android/server/biometrics/AuthenticationStatsCollector.java
+++ b/services/core/java/com/android/server/biometrics/AuthenticationStatsCollector.java
@@ -54,8 +54,8 @@
@NonNull private final Context mContext;
@NonNull private final PackageManager mPackageManager;
- @NonNull private final FaceManager mFaceManager;
- @NonNull private final FingerprintManager mFingerprintManager;
+ @Nullable private final FaceManager mFaceManager;
+ @Nullable private final FingerprintManager mFingerprintManager;
private final boolean mEnabled;
private final float mThreshold;
@@ -197,11 +197,11 @@
}
private boolean hasEnrolledFace(int userId) {
- return mFaceManager.hasEnrolledTemplates(userId);
+ return mFaceManager != null && mFaceManager.hasEnrolledTemplates(userId);
}
private boolean hasEnrolledFingerprint(int userId) {
- return mFingerprintManager.hasEnrolledTemplates(userId);
+ return mFingerprintManager != null && mFingerprintManager.hasEnrolledTemplates(userId);
}
/**
diff --git a/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java b/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java
index e546f42..1660c3e 100644
--- a/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java
+++ b/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java
@@ -21,11 +21,13 @@
import android.Manifest;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
+import android.app.ActivityManager;
import android.app.AppOpsManager;
import android.app.admin.DevicePolicyManager;
import android.app.role.RoleManager;
import android.content.Context;
import android.content.pm.PackageManager;
+import android.content.pm.UserInfo;
import android.os.Binder;
import android.os.BugreportManager.BugreportCallback;
import android.os.BugreportParams;
@@ -37,7 +39,6 @@
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UserHandle;
-import android.os.UserManager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.ArrayMap;
@@ -95,7 +96,6 @@
private static final long DEFAULT_BUGREPORT_SERVICE_TIMEOUT_MILLIS = 30 * 1000;
private final Object mLock = new Object();
- private final Injector mInjector;
private final Context mContext;
private final AppOpsManager mAppOps;
private final TelephonyManager mTelephonyManager;
@@ -346,14 +346,6 @@
AtomicFile getMappingFile() {
return mMappingFile;
}
-
- UserManager getUserManager() {
- return mContext.getSystemService(UserManager.class);
- }
-
- DevicePolicyManager getDevicePolicyManager() {
- return mContext.getSystemService(DevicePolicyManager.class);
- }
}
BugreportManagerServiceImpl(Context context) {
@@ -365,7 +357,6 @@
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
BugreportManagerServiceImpl(Injector injector) {
- mInjector = injector;
mContext = injector.getContext();
mAppOps = mContext.getSystemService(AppOpsManager.class);
mTelephonyManager = mContext.getSystemService(TelephonyManager.class);
@@ -398,7 +389,12 @@
int callingUid = Binder.getCallingUid();
enforcePermission(callingPackage, callingUid, bugreportMode
== BugreportParams.BUGREPORT_MODE_TELEPHONY /* checkCarrierPrivileges */);
- ensureUserCanTakeBugReport(bugreportMode);
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ ensureUserCanTakeBugReport(bugreportMode);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
Slogf.i(TAG, "Starting bugreport for %s / %d", callingPackage, callingUid);
synchronized (mLock) {
@@ -437,6 +433,7 @@
@RequiresPermission(value = Manifest.permission.DUMP, conditional = true)
public void retrieveBugreport(int callingUidUnused, String callingPackage, int userId,
FileDescriptor bugreportFd, String bugreportFile,
+
boolean keepBugreportOnRetrievalUnused, IDumpstateListener listener) {
int callingUid = Binder.getCallingUid();
enforcePermission(callingPackage, callingUid, false);
@@ -568,48 +565,54 @@
}
/**
- * Validates that the calling user is an admin user or, when bugreport is requested remotely
- * that the user is an affiliated user.
+ * Validates that the current user is an admin user or, when bugreport is requested remotely
+ * that the current user is an affiliated user.
*
- * @throws IllegalArgumentException if the calling user is not an admin user
+ * @throws IllegalArgumentException if the current user is not an admin user
*/
private void ensureUserCanTakeBugReport(int bugreportMode) {
- // Get the calling userId before clearing the caller identity.
- int callingUserId = UserHandle.getUserId(Binder.getCallingUid());
- boolean isAdminUser = false;
- final long identity = Binder.clearCallingIdentity();
+ UserInfo currentUser = null;
try {
- isAdminUser = mInjector.getUserManager().isUserAdmin(callingUserId);
- } finally {
- Binder.restoreCallingIdentity(identity);
+ currentUser = ActivityManager.getService().getCurrentUser();
+ } catch (RemoteException e) {
+ // Impossible to get RemoteException for an in-process call.
}
- if (!isAdminUser) {
+
+ if (currentUser == null) {
+ logAndThrow("There is no current user, so no bugreport can be requested.");
+ }
+
+ if (!currentUser.isAdmin()) {
if (bugreportMode == BugreportParams.BUGREPORT_MODE_REMOTE
- && isUserAffiliated(callingUserId)) {
+ && isCurrentUserAffiliated(currentUser.id)) {
return;
}
- logAndThrow(TextUtils.formatSimple("Calling user %s is not an admin user."
- + " Only admin users are allowed to take bugreport.", callingUserId));
+ logAndThrow(TextUtils.formatSimple("Current user %s is not an admin user."
+ + " Only admin users are allowed to take bugreport.", currentUser.id));
}
}
/**
- * Returns {@code true} if the device has device owner and the specified user is affiliated
+ * Returns {@code true} if the device has device owner and the current user is affiliated
* with the device owner.
*/
- private boolean isUserAffiliated(int userId) {
- DevicePolicyManager dpm = mInjector.getDevicePolicyManager();
+ private boolean isCurrentUserAffiliated(int currentUserId) {
+ DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class);
int deviceOwnerUid = dpm.getDeviceOwnerUserId();
if (deviceOwnerUid == UserHandle.USER_NULL) {
return false;
}
- if (DEBUG) {
- Slog.d(TAG, "callingUid: " + userId + " deviceOwnerUid: " + deviceOwnerUid);
- }
+ int callingUserId = UserHandle.getUserId(Binder.getCallingUid());
- if (userId != deviceOwnerUid && !dpm.isAffiliatedUser(userId)) {
- logAndThrow("User " + userId + " is not affiliated to the device owner.");
+ Slog.i(TAG, "callingUid: " + callingUserId + " deviceOwnerUid: " + deviceOwnerUid
+ + " currentUserId: " + currentUserId);
+
+ if (callingUserId != deviceOwnerUid) {
+ logAndThrow("Caller is not device owner on provisioned device.");
+ }
+ if (!dpm.isAffiliatedUser(currentUserId)) {
+ logAndThrow("Current user is not affiliated to the device owner.");
}
return true;
}
diff --git a/services/core/java/com/android/server/pm/BroadcastHelper.java b/services/core/java/com/android/server/pm/BroadcastHelper.java
index 7f58e75e..e830d28 100644
--- a/services/core/java/com/android/server/pm/BroadcastHelper.java
+++ b/services/core/java/com/android/server/pm/BroadcastHelper.java
@@ -827,7 +827,8 @@
// action. When the targetPkg is set, it sends the broadcast to specific app, e.g.
// installer app or null for registered apps. The callback only need to send back to the
// registered apps so we check the null condition here.
- notifyPackageMonitor(action, pkg, extras, userIds, instantUserIds, broadcastAllowList);
+ notifyPackageMonitor(action, pkg, extras, userIds, instantUserIds, broadcastAllowList,
+ null /* filterExtras */);
}
}
@@ -975,14 +976,16 @@
final Bundle options = new BroadcastOptions()
.setDeferralPolicy(BroadcastOptions.DEFERRAL_POLICY_UNTIL_ACTIVE)
.toBundle();
+ BiFunction<Integer, Bundle, Bundle> filterExtrasForReceiver =
+ (callingUid, intentExtras) -> BroadcastHelper.filterExtrasChangedPackageList(
+ snapshot, callingUid, intentExtras);
mHandler.post(() -> sendPackageBroadcast(intent, null /* pkg */,
extras, flags, null /* targetPkg */, null /* finishedReceiver */,
new int[]{userId}, null /* instantUserIds */, null /* broadcastAllowList */,
- (callingUid, intentExtras) -> BroadcastHelper.filterExtrasChangedPackageList(
- snapshot, callingUid, intentExtras),
+ filterExtrasForReceiver,
options));
notifyPackageMonitor(intent, null /* pkg */, extras, new int[]{userId},
- null /* instantUserIds */, null /* broadcastAllowList */);
+ null /* instantUserIds */, null /* broadcastAllowList */, filterExtrasForReceiver);
}
void sendMyPackageSuspendedOrUnsuspended(@NonNull Computer snapshot,
@@ -1068,9 +1071,10 @@
@Nullable Bundle extras,
@NonNull int[] userIds,
@NonNull int[] instantUserIds,
- @Nullable SparseArray<int[]> broadcastAllowList) {
+ @Nullable SparseArray<int[]> broadcastAllowList,
+ @Nullable BiFunction<Integer, Bundle, Bundle> filterExtras) {
mPackageMonitorCallbackHelper.notifyPackageMonitor(action, pkg, extras, userIds,
- instantUserIds, broadcastAllowList, mHandler);
+ instantUserIds, broadcastAllowList, mHandler, filterExtras);
}
private void notifyResourcesChanged(boolean mediaStatus,
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index b7deef0..5225529 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -4626,7 +4626,7 @@
});
mPackageMonitorCallbackHelper.notifyPackageMonitor(Intent.ACTION_PACKAGE_UNSTOPPED,
packageName, extras, userIds, null /* instantUserIds */,
- broadcastAllowList, mHandler);
+ broadcastAllowList, mHandler, null /* filterExtras */);
}
}
}
@@ -7076,7 +7076,7 @@
}
mPackageMonitorCallbackHelper.notifyPackageMonitor(Intent.ACTION_PACKAGE_RESTARTED,
packageName, extras, userIds, null /* instantUserIds */,
- broadcastAllowList, mHandler);
+ broadcastAllowList, mHandler, null /* filterExtras */);
}
@Override
diff --git a/services/core/java/com/android/server/pm/PackageMonitorCallbackHelper.java b/services/core/java/com/android/server/pm/PackageMonitorCallbackHelper.java
index 1bb0730..d05e4c6 100644
--- a/services/core/java/com/android/server/pm/PackageMonitorCallbackHelper.java
+++ b/services/core/java/com/android/server/pm/PackageMonitorCallbackHelper.java
@@ -41,6 +41,7 @@
import com.android.internal.util.ArrayUtils;
import java.util.ArrayList;
+import java.util.function.BiFunction;
/** Helper class to handle PackageMonitorCallback and notify the registered client. This is mainly
* used by PackageMonitor to improve the broadcast latency. */
@@ -105,8 +106,9 @@
extras.putBoolean(Intent.EXTRA_ARCHIVAL, true);
}
extras.putInt(PackageInstaller.EXTRA_DATA_LOADER_TYPE, dataLoaderType);
- notifyPackageMonitor(Intent.ACTION_PACKAGE_ADDED, packageName, extras ,
- userIds /* userIds */, instantUserIds, broadcastAllowList, handler);
+ notifyPackageMonitor(Intent.ACTION_PACKAGE_ADDED, packageName, extras,
+ userIds /* userIds */, instantUserIds, broadcastAllowList, handler,
+ null /* filterExtras */);
}
public void notifyResourcesChanged(boolean mediaStatus, boolean replacing,
@@ -120,7 +122,8 @@
String action = mediaStatus ? Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE
: Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE;
notifyPackageMonitor(action, null /* pkg */, extras, null /* userIds */,
- null /* instantUserIds */, null /* broadcastAllowList */, handler);
+ null /* instantUserIds */, null /* broadcastAllowList */, handler,
+ null /* filterExtras */);
}
public void notifyPackageChanged(String packageName, boolean dontKillApp,
@@ -137,12 +140,12 @@
extras.putString(Intent.EXTRA_REASON, reason);
}
notifyPackageMonitor(Intent.ACTION_PACKAGE_CHANGED, packageName, extras, userIds,
- instantUserIds, broadcastAllowList, handler);
+ instantUserIds, broadcastAllowList, handler, null /* filterExtras */);
}
public void notifyPackageMonitor(String action, String pkg, Bundle extras,
int[] userIds, int[] instantUserIds, SparseArray<int[]> broadcastAllowList,
- Handler handler) {
+ Handler handler, BiFunction<Integer, Bundle, Bundle> filterExtras) {
if (!isAllowedCallbackAction(action)) {
return;
}
@@ -160,10 +163,11 @@
if (ArrayUtils.isEmpty(instantUserIds)) {
doNotifyCallbacksByAction(
- action, pkg, extras, resolvedUserIds, broadcastAllowList, handler);
+ action, pkg, extras, resolvedUserIds, broadcastAllowList, handler,
+ filterExtras);
} else {
doNotifyCallbacksByAction(action, pkg, extras, instantUserIds, broadcastAllowList,
- handler);
+ handler, filterExtras);
}
} catch (RemoteException e) {
// do nothing
@@ -199,11 +203,13 @@
synchronized (mLock) {
callbacks = mCallbacks;
}
- doNotifyCallbacks(callbacks, intent, userId, broadcastAllowList, handler);
+ doNotifyCallbacks(callbacks, intent, userId, broadcastAllowList, handler,
+ null /* filterExtrasFunction */);
}
private void doNotifyCallbacksByAction(String action, String pkg, Bundle extras, int[] userIds,
- SparseArray<int[]> broadcastAllowList, Handler handler) {
+ SparseArray<int[]> broadcastAllowList, Handler handler,
+ BiFunction<Integer, Bundle, Bundle> filterExtrasFunction) {
RemoteCallbackList<IRemoteCallback> callbacks;
synchronized (mLock) {
callbacks = mCallbacks;
@@ -223,12 +229,13 @@
final int[] allowUids =
broadcastAllowList != null ? broadcastAllowList.get(userId) : null;
- doNotifyCallbacks(callbacks, intent, userId, allowUids, handler);
+ doNotifyCallbacks(callbacks, intent, userId, allowUids, handler, filterExtrasFunction);
}
}
private void doNotifyCallbacks(RemoteCallbackList<IRemoteCallback> callbacks,
- Intent intent, int userId, int[] allowUids, Handler handler) {
+ Intent intent, int userId, int[] allowUids, Handler handler,
+ BiFunction<Integer, Bundle, Bundle> filterExtrasFunction) {
handler.post(() -> callbacks.broadcast((callback, user) -> {
RegisterUser registerUser = (RegisterUser) user;
if ((registerUser.getUserId() != UserHandle.USER_ALL) && (registerUser.getUserId()
@@ -236,6 +243,15 @@
return;
}
int registerUid = registerUser.getUid();
+ if (filterExtrasFunction != null) {
+ final Bundle extras = intent.getExtras();
+ if (extras != null) {
+ final Bundle filteredExtras = filterExtrasFunction.apply(registerUid, extras);
+ if (filteredExtras != null) {
+ intent.replaceExtras(filteredExtras);
+ }
+ }
+ }
if (allowUids != null && registerUid != Process.SYSTEM_UID
&& !ArrayUtils.contains(allowUids, registerUid)) {
if (DEBUG) {
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 145eb3b..ca8afe1 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -223,7 +223,6 @@
import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_NONE;
import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_WINDOWING_MODE_RESIZE;
import static com.android.server.wm.ActivityTaskManagerService.getInputDispatchingTimeoutMillisLocked;
-import static com.android.server.wm.ActivityTaskSupervisor.PRESERVE_WINDOWS;
import static com.android.server.wm.IdentifierProto.HASH_CODE;
import static com.android.server.wm.IdentifierProto.TITLE;
import static com.android.server.wm.IdentifierProto.USER_ID;
@@ -949,7 +948,7 @@
private int mConfigurationSeq;
/**
- * Temp configs used in {@link #ensureActivityConfiguration(int, boolean)}
+ * Temp configs used in {@link #ensureActivityConfiguration()}
*/
private final Configuration mTmpConfig = new Configuration();
private final Rect mTmpBounds = new Rect();
@@ -1511,7 +1510,7 @@
updatePictureInPictureMode(null, false);
} else {
mLastReportedMultiWindowMode = inMultiWindowMode;
- ensureActivityConfiguration(0 /* globalChanges */, PRESERVE_WINDOWS);
+ ensureActivityConfiguration();
}
}
}
@@ -1530,8 +1529,7 @@
// precede the configuration change from the resize.
mLastReportedPictureInPictureMode = inPictureInPictureMode;
mLastReportedMultiWindowMode = inPictureInPictureMode;
- ensureActivityConfiguration(0 /* globalChanges */, PRESERVE_WINDOWS,
- true /* ignoreVisibility */);
+ ensureActivityConfiguration(true /* ignoreVisibility */);
if (inPictureInPictureMode && findMainWindow() == null) {
// Prevent malicious app entering PiP without valid WindowState, which can in turn
// result a non-touchable PiP window since the InputConsumer for PiP requires it.
@@ -3107,7 +3105,7 @@
// {@link #returningOptions} of the activity under this one can be applied in
// {@link #handleAlreadyVisible()}.
if (changed || !occludesParent) {
- mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
+ mRootWindowContainer.ensureActivitiesVisible();
}
return changed;
}
@@ -3747,8 +3745,8 @@
}
if (ensureVisibility) {
- mDisplayContent.ensureActivitiesVisible(null /* starting */, 0 /* configChanges */,
- false /* preserveWindows */, true /* notifyClients */);
+ mDisplayContent.ensureActivitiesVisible(null /* starting */,
+ true /* notifyClients */);
}
}
@@ -4165,8 +4163,7 @@
if (rootTask != null && rootTask.shouldSleepOrShutDownActivities()) {
// Activity is always relaunched to either resumed or paused state. If it was
// relaunched while hidden (by keyguard or smth else), it should be stopped.
- rootTask.ensureActivitiesVisible(null /* starting */, 0 /* configChanges */,
- false /* preserveWindows */);
+ rootTask.ensureActivitiesVisible(null /* starting */);
}
}
@@ -4681,14 +4678,12 @@
void setShowWhenLocked(boolean showWhenLocked) {
mShowWhenLocked = showWhenLocked;
- mAtmService.mRootWindowContainer.ensureActivitiesVisible(null /* starting */,
- 0 /* configChanges */, false /* preserveWindows */);
+ mAtmService.mRootWindowContainer.ensureActivitiesVisible();
}
void setInheritShowWhenLocked(boolean inheritShowWhenLocked) {
mInheritShownWhenLocked = inheritShowWhenLocked;
- mAtmService.mRootWindowContainer.ensureActivitiesVisible(null /* starting */,
- 0 /* configChanges */, false /* preserveWindows */);
+ mAtmService.mRootWindowContainer.ensureActivitiesVisible();
}
/**
@@ -6413,7 +6408,7 @@
}
mDisplayContent.handleActivitySizeCompatModeIfNeeded(this);
- mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
+ mRootWindowContainer.ensureActivitiesVisible();
}
/**
@@ -7894,7 +7889,7 @@
void applyFixedRotationTransform(DisplayInfo info, DisplayFrames displayFrames,
Configuration config) {
super.applyFixedRotationTransform(info, displayFrames, config);
- ensureActivityConfiguration(0 /* globalChanges */, false /* preserveWindow */);
+ ensureActivityConfiguration();
}
/**
@@ -7989,7 +7984,7 @@
startFreezingScreen(originalDisplayRotation);
// This activity may relaunch or perform configuration change so once it has reported drawn,
// the screen can be unfrozen.
- ensureActivityConfiguration(0 /* globalChanges */, !PRESERVE_WINDOWS);
+ ensureActivityConfiguration();
if (mTransitionController.isCollecting(this)) {
// In case the task was changed from PiP but still keeps old transform.
task.resetSurfaceControlTransforms();
@@ -8017,7 +8012,7 @@
// the request is handled at task level with letterbox.
if (!getMergedOverrideConfiguration().equals(
mLastReportedConfiguration.getMergedConfiguration())) {
- ensureActivityConfiguration(0 /* globalChanges */, false /* preserveWindow */,
+ ensureActivityConfiguration(
false /* ignoreVisibility */, true /* isRequestedOrientationChanged */);
if (mTransitionController.inPlayingTransition(this)) {
mTransitionController.mValidateActivityCompat.add(this);
@@ -9525,14 +9520,12 @@
return mLastReportedDisplayId != getDisplayId();
}
- boolean ensureActivityConfiguration(int globalChanges, boolean preserveWindow) {
- return ensureActivityConfiguration(globalChanges, preserveWindow,
- false /* ignoreVisibility */, false /* isRequestedOrientationChanged */);
+ boolean ensureActivityConfiguration() {
+ return ensureActivityConfiguration(false /* ignoreVisibility */);
}
- boolean ensureActivityConfiguration(int globalChanges, boolean preserveWindow,
- boolean ignoreVisibility) {
- return ensureActivityConfiguration(globalChanges, preserveWindow, ignoreVisibility,
+ boolean ensureActivityConfiguration(boolean ignoreVisibility) {
+ return ensureActivityConfiguration(ignoreVisibility,
false /* isRequestedOrientationChanged */);
}
@@ -9540,9 +9533,6 @@
* Make sure the given activity matches the current configuration. Ensures the HistoryRecord
* is updated with the correct configuration and all other bookkeeping is handled.
*
- * @param globalChanges The changes to the global configuration.
- * @param preserveWindow If the activity window should be preserved on screen if the activity
- * is relaunched.
* @param ignoreVisibility If we should try to relaunch the activity even if it is invisible
* (stopped state). This is useful for the case where we know the
* activity will be visible soon and we want to ensure its configuration
@@ -9552,8 +9542,8 @@
* @return False if the activity was relaunched and true if it wasn't relaunched because we
* can't or the app handles the specific configuration that is changing.
*/
- boolean ensureActivityConfiguration(int globalChanges, boolean preserveWindow,
- boolean ignoreVisibility, boolean isRequestedOrientationChanged) {
+ boolean ensureActivityConfiguration(boolean ignoreVisibility,
+ boolean isRequestedOrientationChanged) {
final Task rootTask = getRootTask();
if (rootTask.mConfigWillChange) {
ProtoLog.v(WM_DEBUG_CONFIGURATION, "Skipping config check "
@@ -9667,10 +9657,21 @@
if (shouldRelaunchLocked(changes, mTmpConfig)) {
// Aha, the activity isn't handling the change, so DIE DIE DIE.
configChangeFlags |= changes;
- startFreezingScreenLocked(globalChanges);
+ if (mVisible && mAtmService.mTmpUpdateConfigurationResult.mIsUpdating
+ && !mTransitionController.isShellTransitionsEnabled()) {
+ startFreezingScreenLocked(mAtmService.mTmpUpdateConfigurationResult.changes);
+ }
+ final boolean displayMayChange = mTmpConfig.windowConfiguration.getDisplayRotation()
+ != getWindowConfiguration().getDisplayRotation()
+ || !mTmpConfig.windowConfiguration.getMaxBounds().equals(
+ getWindowConfiguration().getMaxBounds());
+ final boolean isAppResizeOnly = !displayMayChange
+ && (changes & ~(CONFIG_SCREEN_SIZE | CONFIG_SMALLEST_SCREEN_SIZE
+ | CONFIG_ORIENTATION | CONFIG_SCREEN_LAYOUT)) == 0;
// Do not preserve window if it is freezing screen because the original window won't be
// able to update drawn state that causes freeze timeout.
- preserveWindow &= isResizeOnlyChange(changes) && !mFreezingScreen;
+ // TODO(b/258618073): Always preserve if possible.
+ final boolean preserveWindow = isAppResizeOnly && !mFreezingScreen;
final boolean hasResizeChange = hasResizeChange(changes & ~info.getRealConfigChanged());
if (hasResizeChange) {
final boolean isDragResizing = task.isDragResizing();
@@ -9834,11 +9835,6 @@
return changes;
}
- private static boolean isResizeOnlyChange(int change) {
- return (change & ~(CONFIG_SCREEN_SIZE | CONFIG_SMALLEST_SCREEN_SIZE | CONFIG_ORIENTATION
- | CONFIG_SCREEN_LAYOUT)) == 0;
- }
-
private static boolean hasResizeChange(int change) {
return (change & (CONFIG_SCREEN_SIZE | CONFIG_SMALLEST_SCREEN_SIZE | CONFIG_ORIENTATION
| CONFIG_SCREEN_LAYOUT)) != 0;
@@ -9882,8 +9878,6 @@
task.mTaskId, shortComponentName, Integer.toHexString(configChangeFlags));
}
- startFreezingScreenLocked(0);
-
try {
ProtoLog.i(WM_DEBUG_STATES, "Moving to %s Relaunching %s callers=%s" ,
(andResume ? "RESUMED" : "PAUSED"), this, Debug.getCallers(6));
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index cb2adbc..d90d017 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -73,7 +73,6 @@
import static com.android.server.wm.ActivityTaskManagerService.ANIMATE;
import static com.android.server.wm.ActivityTaskSupervisor.DEFER_RESUME;
import static com.android.server.wm.ActivityTaskSupervisor.ON_TOP;
-import static com.android.server.wm.ActivityTaskSupervisor.PRESERVE_WINDOWS;
import static com.android.server.wm.BackgroundActivityStartController.BAL_ALLOW_DEFAULT;
import static com.android.server.wm.BackgroundActivityStartController.BAL_BLOCK;
import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.PHASE_BOUNDS;
@@ -1733,6 +1732,7 @@
// So disallow the transient hide activity to move itself to front, e.g. trampoline.
if (!avoidMoveToFront() && (mService.mHomeProcess == null
|| mService.mHomeProcess.mUid != realCallingUid)
+ && (prevTopTask != null && prevTopTask.isActivityTypeHomeOrRecents())
&& r.mTransitionController.isTransientHide(targetTask)) {
mCanMoveToFrontCode = MOVE_TO_FRONT_AVOID_LEGACY;
}
@@ -1859,8 +1859,7 @@
// over is removed.
// Passing {@code null} as the start parameter ensures all activities are made
// visible.
- mTargetRootTask.ensureActivitiesVisible(null /* starting */,
- 0 /* configChanges */, !PRESERVE_WINDOWS);
+ mTargetRootTask.ensureActivitiesVisible(null /* starting */);
// Go ahead and tell window manager to execute app transition for this activity
// since the app transition will not be triggered through the resume channel.
mTargetRootTask.mDisplayContent.executeAppTransition();
@@ -2867,7 +2866,7 @@
mRootWindowContainer.resumeFocusedTasksTopActivities(mTargetRootTask, null,
mOptions, mTransientLaunch);
} else {
- mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
+ mRootWindowContainer.ensureActivitiesVisible();
}
} else {
ActivityOptions.abort(mOptions);
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index dbae29b..f43c1b0 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -118,7 +118,6 @@
import static com.android.server.wm.ActivityTaskManagerService.UiHandler.DISMISS_DIALOG_UI_MSG;
import static com.android.server.wm.ActivityTaskSupervisor.DEFER_RESUME;
import static com.android.server.wm.ActivityTaskSupervisor.ON_TOP;
-import static com.android.server.wm.ActivityTaskSupervisor.PRESERVE_WINDOWS;
import static com.android.server.wm.ActivityTaskSupervisor.REMOVE_FROM_RECENTS;
import static com.android.server.wm.BackgroundActivityStartController.BalVerdict;
import static com.android.server.wm.LockTaskController.LOCK_TASK_AUTH_DONT_LOCK;
@@ -496,16 +495,13 @@
final UpdateConfigurationResult mTmpUpdateConfigurationResult =
new UpdateConfigurationResult();
+ // TODO(b/258618073): Remove this and make the related methods return whether config is changed.
static final class UpdateConfigurationResult {
// Configuration changes that were updated.
int changes;
// If the activity was relaunched to match the new configuration.
boolean activityRelaunched;
-
- void reset() {
- changes = 0;
- activityRelaunched = false;
- }
+ boolean mIsUpdating;
}
/** Current sequencing integer of the configuration, for skipping old configurations. */
@@ -3834,8 +3830,7 @@
Settings.System.clearConfiguration(values);
}
updateConfigurationLocked(values, null, false, false /* persistent */,
- UserHandle.USER_NULL, false /* deferResume */,
- mTmpUpdateConfigurationResult);
+ UserHandle.USER_NULL, false /* deferResume */);
return mTmpUpdateConfigurationResult.changes != 0;
} finally {
Binder.restoreCallingIdentity(origId);
@@ -4507,12 +4502,6 @@
}
}
- private boolean updateConfigurationLocked(Configuration values, ActivityRecord starting,
- boolean initLocale, boolean persistent, int userId, boolean deferResume) {
- return updateConfigurationLocked(values, starting, initLocale, persistent, userId,
- deferResume, null /* result */);
- }
-
/**
* Do either or both things: (1) change the current configuration, and (2)
* make sure the given activity is running with the (now) current
@@ -4524,8 +4513,7 @@
* for that particular user
*/
boolean updateConfigurationLocked(Configuration values, ActivityRecord starting,
- boolean initLocale, boolean persistent, int userId, boolean deferResume,
- ActivityTaskManagerService.UpdateConfigurationResult result) {
+ boolean initLocale, boolean persistent, int userId, boolean deferResume) {
int changes = 0;
boolean kept = true;
@@ -4533,19 +4521,18 @@
try {
if (values != null) {
changes = updateGlobalConfigurationLocked(values, initLocale, persistent, userId);
+ mTmpUpdateConfigurationResult.changes = changes;
+ mTmpUpdateConfigurationResult.mIsUpdating = true;
}
if (!deferResume) {
kept = ensureConfigAndVisibilityAfterUpdate(starting, changes);
}
} finally {
+ mTmpUpdateConfigurationResult.mIsUpdating = false;
continueWindowLayout();
}
-
- if (result != null) {
- result.changes = changes;
- result.activityRelaunched = !kept;
- }
+ mTmpUpdateConfigurationResult.activityRelaunched = !kept;
return kept;
}
@@ -5325,12 +5312,10 @@
}
if (starting != null) {
- kept = starting.ensureActivityConfiguration(changes,
- false /* preserveWindow */);
+ kept = starting.ensureActivityConfiguration();
// And we need to make sure at this point that all other activities
// are made visible with the correct configuration.
- mRootWindowContainer.ensureActivitiesVisible(starting, changes,
- !PRESERVE_WINDOWS);
+ mRootWindowContainer.ensureActivitiesVisible(starting);
}
}
diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
index 10efb94..1872f6e 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
@@ -1462,7 +1462,7 @@
}
mLaunchingActivityWakeLock.release();
}
- mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
+ mRootWindowContainer.ensureActivitiesVisible();
}
// Atomically retrieve all of the other things to do.
@@ -1603,7 +1603,7 @@
*/
rootTask.cancelAnimation();
rootTask.setForceHidden(FLAG_FORCE_HIDDEN_FOR_PINNED_TASK, true /* set */);
- rootTask.ensureActivitiesVisible(null, 0, PRESERVE_WINDOWS);
+ rootTask.ensureActivitiesVisible(null /* starting */);
activityIdleInternal(null /* idleActivity */, false /* fromTimeout */,
true /* processPausingActivities */, null /* configuration */);
@@ -1622,7 +1622,7 @@
// Follow on the workaround: activities are kept force hidden till the new windowing
// mode is set.
rootTask.setForceHidden(FLAG_FORCE_HIDDEN_FOR_PINNED_TASK, false /* set */);
- mRootWindowContainer.ensureActivitiesVisible(null, 0, PRESERVE_WINDOWS);
+ mRootWindowContainer.ensureActivitiesVisible();
mRootWindowContainer.resumeFocusedTasksTopActivities();
} finally {
mService.continueWindowLayout();
@@ -2026,7 +2026,7 @@
final Task rootTask = r.getRootTask();
if (rootTask.getDisplayArea().allResumedActivitiesComplete()) {
- mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
+ mRootWindowContainer.ensureActivitiesVisible();
// Make sure activity & window visibility should be identical
// for all displays in this stage.
mRootWindowContainer.executeAppTransitionForAllDisplay();
@@ -2042,7 +2042,7 @@
mRecentTasks.add(task);
mService.getTaskChangeNotificationController().notifyTaskStackChanged();
- rootTask.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
+ rootTask.ensureActivitiesVisible(null /* starting */);
// When launching tasks behind, update the last active time of the top task after the new
// task has been shown briefly
diff --git a/services/core/java/com/android/server/wm/BackNavigationController.java b/services/core/java/com/android/server/wm/BackNavigationController.java
index c3f1e41..22d17b5 100644
--- a/services/core/java/com/android/server/wm/BackNavigationController.java
+++ b/services/core/java/com/android/server/wm/BackNavigationController.java
@@ -1614,7 +1614,7 @@
"Setting Activity.mLauncherTaskBehind to true. Activity=%s", activity);
activity.mTaskSupervisor.mStoppingActivities.remove(activity);
activity.getDisplayContent().ensureActivitiesVisible(null /* starting */,
- 0 /* configChanges */, false /* preserveWindows */, true);
+ true /* notifyClients */);
}
private static void restoreLaunchBehind(@NonNull ActivityRecord activity) {
diff --git a/services/core/java/com/android/server/wm/ClientLifecycleManager.java b/services/core/java/com/android/server/wm/ClientLifecycleManager.java
index 2e47677..e4eb7b3 100644
--- a/services/core/java/com/android/server/wm/ClientLifecycleManager.java
+++ b/services/core/java/com/android/server/wm/ClientLifecycleManager.java
@@ -74,13 +74,13 @@
}
/**
- * Similar to {@link #scheduleTransactionItem}, but is called without WM lock.
+ * Similar to {@link #scheduleTransactionItem}, but it sends the transaction immediately and
+ * it can be called without WM lock.
*
* @see WindowProcessController#setReportedProcState(int)
*/
- void scheduleTransactionItemUnlocked(@NonNull IApplicationThread client,
+ void scheduleTransactionItemNow(@NonNull IApplicationThread client,
@NonNull ClientTransactionItem transactionItem) throws RemoteException {
- // Immediately dispatching to client, and must not access WMS.
final ClientTransaction clientTransaction = ClientTransaction.obtain(client);
if (transactionItem.isActivityLifecycleItem()) {
clientTransaction.setLifecycleStateRequest((ActivityLifecycleItem) transactionItem);
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index f8dc9c7..e7ecf52 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -779,7 +779,7 @@
/**
* Used to prevent recursions when calling
- * {@link #ensureActivitiesVisible(ActivityRecord, int, boolean, boolean)}
+ * {@link #ensureActivitiesVisible(ActivityRecord, boolean)}
*/
private boolean mInEnsureActivitiesVisible = false;
@@ -1713,7 +1713,7 @@
if (handled && requestingContainer instanceof ActivityRecord) {
final ActivityRecord activityRecord = (ActivityRecord) requestingContainer;
final boolean kept = updateDisplayOverrideConfigurationLocked(config, activityRecord,
- false /* deferResume */, null /* result */);
+ false /* deferResume */);
if (!kept) {
mRootWindowContainer.resumeFocusedTasksTopActivities();
}
@@ -1721,7 +1721,7 @@
// We have a new configuration to push so we need to update ATMS for now.
// TODO: Clean up display configuration push between ATMS and WMS after unification.
updateDisplayOverrideConfigurationLocked(config, null /* starting */,
- false /* deferResume */, null);
+ false /* deferResume */);
}
return handled;
}
@@ -6333,7 +6333,7 @@
Settings.System.clearConfiguration(values);
updateDisplayOverrideConfigurationLocked(values, null /* starting */,
- false /* deferResume */, mAtmService.mTmpUpdateConfigurationResult);
+ false /* deferResume */);
return mAtmService.mTmpUpdateConfigurationResult.changes != 0;
}
@@ -6342,8 +6342,7 @@
* new one will be computed in WM based on current display info.
*/
boolean updateDisplayOverrideConfigurationLocked(Configuration values,
- ActivityRecord starting, boolean deferResume,
- ActivityTaskManagerService.UpdateConfigurationResult result) {
+ ActivityRecord starting, boolean deferResume) {
int changes = 0;
boolean kept = true;
@@ -6361,19 +6360,19 @@
} else {
changes = performDisplayOverrideConfigUpdate(values);
}
+ mAtmService.mTmpUpdateConfigurationResult.changes = changes;
+ mAtmService.mTmpUpdateConfigurationResult.mIsUpdating = true;
}
if (!deferResume) {
kept = mAtmService.ensureConfigAndVisibilityAfterUpdate(starting, changes);
}
} finally {
+ mAtmService.mTmpUpdateConfigurationResult.mIsUpdating = false;
mAtmService.continueWindowLayout();
}
- if (result != null) {
- result.changes = changes;
- result.activityRelaunched = !kept;
- }
+ mAtmService.mTmpUpdateConfigurationResult.activityRelaunched = !kept;
return kept;
}
@@ -6569,8 +6568,7 @@
}
- void ensureActivitiesVisible(ActivityRecord starting, int configChanges,
- boolean preserveWindows, boolean notifyClients) {
+ void ensureActivitiesVisible(ActivityRecord starting, boolean notifyClients) {
if (mInEnsureActivitiesVisible) {
// Don't do recursive work.
return;
@@ -6579,8 +6577,7 @@
try {
mInEnsureActivitiesVisible = true;
forAllRootTasks(rootTask -> {
- rootTask.ensureActivitiesVisible(starting, configChanges, preserveWindows,
- notifyClients);
+ rootTask.ensureActivitiesVisible(starting, notifyClients);
});
if (mTransitionController.useShellTransitionsRotation()
&& mTransitionController.isCollecting()
@@ -6619,7 +6616,7 @@
if (!wasTransitionSet) {
prepareAppTransition(TRANSIT_NONE);
}
- mRootWindowContainer.ensureActivitiesVisible(null, 0, false /* preserveWindows */);
+ mRootWindowContainer.ensureActivitiesVisible();
// If there was a transition set already we don't want to interfere with it as we might be
// starting it too early.
diff --git a/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java b/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java
index 9cc311d..f40eb24 100644
--- a/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java
+++ b/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java
@@ -33,8 +33,6 @@
private boolean mAboveTop;
private boolean mContainerShouldBeVisible;
private boolean mBehindFullyOccludedContainer;
- private int mConfigChanges;
- private boolean mPreserveWindows;
private boolean mNotifyClients;
EnsureActivitiesVisibleHelper(TaskFragment container) {
@@ -45,14 +43,10 @@
* Update all attributes except {@link mTaskFragment} to use in subsequent calculations.
*
* @param starting The activity that is being started
- * @param configChanges Parts of the configuration that changed for this activity for evaluating
- * if the screen should be frozen.
- * @param preserveWindows Flag indicating whether windows should be preserved when updating.
* @param notifyClients Flag indicating whether the configuration and visibility changes shoulc
* be sent to the clients.
*/
- void reset(ActivityRecord starting, int configChanges, boolean preserveWindows,
- boolean notifyClients) {
+ void reset(ActivityRecord starting, boolean notifyClients) {
mStarting = starting;
mTopRunningActivity = mTaskFragment.topRunningActivity();
// If the top activity is not fullscreen, then we need to make sure any activities under it
@@ -60,33 +54,26 @@
mAboveTop = mTopRunningActivity != null;
mContainerShouldBeVisible = mTaskFragment.shouldBeVisible(mStarting);
mBehindFullyOccludedContainer = !mContainerShouldBeVisible;
- mConfigChanges = configChanges;
- mPreserveWindows = preserveWindows;
mNotifyClients = notifyClients;
}
/**
* Update and commit visibility with an option to also update the configuration of visible
* activities.
- * @see Task#ensureActivitiesVisible(ActivityRecord, int, boolean)
- * @see RootWindowContainer#ensureActivitiesVisible(ActivityRecord, int, boolean)
+ * @see Task#ensureActivitiesVisible(ActivityRecord)
+ * @see RootWindowContainer#ensureActivitiesVisible()
* @param starting The top most activity in the task.
* The activity is either starting or resuming.
* Caller should ensure starting activity is visible.
*
- * @param configChanges Parts of the configuration that changed for this activity for evaluating
- * if the screen should be frozen.
- * @param preserveWindows Flag indicating whether windows should be preserved when updating.
* @param notifyClients Flag indicating whether the configuration and visibility changes shoulc
* be sent to the clients.
*/
- void process(@Nullable ActivityRecord starting, int configChanges, boolean preserveWindows,
- boolean notifyClients) {
- reset(starting, configChanges, preserveWindows, notifyClients);
+ void process(@Nullable ActivityRecord starting, boolean notifyClients) {
+ reset(starting, notifyClients);
if (DEBUG_VISIBILITY) {
- Slog.v(TAG_VISIBILITY, "ensureActivitiesVisible behind " + mTopRunningActivity
- + " configChanges=0x" + Integer.toHexString(configChanges));
+ Slog.v(TAG_VISIBILITY, "ensureActivitiesVisible behind " + mTopRunningActivity);
}
if (mTopRunningActivity != null && mTaskFragment.asTask() != null) {
// TODO(14709632): Check if this needed to be implemented in TaskFragment.
@@ -107,8 +94,7 @@
final TaskFragment childTaskFragment = child.asTaskFragment();
if (childTaskFragment != null
&& childTaskFragment.getTopNonFinishingActivity() != null) {
- childTaskFragment.updateActivityVisibilities(starting, configChanges,
- preserveWindows, notifyClients);
+ childTaskFragment.updateActivityVisibilities(starting, notifyClients);
// The TaskFragment should fully occlude the activities below if the bounds
// equals to its parent task, unless it is translucent.
mBehindFullyOccludedContainer |=
@@ -188,13 +174,11 @@
// First: if this is not the current activity being started, make
// sure it matches the current configuration.
if (r != mStarting && mNotifyClients) {
- r.ensureActivityConfiguration(0 /* globalChanges */, mPreserveWindows,
- true /* ignoreVisibility */);
+ r.ensureActivityConfiguration(true /* ignoreVisibility */);
}
if (!r.attachedToProcess()) {
- makeVisibleAndRestartIfNeeded(mStarting, mConfigChanges,
- resumeTopActivity && isTop, r);
+ makeVisibleAndRestartIfNeeded(mStarting, resumeTopActivity && isTop, r);
} else if (r.isVisibleRequested()) {
// If this activity is already visible, then there is nothing to do here.
if (DEBUG_VISIBILITY) {
@@ -213,8 +197,6 @@
} else {
r.makeVisibleIfNeeded(mStarting, mNotifyClients);
}
- // Aggregate current change flags.
- mConfigChanges |= r.configChangeFlags;
} else {
if (DEBUG_VISIBILITY) {
Slog.v(TAG_VISIBILITY, "Make invisible? " + r
@@ -242,16 +224,13 @@
}
}
- private void makeVisibleAndRestartIfNeeded(ActivityRecord starting, int configChanges,
+ private void makeVisibleAndRestartIfNeeded(ActivityRecord starting,
boolean andResume, ActivityRecord r) {
// This activity needs to be visible, but isn't even running...
// get it started and resume if no other root task in this root task is resumed.
if (DEBUG_VISIBILITY) {
Slog.v(TAG_VISIBILITY, "Start and freeze screen for " + r);
}
- if (r != starting) {
- r.startFreezingScreenLocked(configChanges);
- }
if (!r.isVisibleRequested() || r.mLaunchTaskBehind) {
if (DEBUG_VISIBILITY) {
Slog.v(TAG_VISIBILITY, "Starting and making visible: " + r);
diff --git a/services/core/java/com/android/server/wm/KeyguardController.java b/services/core/java/com/android/server/wm/KeyguardController.java
index cbc7b83..6d11804 100644
--- a/services/core/java/com/android/server/wm/KeyguardController.java
+++ b/services/core/java/com/android/server/wm/KeyguardController.java
@@ -43,7 +43,6 @@
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
-import static com.android.server.wm.ActivityTaskSupervisor.PRESERVE_WINDOWS;
import static com.android.server.wm.KeyguardControllerProto.AOD_SHOWING;
import static com.android.server.wm.KeyguardControllerProto.KEYGUARD_GOING_AWAY;
import static com.android.server.wm.KeyguardControllerProto.KEYGUARD_PER_DISPLAY;
@@ -239,7 +238,7 @@
// Update the sleep token first such that ensureActivitiesVisible has correct sleep token
// state when evaluating visibilities.
updateKeyguardSleepToken();
- mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
+ mRootWindowContainer.ensureActivitiesVisible();
InputMethodManagerInternal.get().updateImeWindowStatus(false /* disableImeIcon */,
displayId);
setWakeTransitionReady();
@@ -291,7 +290,7 @@
// Some stack visibility might change (e.g. docked stack)
mRootWindowContainer.resumeFocusedTasksTopActivities();
- mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
+ mRootWindowContainer.ensureActivitiesVisible();
mRootWindowContainer.addStartingWindowsForVisibleActivities();
mWindowManager.executeAppTransition();
} finally {
diff --git a/services/core/java/com/android/server/wm/RecentsAnimation.java b/services/core/java/com/android/server/wm/RecentsAnimation.java
index 5269d35..7b23004 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimation.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimation.java
@@ -28,7 +28,6 @@
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_RECENTS_ANIMATIONS;
import static com.android.server.wm.ActivityRecord.State.STOPPED;
import static com.android.server.wm.ActivityRecord.State.STOPPING;
-import static com.android.server.wm.ActivityTaskSupervisor.PRESERVE_WINDOWS;
import static com.android.server.wm.RecentsAnimationController.REORDER_KEEP_IN_PLACE;
import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_TO_ORIGINAL_POSITION;
import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_TO_TOP;
@@ -126,8 +125,7 @@
// The activity may be relaunched if it cannot handle the current configuration
// changes. The activity will be paused state if it is relaunched, otherwise it
// keeps the original stopped state.
- targetActivity.ensureActivityConfiguration(0 /* globalChanges */,
- false /* preserveWindow */, true /* ignoreVisibility */);
+ targetActivity.ensureActivityConfiguration(true /* ignoreVisibility */);
ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS, "Updated config=%s",
targetActivity.getConfiguration());
}
@@ -261,7 +259,7 @@
// If we updated the launch-behind state, update the visibility of the activities after
// we fetch the visible tasks to be controlled by the animation
- mService.mRootWindowContainer.ensureActivitiesVisible(null, 0, PRESERVE_WINDOWS);
+ mService.mRootWindowContainer.ensureActivitiesVisible();
ActivityOptions options = null;
if (eventTime > 0) {
@@ -380,8 +378,7 @@
// transition (the target activity will be one of closing apps).
if (!controller.shouldDeferCancelWithScreenshot()
&& !targetRootTask.isFocusedRootTaskOnDisplay()) {
- targetRootTask.ensureActivitiesVisible(null /* starting */,
- 0 /* starting */, false /* preserveWindows */);
+ targetRootTask.ensureActivitiesVisible(null /* starting */);
}
// Keep target root task in place, nothing changes, so ignore the transition
// logic below
@@ -389,7 +386,7 @@
}
mWindowManager.prepareAppTransitionNone();
- mService.mRootWindowContainer.ensureActivitiesVisible(null, 0, false);
+ mService.mRootWindowContainer.ensureActivitiesVisible();
mService.mRootWindowContainer.resumeFocusedTasksTopActivities();
// No reason to wait for the pausing activity in this case, as the hiding of
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 9a75dae..ca66a66 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -63,7 +63,6 @@
import static com.android.server.wm.ActivityTaskManagerService.isPip2ExperimentEnabled;
import static com.android.server.wm.ActivityTaskSupervisor.DEFER_RESUME;
import static com.android.server.wm.ActivityTaskSupervisor.ON_TOP;
-import static com.android.server.wm.ActivityTaskSupervisor.PRESERVE_WINDOWS;
import static com.android.server.wm.ActivityTaskSupervisor.dumpHistoryList;
import static com.android.server.wm.ActivityTaskSupervisor.printThisActivity;
import static com.android.server.wm.KeyguardController.KEYGUARD_SLEEP_TOKEN_TAG;
@@ -1753,8 +1752,7 @@
// activities are affecting configuration now.
// Passing null here for 'starting' param value, so that visibility of actual starting
// activity will be properly updated.
- ensureActivitiesVisible(null /* starting */, 0 /* configChanges */,
- false /* preserveWindows */, false /* notifyClients */);
+ ensureActivitiesVisible(null /* starting */, false /* notifyClients */);
if (displayId == INVALID_DISPLAY) {
// The caller didn't provide a valid display id, skip updating config.
@@ -1778,7 +1776,7 @@
if (displayContent != null) {
// Update the configuration of the activities on the display.
return displayContent.updateDisplayOverrideConfigurationLocked(config, starting,
- deferResume, null /* result */);
+ deferResume);
} else {
return true;
}
@@ -1865,16 +1863,18 @@
* Make sure that all activities that need to be visible in the system actually are and update
* their configuration.
*/
- void ensureActivitiesVisible(ActivityRecord starting, int configChanges,
- boolean preserveWindows) {
- ensureActivitiesVisible(starting, configChanges, preserveWindows, true /* notifyClients */);
+ void ensureActivitiesVisible() {
+ ensureActivitiesVisible(null /* starting */);
+ }
+
+ void ensureActivitiesVisible(ActivityRecord starting) {
+ ensureActivitiesVisible(starting, true /* notifyClients */);
}
/**
- * @see #ensureActivitiesVisible(ActivityRecord, int, boolean)
+ * @see #ensureActivitiesVisible()
*/
- void ensureActivitiesVisible(ActivityRecord starting, int configChanges,
- boolean preserveWindows, boolean notifyClients) {
+ void ensureActivitiesVisible(ActivityRecord starting, boolean notifyClients) {
if (mTaskSupervisor.inActivityVisibilityUpdate()
|| mTaskSupervisor.isRootVisibilityUpdateDeferred()) {
// Don't do recursive work.
@@ -1885,8 +1885,7 @@
// First the front root tasks. In case any are not fullscreen and are in front of home.
for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
final DisplayContent display = getChildAt(displayNdx);
- display.ensureActivitiesVisible(starting, configChanges, preserveWindows,
- notifyClients);
+ display.ensureActivitiesVisible(starting, notifyClients);
}
} finally {
mTaskSupervisor.endActivityVisibilityUpdate();
@@ -2237,7 +2236,7 @@
try {
if (localVisibilityDeferred) {
mTaskSupervisor.setDeferRootVisibilityUpdate(false);
- ensureActivitiesVisible(null, 0, false /* preserveWindows */);
+ ensureActivitiesVisible();
}
} finally {
transitionController.continueTransitionReady();
@@ -2370,7 +2369,7 @@
// It may be nothing to resume because there are pausing activities or all the top
// activities are resumed. Then it still needs to make sure all visible activities are
// running in case the tasks were reordered or there are non-top visible activities.
- ensureActivitiesVisible(null /* starting */, 0 /* configChanges */, !PRESERVE_WINDOWS);
+ ensureActivitiesVisible();
}
}
@@ -2542,8 +2541,7 @@
// display orientation can be updated first if needed. Otherwise there may
// have redundant configuration changes due to apply outdated display
// orientation (from keyguard) to activity.
- rootTask.ensureActivitiesVisible(null /* starting */, 0 /* configChanges */,
- false /* preserveWindows */);
+ rootTask.ensureActivitiesVisible(null /* starting */);
}
});
}
@@ -2885,8 +2883,7 @@
if (allowDelay) {
result[0] &= task.goToSleepIfPossible(shuttingDown);
} else {
- task.ensureActivitiesVisible(null /* starting */, 0 /* configChanges */,
- !PRESERVE_WINDOWS);
+ task.ensureActivitiesVisible(null /* starting */);
}
});
return result[0];
@@ -3774,8 +3771,7 @@
}
}
if (!mHasActivityStarted) {
- ensureActivitiesVisible(null /* starting */, 0 /* configChanges */,
- false /* preserveWindows */);
+ ensureActivitiesVisible();
}
return mHasActivityStarted;
}
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index 7995028..ed54ea8 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -771,6 +771,7 @@
if (mLastReportedAnimatorScale != mService.getCurrentAnimatorScale()) {
mService.dispatchNewAnimatorScaleLocked(this);
}
+ mProcess.mWindowSession = this;
}
mAddedWindows.add(w);
}
@@ -782,6 +783,9 @@
}
}
+ boolean hasWindow() {
+ return !mAddedWindows.isEmpty();
+ }
void onWindowSurfaceVisibilityChanged(WindowSurfaceController surfaceController,
boolean visible, int type) {
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index dbfcc22..c674176 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -90,7 +90,6 @@
import static com.android.server.wm.ActivityTaskManagerService.H.FIRST_ACTIVITY_TASK_MSG;
import static com.android.server.wm.ActivityTaskSupervisor.DEFER_RESUME;
import static com.android.server.wm.ActivityTaskSupervisor.ON_TOP;
-import static com.android.server.wm.ActivityTaskSupervisor.PRESERVE_WINDOWS;
import static com.android.server.wm.ActivityTaskSupervisor.REMOVE_FROM_RECENTS;
import static com.android.server.wm.ActivityTaskSupervisor.printThisActivity;
import static com.android.server.wm.IdentifierProto.HASH_CODE;
@@ -760,7 +759,7 @@
return;
}
mResizeMode = resizeMode;
- mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
+ mRootWindowContainer.ensureActivitiesVisible();
mRootWindowContainer.resumeFocusedTasksTopActivities();
updateTaskDescription();
}
@@ -801,15 +800,14 @@
if (setBounds(bounds, forced) != BOUNDS_CHANGE_NONE) {
final ActivityRecord r = topRunningActivityLocked();
if (r != null) {
- kept = r.ensureActivityConfiguration(0 /* globalChanges */,
- preserveWindow);
+ kept = r.ensureActivityConfiguration();
// Preserve other windows for resizing because if resizing happens when there
// is a dialog activity in the front, the activity that still shows some
// content to the user will become black and cause flickers. Note in most cases
// this won't cause tons of irrelevant windows being preserved because only
// activities in this task may experience a bounds change. Configs for other
// activities stay the same.
- mRootWindowContainer.ensureActivitiesVisible(r, 0, preserveWindow);
+ mRootWindowContainer.ensureActivitiesVisible(r);
if (!kept) {
mRootWindowContainer.resumeFocusedTasksTopActivities();
}
@@ -915,7 +913,7 @@
if (!deferResume) {
// The task might have already been running and its visibility needs to be synchronized
// with the visibility of the root task / windows.
- root.ensureActivitiesVisible(null, 0, PRESERVE_WINDOWS);
+ root.ensureActivitiesVisible();
root.resumeFocusedTasksTopActivities();
}
@@ -4752,7 +4750,7 @@
}
if (!mTaskSupervisor.isRootVisibilityUpdateDeferred()) {
- mRootWindowContainer.ensureActivitiesVisible(null, 0, PRESERVE_WINDOWS);
+ mRootWindowContainer.ensureActivitiesVisible();
mRootWindowContainer.resumeFocusedTasksTopActivities();
}
}
@@ -4793,8 +4791,7 @@
mRootWindowContainer.resumeFocusedTasksTopActivities();
// Update visibility of activities before notifying WM. This way it won't try to resize
// windows that are no longer visible.
- mRootWindowContainer.ensureActivitiesVisible(null /* starting */, 0 /* configChanges */,
- !PRESERVE_WINDOWS);
+ mRootWindowContainer.ensureActivitiesVisible();
}
final boolean isOnHomeDisplay() {
@@ -4938,41 +4935,27 @@
* @param starting The top most activity in the task.
* The activity is either starting or resuming.
* Caller should ensure starting activity is visible.
- * @param preserveWindows Flag indicating whether windows should be preserved when updating
- * configuration in {@link EnsureActivitiesVisibleHelper}.
- * @param configChanges Parts of the configuration that changed for this activity for evaluating
- * if the screen should be frozen as part of
- * {@link EnsureActivitiesVisibleHelper}.
- *
*/
- void ensureActivitiesVisible(@Nullable ActivityRecord starting, int configChanges,
- boolean preserveWindows) {
- ensureActivitiesVisible(starting, configChanges, preserveWindows, true /* notifyClients */);
+ void ensureActivitiesVisible(@Nullable ActivityRecord starting) {
+ ensureActivitiesVisible(starting, true /* notifyClients */);
}
/**
* Ensure visibility with an option to also update the configuration of visible activities.
- * @see #ensureActivitiesVisible(ActivityRecord, int, boolean)
- * @see RootWindowContainer#ensureActivitiesVisible(ActivityRecord, int, boolean)
+ * @see #ensureActivitiesVisible(ActivityRecord)
+ * @see RootWindowContainer#ensureActivitiesVisible()
* @param starting The top most activity in the task.
* The activity is either starting or resuming.
* Caller should ensure starting activity is visible.
* @param notifyClients Flag indicating whether the visibility updates should be sent to the
* clients in {@link EnsureActivitiesVisibleHelper}.
- * @param preserveWindows Flag indicating whether windows should be preserved when updating
- * configuration in {@link EnsureActivitiesVisibleHelper}.
- * @param configChanges Parts of the configuration that changed for this activity for evaluating
- * if the screen should be frozen as part of
- * {@link EnsureActivitiesVisibleHelper}.
*/
// TODO: Should be re-worked based on the fact that each task as a root task in most cases.
- void ensureActivitiesVisible(@Nullable ActivityRecord starting, int configChanges,
- boolean preserveWindows, boolean notifyClients) {
+ void ensureActivitiesVisible(@Nullable ActivityRecord starting, boolean notifyClients) {
mTaskSupervisor.beginActivityVisibilityUpdate();
try {
forAllLeafTasks(task -> {
- task.updateActivityVisibilities(starting, configChanges, preserveWindows,
- notifyClients);
+ task.updateActivityVisibilities(starting, notifyClients);
}, true /* traverseTopToBottom */);
if (mTranslucentActivityWaiting != null &&
@@ -5273,7 +5256,7 @@
// tell WindowManager that r is visible even though it is at the back of the root
// task.
r.setVisibility(true);
- ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
+ ensureActivitiesVisible(null /* starting */);
// If launching behind, the app will start regardless of what's above it, so mark it
// as unknown even before prior `pause`. This also prevents a race between set-ready
// and activityPause. Launch-behind is basically only used for dream now.
diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java
index c57983c..90a3b253 100644
--- a/services/core/java/com/android/server/wm/TaskDisplayArea.java
+++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java
@@ -1777,13 +1777,11 @@
void onRootTaskOrderChanged(Task rootTask);
}
- void ensureActivitiesVisible(ActivityRecord starting, int configChanges,
- boolean preserveWindows, boolean notifyClients) {
+ void ensureActivitiesVisible(ActivityRecord starting, boolean notifyClients) {
mAtmService.mTaskSupervisor.beginActivityVisibilityUpdate();
try {
forAllRootTasks(rootTask -> {
- rootTask.ensureActivitiesVisible(starting, configChanges, preserveWindows,
- notifyClients);
+ rootTask.ensureActivitiesVisible(starting, notifyClients);
});
} finally {
mAtmService.mTaskSupervisor.endActivityVisibilityUpdate();
diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java
index 5d01912..d425bdf 100644
--- a/services/core/java/com/android/server/wm/TaskFragment.java
+++ b/services/core/java/com/android/server/wm/TaskFragment.java
@@ -57,7 +57,6 @@
import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_TRANSITION;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
-import static com.android.server.wm.ActivityTaskSupervisor.PRESERVE_WINDOWS;
import static com.android.server.wm.ActivityTaskSupervisor.printThisActivity;
import static com.android.server.wm.IdentifierProto.HASH_CODE;
import static com.android.server.wm.IdentifierProto.TITLE;
@@ -950,8 +949,7 @@
}
if (shouldSleep) {
- updateActivityVisibilities(null /* starting */, 0 /* configChanges */,
- !PRESERVE_WINDOWS, true /* notifyClients */);
+ updateActivityVisibilities(null /* starting */, true /* notifyClients */);
}
return shouldSleep;
@@ -1218,12 +1216,11 @@
return top != null && top.mLaunchTaskBehind;
}
- final void updateActivityVisibilities(@Nullable ActivityRecord starting, int configChanges,
- boolean preserveWindows, boolean notifyClients) {
+ final void updateActivityVisibilities(@Nullable ActivityRecord starting,
+ boolean notifyClients) {
mTaskSupervisor.beginActivityVisibilityUpdate();
try {
- mEnsureActivitiesVisibleHelper.process(
- starting, configChanges, preserveWindows, notifyClients);
+ mEnsureActivitiesVisibleHelper.process(starting, notifyClients);
} finally {
mTaskSupervisor.endActivityVisibilityUpdate();
}
@@ -1249,8 +1246,7 @@
if (mResumedActivity == next && next.isState(RESUMED)
&& taskDisplayArea.allResumedActivitiesComplete()) {
// Ensure the visibility gets updated before execute app transition.
- taskDisplayArea.ensureActivitiesVisible(null /* starting */, 0 /* configChanges */,
- false /* preserveWindows */, true /* notifyClients */);
+ taskDisplayArea.ensureActivitiesVisible(null /* starting */, true /* notifyClients */);
// Make sure we have executed any pending transitions, since there
// should be nothing left to do at this point.
executeAppTransition(options);
@@ -1907,7 +1903,7 @@
prev.resumeKeyDispatchingLocked();
}
- mRootWindowContainer.ensureActivitiesVisible(resuming, 0, !PRESERVE_WINDOWS);
+ mRootWindowContainer.ensureActivitiesVisible(resuming);
// Notify when the task stack has changed, but only if visibilities changed (not just
// focus). Also if there is an active root pinned task - we always want to notify it about
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index 3117db5..b12855e 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -1136,8 +1136,7 @@
// The transient hide tasks could be occluded now, e.g. returning to home. So trigger
// the update to make the activities in the tasks invisible-requested, then the next
// step can continue to commit the visibility.
- mController.mAtm.mRootWindowContainer.ensureActivitiesVisible(null /* starting */,
- 0 /* configChanges */, true /* preserveWindows */);
+ mController.mAtm.mRootWindowContainer.ensureActivitiesVisible();
// Record all the now-hiding activities so that they are committed. Just use
// mParticipants because we can avoid a new list this way.
for (int i = 0; i < mTransientHideTasks.size(); ++i) {
@@ -2863,8 +2862,7 @@
* check whether to deliver the new configuration to clients.
*/
@Nullable
- ArrayList<ActivityRecord> applyDisplayChangeIfNeeded() {
- ArrayList<ActivityRecord> activitiesMayChange = null;
+ void applyDisplayChangeIfNeeded(@NonNull ArraySet<WindowContainer<?>> activitiesMayChange) {
for (int i = mParticipants.size() - 1; i >= 0; --i) {
final WindowContainer<?> wc = mParticipants.valueAt(i);
final DisplayContent dc = wc.asDisplayContent();
@@ -2881,18 +2879,13 @@
// If the update is deferred, sendNewConfiguration won't deliver new configuration to
// clients, then it is the caller's responsibility to deliver the changes.
if (mController.mAtm.mTaskSupervisor.isRootVisibilityUpdateDeferred()) {
- if (activitiesMayChange == null) {
- activitiesMayChange = new ArrayList<>();
- }
- final ArrayList<ActivityRecord> visibleActivities = activitiesMayChange;
dc.forAllActivities(r -> {
if (r.isVisibleRequested()) {
- visibleActivities.add(r);
+ activitiesMayChange.add(r);
}
});
}
}
- return activitiesMayChange;
}
boolean getLegacyIsReady() {
diff --git a/services/core/java/com/android/server/wm/WindowManagerFlags.java b/services/core/java/com/android/server/wm/WindowManagerFlags.java
index 89a70e5..7b0d931 100644
--- a/services/core/java/com/android/server/wm/WindowManagerFlags.java
+++ b/services/core/java/com/android/server/wm/WindowManagerFlags.java
@@ -43,8 +43,6 @@
/* Start Available Flags */
- final boolean mWindowStateResizeItemFlag = Flags.windowStateResizeItemFlag();
-
final boolean mWallpaperOffsetAsync = Flags.wallpaperOffsetAsync();
final boolean mAllowsScreenSizeDecoupledFromStatusBarAndCutout =
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index c1310a6..dda33f3 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -3105,7 +3105,7 @@
try {
synchronized (mGlobalLock) {
if (mAtmService.mKeyguardController.isKeyguardShowing(DEFAULT_DISPLAY)) {
- mRoot.ensureActivitiesVisible(null, 0, false /* preserveWindows */);
+ mRoot.ensureActivitiesVisible();
}
}
} finally {
diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java
index 4b99432..9e4a31c 100644
--- a/services/core/java/com/android/server/wm/WindowOrganizerController.java
+++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java
@@ -65,7 +65,6 @@
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WINDOW_ORGANIZER;
import static com.android.server.wm.ActivityRecord.State.PAUSING;
import static com.android.server.wm.ActivityTaskManagerService.enforceTaskPermission;
-import static com.android.server.wm.ActivityTaskSupervisor.PRESERVE_WINDOWS;
import static com.android.server.wm.ActivityTaskSupervisor.REMOVE_FROM_RECENTS;
import static com.android.server.wm.Task.FLAG_FORCE_HIDDEN_FOR_PINNED_TASK;
import static com.android.server.wm.Task.FLAG_FORCE_HIDDEN_FOR_TASK_ORG;
@@ -571,14 +570,15 @@
mService.deferWindowLayout();
mService.mTaskSupervisor.setDeferRootVisibilityUpdate(true /* deferUpdate */);
try {
- final ArrayList<ActivityRecord> activitiesMayChange =
- transition != null ? transition.applyDisplayChangeIfNeeded() : null;
- if (activitiesMayChange != null) {
- effects |= TRANSACT_EFFECTS_CLIENT_CONFIG;
+ final ArraySet<WindowContainer<?>> haveConfigChanges = new ArraySet<>();
+ if (transition != null) {
+ transition.applyDisplayChangeIfNeeded(haveConfigChanges);
+ if (!haveConfigChanges.isEmpty()) {
+ effects |= TRANSACT_EFFECTS_CLIENT_CONFIG;
+ }
}
final List<WindowContainerTransaction.HierarchyOp> hops = t.getHierarchyOps();
final int hopSize = hops.size();
- final ArraySet<WindowContainer<?>> haveConfigChanges = new ArraySet<>();
Iterator<Map.Entry<IBinder, WindowContainerTransaction.Change>> entries =
t.getChanges().entrySet().iterator();
while (entries.hasNext()) {
@@ -626,7 +626,7 @@
// When removing pip, make sure that onStop is sent to the app ahead of
// onPictureInPictureModeChanged.
// See also PinnedStackTests#testStopBeforeMultiWindowCallbacksOnDismiss
- wc.asTask().ensureActivitiesVisible(null, 0, PRESERVE_WINDOWS);
+ wc.asTask().ensureActivitiesVisible(null /* starting */);
wc.asTask().mTaskSupervisor.processStoppingAndFinishingActivities(
null /* launchedActivity */, false /* processPausingActivities */,
"force-stop-on-removing-pip");
@@ -692,29 +692,16 @@
if ((effects & TRANSACT_EFFECTS_LIFECYCLE) != 0) {
mService.mTaskSupervisor.setDeferRootVisibilityUpdate(false /* deferUpdate */);
// Already calls ensureActivityConfig
- mService.mRootWindowContainer.ensureActivitiesVisible(null, 0, PRESERVE_WINDOWS);
+ mService.mRootWindowContainer.ensureActivitiesVisible();
mService.mRootWindowContainer.resumeFocusedTasksTopActivities();
} else if ((effects & TRANSACT_EFFECTS_CLIENT_CONFIG) != 0) {
for (int i = haveConfigChanges.size() - 1; i >= 0; --i) {
haveConfigChanges.valueAt(i).forAllActivities(r -> {
- r.ensureActivityConfiguration(0, PRESERVE_WINDOWS);
- if (activitiesMayChange != null) {
- activitiesMayChange.remove(r);
+ if (r.isVisibleRequested()) {
+ r.ensureActivityConfiguration(true /* ignoreVisibility */);
}
});
}
- // TODO(b/258618073): Combine with haveConfigChanges after confirming that there
- // is no problem to always preserve window. Currently this uses the parameters
- // as ATMS#ensureConfigAndVisibilityAfterUpdate.
- if (activitiesMayChange != null) {
- for (int i = activitiesMayChange.size() - 1; i >= 0; --i) {
- final ActivityRecord ar = activitiesMayChange.get(i);
- if (!ar.isVisibleRequested()) continue;
- ar.ensureActivityConfiguration(0 /* globalChanges */,
- !PRESERVE_WINDOWS, true /* ignoreVisibility */,
- false /* isRequestedOrientationChanged */);
- }
- }
}
if (effects != 0) {
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index 5721750..b8fa5e5 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -188,6 +188,10 @@
// Set to true when process was launched with a wrapper attached
private volatile boolean mUsingWrapper;
+ /** Non-null if this process may have a window. */
+ @Nullable
+ Session mWindowSession;
+
// Thread currently set for VR scheduling
int mVrThreadTid;
@@ -399,7 +403,7 @@
// the latest configuration in their lifecycle callbacks (e.g. onReceive, onCreate).
try {
// No WM lock here.
- mAtm.getLifecycleManager().scheduleTransactionItemUnlocked(
+ mAtm.getLifecycleManager().scheduleTransactionItemNow(
thread, configurationChangeItem);
} catch (Exception e) {
Slog.e(TAG_CONFIGURATION, "Failed to schedule ConfigurationChangeItem="
@@ -989,7 +993,7 @@
if (packageName.equals(r.packageName)
&& r.applyAppSpecificConfig(nightMode, localesOverride, gender)
&& r.isVisibleRequested()) {
- r.ensureActivityConfiguration(0 /* globalChanges */, true /* preserveWindow */);
+ r.ensureActivityConfiguration();
}
}
}
@@ -1675,7 +1679,12 @@
private void scheduleClientTransactionItem(@NonNull IApplicationThread thread,
@NonNull ClientTransactionItem transactionItem) {
try {
- mAtm.getLifecycleManager().scheduleTransactionItem(thread, transactionItem);
+ if (mWindowSession != null && mWindowSession.hasWindow()) {
+ mAtm.getLifecycleManager().scheduleTransactionItem(thread, transactionItem);
+ } else {
+ // Non-UI process can handle the change directly.
+ mAtm.getLifecycleManager().scheduleTransactionItemNow(thread, transactionItem);
+ }
} catch (DeadObjectException e) {
// Expected if the process has been killed.
Slog.w(TAG_CONFIGURATION, "Failed for dead process. ClientTransactionItem="
@@ -1723,7 +1732,7 @@
overrideConfig.assetsSeq = assetSeq;
r.onRequestedOverrideConfigurationChanged(overrideConfig);
if (r.isVisibleRequested()) {
- r.ensureActivityConfiguration(0, true);
+ r.ensureActivityConfiguration();
}
}
}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 32638e0..58ade1b 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -252,6 +252,7 @@
import com.android.server.wm.LocalAnimationAdapter.AnimationSpec;
import com.android.server.wm.RefreshRatePolicy.FrameRateVote;
import com.android.server.wm.SurfaceAnimator.AnimationType;
+import com.android.window.flags.Flags;
import dalvik.annotation.optimization.NeverCompile;
@@ -3675,7 +3676,7 @@
markRedrawForSyncReported();
- if (mWmService.mFlags.mWindowStateResizeItemFlag) {
+ if (Flags.bundleClientTransactionFlag()) {
getProcess().scheduleClientTransactionItem(
WindowStateResizeItem.obtain(mClient, mClientWindowFrames, reportDraw,
mLastReportedConfiguration, getCompatInsetsState(), forceRelayout,
diff --git a/services/credentials/java/com/android/server/credentials/CredentialManagerService.java b/services/credentials/java/com/android/server/credentials/CredentialManagerService.java
index 4a2e1cb..686b2a8 100644
--- a/services/credentials/java/com/android/server/credentials/CredentialManagerService.java
+++ b/services/credentials/java/com/android/server/credentials/CredentialManagerService.java
@@ -65,7 +65,6 @@
import android.util.SparseArray;
import com.android.internal.annotations.GuardedBy;
-import com.android.internal.content.PackageMonitor;
import com.android.server.credentials.metrics.ApiName;
import com.android.server.credentials.metrics.ApiStatus;
import com.android.server.infra.AbstractMasterSystemService;
@@ -1204,6 +1203,9 @@
// If the app being removed matches any of the package names from
// this list then don't add it in the output.
Set<String> providers = new HashSet<>();
+ if (rawProviders == null || packageName == null) {
+ return providers;
+ }
for (String rawComponentName : rawProviders.split(":")) {
if (TextUtils.isEmpty(rawComponentName)
|| rawComponentName.equals("null")) {
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/PackageMonitorCallbackHelperTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/PackageMonitorCallbackHelperTest.java
index 6c44fd0..60cedcf 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/PackageMonitorCallbackHelperTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/PackageMonitorCallbackHelperTest.java
@@ -44,6 +44,7 @@
import org.mockito.ArgumentCaptor;
import java.util.ArrayList;
+import java.util.function.BiFunction;
/**
* A unit test for PackageMonitorCallbackHelper implementation.
@@ -78,7 +79,8 @@
mPackageMonitorCallbackHelper.notifyPackageMonitor(Intent.ACTION_PACKAGE_ADDED,
FAKE_PACKAGE_NAME, createFakeBundle(), new int[]{0} /* userIds */,
- null /* instantUserIds */, null /* broadcastAllowList */, mHandler);
+ null /* instantUserIds */, null /* broadcastAllowList */, mHandler,
+ null /* filterExtras */);
verify(callback, after(WAIT_CALLBACK_CALLED_IN_MS).never()).sendResult(any());
}
@@ -91,7 +93,7 @@
Binder.getCallingUid());
mPackageMonitorCallbackHelper.notifyPackageMonitor(Intent.ACTION_PACKAGE_ADDED,
FAKE_PACKAGE_NAME, createFakeBundle(), new int[]{0}, null /* instantUserIds */,
- null /* broadcastAllowList */, mHandler);
+ null /* broadcastAllowList */, mHandler, null /* filterExtras */);
verify(callback, after(WAIT_CALLBACK_CALLED_IN_MS).times(1)).sendResult(any());
@@ -99,12 +101,41 @@
mPackageMonitorCallbackHelper.unregisterPackageMonitorCallback(callback);
mPackageMonitorCallbackHelper.notifyPackageMonitor(Intent.ACTION_PACKAGE_ADDED,
FAKE_PACKAGE_NAME, createFakeBundle(), new int[]{0} /* userIds */,
- null /* instantUserIds */, null /* broadcastAllowList */, mHandler);
+ null /* instantUserIds */, null /* broadcastAllowList */, mHandler,
+ null /* filterExtras */);
verify(callback, after(WAIT_CALLBACK_CALLED_IN_MS).never()).sendResult(any());
}
@Test
+ public void testPackageMonitorCallback_SuspendCallbackCalled() throws Exception {
+ Bundle result = new Bundle();
+ result.putInt(Intent.EXTRA_UID, FAKE_PACKAGE_UID);
+ result.putStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST, new String[]{FAKE_PACKAGE_NAME});
+ BiFunction<Integer, Bundle, Bundle> filterExtras = (callingUid, intentExtras) -> result;
+
+ IRemoteCallback callback = createMockPackageMonitorCallback();
+ mPackageMonitorCallbackHelper.registerPackageMonitorCallback(callback, 0 /* userId */,
+ Binder.getCallingUid());
+ mPackageMonitorCallbackHelper.notifyPackageMonitor(Intent.ACTION_PACKAGES_SUSPENDED,
+ FAKE_PACKAGE_NAME, createFakeBundle(), new int[]{0}, null /* instantUserIds */,
+ null /* broadcastAllowList */, mHandler, filterExtras);
+
+ ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
+ verify(callback, after(WAIT_CALLBACK_CALLED_IN_MS).times(1)).sendResult(
+ bundleCaptor.capture());
+ Bundle bundle = bundleCaptor.getValue();
+ Intent intent = bundle.getParcelable(
+ PackageManager.EXTRA_PACKAGE_MONITOR_CALLBACK_RESULT, Intent.class);
+ assertThat(intent).isNotNull();
+ assertThat(intent.getAction()).isEqualTo(Intent.ACTION_PACKAGES_SUSPENDED);
+ String[] pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
+ assertThat(pkgList).isNotNull();
+ assertThat(pkgList.length).isEqualTo(1);
+ assertThat(pkgList[0]).isEqualTo(FAKE_PACKAGE_NAME);
+ }
+
+ @Test
public void testRegisterPackageMonitorCallback_callbackCalled() throws Exception {
IRemoteCallback callback = createMockPackageMonitorCallback();
@@ -112,7 +143,8 @@
Binder.getCallingUid());
mPackageMonitorCallbackHelper.notifyPackageMonitor(Intent.ACTION_PACKAGE_ADDED,
FAKE_PACKAGE_NAME, createFakeBundle(), new int[]{0} /* userIds */,
- null /* instantUserIds */, null /* broadcastAllowList */, mHandler);
+ null /* instantUserIds */, null /* broadcastAllowList */, mHandler,
+ null /* filterExtras */);
ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
verify(callback, after(WAIT_CALLBACK_CALLED_IN_MS).times(1)).sendResult(
@@ -136,7 +168,8 @@
// Notify for user 10
mPackageMonitorCallbackHelper.notifyPackageMonitor(Intent.ACTION_PACKAGE_ADDED,
FAKE_PACKAGE_NAME, createFakeBundle(), new int[]{10} /* userIds */,
- null /* instantUserIds */, null /* broadcastAllowList */, mHandler);
+ null /* instantUserIds */, null /* broadcastAllowList */, mHandler,
+ null /* filterExtras */);
verify(callback, after(WAIT_CALLBACK_CALLED_IN_MS).never()).sendResult(any());
}
@@ -239,7 +272,8 @@
mPackageMonitorCallbackHelper.onUserRemoved(10);
mPackageMonitorCallbackHelper.notifyPackageMonitor(Intent.ACTION_PACKAGE_ADDED,
FAKE_PACKAGE_NAME, createFakeBundle(), new int[]{10} /* userIds */,
- null /* instantUserIds */, null /* broadcastAllowList */, mHandler);
+ null /* instantUserIds */, null /* broadcastAllowList */, mHandler,
+ null /* filterExtras */);
verify(callback, after(WAIT_CALLBACK_CALLED_IN_MS).never()).sendResult(any());
}
@@ -255,7 +289,7 @@
Binder.getCallingUid());
mPackageMonitorCallbackHelper.notifyPackageMonitor(Intent.ACTION_PACKAGE_ADDED,
FAKE_PACKAGE_NAME, createFakeBundle(), new int[]{0} /* userIds */,
- null /* instantUserIds */, broadcastAllowList, mHandler);
+ null /* instantUserIds */, broadcastAllowList, mHandler, null /* filterExtras */);
verify(callback, after(WAIT_CALLBACK_CALLED_IN_MS).times(1)).sendResult(any());
}
@@ -271,7 +305,7 @@
Binder.getCallingUid());
mPackageMonitorCallbackHelper.notifyPackageMonitor(Intent.ACTION_PACKAGE_ADDED,
FAKE_PACKAGE_NAME, createFakeBundle(), new int[]{0} /* userIds */,
- null /* instantUserIds */, broadcastAllowList, mHandler);
+ null /* instantUserIds */, broadcastAllowList, mHandler, null /* filterExtras */);
verify(callback, after(WAIT_CALLBACK_CALLED_IN_MS).never()).sendResult(any());
}
@@ -287,7 +321,7 @@
Process.SYSTEM_UID);
mPackageMonitorCallbackHelper.notifyPackageMonitor(Intent.ACTION_PACKAGE_ADDED,
FAKE_PACKAGE_NAME, createFakeBundle(), new int[]{0} /* userIds */,
- null /* instantUserIds */, broadcastAllowList, mHandler);
+ null /* instantUserIds */, broadcastAllowList, mHandler, null /* filterExtras */);
verify(callback, after(WAIT_CALLBACK_CALLED_IN_MS).times(1)).sendResult(any());
}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/AuthenticationStatsCollectorTest.java b/services/tests/servicestests/src/com/android/server/biometrics/AuthenticationStatsCollectorTest.java
index d2e83e9..9eeb4f3 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/AuthenticationStatsCollectorTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/AuthenticationStatsCollectorTest.java
@@ -271,6 +271,7 @@
.thenReturn(true);
when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_FACE)).thenReturn(false);
when(mFingerprintManager.hasEnrolledTemplates(anyInt())).thenReturn(true);
+ when(mContext.getSystemService(Context.FACE_SERVICE)).thenReturn(null);
mAuthenticationStatsCollector.authenticate(USER_ID_1, false /* authenticated */);
diff --git a/services/tests/servicestests/src/com/android/server/credentials/CredentialManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/credentials/CredentialManagerServiceTest.java
index fd1abff..d850c73 100644
--- a/services/tests/servicestests/src/com/android/server/credentials/CredentialManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/credentials/CredentialManagerServiceTest.java
@@ -53,6 +53,12 @@
}
@Test
+ public void getStoredProviders_nullValue_success() {
+ Set<String> providers = CredentialManagerService.getStoredProviders(null, null);
+ assertThat(providers.size()).isEqualTo(0);
+ }
+
+ @Test
public void getStoredProviders_success() {
Set<String> providers =
CredentialManagerService.getStoredProviders(
diff --git a/services/tests/servicestests/src/com/android/server/os/BugreportManagerServiceImplTest.java b/services/tests/servicestests/src/com/android/server/os/BugreportManagerServiceImplTest.java
index 21b8a94..dc1d2c5 100644
--- a/services/tests/servicestests/src/com/android/server/os/BugreportManagerServiceImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/os/BugreportManagerServiceImplTest.java
@@ -16,26 +16,23 @@
package com.android.server.os;
+import android.app.admin.flags.Flags;
+import static android.app.admin.flags.Flags.onboardingBugreportV2Enabled;
+
import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertThrows;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.Mockito.when;
-import android.app.admin.DevicePolicyManager;
-import android.app.admin.flags.Flags;
import android.app.role.RoleManager;
import android.content.Context;
import android.os.Binder;
import android.os.BugreportManager.BugreportCallback;
-import android.os.BugreportParams;
import android.os.IBinder;
import android.os.IDumpstateListener;
import android.os.Process;
import android.os.RemoteException;
-import android.os.UserManager;
import android.platform.test.annotations.RequiresFlagsEnabled;
import android.platform.test.flag.junit.CheckFlagsRule;
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
@@ -51,8 +48,6 @@
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
import java.io.FileDescriptor;
import java.util.concurrent.CompletableFuture;
@@ -71,11 +66,6 @@
private BugreportManagerServiceImpl mService;
private BugreportManagerServiceImpl.BugreportFileManager mBugreportFileManager;
- @Mock
- private UserManager mMockUserManager;
- @Mock
- private DevicePolicyManager mMockDevicePolicyManager;
-
private int mCallingUid = 1234;
private String mCallingPackage = "test.package";
private AtomicFile mMappingFile;
@@ -85,17 +75,14 @@
@Before
public void setUp() {
- MockitoAnnotations.initMocks(this);
mContext = InstrumentationRegistry.getInstrumentation().getContext();
mMappingFile = new AtomicFile(mContext.getFilesDir(), "bugreport-mapping.xml");
ArraySet<String> mAllowlistedPackages = new ArraySet<>();
mAllowlistedPackages.add(mContext.getPackageName());
mService = new BugreportManagerServiceImpl(
- new TestInjector(mContext, mAllowlistedPackages, mMappingFile,
- mMockUserManager, mMockDevicePolicyManager));
+ new BugreportManagerServiceImpl.Injector(mContext, mAllowlistedPackages,
+ mMappingFile));
mBugreportFileManager = new BugreportManagerServiceImpl.BugreportFileManager(mMappingFile);
- // The calling user is an admin user by default.
- when(mMockUserManager.isUserAdmin(anyInt())).thenReturn(true);
}
@After
@@ -178,36 +165,6 @@
}
@Test
- public void testStartBugreport_throwsForNonAdminUser() throws Exception {
- when(mMockUserManager.isUserAdmin(anyInt())).thenReturn(false);
-
- Exception thrown = assertThrows(Exception.class,
- () -> mService.startBugreport(mCallingUid, mContext.getPackageName(),
- new FileDescriptor(), /* screenshotFd= */ null,
- BugreportParams.BUGREPORT_MODE_FULL,
- /* flags= */ 0, new Listener(new CountDownLatch(1)),
- /* isScreenshotRequested= */ false));
-
- assertThat(thrown.getMessage()).contains("not an admin user");
- }
-
- @Test
- public void testStartBugreport_throwsForNotAffiliatedUser() throws Exception {
- when(mMockUserManager.isUserAdmin(anyInt())).thenReturn(false);
- when(mMockDevicePolicyManager.getDeviceOwnerUserId()).thenReturn(-1);
- when(mMockDevicePolicyManager.isAffiliatedUser(anyInt())).thenReturn(false);
-
- Exception thrown = assertThrows(Exception.class,
- () -> mService.startBugreport(mCallingUid, mContext.getPackageName(),
- new FileDescriptor(), /* screenshotFd= */ null,
- BugreportParams.BUGREPORT_MODE_REMOTE,
- /* flags= */ 0, new Listener(new CountDownLatch(1)),
- /* isScreenshotRequested= */ false));
-
- assertThat(thrown.getMessage()).contains("not affiliated to the device owner");
- }
-
- @Test
public void testRetrieveBugreportWithoutFilesForCaller() throws Exception {
CountDownLatch latch = new CountDownLatch(1);
Listener listener = new Listener(latch);
@@ -250,8 +207,7 @@
private void clearAllowlist() {
mService = new BugreportManagerServiceImpl(
- new TestInjector(mContext, new ArraySet<>(), mMappingFile,
- mMockUserManager, mMockDevicePolicyManager));
+ new BugreportManagerServiceImpl.Injector(mContext, new ArraySet<>(), mMappingFile));
}
private static class Listener implements IDumpstateListener {
@@ -302,27 +258,4 @@
complete(successful);
}
}
-
- private static class TestInjector extends BugreportManagerServiceImpl.Injector {
-
- private final UserManager mUserManager;
- private final DevicePolicyManager mDevicePolicyManager;
-
- TestInjector(Context context, ArraySet<String> allowlistedPackages, AtomicFile mappingFile,
- UserManager um, DevicePolicyManager dpm) {
- super(context, allowlistedPackages, mappingFile);
- mUserManager = um;
- mDevicePolicyManager = dpm;
- }
-
- @Override
- public UserManager getUserManager() {
- return mUserManager;
- }
-
- @Override
- public DevicePolicyManager getDevicePolicyManager() {
- return mDevicePolicyManager;
- }
- }
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index 718c598..e88a00b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -161,6 +161,7 @@
import com.android.internal.R;
import com.android.server.wm.ActivityRecord.State;
+import com.android.window.flags.Flags;
import org.junit.Assert;
import org.junit.Before;
@@ -320,7 +321,7 @@
}
private void ensureActivityConfiguration(ActivityRecord activity) {
- activity.ensureActivityConfiguration(0 /* globalChanges */, false /* preserveWindow */);
+ activity.ensureActivityConfiguration();
}
@Test
@@ -718,7 +719,7 @@
// Clear size compat.
activity.clearSizeCompatMode();
- activity.ensureActivityConfiguration(0 /* globalChanges */, false /* preserveWindow */);
+ activity.ensureActivityConfiguration();
mDisplayContent.sendNewConfiguration();
// Relaunching the app should still respect the orientation request.
@@ -819,8 +820,7 @@
task.onConfigurationChanged(newConfig);
- activity.ensureActivityConfiguration(0 /* globalChanges */,
- false /* preserveWindow */, true /* ignoreVisibility */);
+ activity.ensureActivityConfiguration(true /* ignoreVisibility */);
final ActivityConfigurationChangeItem expected =
ActivityConfigurationChangeItem.obtain(activity.token,
@@ -1563,8 +1563,7 @@
topActivity.nowVisible = true;
topActivity.setState(RESUMED, "true");
doCallRealMethod().when(mRootWindowContainer).ensureActivitiesVisible(
- any() /* starting */, anyInt() /* configChanges */,
- anyBoolean() /* preserveWindows */, anyBoolean() /* notifyClients */);
+ any() /* starting */, anyBoolean() /* notifyClients */);
topActivity.setShowWhenLocked(true);
// Verify the stack-top activity is occluded keyguard.
@@ -1624,7 +1623,6 @@
secondActivity.finishing = true;
secondActivity.completeFinishing("test");
verify(secondActivity.mDisplayContent).ensureActivitiesVisible(null /* starting */,
- 0 /* configChanges */ , false /* preserveWindows */,
true /* notifyClients */);
// Finish the first activity
@@ -1632,7 +1630,6 @@
firstActivity.setVisibleRequested(true);
firstActivity.completeFinishing("test");
verify(firstActivity.mDisplayContent, times(2)).ensureActivitiesVisible(null /* starting */,
- 0 /* configChanges */ , false /* preserveWindows */,
true /* notifyClients */);
// Remove the translucent activity and clear invocations for next test
@@ -1960,6 +1957,7 @@
display.continueUpdateOrientationForDiffOrienLaunchingApp();
assertTrue(display.isFixedRotationLaunchingApp(activity));
+ activity.stopFreezingScreen(true /* unfreezeSurfaceNow */, true /* force */);
// Simulate the rotation has been updated to previous one, e.g. sensor updates before the
// remote rotation is completed.
doReturn(originalRotation).when(displayRotation).rotationForOrientation(
@@ -1970,14 +1968,12 @@
activity.finishFixedRotationTransform();
final ScreenRotationAnimation rotationAnim = display.getRotationAnimation();
assertNotNull(rotationAnim);
- rotationAnim.setRotation(display.getPendingTransaction(), originalRotation);
// Because the display doesn't rotate, the rotated activity needs to cancel the fixed
// rotation. There should be a rotation animation to cover the change of activity.
verify(activity).onCancelFixedRotationTransform(rotatedInfo.rotation);
assertTrue(activity.isFreezingScreen());
assertFalse(displayRotation.isRotatingSeamlessly());
- assertTrue(rotationAnim.isRotating());
// Simulate the remote rotation has completed and the configuration doesn't change, then
// the rotated activity should also be restored by clearing the transform.
@@ -3370,7 +3366,7 @@
// to client if the app didn't request IME visible.
assertFalse(app2.mActivityRecord.mImeInsetsFrozenUntilStartInput);
- if (mWm.mFlags.mWindowStateResizeItemFlag) {
+ if (Flags.bundleClientTransactionFlag()) {
verify(app2.getProcess()).scheduleClientTransactionItem(
isA(WindowStateResizeItem.class));
} else {
@@ -3697,7 +3693,7 @@
doReturn(false).when(activity).showToCurrentUser();
spyOn(taskFragment);
doReturn(false).when(taskFragment).shouldBeVisible(any());
- display.ensureActivitiesVisible(null, 0, false, false);
+ display.ensureActivitiesVisible(null /* starting */, false /* notifyClients */);
assertFalse(activity.isVisibleRequested());
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ClientLifecycleManagerTests.java b/services/tests/wmtests/src/com/android/server/wm/ClientLifecycleManagerTests.java
index c757457..09f677e7 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ClientLifecycleManagerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ClientLifecycleManagerTests.java
@@ -172,7 +172,7 @@
@Test
public void testScheduleTransactionItemUnlocked() throws RemoteException {
// Use non binder client to get non-recycled ClientTransaction.
- mLifecycleManager.scheduleTransactionItemUnlocked(mNonBinderClient, mTransactionItem);
+ mLifecycleManager.scheduleTransactionItemNow(mNonBinderClient, mTransactionItem);
// Dispatch immediately.
assertTrue(mLifecycleManager.mPendingTransactions.isEmpty());
@@ -217,6 +217,8 @@
@Test
public void testDispatchPendingTransactions() throws RemoteException {
+ mSetFlagsRule.enableFlags(FLAG_BUNDLE_CLIENT_TRANSACTION_FLAG);
+
mLifecycleManager.mPendingTransactions.put(mClientBinder, mTransaction);
mLifecycleManager.dispatchPendingTransactions();
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index dfe79bf..6497ee9 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -75,7 +75,6 @@
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.reset;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.same;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.server.wm.ActivityTaskSupervisor.ON_TOP;
@@ -490,7 +489,7 @@
newOverrideConfig.fontScale += 0.3;
defaultDisplay.updateDisplayOverrideConfigurationLocked(newOverrideConfig,
- null /* starting */, false /* deferResume */, null /* result */);
+ null /* starting */, false /* deferResume */);
// Check that global configuration is updated, as we've updated default display's config.
Configuration globalConfig = mWm.mRoot.getConfiguration();
@@ -499,7 +498,7 @@
// Return back to original values.
defaultDisplay.updateDisplayOverrideConfigurationLocked(currentConfig,
- null /* starting */, false /* deferResume */, null /* result */);
+ null /* starting */, false /* deferResume */);
globalConfig = mWm.mRoot.getConfiguration();
assertEquals(currentConfig.densityDpi, globalConfig.densityDpi);
assertEquals(currentConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */);
@@ -1176,7 +1175,7 @@
activity.setRequestedOrientation(newOrientation);
verify(dc, never()).updateDisplayOverrideConfigurationLocked(any(), eq(activity),
- anyBoolean(), same(null));
+ anyBoolean());
assertEquals(ROTATION_180, dc.getRotation());
}
@@ -2123,10 +2122,8 @@
// Once transition starts, rotation is applied and transition shows DC rotating.
testPlayer.startTransition();
waitUntilHandlersIdle();
- verify(activity1).ensureActivityConfiguration(anyInt(), anyBoolean(), anyBoolean(),
- anyBoolean());
- verify(activity2).ensureActivityConfiguration(anyInt(), anyBoolean(), anyBoolean(),
- anyBoolean());
+ verify(activity1).ensureActivityConfiguration(anyBoolean(), anyBoolean());
+ verify(activity2).ensureActivityConfiguration(anyBoolean(), anyBoolean());
assertNotEquals(origRot, dc.getConfiguration().windowConfiguration.getRotation());
assertNotNull(testPlayer.mLastReady);
assertTrue(testPlayer.mController.isPlaying());
@@ -2248,11 +2245,11 @@
// The assertion will fail if DisplayArea#ensureActivitiesVisible is called twice.
assertFalse(called[0]);
called[0] = true;
- mDisplayContent.ensureActivitiesVisible(null, 0, false, false);
+ mDisplayContent.ensureActivitiesVisible(null, false);
return null;
- }).when(mockTda).ensureActivitiesVisible(any(), anyInt(), anyBoolean(), anyBoolean());
+ }).when(mockTda).ensureActivitiesVisible(any(), anyBoolean());
- mDisplayContent.ensureActivitiesVisible(null, 0, false, false);
+ mDisplayContent.ensureActivitiesVisible(null, false);
}
@Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
index 8de45b0..32b3558 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
@@ -106,8 +106,7 @@
topActivity.getRootTask().moveToFront("testRecentsActivityVisiblility");
doCallRealMethod().when(mRootWindowContainer).ensureActivitiesVisible(
- any() /* starting */, anyInt() /* configChanges */,
- anyBoolean() /* preserveWindows */, anyBoolean() /* notifyClients */);
+ any() /* starting */, anyBoolean() /* notifyClients */);
RecentsAnimationCallbacks recentsAnimation = startRecentsActivity(
mRecentsComponent, true /* getRecentsAnimation */);
@@ -178,8 +177,7 @@
mAtm.startRecentsActivity(recentsIntent, 0 /* eventTime */,
null /* recentsAnimationRunner */);
- verify(recentsActivity).ensureActivityConfiguration(anyInt() /* globalChanges */,
- anyBoolean() /* preserveWindow */, eq(true) /* ignoreVisibility */);
+ verify(recentsActivity).ensureActivityConfiguration(eq(true) /* ignoreVisibility */);
assertThat(mSupervisor.mStoppingActivities).contains(recentsActivity);
}
@@ -199,8 +197,7 @@
"testRestartRecentsActivity");
doCallRealMethod().when(mRootWindowContainer).ensureActivitiesVisible(
- any() /* starting */, anyInt() /* configChanges */,
- anyBoolean() /* preserveWindows */, anyBoolean() /* notifyClients */);
+ any() /* starting */, anyBoolean() /* notifyClients */);
doReturn(app).when(mAtm).getProcessController(eq(recentActivity.processName), anyInt());
doNothing().when(mClientLifecycleManager).scheduleTransaction(any());
@@ -354,8 +351,7 @@
doReturn(TEST_USER_ID).when(mAtm).getCurrentUserId();
doCallRealMethod().when(mRootWindowContainer).ensureActivitiesVisible(
- any() /* starting */, anyInt() /* configChanges */,
- anyBoolean() /* preserveWindows */, anyBoolean() /* notifyClients */);
+ any() /* starting */, anyBoolean() /* notifyClients */);
startRecentsActivity(otherUserHomeActivity.getTask().getBaseIntent().getComponent(),
true);
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootTaskTests.java b/services/tests/wmtests/src/com/android/server/wm/RootTaskTests.java
index 89cd726..b5883b1 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootTaskTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootTaskTests.java
@@ -823,8 +823,7 @@
.build();
doReturn(false).when(secondActivity).occludesParent();
- homeRootTask.ensureActivitiesVisible(null /* starting */, 0 /* configChanges */,
- false /* preserveWindows */);
+ homeRootTask.ensureActivitiesVisible(null /* starting */);
assertTrue(firstActivity.shouldBeVisible());
}
@@ -1419,8 +1418,7 @@
// Any common path that updates activity visibility should clear the unknown visibility
// records that are no longer visible according to hierarchy.
- task.ensureActivitiesVisible(null /* starting */, 0 /* configChanges */,
- false /* preserveWindows */);
+ task.ensureActivitiesVisible(null /* starting */);
// Assume the top activity relayouted, just remove it directly.
unknownAppVisibilityController.appRemovedOrHidden(activities[1]);
// All unresolved records should be removed.
@@ -1441,8 +1439,7 @@
doNothing().when(mSupervisor).startSpecificActivity(any(), anyBoolean(),
anyBoolean());
- task.ensureActivitiesVisible(null /* starting */, 0 /* configChanges */,
- false /* preserveWindows */);
+ task.ensureActivitiesVisible(null /* starting */);
verify(mSupervisor).startSpecificActivity(any(), eq(false) /* andResume */,
anyBoolean());
}
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 c3102e0..5518c60 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -947,7 +947,7 @@
// Recompute the natural configuration in the new display.
mActivity.clearSizeCompatMode();
- mActivity.ensureActivityConfiguration(0 /* globalChanges */, false /* preserveWindow */);
+ mActivity.ensureActivityConfiguration();
// Because the display cannot rotate, the portrait activity will fit the short side of
// display with keeping portrait bounds [200, 0 - 700, 1000] in center.
assertEquals(newDisplayBounds.height(), currentBounds.height());
@@ -4858,7 +4858,7 @@
}
// Make sure to use the provided configuration to construct the size compat fields.
activity.clearSizeCompatMode();
- activity.ensureActivityConfiguration(0 /* globalChanges */, false /* preserveWindow */);
+ activity.ensureActivityConfiguration();
// Make sure the display configuration reflects the change of activity.
if (activity.mDisplayContent.updateOrientation()) {
activity.mDisplayContent.sendNewConfiguration();
diff --git a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
index 8cd9ff3..90493d4 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
@@ -375,8 +375,7 @@
// Always keep things awake.
doReturn(true).when(mWmService.mRoot).hasAwakeDisplay();
// Called when moving activity to pinned stack.
- doNothing().when(mWmService.mRoot).ensureActivitiesVisible(any(),
- anyInt(), anyBoolean(), anyBoolean());
+ doNothing().when(mWmService.mRoot).ensureActivitiesVisible(any(), anyBoolean());
spyOn(mWmService.mDisplayWindowSettings);
spyOn(mWmService.mDisplayWindowSettingsProvider);
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java
index ec068be..00e22fd 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java
@@ -269,8 +269,7 @@
mTaskFragment.getTask().addChild(activityBelow, 0);
// Ensure the activity below is visible
- mTaskFragment.getTask().ensureActivitiesVisible(null /* starting */, 0 /* configChanges */,
- false /* preserveWindows */);
+ mTaskFragment.getTask().ensureActivitiesVisible(null /* starting */);
assertEquals(true, activityBelow.isVisibleRequested());
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
index da7612b..45e1e95 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
@@ -339,16 +339,14 @@
// Check visibility of occluded tasks
doReturn(false).when(leafTask1).shouldBeVisible(any());
doReturn(true).when(leafTask2).shouldBeVisible(any());
- rootTask.ensureActivitiesVisible(
- null /* starting */ , 0 /* configChanges */, false /* preserveWindows */);
+ rootTask.ensureActivitiesVisible(null /* starting */);
assertFalse(activity1.isVisible());
assertTrue(activity2.isVisible());
// Check visibility of not occluded tasks
doReturn(true).when(leafTask1).shouldBeVisible(any());
doReturn(true).when(leafTask2).shouldBeVisible(any());
- rootTask.ensureActivitiesVisible(
- null /* starting */ , 0 /* configChanges */, false /* preserveWindows */);
+ rootTask.ensureActivitiesVisible(null /* starting */);
assertTrue(activity1.isVisible());
assertTrue(activity2.isVisible());
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
index 71447e7..fddd771 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
@@ -1495,8 +1495,7 @@
verify(taskSnapshotController, times(0)).recordSnapshot(eq(task1));
enteringAnimReports.clear();
- doCallRealMethod().when(mWm.mRoot).ensureActivitiesVisible(any(),
- anyInt(), anyBoolean(), anyBoolean());
+ doCallRealMethod().when(mWm.mRoot).ensureActivitiesVisible(any(), anyBoolean());
final boolean[] wasInFinishingTransition = { false };
controller.registerLegacyListener(new WindowManagerInternal.AppTransitionListener() {
@Override
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
index e31ee11..400e4b6 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
@@ -38,7 +38,6 @@
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.clearInvocations;
@@ -306,10 +305,12 @@
@Test
public void testCachedStateConfigurationChange() throws RemoteException {
- doNothing().when(mClientLifecycleManager).scheduleTransactionItemUnlocked(any(), any());
+ doNothing().when(mClientLifecycleManager).scheduleTransactionItemNow(any(), any());
final IApplicationThread thread = mWpc.getThread();
final Configuration newConfig = new Configuration(mWpc.getConfiguration());
newConfig.densityDpi += 100;
+ mWpc.mWindowSession = getTestSession();
+ mWpc.mWindowSession.onWindowAdded(mock(WindowState.class));
// Non-cached state will send the change directly.
mWpc.setReportedProcState(ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND);
clearInvocations(mClientLifecycleManager);
@@ -322,13 +323,13 @@
newConfig.densityDpi += 100;
mWpc.onConfigurationChanged(newConfig);
verify(mClientLifecycleManager, never()).scheduleTransactionItem(eq(thread), any());
- verify(mClientLifecycleManager, never()).scheduleTransactionItemUnlocked(eq(thread), any());
+ verify(mClientLifecycleManager, never()).scheduleTransactionItemNow(eq(thread), any());
// Cached -> non-cached will send the previous deferred config immediately.
mWpc.setReportedProcState(ActivityManager.PROCESS_STATE_RECEIVER);
final ArgumentCaptor<ConfigurationChangeItem> captor =
ArgumentCaptor.forClass(ConfigurationChangeItem.class);
- verify(mClientLifecycleManager).scheduleTransactionItemUnlocked(
+ verify(mClientLifecycleManager).scheduleTransactionItemNow(
eq(thread), captor.capture());
final ClientTransactionHandler client = mock(ClientTransactionHandler.class);
captor.getValue().preExecute(client);
@@ -432,7 +433,7 @@
mWpc.updateAppSpecificSettingsForAllActivitiesInPackage(DEFAULT_COMPONENT_PACKAGE_NAME,
Configuration.UI_MODE_NIGHT_YES, LocaleList.forLanguageTags("en-XA"),
GRAMMATICAL_GENDER_NOT_SPECIFIED);
- verify(activity).ensureActivityConfiguration(anyInt(), anyBoolean());
+ verify(activity).ensureActivityConfiguration();
}
@Test
@@ -443,7 +444,7 @@
Configuration.UI_MODE_NIGHT_YES, LocaleList.forLanguageTags("en-XA"),
GRAMMATICAL_GENDER_NOT_SPECIFIED);
verify(activity, never()).applyAppSpecificConfig(anyInt(), any(), anyInt());
- verify(activity, never()).ensureActivityConfiguration(anyInt(), anyBoolean());
+ verify(activity, never()).ensureActivityConfiguration();
}
@Test