Merge "Add flags for com.android.internal.widget" into main
diff --git a/cmds/idmap2/Android.bp b/cmds/idmap2/Android.bp
index 58763a7..d9ff190 100644
--- a/cmds/idmap2/Android.bp
+++ b/cmds/idmap2/Android.bp
@@ -165,6 +165,7 @@
],
host_supported: true,
test_suites: ["general-tests"],
+ require_root: true,
srcs: [
"tests/BinaryStreamVisitorTests.cpp",
"tests/CommandLineOptionsTests.cpp",
diff --git a/cmds/idmap2/libidmap2/ResourceContainer.cpp b/cmds/idmap2/libidmap2/ResourceContainer.cpp
index 57ae354..f22a481 100644
--- a/cmds/idmap2/libidmap2/ResourceContainer.cpp
+++ b/cmds/idmap2/libidmap2/ResourceContainer.cpp
@@ -22,6 +22,7 @@
#include <utility>
#include <vector>
+#include "android-base/scopeguard.h"
#include "androidfw/ApkAssets.h"
#include "androidfw/AssetManager.h"
#include "androidfw/Util.h"
@@ -269,27 +270,40 @@
std::unique_ptr<AssetManager2> am;
ZipAssetsProvider* zip_assets;
- static Result<ResState> Initialize(std::unique_ptr<ZipAssetsProvider> zip,
+ static Result<ResState> Initialize(std::unique_ptr<ZipAssetsProvider>&& zip,
package_property_t flags) {
ResState state;
state.zip_assets = zip.get();
if ((state.apk_assets = ApkAssets::Load(std::move(zip), flags)) == nullptr) {
- return Error("failed to load apk asset");
+ return Error("failed to load apk asset for '%s'",
+ state.zip_assets->GetDebugName().c_str());
}
+ // Make sure we put ZipAssetsProvider where we took it if initialization fails, so the
+ // original object stays valid for any next call it may get.
+ auto scoped_restore_zip_assets = android::base::ScopeGuard([&zip, &state]() {
+ zip = std::unique_ptr<ZipAssetsProvider>(
+ static_cast<ZipAssetsProvider*>(
+ std::move(const_cast<ApkAssets&>(*state.apk_assets)).TakeAssetsProvider().release()));
+ });
+
if ((state.arsc = state.apk_assets->GetLoadedArsc()) == nullptr) {
- return Error("failed to retrieve loaded arsc");
+ return Error("failed to retrieve loaded arsc for '%s'",
+ state.zip_assets->GetDebugName().c_str());
}
if ((state.package = GetPackageAtIndex0(state.arsc)) == nullptr) {
- return Error("failed to retrieve loaded package at index 0");
+ return Error("failed to retrieve loaded package at index 0 for '%s'",
+ state.zip_assets->GetDebugName().c_str());
}
state.am = std::make_unique<AssetManager2>();
if (!state.am->SetApkAssets({state.apk_assets}, false)) {
- return Error("failed to create asset manager");
+ return Error("failed to create asset manager for '%s'",
+ state.zip_assets->GetDebugName().c_str());
}
+ scoped_restore_zip_assets.Disable();
return state;
}
};
diff --git a/cmds/idmap2/tests/IdmapTests.cpp b/cmds/idmap2/tests/IdmapTests.cpp
index 1b656e8..7093614 100644
--- a/cmds/idmap2/tests/IdmapTests.cpp
+++ b/cmds/idmap2/tests/IdmapTests.cpp
@@ -214,6 +214,20 @@
ASSERT_EQ(idmap->GetHeader()->GetOverlayName(), TestConstants::OVERLAY_NAME_ALL_POLICIES);
}
+TEST(IdmapTests, TargetContainerWorksAfterError) {
+ auto target = TargetResourceContainer::FromPath(GetTestDataPath() + "/target/target-bad.apk");
+ ASSERT_TRUE(target);
+
+ auto crc = target->get()->GetCrc();
+ ASSERT_TRUE(crc);
+
+ // This call tries to construct the full ApkAssets state, and fails.
+ ASSERT_FALSE(target->get()->DefinesOverlayable());
+ auto crc2 = target->get()->GetCrc();
+ ASSERT_TRUE(crc2);
+ EXPECT_EQ(*crc, *crc2);
+}
+
TEST(IdmapTests, CreateIdmapDataFromApkAssets) {
std::string target_apk_path = GetTestDataPath() + "/target/target.apk";
std::string overlay_apk_path = GetTestDataPath() + "/overlay/overlay.apk";
diff --git a/cmds/idmap2/tests/data/target/target-bad.apk b/cmds/idmap2/tests/data/target/target-bad.apk
new file mode 100644
index 0000000..fd86782
--- /dev/null
+++ b/cmds/idmap2/tests/data/target/target-bad.apk
Binary files differ
diff --git a/core/api/current.txt b/core/api/current.txt
index f3d19ca..ac6e293 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -40754,8 +40754,10 @@
method @NonNull public java.util.List<java.security.cert.X509Certificate> getGrantedCertificateChainFromId(long) throws android.security.keystore.KeyPermanentlyInvalidatedException, java.security.UnrecoverableKeyException;
method @NonNull public java.security.Key getGrantedKeyFromId(long) throws android.security.keystore.KeyPermanentlyInvalidatedException, java.security.UnrecoverableKeyException;
method @NonNull public java.security.KeyPair getGrantedKeyPairFromId(long) throws android.security.keystore.KeyPermanentlyInvalidatedException, java.security.UnrecoverableKeyException;
+ method @FlaggedApi("android.security.keystore2.attest_modules") @NonNull public byte[] getSupplementaryAttestationInfo(int) throws android.security.KeyStoreException;
method public long grantKeyAccess(@NonNull String, int) throws android.security.KeyStoreException, java.security.UnrecoverableKeyException;
method public void revokeKeyAccess(@NonNull String, int) throws android.security.KeyStoreException, java.security.UnrecoverableKeyException;
+ field public static final int MODULE_HASH = -1879047468; // 0x900002d4
}
public class SecureKeyImportUnavailableException extends java.security.ProviderException {
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index d1de19e..a593970 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -5264,9 +5264,9 @@
}
@FlaggedApi("android.chre.flags.offload_api") public class HubEndpointSession implements java.lang.AutoCloseable {
- method public void close();
+ method @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB) public void close();
method @Nullable public android.hardware.contexthub.HubServiceInfo getServiceInfo();
- method @NonNull public android.hardware.location.ContextHubTransaction<java.lang.Void> sendMessage(@NonNull android.hardware.contexthub.HubMessage);
+ method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB) public android.hardware.location.ContextHubTransaction<java.lang.Void> sendMessage(@NonNull android.hardware.contexthub.HubMessage);
}
@FlaggedApi("android.chre.flags.offload_api") public class HubEndpointSessionResult {
diff --git a/core/java/android/app/admin/UnknownAuthority.java b/core/java/android/app/admin/UnknownAuthority.java
index 82dcf7e..bebffde 100644
--- a/core/java/android/app/admin/UnknownAuthority.java
+++ b/core/java/android/app/admin/UnknownAuthority.java
@@ -74,14 +74,14 @@
@Override
public boolean equals(@Nullable Object o) {
if (this == o) return true;
- if (o != null && getClass() == o.getClass()) return false;
+ if (o == null || getClass() != o.getClass()) return false;
UnknownAuthority other = (UnknownAuthority) o;
return Objects.equals(mName, other.mName);
}
@Override
public int hashCode() {
- return mName.hashCode();
+ return Objects.hashCode(mName);
}
@Override
diff --git a/core/java/android/hardware/contexthub/HubEndpointSession.java b/core/java/android/hardware/contexthub/HubEndpointSession.java
index cf952cb..b3d65c1 100644
--- a/core/java/android/hardware/contexthub/HubEndpointSession.java
+++ b/core/java/android/hardware/contexthub/HubEndpointSession.java
@@ -19,6 +19,7 @@
import android.annotation.FlaggedApi;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.chre.flags.Flags;
import android.hardware.location.ContextHubTransaction;
@@ -70,6 +71,7 @@
* receiving the response for the message.
*/
@NonNull
+ @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB)
public ContextHubTransaction<Void> sendMessage(@NonNull HubMessage message) {
if (mIsClosed.get()) {
throw new IllegalStateException("Session is already closed.");
@@ -120,6 +122,7 @@
* <p>When this function is invoked, the messaging associated with this session is invalidated.
* All futures messages targeted for this client are dropped.
*/
+ @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB)
public void close() {
if (!mIsClosed.getAndSet(true)) {
mCloseGuard.close();
diff --git a/core/java/android/window/flags/lse_desktop_experience.aconfig b/core/java/android/window/flags/lse_desktop_experience.aconfig
index d45d5c4..5053aa8 100644
--- a/core/java/android/window/flags/lse_desktop_experience.aconfig
+++ b/core/java/android/window/flags/lse_desktop_experience.aconfig
@@ -467,4 +467,11 @@
namespace: "lse_desktop_experience"
description: "Enable drag-and-drop between connected displays."
bug: "381793841"
+}
+
+flag {
+ name: "enable_connected_displays_window_drag"
+ namespace: "lse_desktop_experience"
+ description: "Enable window drag between connected displays."
+ bug: "381172172"
}
\ No newline at end of file
diff --git a/keystore/java/Android.bp b/keystore/java/Android.bp
index 21edff1..264ac5ff 100644
--- a/keystore/java/Android.bp
+++ b/keystore/java/Android.bp
@@ -13,5 +13,13 @@
"**/*.java",
"**/*.aidl",
],
+ exclude_srcs: select(release_flag("RELEASE_ATTEST_MODULES"), {
+ true: [
+ "android/security/KeyStore2HalCurrent.java",
+ ],
+ default: [
+ "android/security/KeyStore2HalLatest.java",
+ ],
+ }),
visibility: ["//frameworks/base"],
}
diff --git a/keystore/java/android/security/KeyStore2.java b/keystore/java/android/security/KeyStore2.java
index dd703f5..f5cf571 100644
--- a/keystore/java/android/security/KeyStore2.java
+++ b/keystore/java/android/security/KeyStore2.java
@@ -101,7 +101,7 @@
R execute(IKeystoreService service) throws RemoteException;
}
- private <R> R handleRemoteExceptionWithRetry(@NonNull CheckedRemoteRequest<R> request)
+ <R> R handleRemoteExceptionWithRetry(@NonNull CheckedRemoteRequest<R> request)
throws KeyStoreException {
IKeystoreService service = getService(false /* retryLookup */);
boolean firstTry = true;
@@ -369,6 +369,18 @@
}
}
+ /**
+ * Returns tag-specific info required to interpret a tag's attested value.
+ * @see IKeystoreService#getSupplementaryAttestationInfo(Tag) for more details.
+ * @param tag
+ * @return
+ * @throws KeyStoreException
+ * @hide
+ */
+ public byte[] getSupplementaryAttestationInfo(int tag) throws KeyStoreException {
+ return KeyStore2HalVersion.getSupplementaryAttestationInfoHelper(tag, this);
+ }
+
static KeyStoreException getKeyStoreException(int errorCode, String serviceErrorMessage) {
if (errorCode > 0) {
// KeyStore layer error
diff --git a/keystore/java/android/security/KeyStore2HalCurrent.java b/keystore/java/android/security/KeyStore2HalCurrent.java
new file mode 100644
index 0000000..f4d8fe6
--- /dev/null
+++ b/keystore/java/android/security/KeyStore2HalCurrent.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security;
+
+/**
+ * @hide This class is necessary to allow the version of the AIDL interface for Keystore and
+* KeyMint used in KeyStore2.java to differ by BUILD flag `RELEASE_ATTEST_MODULES`. When
+* `RELEASE_ATTEST_MODULES` is not set, this file is included, and the current HALs for Keystore
+* (V4) and KeyMint (V3) are used.
+*/
+class KeyStore2HalVersion {
+ public static byte[] getSupplementaryAttestationInfoHelper(int tag, KeyStore2 ks)
+ throws KeyStoreException {
+ return new byte[0];
+ }
+}
diff --git a/keystore/java/android/security/KeyStore2HalLatest.java b/keystore/java/android/security/KeyStore2HalLatest.java
new file mode 100644
index 0000000..123f1c0
--- /dev/null
+++ b/keystore/java/android/security/KeyStore2HalLatest.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security;
+
+/**
+ * @hide This class is necessary to allow the version of the AIDL interface for Keystore and
+* KeyMint used in KeyStore2.java to differ by BUILD flag `RELEASE_ATTEST_MODULES`. When
+* `RELEASE_ATTEST_MODULES` is set, this file is included, and the latest HALs for Keystore (V5)
+* and KeyMint (V4) are used.
+*/
+class KeyStore2HalVersion {
+ public static byte[] getSupplementaryAttestationInfoHelper(int tag, KeyStore2 ks)
+ throws KeyStoreException {
+ return ks.handleRemoteExceptionWithRetry(
+ (service) -> service.getSupplementaryAttestationInfo(tag));
+ }
+}
diff --git a/keystore/java/android/security/keystore/KeyStoreManager.java b/keystore/java/android/security/keystore/KeyStoreManager.java
index e6091c1..740ccb5 100644
--- a/keystore/java/android/security/keystore/KeyStoreManager.java
+++ b/keystore/java/android/security/keystore/KeyStoreManager.java
@@ -17,9 +17,11 @@
package android.security.keystore;
import android.annotation.FlaggedApi;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SystemService;
import android.content.Context;
+import android.hardware.security.keymint.TagType;
import android.security.KeyStore2;
import android.security.KeyStoreException;
import android.security.keystore2.AndroidKeyStoreProvider;
@@ -32,6 +34,8 @@
import com.android.internal.annotations.GuardedBy;
import java.io.ByteArrayInputStream;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.security.Key;
import java.security.KeyPair;
import java.security.PublicKey;
@@ -299,6 +303,37 @@
return Collections.emptyList();
}
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(value = {MODULE_HASH})
+ public @interface SupplementaryAttestationInfoTagEnum {}
+
+ /**
+ * When passed into getSupplementaryAttestationInfo, getSupplementaryAttestationInfo returns the
+ * DER-encoded structure corresponding to the `Modules` schema described in the KeyMint HAL's
+ * KeyCreationResult.aidl. The SHA-256 hash of this encoded structure is what's included with
+ * the tag in attestations.
+ */
+ // TODO(b/369375199): Replace with Tag.MODULE_HASH when flagging is removed.
+ public static final int MODULE_HASH = TagType.BYTES | 724;
+
+ /**
+ * Returns tag-specific data required to interpret a tag's attested value.
+ *
+ * When performing key attestation, the obtained attestation certificate contains a list of tags
+ * and their corresponding attested values. For some tags, additional information about the
+ * attested value can be queried via this API. See individual tags for specifics.
+ *
+ * @param tag tag for which info is being requested
+ * @return tag-specific info
+ * @throws KeyStoreException if the requested info is not available
+ */
+ @FlaggedApi(android.security.keystore2.Flags.FLAG_ATTEST_MODULES)
+ public @NonNull byte[] getSupplementaryAttestationInfo(
+ @SupplementaryAttestationInfoTagEnum int tag) throws KeyStoreException {
+ return mKeyStore2.getSupplementaryAttestationInfo(tag);
+ }
+
/**
* Returns a new {@link KeyDescriptor} instance in the app domain / namespace with the {@code
* alias} set to the provided value.
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/DesktopModeFlickerScenarios.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/DesktopModeFlickerScenarios.kt
index f6d2cc0..f4f60d7 100644
--- a/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/DesktopModeFlickerScenarios.kt
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/DesktopModeFlickerScenarios.kt
@@ -272,9 +272,11 @@
TaggedCujTransitionMatcher(associatedTransitionRequired = false)
)
.build(),
- assertions = AssertionTemplates.DESKTOP_MODE_APP_VISIBILITY_ASSERTIONS +
- listOf(AppWindowCoversLeftHalfScreenAtEnd(DESKTOP_MODE_APP))
- .associateBy({ it }, { AssertionInvocationGroup.BLOCKING }),
+ assertions = AssertionTemplates.DESKTOP_MODE_APP_VISIBILITY_ASSERTIONS + listOf(
+ AppWindowCoversLeftHalfScreenAtEnd(
+ DESKTOP_MODE_APP, SNAP_WINDOW_MAX_DIFF_THRESHOLD_RATIO
+ )
+ ).associateBy({ it }, { AssertionInvocationGroup.BLOCKING }),
)
val SNAP_RESIZE_RIGHT_WITH_DRAG =
@@ -287,9 +289,11 @@
TaggedCujTransitionMatcher(associatedTransitionRequired = false)
)
.build(),
- assertions = AssertionTemplates.DESKTOP_MODE_APP_VISIBILITY_ASSERTIONS +
- listOf(AppWindowCoversRightHalfScreenAtEnd(DESKTOP_MODE_APP))
- .associateBy({ it }, { AssertionInvocationGroup.BLOCKING }),
+ assertions = AssertionTemplates.DESKTOP_MODE_APP_VISIBILITY_ASSERTIONS + listOf(
+ AppWindowCoversRightHalfScreenAtEnd(
+ DESKTOP_MODE_APP, SNAP_WINDOW_MAX_DIFF_THRESHOLD_RATIO
+ )
+ ).associateBy({ it }, { AssertionInvocationGroup.BLOCKING }),
)
val SNAP_RESIZE_WITH_DRAG_NON_RESIZABLE =
diff --git a/libs/WindowManager/Shell/tests/e2e/splitscreen/scenarios/src/com/android/wm/shell/scenarios/SwitchBackToSplitFromAnotherApp.kt b/libs/WindowManager/Shell/tests/e2e/splitscreen/scenarios/src/com/android/wm/shell/scenarios/SwitchBackToSplitFromAnotherApp.kt
index 2ccffa85..a3d6020 100644
--- a/libs/WindowManager/Shell/tests/e2e/splitscreen/scenarios/src/com/android/wm/shell/scenarios/SwitchBackToSplitFromAnotherApp.kt
+++ b/libs/WindowManager/Shell/tests/e2e/splitscreen/scenarios/src/com/android/wm/shell/scenarios/SwitchBackToSplitFromAnotherApp.kt
@@ -66,5 +66,6 @@
fun teardown() {
primaryApp.exit(wmHelper)
secondaryApp.exit(wmHelper)
+ Utils.resetFreezeRecentTaskList()
}
}
diff --git a/libs/WindowManager/Shell/tests/e2e/splitscreen/scenarios/src/com/android/wm/shell/scenarios/SwitchBackToSplitFromHome.kt b/libs/WindowManager/Shell/tests/e2e/splitscreen/scenarios/src/com/android/wm/shell/scenarios/SwitchBackToSplitFromHome.kt
index 8673c46..9c7de05 100644
--- a/libs/WindowManager/Shell/tests/e2e/splitscreen/scenarios/src/com/android/wm/shell/scenarios/SwitchBackToSplitFromHome.kt
+++ b/libs/WindowManager/Shell/tests/e2e/splitscreen/scenarios/src/com/android/wm/shell/scenarios/SwitchBackToSplitFromHome.kt
@@ -65,5 +65,6 @@
fun teardown() {
primaryApp.exit(wmHelper)
secondaryApp.exit(wmHelper)
+ Utils.resetFreezeRecentTaskList()
}
}
diff --git a/libs/WindowManager/Shell/tests/e2e/splitscreen/scenarios/src/com/android/wm/shell/scenarios/SwitchBackToSplitFromRecent.kt b/libs/WindowManager/Shell/tests/e2e/splitscreen/scenarios/src/com/android/wm/shell/scenarios/SwitchBackToSplitFromRecent.kt
index 22adf6c..9eb2972 100644
--- a/libs/WindowManager/Shell/tests/e2e/splitscreen/scenarios/src/com/android/wm/shell/scenarios/SwitchBackToSplitFromRecent.kt
+++ b/libs/WindowManager/Shell/tests/e2e/splitscreen/scenarios/src/com/android/wm/shell/scenarios/SwitchBackToSplitFromRecent.kt
@@ -68,5 +68,6 @@
fun teardown() {
primaryApp.exit(wmHelper)
secondaryApp.exit(wmHelper)
+ Utils.resetFreezeRecentTaskList()
}
}
diff --git a/libs/WindowManager/Shell/tests/e2e/splitscreen/scenarios/src/com/android/wm/shell/scenarios/SwitchBetweenSplitPairs.kt b/libs/WindowManager/Shell/tests/e2e/splitscreen/scenarios/src/com/android/wm/shell/scenarios/SwitchBetweenSplitPairs.kt
index 4ded148..d833d91 100644
--- a/libs/WindowManager/Shell/tests/e2e/splitscreen/scenarios/src/com/android/wm/shell/scenarios/SwitchBetweenSplitPairs.kt
+++ b/libs/WindowManager/Shell/tests/e2e/splitscreen/scenarios/src/com/android/wm/shell/scenarios/SwitchBetweenSplitPairs.kt
@@ -68,5 +68,6 @@
secondaryApp.exit(wmHelper)
thirdApp.exit(wmHelper)
fourthApp.exit(wmHelper)
+ Utils.resetFreezeRecentTaskList()
}
}
diff --git a/libs/WindowManager/Shell/tests/e2e/utils/src/com/android/wm/shell/Utils.kt b/libs/WindowManager/Shell/tests/e2e/utils/src/com/android/wm/shell/Utils.kt
index c0fafef..4a9e73b 100644
--- a/libs/WindowManager/Shell/tests/e2e/utils/src/com/android/wm/shell/Utils.kt
+++ b/libs/WindowManager/Shell/tests/e2e/utils/src/com/android/wm/shell/Utils.kt
@@ -28,7 +28,10 @@
import android.tools.flicker.rules.ChangeDisplayOrientationRule
import android.tools.flicker.rules.LaunchAppRule
import android.tools.flicker.rules.RemoveAllTasksButHomeRule
+import android.util.Log
import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.uiautomator.UiDevice
+import java.io.IOException
import org.junit.rules.RuleChain
object Utils {
@@ -52,4 +55,17 @@
.around(PressHomeRule())
.around(EnsureDeviceSettingsRule())
}
+
+ /**
+ * Resets the frozen recent tasks list (ie. commits the quickswitch to the current task and
+ * reorders the current task to the end of the recents list).
+ */
+ fun resetFreezeRecentTaskList() {
+ try {
+ UiDevice.getInstance(instrumentation)
+ .executeShellCommand("wm reset-freeze-recent-tasks")
+ } catch (e: IOException) {
+ Log.e("TestUtils", "Failed to reset frozen recent tasks list", e)
+ }
+ }
}
diff --git a/libs/androidfw/ApkAssets.cpp b/libs/androidfw/ApkAssets.cpp
index 49254d1..dbb8914 100644
--- a/libs/androidfw/ApkAssets.cpp
+++ b/libs/androidfw/ApkAssets.cpp
@@ -40,20 +40,21 @@
}
ApkAssetsPtr ApkAssets::Load(const std::string& path, package_property_t flags) {
- return Load(ZipAssetsProvider::Create(path, flags), flags);
+ return LoadImpl(ZipAssetsProvider::Create(path, flags), flags);
}
ApkAssetsPtr ApkAssets::LoadFromFd(base::unique_fd fd, const std::string& debug_name,
package_property_t flags, off64_t offset, off64_t len) {
- return Load(ZipAssetsProvider::Create(std::move(fd), debug_name, offset, len), flags);
+ return LoadImpl(ZipAssetsProvider::Create(std::move(fd), debug_name, offset, len), flags);
}
-ApkAssetsPtr ApkAssets::Load(std::unique_ptr<AssetsProvider> assets, package_property_t flags) {
+ApkAssetsPtr ApkAssets::LoadImpl(std::unique_ptr<AssetsProvider>&& assets,
+ package_property_t flags) {
return LoadImpl(std::move(assets), flags, nullptr /* idmap_asset */, nullptr /* loaded_idmap */);
}
-ApkAssetsPtr ApkAssets::LoadTable(std::unique_ptr<Asset> resources_asset,
- std::unique_ptr<AssetsProvider> assets,
+ApkAssetsPtr ApkAssets::LoadTable(std::unique_ptr<Asset>&& resources_asset,
+ std::unique_ptr<AssetsProvider>&& assets,
package_property_t flags) {
if (resources_asset == nullptr) {
return {};
@@ -97,10 +98,10 @@
std::move(loaded_idmap));
}
-ApkAssetsPtr ApkAssets::LoadImpl(std::unique_ptr<AssetsProvider> assets,
+ApkAssetsPtr ApkAssets::LoadImpl(std::unique_ptr<AssetsProvider>&& assets,
package_property_t property_flags,
- std::unique_ptr<Asset> idmap_asset,
- std::unique_ptr<LoadedIdmap> loaded_idmap) {
+ std::unique_ptr<Asset>&& idmap_asset,
+ std::unique_ptr<LoadedIdmap>&& loaded_idmap) {
if (assets == nullptr) {
return {};
}
@@ -119,11 +120,11 @@
std::move(idmap_asset), std::move(loaded_idmap));
}
-ApkAssetsPtr ApkAssets::LoadImpl(std::unique_ptr<Asset> resources_asset,
- std::unique_ptr<AssetsProvider> assets,
+ApkAssetsPtr ApkAssets::LoadImpl(std::unique_ptr<Asset>&& resources_asset,
+ std::unique_ptr<AssetsProvider>&& assets,
package_property_t property_flags,
- std::unique_ptr<Asset> idmap_asset,
- std::unique_ptr<LoadedIdmap> loaded_idmap) {
+ std::unique_ptr<Asset>&& idmap_asset,
+ std::unique_ptr<LoadedIdmap>&& loaded_idmap) {
if (assets == nullptr ) {
return {};
}
diff --git a/libs/androidfw/include/androidfw/ApkAssets.h b/libs/androidfw/include/androidfw/ApkAssets.h
index 1fa6752..231808b 100644
--- a/libs/androidfw/include/androidfw/ApkAssets.h
+++ b/libs/androidfw/include/androidfw/ApkAssets.h
@@ -47,13 +47,37 @@
package_property_t flags = 0U, off64_t offset = 0,
off64_t len = AssetsProvider::kUnknownLength);
+ //
// Creates an ApkAssets from an AssetProvider.
- // The ApkAssets will take care of destroying the AssetsProvider when it is destroyed.
- static ApkAssetsPtr Load(std::unique_ptr<AssetsProvider> assets, package_property_t flags = 0U);
+ // The ApkAssets will take care of destroying the AssetsProvider when it is destroyed;
+ // the original argument is not moved from if loading fails.
+ //
+ // Note: this function takes care of the case when you pass a move(unique_ptr<Derived>)
+ // that would create a temporary unique_ptr<AssetsProvider> by moving your pointer into
+ // it before the function call, making it impossible to not move from the parameter
+ // on loading failure. The two overloads take care of moving the pointer back if needed.
+ //
+
+ template <class T>
+ static ApkAssetsPtr Load(std::unique_ptr<T>&& assets, package_property_t flags = 0U)
+ requires(std::is_same_v<T, AssetsProvider>) {
+ return LoadImpl(std::move(assets), flags);
+ }
+
+ template <class T>
+ static ApkAssetsPtr Load(std::unique_ptr<T>&& assets, package_property_t flags = 0U)
+ requires(!std::is_same_v<T, AssetsProvider> && std::is_base_of_v<AssetsProvider, T>) {
+ std::unique_ptr<AssetsProvider> base_assets(std::move(assets));
+ auto res = LoadImpl(std::move(base_assets), flags);
+ if (!res) {
+ assets.reset(static_cast<T*>(base_assets.release()));
+ }
+ return res;
+ }
// Creates an ApkAssets from the given asset file representing a resources.arsc.
- static ApkAssetsPtr LoadTable(std::unique_ptr<Asset> resources_asset,
- std::unique_ptr<AssetsProvider> assets,
+ static ApkAssetsPtr LoadTable(std::unique_ptr<Asset>&& resources_asset,
+ std::unique_ptr<AssetsProvider>&& assets,
package_property_t flags = 0U);
// Creates an ApkAssets from an IDMAP, which contains the original APK path, and the overlay
@@ -94,17 +118,29 @@
bool IsUpToDate() const;
- private:
- static ApkAssetsPtr LoadImpl(std::unique_ptr<AssetsProvider> assets,
- package_property_t property_flags,
- std::unique_ptr<Asset> idmap_asset,
- std::unique_ptr<LoadedIdmap> loaded_idmap);
+ // DANGER!
+ // This is a destructive method that rips the assets provider out of ApkAssets object.
+ // It is only useful when one knows this assets object can't be used anymore, and they
+ // need the underlying assets provider back (e.g. when initialization fails for some
+ // reason).
+ std::unique_ptr<AssetsProvider> TakeAssetsProvider() && {
+ return std::move(assets_provider_);
+ }
- static ApkAssetsPtr LoadImpl(std::unique_ptr<Asset> resources_asset,
- std::unique_ptr<AssetsProvider> assets,
+ private:
+ static ApkAssetsPtr LoadImpl(std::unique_ptr<AssetsProvider>&& assets,
package_property_t property_flags,
- std::unique_ptr<Asset> idmap_asset,
- std::unique_ptr<LoadedIdmap> loaded_idmap);
+ std::unique_ptr<Asset>&& idmap_asset,
+ std::unique_ptr<LoadedIdmap>&& loaded_idmap);
+
+ static ApkAssetsPtr LoadImpl(std::unique_ptr<Asset>&& resources_asset,
+ std::unique_ptr<AssetsProvider>&& assets,
+ package_property_t property_flags,
+ std::unique_ptr<Asset>&& idmap_asset,
+ std::unique_ptr<LoadedIdmap>&& loaded_idmap);
+
+ static ApkAssetsPtr LoadImpl(std::unique_ptr<AssetsProvider>&& assets,
+ package_property_t flags = 0U);
// Allows us to make it possible to call make_shared from inside the class but still keeps the
// ctor 'private' for all means and purposes.
diff --git a/libs/androidfw/tests/ApkAssets_test.cpp b/libs/androidfw/tests/ApkAssets_test.cpp
index 70326b7..c36d990 100644
--- a/libs/androidfw/tests/ApkAssets_test.cpp
+++ b/libs/androidfw/tests/ApkAssets_test.cpp
@@ -28,6 +28,7 @@
using ::com::android::basic::R;
using ::testing::Eq;
using ::testing::Ge;
+using ::testing::IsNull;
using ::testing::NotNull;
using ::testing::SizeIs;
using ::testing::StrEq;
@@ -108,4 +109,26 @@
EXPECT_THAT(buffer, StrEq("This should be uncompressed.\n\n"));
}
+TEST(ApkAssetsTest, TakeAssetsProviderNotCrashing) {
+ // Make sure the apk assets object can survive taking its assets provider and doesn't crash
+ // the process.
+ {
+ auto loaded_apk = ApkAssets::Load(GetTestDataPath() + "/basic/basic.apk");
+ ASSERT_THAT(loaded_apk, NotNull());
+
+ auto provider = std::move(*loaded_apk).TakeAssetsProvider();
+ ASSERT_THAT(provider, NotNull());
+ }
+ // If this test doesn't crash by this point we're all good.
+}
+
+TEST(ApkAssetsTest, AssetsProviderNotMovedOnError) {
+ auto assets_provider
+ = ZipAssetsProvider::Create(GetTestDataPath() + "/bad/bad.apk", 0);
+ ASSERT_THAT(assets_provider, NotNull());
+ auto loaded_apk = ApkAssets::Load(std::move(assets_provider));
+ ASSERT_THAT(loaded_apk, IsNull());
+ ASSERT_THAT(assets_provider, NotNull());
+}
+
} // namespace android
diff --git a/libs/androidfw/tests/data/bad/bad.apk b/libs/androidfw/tests/data/bad/bad.apk
new file mode 100644
index 0000000..3226bcd5
--- /dev/null
+++ b/libs/androidfw/tests/data/bad/bad.apk
Binary files differ
diff --git a/libs/input/MouseCursorController.cpp b/libs/input/MouseCursorController.cpp
index 28d96e3..65663d0 100644
--- a/libs/input/MouseCursorController.cpp
+++ b/libs/input/MouseCursorController.cpp
@@ -49,8 +49,7 @@
mLocked.lastFrameUpdatedTime = 0;
mLocked.pointerFadeDirection = 0;
- mLocked.pointerX = 0;
- mLocked.pointerY = 0;
+ mLocked.pointerPosition = {0, 0};
mLocked.pointerAlpha = 0.0f; // pointer is initially faded
mLocked.pointerSprite = mContext.getSpriteController().createSprite();
mLocked.updatePointerIcon = false;
@@ -66,11 +65,11 @@
mLocked.pointerSprite.clear();
}
-FloatPoint MouseCursorController::move(float deltaX, float deltaY) {
+vec2 MouseCursorController::move(vec2 delta) {
#if DEBUG_MOUSE_CURSOR_UPDATES
ALOGD("Move pointer by deltaX=%0.3f, deltaY=%0.3f", deltaX, deltaY);
#endif
- if (deltaX == 0.0f && deltaY == 0.0f) {
+ if (delta.x == 0.0f && delta.y == 0.0f) {
return {0, 0};
}
@@ -78,19 +77,19 @@
// if there's another display on the other side of the transition. At this point we still need
// to move the cursor to the boundary.
std::scoped_lock lock(mLock);
- const FloatPoint position{mLocked.pointerX + deltaX, mLocked.pointerY + deltaY};
- setPositionLocked(position.x, position.y);
+ const vec2 targetPosition = mLocked.pointerPosition + delta;
+ setPositionLocked(targetPosition);
// The amount of the delta that was not consumed as a result of the cursor
// hitting the edge of the display.
- return {position.x - mLocked.pointerX, position.y - mLocked.pointerY};
+ return targetPosition - mLocked.pointerPosition;
}
-void MouseCursorController::setPosition(float x, float y) {
+void MouseCursorController::setPosition(vec2 position) {
#if DEBUG_MOUSE_CURSOR_UPDATES
ALOGD("Set pointer position to x=%0.3f, y=%0.3f", x, y);
#endif
std::scoped_lock lock(mLock);
- setPositionLocked(x, y);
+ setPositionLocked(position);
}
FloatRect MouseCursorController::getBoundsLocked() REQUIRES(mLock) {
@@ -105,21 +104,21 @@
};
}
-void MouseCursorController::setPositionLocked(float x, float y) REQUIRES(mLock) {
+void MouseCursorController::setPositionLocked(vec2 position) REQUIRES(mLock) {
const auto& v = mLocked.viewport;
if (!v.isValid()) return;
const FloatRect bounds = getBoundsLocked();
- mLocked.pointerX = std::max(bounds.left, std::min(bounds.right, x));
- mLocked.pointerY = std::max(bounds.top, std::min(bounds.bottom, y));
+ mLocked.pointerPosition.x = std::max(bounds.left, std::min(bounds.right, position.x));
+ mLocked.pointerPosition.y = std::max(bounds.top, std::min(bounds.bottom, position.y));
updatePointerLocked();
}
-FloatPoint MouseCursorController::getPosition() const {
+vec2 MouseCursorController::getPosition() const {
std::scoped_lock lock(mLock);
- return {mLocked.pointerX, mLocked.pointerY};
+ return mLocked.pointerPosition;
}
ui::LogicalDisplayId MouseCursorController::getDisplayId() const {
@@ -221,20 +220,21 @@
if (viewport.isValid()) {
// Use integer coordinates as the starting point for the cursor location.
// We usually expect display sizes to be even numbers, so the flooring is precautionary.
- mLocked.pointerX = std::floor((viewport.logicalLeft + viewport.logicalRight) / 2);
- mLocked.pointerY = std::floor((viewport.logicalTop + viewport.logicalBottom) / 2);
+ mLocked.pointerPosition.x =
+ std::floor((viewport.logicalLeft + viewport.logicalRight) / 2);
+ mLocked.pointerPosition.y =
+ std::floor((viewport.logicalTop + viewport.logicalBottom) / 2);
// Reload icon resources for density may be changed.
loadResourcesLocked(getAdditionalMouseResources);
} else {
- mLocked.pointerX = 0;
- mLocked.pointerY = 0;
+ mLocked.pointerPosition = {0, 0};
}
} else if (oldViewport.orientation != viewport.orientation) {
// Apply offsets to convert from the pixel top-left corner position to the pixel center.
// This creates an invariant frame of reference that we can easily rotate when
// taking into account that the pointer may be located at fractional pixel offsets.
- float x = mLocked.pointerX + 0.5f;
- float y = mLocked.pointerY + 0.5f;
+ float x = mLocked.pointerPosition.x + 0.5f;
+ float y = mLocked.pointerPosition.y + 0.5f;
float temp;
// Undo the previous rotation.
@@ -279,8 +279,8 @@
// Apply offsets to convert from the pixel center to the pixel top-left corner position
// and save the results.
- mLocked.pointerX = x - 0.5f;
- mLocked.pointerY = y - 0.5f;
+ mLocked.pointerPosition.x = x - 0.5f;
+ mLocked.pointerPosition.y = y - 0.5f;
}
updatePointerLocked();
@@ -366,7 +366,7 @@
spriteController.openTransaction();
mLocked.pointerSprite->setLayer(Sprite::BASE_LAYER_POINTER);
- mLocked.pointerSprite->setPosition(mLocked.pointerX, mLocked.pointerY);
+ mLocked.pointerSprite->setPosition(mLocked.pointerPosition.x, mLocked.pointerPosition.y);
mLocked.pointerSprite->setDisplayId(mLocked.viewport.displayId);
mLocked.pointerSprite->setSkipScreenshot(mLocked.skipScreenshot);
diff --git a/libs/input/MouseCursorController.h b/libs/input/MouseCursorController.h
index e14a55d..7c674b5 100644
--- a/libs/input/MouseCursorController.h
+++ b/libs/input/MouseCursorController.h
@@ -41,9 +41,9 @@
~MouseCursorController();
// Move the pointer and return unconsumed delta
- FloatPoint move(float deltaX, float deltaY);
- void setPosition(float x, float y);
- FloatPoint getPosition() const;
+ vec2 move(vec2 delta);
+ void setPosition(vec2 position);
+ vec2 getPosition() const;
ui::LogicalDisplayId getDisplayId() const;
void fade(PointerControllerInterface::Transition transition);
void unfade(PointerControllerInterface::Transition transition);
@@ -81,8 +81,7 @@
nsecs_t lastFrameUpdatedTime;
int32_t pointerFadeDirection;
- float pointerX;
- float pointerY;
+ vec2 pointerPosition;
float pointerAlpha;
sp<Sprite> pointerSprite;
SpriteIcon pointerIcon;
@@ -101,7 +100,7 @@
} mLocked GUARDED_BY(mLock);
- void setPositionLocked(float x, float y);
+ void setPositionLocked(vec2 position);
void updatePointerLocked();
diff --git a/libs/input/PointerController.cpp b/libs/input/PointerController.cpp
index a713f1d..0b81211 100644
--- a/libs/input/PointerController.cpp
+++ b/libs/input/PointerController.cpp
@@ -138,7 +138,7 @@
return mDisplayInfoListener->mLock;
}
-FloatPoint PointerController::move(float deltaX, float deltaY) {
+vec2 PointerController::move(float deltaX, float deltaY) {
const ui::LogicalDisplayId displayId = mCursorController.getDisplayId();
ui::Transform transform;
{
@@ -147,10 +147,7 @@
}
const vec2 transformed = transformWithoutTranslation(transform, {deltaX, deltaY});
-
- const FloatPoint unconsumedDelta = mCursorController.move(transformed.x, transformed.y);
- return FloatPoint(transformWithoutTranslation(transform.inverse(),
- {unconsumedDelta.x, unconsumedDelta.y}));
+ return transformWithoutTranslation(transform.inverse(), mCursorController.move(transformed));
}
void PointerController::setPosition(float x, float y) {
@@ -161,16 +158,15 @@
const auto& transform = getTransformForDisplayLocked(displayId);
transformed = transform.transform(x, y);
}
- mCursorController.setPosition(transformed.x, transformed.y);
+ mCursorController.setPosition(transformed);
}
-FloatPoint PointerController::getPosition() const {
+vec2 PointerController::getPosition() const {
const ui::LogicalDisplayId displayId = mCursorController.getDisplayId();
const auto p = mCursorController.getPosition();
{
std::scoped_lock lock(getLock());
- const auto& transform = getTransformForDisplayLocked(displayId);
- return FloatPoint{transform.inverse().transform(p.x, p.y)};
+ return getTransformForDisplayLocked(displayId).inverse().transform(p.x, p.y);
}
}
diff --git a/libs/input/PointerController.h b/libs/input/PointerController.h
index 8b33190..afd7215 100644
--- a/libs/input/PointerController.h
+++ b/libs/input/PointerController.h
@@ -51,9 +51,9 @@
~PointerController() override;
- FloatPoint move(float deltaX, float deltaY) override;
+ vec2 move(float deltaX, float deltaY) override;
void setPosition(float x, float y) override;
- FloatPoint getPosition() const override;
+ vec2 getPosition() const override;
ui::LogicalDisplayId getDisplayId() const override;
void fade(Transition transition) override;
void unfade(Transition transition) override;
@@ -166,13 +166,13 @@
~TouchPointerController() override;
- FloatPoint move(float, float) override {
+ vec2 move(float, float) override {
LOG_ALWAYS_FATAL("Should not be called");
}
void setPosition(float, float) override {
LOG_ALWAYS_FATAL("Should not be called");
}
- FloatPoint getPosition() const override {
+ vec2 getPosition() const override {
LOG_ALWAYS_FATAL("Should not be called");
}
ui::LogicalDisplayId getDisplayId() const override {
diff --git a/packages/LocalTransport/src/com/android/localtransport/LocalTransport.java b/packages/LocalTransport/src/com/android/localtransport/LocalTransport.java
index 6a4bb21..a3b06e8 100644
--- a/packages/LocalTransport/src/com/android/localtransport/LocalTransport.java
+++ b/packages/LocalTransport/src/com/android/localtransport/LocalTransport.java
@@ -16,8 +16,10 @@
package com.android.localtransport;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.backup.BackupAgent;
+import android.app.backup.BackupAnnotations;
import android.app.backup.BackupDataInput;
import android.app.backup.BackupDataOutput;
import android.app.backup.BackupManagerMonitor;
@@ -52,6 +54,7 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
+import java.util.List;
/**
* Backup transport for stashing stuff into a known location on disk, and
@@ -939,4 +942,15 @@
}
}
}
+
+ @NonNull
+ @Override
+ public List<String> getPackagesThatShouldNotUseRestrictedMode(
+ @NonNull List<String> packageNames,
+ @BackupAnnotations.OperationType int operationType) {
+ if (DEBUG) {
+ Log.d(TAG, "No restricted mode packages: " + mParameters.noRestrictedModePackages());
+ }
+ return mParameters.noRestrictedModePackages();
+ }
}
diff --git a/packages/LocalTransport/src/com/android/localtransport/LocalTransportParameters.java b/packages/LocalTransport/src/com/android/localtransport/LocalTransportParameters.java
index aaa18bf..c980913 100644
--- a/packages/LocalTransport/src/com/android/localtransport/LocalTransportParameters.java
+++ b/packages/LocalTransport/src/com/android/localtransport/LocalTransportParameters.java
@@ -16,26 +16,33 @@
package com.android.localtransport;
-import android.util.KeyValueSettingObserver;
import android.content.ContentResolver;
import android.os.Handler;
import android.provider.Settings;
import android.util.KeyValueListParser;
+import android.util.KeyValueSettingObserver;
+
+import java.util.Arrays;
+import java.util.List;
public class LocalTransportParameters extends KeyValueSettingObserver {
- private static final String TAG = "LocalTransportParams";
private static final String SETTING = Settings.Secure.BACKUP_LOCAL_TRANSPORT_PARAMETERS;
private static final String KEY_FAKE_ENCRYPTION_FLAG = "fake_encryption_flag";
private static final String KEY_NON_INCREMENTAL_ONLY = "non_incremental_only";
private static final String KEY_IS_DEVICE_TRANSFER = "is_device_transfer";
private static final String KEY_IS_ENCRYPTED = "is_encrypted";
private static final String KEY_LOG_AGENT_RESULTS = "log_agent_results";
+ // This needs to be a list of package names separated by semicolons. For example:
+ // "com.package1;com.package2;com.package3". We can't use commas because the base class uses
+ // commas to split Key/Value pairs.
+ private static final String KEY_NO_RESTRICTED_MODE_PACKAGES = "no_restricted_mode_packages";
private boolean mFakeEncryptionFlag;
private boolean mIsNonIncrementalOnly;
private boolean mIsDeviceTransfer;
private boolean mIsEncrypted;
private boolean mLogAgentResults;
+ private String mNoRestrictedModePackages;
public LocalTransportParameters(Handler handler, ContentResolver resolver) {
super(handler, resolver, Settings.Secure.getUriFor(SETTING));
@@ -61,6 +68,13 @@
return mLogAgentResults;
}
+ List<String> noRestrictedModePackages() {
+ if (mNoRestrictedModePackages == null) {
+ return List.of();
+ }
+ return Arrays.stream(mNoRestrictedModePackages.split(";")).toList();
+ }
+
public String getSettingValue(ContentResolver resolver) {
return Settings.Secure.getString(resolver, SETTING);
}
@@ -71,5 +85,6 @@
mIsDeviceTransfer = parser.getBoolean(KEY_IS_DEVICE_TRANSFER, false);
mIsEncrypted = parser.getBoolean(KEY_IS_ENCRYPTED, false);
mLogAgentResults = parser.getBoolean(KEY_LOG_AGENT_RESULTS, /* def */ false);
+ mNoRestrictedModePackages = parser.getString(KEY_NO_RESTRICTED_MODE_PACKAGES, /* def */ "");
}
}
diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig
index 5b280486..c1f7868 100644
--- a/packages/SystemUI/aconfig/systemui.aconfig
+++ b/packages/SystemUI/aconfig/systemui.aconfig
@@ -1879,3 +1879,10 @@
description: "Implement the depth push scaling effect on the current app when users pull down shade."
bug: "370560660"
}
+
+flag {
+ name: "expanded_privacy_indicators_on_large_screen"
+ namespace: "systemui"
+ description: "Larger privacy indicators on large screen"
+ bug: "381864715"
+}
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt
index 7a8d20a..caf5e41 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt
@@ -124,7 +124,7 @@
return newDragController
}
- internal fun createSwipeAnimation(swipes: Swipes, result: UserActionResult): SwipeAnimation<*> {
+ private fun createSwipeAnimation(swipes: Swipes, result: UserActionResult): SwipeAnimation<*> {
val upOrLeftResult = swipes.upOrLeftResult
val downOrRightResult = swipes.downOrRightResult
val isUpOrLeft =
@@ -248,38 +248,8 @@
else -> desiredOffset.fastCoerceIn(distance, 0f)
}
- val consumedDelta = newOffset - previousOffset
-
swipeAnimation.dragOffset = newOffset
- val result = swipes.findUserActionResult(directionOffset = newOffset)
-
- if (result == null) {
- onCancel(canChangeContent = true)
- return 0f
- }
-
- val currentTransitionIrreversible =
- if (swipeAnimation.isUpOrLeft) {
- swipes.upOrLeftResult?.isIrreversible ?: false
- } else {
- swipes.downOrRightResult?.isIrreversible ?: false
- }
-
- val needNewTransition =
- !currentTransitionIrreversible &&
- (result.toContent(layoutState.currentScene) != swipeAnimation.toContent ||
- result.transitionKey != swipeAnimation.contentTransition.key)
-
- if (needNewTransition) {
- // Make sure the current transition will finish to the right current scene.
- swipeAnimation.currentContent = swipeAnimation.fromContent
-
- val newSwipeAnimation = draggableHandler.createSwipeAnimation(swipes, result)
- newSwipeAnimation.dragOffset = newOffset
- updateTransition(newSwipeAnimation)
- }
-
- return consumedDelta
+ return newOffset - previousOffset
}
override suspend fun onStop(velocity: Float, canChangeContent: Boolean): Float {
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt
index 759100b..a14b2b3 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt
@@ -554,12 +554,6 @@
* bigger than 100% when the user released their finger. `
*/
open val requiresFullDistanceSwipe: Boolean,
-
- /**
- * Whether swiping back in the opposite direction past the origin point of the swipe can replace
- * the action with the action for the opposite direction.
- */
- open val isIrreversible: Boolean = false,
) {
internal abstract fun toContent(currentScene: SceneKey): ContentKey
@@ -569,7 +563,6 @@
val toScene: SceneKey,
override val transitionKey: TransitionKey? = null,
override val requiresFullDistanceSwipe: Boolean = false,
- override val isIrreversible: Boolean = false,
) : UserActionResult(transitionKey, requiresFullDistanceSwipe) {
override fun toContent(currentScene: SceneKey): ContentKey = toScene
}
@@ -579,7 +572,6 @@
val overlay: OverlayKey,
override val transitionKey: TransitionKey? = null,
override val requiresFullDistanceSwipe: Boolean = false,
- override val isIrreversible: Boolean = false,
) : UserActionResult(transitionKey, requiresFullDistanceSwipe) {
override fun toContent(currentScene: SceneKey): ContentKey = overlay
}
@@ -622,14 +614,7 @@
* the user released their finger.
*/
requiresFullDistanceSwipe: Boolean = false,
-
- /**
- * Whether swiping back in the opposite direction past the origin point of the swipe can
- * replace the action with the action for the opposite direction.
- */
- isIrreversible: Boolean = false,
- ): UserActionResult =
- ChangeScene(toScene, transitionKey, requiresFullDistanceSwipe, isIrreversible)
+ ): UserActionResult = ChangeScene(toScene, transitionKey, requiresFullDistanceSwipe)
/** A [UserActionResult] that shows [toOverlay]. */
operator fun invoke(
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt
index 394568d..2c8dc32 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt
@@ -418,37 +418,6 @@
}
@Test
- fun onDragReversedDirection_changeToScene() = runGestureTest {
- // Drag A -> B with progress 0.6
- val dragController = onDragStarted(overSlop = -60f)
- assertTransition(
- currentScene = SceneA,
- fromScene = SceneA,
- toScene = SceneB,
- progress = 0.6f,
- )
-
- // Reverse direction such that A -> C now with 0.4
- dragController.onDragDelta(pixels = 100f)
- assertTransition(
- currentScene = SceneA,
- fromScene = SceneA,
- toScene = SceneC,
- progress = 0.4f,
- )
-
- // After the drag stopped scene C should be committed
- dragController.onDragStoppedAnimateNow(
- velocity = velocityThreshold,
- onAnimationStart = {
- assertTransition(currentScene = SceneC, fromScene = SceneA, toScene = SceneC)
- },
- expectedConsumedVelocity = velocityThreshold,
- )
- assertIdle(currentScene = SceneC)
- }
-
- @Test
fun onDragStartedWithoutActionsInBothDirections_stayIdle() = runGestureTest {
onDragStarted(
horizontalDraggableHandler,
@@ -498,31 +467,9 @@
}
@Test
- fun onDragWithActionsInBothDirections_dragToOppositeDirectionReplacesAction() = runGestureTest {
- // We are on SceneA. UP -> B, DOWN-> C.
- val dragController = onDragStarted(overSlop = up(fractionOfScreen = 0.2f))
- assertTransition(
- currentScene = SceneA,
- fromScene = SceneA,
- toScene = SceneB,
- progress = 0.2f,
- )
-
- // Reverse drag direction, it will replace the previous transition
- dragController.onDragDelta(pixels = down(fractionOfScreen = 0.5f))
- assertTransition(
- currentScene = SceneA,
- fromScene = SceneA,
- toScene = SceneC,
- progress = 0.3f,
- )
- }
-
- @Test
fun onDragWithActionsInBothDirections_dragToOppositeDirectionNotReplaceable() = runGestureTest {
// We are on SceneA. UP -> B, DOWN-> C. The up swipe is not replaceable though.
- mutableUserActionsA =
- mapOf(Swipe.Up to UserActionResult(SceneB, isIrreversible = true), Swipe.Down to SceneC)
+ mutableUserActionsA = mapOf(Swipe.Up to UserActionResult(SceneB), Swipe.Down to SceneC)
val dragController =
onDragStarted(
pointersInfo =
@@ -536,7 +483,7 @@
progress = 0.2f,
)
- // Reverse drag direction, it cannot replace the previous transition
+ // Reverse drag direction, it does not replace the previous transition.
dragController.onDragDelta(pixels = down(fractionOfScreen = 0.5f))
assertTransition(
currentScene = SceneA,
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SwipeToSceneTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SwipeToSceneTest.kt
index b3a3261..fe7b5b6 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SwipeToSceneTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SwipeToSceneTest.kt
@@ -664,17 +664,11 @@
}
}
- // Swipe down for the default transition from A to B.
- rule.onRoot().performTouchInput {
- down(middle)
- moveBy(Offset(0f, touchSlop), delayMillis = 1_000)
- }
-
- assertThat(state.isTransitioning(from = SceneA, to = SceneB)).isTrue()
- assertThat(state.currentTransition?.transformationSpec?.transformationMatchers).hasSize(1)
-
// Move the pointer up to swipe to scene B using the new transition.
- rule.onRoot().performTouchInput { moveBy(Offset(0f, -1.dp.toPx()), delayMillis = 1_000) }
+ rule.onRoot().performTouchInput {
+ down(center)
+ moveBy(Offset(0f, -touchSlop - 1.dp.toPx()), delayMillis = 1_000)
+ }
assertThat(state.isTransitioning(from = SceneA, to = SceneB)).isTrue()
assertThat(state.currentTransition?.transformationSpec?.transformationMatchers).hasSize(2)
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/ExpandHelperTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/ExpandHelperTest.java
index 1b07241..7fb879c 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/ExpandHelperTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/ExpandHelperTest.java
@@ -31,7 +31,7 @@
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.animation.AnimatorTestRule;
-import com.android.systemui.flags.FakeFeatureFlags;
+import com.android.systemui.flags.FakeFeatureFlagsClassic;
import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationTestHelper;
@@ -49,7 +49,7 @@
@Rule
public final AnimatorTestRule mAnimatorTestRule = new AnimatorTestRule(this);
- private final FakeFeatureFlags mFeatureFlags = new FakeFeatureFlags();
+ private final FakeFeatureFlagsClassic mFeatureFlags = new FakeFeatureFlagsClassic();
private ExpandableNotificationRow mRow;
private ExpandHelper mExpandHelper;
private ExpandHelper.Callback mCallback;
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/ui/viewmodel/CommunalUserActionsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/ui/viewmodel/CommunalUserActionsViewModelTest.kt
index 755c4eb..ca7e203 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/ui/viewmodel/CommunalUserActionsViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/ui/viewmodel/CommunalUserActionsViewModelTest.kt
@@ -85,8 +85,7 @@
assertThat(actions).isNotEmpty()
assertThat(actions?.get(Swipe.End)).isEqualTo(UserActionResult(SceneFamilies.Home))
assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Bouncer))
- assertThat(actions?.get(Swipe.Down))
- .isEqualTo(UserActionResult(Scenes.Shade, isIrreversible = true))
+ assertThat(actions?.get(Swipe.Down)).isEqualTo(UserActionResult(Scenes.Shade))
setUpState(
isShadeTouchable = false,
@@ -103,8 +102,7 @@
assertThat(actions).isNotEmpty()
assertThat(actions?.get(Swipe.End)).isEqualTo(UserActionResult(SceneFamilies.Home))
assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Gone))
- assertThat(actions?.get(Swipe.Down))
- .isEqualTo(UserActionResult(Scenes.Shade, isIrreversible = true))
+ assertThat(actions?.get(Swipe.Down)).isEqualTo(UserActionResult(Scenes.Shade))
}
@Test
@@ -122,7 +120,7 @@
assertThat(actions?.get(Swipe.End)).isEqualTo(UserActionResult(SceneFamilies.Home))
assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Bouncer))
assertThat(actions?.get(Swipe.Down))
- .isEqualTo(UserActionResult(Scenes.Shade, ToSplitShade, isIrreversible = true))
+ .isEqualTo(UserActionResult(Scenes.Shade, ToSplitShade))
setUpState(
isShadeTouchable = false,
@@ -140,7 +138,7 @@
assertThat(actions?.get(Swipe.End)).isEqualTo(UserActionResult(SceneFamilies.Home))
assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Gone))
assertThat(actions?.get(Swipe.Down))
- .isEqualTo(UserActionResult(Scenes.Shade, ToSplitShade, isIrreversible = true))
+ .isEqualTo(UserActionResult(Scenes.Shade, ToSplitShade))
}
@Test
@@ -158,9 +156,7 @@
assertThat(actions?.get(Swipe.End)).isEqualTo(UserActionResult(SceneFamilies.Home))
assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Bouncer))
assertThat(actions?.get(Swipe.Down))
- .isEqualTo(
- UserActionResult.ShowOverlay(Overlays.NotificationsShade, isIrreversible = true)
- )
+ .isEqualTo(UserActionResult.ShowOverlay(Overlays.NotificationsShade))
setUpState(
isShadeTouchable = false,
@@ -174,9 +170,7 @@
assertThat(actions?.get(Swipe.End)).isEqualTo(UserActionResult(SceneFamilies.Home))
assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Gone))
assertThat(actions?.get(Swipe.Down))
- .isEqualTo(
- UserActionResult.ShowOverlay(Overlays.NotificationsShade, isIrreversible = true)
- )
+ .isEqualTo(UserActionResult.ShowOverlay(Overlays.NotificationsShade))
}
private fun TestScope.setUpState(
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/ui/viewmodel/DreamUserActionsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/ui/viewmodel/DreamUserActionsViewModelTest.kt
index 55b87db..d6daa79 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/ui/viewmodel/DreamUserActionsViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/ui/viewmodel/DreamUserActionsViewModelTest.kt
@@ -86,8 +86,7 @@
)
assertThat(actions).isNotEmpty()
assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Bouncer))
- assertThat(actions?.get(Swipe.Down))
- .isEqualTo(UserActionResult(Scenes.Shade, isIrreversible = true))
+ assertThat(actions?.get(Swipe.Down)).isEqualTo(UserActionResult(Scenes.Shade))
assertThat(actions?.get(Swipe.Start)).isNull()
assertThat(actions?.get(Swipe.End)).isNull()
@@ -105,8 +104,7 @@
)
assertThat(actions).isNotEmpty()
assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Gone))
- assertThat(actions?.get(Swipe.Down))
- .isEqualTo(UserActionResult(Scenes.Shade, isIrreversible = true))
+ assertThat(actions?.get(Swipe.Down)).isEqualTo(UserActionResult(Scenes.Shade))
assertThat(actions?.get(Swipe.Start)).isNull()
assertThat(actions?.get(Swipe.End)).isNull()
}
@@ -127,7 +125,7 @@
assertThat(actions).isNotEmpty()
assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Bouncer))
assertThat(actions?.get(Swipe.Down))
- .isEqualTo(UserActionResult(Scenes.Shade, ToSplitShade, isIrreversible = true))
+ .isEqualTo(UserActionResult(Scenes.Shade, ToSplitShade))
assertThat(actions?.get(Swipe.Start)).isNull()
assertThat(actions?.get(Swipe.End)).isNull()
@@ -146,7 +144,7 @@
assertThat(actions).isNotEmpty()
assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Gone))
assertThat(actions?.get(Swipe.Down))
- .isEqualTo(UserActionResult(Scenes.Shade, ToSplitShade, isIrreversible = true))
+ .isEqualTo(UserActionResult(Scenes.Shade, ToSplitShade))
assertThat(actions?.get(Swipe.Start)).isNull()
assertThat(actions?.get(Swipe.End)).isNull()
}
@@ -167,9 +165,7 @@
assertThat(actions).isNotEmpty()
assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Bouncer))
assertThat(actions?.get(Swipe.Down))
- .isEqualTo(
- UserActionResult.ShowOverlay(Overlays.NotificationsShade, isIrreversible = true)
- )
+ .isEqualTo(UserActionResult.ShowOverlay(Overlays.NotificationsShade))
assertThat(actions?.get(Swipe.Start)).isNull()
assertThat(actions?.get(Swipe.End)).isNull()
@@ -184,9 +180,7 @@
assertThat(actions).isNotEmpty()
assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Gone))
assertThat(actions?.get(Swipe.Down))
- .isEqualTo(
- UserActionResult.ShowOverlay(Overlays.NotificationsShade, isIrreversible = true)
- )
+ .isEqualTo(UserActionResult.ShowOverlay(Overlays.NotificationsShade))
assertThat(actions?.get(Swipe.Start)).isNull()
assertThat(actions?.get(Swipe.End)).isNull()
}
@@ -206,8 +200,7 @@
)
assertThat(actions).isNotEmpty()
assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Bouncer))
- assertThat(actions?.get(Swipe.Down))
- .isEqualTo(UserActionResult(Scenes.Shade, isIrreversible = true))
+ assertThat(actions?.get(Swipe.Down)).isEqualTo(UserActionResult(Scenes.Shade))
assertThat(actions?.get(Swipe.Start)).isEqualTo(UserActionResult(Scenes.Communal))
assertThat(actions?.get(Swipe.End)).isNull()
@@ -225,8 +218,7 @@
)
assertThat(actions).isNotEmpty()
assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Gone))
- assertThat(actions?.get(Swipe.Down))
- .isEqualTo(UserActionResult(Scenes.Shade, isIrreversible = true))
+ assertThat(actions?.get(Swipe.Down)).isEqualTo(UserActionResult(Scenes.Shade))
assertThat(actions?.get(Swipe.Start)).isEqualTo(UserActionResult(Scenes.Communal))
assertThat(actions?.get(Swipe.End)).isNull()
}
@@ -247,7 +239,7 @@
assertThat(actions).isNotEmpty()
assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Bouncer))
assertThat(actions?.get(Swipe.Down))
- .isEqualTo(UserActionResult(Scenes.Shade, ToSplitShade, isIrreversible = true))
+ .isEqualTo(UserActionResult(Scenes.Shade, ToSplitShade))
assertThat(actions?.get(Swipe.Start)).isEqualTo(UserActionResult(Scenes.Communal))
assertThat(actions?.get(Swipe.End)).isNull()
@@ -266,7 +258,7 @@
assertThat(actions).isNotEmpty()
assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Gone))
assertThat(actions?.get(Swipe.Down))
- .isEqualTo(UserActionResult(Scenes.Shade, ToSplitShade, isIrreversible = true))
+ .isEqualTo(UserActionResult(Scenes.Shade, ToSplitShade))
assertThat(actions?.get(Swipe.Start)).isEqualTo(UserActionResult(Scenes.Communal))
assertThat(actions?.get(Swipe.End)).isNull()
}
@@ -287,9 +279,7 @@
assertThat(actions).isNotEmpty()
assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Bouncer))
assertThat(actions?.get(Swipe.Down))
- .isEqualTo(
- UserActionResult.ShowOverlay(Overlays.NotificationsShade, isIrreversible = true)
- )
+ .isEqualTo(UserActionResult.ShowOverlay(Overlays.NotificationsShade))
assertThat(actions?.get(Swipe.Start)).isEqualTo(UserActionResult(Scenes.Communal))
assertThat(actions?.get(Swipe.End)).isNull()
@@ -304,9 +294,7 @@
assertThat(actions).isNotEmpty()
assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Gone))
assertThat(actions?.get(Swipe.Down))
- .isEqualTo(
- UserActionResult.ShowOverlay(Overlays.NotificationsShade, isIrreversible = true)
- )
+ .isEqualTo(UserActionResult.ShowOverlay(Overlays.NotificationsShade))
assertThat(actions?.get(Swipe.Start)).isEqualTo(UserActionResult(Scenes.Communal))
assertThat(actions?.get(Swipe.End)).isNull()
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/data/source/TestShortcuts.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/data/source/TestShortcuts.kt
index 407bdf8..cc718c7 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/data/source/TestShortcuts.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/data/source/TestShortcuts.kt
@@ -74,6 +74,27 @@
/* modifiers = */ KeyEvent.META_SHIFT_ON,
)
+ private val ShortcutsWithDiffSizeOfKeys =
+ KeyboardShortcutInfo(
+ /* label = */ "Shortcuts with diff size of keys",
+ /* keycode = */ KeyEvent.KEYCODE_HOME,
+ /* modifiers = */ 0,
+ )
+
+ private val ShortcutsWithDiffSizeOfKeys2 =
+ KeyboardShortcutInfo(
+ /* label = */ ShortcutsWithDiffSizeOfKeys.label,
+ /* keycode = */ KeyEvent.KEYCODE_1,
+ /* modifiers = */ META_META_ON,
+ )
+
+ private val ShortcutsWithDiffSizeOfKeys3 =
+ KeyboardShortcutInfo(
+ /* label = */ ShortcutsWithDiffSizeOfKeys.label,
+ /* keycode = */ KeyEvent.KEYCODE_2,
+ /* modifiers = */ META_META_ON or META_FUNCTION_ON,
+ )
+
private val shortcutWithGroupedRepeatedLabel =
shortcut(shortcutInfoWithRepeatedLabel.label!!.toString()) {
command {
@@ -381,6 +402,16 @@
groupWithSupportedAndUnsupportedModifierShortcut,
)
+ val groupWithDifferentSizeOfShortcutKeys =
+ KeyboardShortcutGroup(
+ "Group with different size of shortcut keys",
+ listOf(
+ ShortcutsWithDiffSizeOfKeys3,
+ ShortcutsWithDiffSizeOfKeys,
+ ShortcutsWithDiffSizeOfKeys2,
+ ),
+ )
+
val subCategoriesWithUnsupportedModifiersRemoved =
listOf(subCategoryWithStandardShortcut, subCategoryWithUnsupportedShortcutsRemoved)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/domain/interactor/ShortcutHelperCategoriesInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/domain/interactor/ShortcutHelperCategoriesInteractorTest.kt
index c3cedba..8f0bc64 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/domain/interactor/ShortcutHelperCategoriesInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/domain/interactor/ShortcutHelperCategoriesInteractorTest.kt
@@ -369,6 +369,20 @@
}
}
+ @Test
+ fun categories_showShortcutsInAscendingOrderOfKeySize() =
+ testScope.runTest {
+ systemShortcutsSource.setGroups(TestShortcuts.groupWithDifferentSizeOfShortcutKeys)
+ val categories by collectLastValue(interactor.shortcutCategories)
+
+ helper.showFromActivity()
+
+ val systemCategoryShortcuts = categories?.get(0)?.subCategories?.get(0)?.shortcuts
+ val shortcutKeyCount =
+ systemCategoryShortcuts?.flatMap { it.commands }?.map { it.keys.size }
+ assertThat(shortcutKeyCount).containsExactly(1, 2, 3).inOrder()
+ }
+
private fun setCustomInputGestures(customInputGestures: List<InputGestureData>) {
whenever(fakeInputManager.inputManager.getCustomInputGestures(/* filter= */ anyOrNull()))
.thenReturn(customInputGestures)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenUserActionsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenUserActionsViewModelTest.kt
index 62cc763..97e6763 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenUserActionsViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenUserActionsViewModelTest.kt
@@ -306,8 +306,7 @@
// Top edge is not applicable in dual shade, as well as two-finger swipe.
assertThat(downDestination).isNull()
} else {
- assertThat(downDestination)
- .isEqualTo(ShowOverlay(Overlays.NotificationsShade, isIrreversible = true))
+ assertThat(downDestination).isEqualTo(ShowOverlay(Overlays.NotificationsShade))
assertThat(downDestination?.transitionKey).isNull()
}
@@ -323,7 +322,7 @@
downWithTwoPointers -> assertThat(downFromTopRightDestination).isNull()
else -> {
assertThat(downFromTopRightDestination)
- .isEqualTo(ShowOverlay(Overlays.QuickSettingsShade, isIrreversible = true))
+ .isEqualTo(ShowOverlay(Overlays.QuickSettingsShade))
assertThat(downFromTopRightDestination?.transitionKey).isNull()
}
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/GoneUserActionsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/GoneUserActionsViewModelTest.kt
index bb2e941..fc915ca 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/GoneUserActionsViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/GoneUserActionsViewModelTest.kt
@@ -104,7 +104,7 @@
runCurrent()
assertThat(userActions?.get(swipeDownFromTopWithTwoFingers()))
- .isEqualTo(UserActionResult(Scenes.QuickSettings, isIrreversible = true))
+ .isEqualTo(UserActionResult(Scenes.QuickSettings))
}
@Test
@@ -116,7 +116,7 @@
runCurrent()
assertThat(userActions?.get(swipeDownFromTopWithTwoFingers()))
- .isEqualTo(UserActionResult(Scenes.Shade, ToSplitShade, isIrreversible = true))
+ .isEqualTo(UserActionResult(Scenes.Shade, ToSplitShade))
}
@Test
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowControllerTest.kt
index ca0f9ef..8bca17f 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowControllerTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowControllerTest.kt
@@ -28,7 +28,7 @@
import com.android.internal.logging.UiEventLogger
import com.android.internal.statusbar.IStatusBarService
import com.android.systemui.SysuiTestCase
-import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.FeatureFlagsClassic
import com.android.systemui.log.logcatLogBuffer
import com.android.systemui.plugins.FalsingManager
import com.android.systemui.plugins.PluginManager
@@ -57,9 +57,7 @@
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.withArgCaptor
import com.android.systemui.util.time.SystemClock
-import com.android.systemui.wmshell.BubblesManager
import com.google.android.msdl.domain.MSDLPlayer
-import java.util.Optional
import junit.framework.Assert
import org.junit.After
import org.junit.Before
@@ -103,9 +101,8 @@
private val gutsManager: NotificationGutsManager = mock()
private val onUserInteractionCallback: OnUserInteractionCallback = mock()
private val falsingManager: FalsingManager = mock()
- private val featureFlags: FeatureFlags = mock()
+ private val featureFlags: FeatureFlagsClassic = mock()
private val peopleNotificationIdentifier: PeopleNotificationIdentifier = mock()
- private val bubblesManager: BubblesManager = mock()
private val settingsController: NotificationSettingsController = mock()
private val dragController: ExpandableNotificationRowDragController = mock()
private val dismissibilityProvider: NotificationDismissibilityProvider = mock()
@@ -147,7 +144,6 @@
falsingManager,
featureFlags,
peopleNotificationIdentifier,
- Optional.of(bubblesManager),
settingsController,
dragController,
dismissibilityProvider,
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
index 080ac3f..b323ef8 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
@@ -25,7 +25,6 @@
import static com.android.systemui.statusbar.NotificationEntryHelper.modifyRanking;
import static com.android.systemui.util.Assert.runWithCurrentThreadAsMainThread;
-import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -59,8 +58,8 @@
import com.android.keyguard.TestScopeProvider;
import com.android.systemui.TestableDependency;
import com.android.systemui.classifier.FalsingManagerFake;
-import com.android.systemui.flags.FakeFeatureFlags;
-import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.flags.FakeFeatureFlagsClassic;
+import com.android.systemui.flags.FeatureFlagsClassic;
import com.android.systemui.media.controls.util.MediaFeatureFlag;
import com.android.systemui.media.dialog.MediaOutputDialogManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -71,7 +70,6 @@
import com.android.systemui.statusbar.SmartReplyController;
import com.android.systemui.statusbar.notification.ColorUpdateLogger;
import com.android.systemui.statusbar.notification.ConversationNotificationProcessor;
-import com.android.systemui.statusbar.notification.SourceType;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection;
@@ -79,6 +77,7 @@
import com.android.systemui.statusbar.notification.collection.provider.NotificationDismissibilityProvider;
import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager;
import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
+import com.android.systemui.statusbar.notification.headsup.HeadsUpManager;
import com.android.systemui.statusbar.notification.icon.IconBuilder;
import com.android.systemui.statusbar.notification.icon.IconManager;
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
@@ -89,7 +88,6 @@
import com.android.systemui.statusbar.notification.row.shared.NotificationRowContentBinderRefactor;
import com.android.systemui.statusbar.notification.stack.NotificationChildrenContainerLogger;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
-import com.android.systemui.statusbar.notification.headsup.HeadsUpManager;
import com.android.systemui.statusbar.policy.InflatedSmartReplyState;
import com.android.systemui.statusbar.policy.InflatedSmartReplyViewHolder;
import com.android.systemui.statusbar.policy.SmartReplyConstants;
@@ -99,7 +97,6 @@
import com.android.systemui.util.time.FakeSystemClock;
import com.android.systemui.util.time.SystemClock;
import com.android.systemui.util.time.SystemClockImpl;
-import com.android.systemui.wmshell.BubblesManager;
import com.android.systemui.wmshell.BubblesTestActivity;
import kotlin.coroutines.CoroutineContext;
@@ -109,7 +106,6 @@
import org.mockito.ArgumentCaptor;
import java.util.Objects;
-import java.util.Optional;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
@@ -149,7 +145,7 @@
private final NotificationDismissibilityProvider mDismissibilityProvider;
public final Runnable mFutureDismissalRunnable;
private @InflationFlag int mDefaultInflationFlags;
- private final FakeFeatureFlags mFeatureFlags;
+ private final FakeFeatureFlagsClassic mFeatureFlags;
private final SystemClock mSystemClock;
private final RowInflaterTaskLogger mRowInflaterTaskLogger;
private final TestScope mTestScope = TestScopeProvider.getTestScope();
@@ -167,17 +163,17 @@
Context context,
TestableDependency dependency,
@Nullable TestableLooper testLooper) {
- this(context, dependency, testLooper, new FakeFeatureFlags());
+ this(context, dependency, testLooper, new FakeFeatureFlagsClassic());
}
public NotificationTestHelper(
Context context,
TestableDependency dependency,
@Nullable TestableLooper testLooper,
- @NonNull FakeFeatureFlags featureFlags) {
+ @NonNull FakeFeatureFlagsClassic featureFlags) {
mContext = context;
mFeatureFlags = Objects.requireNonNull(featureFlags);
- dependency.injectTestDependency(FeatureFlags.class, mFeatureFlags);
+ dependency.injectTestDependency(FeatureFlagsClassic.class, mFeatureFlags);
dependency.injectMockDependency(NotificationMediaManager.class);
dependency.injectMockDependency(NotificationShadeWindowController.class);
dependency.injectMockDependency(MediaOutputDialogManager.class);
@@ -280,24 +276,6 @@
}
/**
- * Creates a generic row with rounded border.
- *
- * @return a generic row with the set roundness.
- * @throws Exception
- */
- public ExpandableNotificationRow createRowWithRoundness(
- float topRoundness,
- float bottomRoundness,
- SourceType sourceType
- ) throws Exception {
- ExpandableNotificationRow row = createRow();
- row.requestRoundness(topRoundness, bottomRoundness, sourceType, /*animate = */ false);
- assertEquals(topRoundness, row.getTopRoundness(), /* delta = */ 0f);
- assertEquals(bottomRoundness, row.getBottomRoundness(), /* delta = */ 0f);
- return row;
- }
-
- /**
* Creates a generic row.
*
* @return a generic row with no special properties.
@@ -400,9 +378,8 @@
null /* groupKey */,
makeBubbleMetadata(null /* deleteIntent */, false /* autoExpand */));
n.flags |= FLAG_FSI_REQUESTED_BUT_DENIED;
- ExpandableNotificationRow row = generateRow(n, PKG, UID, USER_HANDLE,
+ return generateRow(n, PKG, UID, USER_HANDLE,
mDefaultInflationFlags, IMPORTANCE_HIGH);
- return row;
}
@@ -668,7 +645,6 @@
mStatusBarStateController,
mPeopleNotificationIdentifier,
mOnUserInteractionCallback,
- Optional.of(mock(BubblesManager.class)),
mock(NotificationGutsManager.class),
mDismissibilityProvider,
mock(MetricsLogger.class),
@@ -676,7 +652,6 @@
mock(ColorUpdateLogger.class),
mock(SmartReplyConstants.class),
mock(SmartReplyController.class),
- mFeatureFlags,
mock(IStatusBarService.class),
mock(UiEventLogger.class));
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/NotificationTargetsHelperTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/NotificationTargetsHelperTest.kt
index 660eb30..87833d0 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/NotificationTargetsHelperTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/NotificationTargetsHelperTest.kt
@@ -5,7 +5,7 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
-import com.android.systemui.flags.FakeFeatureFlags
+import com.android.systemui.flags.FakeFeatureFlagsClassic
import com.android.systemui.statusbar.notification.row.NotificationTestHelper
import com.android.systemui.util.mockito.mock
import junit.framework.Assert.assertEquals
@@ -18,7 +18,7 @@
@RunWith(AndroidJUnit4::class)
@RunWithLooper
class NotificationTargetsHelperTest : SysuiTestCase() {
- private val featureFlags = FakeFeatureFlags()
+ private val featureFlags = FakeFeatureFlagsClassic()
lateinit var notificationTestHelper: NotificationTestHelper
private val sectionsManager: NotificationSectionsManager = mock()
private val stackScrollLayout: NotificationStackScrollLayout = mock()
@@ -90,11 +90,7 @@
)
val expected =
- RoundableTargets(
- before = children.attachedChildren[1],
- swiped = swiped,
- after = null,
- )
+ RoundableTargets(before = children.attachedChildren[1], swiped = swiped, after = null)
assertEquals(expected, actual)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/source/SystemShortcutsSource.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/source/SystemShortcutsSource.kt
index 687ad95..5060abd 100644
--- a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/source/SystemShortcutsSource.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/source/SystemShortcutsSource.kt
@@ -54,7 +54,7 @@
listOf(
KeyboardShortcutGroup(
resources.getString(R.string.shortcut_helper_category_system_controls),
- hardwareShortcuts(deviceId) + systemControlsShortcuts(),
+ systemControlsShortcuts() + hardwareShortcuts(deviceId),
),
KeyboardShortcutGroup(
resources.getString(R.string.shortcut_helper_category_system_apps),
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/domain/interactor/ShortcutHelperCategoriesInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/domain/interactor/ShortcutHelperCategoriesInteractor.kt
index 2385cc6..d625846 100644
--- a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/domain/interactor/ShortcutHelperCategoriesInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/domain/interactor/ShortcutHelperCategoriesInteractor.kt
@@ -95,7 +95,7 @@
Shortcut(
label = commonLabel,
icon = groupedShortcuts.firstOrNull()?.icon,
- commands = groupedShortcuts.flatMap { it.commands },
+ commands = groupedShortcuts.flatMap { it.commands }.sortedBy { it.keys.size },
contentDescription =
toContentDescription(commonLabel, groupedShortcuts.flatMap { it.commands }),
)
diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/BaseMediaProjectionPermissionDialogDelegate.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/BaseMediaProjectionPermissionDialogDelegate.kt
index 6f5d262..e17255a 100644
--- a/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/BaseMediaProjectionPermissionDialogDelegate.kt
+++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/BaseMediaProjectionPermissionDialogDelegate.kt
@@ -53,7 +53,22 @@
private lateinit var cancelButton: TextView
private lateinit var screenShareModeSpinner: Spinner
protected lateinit var dialog: AlertDialog
- private lateinit var viewBinder: BaseMediaProjectionPermissionViewBinder
+ protected lateinit var viewBinder: BaseMediaProjectionPermissionViewBinder
+
+ /**
+ * Create the view binder for the permission dialog, this can be override by child classes to
+ * support a different type of view binder
+ */
+ open fun createViewBinder(): BaseMediaProjectionPermissionViewBinder {
+ return BaseMediaProjectionPermissionViewBinder(
+ screenShareOptions,
+ appName,
+ hostUid,
+ mediaProjectionMetricsLogger,
+ defaultSelectedMode,
+ dialog,
+ )
+ }
@CallSuper
override fun onStop(dialog: T) {
@@ -71,15 +86,7 @@
updateIcon()
createOptionsView(getOptionsViewLayoutId())
if (!::viewBinder.isInitialized) {
- viewBinder =
- BaseMediaProjectionPermissionViewBinder(
- screenShareOptions,
- appName,
- hostUid,
- mediaProjectionMetricsLogger,
- defaultSelectedMode,
- dialog,
- )
+ viewBinder = createViewBinder()
}
viewBinder.bind()
initScreenShareSpinner()
diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/BaseMediaProjectionPermissionViewBinder.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/BaseMediaProjectionPermissionViewBinder.kt
index 70b25f5..728255d 100644
--- a/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/BaseMediaProjectionPermissionViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/BaseMediaProjectionPermissionViewBinder.kt
@@ -61,7 +61,7 @@
startButton.text = startButtonText
}
- fun onItemSelected(pos: Int) {
+ open fun onItemSelected(pos: Int) {
selectedScreenShareOption = screenShareOptions[pos]
setOptionSpecificFields()
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialogDelegate.kt b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialogDelegate.kt
index d9cc0c8..1da4c1d 100644
--- a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialogDelegate.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialogDelegate.kt
@@ -21,7 +21,6 @@
import android.content.Context
import android.content.Intent
import android.hardware.display.DisplayManager
-import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.os.Looper
@@ -30,8 +29,6 @@
import android.view.Display
import android.view.MotionEvent.ACTION_MOVE
import android.view.View
-import android.view.View.GONE
-import android.view.View.VISIBLE
import android.view.accessibility.AccessibilityNodeInfo
import android.widget.AdapterView
import android.widget.ArrayAdapter
@@ -44,10 +41,10 @@
import com.android.systemui.mediaprojection.MediaProjectionMetricsLogger
import com.android.systemui.mediaprojection.appselector.MediaProjectionAppSelectorActivity
import com.android.systemui.mediaprojection.permission.BaseMediaProjectionPermissionDialogDelegate
+import com.android.systemui.mediaprojection.permission.BaseMediaProjectionPermissionViewBinder
import com.android.systemui.mediaprojection.permission.ENTIRE_SCREEN
import com.android.systemui.mediaprojection.permission.SINGLE_APP
import com.android.systemui.mediaprojection.permission.ScreenShareMode
-import com.android.systemui.mediaprojection.permission.ScreenShareOption
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.res.R
import com.android.systemui.settings.UserContextProvider
@@ -64,15 +61,15 @@
private val activityStarter: ActivityStarter,
private val userContextProvider: UserContextProvider,
private val onStartRecordingClicked: Runnable?,
- mediaProjectionMetricsLogger: MediaProjectionMetricsLogger,
+ private val mediaProjectionMetricsLogger: MediaProjectionMetricsLogger,
private val systemUIDialogFactory: SystemUIDialog.Factory,
@ScreenShareMode defaultSelectedMode: Int,
@StyleRes private val theme: Int,
private val context: Context,
- displayManager: DisplayManager,
+ private val displayManager: DisplayManager,
) :
BaseMediaProjectionPermissionDialogDelegate<SystemUIDialog>(
- createOptionList(displayManager),
+ ScreenRecordPermissionViewBinder.createOptionList(displayManager),
appName = null,
hostUid = hostUid,
mediaProjectionMetricsLogger,
@@ -119,10 +116,19 @@
}
private lateinit var tapsSwitch: Switch
- private lateinit var tapsView: View
private lateinit var audioSwitch: Switch
private lateinit var options: Spinner
+ override fun createViewBinder(): BaseMediaProjectionPermissionViewBinder {
+ return ScreenRecordPermissionViewBinder(
+ hostUid,
+ mediaProjectionMetricsLogger,
+ defaultSelectedMode,
+ displayManager,
+ dialog,
+ )
+ }
+
override fun createDialog(): SystemUIDialog {
return systemUIDialogFactory.create(this, context, theme)
}
@@ -169,6 +175,7 @@
@SuppressLint("ClickableViewAccessibility")
private fun initRecordOptionsView() {
+ // TODO(b/378514312): Move this function to ScreenRecordPermissionViewBinder
audioSwitch = dialog.requireViewById(R.id.screenrecord_audio_switch)
tapsSwitch = dialog.requireViewById(R.id.screenrecord_taps_switch)
@@ -177,9 +184,6 @@
audioSwitch.setOnTouchListener { _, event -> event.action == ACTION_MOVE }
tapsSwitch.setOnTouchListener { _, event -> event.action == ACTION_MOVE }
- tapsView = dialog.requireViewById(R.id.show_taps)
- updateTapsViewVisibility()
-
options = dialog.requireViewById(R.id.screen_recording_options)
val a: ArrayAdapter<*> =
ScreenRecordingAdapter(
@@ -207,16 +211,6 @@
options.isLongClickable = false
}
- override fun onItemSelected(adapterView: AdapterView<*>?, view: View, pos: Int, id: Long) {
- super.onItemSelected(adapterView, view, pos, id)
- updateTapsViewVisibility()
- }
-
- private fun updateTapsViewVisibility() {
- tapsView.visibility =
- if (getSelectedScreenShareOption().mode == SINGLE_APP) GONE else VISIBLE
- }
-
/**
* Starts screen capture after some countdown
*
@@ -281,81 +275,5 @@
)
private const val DELAY_MS: Long = 3000
private const val INTERVAL_MS: Long = 1000
-
- private val RECORDABLE_DISPLAY_TYPES =
- intArrayOf(
- Display.TYPE_OVERLAY,
- Display.TYPE_EXTERNAL,
- Display.TYPE_INTERNAL,
- Display.TYPE_WIFI,
- )
-
- private val filterDeviceTypeFlag: Boolean =
- com.android.media.projection.flags.Flags
- .mediaProjectionConnectedDisplayNoVirtualDevice()
-
- private fun createOptionList(displayManager: DisplayManager): List<ScreenShareOption> {
- if (!com.android.media.projection.flags.Flags.mediaProjectionConnectedDisplay()) {
- return listOf(
- ScreenShareOption(
- SINGLE_APP,
- R.string.screenrecord_permission_dialog_option_text_single_app,
- R.string.screenrecord_permission_dialog_warning_single_app,
- startButtonText =
- R.string
- .media_projection_entry_generic_permission_dialog_continue_single_app,
- ),
- ScreenShareOption(
- ENTIRE_SCREEN,
- R.string.screenrecord_permission_dialog_option_text_entire_screen,
- R.string.screenrecord_permission_dialog_warning_entire_screen,
- startButtonText =
- R.string.screenrecord_permission_dialog_continue_entire_screen,
- displayId = Display.DEFAULT_DISPLAY,
- displayName = Build.MODEL,
- ),
- )
- }
-
- return listOf(
- ScreenShareOption(
- SINGLE_APP,
- R.string.screenrecord_permission_dialog_option_text_single_app,
- R.string.screenrecord_permission_dialog_warning_single_app,
- startButtonText =
- R.string
- .media_projection_entry_generic_permission_dialog_continue_single_app,
- ),
- ScreenShareOption(
- ENTIRE_SCREEN,
- R.string.screenrecord_permission_dialog_option_text_entire_screen_for_display,
- R.string.screenrecord_permission_dialog_warning_entire_screen,
- startButtonText =
- R.string.screenrecord_permission_dialog_continue_entire_screen,
- displayId = Display.DEFAULT_DISPLAY,
- displayName = Build.MODEL,
- ),
- ) +
- displayManager.displays
- .filter {
- it.displayId != Display.DEFAULT_DISPLAY &&
- (!filterDeviceTypeFlag || it.type in RECORDABLE_DISPLAY_TYPES)
- }
- .map {
- ScreenShareOption(
- ENTIRE_SCREEN,
- R.string
- .screenrecord_permission_dialog_option_text_entire_screen_for_display,
- warningText =
- R.string
- .media_projection_entry_app_permission_dialog_warning_entire_screen,
- startButtonText =
- R.string
- .media_projection_entry_app_permission_dialog_continue_entire_screen,
- displayId = it.displayId,
- displayName = it.name,
- )
- }
- }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionViewBinder.kt b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionViewBinder.kt
new file mode 100644
index 0000000..91c6b47
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionViewBinder.kt
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.screenrecord
+
+import android.annotation.SuppressLint
+import android.app.AlertDialog
+import android.hardware.display.DisplayManager
+import android.os.Build
+import android.view.Display
+import android.view.View
+import android.view.View.GONE
+import android.view.View.VISIBLE
+import com.android.systemui.mediaprojection.MediaProjectionMetricsLogger
+import com.android.systemui.mediaprojection.permission.BaseMediaProjectionPermissionViewBinder
+import com.android.systemui.mediaprojection.permission.ENTIRE_SCREEN
+import com.android.systemui.mediaprojection.permission.SINGLE_APP
+import com.android.systemui.mediaprojection.permission.ScreenShareMode
+import com.android.systemui.mediaprojection.permission.ScreenShareOption
+import com.android.systemui.res.R
+
+class ScreenRecordPermissionViewBinder(
+ hostUid: Int,
+ mediaProjectionMetricsLogger: MediaProjectionMetricsLogger,
+ @ScreenShareMode defaultSelectedMode: Int,
+ displayManager: DisplayManager,
+ private val dialog: AlertDialog,
+) :
+ BaseMediaProjectionPermissionViewBinder(
+ createOptionList(displayManager),
+ appName = null,
+ hostUid = hostUid,
+ mediaProjectionMetricsLogger,
+ defaultSelectedMode,
+ dialog,
+ ) {
+ private lateinit var tapsView: View
+
+ override fun bind() {
+ super.bind()
+ initRecordOptionsView()
+ }
+
+ @SuppressLint("ClickableViewAccessibility")
+ private fun initRecordOptionsView() {
+ tapsView = dialog.requireViewById(R.id.show_taps)
+ updateTapsViewVisibility()
+ }
+
+ override fun onItemSelected(pos: Int) {
+ super.onItemSelected(pos)
+ updateTapsViewVisibility()
+ }
+
+ private fun updateTapsViewVisibility() {
+ tapsView.visibility = if (selectedScreenShareOption.mode == SINGLE_APP) GONE else VISIBLE
+ }
+
+ companion object {
+ private val RECORDABLE_DISPLAY_TYPES =
+ intArrayOf(
+ Display.TYPE_OVERLAY,
+ Display.TYPE_EXTERNAL,
+ Display.TYPE_INTERNAL,
+ Display.TYPE_WIFI,
+ )
+
+ private val filterDeviceTypeFlag: Boolean =
+ com.android.media.projection.flags.Flags
+ .mediaProjectionConnectedDisplayNoVirtualDevice()
+
+ fun createOptionList(displayManager: DisplayManager): List<ScreenShareOption> {
+ if (!com.android.media.projection.flags.Flags.mediaProjectionConnectedDisplay()) {
+ return listOf(
+ ScreenShareOption(
+ SINGLE_APP,
+ R.string.screenrecord_permission_dialog_option_text_single_app,
+ R.string.screenrecord_permission_dialog_warning_single_app,
+ startButtonText =
+ R.string
+ .media_projection_entry_generic_permission_dialog_continue_single_app,
+ ),
+ ScreenShareOption(
+ ENTIRE_SCREEN,
+ R.string.screenrecord_permission_dialog_option_text_entire_screen,
+ R.string.screenrecord_permission_dialog_warning_entire_screen,
+ startButtonText =
+ R.string.screenrecord_permission_dialog_continue_entire_screen,
+ displayId = Display.DEFAULT_DISPLAY,
+ displayName = Build.MODEL,
+ ),
+ )
+ }
+
+ return listOf(
+ ScreenShareOption(
+ SINGLE_APP,
+ R.string.screenrecord_permission_dialog_option_text_single_app,
+ R.string.screenrecord_permission_dialog_warning_single_app,
+ startButtonText =
+ R.string
+ .media_projection_entry_generic_permission_dialog_continue_single_app,
+ ),
+ ScreenShareOption(
+ ENTIRE_SCREEN,
+ R.string.screenrecord_permission_dialog_option_text_entire_screen_for_display,
+ R.string.screenrecord_permission_dialog_warning_entire_screen,
+ startButtonText =
+ R.string.screenrecord_permission_dialog_continue_entire_screen,
+ displayId = Display.DEFAULT_DISPLAY,
+ displayName = Build.MODEL,
+ ),
+ ) +
+ displayManager.displays
+ .filter {
+ it.displayId != Display.DEFAULT_DISPLAY &&
+ (!filterDeviceTypeFlag || it.type in RECORDABLE_DISPLAY_TYPES)
+ }
+ .map {
+ ScreenShareOption(
+ ENTIRE_SCREEN,
+ R.string
+ .screenrecord_permission_dialog_option_text_entire_screen_for_display,
+ warningText =
+ R.string
+ .media_projection_entry_app_permission_dialog_warning_entire_screen,
+ startButtonText =
+ R.string
+ .media_projection_entry_app_permission_dialog_continue_entire_screen,
+ displayId = it.displayId,
+ displayName = it.name,
+ )
+ }
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActions.kt b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActions.kt
index dd1b58c..c6752f8 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActions.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActions.kt
@@ -30,8 +30,8 @@
isDownFromTopEdgeEnabled: Boolean = true,
requireTwoPointersForTopEdgeForQs: Boolean = false,
): Array<Pair<UserAction, UserActionResult>> {
- val shadeUserActionResult = UserActionResult(Scenes.Shade, isIrreversible = true)
- val qsSceneUserActionResult = UserActionResult(Scenes.QuickSettings, isIrreversible = true)
+ val shadeUserActionResult = UserActionResult(Scenes.Shade)
+ val qsSceneUserActionResult = UserActionResult(Scenes.QuickSettings)
return buildList {
// Swiping down, not from the edge, always goes to shade.
add(Swipe.Down to shadeUserActionResult)
@@ -53,7 +53,7 @@
/** Returns collection of [UserAction] to [UserActionResult] pairs for opening the split shade. */
fun splitShadeActions(): Array<Pair<UserAction, UserActionResult>> {
- val shadeUserActionResult = UserActionResult(Scenes.Shade, ToSplitShade, isIrreversible = true)
+ val shadeUserActionResult = UserActionResult(Scenes.Shade, ToSplitShade)
return arrayOf(
// Swiping down, not from the edge, always goes to shade.
Swipe.Down to shadeUserActionResult,
@@ -66,10 +66,8 @@
/** Returns collection of [UserAction] to [UserActionResult] pairs for opening the dual shade. */
fun dualShadeActions(): Array<Pair<UserAction, UserActionResult>> {
- val notifShadeUserActionResult =
- UserActionResult.ShowOverlay(Overlays.NotificationsShade, isIrreversible = true)
- val qsShadeuserActionResult =
- UserActionResult.ShowOverlay(Overlays.QuickSettingsShade, isIrreversible = true)
+ val notifShadeUserActionResult = UserActionResult.ShowOverlay(Overlays.NotificationsShade)
+ val qsShadeuserActionResult = UserActionResult.ShowOverlay(Overlays.QuickSettingsShade)
return arrayOf(
Swipe.Down to notifShadeUserActionResult,
Swipe.Down(fromSource = SceneContainerEdge.TopRight) to qsShadeuserActionResult,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index d71b1b2..c8811fd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -79,7 +79,6 @@
import com.android.internal.widget.CachingIconView;
import com.android.internal.widget.CallLayout;
import com.android.systemui.Flags;
-import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.flags.RefactorFlag;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.PluginListener;
@@ -130,14 +129,12 @@
import com.android.systemui.util.Compile;
import com.android.systemui.util.DumpUtilsKt;
import com.android.systemui.util.ListenerSet;
-import com.android.systemui.wmshell.BubblesManager;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
-import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.function.BooleanSupplier;
import java.util.function.Consumer;
@@ -151,7 +148,6 @@
NotificationFadeAware.FadeOptimizedNotification {
private static final String TAG = "ExpandableNotifRow";
- private static final boolean DEBUG = Compile.IS_DEBUG && Log.isLoggable(TAG, Log.DEBUG);
private static final boolean DEBUG_ONMEASURE =
Compile.IS_DEBUG && Log.isLoggable(TAG, Log.VERBOSE);
private static final int MENU_VIEW_INDEX = 0;
@@ -186,12 +182,10 @@
private LayoutListener mLayoutListener;
private RowContentBindStage mRowContentBindStage;
private PeopleNotificationIdentifier mPeopleNotificationIdentifier;
- private Optional<BubblesManager> mBubblesManagerOptional;
private MetricsLogger mMetricsLogger;
private NotificationChildrenContainerLogger mChildrenContainerLogger;
private ColorUpdateLogger mColorUpdateLogger;
private NotificationDismissibilityProvider mDismissibilityProvider;
- private FeatureFlags mFeatureFlags;
private int mIconTransformContentShift;
private int mMaxHeadsUpHeightBeforeN;
private int mMaxHeadsUpHeightBeforeP;
@@ -342,7 +336,7 @@
*/
private boolean mIgnoreLockscreenConstraints;
- private OnClickListener mExpandClickListener = new OnClickListener() {
+ private final OnClickListener mExpandClickListener = new OnClickListener() {
@Override
public void onClick(View v) {
toggleExpansionState(v, /* shouldLogExpandClickMetric = */true);
@@ -431,13 +425,10 @@
@Nullable
private Runnable mOnIntrinsicHeightReachedRunnable;
- private float mTopRoundnessDuringLaunchAnimation;
- private float mBottomRoundnessDuringLaunchAnimation;
- private float mSmallRoundness;
+ private final float mSmallRoundness;
- private ListenerSet<DismissButtonTargetVisibilityListener>
- mDismissButtonTargetVisibilityListeners
- = new ListenerSet();
+ private final ListenerSet<DismissButtonTargetVisibilityListener>
+ mDismissButtonTargetVisibilityListeners = new ListenerSet<>();
public NotificationContentView[] getLayouts() {
return Arrays.copyOf(mLayouts, mLayouts.length);
@@ -788,7 +779,7 @@
if (targetVisible != null) {
for (DismissButtonTargetVisibilityListener listener :
mDismissButtonTargetVisibilityListeners) {
- listener.onTargetVisibilityChanged(targetVisible.booleanValue());
+ listener.onTargetVisibilityChanged(targetVisible);
}
}
@@ -2024,7 +2015,6 @@
StatusBarStateController statusBarStateController,
PeopleNotificationIdentifier peopleNotificationIdentifier,
OnUserInteractionCallback onUserInteractionCallback,
- Optional<BubblesManager> bubblesManagerOptional,
NotificationGutsManager gutsManager,
NotificationDismissibilityProvider dismissibilityProvider,
MetricsLogger metricsLogger,
@@ -2032,7 +2022,6 @@
ColorUpdateLogger colorUpdateLogger,
SmartReplyConstants smartReplyConstants,
SmartReplyController smartReplyController,
- FeatureFlags featureFlags,
IStatusBarService statusBarService,
UiEventLogger uiEventLogger) {
mEntry = entry;
@@ -2067,13 +2056,11 @@
);
}
mOnUserInteractionCallback = onUserInteractionCallback;
- mBubblesManagerOptional = bubblesManagerOptional;
mNotificationGutsManager = gutsManager;
mMetricsLogger = metricsLogger;
mChildrenContainerLogger = childrenContainerLogger;
mColorUpdateLogger = colorUpdateLogger;
mDismissibilityProvider = dismissibilityProvider;
- mFeatureFlags = featureFlags;
setHapticFeedbackEnabled(!Flags.msdlFeedback());
}
@@ -2470,10 +2457,6 @@
: View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
}
- public CharSequence getActiveRemoteInputText() {
- return mPrivateLayout.getActiveRemoteInputText();
- }
-
/**
* Reset the translation with an animation.
*/
@@ -2548,7 +2531,7 @@
return getTranslationX();
}
- if (mTranslateableViews != null && mTranslateableViews.size() > 0) {
+ if (mTranslateableViews != null && !mTranslateableViews.isEmpty()) {
// All of the views in the list should have same translation, just use first one.
return mTranslateableViews.get(0).getTranslationX();
}
@@ -2683,7 +2666,7 @@
int clipTopAmount = (int) MathUtils.lerp(startClipTopAmount, 0, params.getProgress());
if (mNotificationParent != null) {
float parentTranslationY = mNotificationParent.getTranslationY();
- top -= parentTranslationY;
+ top -= (int) parentTranslationY;
mNotificationParent.setTranslationZ(translationZ);
// When the expanding notification is below its parent, the parent must be clipped
@@ -2710,9 +2693,6 @@
float absoluteCenterX = getLocationOnScreen()[0] + getWidth() / 2f - getTranslationX();
setTranslationX(params.getCenterX() - absoluteCenterX);
- final float maxRadius = getMaxRadius();
- mTopRoundnessDuringLaunchAnimation = params.getTopCornerRadius() / maxRadius;
- mBottomRoundnessDuringLaunchAnimation = params.getBottomCornerRadius() / maxRadius;
invalidateOutline();
mBackgroundNormal.setExpandAnimationSize(params.getWidth(), actualHeight);
@@ -2922,7 +2902,6 @@
}
}
-
@Override
public int getHeightWithoutLockscreenConstraints() {
mIgnoreLockscreenConstraints = true;
@@ -3248,7 +3227,7 @@
notifyHeightChanged(/* needsAnimation= */ false);
}
- public void setChildrenExpanded(boolean expanded, boolean animate) {
+ public void setChildrenExpanded(boolean expanded) {
mChildrenExpanded = expanded;
if (mChildrenContainer != null) {
mChildrenContainer.setChildrenExpanded(expanded);
@@ -3900,10 +3879,6 @@
return mEntry.getSbn().getNotification().isMediaNotification();
}
- public boolean isGroupNotFullyVisible() {
- return getClipTopAmount() > 0 || getTranslationY() < 0;
- }
-
public void setAboveShelf(boolean aboveShelf) {
boolean wasAboveShelf = isAboveShelf();
mAboveShelf = aboveShelf;
@@ -4132,10 +4107,6 @@
mTargetPoint = p;
}
- public Point getTargetPoint() {
- return mTargetPoint;
- }
-
/** Update the minimum roundness based on current state */
private void updateBaseRoundness() {
if (isChildInGroup()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java
index a150f7f..e06280e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java
@@ -35,7 +35,7 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.UiEventLogger;
import com.android.internal.statusbar.IStatusBarService;
-import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.flags.FeatureFlagsClassic;
import com.android.systemui.flags.Flags;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.PluginManager;
@@ -51,6 +51,7 @@
import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
import com.android.systemui.statusbar.notification.collection.render.NodeController;
import com.android.systemui.statusbar.notification.collection.render.NotifViewController;
+import com.android.systemui.statusbar.notification.headsup.HeadsUpManager;
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
import com.android.systemui.statusbar.notification.row.dagger.AppName;
import com.android.systemui.statusbar.notification.row.dagger.NotificationKey;
@@ -59,17 +60,14 @@
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import com.android.systemui.statusbar.notification.stack.ui.view.NotificationRowStatsLogger;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
-import com.android.systemui.statusbar.notification.headsup.HeadsUpManager;
import com.android.systemui.statusbar.policy.SmartReplyConstants;
import com.android.systemui.statusbar.policy.dagger.RemoteInputViewSubcomponent;
import com.android.systemui.util.time.SystemClock;
-import com.android.systemui.wmshell.BubblesManager;
import com.google.android.msdl.data.model.MSDLToken;
import com.google.android.msdl.domain.MSDLPlayer;
import java.util.List;
-import java.util.Optional;
import javax.inject.Inject;
import javax.inject.Named;
@@ -108,10 +106,9 @@
private final NotificationGutsManager mNotificationGutsManager;
private final OnUserInteractionCallback mOnUserInteractionCallback;
private final FalsingManager mFalsingManager;
- private final FeatureFlags mFeatureFlags;
+ private final FeatureFlagsClassic mFeatureFlags;
private final boolean mAllowLongPress;
private final PeopleNotificationIdentifier mPeopleNotificationIdentifier;
- private final Optional<BubblesManager> mBubblesManagerOptional;
private final SmartReplyConstants mSmartReplyConstants;
private final SmartReplyController mSmartReplyController;
private final ExpandableNotificationRowDragController mDragController;
@@ -271,9 +268,8 @@
@Named(ALLOW_NOTIFICATION_LONG_PRESS_NAME) boolean allowLongPress,
OnUserInteractionCallback onUserInteractionCallback,
FalsingManager falsingManager,
- FeatureFlags featureFlags,
+ FeatureFlagsClassic featureFlags,
PeopleNotificationIdentifier peopleNotificationIdentifier,
- Optional<BubblesManager> bubblesManagerOptional,
NotificationSettingsController settingsController,
ExpandableNotificationRowDragController dragController,
NotificationDismissibilityProvider dismissibilityProvider,
@@ -303,7 +299,6 @@
mAllowLongPress = allowLongPress;
mFeatureFlags = featureFlags;
mPeopleNotificationIdentifier = peopleNotificationIdentifier;
- mBubblesManagerOptional = bubblesManagerOptional;
mSettingsController = settingsController;
mDragController = dragController;
mMetricsLogger = metricsLogger;
@@ -340,7 +335,6 @@
mStatusBarStateController,
mPeopleNotificationIdentifier,
mOnUserInteractionCallback,
- mBubblesManagerOptional,
mNotificationGutsManager,
mDismissibilityProvider,
mMetricsLogger,
@@ -348,7 +342,6 @@
mColorUpdateLogger,
mSmartReplyConstants,
mSmartReplyController,
- mFeatureFlags,
mStatusBarService,
mUiEventLogger
);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
index 6293640..c8e18a8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
@@ -1128,7 +1128,7 @@
final int count = mAttachedChildren.size();
for (int childIdx = 0; childIdx < count; childIdx++) {
ExpandableNotificationRow child = mAttachedChildren.get(childIdx);
- child.setChildrenExpanded(childrenExpanded, false);
+ child.setChildrenExpanded(childrenExpanded);
}
updateHeaderTouchability();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index c7b3fd7..b9e38ab 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -99,7 +99,6 @@
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.notification.ColorUpdateLogger;
import com.android.systemui.statusbar.notification.FakeShadowView;
-import com.android.systemui.statusbar.notification.headsup.HeadsUpTouchHelper;
import com.android.systemui.statusbar.notification.LaunchAnimationParameters;
import com.android.systemui.statusbar.notification.NotificationTransitionAnimatorController;
import com.android.systemui.statusbar.notification.NotificationUtils;
@@ -110,6 +109,8 @@
import com.android.systemui.statusbar.notification.emptyshade.ui.view.EmptyShadeView;
import com.android.systemui.statusbar.notification.footer.shared.FooterViewRefactor;
import com.android.systemui.statusbar.notification.footer.ui.view.FooterView;
+import com.android.systemui.statusbar.notification.headsup.HeadsUpTouchHelper;
+import com.android.systemui.statusbar.notification.headsup.HeadsUpUtil;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
@@ -126,7 +127,6 @@
import com.android.systemui.statusbar.notification.stack.ui.view.NotificationScrollView;
import com.android.systemui.statusbar.phone.HeadsUpAppearanceController;
import com.android.systemui.statusbar.phone.ScreenOffAnimationController;
-import com.android.systemui.statusbar.notification.headsup.HeadsUpUtil;
import com.android.systemui.statusbar.policy.ScrollAdapter;
import com.android.systemui.statusbar.policy.SplitShadeStateController;
import com.android.systemui.util.Assert;
@@ -6860,7 +6860,7 @@
mExpandedGroupView = changedRow;
mNeedsAnimation = true;
}
- changedRow.setChildrenExpanded(expanded, animated);
+ changedRow.setChildrenExpanded(expanded);
onChildHeightChanged(changedRow, false /* needsAnimation */);
runAfterAnimationFinished(new Runnable() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
index df561ab..192d66c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
@@ -113,7 +113,7 @@
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.deviceentry.domain.interactor.DeviceEntryUdfpsInteractor;
import com.android.systemui.dump.DumpManager;
-import com.android.systemui.flags.FakeFeatureFlags;
+import com.android.systemui.flags.FakeFeatureFlagsClassic;
import com.android.systemui.flags.SceneContainerFlagParameterizationKt;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.kosmos.KosmosJavaAdapter;
@@ -368,7 +368,7 @@
private TestableLooper mTestableLooper;
private final FakeDisplayTracker mDisplayTracker = new FakeDisplayTracker(mContext);
- private final FakeFeatureFlags mFeatureFlags = new FakeFeatureFlags();
+ private final FakeFeatureFlagsClassic mFeatureFlags = new FakeFeatureFlagsClassic();
private UserHandle mUser0;
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowBuilder.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowBuilder.kt
index 2d3f68f..7126933 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowBuilder.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowBuilder.kt
@@ -34,7 +34,7 @@
import com.android.systemui.classifier.FalsingManagerFake
import com.android.systemui.dump.DumpManager
import com.android.systemui.flags.FakeFeatureFlagsClassic
-import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.FeatureFlagsClassic
import com.android.systemui.flags.Flags
import com.android.systemui.log.logcatLogBuffer
import com.android.systemui.media.controls.util.MediaFeatureFlag
@@ -92,8 +92,6 @@
import com.android.systemui.util.concurrency.FakeExecutor
import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.time.FakeSystemClock
-import com.android.systemui.wmshell.BubblesManager
-import java.util.Optional
import java.util.concurrent.CountDownLatch
import java.util.concurrent.Executor
import java.util.concurrent.TimeUnit
@@ -106,7 +104,7 @@
class ExpandableNotificationRowBuilder(
private val context: Context,
dependency: TestableDependency,
- private val featureFlags: FakeFeatureFlagsClassic = FakeFeatureFlagsClassic(),
+ featureFlags: FakeFeatureFlagsClassic = FakeFeatureFlagsClassic(),
) {
private val mMockLogger: ExpandableNotificationRowLogger
@@ -137,7 +135,7 @@
featureFlags.setDefault(Flags.ENABLE_NOTIFICATIONS_SIMULATE_SLOW_MEASURE)
featureFlags.setDefault(Flags.BIGPICTURE_NOTIFICATION_LAZY_LOADING)
- dependency.injectTestDependency(FeatureFlags::class.java, featureFlags)
+ dependency.injectTestDependency(FeatureFlagsClassic::class.java, featureFlags)
dependency.injectMockDependency(NotificationMediaManager::class.java)
dependency.injectMockDependency(NotificationShadeWindowController::class.java)
dependency.injectMockDependency(MediaOutputDialogManager::class.java)
@@ -299,7 +297,7 @@
}
private fun getNotifRemoteViewsFactoryContainer(
- featureFlags: FeatureFlags
+ featureFlags: FeatureFlagsClassic
): NotifRemoteViewsFactoryContainer {
return NotifRemoteViewsFactoryContainerImpl(
featureFlags,
@@ -380,7 +378,6 @@
mStatusBarStateController,
mPeopleNotificationIdentifier,
mOnUserInteractionCallback,
- Optional.of(Mockito.mock(BubblesManager::class.java, STUB_ONLY)),
Mockito.mock(NotificationGutsManager::class.java, STUB_ONLY),
mDismissibilityProvider,
Mockito.mock(MetricsLogger::class.java, STUB_ONLY),
@@ -388,11 +385,10 @@
Mockito.mock(ColorUpdateLogger::class.java, STUB_ONLY),
mSmartReplyConstants,
mSmartReplyController,
- featureFlags,
Mockito.mock(IStatusBarService::class.java, STUB_ONLY),
Mockito.mock(UiEventLogger::class.java, STUB_ONLY),
)
- row.setAboveShelfChangedListener { aboveShelf: Boolean -> }
+ row.setAboveShelfChangedListener {}
mBindStage.getStageParams(entry).requireContentViews(extraInflationFlags)
inflateAndWait(entry)
return row
@@ -410,7 +406,7 @@
private const val PKG = "com.android.systemui"
private const val UID = 1000
private val USER_HANDLE = UserHandle.of(ActivityManager.getCurrentUser())
- private val INFLATION_FLAGS =
+ private const val INFLATION_FLAGS =
FLAG_CONTENT_VIEW_CONTRACTED or FLAG_CONTENT_VIEW_EXPANDED or FLAG_CONTENT_VIEW_HEADS_UP
private const val IS_CONVERSATION_FLAG = "test.isConversation"
diff --git a/services/backup/java/com/android/server/backup/UserBackupManagerService.java b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
index a90b693..3025e2e 100644
--- a/services/backup/java/com/android/server/backup/UserBackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
@@ -314,8 +314,6 @@
private static final String SERIAL_ID_FILE = "serial_id";
- private static final String SKIP_USER_FACING_PACKAGES = "backup_skip_user_facing_packages";
-
private final @UserIdInt int mUserId;
private final BackupAgentTimeoutParameters mAgentTimeoutParameters;
private final TransportManager mTransportManager;
@@ -3503,40 +3501,6 @@
}
}
- /**
- * We want to skip backup/restore of certain packages if 'backup_skip_user_facing_packages' is
- * set to true in secure settings. See b/153940088 for details.
- *
- * TODO(b/154822946): Remove this logic in the next release.
- */
- public List<PackageInfo> filterUserFacingPackages(List<PackageInfo> packages) {
- if (!shouldSkipUserFacingData()) {
- return packages;
- }
-
- List<PackageInfo> filteredPackages = new ArrayList<>(packages.size());
- for (PackageInfo packageInfo : packages) {
- if (!shouldSkipPackage(packageInfo.packageName)) {
- filteredPackages.add(packageInfo);
- } else {
- Slog.i(TAG, "Will skip backup/restore for " + packageInfo.packageName);
- }
- }
-
- return filteredPackages;
- }
-
- @VisibleForTesting
- public boolean shouldSkipUserFacingData() {
- return Settings.Secure.getInt(mContext.getContentResolver(), SKIP_USER_FACING_PACKAGES,
- /* def */ 0) != 0;
- }
-
- @VisibleForTesting
- public boolean shouldSkipPackage(String packageName) {
- return WALLPAPER_PACKAGE.equals(packageName);
- }
-
private void updateStateForTransport(String newTransportName) {
// Publish the name change
Settings.Secure.putStringForUser(mContext.getContentResolver(),
diff --git a/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java b/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java
index 7994948..990c941 100644
--- a/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java
+++ b/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java
@@ -272,8 +272,6 @@
}
}
- mPackages = backupManagerService.filterUserFacingPackages(mPackages);
-
Set<String> packageNames = Sets.newHashSet();
for (PackageInfo pkgInfo : mPackages) {
packageNames.add(pkgInfo.packageName);
diff --git a/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java b/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
index dad84c8..ec9d340 100644
--- a/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
+++ b/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
@@ -315,8 +315,6 @@
}
}
- mAcceptSet = backupManagerService.filterUserFacingPackages(mAcceptSet);
-
if (MORE_DEBUG) {
Slog.v(TAG, "Restore; accept set size is " + mAcceptSet.size());
for (PackageInfo info : mAcceptSet) {
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 4454dd4..9eba926 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -181,6 +181,7 @@
private static final int MSG_RELOAD_DEVICE_ALIASES = 2;
private static final int MSG_DELIVER_TABLET_MODE_CHANGED = 3;
private static final int MSG_CURRENT_USER_CHANGED = 4;
+ private static final int MSG_SYSTEM_READY = 5;
private static final int DEFAULT_VIBRATION_MAGNITUDE = 192;
private static final AdditionalDisplayInputProperties
@@ -564,6 +565,14 @@
Watchdog.getInstance().addMonitor(this);
}
+ private void onBootPhase(int phase) {
+ // On ActivityManager thread, shift to handler to avoid blocking other system services in
+ // this boot phase.
+ if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
+ mHandler.sendEmptyMessage(MSG_SYSTEM_READY);
+ }
+ }
+
// TODO(BT) Pass in parameter for bluetooth system
public void systemRunning() {
if (DEBUG) {
@@ -3220,6 +3229,9 @@
case MSG_CURRENT_USER_CHANGED:
handleCurrentUserChanged((int) msg.obj);
break;
+ case MSG_SYSTEM_READY:
+ systemRunning();
+ break;
}
}
}
@@ -3424,10 +3436,7 @@
@Override
public void onBootPhase(int phase) {
- // Called on ActivityManager thread.
- if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
- mService.systemRunning();
- }
+ mService.onBootPhase(phase);
}
@Override
diff --git a/services/core/java/com/android/server/location/contexthub/ContextHubEndpointBroker.java b/services/core/java/com/android/server/location/contexthub/ContextHubEndpointBroker.java
index 53389ca..aa215ce 100644
--- a/services/core/java/com/android/server/location/contexthub/ContextHubEndpointBroker.java
+++ b/services/core/java/com/android/server/location/contexthub/ContextHubEndpointBroker.java
@@ -24,6 +24,11 @@
import android.hardware.contexthub.IContextHubEndpoint;
import android.hardware.contexthub.IContextHubEndpointCallback;
import android.hardware.location.IContextHubTransactionCallback;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.util.concurrent.atomic.AtomicBoolean;
/**
* A class that represents a broker for the endpoint registered by the client app. This class
@@ -31,7 +36,8 @@
*
* @hide
*/
-public class ContextHubEndpointBroker extends IContextHubEndpoint.Stub {
+public class ContextHubEndpointBroker extends IContextHubEndpoint.Stub
+ implements IBinder.DeathRecipient {
private static final String TAG = "ContextHubEndpointBroker";
/** The context of the service. */
@@ -52,6 +58,9 @@
/** The remote callback interface for this endpoint. */
private final IContextHubEndpointCallback mContextHubEndpointCallback;
+ /** True if this endpoint is registered with the service. */
+ private AtomicBoolean mIsRegistered = new AtomicBoolean(true);
+
/* package */ ContextHubEndpointBroker(
Context context,
IContextHubWrapper contextHubProxy,
@@ -72,27 +81,55 @@
}
@Override
- public int openSession(HubEndpointInfo destination, HubServiceInfo serviceInfo) {
- // TODO(b/378487799): Implement this
- return 0;
+ public int openSession(HubEndpointInfo destination, HubServiceInfo serviceInfo)
+ throws RemoteException {
+ ContextHubServiceUtil.checkPermissions(mContext);
+ if (!mIsRegistered.get()) throw new IllegalStateException("Endpoint is not registered");
+ int sessionId = mEndpointManager.reserveSessionId();
+ EndpointInfo halEndpointInfo = ContextHubServiceUtil.convertHalEndpointInfo(destination);
+ try {
+ mContextHubProxy.openEndpointSession(
+ sessionId,
+ halEndpointInfo.id,
+ mHalEndpointInfo.id,
+ serviceInfo == null ? null : serviceInfo.getServiceDescriptor());
+ } catch (RemoteException | IllegalArgumentException | UnsupportedOperationException e) {
+ Log.e(TAG, "Exception while calling HAL openEndpointSession", e);
+ mEndpointManager.returnSessionId(sessionId);
+ throw e;
+ }
+
+ return sessionId;
}
@Override
- public void closeSession(int sessionId, int reason) {
- // TODO(b/378487799): Implement this
-
+ public void closeSession(int sessionId, int reason) throws RemoteException {
+ ContextHubServiceUtil.checkPermissions(mContext);
+ if (!mIsRegistered.get()) throw new IllegalStateException("Endpoint is not registered");
+ try {
+ mContextHubProxy.closeEndpointSession(sessionId, (byte) reason);
+ } catch (RemoteException | IllegalArgumentException | UnsupportedOperationException e) {
+ Log.e(TAG, "Exception while calling HAL closeEndpointSession", e);
+ throw e;
+ }
}
@Override
public void openSessionRequestComplete(int sessionId) {
// TODO(b/378487799): Implement this
-
}
@Override
public void unregister() {
- // TODO(b/378487799): Implement this
-
+ ContextHubServiceUtil.checkPermissions(mContext);
+ mIsRegistered.set(false);
+ try {
+ mContextHubProxy.unregisterEndpoint(mHalEndpointInfo);
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException while calling HAL unregisterEndpoint", e);
+ }
+ // TODO(b/378487799): Release reserved session IDs
+ mEndpointManager.unregisterEndpoint(mEndpointInfo.getIdentifier().getEndpoint());
}
@Override
@@ -105,4 +142,16 @@
public void sendMessageDeliveryStatus(int sessionId, int messageSeqNumber, byte errorCode) {
// TODO(b/381102453): Implement this
}
+
+ /** Invoked when the underlying binder of this broker has died at the client process. */
+ @Override
+ public void binderDied() {
+ unregister();
+ }
+
+ /* package */ void attachDeathRecipient() throws RemoteException {
+ if (mContextHubEndpointCallback != null) {
+ mContextHubEndpointCallback.asBinder().linkToDeath(this, 0 /* flags */);
+ }
+ }
}
diff --git a/services/core/java/com/android/server/location/contexthub/ContextHubEndpointManager.java b/services/core/java/com/android/server/location/contexthub/ContextHubEndpointManager.java
index 54ce74f..fb64f99 100644
--- a/services/core/java/com/android/server/location/contexthub/ContextHubEndpointManager.java
+++ b/services/core/java/com/android/server/location/contexthub/ContextHubEndpointManager.java
@@ -22,11 +22,15 @@
import android.hardware.contexthub.IContextHubEndpoint;
import android.hardware.contexthub.IContextHubEndpointCallback;
import android.os.RemoteException;
+import android.os.ServiceSpecificException;
import android.util.Log;
import com.android.internal.annotations.GuardedBy;
+import java.util.Collections;
+import java.util.HashMap;
import java.util.Map;
+import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
/**
@@ -40,6 +44,12 @@
/** The hub ID of the Context Hub Service. */
private static final long SERVICE_HUB_ID = 0x416e64726f696400L;
+ /** The range of session IDs to use for endpoints */
+ private static final int SERVICE_SESSION_RANGE = 1024;
+
+ /** The length of the array that should be returned by HAL requestSessionIdRange */
+ private static final int SERVICE_SESSION_RANGE_LENGTH = 2;
+
/** The context of the service. */
private final Context mContext;
@@ -55,9 +65,57 @@
@GuardedBy("mEndpointLock")
private long mNextEndpointId = 0;
+ /** The minimum session ID reservable by endpoints (retrieved from HAL) */
+ private final int mMinSessionId;
+
+ /** The minimum session ID reservable by endpoints (retrieved from HAL) */
+ private final int mMaxSessionId;
+
+ /** Variables for managing session ID creation */
+ private final Object mSessionIdLock = new Object();
+
+ /** A set of session IDs that have been reserved by an endpoint. */
+ @GuardedBy("mSessionIdLock")
+ private final Set<Integer> mReservedSessionIds =
+ Collections.newSetFromMap(new HashMap<Integer, Boolean>());
+
+ @GuardedBy("mSessionIdLock")
+ private int mNextSessionId = 0;
+
+ /** Initialized to true if all initialization in the constructor succeeds. */
+ private final boolean mSessionIdsValid;
+
/* package */ ContextHubEndpointManager(Context context, IContextHubWrapper contextHubProxy) {
mContext = context;
mContextHubProxy = contextHubProxy;
+ int[] range = null;
+ try {
+ range = mContextHubProxy.requestSessionIdRange(SERVICE_SESSION_RANGE);
+ if (range != null && range.length < SERVICE_SESSION_RANGE_LENGTH) {
+ Log.e(TAG, "Invalid session ID range: range array size = " + range.length);
+ range = null;
+ }
+ } catch (RemoteException | IllegalArgumentException | ServiceSpecificException e) {
+ Log.e(TAG, "Exception while calling HAL requestSessionIdRange", e);
+ }
+
+ if (range == null) {
+ mMinSessionId = -1;
+ mMaxSessionId = -1;
+ mSessionIdsValid = false;
+ } else {
+ mMinSessionId = range[0];
+ mMaxSessionId = range[1];
+ if (!isSessionIdRangeValid(mMinSessionId, mMaxSessionId)) {
+ Log.e(
+ TAG,
+ "Invalid session ID range: max=" + mMaxSessionId + " min=" + mMinSessionId);
+ mSessionIdsValid = false;
+ } else {
+ mNextSessionId = mMinSessionId;
+ mSessionIdsValid = true;
+ }
+ }
}
/**
@@ -71,6 +129,9 @@
/* package */ IContextHubEndpoint registerEndpoint(
HubEndpointInfo pendingEndpointInfo, IContextHubEndpointCallback callback)
throws RemoteException {
+ if (!mSessionIdsValid) {
+ throw new IllegalStateException("ContextHubEndpointManager failed to initialize");
+ }
ContextHubEndpointBroker broker;
long endpointId = getNewEndpointId();
EndpointInfo halEndpointInfo =
@@ -91,15 +152,65 @@
callback);
mEndpointMap.put(endpointId, broker);
- // TODO(b/378487799): Add death recipient
+ try {
+ broker.attachDeathRecipient();
+ } catch (RemoteException e) {
+ // The client process has died, so we close the connection and return null
+ Log.e(TAG, "Failed to attach death recipient to client", e);
+ broker.unregister();
+ return null;
+ }
Log.d(TAG, "Registered endpoint with ID = " + endpointId);
return IContextHubEndpoint.Stub.asInterface(broker);
}
/**
- * @return an available endpoint ID
+ * Reserves an available session ID for an endpoint.
+ *
+ * @throws IllegalStateException if no session ID was available.
+ * @return The reserved session ID.
*/
+ /* package */ int reserveSessionId() {
+ int id = -1;
+ synchronized (mSessionIdLock) {
+ final int maxCapacity = mMaxSessionId - mMinSessionId + 1;
+ if (mReservedSessionIds.size() >= maxCapacity) {
+ throw new IllegalStateException("Too many sessions reserved");
+ }
+
+ id = mNextSessionId;
+ for (int i = mMinSessionId; i <= mMaxSessionId; i++) {
+ if (!mReservedSessionIds.contains(id)) {
+ mNextSessionId = (id == mMaxSessionId) ? mMinSessionId : id + 1;
+ break;
+ }
+
+ id = (id == mMaxSessionId) ? mMinSessionId : id + 1;
+ }
+
+ mReservedSessionIds.add(id);
+ }
+ return id;
+ }
+
+ /** Returns a previously reserved session ID through {@link #reserveSessionId()}. */
+ /* package */ void returnSessionId(int sessionId) {
+ synchronized (mSessionIdLock) {
+ mReservedSessionIds.remove(sessionId);
+ }
+ }
+
+ /**
+ * Unregisters an endpoint given its ID.
+ *
+ * @param endpointId The ID of the endpoint to unregister.
+ */
+ /* package */ void unregisterEndpoint(long endpointId) {
+ mEndpointMap.remove(endpointId);
+ }
+
+ /** @return an available endpoint ID */
private long getNewEndpointId() {
synchronized (mEndpointLock) {
if (mNextEndpointId == Long.MAX_VALUE) {
@@ -108,4 +219,8 @@
return mNextEndpointId++;
}
}
+
+ private boolean isSessionIdRangeValid(int minId, int maxId) {
+ return (minId <= maxId) && (minId >= 0) && (maxId >= 0);
+ }
}
diff --git a/services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java b/services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java
index 14d75b0..c79dc84 100644
--- a/services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java
+++ b/services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java
@@ -18,6 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.chre.flags.Flags;
+import android.hardware.contexthub.EndpointId;
import android.hardware.contexthub.HostEndpointInfo;
import android.hardware.contexthub.HubEndpointInfo;
import android.hardware.contexthub.MessageDeliveryStatus;
@@ -243,6 +244,23 @@
public void registerEndpoint(android.hardware.contexthub.EndpointInfo info)
throws RemoteException {}
+ /** Unregisters a previously registered endpoint */
+ public int[] requestSessionIdRange(int size) throws RemoteException {
+ return null;
+ }
+
+ /** Opens an endpoint session between two endpoints */
+ public void openEndpointSession(
+ int sessionId, EndpointId destination, EndpointId initiator, String serviceDescriptor)
+ throws RemoteException {}
+
+ /** Closes a previously opened endpoint */
+ public void closeEndpointSession(int sessionId, byte reason) throws RemoteException {}
+
+ /** Unregisters a previously registered endpoint */
+ public void unregisterEndpoint(android.hardware.contexthub.EndpointInfo info)
+ throws RemoteException {}
+
/**
* @return True if this version of the Contexthub HAL supports Location setting notifications.
*/
@@ -685,6 +703,48 @@
hub.registerEndpoint(info);
}
+ @Override
+ public int[] requestSessionIdRange(int size) throws RemoteException {
+ android.hardware.contexthub.IContextHub hub = getHub();
+ if (hub == null) {
+ return null;
+ }
+ return hub.requestSessionIdRange(size);
+ }
+
+ @Override
+ public void openEndpointSession(
+ int sessionId,
+ EndpointId destination,
+ EndpointId initiator,
+ String serviceDescriptor)
+ throws RemoteException {
+ android.hardware.contexthub.IContextHub hub = getHub();
+ if (hub == null) {
+ return;
+ }
+ hub.openEndpointSession(sessionId, destination, initiator, serviceDescriptor);
+ }
+
+ @Override
+ public void closeEndpointSession(int sessionId, byte reason) throws RemoteException {
+ android.hardware.contexthub.IContextHub hub = getHub();
+ if (hub == null) {
+ return;
+ }
+ hub.closeEndpointSession(sessionId, reason);
+ }
+
+ @Override
+ public void unregisterEndpoint(android.hardware.contexthub.EndpointInfo info)
+ throws RemoteException {
+ android.hardware.contexthub.IContextHub hub = getHub();
+ if (hub == null) {
+ return;
+ }
+ hub.unregisterEndpoint(info);
+ }
+
public boolean supportsLocationSettingNotifications() {
return true;
}
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index 20481f2..1fc609b7 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -1429,7 +1429,16 @@
// Commit wallpaper visibility after activity, because usually the wallpaper target token is
// an activity, and wallpaper's visibility depends on activity's visibility.
for (int i = mParticipants.size() - 1; i >= 0; --i) {
- final WallpaperWindowToken wt = mParticipants.valueAt(i).asWallpaperToken();
+ final WindowContainer<?> wc = mParticipants.valueAt(i);
+ WallpaperWindowToken wt = wc.asWallpaperToken();
+ if (!Flags.ensureWallpaperInTransitions()) {
+ if (wt == null) {
+ final WindowState windowState = wc.asWindowState();
+ if (windowState != null) {
+ wt = windowState.mToken.asWallpaperToken();
+ }
+ }
+ }
if (wt == null) continue;
final WindowState target = wt.mDisplayContent.mWallpaperController.getWallpaperTarget();
final boolean isTargetInvisible = target == null || !target.mToken.isVisible();
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index 9430194..5a45730 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -362,7 +362,7 @@
void setMotionClassifierEnabled(bool enabled);
std::optional<std::string> getBluetoothAddress(int32_t deviceId);
void setStylusButtonMotionEventsEnabled(bool enabled);
- FloatPoint getMouseCursorPosition(ui::LogicalDisplayId displayId);
+ vec2 getMouseCursorPosition(ui::LogicalDisplayId displayId);
void setStylusPointerIconEnabled(bool enabled);
void setInputMethodConnectionIsActive(bool isActive);
void setKeyRemapping(const std::map<int32_t, int32_t>& keyRemapping);
@@ -441,7 +441,7 @@
std::shared_ptr<PointerControllerInterface> createPointerController(
PointerControllerInterface::ControllerType type) override;
void notifyPointerDisplayIdChanged(ui::LogicalDisplayId displayId,
- const FloatPoint& position) override;
+ const vec2& position) override;
void notifyMouseCursorFadedOnTyping() override;
/* --- InputFilterPolicyInterface implementation --- */
@@ -871,7 +871,7 @@
}
void NativeInputManager::notifyPointerDisplayIdChanged(ui::LogicalDisplayId pointerDisplayId,
- const FloatPoint& position) {
+ const vec2& position) {
// Notify the Reader so that devices can be reconfigured.
{ // acquire lock
std::scoped_lock _l(mLock);
@@ -2023,7 +2023,7 @@
InputReaderConfiguration::Change::STYLUS_BUTTON_REPORTING);
}
-FloatPoint NativeInputManager::getMouseCursorPosition(ui::LogicalDisplayId displayId) {
+vec2 NativeInputManager::getMouseCursorPosition(ui::LogicalDisplayId displayId) {
return mInputManager->getChoreographer().getMouseCursorPosition(displayId);
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index ac1219c..3ccde06 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -9085,11 +9085,13 @@
}
CallerIdentity caller = getCallerIdentity(who);
- if (!Flags.setAutoTimeEnabledCoexistence()) {
+ if (Flags.setAutoTimeEnabledCoexistence()) {
+ Preconditions.checkCallAuthorization(hasPermission(SET_TIME, caller.getPackageName()));
+ } else {
Objects.requireNonNull(who, "ComponentName is null");
- }
- Preconditions.checkCallAuthorization(isProfileOwnerOnUser0(caller)
+ Preconditions.checkCallAuthorization(isProfileOwnerOnUser0(caller)
|| isProfileOwnerOfOrganizationOwnedDevice(caller) || isDefaultDeviceOwner(caller));
+ }
return mInjector.settingsGlobalGetInt(Global.AUTO_TIME, 0) > 0;
}
@@ -9166,10 +9168,7 @@
}
CallerIdentity caller = getCallerIdentity(who);
-
- if (!Flags.setAutoTimeZoneEnabledCoexistence()) {
- Objects.requireNonNull(who, "ComponentName is null");
- }
+ Objects.requireNonNull(who, "ComponentName is null");
Preconditions.checkCallAuthorization(isProfileOwnerOnUser0(caller)
|| isProfileOwnerOfOrganizationOwnedDevice(caller) || isDefaultDeviceOwner(
caller));
@@ -9193,10 +9192,15 @@
}
CallerIdentity caller = getCallerIdentity(who);
- Objects.requireNonNull(who, "ComponentName is null");
- Preconditions.checkCallAuthorization(isProfileOwnerOnUser0(caller)
+ if (Flags.setAutoTimeZoneEnabledCoexistence()) {
+ Preconditions.checkCallAuthorization(
+ hasPermission(SET_TIME_ZONE, caller.getPackageName()));
+ } else {
+ Objects.requireNonNull(who, "ComponentName is null");
+ Preconditions.checkCallAuthorization(isProfileOwnerOnUser0(caller)
|| isProfileOwnerOfOrganizationOwnedDevice(caller) || isDefaultDeviceOwner(
caller));
+ }
return mInjector.settingsGlobalGetInt(Global.AUTO_TIME_ZONE, 0) > 0;
}
diff --git a/services/robotests/backup/src/com/android/server/backup/UserBackupManagerServiceTest.java b/services/robotests/backup/src/com/android/server/backup/UserBackupManagerServiceTest.java
index 02e0bbf..eb61a40 100644
--- a/services/robotests/backup/src/com/android/server/backup/UserBackupManagerServiceTest.java
+++ b/services/robotests/backup/src/com/android/server/backup/UserBackupManagerServiceTest.java
@@ -30,13 +30,10 @@
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.robolectric.Shadows.shadowOf;
-import static org.testng.Assert.assertFalse;
-import static org.testng.Assert.assertTrue;
import static org.testng.Assert.expectThrows;
import android.app.backup.BackupManager;
@@ -90,7 +87,6 @@
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.List;
/**
@@ -110,7 +106,6 @@
private static final String TAG = "BMSTest";
private static final String PACKAGE_1 = "some.package.1";
private static final String PACKAGE_2 = "some.package.2";
- private static final String USER_FACING_PACKAGE = "user.facing.package";
private static final int USER_ID = 10;
@Mock private TransportManager mTransportManager;
@@ -1213,47 +1208,6 @@
eq(packageTrackingReceiver), eq(UserHandle.of(USER_ID)), any(), any(), any());
}
- @Test
- public void testFilterUserFacingPackages_shouldSkipUserFacing_filtersUserFacing() {
- List<PackageInfo> packages = Arrays.asList(getPackageInfo(USER_FACING_PACKAGE),
- getPackageInfo(PACKAGE_1));
- UserBackupManagerService backupManagerService = spy(
- createUserBackupManagerServiceAndRunTasks());
- when(backupManagerService.shouldSkipUserFacingData()).thenReturn(true);
- when(backupManagerService.shouldSkipPackage(eq(USER_FACING_PACKAGE))).thenReturn(true);
-
- List<PackageInfo> filteredPackages = backupManagerService.filterUserFacingPackages(
- packages);
-
- assertFalse(containsPackage(filteredPackages, USER_FACING_PACKAGE));
- assertTrue(containsPackage(filteredPackages, PACKAGE_1));
- }
-
- @Test
- public void testFilterUserFacingPackages_shouldNotSkipUserFacing_doesNotFilterUserFacing() {
- List<PackageInfo> packages = Arrays.asList(getPackageInfo(USER_FACING_PACKAGE),
- getPackageInfo(PACKAGE_1));
- UserBackupManagerService backupManagerService = spy(
- createUserBackupManagerServiceAndRunTasks());
- when(backupManagerService.shouldSkipUserFacingData()).thenReturn(false);
- when(backupManagerService.shouldSkipPackage(eq(USER_FACING_PACKAGE))).thenReturn(true);
-
- List<PackageInfo> filteredPackages = backupManagerService.filterUserFacingPackages(
- packages);
-
- assertTrue(containsPackage(filteredPackages, USER_FACING_PACKAGE));
- assertTrue(containsPackage(filteredPackages, PACKAGE_1));
- }
-
- private static boolean containsPackage(List<PackageInfo> packages, String targetPackage) {
- for (PackageInfo packageInfo : packages) {
- if (targetPackage.equals(packageInfo.packageName)) {
- return true;
- }
- }
- return false;
- }
-
private UserBackupManagerService createUserBackupManagerServiceAndRunTasks() {
return BackupManagerServiceTestUtils.createUserBackupManagerServiceAndRunTasks(
USER_ID, mContext, mBackupThread, mBaseStateDir, mDataDir, mTransportManager);
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryExternalStatsWorkerTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryExternalStatsWorkerTest.java
index d7b60cf..2b15231 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryExternalStatsWorkerTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryExternalStatsWorkerTest.java
@@ -39,7 +39,6 @@
import android.os.Handler;
import android.os.Looper;
import android.os.connectivity.WifiActivityEnergyInfo;
-import android.platform.test.ravenwood.RavenwoodConfig;
import android.power.PowerStatsInternal;
import android.util.IntArray;
import android.util.SparseArray;
@@ -66,9 +65,6 @@
@SuppressWarnings("GuardedBy")
@android.platform.test.annotations.DisabledOnRavenwood
public class BatteryExternalStatsWorkerTest {
- @RavenwoodConfig.Config
- public final RavenwoodConfig mRavenwood = new RavenwoodConfig.Builder().build();
-
private BatteryExternalStatsWorker mBatteryExternalStatsWorker;
private TestPowerStatsInternal mPowerStatsInternal;
private Handler mHandler;
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/processor/WakelockPowerStatsProcessorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/WakelockPowerStatsProcessorTest.java
index f64dc08..ed3cda0 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/processor/WakelockPowerStatsProcessorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/WakelockPowerStatsProcessorTest.java
@@ -34,7 +34,6 @@
import android.os.BatteryConsumer;
import android.os.PersistableBundle;
import android.os.Process;
-import android.platform.test.ravenwood.RavenwoodConfig;
import com.android.internal.os.BatteryStatsHistory;
import com.android.internal.os.MonotonicClock;
@@ -48,11 +47,6 @@
import org.junit.Test;
public class WakelockPowerStatsProcessorTest {
- @RavenwoodConfig.Config
- public static final RavenwoodConfig sConfig = new RavenwoodConfig.Builder()
- .setProvideMainThread(true)
- .build();
-
@Rule
public final BatteryUsageStatsRule mStatsRule = new BatteryUsageStatsRule()
.setAveragePower(PowerProfile.POWER_CPU_IDLE, 720);
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 7cfdec6..59cb5ff 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -10061,6 +10061,13 @@
"satellite_nidd_apn_name_string";
/**
+ * The display name that will be used for satellite functionality within the UI.
+ * The default string value for this is "Satellite".
+ * @hide
+ */
+ public static final String KEY_SATELLITE_DISPLAY_NAME_STRING = "satellite_display_name_string";
+
+ /**
* Default value {@code true}, meaning when an emergency call request comes in, if the device is
* in emergency satellite mode but hasn't sent the first satellite datagram, then exits
* satellite mode to allow the emergency call to go through.
@@ -11343,6 +11350,7 @@
sDefaults.putBoolean(KEY_EMERGENCY_MESSAGING_SUPPORTED_BOOL, false);
sDefaults.putInt(KEY_EMERGENCY_CALL_TO_SATELLITE_T911_HANDOVER_TIMEOUT_MILLIS_INT,
(int) TimeUnit.SECONDS.toMillis(30));
+ sDefaults.putString(KEY_SATELLITE_DISPLAY_NAME_STRING, "");
sDefaults.putBoolean(KEY_SATELLITE_ESOS_SUPPORTED_BOOL, false);
sDefaults.putBoolean(KEY_SATELLITE_ROAMING_P2P_SMS_SUPPORTED_BOOL, false);
sDefaults.putString(KEY_SATELLITE_NIDD_APN_NAME_STRING, "");
diff --git a/telephony/java/android/telephony/satellite/SatelliteManager.java b/telephony/java/android/telephony/satellite/SatelliteManager.java
index db5689b7..1025c15 100644
--- a/telephony/java/android/telephony/satellite/SatelliteManager.java
+++ b/telephony/java/android/telephony/satellite/SatelliteManager.java
@@ -292,6 +292,13 @@
/**
* Bundle key to get the response from
+ * {@link #requestSatelliteDisplayName(Executor, OutcomeReceiver)}.
+ * @hide
+ */
+ public static final String KEY_SATELLITE_DISPLAY_NAME = "satellite_display_name";
+
+ /**
+ * Bundle key to get the response from
* {@link #requestSelectedNbIotSatelliteSubscriptionId(Executor, OutcomeReceiver)}.
* @hide
*/
@@ -3594,6 +3601,65 @@
}
/**
+ * Request to get the display name of satellite feature in the UI.
+ *
+ * @param executor The executor on which the callback will be called.
+ * @param callback The callback object to which the result will be delivered.
+ * If the request is successful, {@link OutcomeReceiver#onResult(Object)}
+ * will return display name of the satellite feature in string format. Defaults
+ * to satellite. If the request is not successful,
+ * {@link OutcomeReceiver#onError(Throwable)} will return an error with
+ * a SatelliteException.
+ *
+ * @throws SecurityException if the caller doesn't have required permission.
+ * @throws IllegalStateException if the Telephony process is not currently available.
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
+ public void requestSatelliteDisplayName(
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull OutcomeReceiver<String, SatelliteException> callback) {
+ Objects.requireNonNull(executor);
+ Objects.requireNonNull(callback);
+
+ try {
+ ITelephony telephony = getITelephony();
+ if (telephony != null) {
+ ResultReceiver receiver = new ResultReceiver(null) {
+ @Override
+ protected void onReceiveResult(int resultCode, Bundle resultData) {
+ if (resultCode == SATELLITE_RESULT_SUCCESS) {
+ if (resultData.containsKey(KEY_SATELLITE_DISPLAY_NAME)) {
+ String satelliteDisplayName =
+ resultData.getString(KEY_SATELLITE_DISPLAY_NAME);
+ executor.execute(() -> Binder.withCleanCallingIdentity(() ->
+ callback.onResult(satelliteDisplayName)));
+ } else {
+ loge("KEY_SATELLITE_DISPLAY_NAME does not exist.");
+ executor.execute(() -> Binder.withCleanCallingIdentity(() ->
+ callback.onError(new SatelliteException(
+ SATELLITE_RESULT_REQUEST_FAILED))));
+ }
+ } else {
+ executor.execute(() -> Binder.withCleanCallingIdentity(() ->
+ callback.onError(new SatelliteException(resultCode))));
+ }
+ }
+ };
+ telephony.requestSatelliteDisplayName(receiver);
+ } else {
+ loge("requestSatelliteDisplayName() invalid telephony");
+ executor.execute(() -> Binder.withCleanCallingIdentity(() -> callback.onError(
+ new SatelliteException(SATELLITE_RESULT_ILLEGAL_STATE))));
+ }
+ } catch (RemoteException ex) {
+ loge("requestSatelliteDisplayName() RemoteException: " + ex);
+ executor.execute(() -> Binder.withCleanCallingIdentity(() -> callback.onError(
+ new SatelliteException(SATELLITE_RESULT_ILLEGAL_STATE))));
+ }
+ }
+
+ /**
* Deliver the list of provisioned satellite subscriber infos.
*
* @param list The list of provisioned satellite subscriber infos.
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 131f46b..da7669f 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -3471,6 +3471,17 @@
void requestSatelliteSubscriberProvisionStatus(in ResultReceiver result);
/**
+ * Request to get the name to display for Satellite subscription.
+ *
+ * @param receiver The result receiver that returns the diplay name to be used for the satellite
+ * subscription.
+ * @hide
+ */
+ @JavaPassthrough(annotation="@android.annotation.RequiresPermission("
+ + "android.Manifest.permission.SATELLITE_COMMUNICATION)")
+ void requestSatelliteDisplayName(in ResultReceiver receiver);
+
+ /**
* Deliver the list of provisioned satellite subscriber infos.
*
* @param list The list of provisioned satellite subscriber infos.