Compare commits
No commits in common. "aosp16" and "aosp13" have entirely different histories.
84 changed files with 1262 additions and 18274 deletions
197
apply.sh
197
apply.sh
|
|
@ -1,197 +1,4 @@
|
|||
#!/bin/bash
|
||||
# Apply or reset patches
|
||||
# Usage: apply.sh <command> [options]
|
||||
# Commands:
|
||||
# apply Apply all patches from asb/<year-month>/ and petergsi subdirectories
|
||||
# reset Reset all repos to their original state
|
||||
|
||||
set -e
|
||||
|
||||
# Always execute in the script's directory
|
||||
pushd "$(dirname "$(realpath "$0")")"
|
||||
|
||||
COMMAND="${1:-apply}"
|
||||
shift || true
|
||||
|
||||
apply_asb_patches() {
|
||||
local asb_base="$(realpath asb 2>/dev/null || echo '')"
|
||||
if [ -z "$asb_base" ] || [ ! -d "$asb_base" ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
local patch_dirs
|
||||
patch_dirs=$(find "$asb_base" -name "*.patch" -printf "%h\n" | sort -u)
|
||||
|
||||
for patch_dir in $patch_dirs; do
|
||||
local repo_path="${patch_dir#$asb_base/}"
|
||||
repo_path="${repo_path#20*/}"
|
||||
local target_dir="$(dirname "$asb_base")/../$repo_path"
|
||||
|
||||
if [ ! -d "$target_dir" ]; then
|
||||
echo "Warning: Repository $repo_path not found for ASB patches, skipping"
|
||||
continue
|
||||
fi
|
||||
|
||||
pushd "$target_dir"
|
||||
|
||||
if ! git am -3 "$patch_dir"/*.patch 2>/dev/null; then
|
||||
echo "Failed to apply ASB patches to $repo_path"
|
||||
echo "ASB patch application failed, aborting."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
popd
|
||||
done
|
||||
}
|
||||
|
||||
apply_petergsi_patches() {
|
||||
local patch_base="$(realpath petergsi)"
|
||||
echo "petergsi directory: $patch_base"
|
||||
local failed_file="/tmp/apply_failed_repos_$$.txt"
|
||||
|
||||
if [ ! -d "$patch_base" ]; then
|
||||
echo "Error: petergsi directory not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
: > "$failed_file"
|
||||
|
||||
local patch_dirs
|
||||
patch_dirs=$(find "$patch_base" -name "*.patch" -printf "%h\n" | sort -u)
|
||||
|
||||
for patch_dir in $patch_dirs; do
|
||||
local repo_path="${patch_dir#$patch_base/}"
|
||||
local target_dir="$(dirname "$patch_base")/../$repo_path"
|
||||
|
||||
if [ ! -d "$target_dir" ]; then
|
||||
echo "Warning: Repository $repo_path not found, skipping"
|
||||
continue
|
||||
fi
|
||||
|
||||
cd "$target_dir"
|
||||
|
||||
git tag -d "before-petergsi" 2>/dev/null || true
|
||||
git tag "before-petergsi" 2>/dev/null || true
|
||||
|
||||
if ! git am -3 "$patch_dir"/*.patch 2>/dev/null; then
|
||||
echo "$repo_path" >> "$failed_file"
|
||||
echo "Failed to apply patches to $repo_path"
|
||||
fi
|
||||
done
|
||||
|
||||
if [ -s "$failed_file" ]; then
|
||||
echo ""
|
||||
echo "Failed to apply patches in the following repositories:"
|
||||
while read -r repo; do
|
||||
echo " $repo"
|
||||
done < "$failed_file"
|
||||
fi
|
||||
|
||||
rm -f "$failed_file"
|
||||
}
|
||||
|
||||
apply_patches() {
|
||||
apply_asb_patches
|
||||
apply_petergsi_patches
|
||||
}
|
||||
|
||||
reset_one() {
|
||||
[ "$(basename "$PWD")" == "patches" ] && return
|
||||
|
||||
check_baseline() {
|
||||
current=$(git rev-parse HEAD)
|
||||
baseline=$REPO_LREV
|
||||
if [ -z "$baseline" ] || [ "$current" = "$baseline" ]; then
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
check_safety() {
|
||||
branch=$(git symbolic-ref --short HEAD 2>/dev/null)
|
||||
if [ -n "$branch" ]; then
|
||||
if [ "$FORCE" != "1" ]; then
|
||||
echo "SKIP_REPO:$REPO_PATH"
|
||||
return 1
|
||||
fi
|
||||
git checkout --detach HEAD 2>/dev/null
|
||||
fi
|
||||
dirty=$(git status --porcelain)
|
||||
if [ -n "$dirty" ]; then
|
||||
if [ "$FORCE" != "1" ]; then
|
||||
echo "SKIP_REPO:$REPO_PATH"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
if [ "$FAST" = "1" ]; then
|
||||
check_baseline || return 0
|
||||
check_safety || return 0
|
||||
else
|
||||
check_safety || return 0
|
||||
check_baseline || return 0
|
||||
fi
|
||||
|
||||
if [ "$DRY" != "1" ]; then
|
||||
rm -rf .git/rebase-apply
|
||||
git reset --hard "$baseline" >/dev/null
|
||||
fi
|
||||
reverted=$(git log --oneline "$baseline".."$current" 2>/dev/null)
|
||||
if [ -n "$reverted" ]; then
|
||||
echo "Reset $REPO_PATH, reverted commits:"
|
||||
echo "$reverted" | sed "s/^/ /"
|
||||
else
|
||||
echo "Reset $REPO_PATH (could not list reverted commits)"
|
||||
fi
|
||||
}
|
||||
|
||||
export -f reset_one
|
||||
|
||||
reset_patches() {
|
||||
FORCE=0
|
||||
FAST=0
|
||||
DRY=0
|
||||
for arg in "$@"; do
|
||||
case "$arg" in
|
||||
--force) FORCE=1 ;;
|
||||
--fast) FAST=1 ;;
|
||||
--dry) DRY=1 ;;
|
||||
*)
|
||||
esac
|
||||
done
|
||||
export FORCE FAST DRY
|
||||
|
||||
repo forall -c 'bash -c reset_one' 2>&1 | tee /tmp/reset_output.txt
|
||||
|
||||
skipped_count=$(grep -c "^SKIP_REPO:" /tmp/reset_output.txt 2>/dev/null || echo 0)
|
||||
|
||||
if [ "$skipped_count" != "0" ]; then
|
||||
echo ""
|
||||
echo "Skipped the following repositories (not reset):"
|
||||
grep "^SKIP_REPO:" /tmp/reset_output.txt | sed 's/SKIP_REPO://'
|
||||
fi
|
||||
|
||||
rm -f /tmp/reset_output.txt
|
||||
}
|
||||
|
||||
case "$COMMAND" in
|
||||
apply)
|
||||
apply_patches
|
||||
;;
|
||||
reset)
|
||||
reset_patches "$@"
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $0 <apply|reset> [options]"
|
||||
echo ""
|
||||
echo "Commands:"
|
||||
echo " apply Apply all patches from asb/<year-month>/ and petergsi subdirectories"
|
||||
echo " reset Reset all repos to their original state"
|
||||
echo ""
|
||||
echo "Options for reset:"
|
||||
echo " --force Also reset projects on a development branch or with uncommitted changes"
|
||||
echo " --fast Faster check, but may miss branch/dirty changes"
|
||||
echo " --dry Print what would be reset without actually resetting"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
find . -name "*.patch" -printf "%h\n" | uniq | xargs -I{} bash -c "cd $(pwd)/../{}; git am $(pwd)/{}/*"
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -1,36 +0,0 @@
|
|||
From b51a58ecec96558e1c6b1d47728f45a8795dc7ab Mon Sep 17 00:00:00 2001
|
||||
From: Nate Myren <ntmyren@google.com>
|
||||
Date: Tue, 7 Oct 2025 14:03:49 -0700
|
||||
Subject: [PATCH] Ensure sandboxed UIDs are treated as untrusted in Appops
|
||||
|
||||
They should not be considered "system" app for the purposes of
|
||||
attribution tag vaildation
|
||||
|
||||
Bug: 443742082
|
||||
Test: atest AppOpsMemoryUsageTest
|
||||
Flag: EXEMPT CVE_FIX
|
||||
Cherrypick-From: https://googleplex-android-review.googlesource.com/q/commit:1bc6b146137f76589146dff5cd82363de7ccfb7d
|
||||
Cherrypick-From: https://googleplex-android-review.googlesource.com/q/commit:066eff80abf013531320b8280637d1d00dd553a1
|
||||
Merged-In: I0c4ac8eaa8966027ad01375dde58b05febec3ffb
|
||||
Change-Id: I0c4ac8eaa8966027ad01375dde58b05febec3ffb
|
||||
---
|
||||
services/core/java/com/android/server/appop/AppOpsService.java | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
|
||||
index ae8a8d943ccc..9c9d338099dd 100644
|
||||
--- a/services/core/java/com/android/server/appop/AppOpsService.java
|
||||
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
|
||||
@@ -5043,6 +5043,9 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
if (packageName == null) {
|
||||
return true;
|
||||
}
|
||||
+ if (Process.isSdkSandboxUid(uid)) {
|
||||
+ return false;
|
||||
+ }
|
||||
int appId = UserHandle.getAppId(uid);
|
||||
if (appId > 0 && appId < Process.FIRST_APPLICATION_UID) {
|
||||
return true;
|
||||
--
|
||||
2.53.0
|
||||
|
||||
|
|
@ -1,313 +0,0 @@
|
|||
From a4523e227733ae20eafe4ec3e85474a5b7ebf7c6 Mon Sep 17 00:00:00 2001
|
||||
From: Nate Myren <ntmyren@google.com>
|
||||
Date: Wed, 15 Oct 2025 15:48:49 -0700
|
||||
Subject: [PATCH] Prohibit untrusted proxys from specifying proxied attribution
|
||||
tags
|
||||
|
||||
Only trusted proxies should be allowed to specify tags. Also prevents
|
||||
startOperationDryRun from editing the know attribution tags, as the dry
|
||||
run should change no state.
|
||||
|
||||
Bug: 445917646
|
||||
Test: atest AttributionTest
|
||||
Flag: EXEMPT CVE_FIX
|
||||
(cherry picked from commit 110db0acb84cbd21f9da9391ab242d141ebf390c)
|
||||
Cherrypick-From: https://googleplex-android-review.googlesource.com/q/commit:94d32dce4639ba16b321667719678d2a6b42d9c3
|
||||
Merged-In: I14ab1389384fd28009edd9cceceaacdb97fb96e5
|
||||
Change-Id: I14ab1389384fd28009edd9cceceaacdb97fb96e5
|
||||
---
|
||||
.../android/server/appop/AppOpsService.java | 112 ++++++++++++++----
|
||||
.../android/server/appop/AttributedOp.java | 14 +++
|
||||
2 files changed, 105 insertions(+), 21 deletions(-)
|
||||
|
||||
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
|
||||
index 9c9d338099dd..85a5ac8bf3ca 100644
|
||||
--- a/services/core/java/com/android/server/appop/AppOpsService.java
|
||||
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
|
||||
@@ -39,6 +39,7 @@ import static android.app.AppOpsManager.OP_CAMERA_SANDBOXED;
|
||||
import static android.app.AppOpsManager.OP_FLAGS_ALL;
|
||||
import static android.app.AppOpsManager.OP_FLAG_SELF;
|
||||
import static android.app.AppOpsManager.OP_FLAG_TRUSTED_PROXIED;
|
||||
+import static android.app.AppOpsManager.OP_FLAG_UNTRUSTED_PROXIED;
|
||||
import static android.app.AppOpsManager.OP_NONE;
|
||||
import static android.app.AppOpsManager.OP_PLAY_AUDIO;
|
||||
import static android.app.AppOpsManager.OP_RECEIVE_AMBIENT_TRIGGER_AUDIO;
|
||||
@@ -3189,7 +3190,7 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
public int checkPackage(int uid, String packageName) {
|
||||
Objects.requireNonNull(packageName);
|
||||
try {
|
||||
- verifyAndGetBypass(uid, packageName, null, Process.INVALID_UID, null, true);
|
||||
+ verifyAndGetBypass(uid, packageName, null, Process.INVALID_UID, null, true, true);
|
||||
// When the caller is the system, it's possible that the packageName is the special
|
||||
// one (e.g., "root") which isn't actually existed.
|
||||
if (resolveNonAppUid(packageName) == uid
|
||||
@@ -3407,8 +3408,10 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
@OpFlags int flags, boolean shouldCollectAsyncNotedOp, @Nullable String message,
|
||||
boolean shouldCollectMessage, int notedCount) {
|
||||
PackageVerificationResult pvr;
|
||||
+ boolean proxyTrusted = (flags & OP_FLAG_UNTRUSTED_PROXIED) == 0;
|
||||
try {
|
||||
- pvr = verifyAndGetBypass(uid, packageName, attributionTag, proxyUid, proxyPackageName);
|
||||
+ pvr = verifyAndGetBypass(uid, packageName, attributionTag, proxyUid, proxyPackageName,
|
||||
+ proxyTrusted);
|
||||
if (!pvr.isAttributionTagValid) {
|
||||
attributionTag = null;
|
||||
}
|
||||
@@ -4072,8 +4075,10 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
boolean shouldCollectMessage, @AttributionFlags int attributionFlags,
|
||||
int attributionChainId) {
|
||||
PackageVerificationResult pvr;
|
||||
+ boolean proxyTrusted = (flags & OP_FLAG_UNTRUSTED_PROXIED) == 0;
|
||||
try {
|
||||
- pvr = verifyAndGetBypass(uid, packageName, attributionTag, proxyUid, proxyPackageName);
|
||||
+ pvr = verifyAndGetBypass(uid, packageName, attributionTag, proxyUid, proxyPackageName,
|
||||
+ proxyTrusted);
|
||||
if (!pvr.isAttributionTagValid) {
|
||||
attributionTag = null;
|
||||
}
|
||||
@@ -4206,8 +4211,10 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
int proxyUid, String proxyPackageName, @OpFlags int flags,
|
||||
boolean startIfModeDefault) {
|
||||
PackageVerificationResult pvr;
|
||||
+ boolean proxyTrusted = (flags & OP_FLAG_UNTRUSTED_PROXIED) == 0;
|
||||
try {
|
||||
- pvr = verifyAndGetBypass(uid, packageName, attributionTag, proxyUid, proxyPackageName);
|
||||
+ pvr = verifyAndGetBypass(uid, packageName, attributionTag, proxyUid, proxyPackageName,
|
||||
+ proxyTrusted);
|
||||
if (!pvr.isAttributionTagValid) {
|
||||
attributionTag = null;
|
||||
}
|
||||
@@ -4223,7 +4230,9 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
|
||||
boolean isRestricted = false;
|
||||
synchronized (this) {
|
||||
- final Ops ops = getOpsLocked(uid, packageName, attributionTag,
|
||||
+ // Edit is true (so we create the Ops object if needed), but attribution tag is given as
|
||||
+ // null, so we don't cache any information about it.
|
||||
+ final Ops ops = getOpsLocked(uid, packageName, null,
|
||||
pvr.isAttributionTagValid, pvr.bypass, /* edit */ true);
|
||||
if (ops == null) {
|
||||
if (DEBUG) {
|
||||
@@ -4402,8 +4411,11 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
int virtualDeviceId) {
|
||||
PackageVerificationResult pvr;
|
||||
try {
|
||||
+ // assume the proxy is trusted, since we aren't sure. We'll search for the attribution
|
||||
+ // tag with trusted flags, and if we don't find it, search for a null tag with
|
||||
+ // untrusted flags
|
||||
pvr = verifyAndGetBypass(proxiedUid, proxiedPackageName, attributionTag,
|
||||
- proxyUid, proxyPackageName);
|
||||
+ proxyUid, proxyPackageName, /* isProxyTrusted */ true);
|
||||
if (!pvr.isAttributionTagValid) {
|
||||
attributionTag = null;
|
||||
}
|
||||
@@ -4413,8 +4425,9 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
}
|
||||
|
||||
synchronized (this) {
|
||||
+ boolean hasProxy = proxyUid != Process.INVALID_UID;
|
||||
Op op = getOpLocked(code, proxiedUid, proxiedPackageName, attributionTag,
|
||||
- pvr.isAttributionTagValid, pvr.bypass, /* edit */ true);
|
||||
+ pvr.isAttributionTagValid, pvr.bypass, /* edit */ false);
|
||||
if (op == null) {
|
||||
Slog.e(TAG, "Operation not found: uid=" + proxiedUid + " pkg=" + proxiedPackageName
|
||||
+ "("
|
||||
@@ -4422,9 +4435,8 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
return;
|
||||
}
|
||||
final AttributedOp attributedOp =
|
||||
- op.mDeviceAttributedOps.getOrDefault(
|
||||
- getPersistentDeviceIdForOp(virtualDeviceId, code),
|
||||
- new ArrayMap<>()).get(attributionTag);
|
||||
+ getAttributedOpWithClientId(op, clientId, attributionTag, virtualDeviceId,
|
||||
+ hasProxy);
|
||||
if (attributedOp == null) {
|
||||
Slog.e(TAG, "Attribution not found: uid=" + proxiedUid
|
||||
+ " pkg=" + proxiedPackageName + "("
|
||||
@@ -4442,6 +4454,54 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
+ private AttributedOp getAttributedOpWithClientId(Op op, IBinder clientId,
|
||||
+ String attributionTag, int virtualDeviceId, boolean hasProxy) {
|
||||
+ AttributedOp attributedOp =
|
||||
+ op.mDeviceAttributedOps.getOrDefault(
|
||||
+ getPersistentDeviceIdForOp(virtualDeviceId, op.op),
|
||||
+ new ArrayMap<>()).get(attributionTag);
|
||||
+ if (!hasProxy) {
|
||||
+ return attributedOp;
|
||||
+ }
|
||||
+ boolean hasTrustedInProgressEvent = attributedOp != null
|
||||
+ && attributedOp.hasInProgressEvent((event -> event.getClientId() == clientId
|
||||
+ && (event.getFlags() & OP_FLAG_UNTRUSTED_PROXIED) == 0));
|
||||
+ if (hasTrustedInProgressEvent) {
|
||||
+ return attributedOp;
|
||||
+ }
|
||||
+
|
||||
+ // We failed to find a trusted in progress event that matches the clientId. Check if the
|
||||
+ // tag is valid in the package, and look for an untrusted access matching that tag, if so
|
||||
+ boolean tagValid = false;
|
||||
+ try {
|
||||
+ tagValid = verifyAndGetBypass(op.uid, op.packageName, attributionTag)
|
||||
+ .isAttributionTagValid;
|
||||
+ } catch (SecurityException e) {
|
||||
+ // assume tag is invalid
|
||||
+ }
|
||||
+ if (tagValid) {
|
||||
+ boolean hasUntrustedInProgressEvent = attributedOp != null
|
||||
+ && attributedOp.hasInProgressEvent((event -> event.getClientId() == clientId
|
||||
+ && (event.getFlags() & OP_FLAG_UNTRUSTED_PROXIED) != 0));
|
||||
+ if (hasUntrustedInProgressEvent) {
|
||||
+ return attributedOp;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // The tag was not valid, or we failed to find an untrusted event. Look for an untrusted
|
||||
+ // event with the null attribution tag
|
||||
+ attributedOp = op.mDeviceAttributedOps.getOrDefault(
|
||||
+ getPersistentDeviceIdForOp(virtualDeviceId, op.op),
|
||||
+ new ArrayMap<>()).get(null);
|
||||
+ boolean hasUntrustedNullEvent = attributedOp != null
|
||||
+ && attributedOp.hasInProgressEvent((event -> event.getClientId() == clientId
|
||||
+ && (event.getFlags() & OP_FLAG_UNTRUSTED_PROXIED) != 0));
|
||||
+ if (hasUntrustedNullEvent) {
|
||||
+ return attributedOp;
|
||||
+ }
|
||||
+ return null;
|
||||
+ }
|
||||
+
|
||||
void scheduleOpActiveChangedIfNeededLocked(int code, int uid, @NonNull
|
||||
String packageName, @Nullable String attributionTag, int virtualDeviceId,
|
||||
boolean active, @AttributionFlags int attributionFlags, int attributionChainId) {
|
||||
@@ -4881,20 +4941,22 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
}
|
||||
|
||||
/**
|
||||
- * @see #verifyAndGetBypass(int, String, String, int, String, boolean)
|
||||
+ * @see #verifyAndGetBypass(int, String, String, int, String, boolean, boolean)
|
||||
*/
|
||||
private @NonNull PackageVerificationResult verifyAndGetBypass(int uid, String packageName,
|
||||
@Nullable String attributionTag) {
|
||||
- return verifyAndGetBypass(uid, packageName, attributionTag, Process.INVALID_UID, null);
|
||||
+ return verifyAndGetBypass(uid, packageName, attributionTag, Process.INVALID_UID, null,
|
||||
+ true);
|
||||
}
|
||||
|
||||
/**
|
||||
- * @see #verifyAndGetBypass(int, String, String, int, String, boolean)
|
||||
+ * @see #verifyAndGetBypass(int, String, String, int, String, boolean, boolean)
|
||||
*/
|
||||
private @NonNull PackageVerificationResult verifyAndGetBypass(int uid, String packageName,
|
||||
- @Nullable String attributionTag, int proxyUid, @Nullable String proxyPackageName) {
|
||||
+ @Nullable String attributionTag, int proxyUid, @Nullable String proxyPackageName,
|
||||
+ boolean isProxyTrusted) {
|
||||
return verifyAndGetBypass(uid, packageName, attributionTag, proxyUid, proxyPackageName,
|
||||
- false);
|
||||
+ isProxyTrusted, false);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -4907,6 +4969,8 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
* @param attributionTag attribution tag or {@code null} if no need to verify
|
||||
* @param proxyUid The proxy uid, from which the attribution tag is to be pulled
|
||||
* @param proxyPackageName The proxy package, from which the attribution tag may be pulled
|
||||
+ * @param isProxyTrusted Whether or not the proxy package is trusted. If it isn't, then the
|
||||
+ * proxy attribution tag will not be used
|
||||
* @param suppressErrorLogs Whether to print to logcat about nonmatching parameters
|
||||
*
|
||||
* @return PackageVerificationResult containing {@link RestrictionBypass} and whether the
|
||||
@@ -4914,7 +4978,7 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
*/
|
||||
private @NonNull PackageVerificationResult verifyAndGetBypass(int uid, String packageName,
|
||||
@Nullable String attributionTag, int proxyUid, @Nullable String proxyPackageName,
|
||||
- boolean suppressErrorLogs) {
|
||||
+ boolean isProxyTrusted, boolean suppressErrorLogs) {
|
||||
if (uid == Process.ROOT_UID) {
|
||||
// For backwards compatibility, don't check package name for root UID, unless someone
|
||||
// is claiming to be a proxy for root, which should never happen in normal usage.
|
||||
@@ -4922,7 +4986,8 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
// system app (or is null), in order to prevent abusive apps clogging the appops
|
||||
// system with unlimited attribution tags via proxy calls.
|
||||
return new PackageVerificationResult(null,
|
||||
- /* isAttributionTagValid */ isPackageNullOrSystem(proxyPackageName, proxyUid));
|
||||
+ /* isAttributionTagValid */ isProxyTrusted
|
||||
+ && isPackageNullOrSystem(proxyPackageName, proxyUid));
|
||||
}
|
||||
if (Process.isSdkSandboxUid(uid)) {
|
||||
// SDK sandbox processes run in their own UID range, but their associated
|
||||
@@ -4986,7 +5051,8 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
// system app (or is null), in order to prevent abusive apps clogging the appops
|
||||
// system with unlimited attribution tags via proxy calls.
|
||||
return new PackageVerificationResult(RestrictionBypass.UNRESTRICTED,
|
||||
- /* isAttributionTagValid */ isPackageNullOrSystem(proxyPackageName, proxyUid));
|
||||
+ /* isAttributionTagValid */ isProxyTrusted
|
||||
+ && isPackageNullOrSystem(proxyPackageName, proxyUid));
|
||||
}
|
||||
|
||||
int userId = UserHandle.getUserId(uid);
|
||||
@@ -5007,8 +5073,9 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
if (!isAttributionTagValid) {
|
||||
AndroidPackage proxyPkg = proxyPackageName != null
|
||||
? pmInt.getPackage(proxyPackageName) : null;
|
||||
- // Re-check in proxy.
|
||||
- isAttributionTagValid = isAttributionInPackage(proxyPkg, attributionTag);
|
||||
+ // Re-check in proxy, if trusted.
|
||||
+ isAttributionTagValid =
|
||||
+ isProxyTrusted && isAttributionInPackage(proxyPkg, attributionTag);
|
||||
String msg;
|
||||
if (pkg != null && isAttributionTagValid) {
|
||||
msg = "attributionTag " + attributionTag + " declared in manifest of the proxy"
|
||||
@@ -5035,7 +5102,6 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
throw new SecurityException("Specified package \"" + packageName + "\" under uid " + uid
|
||||
+ otherUidMessage);
|
||||
}
|
||||
-
|
||||
return new PackageVerificationResult(bypass, isAttributionTagValid);
|
||||
}
|
||||
|
||||
@@ -5050,6 +5116,10 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
if (appId > 0 && appId < Process.FIRST_APPLICATION_UID) {
|
||||
return true;
|
||||
}
|
||||
+ if (mPackageManagerInternal.getPackageUid(packageName, PackageManager.MATCH_ALL,
|
||||
+ UserHandle.getUserId(uid)) != uid) {
|
||||
+ return false;
|
||||
+ }
|
||||
return mPackageManagerInternal.isSystemPackage(packageName);
|
||||
}
|
||||
|
||||
diff --git a/services/core/java/com/android/server/appop/AttributedOp.java b/services/core/java/com/android/server/appop/AttributedOp.java
|
||||
index b9bc27d9c696..73f9fede9ed6 100644
|
||||
--- a/services/core/java/com/android/server/appop/AttributedOp.java
|
||||
+++ b/services/core/java/com/android/server/appop/AttributedOp.java
|
||||
@@ -40,6 +40,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.function.Consumer;
|
||||
+import java.util.function.Predicate;
|
||||
|
||||
final class AttributedOp {
|
||||
private final @NonNull AppOpsService mAppOpsService;
|
||||
@@ -620,6 +621,19 @@ final class AttributedOp {
|
||||
return mPausedInProgressEvents != null && !mPausedInProgressEvents.isEmpty();
|
||||
}
|
||||
|
||||
+ public boolean hasInProgressEvent(Predicate<InProgressStartOpEvent> predicate) {
|
||||
+ ArrayMap<IBinder, InProgressStartOpEvent> events =
|
||||
+ isPaused() ? mPausedInProgressEvents : mInProgressEvents;
|
||||
+ if (events == null || events.isEmpty()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ for (int i = 0; i < events.size(); i++) {
|
||||
+ if (predicate.test(events.valueAt(i))) {
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
+ return false;
|
||||
+ }
|
||||
boolean hasAnyTime() {
|
||||
return (mAccessEvents != null && mAccessEvents.size() > 0)
|
||||
|| (mRejectEvents != null && mRejectEvents.size() > 0);
|
||||
--
|
||||
2.53.0
|
||||
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
From e770e9f0234158f4631c7147b64a1d70e0843d0b Mon Sep 17 00:00:00 2001
|
||||
From: Nate Myren <ntmyren@google.com>
|
||||
Date: Wed, 5 Nov 2025 14:36:49 -0800
|
||||
Subject: [PATCH] Trim permission, permission group names
|
||||
|
||||
Bug: 453649815
|
||||
Test: atest AppSecurityTests
|
||||
Flag: EXEMPT CVE_FIX
|
||||
(cherry picked from commit 595cf99ecd42927eebf804638a4623313f3f14db)
|
||||
Cherrypick-From: https://googleplex-android-review.googlesource.com/q/commit:08ea2a452c271ccf258d63efc0126c7fa13d3312
|
||||
Merged-In: I673ad83d05c9825177967e4f0a960e8841610b71
|
||||
Change-Id: I673ad83d05c9825177967e4f0a960e8841610b71
|
||||
---
|
||||
.../internal/pm/pkg/component/ParsedPermissionUtils.java | 7 ++++++-
|
||||
1 file changed, 6 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/core/java/com/android/internal/pm/pkg/component/ParsedPermissionUtils.java b/core/java/com/android/internal/pm/pkg/component/ParsedPermissionUtils.java
|
||||
index d4dabf51d4c7..0dd0969ae35e 100644
|
||||
--- a/core/java/com/android/internal/pm/pkg/component/ParsedPermissionUtils.java
|
||||
+++ b/core/java/com/android/internal/pm/pkg/component/ParsedPermissionUtils.java
|
||||
@@ -152,6 +152,8 @@ public class ParsedPermissionUtils {
|
||||
}
|
||||
}
|
||||
|
||||
+ permission.setName(permission.getName().trim());
|
||||
+
|
||||
permission.setProtectionLevel(
|
||||
PermissionInfo.fixProtectionLevel(permission.getProtectionLevel()));
|
||||
|
||||
@@ -199,6 +201,8 @@ public class ParsedPermissionUtils {
|
||||
sa.recycle();
|
||||
}
|
||||
|
||||
+ permission.setName(permission.getName().trim());
|
||||
+
|
||||
int index = permission.getName().indexOf('.');
|
||||
if (index > 0) {
|
||||
index = permission.getName().indexOf('.', index + 1);
|
||||
@@ -248,7 +252,8 @@ public class ParsedPermissionUtils {
|
||||
.setBackgroundRequestDetailRes(sa.getResourceId(R.styleable.AndroidManifestPermissionGroup_backgroundRequestDetail, 0))
|
||||
.setRequestRes(sa.getResourceId(R.styleable.AndroidManifestPermissionGroup_request, 0))
|
||||
.setPriority(sa.getInt(R.styleable.AndroidManifestPermissionGroup_priority, 0))
|
||||
- .setFlags(sa.getInt(R.styleable.AndroidManifestPermissionGroup_permissionGroupFlags,0));
|
||||
+ .setFlags(sa.getInt(R.styleable.AndroidManifestPermissionGroup_permissionGroupFlags,0))
|
||||
+ .setName(permissionGroup.getName().trim());
|
||||
// @formatter:on
|
||||
} finally {
|
||||
sa.recycle();
|
||||
--
|
||||
2.53.0
|
||||
|
||||
|
|
@ -1,222 +0,0 @@
|
|||
From cea235f00865ff73344f1efa9494e47beecc3fd5 Mon Sep 17 00:00:00 2001
|
||||
From: Shawn Lin <shawnlin@google.com>
|
||||
Date: Wed, 15 Oct 2025 12:18:38 +0000
|
||||
Subject: [PATCH] Fixed "Unlock your phone" unexpectedlly turned ON after OTA
|
||||
|
||||
If the new setting key is not set, we should use the value of the old
|
||||
ones as the default value.
|
||||
|
||||
Bug: 444673089
|
||||
Test: atest BiometricServiceTest
|
||||
Flag: EXEMPT BUGFIX
|
||||
(cherry picked from commit a3799e443e9fdbbcbc96824b8d2fc1e4c683bb7e)
|
||||
Cherrypick-From: https://googleplex-android-review.googlesource.com/q/commit:2b8bc2b15f2aceb4e2a379209997afce16427e76
|
||||
Merged-In: I902c7fd9781037ba05b30821b4fa22aa1509f3fd
|
||||
Change-Id: I902c7fd9781037ba05b30821b4fa22aa1509f3fd
|
||||
---
|
||||
.../server/biometrics/BiometricService.java | 45 ++++++++-
|
||||
.../biometrics/BiometricServiceTest.java | 91 +++++++++++++++++++
|
||||
2 files changed, 132 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java
|
||||
index cf5fa9699ca9..7485929147e5 100644
|
||||
--- a/services/core/java/com/android/server/biometrics/BiometricService.java
|
||||
+++ b/services/core/java/com/android/server/biometrics/BiometricService.java
|
||||
@@ -412,20 +412,39 @@ public class BiometricService extends SystemService {
|
||||
notifyEnabledOnKeyguardCallbacks(userId, TYPE_ANY_BIOMETRIC);
|
||||
}
|
||||
} else if (FACE_KEYGUARD_ENABLED.equals(uri)) {
|
||||
+ final int biometricKeyguardEnabled = Settings.Secure.getIntForUser(
|
||||
+ mContentResolver,
|
||||
+ Settings.Secure.BIOMETRIC_KEYGUARD_ENABLED,
|
||||
+ -1 /* default */,
|
||||
+ userId);
|
||||
+ // For OTA case: if FACE_KEYGUARD_ENABLED is not set and BIOMETRIC_APP_ENABLED is
|
||||
+ // set, set the default value of the former to that of the latter.
|
||||
+ final boolean defaultValue = biometricKeyguardEnabled == -1
|
||||
+ ? DEFAULT_KEYGUARD_ENABLED : biometricKeyguardEnabled == 1;
|
||||
mFaceEnabledOnKeyguard.put(userId, Settings.Secure.getIntForUser(
|
||||
mContentResolver,
|
||||
Settings.Secure.FACE_KEYGUARD_ENABLED,
|
||||
- DEFAULT_KEYGUARD_ENABLED ? 1 : 0 /* default */,
|
||||
+ defaultValue ? 1 : 0 /* default */,
|
||||
userId) != 0);
|
||||
|
||||
if (userId == ActivityManager.getCurrentUser() && !selfChange) {
|
||||
notifyEnabledOnKeyguardCallbacks(userId, TYPE_FACE);
|
||||
}
|
||||
} else if (FINGERPRINT_KEYGUARD_ENABLED.equals(uri)) {
|
||||
+ final int biometricKeyguardEnabled = Settings.Secure.getIntForUser(
|
||||
+ mContentResolver,
|
||||
+ Settings.Secure.BIOMETRIC_KEYGUARD_ENABLED,
|
||||
+ -1 /* default */,
|
||||
+ userId);
|
||||
+ // For OTA case: if FINGERPRINT_KEYGUARD_ENABLED is not set and
|
||||
+ // BIOMETRIC_APP_ENABLED is set, set the default value of the former to that of the
|
||||
+ // latter.
|
||||
+ final boolean defaultValue = biometricKeyguardEnabled == -1
|
||||
+ ? DEFAULT_KEYGUARD_ENABLED : biometricKeyguardEnabled == 1;
|
||||
mFingerprintEnabledOnKeyguard.put(userId, Settings.Secure.getIntForUser(
|
||||
mContentResolver,
|
||||
Settings.Secure.FINGERPRINT_KEYGUARD_ENABLED,
|
||||
- DEFAULT_KEYGUARD_ENABLED ? 1 : 0 /* default */,
|
||||
+ defaultValue ? 1 : 0 /* default */,
|
||||
userId) != 0);
|
||||
|
||||
if (userId == ActivityManager.getCurrentUser() && !selfChange) {
|
||||
@@ -438,16 +457,34 @@ public class BiometricService extends SystemService {
|
||||
DEFAULT_APP_ENABLED ? 1 : 0 /* default */,
|
||||
userId) != 0);
|
||||
} else if (FACE_APP_ENABLED.equals(uri)) {
|
||||
+ final int biometricAppEnabled = Settings.Secure.getIntForUser(
|
||||
+ mContentResolver,
|
||||
+ Settings.Secure.BIOMETRIC_APP_ENABLED,
|
||||
+ -1 /* default */,
|
||||
+ userId);
|
||||
+ // For OTA case: if FACE_APP_ENABLED is not set and BIOMETRIC_APP_ENABLED is set,
|
||||
+ // set the default value of the former to that of the latter.
|
||||
+ final boolean defaultValue = biometricAppEnabled == -1
|
||||
+ ? DEFAULT_APP_ENABLED : biometricAppEnabled == 1;
|
||||
mFaceEnabledForApps.put(userId, Settings.Secure.getIntForUser(
|
||||
mContentResolver,
|
||||
Settings.Secure.FACE_APP_ENABLED,
|
||||
- DEFAULT_APP_ENABLED ? 1 : 0 /* default */,
|
||||
+ defaultValue ? 1 : 0 /* default */,
|
||||
userId) != 0);
|
||||
} else if (FINGERPRINT_APP_ENABLED.equals(uri)) {
|
||||
+ final int biometricAppEnabled = Settings.Secure.getIntForUser(
|
||||
+ mContentResolver,
|
||||
+ Settings.Secure.BIOMETRIC_APP_ENABLED,
|
||||
+ -1 /* default */,
|
||||
+ userId);
|
||||
+ // For OTA case: if FINGERPRINT_APP_ENABLED is not set and BIOMETRIC_APP_ENABLED is
|
||||
+ // set, set the default value of the former to that of the latter.
|
||||
+ final boolean defaultValue = biometricAppEnabled == -1
|
||||
+ ? DEFAULT_APP_ENABLED : biometricAppEnabled == 1;
|
||||
mFingerprintEnabledForApps.put(userId, Settings.Secure.getIntForUser(
|
||||
mContentResolver,
|
||||
Settings.Secure.FINGERPRINT_APP_ENABLED,
|
||||
- DEFAULT_APP_ENABLED ? 1 : 0 /* default */,
|
||||
+ defaultValue ? 1 : 0 /* default */,
|
||||
userId) != 0);
|
||||
} else if (MANDATORY_BIOMETRICS_ENABLED.equals(uri)) {
|
||||
updateMandatoryBiometricsForAllProfiles(userId);
|
||||
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java b/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java
|
||||
index 9918a9a35c33..3061bab24518 100644
|
||||
--- a/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java
|
||||
+++ b/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java
|
||||
@@ -21,6 +21,12 @@ import static android.hardware.biometrics.BiometricAuthenticator.TYPE_CREDENTIAL
|
||||
import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE;
|
||||
import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT;
|
||||
import static android.hardware.biometrics.BiometricManager.Authenticators;
|
||||
+import static android.provider.Settings.Secure.BIOMETRIC_APP_ENABLED;
|
||||
+import static android.provider.Settings.Secure.BIOMETRIC_KEYGUARD_ENABLED;
|
||||
+import static android.provider.Settings.Secure.FACE_APP_ENABLED;
|
||||
+import static android.provider.Settings.Secure.FACE_KEYGUARD_ENABLED;
|
||||
+import static android.provider.Settings.Secure.FINGERPRINT_APP_ENABLED;
|
||||
+import static android.provider.Settings.Secure.FINGERPRINT_KEYGUARD_ENABLED;
|
||||
import static android.view.DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS;
|
||||
|
||||
import static com.android.server.biometrics.BiometricServiceStateProto.STATE_AUTHENTICATED_PENDING_SYSUI;
|
||||
@@ -40,6 +46,7 @@ import static junit.framework.TestCase.assertNotNull;
|
||||
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
+import static org.junit.Assume.assumeTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
@@ -2147,6 +2154,90 @@ public class BiometricServiceTest {
|
||||
invokeCanAuthenticate(mBiometricService, Authenticators.BIOMETRIC_STRONG));
|
||||
}
|
||||
|
||||
+ @Test
|
||||
+ @RequiresFlagsEnabled(com.android.settings.flags.Flags.FLAG_BIOMETRICS_ONBOARDING_EDUCATION)
|
||||
+ public void
|
||||
+ testEnabledForApps_biometricAppEnableOff_fpAppEnabledNotSet_returnFalse()
|
||||
+ throws Exception {
|
||||
+ final Context context = ApplicationProvider.getApplicationContext();
|
||||
+ final int value = Settings.Secure.getIntForUser(context.getContentResolver(),
|
||||
+ FINGERPRINT_APP_ENABLED, -1, context.getUserId());
|
||||
+ assumeTrue("FINGERPRINT_APP_ENABLED is set. Skipped", value == -1);
|
||||
+
|
||||
+ Settings.Secure.putIntForUser(context.getContentResolver(),
|
||||
+ BIOMETRIC_APP_ENABLED, 0, context.getUserId());
|
||||
+
|
||||
+ final BiometricService.SettingObserver settingObserver =
|
||||
+ new BiometricService.SettingObserver(
|
||||
+ context, mBiometricHandlerProvider.getBiometricCallbackHandler(),
|
||||
+ new ArrayList<>(), mUserManager, mFingerprintManager, mFaceManager);
|
||||
+
|
||||
+ assertFalse(settingObserver.getEnabledForApps(context.getUserId(), TYPE_FINGERPRINT));
|
||||
+ }
|
||||
+
|
||||
+ @Test
|
||||
+ @RequiresFlagsEnabled(com.android.settings.flags.Flags.FLAG_BIOMETRICS_ONBOARDING_EDUCATION)
|
||||
+ public void
|
||||
+ testKeyguardEnabled_biometricKeyguardEnableOff_fpKeyguardEnabledNotSet_returnFalse()
|
||||
+ throws Exception {
|
||||
+ final Context context = ApplicationProvider.getApplicationContext();
|
||||
+ final int value = Settings.Secure.getIntForUser(context.getContentResolver(),
|
||||
+ FINGERPRINT_KEYGUARD_ENABLED, -1, context.getUserId());
|
||||
+ assumeTrue("FINGERPRINT_KEYGUARD_ENABLED is set. Skipped", value == -1);
|
||||
+
|
||||
+ Settings.Secure.putIntForUser(context.getContentResolver(),
|
||||
+ BIOMETRIC_KEYGUARD_ENABLED, 0, context.getUserId());
|
||||
+
|
||||
+ final BiometricService.SettingObserver settingObserver =
|
||||
+ new BiometricService.SettingObserver(
|
||||
+ context, mBiometricHandlerProvider.getBiometricCallbackHandler(),
|
||||
+ new ArrayList<>(), mUserManager, mFingerprintManager, mFaceManager);
|
||||
+
|
||||
+ assertFalse(settingObserver.getEnabledOnKeyguard(context.getUserId(), TYPE_FINGERPRINT));
|
||||
+ }
|
||||
+
|
||||
+ @Test
|
||||
+ @RequiresFlagsEnabled(com.android.settings.flags.Flags.FLAG_BIOMETRICS_ONBOARDING_EDUCATION)
|
||||
+ public void
|
||||
+ testEnabledForApps_biometricAppEnableOff_faceAppEnabledNotSet_returnFalse()
|
||||
+ throws Exception {
|
||||
+ final Context context = ApplicationProvider.getApplicationContext();
|
||||
+ final int value = Settings.Secure.getIntForUser(context.getContentResolver(),
|
||||
+ FACE_APP_ENABLED, -1, context.getUserId());
|
||||
+ assumeTrue("FACE_APP_ENABLED is set. Skipped", value == -1);
|
||||
+
|
||||
+ Settings.Secure.putIntForUser(context.getContentResolver(),
|
||||
+ BIOMETRIC_APP_ENABLED, 0, context.getUserId());
|
||||
+
|
||||
+ final BiometricService.SettingObserver settingObserver =
|
||||
+ new BiometricService.SettingObserver(
|
||||
+ context, mBiometricHandlerProvider.getBiometricCallbackHandler(),
|
||||
+ new ArrayList<>(), mUserManager, mFingerprintManager, mFaceManager);
|
||||
+
|
||||
+ assertFalse(settingObserver.getEnabledForApps(context.getUserId(), TYPE_FACE));
|
||||
+ }
|
||||
+
|
||||
+ @Test
|
||||
+ @RequiresFlagsEnabled(com.android.settings.flags.Flags.FLAG_BIOMETRICS_ONBOARDING_EDUCATION)
|
||||
+ public void
|
||||
+ testKeyguardEnabled_biometricKeyguardEnableOff_faceKeyguardEnabledNotSet_returnFalse()
|
||||
+ throws Exception {
|
||||
+ final Context context = ApplicationProvider.getApplicationContext();
|
||||
+ final int value = Settings.Secure.getIntForUser(context.getContentResolver(),
|
||||
+ FACE_KEYGUARD_ENABLED, -1, context.getUserId());
|
||||
+ assumeTrue("FACE_KEYGUARD_ENABLED is set. Skipped", value == -1);
|
||||
+
|
||||
+ Settings.Secure.putIntForUser(context.getContentResolver(),
|
||||
+ BIOMETRIC_KEYGUARD_ENABLED, 0, context.getUserId());
|
||||
+
|
||||
+ final BiometricService.SettingObserver settingObserver =
|
||||
+ new BiometricService.SettingObserver(
|
||||
+ context, mBiometricHandlerProvider.getBiometricCallbackHandler(),
|
||||
+ new ArrayList<>(), mUserManager, mFingerprintManager, mFaceManager);
|
||||
+
|
||||
+ assertFalse(settingObserver.getEnabledOnKeyguard(context.getUserId(), TYPE_FACE));
|
||||
+ }
|
||||
+
|
||||
// Helper methods
|
||||
|
||||
private int invokeCanAuthenticate(BiometricService service, int authenticators)
|
||||
--
|
||||
2.53.0
|
||||
|
||||
|
|
@ -1,496 +0,0 @@
|
|||
From 304bb7de32dea642932c73e09ec1bb2ef6cbf3d5 Mon Sep 17 00:00:00 2001
|
||||
From: Hiroki Sato <hirokisato@google.com>
|
||||
Date: Mon, 20 Oct 2025 19:13:15 +0900
|
||||
Subject: [PATCH] Harden InputMethodInfo parsing against large metadata
|
||||
|
||||
An IME's metadata can reference arbitrarily large strings (e.g.,
|
||||
@string/large_text), which can lead to OOM or large Binder transactions
|
||||
during parsing. The previous check only validated the raw XML file
|
||||
size, failing to account for the size of these resolved string
|
||||
references.
|
||||
|
||||
This patch hardens the InputMethodInfo constructor by enforcing a 200KB
|
||||
cumulative limit on all resolved metadata attributes. A new
|
||||
MetadataReadBytesTracker now sums the actual size of all read
|
||||
attributes, including the full length of any strings, and parsing is
|
||||
aborted if this 200KB limit is exceeded.
|
||||
|
||||
Bug: 449416164
|
||||
Bug: 449181366
|
||||
Bug: 449393786
|
||||
Bug: 449227003
|
||||
Test: CtsInputMethodTestCases:{InputMethodRegistrationTest,InputMethodInfoTest}
|
||||
Test: InputMethodCoreTests:{InputMethodSubtypeArrayTest,InputMethodInfoTest}
|
||||
Flag: EXEMPT BUGFIX
|
||||
(cherry picked from commit 7afc13faace7cfafd0353482db33504c5e269d69)
|
||||
Cherrypick-From: https://googleplex-android-review.googlesource.com/q/commit:75fd0e67bd2945d7314b56c24850bd9f1c2c4dbf
|
||||
Merged-In: I43f7be8eb80abeb39863a3b01d3a606beb90120c
|
||||
Change-Id: I43f7be8eb80abeb39863a3b01d3a606beb90120c
|
||||
---
|
||||
.../view/inputmethod/InputMethodInfo.java | 280 ++++++++++++++----
|
||||
.../view/inputmethod/InputMethodInfoTest.java | 98 ++++++
|
||||
2 files changed, 321 insertions(+), 57 deletions(-)
|
||||
|
||||
diff --git a/core/java/android/view/inputmethod/InputMethodInfo.java b/core/java/android/view/inputmethod/InputMethodInfo.java
|
||||
index c9485d7d3b0f4..184fea5be0f57 100644
|
||||
--- a/core/java/android/view/inputmethod/InputMethodInfo.java
|
||||
+++ b/core/java/android/view/inputmethod/InputMethodInfo.java
|
||||
@@ -50,6 +50,8 @@
|
||||
import android.util.Xml;
|
||||
import android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder;
|
||||
|
||||
+import com.android.internal.annotations.VisibleForTesting;
|
||||
+
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
@@ -313,68 +315,70 @@ public InputMethodInfo(Context context, ResolveInfo service,
|
||||
"Meta-data does not start with input-method tag");
|
||||
}
|
||||
|
||||
- TypedArray sa = res.obtainAttributes(attrs,
|
||||
- com.android.internal.R.styleable.InputMethod);
|
||||
- settingsActivityComponent = sa.getString(
|
||||
- com.android.internal.R.styleable.InputMethod_settingsActivity);
|
||||
- languageSettingsActivityComponent = sa.getString(
|
||||
- com.android.internal.R.styleable.InputMethod_languageSettingsActivity);
|
||||
- if ((si.name != null && si.name.length() > COMPONENT_NAME_MAX_LENGTH)
|
||||
- || (settingsActivityComponent != null
|
||||
- && settingsActivityComponent.length()
|
||||
- > COMPONENT_NAME_MAX_LENGTH)
|
||||
- || (languageSettingsActivityComponent != null
|
||||
- && languageSettingsActivityComponent.length()
|
||||
- > COMPONENT_NAME_MAX_LENGTH)) {
|
||||
- throw new XmlPullParserException(
|
||||
- "Activity name exceeds maximum of 1000 characters");
|
||||
+ final MetadataReadBytesTracker readTracker = new MetadataReadBytesTracker();
|
||||
+ try (TypedArrayWrapper sa = TypedArrayWrapper.createForMethod(
|
||||
+ res.obtainAttributes(attrs, com.android.internal.R.styleable.InputMethod),
|
||||
+ readTracker)) {
|
||||
+ settingsActivityComponent = sa.getString(
|
||||
+ com.android.internal.R.styleable.InputMethod_settingsActivity);
|
||||
+ languageSettingsActivityComponent = sa.getString(
|
||||
+ com.android.internal.R.styleable.InputMethod_languageSettingsActivity);
|
||||
+ isVrOnly = sa.getBoolean(com.android.internal.R.styleable.InputMethod_isVrOnly,
|
||||
+ false);
|
||||
+ isVirtualDeviceOnly = sa.getBoolean(
|
||||
+ com.android.internal.R.styleable.InputMethod_isVirtualDeviceOnly, false);
|
||||
+ isDefaultResId = sa.getResourceId(
|
||||
+ com.android.internal.R.styleable.InputMethod_isDefault, 0);
|
||||
+ supportsSwitchingToNextInputMethod = sa.getBoolean(
|
||||
+ com.android.internal.R.styleable
|
||||
+ .InputMethod_supportsSwitchingToNextInputMethod,
|
||||
+ false);
|
||||
+ inlineSuggestionsEnabled = sa.getBoolean(
|
||||
+ com.android.internal.R.styleable.InputMethod_supportsInlineSuggestions,
|
||||
+ false);
|
||||
+ supportsInlineSuggestionsWithTouchExploration = sa.getBoolean(
|
||||
+ com.android.internal.R.styleable
|
||||
+ .InputMethod_supportsInlineSuggestionsWithTouchExploration, false);
|
||||
+ suppressesSpellChecker = sa.getBoolean(
|
||||
+ com.android.internal.R.styleable.InputMethod_suppressesSpellChecker, false);
|
||||
+ showInInputMethodPicker = sa.getBoolean(
|
||||
+ com.android.internal.R.styleable.InputMethod_showInInputMethodPicker, true);
|
||||
+ mHandledConfigChanges = sa.getInt(
|
||||
+ com.android.internal.R.styleable.InputMethod_configChanges, 0);
|
||||
+ mSupportsStylusHandwriting = sa.getBoolean(
|
||||
+ com.android.internal.R.styleable.InputMethod_supportsStylusHandwriting,
|
||||
+ false);
|
||||
+ mSupportsConnectionlessStylusHandwriting = sa.getBoolean(
|
||||
+ com.android.internal.R.styleable
|
||||
+ .InputMethod_supportsConnectionlessStylusHandwriting, false);
|
||||
+ stylusHandwritingSettingsActivity = sa.getString(
|
||||
+ com.android.internal.R.styleable
|
||||
+ .InputMethod_stylusHandwritingSettingsActivity);
|
||||
}
|
||||
|
||||
- isVrOnly = sa.getBoolean(com.android.internal.R.styleable.InputMethod_isVrOnly, false);
|
||||
- isVirtualDeviceOnly = sa.getBoolean(
|
||||
- com.android.internal.R.styleable.InputMethod_isVirtualDeviceOnly, false);
|
||||
- isDefaultResId = sa.getResourceId(
|
||||
- com.android.internal.R.styleable.InputMethod_isDefault, 0);
|
||||
- supportsSwitchingToNextInputMethod = sa.getBoolean(
|
||||
- com.android.internal.R.styleable.InputMethod_supportsSwitchingToNextInputMethod,
|
||||
- false);
|
||||
- inlineSuggestionsEnabled = sa.getBoolean(
|
||||
- com.android.internal.R.styleable.InputMethod_supportsInlineSuggestions, false);
|
||||
- supportsInlineSuggestionsWithTouchExploration = sa.getBoolean(
|
||||
- com.android.internal.R.styleable
|
||||
- .InputMethod_supportsInlineSuggestionsWithTouchExploration, false);
|
||||
- suppressesSpellChecker = sa.getBoolean(
|
||||
- com.android.internal.R.styleable.InputMethod_suppressesSpellChecker, false);
|
||||
- showInInputMethodPicker = sa.getBoolean(
|
||||
- com.android.internal.R.styleable.InputMethod_showInInputMethodPicker, true);
|
||||
- mHandledConfigChanges = sa.getInt(
|
||||
- com.android.internal.R.styleable.InputMethod_configChanges, 0);
|
||||
- mSupportsStylusHandwriting = sa.getBoolean(
|
||||
- com.android.internal.R.styleable.InputMethod_supportsStylusHandwriting, false);
|
||||
- mSupportsConnectionlessStylusHandwriting = sa.getBoolean(
|
||||
- com.android.internal.R.styleable
|
||||
- .InputMethod_supportsConnectionlessStylusHandwriting, false);
|
||||
- stylusHandwritingSettingsActivity = sa.getString(
|
||||
- com.android.internal.R.styleable.InputMethod_stylusHandwritingSettingsActivity);
|
||||
- sa.recycle();
|
||||
-
|
||||
final int depth = parser.getDepth();
|
||||
// Parse all subtypes
|
||||
while (((type = parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth)
|
||||
&& type != XmlPullParser.END_DOCUMENT) {
|
||||
- if (type == XmlPullParser.START_TAG) {
|
||||
- nodeName = parser.getName();
|
||||
- if (!"subtype".equals(nodeName)) {
|
||||
- throw new XmlPullParserException(
|
||||
- "Meta-data in input-method does not start with subtype tag");
|
||||
- }
|
||||
- final TypedArray a = res.obtainAttributes(
|
||||
- attrs, com.android.internal.R.styleable.InputMethod_Subtype);
|
||||
+ if (type != XmlPullParser.START_TAG) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ nodeName = parser.getName();
|
||||
+ if (!"subtype".equals(nodeName)) {
|
||||
+ throw new XmlPullParserException(
|
||||
+ "Meta-data in input-method does not start with subtype tag");
|
||||
+ }
|
||||
+
|
||||
+ final InputMethodSubtype subtype;
|
||||
+ try (TypedArrayWrapper a = TypedArrayWrapper.createForSubtype(
|
||||
+ res.obtainAttributes(attrs,
|
||||
+ com.android.internal.R.styleable.InputMethod_Subtype),
|
||||
+ readTracker)) {
|
||||
String pkLanguageTag = a.getString(com.android.internal.R.styleable
|
||||
.InputMethod_Subtype_physicalKeyboardHintLanguageTag);
|
||||
String pkLayoutType = a.getString(com.android.internal.R.styleable
|
||||
.InputMethod_Subtype_physicalKeyboardHintLayoutType);
|
||||
- final InputMethodSubtype subtype = new InputMethodSubtypeBuilder()
|
||||
+ subtype = new InputMethodSubtypeBuilder()
|
||||
.setSubtypeNameResId(a.getResourceId(com.android.internal.R.styleable
|
||||
.InputMethod_Subtype_label, 0))
|
||||
.setSubtypeIconResId(a.getResourceId(com.android.internal.R.styleable
|
||||
@@ -399,12 +403,11 @@ public InputMethodInfo(Context context, ResolveInfo service,
|
||||
.InputMethod_Subtype_subtypeId, 0 /* use Arrays.hashCode */))
|
||||
.setIsAsciiCapable(a.getBoolean(com.android.internal.R.styleable
|
||||
.InputMethod_Subtype_isAsciiCapable, false)).build();
|
||||
- a.recycle();
|
||||
- if (!subtype.isAuxiliary()) {
|
||||
- isAuxIme = false;
|
||||
- }
|
||||
- subtypes.add(subtype);
|
||||
}
|
||||
+ if (!subtype.isAuxiliary()) {
|
||||
+ isAuxIme = false;
|
||||
+ }
|
||||
+ subtypes.add(subtype);
|
||||
}
|
||||
} catch (NameNotFoundException | IndexOutOfBoundsException | NumberFormatException e) {
|
||||
throw new XmlPullParserException(
|
||||
@@ -468,6 +471,11 @@ private static void validateXmlMetaData(@NonNull ServiceInfo si, @NonNull Resour
|
||||
return;
|
||||
}
|
||||
|
||||
+ if (si.name != null && si.name.length() > COMPONENT_NAME_MAX_LENGTH) {
|
||||
+ throw new XmlPullParserException(
|
||||
+ "Input method name exceeds " + COMPONENT_NAME_MAX_LENGTH + " characters");
|
||||
+ }
|
||||
+
|
||||
// Validate file size using InputStream.skip()
|
||||
long totalBytesSkipped = 0;
|
||||
// Loop to ensure we skip the required number of bytes, as a single
|
||||
@@ -1128,4 +1136,162 @@ public InputMethodInfo[] newArray(int size) {
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
+
|
||||
+ /**
|
||||
+ * A wrapper class for {@link TypedArray} that enforces limits on the size of the metadata
|
||||
+ * read from the XML. Methods throw an {@link XmlPullParserException} if the limit is surpassed.
|
||||
+ *
|
||||
+ * <p>This class works in conjunction with {@link MetadataReadBytesTracker} to:
|
||||
+ * <ul>
|
||||
+ * <li>Limit the length of individual string attributes. For
|
||||
+ * {@code settingsActivity} and {@code languageSettingsActivity}, the maximum length is
|
||||
+ * {@link #COMPONENT_NAME_MAX_LENGTH}. For other string attributes, the maximum length is
|
||||
+ * {@link #STRING_ATTRIBUTES_MAX_CHAR_LENGTH}.</li>
|
||||
+ * <li>Track the total amount of data read from the metadata XML. The
|
||||
+ * {@link MetadataReadBytesTracker} ensures that the cumulative size of all attributes
|
||||
+ * does not exceed {@link #MAX_METADATA_SIZE_BYTES}.
|
||||
+ * </ul>
|
||||
+ *
|
||||
+ * @hide
|
||||
+ */
|
||||
+ @VisibleForTesting
|
||||
+ public static final class TypedArrayWrapper implements AutoCloseable {
|
||||
+ /** The underlying {@link TypedArray} to read from. */
|
||||
+ @NonNull
|
||||
+ private final TypedArray mTypedArray;
|
||||
+ /** Tracker for enforcing metadata size limits. */
|
||||
+ @NonNull
|
||||
+ private final MetadataReadBytesTracker mReadTracker;
|
||||
+ /** {@code true} if parsing a {@code <subtype>} tag, {@code false} otherwise. */
|
||||
+ private final boolean mIsReadingSubtype;
|
||||
+
|
||||
+ /**
|
||||
+ * Creates a {@link TypedArrayWrapper} for parsing attributes of the main
|
||||
+ * {@code <input-method>} tag.
|
||||
+ *
|
||||
+ * @param wrapped The {@link TypedArray} obtained for the {@code <input-method>} tag.
|
||||
+ * @param readTracker The tracker for monitoring data size.
|
||||
+ * @return A new {@link TypedArrayWrapper} instance.
|
||||
+ */
|
||||
+ @NonNull
|
||||
+ @VisibleForTesting
|
||||
+ public static TypedArrayWrapper createForMethod(
|
||||
+ @NonNull TypedArray wrapped, @NonNull MetadataReadBytesTracker readTracker) {
|
||||
+ return new TypedArrayWrapper(wrapped, readTracker, false);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Creates a {@link TypedArrayWrapper} for parsing attributes of a {@code <subtype>} tag.
|
||||
+ *
|
||||
+ * @param wrapped The {@link TypedArray} obtained for the {@code <subtype>} tag.
|
||||
+ * @param readTracker The tracker for monitoring data size.
|
||||
+ * @return A new {@link TypedArrayWrapper} instance.
|
||||
+ */
|
||||
+ @NonNull
|
||||
+ @VisibleForTesting
|
||||
+ public static TypedArrayWrapper createForSubtype(
|
||||
+ @NonNull TypedArray wrapped, @NonNull MetadataReadBytesTracker readTracker) {
|
||||
+ return new TypedArrayWrapper(wrapped, readTracker, true);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Constructs a new wrapper.
|
||||
+ */
|
||||
+ private TypedArrayWrapper(@NonNull TypedArray wrapped,
|
||||
+ @NonNull MetadataReadBytesTracker readTracker, boolean isReadingSubtype) {
|
||||
+ mTypedArray = wrapped;
|
||||
+ mReadTracker = readTracker;
|
||||
+ mIsReadingSubtype = isReadingSubtype;
|
||||
+ }
|
||||
+
|
||||
+ /** Retrieves an integer value for the attribute at {@code index}. */
|
||||
+ @VisibleForTesting
|
||||
+ public int getInt(int index, int defaultValue) throws XmlPullParserException {
|
||||
+ if (!mTypedArray.hasValue(index)) {
|
||||
+ return defaultValue;
|
||||
+ }
|
||||
+ final int ret = mTypedArray.getInt(index, defaultValue);
|
||||
+ mReadTracker.onReadBytes(Integer.BYTES);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ /** Retrieves the string value for the attribute at {@code index}. */
|
||||
+ @VisibleForTesting
|
||||
+ public String getString(int index) throws XmlPullParserException {
|
||||
+ final String ret = mTypedArray.getString(index);
|
||||
+ final int maxLen = getMaxLength(index);
|
||||
+ if (ret != null && ret.length() > maxLen) {
|
||||
+ throw new XmlPullParserException(
|
||||
+ "String resources in input method exceed the length limit of "
|
||||
+ + maxLen + " characters");
|
||||
+ }
|
||||
+ mReadTracker.onReadBytes(ret == null ? 0 : ret.length() * Character.BYTES);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ /** Retrieves a boolean value for the attribute at {@code index}. */
|
||||
+ @VisibleForTesting
|
||||
+ public boolean getBoolean(int index, boolean defaultValue) throws XmlPullParserException {
|
||||
+ if (!mTypedArray.hasValue(index)) {
|
||||
+ return defaultValue;
|
||||
+ }
|
||||
+ final boolean ret = mTypedArray.getBoolean(index, defaultValue);
|
||||
+ mReadTracker.onReadBytes(1);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ /** Retrieves a resource identifier for the attribute at {@code index}. */
|
||||
+ @VisibleForTesting
|
||||
+ public int getResourceId(int index, int defaultValue) throws XmlPullParserException {
|
||||
+ if (!mTypedArray.hasValue(index)) {
|
||||
+ return defaultValue;
|
||||
+ }
|
||||
+ final int ret = mTypedArray.getResourceId(index, defaultValue);
|
||||
+ mReadTracker.onReadBytes(Integer.BYTES);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void close() {
|
||||
+ mTypedArray.recycle();
|
||||
+ }
|
||||
+
|
||||
+ private int getMaxLength(int index) {
|
||||
+ // Note that the Android resource has limit DEFAULT_MAX_STRING_ATTR_LENGTH = 32_768.
|
||||
+ if (mIsReadingSubtype) {
|
||||
+ // No limits for strings in subtype for now.
|
||||
+ return Integer.MAX_VALUE;
|
||||
+ } else {
|
||||
+ return switch (index) {
|
||||
+ // TODO(b/456008595): Consider to add
|
||||
+ // InputMethod_stylusHandwritingSettingsActivity
|
||||
+ case com.android.internal.R.styleable.InputMethod_settingsActivity,
|
||||
+ com.android.internal.R.styleable.InputMethod_languageSettingsActivity ->
|
||||
+ COMPONENT_NAME_MAX_LENGTH;
|
||||
+ default ->
|
||||
+ // TODO(b/456008595): Consider to introduce limits.
|
||||
+ Integer.MAX_VALUE;
|
||||
+ };
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /** @hide */
|
||||
+ @VisibleForTesting
|
||||
+ public static final class MetadataReadBytesTracker {
|
||||
+ private int mRemainingBytes = MAX_METADATA_SIZE_BYTES;
|
||||
+
|
||||
+ @VisibleForTesting
|
||||
+ public MetadataReadBytesTracker() {
|
||||
+ }
|
||||
+
|
||||
+ private void onReadBytes(int bytes) throws XmlPullParserException {
|
||||
+ mRemainingBytes -= bytes;
|
||||
+ if (mRemainingBytes < 0) {
|
||||
+ throw new XmlPullParserException(
|
||||
+ "The input method service has metadata exceeds the "
|
||||
+ + MAX_METADATA_SIZE_BYTES + " byte limit");
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
diff --git a/core/tests/InputMethodCoreTests/src/android/view/inputmethod/InputMethodInfoTest.java b/core/tests/InputMethodCoreTests/src/android/view/inputmethod/InputMethodInfoTest.java
|
||||
index 87333dd31b8d3..1ccc9e5483298 100644
|
||||
--- a/core/tests/InputMethodCoreTests/src/android/view/inputmethod/InputMethodInfoTest.java
|
||||
+++ b/core/tests/InputMethodCoreTests/src/android/view/inputmethod/InputMethodInfoTest.java
|
||||
@@ -16,18 +16,27 @@
|
||||
|
||||
package android.view.inputmethod;
|
||||
|
||||
+import static android.view.inputmethod.InputMethodInfo.COMPONENT_NAME_MAX_LENGTH;
|
||||
+
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
+import static org.junit.Assert.assertThrows;
|
||||
+import static org.mockito.Mockito.mock;
|
||||
+import static org.mockito.Mockito.verify;
|
||||
+import static org.mockito.Mockito.when;
|
||||
|
||||
import android.annotation.XmlRes;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.content.pm.ServiceInfo;
|
||||
+import android.content.res.TypedArray;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcel;
|
||||
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
|
||||
import android.platform.test.flag.junit.SetFlagsRule;
|
||||
+import android.view.inputmethod.InputMethodInfo.MetadataReadBytesTracker;
|
||||
+import android.view.inputmethod.InputMethodInfo.TypedArrayWrapper;
|
||||
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import androidx.test.filters.SmallTest;
|
||||
@@ -38,6 +47,7 @@
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
+import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@@ -131,6 +141,94 @@ public void testIsVirtualDeviceOnly() throws Exception {
|
||||
assertThat(clone.isVirtualDeviceOnly(), is(true));
|
||||
}
|
||||
|
||||
+ @Test
|
||||
+ public void testTypedArrayWrapper() throws Exception {
|
||||
+ final TypedArray mockTypedArray = mock(TypedArray.class);
|
||||
+ when(mockTypedArray.hasValue(0)).thenReturn(true);
|
||||
+ when(mockTypedArray.getInt(0, 0)).thenReturn(123);
|
||||
+ when(mockTypedArray.getString(1)).thenReturn("hello");
|
||||
+ when(mockTypedArray.hasValue(2)).thenReturn(true);
|
||||
+ when(mockTypedArray.getBoolean(2, false)).thenReturn(true);
|
||||
+ when(mockTypedArray.hasValue(3)).thenReturn(true);
|
||||
+ when(mockTypedArray.getResourceId(3, 0)).thenReturn(456);
|
||||
+
|
||||
+ try (TypedArrayWrapper wrapper = TypedArrayWrapper.createForMethod(mockTypedArray,
|
||||
+ new MetadataReadBytesTracker())) {
|
||||
+ assertThat(wrapper.getInt(0, 0), is(123));
|
||||
+ assertThat(wrapper.getString(1), is("hello"));
|
||||
+ assertThat(wrapper.getBoolean(2, false), is(true));
|
||||
+ assertThat(wrapper.getResourceId(3, 0), is(456));
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ @Test
|
||||
+ public void testTypedArrayWrapper_getString_throwsExceptionWhenStringTooLong()
|
||||
+ throws Exception {
|
||||
+ final TypedArray mockTypedArray = mock(TypedArray.class);
|
||||
+ final String longStringA = "a".repeat(COMPONENT_NAME_MAX_LENGTH + 1);
|
||||
+ final String longStringB = "b".repeat(COMPONENT_NAME_MAX_LENGTH + 1);
|
||||
+ when(mockTypedArray.getString(
|
||||
+ com.android.internal.R.styleable.InputMethod_settingsActivity))
|
||||
+ .thenReturn(longStringA);
|
||||
+ when(mockTypedArray.getString(
|
||||
+ com.android.internal.R.styleable.InputMethod_languageSettingsActivity))
|
||||
+ .thenReturn(longStringB);
|
||||
+
|
||||
+ try (TypedArrayWrapper wrapper = TypedArrayWrapper.createForMethod(mockTypedArray,
|
||||
+ new MetadataReadBytesTracker())) {
|
||||
+ assertThrows(
|
||||
+ XmlPullParserException.class,
|
||||
+ () -> wrapper.getString(
|
||||
+ com.android.internal.R.styleable.InputMethod_settingsActivity));
|
||||
+ assertThrows(
|
||||
+ XmlPullParserException.class,
|
||||
+ () -> wrapper.getString(
|
||||
+ com.android.internal.R.styleable.InputMethod_languageSettingsActivity));
|
||||
+ }
|
||||
+
|
||||
+ // The same index can be used for method and subtype for different attributes.
|
||||
+ // This verifies the same index returns the correct string for subtypes.
|
||||
+ try (TypedArrayWrapper wrapper = TypedArrayWrapper.createForSubtype(mockTypedArray,
|
||||
+ new MetadataReadBytesTracker())) {
|
||||
+ assertThat(wrapper.getString(
|
||||
+ com.android.internal.R.styleable.InputMethod_settingsActivity),
|
||||
+ is(longStringA));
|
||||
+ assertThat(wrapper.getString(
|
||||
+ com.android.internal.R.styleable.InputMethod_languageSettingsActivity),
|
||||
+ is(longStringB));
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ @Test
|
||||
+ public void testTypedArrayWrapper_closeRecyclesTypedArray() {
|
||||
+ final TypedArray mockTypedArray = mock(TypedArray.class);
|
||||
+ final TypedArrayWrapper wrapper = TypedArrayWrapper.createForMethod(mockTypedArray,
|
||||
+ new MetadataReadBytesTracker());
|
||||
+
|
||||
+ wrapper.close();
|
||||
+
|
||||
+ verify(mockTypedArray).recycle();
|
||||
+ }
|
||||
+
|
||||
+ @Test
|
||||
+ public void testTypedArrayWrapper_metadataReadBytesTracker_throwsExceptionWhenLimitExceeded() {
|
||||
+ final TypedArray mockTypedArray = mock(TypedArray.class);
|
||||
+ final String longString = "a".repeat(1000);
|
||||
+ when(mockTypedArray.getString(0)).thenReturn(longString);
|
||||
+
|
||||
+ try (TypedArrayWrapper wrapper = TypedArrayWrapper.createForMethod(mockTypedArray,
|
||||
+ new MetadataReadBytesTracker())) {
|
||||
+ assertThrows(XmlPullParserException.class, () -> {
|
||||
+ // Each character is 2 bytes. 1000 chars * 2 = 2000 bytes per call.
|
||||
+ // Limit is 200 * 1024 = 204800 bytes.
|
||||
+ // 204800 / 2000 = 102.4. So 103 calls will exceed the limit.
|
||||
+ for (int i = 0; i < 103; ++i) {
|
||||
+ wrapper.getString(0);
|
||||
+ }
|
||||
+ });
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
private InputMethodInfo buildInputMethodForTest(final @XmlRes int metaDataRes)
|
||||
throws Exception {
|
||||
final Context context = InstrumentationRegistry.getInstrumentation().getContext();
|
||||
|
|
@ -1,837 +0,0 @@
|
|||
From bec80a52aaab578aa0f18527b6e40e165bfb45ab Mon Sep 17 00:00:00 2001
|
||||
From: Hiroki Sato <hirokisato@google.com>
|
||||
Date: Tue, 4 Nov 2025 17:29:42 +0900
|
||||
Subject: [PATCH] Introduce InputMethodSubtypeSafeList
|
||||
|
||||
IMM#getEnabledInputMethodSubtypeList() can return a large list of
|
||||
subtypes, which may cause a TransactionTooLargeException.
|
||||
|
||||
This patch introduces InputMethodSubtypeSafeList to wrap the list as a
|
||||
byte array, avoiding the exception. This mirrors the existing
|
||||
InputMethodInfoSafeList pattern introduced in [1].
|
||||
|
||||
Additionally, this change extracts the common marshalling logic from
|
||||
InputMethodInfoSafeList into a new AbstractSafeList and refactors both
|
||||
SafeList classes to extend it.
|
||||
|
||||
[1] I0a7667070fcdf17d34b248a5988c38064588718a
|
||||
|
||||
DISABLE_TOPIC_PROTECTOR
|
||||
|
||||
Bug: 449416164
|
||||
Bug: 449181366
|
||||
Bug: 449393786
|
||||
Bug: 449227003
|
||||
Test: CtsInputMethodTestCases:{InputMethodRegistrationTest,InputMethodInfoTest}
|
||||
Test: InputMethodCoreTests
|
||||
Flag: EXEMPT BUGFIX
|
||||
(cherry picked from commit 1d68a1099be2b99e8410dad01822851287994682)
|
||||
Cherrypick-From: https://googleplex-android-review.googlesource.com/q/commit:46388aba14b1698df8c98e96d97b50130d1ce085
|
||||
Merged-In: Ied64a9f018fd3e79cfc51ccd82d361b43e5f29dc
|
||||
Change-Id: Ied64a9f018fd3e79cfc51ccd82d361b43e5f29dc
|
||||
---
|
||||
.../IInputMethodManagerGlobalInvoker.java | 6 +-
|
||||
.../inputmethod/AbstractSafeList.java | 127 +++++++++++++++++
|
||||
.../inputmethod/InputMethodInfoSafeList.java | 105 +++-----------
|
||||
.../InputMethodSubtypeSafeList.aidl | 19 +++
|
||||
.../InputMethodSubtypeSafeList.java | 87 ++++++++++++
|
||||
.../internal/view/IInputMethodManager.aidl | 3 +-
|
||||
.../inputmethod/AbstractSafeListTest.java | 98 ++++++++++++++
|
||||
.../InputMethodSubtypeSafeListTest.java | 128 ++++++++++++++++++
|
||||
.../inputmethod/IInputMethodManagerImpl.java | 7 +-
|
||||
.../InputMethodManagerService.java | 13 +-
|
||||
.../server/inputmethod/ZeroJankProxy.java | 4 +-
|
||||
11 files changed, 497 insertions(+), 100 deletions(-)
|
||||
create mode 100644 core/java/com/android/internal/inputmethod/AbstractSafeList.java
|
||||
create mode 100644 core/java/com/android/internal/inputmethod/InputMethodSubtypeSafeList.aidl
|
||||
create mode 100644 core/java/com/android/internal/inputmethod/InputMethodSubtypeSafeList.java
|
||||
create mode 100644 core/tests/InputMethodCoreTests/src/com/android/internal/inputmethod/AbstractSafeListTest.java
|
||||
create mode 100644 core/tests/InputMethodCoreTests/src/com/android/internal/inputmethod/InputMethodSubtypeSafeListTest.java
|
||||
|
||||
diff --git a/core/java/android/view/inputmethod/IInputMethodManagerGlobalInvoker.java b/core/java/android/view/inputmethod/IInputMethodManagerGlobalInvoker.java
|
||||
index fe5afe437834d..b679da84c24d1 100644
|
||||
--- a/core/java/android/view/inputmethod/IInputMethodManagerGlobalInvoker.java
|
||||
+++ b/core/java/android/view/inputmethod/IInputMethodManagerGlobalInvoker.java
|
||||
@@ -44,6 +44,7 @@
|
||||
import com.android.internal.inputmethod.IRemoteComputerControlInputConnection;
|
||||
import com.android.internal.inputmethod.IRemoteInputConnection;
|
||||
import com.android.internal.inputmethod.InputMethodInfoSafeList;
|
||||
+import com.android.internal.inputmethod.InputMethodSubtypeSafeList;
|
||||
import com.android.internal.inputmethod.SoftInputShowHideReason;
|
||||
import com.android.internal.inputmethod.StartInputFlags;
|
||||
import com.android.internal.inputmethod.StartInputReason;
|
||||
@@ -250,8 +251,9 @@ static List<InputMethodSubtype> getEnabledInputMethodSubtypeList(@Nullable Strin
|
||||
return new ArrayList<>();
|
||||
}
|
||||
try {
|
||||
- return service.getEnabledInputMethodSubtypeList(imiId,
|
||||
- allowsImplicitlyEnabledSubtypes, userId);
|
||||
+ return InputMethodSubtypeSafeList.extractFrom(
|
||||
+ service.getEnabledInputMethodSubtypeList(imiId,
|
||||
+ allowsImplicitlyEnabledSubtypes, userId));
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
diff --git a/core/java/com/android/internal/inputmethod/AbstractSafeList.java b/core/java/com/android/internal/inputmethod/AbstractSafeList.java
|
||||
new file mode 100644
|
||||
index 0000000000000..697b153afecfe
|
||||
--- /dev/null
|
||||
+++ b/core/java/com/android/internal/inputmethod/AbstractSafeList.java
|
||||
@@ -0,0 +1,127 @@
|
||||
+/*
|
||||
+ * Copyright 2025 The Android Open Source Project
|
||||
+ *
|
||||
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
||||
+ * you may not use this file except in compliance with the License.
|
||||
+ * You may obtain a copy of the License at
|
||||
+ *
|
||||
+ * http://www.apache.org/licenses/LICENSE-2.0
|
||||
+ *
|
||||
+ * Unless required by applicable law or agreed to in writing, software
|
||||
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
||||
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
+ * See the License for the specific language governing permissions and
|
||||
+ * limitations under the License.
|
||||
+ */
|
||||
+
|
||||
+package com.android.internal.inputmethod;
|
||||
+
|
||||
+import android.annotation.NonNull;
|
||||
+import android.annotation.Nullable;
|
||||
+import android.os.Parcel;
|
||||
+import android.os.Parcelable;
|
||||
+
|
||||
+import com.android.internal.annotations.VisibleForTesting;
|
||||
+
|
||||
+import java.util.ArrayList;
|
||||
+import java.util.List;
|
||||
+
|
||||
+/**
|
||||
+ * An abstract base class for creating a {@link Parcelable} container that can hold an arbitrary
|
||||
+ * number of {@link Parcelable} objects without worrying about
|
||||
+ * {@link android.os.TransactionTooLargeException}.
|
||||
+ *
|
||||
+ * @see Parcel#readBlob()
|
||||
+ * @see Parcel#writeBlob(byte[])
|
||||
+ *
|
||||
+ * @param <T> The type of the {@link Parcelable} objects.
|
||||
+ */
|
||||
+public abstract class AbstractSafeList<T extends Parcelable> implements Parcelable {
|
||||
+ @Nullable
|
||||
+ private byte[] mBuffer;
|
||||
+
|
||||
+ protected AbstractSafeList(@Nullable List<T> list) {
|
||||
+ if (list != null && !list.isEmpty()) {
|
||||
+ mBuffer = marshall(list);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ protected AbstractSafeList(@Nullable byte[] buffer) {
|
||||
+ mBuffer = buffer;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Extracts the list of {@link Parcelable} objects from a {@link AbstractSafeList}, and
|
||||
+ * clears the internal buffer of the list.
|
||||
+ *
|
||||
+ * @param from The {@link AbstractSafeList} to extract from.
|
||||
+ * @param creator The {@link Parcelable.Creator} for the {@link Parcelable} objects.
|
||||
+ * @param <T> The type of the {@link Parcelable} objects.
|
||||
+ * @return The list of {@link Parcelable} objects.
|
||||
+ */
|
||||
+ @NonNull
|
||||
+ protected static <T extends Parcelable> List<T> extractFrom(
|
||||
+ @Nullable AbstractSafeList<T> from, @NonNull Parcelable.Creator<T> creator) {
|
||||
+ if (from == null) {
|
||||
+ return new ArrayList<>();
|
||||
+ }
|
||||
+ final byte[] buf = from.mBuffer;
|
||||
+ from.mBuffer = null;
|
||||
+ if (buf != null) {
|
||||
+ final List<T> list = unmarshall(buf, creator);
|
||||
+ if (list != null) {
|
||||
+ return list;
|
||||
+ }
|
||||
+ }
|
||||
+ return new ArrayList<>();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int describeContents() {
|
||||
+ // As long as the parcelled classes return 0, we can also return 0 here.
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
|
||||
+ dest.writeBlob(mBuffer);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Marshalls a list of {@link Parcelable} objects into a byte array.
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ @VisibleForTesting
|
||||
+ public static <T extends Parcelable> byte[] marshall(@NonNull List<T> list) {
|
||||
+ Parcel parcel = null;
|
||||
+ try {
|
||||
+ parcel = Parcel.obtain();
|
||||
+ parcel.writeTypedList(list);
|
||||
+ return parcel.marshall();
|
||||
+ } finally {
|
||||
+ if (parcel != null) {
|
||||
+ parcel.recycle();
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Unmarshalls a byte array into a list of {@link Parcelable} objects.
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ @VisibleForTesting
|
||||
+ public static <T extends Parcelable> List<T> unmarshall(
|
||||
+ @NonNull byte[] data, @NonNull Parcelable.Creator<T> creator) {
|
||||
+ Parcel parcel = null;
|
||||
+ try {
|
||||
+ parcel = Parcel.obtain();
|
||||
+ parcel.unmarshall(data, 0, data.length);
|
||||
+ parcel.setDataPosition(0);
|
||||
+ return parcel.createTypedArrayList(creator);
|
||||
+ } finally {
|
||||
+ if (parcel != null) {
|
||||
+ parcel.recycle();
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
diff --git a/core/java/com/android/internal/inputmethod/InputMethodInfoSafeList.java b/core/java/com/android/internal/inputmethod/InputMethodInfoSafeList.java
|
||||
index 9e720fb6cceea..a2ea5b08f13f3 100644
|
||||
--- a/core/java/com/android/internal/inputmethod/InputMethodInfoSafeList.java
|
||||
+++ b/core/java/com/android/internal/inputmethod/InputMethodInfoSafeList.java
|
||||
@@ -19,24 +19,24 @@
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.os.Parcel;
|
||||
-import android.os.Parcelable;
|
||||
import android.view.inputmethod.InputMethodInfo;
|
||||
|
||||
-import java.util.ArrayList;
|
||||
-import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
- * A {@link Parcelable} container that can holds an arbitrary number of {@link InputMethodInfo}
|
||||
- * without worrying about {@link android.os.TransactionTooLargeException} when passing across
|
||||
- * process boundary.
|
||||
- *
|
||||
- * @see Parcel#readBlob()
|
||||
- * @see Parcel#writeBlob(byte[])
|
||||
+ * A {@link android.os.Parcelable} container that can hold an arbitrary number of
|
||||
+ * {@link InputMethodInfo} without worrying about
|
||||
+ * {@link android.os.TransactionTooLargeException} when passing across process boundary.
|
||||
*/
|
||||
-public final class InputMethodInfoSafeList implements Parcelable {
|
||||
- @Nullable
|
||||
- private byte[] mBuffer;
|
||||
+public final class InputMethodInfoSafeList extends AbstractSafeList<InputMethodInfo> {
|
||||
+
|
||||
+ private InputMethodInfoSafeList(@Nullable byte[] buffer) {
|
||||
+ super(buffer);
|
||||
+ }
|
||||
+
|
||||
+ private InputMethodInfoSafeList(@Nullable List<InputMethodInfo> list) {
|
||||
+ super(list);
|
||||
+ }
|
||||
|
||||
/**
|
||||
* Instantiates a list of {@link InputMethodInfo} from the given {@link InputMethodInfoSafeList}
|
||||
@@ -53,81 +53,20 @@ public final class InputMethodInfoSafeList implements Parcelable {
|
||||
*/
|
||||
@NonNull
|
||||
public static List<InputMethodInfo> extractFrom(@Nullable InputMethodInfoSafeList from) {
|
||||
- final byte[] buf = from.mBuffer;
|
||||
- from.mBuffer = null;
|
||||
- if (buf != null) {
|
||||
- final InputMethodInfo[] array = unmarshall(buf);
|
||||
- if (array != null) {
|
||||
- return new ArrayList<>(Arrays.asList(array));
|
||||
- }
|
||||
- }
|
||||
- return new ArrayList<>();
|
||||
- }
|
||||
-
|
||||
- @NonNull
|
||||
- private static InputMethodInfo[] toArray(@Nullable List<InputMethodInfo> original) {
|
||||
- if (original == null) {
|
||||
- return new InputMethodInfo[0];
|
||||
- }
|
||||
- return original.toArray(new InputMethodInfo[0]);
|
||||
- }
|
||||
-
|
||||
- @Nullable
|
||||
- private static byte[] marshall(@NonNull InputMethodInfo[] array) {
|
||||
- Parcel parcel = null;
|
||||
- try {
|
||||
- parcel = Parcel.obtain();
|
||||
- parcel.writeTypedArray(array, 0);
|
||||
- return parcel.marshall();
|
||||
- } finally {
|
||||
- if (parcel != null) {
|
||||
- parcel.recycle();
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- @Nullable
|
||||
- private static InputMethodInfo[] unmarshall(byte[] data) {
|
||||
- Parcel parcel = null;
|
||||
- try {
|
||||
- parcel = Parcel.obtain();
|
||||
- parcel.unmarshall(data, 0, data.length);
|
||||
- parcel.setDataPosition(0);
|
||||
- return parcel.createTypedArray(InputMethodInfo.CREATOR);
|
||||
- } finally {
|
||||
- if (parcel != null) {
|
||||
- parcel.recycle();
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- private InputMethodInfoSafeList(@Nullable byte[] blob) {
|
||||
- mBuffer = blob;
|
||||
+ return AbstractSafeList.extractFrom(from, InputMethodInfo.CREATOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates {@link InputMethodInfoSafeList} from the given list of {@link InputMethodInfo}.
|
||||
*
|
||||
* @param list list of {@link InputMethodInfo} from which {@link InputMethodInfoSafeList} will
|
||||
- * be created
|
||||
+ * be created. Giving {@code null} will result in an empty
|
||||
+ * {@link InputMethodInfoSafeList}.
|
||||
* @return {@link InputMethodInfoSafeList} that stores the given list of {@link InputMethodInfo}
|
||||
*/
|
||||
@NonNull
|
||||
public static InputMethodInfoSafeList create(@Nullable List<InputMethodInfo> list) {
|
||||
- if (list == null || list.isEmpty()) {
|
||||
- return empty();
|
||||
- }
|
||||
- return new InputMethodInfoSafeList(marshall(toArray(list)));
|
||||
- }
|
||||
-
|
||||
- /**
|
||||
- * Creates an empty {@link InputMethodInfoSafeList}.
|
||||
- *
|
||||
- * @return {@link InputMethodInfoSafeList} that is empty
|
||||
- */
|
||||
- @NonNull
|
||||
- public static InputMethodInfoSafeList empty() {
|
||||
- return new InputMethodInfoSafeList(null);
|
||||
+ return new InputMethodInfoSafeList(list);
|
||||
}
|
||||
|
||||
public static final Creator<InputMethodInfoSafeList> CREATOR = new Creator<>() {
|
||||
@@ -141,16 +80,4 @@ public InputMethodInfoSafeList[] newArray(int size) {
|
||||
return new InputMethodInfoSafeList[size];
|
||||
}
|
||||
};
|
||||
-
|
||||
- @Override
|
||||
- public int describeContents() {
|
||||
- // As long as InputMethodInfo#describeContents() is guaranteed to return 0, we can always
|
||||
- // return 0 here.
|
||||
- return 0;
|
||||
- }
|
||||
-
|
||||
- @Override
|
||||
- public void writeToParcel(Parcel dest, int flags) {
|
||||
- dest.writeBlob(mBuffer);
|
||||
- }
|
||||
}
|
||||
diff --git a/core/java/com/android/internal/inputmethod/InputMethodSubtypeSafeList.aidl b/core/java/com/android/internal/inputmethod/InputMethodSubtypeSafeList.aidl
|
||||
new file mode 100644
|
||||
index 0000000000000..11000632eba54
|
||||
--- /dev/null
|
||||
+++ b/core/java/com/android/internal/inputmethod/InputMethodSubtypeSafeList.aidl
|
||||
@@ -0,0 +1,19 @@
|
||||
+/*
|
||||
+ * Copyright 2025 The Android Open Source Project
|
||||
+ *
|
||||
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
||||
+ * you may not use this file except in compliance with the License.
|
||||
+ * You may obtain a copy of the License at
|
||||
+ *
|
||||
+ * http://www.apache.org/licenses/LICENSE-2.0
|
||||
+ *
|
||||
+ * Unless required by applicable law or agreed to in writing, software
|
||||
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
||||
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
+ * See the License for the specific language governing permissions and
|
||||
+ * limitations under the License.
|
||||
+ */
|
||||
+
|
||||
+package com.android.internal.inputmethod;
|
||||
+
|
||||
+parcelable InputMethodSubtypeSafeList;
|
||||
diff --git a/core/java/com/android/internal/inputmethod/InputMethodSubtypeSafeList.java b/core/java/com/android/internal/inputmethod/InputMethodSubtypeSafeList.java
|
||||
new file mode 100644
|
||||
index 0000000000000..cd95088f5cf0d
|
||||
--- /dev/null
|
||||
+++ b/core/java/com/android/internal/inputmethod/InputMethodSubtypeSafeList.java
|
||||
@@ -0,0 +1,87 @@
|
||||
+/*
|
||||
+ * Copyright 2025 The Android Open Source Project
|
||||
+ *
|
||||
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
||||
+ * you may not use this file except in compliance with the License.
|
||||
+ * You may obtain a copy of the License at
|
||||
+ *
|
||||
+ * http://www.apache.org/licenses/LICENSE-2.0
|
||||
+ *
|
||||
+ * Unless required by applicable law or agreed to in writing, software
|
||||
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
||||
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
+ * See the License for the specific language governing permissions and
|
||||
+ * limitations under the License.
|
||||
+ */
|
||||
+
|
||||
+package com.android.internal.inputmethod;
|
||||
+
|
||||
+import android.annotation.NonNull;
|
||||
+import android.annotation.Nullable;
|
||||
+import android.os.Parcel;
|
||||
+import android.view.inputmethod.InputMethodSubtype;
|
||||
+
|
||||
+import java.util.List;
|
||||
+
|
||||
+/**
|
||||
+ * A {@link android.os.Parcelable} container that can hold an arbitrary number of
|
||||
+ * {@link InputMethodSubtype} without worrying about
|
||||
+ * {@link android.os.TransactionTooLargeException} when passing across process boundary.
|
||||
+ */
|
||||
+public final class InputMethodSubtypeSafeList extends AbstractSafeList<InputMethodSubtype> {
|
||||
+
|
||||
+ private InputMethodSubtypeSafeList(@Nullable byte[] buffer) {
|
||||
+ super(buffer);
|
||||
+ }
|
||||
+
|
||||
+ private InputMethodSubtypeSafeList(@Nullable List<InputMethodSubtype> list) {
|
||||
+ super(list);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Instantiates a list of {@link InputMethodSubtype} from the given
|
||||
+ * {@link InputMethodSubtypeSafeList} then clears the internal buffer of
|
||||
+ * {@link InputMethodSubtypeSafeList}.
|
||||
+ *
|
||||
+ * <p>Note that each {@link InputMethodSubtype} item is guaranteed to be a copy of the original
|
||||
+ * {@link InputMethodSubtype} object.</p>
|
||||
+ *
|
||||
+ * <p>Any subsequent call will return an empty list.</p>
|
||||
+ *
|
||||
+ * @param from {@link InputMethodSubtypeSafeList} from which the list of
|
||||
+ * {@link InputMethodSubtype} will be extracted
|
||||
+ * @return list of {@link InputMethodSubtype} stored in the given
|
||||
+ * {@link InputMethodSubtypeSafeList}
|
||||
+ */
|
||||
+ @NonNull
|
||||
+ public static List<InputMethodSubtype> extractFrom(@Nullable InputMethodSubtypeSafeList from) {
|
||||
+ return AbstractSafeList.extractFrom(from, InputMethodSubtype.CREATOR);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Instantiates {@link InputMethodSubtypeSafeList} from the given list of
|
||||
+ * {@link InputMethodSubtype}.
|
||||
+ *
|
||||
+ * @param list list of {@link InputMethodSubtype} from which
|
||||
+ * {@link InputMethodSubtypeSafeList} will be created. Giving {@code null} will
|
||||
+ * result in an empty {@link InputMethodSubtypeSafeList}.
|
||||
+ * @return {@link InputMethodSubtypeSafeList} that stores the given list of
|
||||
+ * {@link InputMethodSubtype}
|
||||
+ */
|
||||
+ @NonNull
|
||||
+ public static InputMethodSubtypeSafeList create(@Nullable List<InputMethodSubtype> list) {
|
||||
+ return new InputMethodSubtypeSafeList(list);
|
||||
+ }
|
||||
+
|
||||
+ public static final Creator<InputMethodSubtypeSafeList> CREATOR = new Creator<>() {
|
||||
+ @Override
|
||||
+ public InputMethodSubtypeSafeList createFromParcel(Parcel in) {
|
||||
+ return new InputMethodSubtypeSafeList(in.readBlob());
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public InputMethodSubtypeSafeList[] newArray(int size) {
|
||||
+ return new InputMethodSubtypeSafeList[size];
|
||||
+ }
|
||||
+ };
|
||||
+}
|
||||
diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl
|
||||
index 29363a533a036..3f6098c270d47 100644
|
||||
--- a/core/java/com/android/internal/view/IInputMethodManager.aidl
|
||||
+++ b/core/java/com/android/internal/view/IInputMethodManager.aidl
|
||||
@@ -32,6 +32,7 @@ import com.android.internal.inputmethod.IRemoteComputerControlInputConnection;
|
||||
import com.android.internal.inputmethod.IRemoteInputConnection;
|
||||
import com.android.internal.inputmethod.InputBindResult;
|
||||
import com.android.internal.inputmethod.InputMethodInfoSafeList;
|
||||
+import com.android.internal.inputmethod.InputMethodSubtypeSafeList;
|
||||
|
||||
/**
|
||||
* Public interface to the global input method manager, used by all client applications.
|
||||
@@ -67,7 +68,7 @@ interface IInputMethodManager {
|
||||
|
||||
@JavaPassthrough(annotation="@android.annotation.RequiresPermission(value = "
|
||||
+ "android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, conditional = true)")
|
||||
- List<InputMethodSubtype> getEnabledInputMethodSubtypeList(in @nullable String imiId,
|
||||
+ InputMethodSubtypeSafeList getEnabledInputMethodSubtypeList(in @nullable String imiId,
|
||||
boolean allowsImplicitlyEnabledSubtypes, int userId);
|
||||
|
||||
@JavaPassthrough(annotation="@android.annotation.RequiresPermission(value = "
|
||||
diff --git a/core/tests/InputMethodCoreTests/src/com/android/internal/inputmethod/AbstractSafeListTest.java b/core/tests/InputMethodCoreTests/src/com/android/internal/inputmethod/AbstractSafeListTest.java
|
||||
new file mode 100644
|
||||
index 0000000000000..0f72f095dbe3c
|
||||
--- /dev/null
|
||||
+++ b/core/tests/InputMethodCoreTests/src/com/android/internal/inputmethod/AbstractSafeListTest.java
|
||||
@@ -0,0 +1,98 @@
|
||||
+/*
|
||||
+ * Copyright 2025 The Android Open Source Project
|
||||
+ *
|
||||
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
||||
+ * you may not use this file except in compliance with the License.
|
||||
+ * You may obtain a copy of the License at
|
||||
+ *
|
||||
+ * http://www.apache.org/licenses/LICENSE-2.0
|
||||
+ *
|
||||
+ * Unless required by applicable law or agreed to in writing, software
|
||||
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
||||
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
+ * See the License for the specific language governing permissions and
|
||||
+ * limitations under the License.
|
||||
+ */
|
||||
+
|
||||
+package com.android.internal.inputmethod;
|
||||
+
|
||||
+import static org.junit.Assert.assertEquals;
|
||||
+import static org.junit.Assert.assertNotNull;
|
||||
+
|
||||
+import android.os.Parcel;
|
||||
+import android.os.Parcelable;
|
||||
+import android.platform.test.annotations.Presubmit;
|
||||
+
|
||||
+import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
+import androidx.test.filters.SmallTest;
|
||||
+
|
||||
+import org.junit.Test;
|
||||
+import org.junit.runner.RunWith;
|
||||
+
|
||||
+import java.util.List;
|
||||
+
|
||||
+@SmallTest
|
||||
+@Presubmit
|
||||
+@RunWith(AndroidJUnit4.class)
|
||||
+public class AbstractSafeListTest {
|
||||
+
|
||||
+ private static class TestParcelable implements Parcelable {
|
||||
+ final int mData;
|
||||
+
|
||||
+ TestParcelable(int data) {
|
||||
+ mData = data;
|
||||
+ }
|
||||
+
|
||||
+ TestParcelable(Parcel parcel) {
|
||||
+ mData = parcel.readInt();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void writeToParcel(Parcel parcel, int flags) {
|
||||
+ parcel.writeInt(mData);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int describeContents() {
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ @SuppressWarnings("EffectivelyPrivate") // Parcelable must have CREATOR.
|
||||
+ public static final Creator<TestParcelable> CREATOR = new Creator<TestParcelable>() {
|
||||
+ @Override
|
||||
+ public TestParcelable createFromParcel(Parcel parcel) {
|
||||
+ return new TestParcelable(parcel);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public TestParcelable[] newArray(int size) {
|
||||
+ return new TestParcelable[size];
|
||||
+ }
|
||||
+ };
|
||||
+ }
|
||||
+
|
||||
+ @Test
|
||||
+ public void testMarshallThenUnmarshall() {
|
||||
+ List<TestParcelable> originalArray = List.of(new TestParcelable(1), new TestParcelable(2));
|
||||
+ byte[] marshalled = AbstractSafeList.marshall(originalArray);
|
||||
+ assertNotNull(marshalled);
|
||||
+ List<TestParcelable> unmarshalled =
|
||||
+ AbstractSafeList.unmarshall(marshalled, TestParcelable.CREATOR);
|
||||
+ assertNotNull(unmarshalled);
|
||||
+ assertEquals(originalArray.size(), unmarshalled.size());
|
||||
+ for (int i = 0; i < originalArray.size(); i++) {
|
||||
+ assertEquals(originalArray.get(i).mData, unmarshalled.get(i).mData);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ @Test
|
||||
+ public void testMarshallEmptyArray() {
|
||||
+ List<TestParcelable> originalArray = List.of();
|
||||
+ byte[] marshalled = AbstractSafeList.marshall(originalArray);
|
||||
+ assertNotNull(marshalled);
|
||||
+ List<TestParcelable> unmarshalled =
|
||||
+ AbstractSafeList.unmarshall(marshalled, TestParcelable.CREATOR);
|
||||
+ assertNotNull(unmarshalled);
|
||||
+ assertEquals(0, unmarshalled.size());
|
||||
+ }
|
||||
+}
|
||||
diff --git a/core/tests/InputMethodCoreTests/src/com/android/internal/inputmethod/InputMethodSubtypeSafeListTest.java b/core/tests/InputMethodCoreTests/src/com/android/internal/inputmethod/InputMethodSubtypeSafeListTest.java
|
||||
new file mode 100644
|
||||
index 0000000000000..089ffb80d7a90
|
||||
--- /dev/null
|
||||
+++ b/core/tests/InputMethodCoreTests/src/com/android/internal/inputmethod/InputMethodSubtypeSafeListTest.java
|
||||
@@ -0,0 +1,128 @@
|
||||
+/*
|
||||
+ * Copyright 2025 The Android Open Source Project
|
||||
+ *
|
||||
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
||||
+ * you may not use this file except in compliance with the License.
|
||||
+ * You may obtain a copy of the License at
|
||||
+ *
|
||||
+ * http://www.apache.org/licenses/LICENSE-2.0
|
||||
+ *
|
||||
+ * Unless required by applicable law or agreed to in writing, software
|
||||
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
||||
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
+ * See the License for the specific language governing permissions and
|
||||
+ * limitations under the License.
|
||||
+ */
|
||||
+
|
||||
+package com.android.internal.inputmethod;
|
||||
+
|
||||
+import static org.junit.Assert.assertEquals;
|
||||
+import static org.junit.Assert.assertNotNull;
|
||||
+import static org.junit.Assert.assertNotSame;
|
||||
+import static org.junit.Assert.assertTrue;
|
||||
+
|
||||
+import android.os.Parcel;
|
||||
+import android.platform.test.annotations.Presubmit;
|
||||
+import android.view.inputmethod.InputMethodSubtype;
|
||||
+
|
||||
+import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
+import androidx.test.filters.SmallTest;
|
||||
+
|
||||
+import org.junit.Test;
|
||||
+import org.junit.runner.RunWith;
|
||||
+
|
||||
+import java.util.ArrayList;
|
||||
+import java.util.Collections;
|
||||
+import java.util.List;
|
||||
+import java.util.function.Function;
|
||||
+
|
||||
+@SmallTest
|
||||
+@Presubmit
|
||||
+@RunWith(AndroidJUnit4.class)
|
||||
+public class InputMethodSubtypeSafeListTest {
|
||||
+
|
||||
+ private static InputMethodSubtype createFakeInputMethodSubtype(String locale, String mode) {
|
||||
+ return new InputMethodSubtype.InputMethodSubtypeBuilder()
|
||||
+ .setSubtypeLocale(locale)
|
||||
+ .setSubtypeMode(mode)
|
||||
+ .build();
|
||||
+ }
|
||||
+
|
||||
+ private static List<InputMethodSubtype> createTestInputMethodSubtypeList() {
|
||||
+ List<InputMethodSubtype> list = new ArrayList<>();
|
||||
+ list.add(createFakeInputMethodSubtype("en_US", "keyboard"));
|
||||
+ list.add(createFakeInputMethodSubtype("ja_JP", "keyboard"));
|
||||
+ list.add(createFakeInputMethodSubtype("en_GB", "voice"));
|
||||
+ return list;
|
||||
+ }
|
||||
+
|
||||
+ private static void assertItemsAfterExtract(
|
||||
+ List<InputMethodSubtype> originals,
|
||||
+ Function<List<InputMethodSubtype>, InputMethodSubtypeSafeList> factory) {
|
||||
+ InputMethodSubtypeSafeList list = factory.apply(originals);
|
||||
+ List<InputMethodSubtype> extracted = InputMethodSubtypeSafeList.extractFrom(list);
|
||||
+ assertEquals(originals.size(), extracted.size());
|
||||
+ for (int i = 0; i < originals.size(); i++) {
|
||||
+ assertNotSame(
|
||||
+ "InputMethodSubtypeSafeList.extractFrom() must clone each instance",
|
||||
+ originals.get(i), extracted.get(i));
|
||||
+ assertEquals(
|
||||
+ "Verify the cloned instances have the equal locale",
|
||||
+ originals.get(i).getLocale(), extracted.get(i).getLocale());
|
||||
+ assertEquals(
|
||||
+ "Verify the cloned instances have the equal mode",
|
||||
+ originals.get(i).getMode(), extracted.get(i).getMode());
|
||||
+ }
|
||||
+
|
||||
+ // Subsequent calls of InputMethodSubtypeSafeList.extractFrom() return an empty list.
|
||||
+ List<InputMethodSubtype> extracted2 = InputMethodSubtypeSafeList.extractFrom(list);
|
||||
+ assertTrue(extracted2.isEmpty());
|
||||
+ }
|
||||
+
|
||||
+ private static InputMethodSubtypeSafeList cloneViaParcel(InputMethodSubtypeSafeList original) {
|
||||
+ Parcel parcel = null;
|
||||
+ try {
|
||||
+ parcel = Parcel.obtain();
|
||||
+ original.writeToParcel(parcel, 0);
|
||||
+ parcel.setDataPosition(0);
|
||||
+ InputMethodSubtypeSafeList newInstance =
|
||||
+ InputMethodSubtypeSafeList.CREATOR.createFromParcel(parcel);
|
||||
+ assertNotNull(newInstance);
|
||||
+ return newInstance;
|
||||
+ } finally {
|
||||
+ if (parcel != null) {
|
||||
+ parcel.recycle();
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ @Test
|
||||
+ public void testCreate() {
|
||||
+ assertNotNull(InputMethodSubtypeSafeList.create(createTestInputMethodSubtypeList()));
|
||||
+ }
|
||||
+
|
||||
+ @Test
|
||||
+ public void testExtract() {
|
||||
+ assertItemsAfterExtract(
|
||||
+ createTestInputMethodSubtypeList(),
|
||||
+ InputMethodSubtypeSafeList::create);
|
||||
+ }
|
||||
+
|
||||
+ @Test
|
||||
+ public void testExtractAfterParceling() {
|
||||
+ assertItemsAfterExtract(
|
||||
+ createTestInputMethodSubtypeList(),
|
||||
+ originals -> cloneViaParcel(InputMethodSubtypeSafeList.create(originals)));
|
||||
+ }
|
||||
+
|
||||
+ @Test
|
||||
+ public void testExtractEmptyList() {
|
||||
+ assertItemsAfterExtract(Collections.emptyList(), InputMethodSubtypeSafeList::create);
|
||||
+ }
|
||||
+
|
||||
+ @Test
|
||||
+ public void testExtractAfterParcelingEmptyList() {
|
||||
+ assertItemsAfterExtract(Collections.emptyList(),
|
||||
+ originals -> cloneViaParcel(InputMethodSubtypeSafeList.create(originals)));
|
||||
+ }
|
||||
+}
|
||||
diff --git a/services/core/java/com/android/server/inputmethod/IInputMethodManagerImpl.java b/services/core/java/com/android/server/inputmethod/IInputMethodManagerImpl.java
|
||||
index baa1d1ca77c0f..419d37fd791a1 100644
|
||||
--- a/services/core/java/com/android/server/inputmethod/IInputMethodManagerImpl.java
|
||||
+++ b/services/core/java/com/android/server/inputmethod/IInputMethodManagerImpl.java
|
||||
@@ -45,6 +45,7 @@
|
||||
import com.android.internal.inputmethod.IRemoteComputerControlInputConnection;
|
||||
import com.android.internal.inputmethod.IRemoteInputConnection;
|
||||
import com.android.internal.inputmethod.InputMethodInfoSafeList;
|
||||
+import com.android.internal.inputmethod.InputMethodSubtypeSafeList;
|
||||
import com.android.internal.inputmethod.StartInputFlags;
|
||||
import com.android.internal.inputmethod.StartInputReason;
|
||||
import com.android.internal.view.IInputMethodManager;
|
||||
@@ -104,7 +105,8 @@ List<InputMethodInfo> getInputMethodListLegacy(@UserIdInt int userId,
|
||||
@NonNull
|
||||
List<InputMethodInfo> getEnabledInputMethodListLegacy(@UserIdInt int userId);
|
||||
|
||||
- List<InputMethodSubtype> getEnabledInputMethodSubtypeList(String imiId,
|
||||
+ @NonNull
|
||||
+ InputMethodSubtypeSafeList getEnabledInputMethodSubtypeList(String imiId,
|
||||
boolean allowsImplicitlyEnabledSubtypes, @UserIdInt int userId);
|
||||
|
||||
InputMethodSubtype getLastInputMethodSubtype(@UserIdInt int userId);
|
||||
@@ -255,8 +257,9 @@ public List<InputMethodInfo> getEnabledInputMethodListLegacy(@UserIdInt int user
|
||||
return mCallback.getEnabledInputMethodListLegacy(userId);
|
||||
}
|
||||
|
||||
+ @NonNull
|
||||
@Override
|
||||
- public List<InputMethodSubtype> getEnabledInputMethodSubtypeList(String imiId,
|
||||
+ public InputMethodSubtypeSafeList getEnabledInputMethodSubtypeList(String imiId,
|
||||
boolean allowsImplicitlyEnabledSubtypes, @UserIdInt int userId) {
|
||||
return mCallback.getEnabledInputMethodSubtypeList(imiId, allowsImplicitlyEnabledSubtypes,
|
||||
userId);
|
||||
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
|
||||
index 355ca4048868a..1ec1c79497ee0 100644
|
||||
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
|
||||
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
|
||||
@@ -172,6 +172,7 @@
|
||||
import com.android.internal.inputmethod.InputMethodInfoSafeList;
|
||||
import com.android.internal.inputmethod.InputMethodNavButtonFlags;
|
||||
import com.android.internal.inputmethod.InputMethodSubtypeHandle;
|
||||
+import com.android.internal.inputmethod.InputMethodSubtypeSafeList;
|
||||
import com.android.internal.inputmethod.SoftInputShowHideReason;
|
||||
import com.android.internal.inputmethod.StartInputFlags;
|
||||
import com.android.internal.inputmethod.StartInputReason;
|
||||
@@ -1585,7 +1586,7 @@ public InputMethodInfoSafeList getInputMethodList(@UserIdInt int userId,
|
||||
Manifest.permission.INTERACT_ACROSS_USERS_FULL, null);
|
||||
}
|
||||
if (!mUserManagerInternal.exists(userId)) {
|
||||
- return InputMethodInfoSafeList.empty();
|
||||
+ return InputMethodInfoSafeList.create(null);
|
||||
}
|
||||
final int callingUid = Binder.getCallingUid();
|
||||
final long ident = Binder.clearCallingIdentity();
|
||||
@@ -1606,7 +1607,7 @@ public InputMethodInfoSafeList getEnabledInputMethodList(@UserIdInt int userId)
|
||||
Manifest.permission.INTERACT_ACROSS_USERS_FULL, null);
|
||||
}
|
||||
if (!mUserManagerInternal.exists(userId)) {
|
||||
- return InputMethodInfoSafeList.empty();
|
||||
+ return InputMethodInfoSafeList.create(null);
|
||||
}
|
||||
final int callingUid = Binder.getCallingUid();
|
||||
final long ident = Binder.clearCallingIdentity();
|
||||
@@ -1730,8 +1731,9 @@ private List<InputMethodInfo> getEnabledInputMethodListInternal(@UserIdInt int u
|
||||
* subtypes
|
||||
* @param userId the user ID to be queried about
|
||||
*/
|
||||
+ @NonNull
|
||||
@Override
|
||||
- public List<InputMethodSubtype> getEnabledInputMethodSubtypeList(String imiId,
|
||||
+ public InputMethodSubtypeSafeList getEnabledInputMethodSubtypeList(String imiId,
|
||||
boolean allowsImplicitlyEnabledSubtypes, @UserIdInt int userId) {
|
||||
if (UserHandle.getCallingUserId() != userId) {
|
||||
mContext.enforceCallingOrSelfPermission(
|
||||
@@ -1741,8 +1743,9 @@ public List<InputMethodSubtype> getEnabledInputMethodSubtypeList(String imiId,
|
||||
final int callingUid = Binder.getCallingUid();
|
||||
final long ident = Binder.clearCallingIdentity();
|
||||
try {
|
||||
- return getEnabledInputMethodSubtypeListInternal(imiId,
|
||||
- allowsImplicitlyEnabledSubtypes, userId, callingUid);
|
||||
+ return InputMethodSubtypeSafeList.create(
|
||||
+ getEnabledInputMethodSubtypeListInternal(imiId,
|
||||
+ allowsImplicitlyEnabledSubtypes, userId, callingUid));
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(ident);
|
||||
}
|
||||
diff --git a/services/core/java/com/android/server/inputmethod/ZeroJankProxy.java b/services/core/java/com/android/server/inputmethod/ZeroJankProxy.java
|
||||
index 910c9a688969b..e8a3da5f0199b 100644
|
||||
--- a/services/core/java/com/android/server/inputmethod/ZeroJankProxy.java
|
||||
+++ b/services/core/java/com/android/server/inputmethod/ZeroJankProxy.java
|
||||
@@ -61,6 +61,7 @@
|
||||
import com.android.internal.inputmethod.IRemoteComputerControlInputConnection;
|
||||
import com.android.internal.inputmethod.IRemoteInputConnection;
|
||||
import com.android.internal.inputmethod.InputMethodInfoSafeList;
|
||||
+import com.android.internal.inputmethod.InputMethodSubtypeSafeList;
|
||||
import com.android.internal.inputmethod.StartInputFlags;
|
||||
import com.android.internal.inputmethod.StartInputReason;
|
||||
import com.android.internal.util.FunctionalUtils.ThrowingRunnable;
|
||||
@@ -149,8 +150,9 @@ public List<InputMethodInfo> getEnabledInputMethodListLegacy(int userId) {
|
||||
return mInner.getEnabledInputMethodListLegacy(userId);
|
||||
}
|
||||
|
||||
+ @NonNull
|
||||
@Override
|
||||
- public List<InputMethodSubtype> getEnabledInputMethodSubtypeList(String imiId,
|
||||
+ public InputMethodSubtypeSafeList getEnabledInputMethodSubtypeList(String imiId,
|
||||
boolean allowsImplicitlyEnabledSubtypes, int userId) {
|
||||
return mInner.getEnabledInputMethodSubtypeList(imiId, allowsImplicitlyEnabledSubtypes,
|
||||
userId);
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
From cee45869c491d4e39877918ee881eb60dec7d6e5 Mon Sep 17 00:00:00 2001
|
||||
From: Iustin Ventaniuc <iustiniv@google.com>
|
||||
Date: Thu, 13 Nov 2025 09:48:16 +0000
|
||||
Subject: [PATCH] Handle loadDescription OutOfMemoryError in DeviceAdminInfo
|
||||
|
||||
loadDescription was potentially vulnerable to an attack which causes a
|
||||
DoS exploit by injecting a maliciously large string into the Receiver's
|
||||
label.
|
||||
|
||||
Bug: 443062265
|
||||
Test: manual
|
||||
Flag: EXEMPT BUGFIX
|
||||
Cherrypick-From: https://googleplex-android-review.googlesource.com/q/commit:06a5b2327caa3aa8843496458e98b9bb070df6e5
|
||||
Cherrypick-From: https://googleplex-android-review.googlesource.com/q/commit:660101e3cdd2f8e8bc627517691dfb885a5c8302
|
||||
Merged-In: Icab26c4b77e73f0fcb9a560e3211482ebe2f37bf
|
||||
Change-Id: Icab26c4b77e73f0fcb9a560e3211482ebe2f37bf
|
||||
---
|
||||
core/java/android/app/admin/DeviceAdminInfo.java | 6 +++++-
|
||||
1 file changed, 5 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/core/java/android/app/admin/DeviceAdminInfo.java b/core/java/android/app/admin/DeviceAdminInfo.java
|
||||
index 7b46db16f80a..7616d805c31c 100644
|
||||
--- a/core/java/android/app/admin/DeviceAdminInfo.java
|
||||
+++ b/core/java/android/app/admin/DeviceAdminInfo.java
|
||||
@@ -473,8 +473,12 @@ public final class DeviceAdminInfo implements Parcelable {
|
||||
*/
|
||||
public CharSequence loadDescription(PackageManager pm) throws NotFoundException {
|
||||
if (mActivityInfo.descriptionRes != 0) {
|
||||
- return pm.getText(mActivityInfo.packageName,
|
||||
+ try {
|
||||
+ return pm.getText(mActivityInfo.packageName,
|
||||
mActivityInfo.descriptionRes, mActivityInfo.applicationInfo);
|
||||
+ } catch (OutOfMemoryError e) {
|
||||
+ throw new NotFoundException();
|
||||
+ }
|
||||
}
|
||||
throw new NotFoundException();
|
||||
}
|
||||
--
|
||||
2.53.0
|
||||
|
||||
|
|
@ -1,146 +0,0 @@
|
|||
From 4264c2f606cdd538fc5825827ede4d1669015f66 Mon Sep 17 00:00:00 2001
|
||||
From: Annie Lin <theannielin@google.com>
|
||||
Date: Wed, 3 Dec 2025 17:18:51 -0800
|
||||
Subject: [PATCH] Prevent launchedFromPackage spoofing via
|
||||
FLAG_ACTIVITY_FORWARD_RESULT.
|
||||
|
||||
Bug: 457742426
|
||||
Test: atest ActivityStarterTests
|
||||
Test: Verified via test app
|
||||
Flag: EXEMPT CVE_FIX
|
||||
Cherrypick-From: https://googleplex-android-review.googlesource.com/q/commit:3bb240273822e41f3c6911c60d15983a600308f7
|
||||
Cherrypick-From: https://googleplex-android-review.googlesource.com/q/commit:8e6622267809c37fa7989e4f07af3834f39f09e2
|
||||
Merged-In: Ic9637c56803b00acc9fca59f8092ed02dd46a4fb
|
||||
Change-Id: Ic9637c56803b00acc9fca59f8092ed02dd46a4fb
|
||||
---
|
||||
.../android/server/wm/ActivityStarter.java | 20 +++--
|
||||
.../server/wm/ActivityStarterTests.java | 82 +++++++++++++++++++
|
||||
2 files changed, 97 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
|
||||
index 21638a31a629b..b0a80079682af 100644
|
||||
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
|
||||
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
|
||||
@@ -1131,14 +1131,24 @@ private int executeRequest(Request request) {
|
||||
// in the flow, and asking to forward its result back to the previous. In this
|
||||
// case the activity is serving as a trampoline between the two, so we also want
|
||||
// to update its launchedFromPackage to be the same as the previous activity.
|
||||
- // Note that this is safe, since we know these two packages come from the same
|
||||
- // uid; the caller could just as well have supplied that same package name itself
|
||||
- // . This specifially deals with the case of an intent picker/chooser being
|
||||
+ // This specifically deals with the case of an intent picker/chooser being
|
||||
// launched in the app flow to redirect to an activity picked by the user, where
|
||||
// we want the final activity to consider it to have been launched by the
|
||||
// previous app activity.
|
||||
- callingPackage = sourceRecord.launchedFromPackage;
|
||||
- callingFeatureId = sourceRecord.launchedFromFeatureId;
|
||||
+ final String launchedFromPackage = sourceRecord.launchedFromPackage;
|
||||
+ if (launchedFromPackage != null) {
|
||||
+ final PackageManagerInternal pmInternal =
|
||||
+ mService.getPackageManagerInternalLocked();
|
||||
+ final int packageUid = pmInternal.getPackageUid(
|
||||
+ launchedFromPackage, 0 /* flags */,
|
||||
+ UserHandle.getUserId(callingUid));
|
||||
+ // Only override callingPackage and callingFeatureId based on package UID check.
|
||||
+ // This is to prevent spoofing. See b/457742426.
|
||||
+ if (UserHandle.isSameApp(packageUid, callingUid)) {
|
||||
+ callingPackage = launchedFromPackage;
|
||||
+ callingFeatureId = sourceRecord.launchedFromFeatureId;
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
|
||||
index e4ad38689daa4..6d59fe5b21bda 100644
|
||||
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
|
||||
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
|
||||
@@ -1997,6 +1997,88 @@ private ActivityRecord createBubbledActivity() {
|
||||
.build();
|
||||
}
|
||||
|
||||
+ /**
|
||||
+ * This test simulates the following scenario:
|
||||
+ * 1. Privileged app (P) starts malicious app's activity (M1).
|
||||
+ * 2. M1 starts M2 (also in malicious app) using startNextMatchingActivity().
|
||||
+ * This causes M2's launchedFromPackage to be P.
|
||||
+ * 3. M2 starts an activity in P (P2) using startActivity() with
|
||||
+ * FLAG_ACTIVITY_FORWARD_RESULT.
|
||||
+ * The test verifies that P2's launchedFromPackage is M, not P.
|
||||
+ * See b/457742426 for details.
|
||||
+ */
|
||||
+ @Test
|
||||
+ public void testLaunchedFromPackage_nextMatchingActivity_forwardResult() {
|
||||
+ final String privilegedPackage = "com.test.privileged";
|
||||
+ final int privilegedUid = 10001;
|
||||
+ final String maliciousPackage = "com.test.malicious";
|
||||
+ final int maliciousUid = 10002;
|
||||
+
|
||||
+ // Setup P1 activity
|
||||
+ final ActivityRecord p1 = new ActivityBuilder(mAtm)
|
||||
+ .setComponent(new ComponentName(privilegedPackage, "P1Activity"))
|
||||
+ .setUid(privilegedUid)
|
||||
+ .setCreateTask(true)
|
||||
+ .build();
|
||||
+
|
||||
+ // Setup M1 activity, launched by P1
|
||||
+ final ActivityRecord m1 = new ActivityBuilder(mAtm)
|
||||
+ .setComponent(new ComponentName(maliciousPackage, "M1Activity"))
|
||||
+ .setUid(maliciousUid)
|
||||
+ .setCreateTask(true)
|
||||
+ .setLaunchedFromPackage(privilegedPackage)
|
||||
+ .setLaunchedFromUid(privilegedUid)
|
||||
+ .build();
|
||||
+ m1.resultTo = p1;
|
||||
+
|
||||
+ // Setup M2 activity, as if launched from M1 via startNextMatchingActivity()
|
||||
+ final ActivityRecord m2 = new ActivityBuilder(mAtm)
|
||||
+ .setComponent(new ComponentName(maliciousPackage, "M2Activity"))
|
||||
+ .setUid(maliciousUid)
|
||||
+ .setCreateTask(true)
|
||||
+ .setLaunchedFromPackage(privilegedPackage) // Spoofed package name
|
||||
+ .setLaunchedFromUid(maliciousUid)
|
||||
+ .build();
|
||||
+ m2.resultTo = p1; // result is forwarded
|
||||
+
|
||||
+ // M2 starts P2
|
||||
+ final ActivityStarter starter = prepareStarter(0);
|
||||
+ doReturn(privilegedUid).when(mMockPackageManager).getPackageUid(
|
||||
+ eq(privilegedPackage), anyLong(), anyInt());
|
||||
+ doReturn(maliciousUid).when(mMockPackageManager).getPackageUid(
|
||||
+ eq(maliciousPackage), anyLong(), anyInt());
|
||||
+ starter.setCallingPackage(maliciousPackage);
|
||||
+ starter.setCallingUid(maliciousUid);
|
||||
+
|
||||
+ final Intent p2Intent = new Intent();
|
||||
+ p2Intent.setComponent(new ComponentName(privilegedPackage, "P2Activity"));
|
||||
+ p2Intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
|
||||
+
|
||||
+ final ActivityInfo p2ActivityInfo = new ActivityInfo();
|
||||
+ p2ActivityInfo.applicationInfo = new ApplicationInfo();
|
||||
+ p2ActivityInfo.applicationInfo.packageName = privilegedPackage;
|
||||
+ p2ActivityInfo.applicationInfo.uid = privilegedUid;
|
||||
+ p2ActivityInfo.name = "P2Activity";
|
||||
+
|
||||
+ final ActivityRecord[] outActivity = new ActivityRecord[1];
|
||||
+
|
||||
+ // The request simulates M2 starting P2
|
||||
+ starter.setIntent(p2Intent)
|
||||
+ .setActivityInfo(p2ActivityInfo)
|
||||
+ .setResultTo(m2.token) // sourceRecord is m2
|
||||
+ .setRequestCode(-1) // for startActivity()
|
||||
+ .setOutActivity(outActivity)
|
||||
+ .execute();
|
||||
+
|
||||
+ final ActivityRecord p2 = outActivity[0];
|
||||
+
|
||||
+ assertNotNull(p2);
|
||||
+ assertEquals("launchedFromPackage should be the immediate caller",
|
||||
+ maliciousPackage, p2.launchedFromPackage);
|
||||
+ assertEquals("launchedFromUid should be the immediate caller",
|
||||
+ maliciousUid, p2.launchedFromUid);
|
||||
+ }
|
||||
+
|
||||
private static void startActivityInner(ActivityStarter starter, ActivityRecord target,
|
||||
ActivityRecord source, ActivityOptions options, Task inTask,
|
||||
TaskFragment inTaskFragment) {
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
From 09055276288a68cf35b0f84ba32e28822f74ecf9 Mon Sep 17 00:00:00 2001
|
||||
From: Sanjana Sunil <sanjanasunil@google.com>
|
||||
Date: Wed, 26 Nov 2025 14:40:09 +0000
|
||||
Subject: [PATCH] Explicitly unset INSTALL_FROM_MANAGED_USER_OR_PROFILE flag
|
||||
|
||||
If the flag is not explicitly unset, an app could set this flag, leading
|
||||
to unexpected behaviour if the install is not actually from a managed
|
||||
user or profile.
|
||||
|
||||
Bug: 459461121
|
||||
Test: atest PackageManagerShellCommandInstallTest#testSessionCreationWithManagedUserOrProfileFlag_notFromManagedProfile
|
||||
Flag: EXEMPT BUGFIX
|
||||
Cherrypick-From: https://googleplex-android-review.googlesource.com/q/commit:990428772d4718853382ec4c5feda2b7bd6f923f
|
||||
Merged-In: I21bbbf628e97244d469eb23ce0558dbf560b7618
|
||||
Change-Id: I21bbbf628e97244d469eb23ce0558dbf560b7618
|
||||
---
|
||||
.../java/com/android/server/pm/PackageInstallerService.java | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
|
||||
index 2d0bb258e89f..a0ad5d1aaa30 100644
|
||||
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
|
||||
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
|
||||
@@ -1027,6 +1027,8 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
|
||||
}
|
||||
|
||||
final var dpmi = LocalServices.getService(DevicePolicyManagerInternal.class);
|
||||
+ // Only the system should be able to set this flag - so ensure it is unset when not needed.
|
||||
+ params.installFlags &= ~PackageManager.INSTALL_FROM_MANAGED_USER_OR_PROFILE;
|
||||
if (dpmi != null && dpmi.isUserOrganizationManaged(userId)) {
|
||||
params.installFlags |= PackageManager.INSTALL_FROM_MANAGED_USER_OR_PROFILE;
|
||||
}
|
||||
--
|
||||
2.53.0
|
||||
|
||||
|
|
@ -1,236 +0,0 @@
|
|||
From 3aaff9fb5b1b5428d57297b168efa01072463321 Mon Sep 17 00:00:00 2001
|
||||
From: Julia Reynolds <juliacr@google.com>
|
||||
Date: Wed, 12 Nov 2025 12:09:31 -0500
|
||||
Subject: [PATCH] Be more strict about content types for message array
|
||||
|
||||
Now with fewer class cast exceptions
|
||||
|
||||
Test: ConversationNotification
|
||||
Test: NotificationManagerServiceTest
|
||||
Bug: 433746973
|
||||
Flag: EXEMPT BUGFIX
|
||||
(cherry picked from commit 71d4afae00c7d6d9238f8ec82303e1e13da50fbb)
|
||||
Cherrypick-From: https://googleplex-android-review.googlesource.com/q/commit:f64c1e377842d9a8df814bcbad831bd4ce01583d
|
||||
Merged-In: I3022e010de95f14dcd0d09d123684ee265101e0a
|
||||
Change-Id: I3022e010de95f14dcd0d09d123684ee265101e0a
|
||||
---
|
||||
core/java/android/app/Notification.java | 18 ++--
|
||||
.../NotificationManagerServiceTest.java | 102 +++++++++++++++++-
|
||||
2 files changed, 108 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
|
||||
index 354e594cf7303..85921a77c6b43 100644
|
||||
--- a/core/java/android/app/Notification.java
|
||||
+++ b/core/java/android/app/Notification.java
|
||||
@@ -3236,8 +3236,8 @@ public void visitUris(@NonNull Consumer<Uri> visitor) {
|
||||
person.visitUris(visitor);
|
||||
}
|
||||
|
||||
- final Parcelable[] messages = extras.getParcelableArray(EXTRA_MESSAGES,
|
||||
- Parcelable.class);
|
||||
+ final Bundle[] messages =
|
||||
+ getParcelableArrayFromBundle(extras, EXTRA_MESSAGES, Bundle.class);
|
||||
if (!ArrayUtils.isEmpty(messages)) {
|
||||
for (MessagingStyle.Message message : MessagingStyle.Message
|
||||
.getMessagesFromBundleArray(messages)) {
|
||||
@@ -3245,8 +3245,8 @@ public void visitUris(@NonNull Consumer<Uri> visitor) {
|
||||
}
|
||||
}
|
||||
|
||||
- final Parcelable[] historic = extras.getParcelableArray(EXTRA_HISTORIC_MESSAGES,
|
||||
- Parcelable.class);
|
||||
+ final Parcelable[] historic =
|
||||
+ getParcelableArrayFromBundle(extras, EXTRA_HISTORIC_MESSAGES, Bundle.class);
|
||||
if (!ArrayUtils.isEmpty(historic)) {
|
||||
for (MessagingStyle.Message message : MessagingStyle.Message
|
||||
.getMessagesFromBundleArray(historic)) {
|
||||
@@ -8501,8 +8501,8 @@ public boolean showsChronometer() {
|
||||
*/
|
||||
public boolean hasImage() {
|
||||
if (isStyle(MessagingStyle.class) && extras != null) {
|
||||
- final Parcelable[] messages = extras.getParcelableArray(EXTRA_MESSAGES,
|
||||
- Parcelable.class);
|
||||
+ final Bundle[] messages =
|
||||
+ getParcelableArrayFromBundle(extras, EXTRA_MESSAGES, Bundle.class);
|
||||
if (!ArrayUtils.isEmpty(messages)) {
|
||||
for (MessagingStyle.Message m : MessagingStyle.Message
|
||||
.getMessagesFromBundleArray(messages)) {
|
||||
@@ -9794,10 +9794,10 @@ protected void restoreFromExtras(Bundle extras) {
|
||||
mUser = user;
|
||||
}
|
||||
mConversationTitle = extras.getCharSequence(EXTRA_CONVERSATION_TITLE);
|
||||
- Parcelable[] messages = extras.getParcelableArray(EXTRA_MESSAGES, Parcelable.class);
|
||||
+ Bundle[] messages = getParcelableArrayFromBundle(extras, EXTRA_MESSAGES, Bundle.class);
|
||||
mMessages = Message.getMessagesFromBundleArray(messages);
|
||||
- Parcelable[] histMessages = extras.getParcelableArray(EXTRA_HISTORIC_MESSAGES,
|
||||
- Parcelable.class);
|
||||
+ Bundle[] histMessages = getParcelableArrayFromBundle(
|
||||
+ extras, EXTRA_HISTORIC_MESSAGES, Bundle.class);
|
||||
mHistoricMessages = Message.getMessagesFromBundleArray(histMessages);
|
||||
mIsGroupConversation = extras.getBoolean(EXTRA_IS_GROUP_CONVERSATION);
|
||||
mUnreadMessageCount = extras.getInt(EXTRA_CONVERSATION_UNREAD_MESSAGE_COUNT);
|
||||
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
|
||||
index 7dc0921db4104..7be8cba2d23bf 100644
|
||||
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
|
||||
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
|
||||
@@ -30,6 +30,8 @@
|
||||
import static android.app.Flags.FLAG_NM_SUMMARIZATION_UI;
|
||||
import static android.app.Flags.FLAG_UI_RICH_ONGOING;
|
||||
import static android.app.Notification.EXTRA_ALLOW_DURING_SETUP;
|
||||
+import static android.app.Notification.EXTRA_MESSAGES;
|
||||
+import static android.app.Notification.EXTRA_MESSAGING_PERSON;
|
||||
import static android.app.Notification.EXTRA_PICTURE;
|
||||
import static android.app.Notification.EXTRA_PICTURE_ICON;
|
||||
import static android.app.Notification.EXTRA_PREFER_SMALL_ICON;
|
||||
@@ -87,6 +89,7 @@
|
||||
import static android.app.PendingIntent.FLAG_IMMUTABLE;
|
||||
import static android.app.PendingIntent.FLAG_MUTABLE;
|
||||
import static android.app.PendingIntent.FLAG_ONE_SHOT;
|
||||
+import static android.app.PendingIntent.FLAG_UPDATE_CURRENT;
|
||||
import static android.app.StatusBarManager.ACTION_KEYGUARD_PRIVATE_NOTIFICATIONS_CHANGED;
|
||||
import static android.app.StatusBarManager.EXTRA_KM_PRIVATE_NOTIFS_ALLOWED;
|
||||
import static android.app.backup.NotificationLoggingConstants.DATA_TYPE_ZEN_CONFIG;
|
||||
@@ -246,11 +249,13 @@
|
||||
import android.compat.testing.PlatformCompatChangeRule;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ComponentName;
|
||||
+import android.content.ContentProvider;
|
||||
import android.content.ContentUris;
|
||||
import android.content.Context;
|
||||
import android.content.IIntentSender;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
+import android.content.UriPermission;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.IPackageManager;
|
||||
@@ -267,6 +272,7 @@
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Color;
|
||||
+import android.graphics.Rect;
|
||||
import android.graphics.drawable.Icon;
|
||||
import android.media.AudioAttributes;
|
||||
import android.media.AudioManager;
|
||||
@@ -1535,6 +1541,96 @@ private void verifyToastShownForTestPackage(String text, int displayId) {
|
||||
eq(TOAST_DURATION), any(), eq(displayId));
|
||||
}
|
||||
|
||||
+ @Test
|
||||
+ public void testNoUriGrantsForBadMessagesList() throws RemoteException {
|
||||
+ Uri targetUri = Uri.parse("content://com.android.contacts/display_photo/1");
|
||||
+
|
||||
+ // create message person
|
||||
+ Person person = new Person.Builder()
|
||||
+ .setName("Name")
|
||||
+ .setIcon(Icon.createWithContentUri(targetUri))
|
||||
+ .setKey("user_123")
|
||||
+ .setBot(false)
|
||||
+ .build();
|
||||
+
|
||||
+ // create MessagingStyle
|
||||
+ Notification.MessagingStyle messagingStyle = new Notification.MessagingStyle(person)
|
||||
+ .setConversationTitle("Bug discussion")
|
||||
+ .setGroupConversation(true)
|
||||
+ .addMessage("Hi,look my photo", System.currentTimeMillis() - 60000, person)
|
||||
+ .addMessage("Oho, you used my contacts photo",
|
||||
+ System.currentTimeMillis() - 30000, "Friend");
|
||||
+
|
||||
+ // create Notification
|
||||
+ Notification notification = new Notification.Builder(mContext, TEST_CHANNEL_ID)
|
||||
+ .setSmallIcon(R.drawable.sym_def_app_icon)
|
||||
+ .setContentTitle("")
|
||||
+ .setContentText("")
|
||||
+ .setAutoCancel(true)
|
||||
+ .setStyle(messagingStyle)
|
||||
+ .setCategory(Notification.CATEGORY_MESSAGE)
|
||||
+ .setFlag(Notification.FLAG_GROUP_SUMMARY, true)
|
||||
+ .build();
|
||||
+ notification.contentIntent = createPendingIntent("open");
|
||||
+
|
||||
+ notification.extras.remove(EXTRA_MESSAGING_PERSON);
|
||||
+
|
||||
+ // add BadClipDescription to avoid visitUri check uris in EXTRA_MESSAGES value
|
||||
+ ArrayList<Parcelable> parcelableArray =
|
||||
+ new ArrayList<>(List.of(notification.extras.getParcelableArray(EXTRA_MESSAGES)));
|
||||
+ parcelableArray.add(new MyParceledListSlice());
|
||||
+ notification.extras.putParcelableArray(
|
||||
+ EXTRA_MESSAGES, parcelableArray.toArray(new Parcelable[0]));
|
||||
+ try {
|
||||
+ mBinderService.enqueueNotificationWithTag(mPkg, mPkg,
|
||||
+ "testNoUriGrantsForBadMessagesList",
|
||||
+ 1, notification, mContext.getUserId());
|
||||
+ waitForIdle();
|
||||
+ fail("should have failed to parse messages");
|
||||
+ } catch (java.lang.ArrayStoreException e) {
|
||||
+ verify(mUgmInternal, never()).checkGrantUriPermission(
|
||||
+ anyInt(), any(), eq(ContentProvider.getUriWithoutUserId(targetUri)),
|
||||
+ anyInt(), anyInt());
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private class MyParceledListSlice extends Intent {
|
||||
+ @Override
|
||||
+ public void writeToParcel(Parcel dest, int i) {
|
||||
+ Parcel test = Parcel.obtain();
|
||||
+ test.writeString(this.getClass().getName());
|
||||
+ int strLength = test.dataSize();
|
||||
+ test.recycle();
|
||||
+ dest.setDataPosition(dest.dataPosition() - strLength);
|
||||
+ dest.writeString("android.content.pm.ParceledListSlice");
|
||||
+
|
||||
+ dest.writeInt(1);
|
||||
+ dest.writeString(UriPermission.class.getName());
|
||||
+ dest.writeInt(0); // use binder
|
||||
+ dest.writeStrongBinder(new Binder() {
|
||||
+ private int callingPid = -1;
|
||||
+ @Override
|
||||
+ public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
|
||||
+ throws RemoteException {
|
||||
+ if (code == 1) {
|
||||
+ reply.writeNoException();
|
||||
+ reply.writeInt(1);
|
||||
+ if (getCallingUid() == 1000 && callingPid == -1) {
|
||||
+ reply.writeParcelable(new Rect(), 0);
|
||||
+ callingPid = getCallingPid();
|
||||
+ } else {
|
||||
+ reply.writeInt(-1);
|
||||
+ reply.writeInt(-1);
|
||||
+ reply.writeLong(0);
|
||||
+ }
|
||||
+ return true;
|
||||
+ }
|
||||
+ return super.onTransact(code, data, reply, flags);
|
||||
+ }
|
||||
+ });
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
@Test
|
||||
public void testDefaultAssistant_overrideDefault() {
|
||||
final int userId = mContext.getUserId();
|
||||
@@ -8589,7 +8685,7 @@ public void testVisitUris() throws Exception {
|
||||
Bundle extras = new Bundle();
|
||||
extras.putParcelable(Notification.EXTRA_AUDIO_CONTENTS_URI, audioContents);
|
||||
extras.putString(Notification.EXTRA_BACKGROUND_IMAGE_URI, backgroundImage.toString());
|
||||
- extras.putParcelable(Notification.EXTRA_MESSAGING_PERSON, person1);
|
||||
+ extras.putParcelable(EXTRA_MESSAGING_PERSON, person1);
|
||||
extras.putParcelableArrayList(Notification.EXTRA_PEOPLE_LIST,
|
||||
new ArrayList<>(Arrays.asList(person2, person3)));
|
||||
extras.putParcelableArray(Notification.EXTRA_REMOTE_INPUT_HISTORY_ITEMS,
|
||||
@@ -8727,13 +8823,13 @@ public void testVisitUris_styleExtrasWithoutStyle() {
|
||||
.setSmallIcon(android.R.drawable.sym_def_app_icon);
|
||||
|
||||
Bundle messagingExtras = new Bundle();
|
||||
- messagingExtras.putParcelable(Notification.EXTRA_MESSAGING_PERSON,
|
||||
+ messagingExtras.putParcelable(EXTRA_MESSAGING_PERSON,
|
||||
personWithIcon("content://user"));
|
||||
messagingExtras.putParcelableArray(Notification.EXTRA_HISTORIC_MESSAGES,
|
||||
new Bundle[] { new Notification.MessagingStyle.Message("Heyhey!",
|
||||
System.currentTimeMillis() - 100,
|
||||
personWithIcon("content://historicalMessenger")).toBundle()});
|
||||
- messagingExtras.putParcelableArray(Notification.EXTRA_MESSAGES,
|
||||
+ messagingExtras.putParcelableArray(EXTRA_MESSAGES,
|
||||
new Bundle[] { new Notification.MessagingStyle.Message("Are you there?",
|
||||
System.currentTimeMillis(),
|
||||
personWithIcon("content://messenger")).toBundle()});
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
From 924df83d73d9f938fde025c2e793ca12646207e0 Mon Sep 17 00:00:00 2001
|
||||
From: Evan Chen <evanxinchen@google.com>
|
||||
Date: Tue, 18 Nov 2025 22:34:11 +0000
|
||||
Subject: [PATCH] Remove any revoked associations after reboot
|
||||
|
||||
Test: manually
|
||||
Bug: 442392902
|
||||
Flag: EXEMPT bugfix
|
||||
Cherrypick-From: https://googleplex-android-review.googlesource.com/q/commit:13714bcfaff6ef1c16d0aa3d359b1c8bc1859ac3
|
||||
Merged-In: I94b96d98608d6702e1d3a9581e135280149bf7e1
|
||||
Change-Id: I94b96d98608d6702e1d3a9581e135280149bf7e1
|
||||
---
|
||||
.../server/companion/CompanionDeviceManagerService.java | 6 ++++++
|
||||
1 file changed, 6 insertions(+)
|
||||
|
||||
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
|
||||
index 7ff1ddb7dc79..fdefbc412136 100644
|
||||
--- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
|
||||
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
|
||||
@@ -33,6 +33,7 @@ import static com.android.internal.util.CollectionUtils.any;
|
||||
import static com.android.internal.util.Preconditions.checkState;
|
||||
import static com.android.server.companion.association.DisassociationProcessor.REASON_API;
|
||||
import static com.android.server.companion.association.DisassociationProcessor.REASON_PKG_DATA_CLEARED;
|
||||
+import static com.android.server.companion.association.DisassociationProcessor.REASON_REVOKED;
|
||||
import static com.android.server.companion.utils.PackageUtils.enforceUsesCompanionDeviceFeature;
|
||||
import static com.android.server.companion.utils.PackageUtils.isRestrictedSettingsAllowed;
|
||||
import static com.android.server.companion.utils.PermissionsUtils.enforceCallerCanManageAssociationsForPackage;
|
||||
@@ -197,6 +198,11 @@ public class CompanionDeviceManagerService extends SystemService {
|
||||
// Init association stores
|
||||
mAssociationStore.refreshCache();
|
||||
|
||||
+ // Remove any revoked associations after reboot.
|
||||
+ for (AssociationInfo ai : mAssociationStore.getRevokedAssociations()) {
|
||||
+ mDisassociationProcessor.disassociate(ai.getId(), REASON_REVOKED);
|
||||
+ }
|
||||
+
|
||||
// Init UUID store
|
||||
mObservableUuidStore.getObservableUuidsForUser(getContext().getUserId());
|
||||
|
||||
--
|
||||
2.53.0
|
||||
|
||||
|
|
@ -1,118 +0,0 @@
|
|||
From dc8121842868bd90e04176ed42feab3f7e47956b Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Mat=C3=ADas=20Hern=C3=A1ndez?= <matiashe@google.com>
|
||||
Date: Wed, 20 Aug 2025 15:57:28 +0200
|
||||
Subject: [PATCH] Limit the number of services (NLSes, etc) that can be
|
||||
approved per user
|
||||
|
||||
Trying to activate additional packages/components will be silently rejected.
|
||||
|
||||
Bug: 428701593
|
||||
Test: atest ManagedServicesTest NotificationManagerServiceTest
|
||||
Flag: com.android.server.notification.limit_managed_services_count
|
||||
(cherry picked from commit a132684a093d9e1750100b39d4e4168f2d27d349)
|
||||
Cherrypick-From: https://googleplex-android-review.googlesource.com/q/commit:182548fd95b0f245385e5dc45efd2cbd4cd35b57
|
||||
Merged-In: Iddd8044997c41f97369b768f4da5e49efc43ad06
|
||||
Change-Id: Iddd8044997c41f97369b768f4da5e49efc43ad06
|
||||
---
|
||||
.../com/android/server/notification/ManagedServices.java | 8 +++-----
|
||||
.../server/notification/NotificationManagerService.java | 6 +++---
|
||||
.../android/server/notification/ManagedServicesTest.java | 2 --
|
||||
.../notification/NotificationManagerServiceTest.java | 1 -
|
||||
4 files changed, 6 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java
|
||||
index 54cf810fc0397..1dd298cb67b33 100644
|
||||
--- a/services/core/java/com/android/server/notification/ManagedServices.java
|
||||
+++ b/services/core/java/com/android/server/notification/ManagedServices.java
|
||||
@@ -978,8 +978,7 @@ protected boolean setPackageOrComponentEnabled(String pkgOrComponent, int userId
|
||||
if (approvedItem != null) {
|
||||
int uid = getUidForPackageOrComponent(pkgOrComponent, userId);
|
||||
if (enabled) {
|
||||
- if (!Flags.limitManagedServicesCount()
|
||||
- || approved.size() < MAX_SERVICE_ENTRIES) {
|
||||
+ if (approved.size() < MAX_SERVICE_ENTRIES) {
|
||||
approved.add(approvedItem);
|
||||
if (uid != Process.INVALID_UID) {
|
||||
approvedUids.add(uid);
|
||||
@@ -1006,8 +1005,7 @@ protected boolean setPackageOrComponentEnabled(String pkgOrComponent, int userId
|
||||
mUserSetServices.put(userId, userSetServices);
|
||||
}
|
||||
if (userSet) {
|
||||
- if (!Flags.limitManagedServicesCount()
|
||||
- || userSetServices.size() < MAX_SERVICE_ENTRIES) {
|
||||
+ if (userSetServices.size() < MAX_SERVICE_ENTRIES) {
|
||||
userSetServices.add(pkgOrComponent);
|
||||
}
|
||||
} else {
|
||||
@@ -1016,7 +1014,7 @@ protected boolean setPackageOrComponentEnabled(String pkgOrComponent, int userId
|
||||
}
|
||||
}
|
||||
|
||||
- if (!Flags.limitManagedServicesCount() || changed) {
|
||||
+ if (changed) {
|
||||
rebindServices(false, userId);
|
||||
}
|
||||
|
||||
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
|
||||
index 1b2042fc8532c..11ea74dae665b 100644
|
||||
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
|
||||
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
|
||||
@@ -7006,7 +7006,7 @@ public void setNotificationPolicyAccessGrantedForUser(
|
||||
pkg, userId, mConditionProviders.getRequiredPermission())) {
|
||||
boolean changed = mConditionProviders.setPackageOrComponentEnabled(pkg, userId,
|
||||
/* isPrimary= */ true, granted);
|
||||
- if (Flags.limitManagedServicesCount() && !changed) {
|
||||
+ if (!changed) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -7276,7 +7276,7 @@ public void setNotificationListenerAccessGrantedForUser(ComponentName listener,
|
||||
boolean changed = mListeners.setPackageOrComponentEnabled(
|
||||
listener.flattenToString(), userId, /* isPrimary= */ true, granted,
|
||||
userSet);
|
||||
- if (Flags.limitManagedServicesCount() && !changed) {
|
||||
+ if (!changed) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -13809,7 +13809,7 @@ protected boolean setPackageOrComponentEnabled(String pkgOrComponent, int userId
|
||||
boolean isPrimary, boolean enabled, boolean userSet) {
|
||||
boolean changed = super.setPackageOrComponentEnabled(pkgOrComponent, userId, isPrimary,
|
||||
enabled, userSet);
|
||||
- if (Flags.limitManagedServicesCount() && !changed) {
|
||||
+ if (!changed) {
|
||||
return false;
|
||||
}
|
||||
|
||||
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java
|
||||
index 97f9f9ceb4aff..0de1d377bd09a 100644
|
||||
--- a/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java
|
||||
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java
|
||||
@@ -2586,7 +2586,6 @@ public void isUidAllowed_multipleApprovedUids_returnsTrueForBoth() {
|
||||
}
|
||||
|
||||
@Test
|
||||
- @EnableFlags(Flags.FLAG_LIMIT_MANAGED_SERVICES_COUNT)
|
||||
public void setPackageOrComponentEnabled_tooManyPackages_stopsAdding() {
|
||||
ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles,
|
||||
mIpm, APPROVAL_BY_PACKAGE);
|
||||
@@ -2614,7 +2613,6 @@ public void setPackageOrComponentEnabled_tooManyPackages_stopsAdding() {
|
||||
}
|
||||
|
||||
@Test
|
||||
- @EnableFlags(Flags.FLAG_LIMIT_MANAGED_SERVICES_COUNT)
|
||||
public void setPackageOrComponentEnabled_tooManyChanges_stopsAddingToUserSet() {
|
||||
ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles,
|
||||
mIpm, APPROVAL_BY_PACKAGE);
|
||||
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
|
||||
index 7be8cba2d23bf..f96fd66caca6d 100644
|
||||
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
|
||||
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
|
||||
@@ -6478,7 +6478,6 @@ public void testSetListenerAccessForUser_revokeWithNameTooLong_okay() throws Exc
|
||||
}
|
||||
|
||||
@Test
|
||||
- @EnableFlags(Flags.FLAG_LIMIT_MANAGED_SERVICES_COUNT)
|
||||
public void testSetListenerAccessForUser_tooManyListeners_skipsFollowups() throws Exception {
|
||||
UserHandle user = UserHandle.of(mContext.getUserId() + 10);
|
||||
ComponentName c = ComponentName.unflattenFromString("package/Component");
|
||||
|
|
@ -1,101 +0,0 @@
|
|||
From 51368785bd09cd652ed9851727b16545cb92c4e5 Mon Sep 17 00:00:00 2001
|
||||
From: Song Chun Fan <schfan@google.com>
|
||||
Date: Tue, 11 Nov 2025 00:03:48 +0000
|
||||
Subject: [PATCH] [UidMigration] fix update uninstallation with
|
||||
sharedUserMaxSdkVersion
|
||||
|
||||
When a system app is re-enabled after the update is uninstalled, when
|
||||
the system app has shared uid, the current code doesn't support
|
||||
directly reusing the disabled package setting. Instead, the preloaded
|
||||
version is re-scanned and installed as a new app, which can bring
|
||||
breaking behavior of changed UIDs when the manifest has
|
||||
sharedUserMaxSdkVersion.
|
||||
|
||||
This change fixes the bug where registerExistingAppId fails when it
|
||||
comes to shared uid, therefore directly reuses the disabled package
|
||||
setting, consistent with the behavior for non-shared-uid system apps.
|
||||
|
||||
FLAG: EXEMPT BUGFIX
|
||||
Test: manually with system-app-test.sh
|
||||
BUG: 454062218
|
||||
|
||||
|
||||
|
||||
(cherry picked from commit 6b5ea2f7fbf50313d46e54e0d8f8c18c398e4869)
|
||||
Cherrypick-From: https://googleplex-android-review.googlesource.com/q/commit:740256b41ba113708655f82dc5664291bf79edd0
|
||||
Merged-In: I417cec27697a210416027e862a5e5d207d268b82
|
||||
Change-Id: I417cec27697a210416027e862a5e5d207d268b82
|
||||
---
|
||||
.../core/java/com/android/server/pm/Settings.java | 14 +++++++++-----
|
||||
.../src/com/android/server/pm/MockSystem.kt | 2 +-
|
||||
2 files changed, 10 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
|
||||
index 92257f1ee2dd..ab13d7e766e8 100644
|
||||
--- a/services/core/java/com/android/server/pm/Settings.java
|
||||
+++ b/services/core/java/com/android/server/pm/Settings.java
|
||||
@@ -916,8 +916,8 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile
|
||||
p.getPkgState().setUpdatedSystemApp(false);
|
||||
final AndroidPackageInternal pkg = p.getPkg();
|
||||
PackageSetting ret = addPackageLPw(name, p.getRealName(), p.getPath(), p.getAppId(),
|
||||
- p.getFlags(), p.getPrivateFlags(), mDomainVerificationManager.generateNewId(),
|
||||
- pkg == null ? false : pkg.isSdkLibrary());
|
||||
+ p.getFlags(), p.getPrivateFlags(), mDomainVerificationManager.generateNewId(),
|
||||
+ pkg == null ? false : pkg.isSdkLibrary(), p.hasSharedUser());
|
||||
if (ret != null) {
|
||||
ret.setLegacyNativeLibraryPath(p.getLegacyNativeLibraryPath());
|
||||
ret.setPrimaryCpuAbi(p.getPrimaryCpuAbiLegacy());
|
||||
@@ -937,6 +937,7 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile
|
||||
ret.setRestrictUpdateHash(p.getRestrictUpdateHash());
|
||||
ret.setScannedAsStoppedSystemApp(p.isScannedAsStoppedSystemApp());
|
||||
ret.setInstallSource(p.getInstallSource());
|
||||
+ ret.setSharedUserAppId(p.getSharedUserAppId());
|
||||
}
|
||||
mDisabledSysPackages.remove(name);
|
||||
return ret;
|
||||
@@ -958,7 +959,8 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile
|
||||
}
|
||||
|
||||
PackageSetting addPackageLPw(String name, String realName, File codePath, int uid,
|
||||
- int pkgFlags, int pkgPrivateFlags, @NonNull UUID domainSetId, boolean isSdkLibrary) {
|
||||
+ int pkgFlags, int pkgPrivateFlags, @NonNull UUID domainSetId, boolean isSdkLibrary,
|
||||
+ boolean hasSharedUser) {
|
||||
PackageSetting p = mPackages.get(name);
|
||||
if (p != null) {
|
||||
if (p.getAppId() == uid) {
|
||||
@@ -971,7 +973,8 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile
|
||||
p = new PackageSetting(name, realName, codePath, pkgFlags, pkgPrivateFlags, domainSetId)
|
||||
.setAppId(uid);
|
||||
if ((uid == Process.INVALID_UID && isSdkLibrary && Flags.disallowSdkLibsToBeApps())
|
||||
- || mAppIds.registerExistingAppId(uid, p, name)) {
|
||||
+ || mAppIds.registerExistingAppId(uid, p, name)
|
||||
+ || hasSharedUser) {
|
||||
mPackages.put(name, p);
|
||||
return p;
|
||||
}
|
||||
@@ -4266,7 +4269,8 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile
|
||||
} else if (appId > 0 || (appId == Process.INVALID_UID && isSdkLibrary
|
||||
&& Flags.disallowSdkLibsToBeApps())) {
|
||||
packageSetting = addPackageLPw(name.intern(), realName, new File(codePathStr),
|
||||
- appId, pkgFlags, pkgPrivateFlags, domainSetId, isSdkLibrary);
|
||||
+ appId, pkgFlags, pkgPrivateFlags, domainSetId, isSdkLibrary,
|
||||
+ /* hasSharedUser= */ false);
|
||||
if (PackageManagerService.DEBUG_SETTINGS)
|
||||
Log.i(PackageManagerService.TAG, "Reading package " + name + ": appId="
|
||||
+ appId + " pkg=" + packageSetting);
|
||||
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt b/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt
|
||||
index 1b2ab2702d49..9a73ba3c155e 100644
|
||||
--- a/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt
|
||||
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt
|
||||
@@ -168,7 +168,7 @@ class MockSystem(withSession: (StaticMockitoSessionBuilder) -> Unit = {}) {
|
||||
null
|
||||
}
|
||||
whenever(mocks.settings.addPackageLPw(nullable(), nullable(), nullable(), nullable(),
|
||||
- nullable(), nullable(), nullable(), nullable())) {
|
||||
+ nullable(), nullable(), nullable(), nullable(), nullable())) {
|
||||
val name: String = getArgument(0)
|
||||
val pendingAdd = mPendingPackageAdds.firstOrNull { it.first == name }
|
||||
?: return@whenever null
|
||||
--
|
||||
2.53.0
|
||||
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
From c81cf361489e3a3cd764c0a0c85c84958e25d63c Mon Sep 17 00:00:00 2001
|
||||
From: Alec Mouri <alecmouri@google.com>
|
||||
Date: Wed, 5 Nov 2025 21:29:10 +0000
|
||||
Subject: [PATCH] Clip to layer bounds when drawing blur regions
|
||||
|
||||
Otherwise blurs can "escape" layer bounds. This would make 1-2
|
||||
pixel-large layers fill the entire screen if the blur region is
|
||||
appropriately crafted, which is not great.
|
||||
|
||||
Bug: 455563813
|
||||
Flag: EXEMPT CVE_FIX
|
||||
Test: PoC app
|
||||
Cherrypick-From: https://googleplex-android-review.googlesource.com/q/commit:123f8fec995a3103acbc3a1191b9cef71523e013
|
||||
Cherrypick-From: https://googleplex-android-review.googlesource.com/q/commit:f3fecb02978030ae4066235cbe638250996b6a9a
|
||||
Merged-In: If59833f2d5060f5f81395d602e2dcb369a10fdbb
|
||||
Change-Id: If59833f2d5060f5f81395d602e2dcb369a10fdbb
|
||||
---
|
||||
libs/renderengine/skia/SkiaRenderEngine.cpp | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/libs/renderengine/skia/SkiaRenderEngine.cpp b/libs/renderengine/skia/SkiaRenderEngine.cpp
|
||||
index 5b6edb4e30..46c58b0c27 100644
|
||||
--- a/libs/renderengine/skia/SkiaRenderEngine.cpp
|
||||
+++ b/libs/renderengine/skia/SkiaRenderEngine.cpp
|
||||
@@ -907,6 +907,10 @@ void SkiaRenderEngine::drawLayersInternal(
|
||||
SkAutoCanvasRestore acr(canvas, true);
|
||||
if (!roundRectClip.isEmpty()) {
|
||||
canvas->clipRRect(roundRectClip, true);
|
||||
+ } else {
|
||||
+ // We need to clip bounds here since otherwise a client sending a bigger blur region
|
||||
+ // enables the blur to "escape" the layer bounds which is very bad for security
|
||||
+ canvas->clipRRect(bounds, true);
|
||||
}
|
||||
|
||||
// TODO(b/182216890): Filter out empty layers earlier
|
||||
--
|
||||
2.53.0
|
||||
|
||||
|
|
@ -1,82 +0,0 @@
|
|||
From c6da9eeb710c6690d189cb2d1b80b44755860b55 Mon Sep 17 00:00:00 2001
|
||||
From: Kyle Hsiao <kylehsiao@google.com>
|
||||
Date: Wed, 1 Oct 2025 11:57:54 +0000
|
||||
Subject: [PATCH] [NFC] Fix use-after-free in eventCallback
|
||||
|
||||
Transform access to the static shared pointer 'Nfc::mCallback' to be thread-safe to prevent a use-after-free crash.
|
||||
|
||||
The use-after-free occurred when an asynchronous thread (eventCallback) attempted to call a method on 'mCallback' immediately after the main thread Nfc::open had destroyed the underlying object. The simple null check was insufficient due to the race condition.
|
||||
|
||||
This fix implements the correct shared pointer synchronization pattern:
|
||||
1. Protects the read/write of 'mCallback' using 'mCallbackLock'.
|
||||
2. Creates a local 'std::shared_ptr<INfcClientCallback> localCallback' inside the critical section. This local copy holds a temporary strong reference, guaranteeing the object's lifetime for the duration of the subsequent sendEvent() call.
|
||||
|
||||
Bug: 392699284
|
||||
Test: nfc_service_fuzzer
|
||||
Test: atest NfcNciUnitTests
|
||||
Test: atest CtsNfcTestCases
|
||||
Test: atest VtsAidlHalNfcTargetTest
|
||||
Test: atest NfcTestCases
|
||||
Test: atest NfcServiceTest
|
||||
(cherry picked from commit fc619c3348188ff0020cdeb7d4c4728a0246fe1a)
|
||||
Cherrypick-From: https://googleplex-android-review.googlesource.com/q/commit:33b3c128e0f480f6e421761b85c5f00289b62449
|
||||
Merged-In: I8e9e83be7f939bbfc183cb3879808ceacf931450
|
||||
Change-Id: I8e9e83be7f939bbfc183cb3879808ceacf931450
|
||||
---
|
||||
aidl/Nfc.h | 18 ++++++++++++++----
|
||||
1 file changed, 14 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/aidl/Nfc.h b/aidl/Nfc.h
|
||||
index 707bd65..fd23e24 100644
|
||||
--- a/aidl/Nfc.h
|
||||
+++ b/aidl/Nfc.h
|
||||
@@ -32,6 +32,8 @@ using ::aidl::android::hardware::nfc::NfcConfig;
|
||||
using ::aidl::android::hardware::nfc::NfcEvent;
|
||||
using ::aidl::android::hardware::nfc::NfcStatus;
|
||||
|
||||
+static pthread_mutex_t sCallbackLock = PTHREAD_MUTEX_INITIALIZER;
|
||||
+
|
||||
// Default implementation that reports no support NFC.
|
||||
struct Nfc : public BnNfc {
|
||||
public:
|
||||
@@ -52,7 +54,11 @@ struct Nfc : public BnNfc {
|
||||
binder_status_t dump(int fd, const char** args, uint32_t numArgs) override;
|
||||
|
||||
static void eventCallback(uint8_t event, uint8_t status) {
|
||||
- if (mCallback != nullptr) {
|
||||
+ std::shared_ptr<INfcClientCallback> localCallback;
|
||||
+ pthread_mutex_lock(&sCallbackLock);
|
||||
+ localCallback = mCallback;
|
||||
+ pthread_mutex_unlock(&sCallbackLock);
|
||||
+ if (localCallback != nullptr) {
|
||||
NfcEvent mEvent;
|
||||
NfcStatus mStatus;
|
||||
switch (event) {
|
||||
@@ -96,7 +102,7 @@ struct Nfc : public BnNfc {
|
||||
default:
|
||||
mStatus = NfcStatus::FAILED;
|
||||
}
|
||||
- auto ret = mCallback->sendEvent(mEvent, mStatus);
|
||||
+ auto ret = localCallback->sendEvent(mEvent, mStatus);
|
||||
if (!ret.isOk()) {
|
||||
LOG(ERROR) << "Failed to send event!";
|
||||
}
|
||||
@@ -104,9 +110,13 @@ struct Nfc : public BnNfc {
|
||||
}
|
||||
|
||||
static void dataCallback(uint16_t data_len, uint8_t* p_data) {
|
||||
+ std::shared_ptr<INfcClientCallback> localCallback;
|
||||
+ pthread_mutex_lock(&sCallbackLock);
|
||||
+ localCallback = mCallback;
|
||||
+ pthread_mutex_unlock(&sCallbackLock);
|
||||
std::vector<uint8_t> data(p_data, p_data + data_len);
|
||||
- if (mCallback != nullptr) {
|
||||
- auto ret = mCallback->sendData(data);
|
||||
+ if (localCallback != nullptr) {
|
||||
+ auto ret = localCallback->sendData(data);
|
||||
if (!ret.isOk()) {
|
||||
LOG(ERROR) << "Failed to send data!";
|
||||
}
|
||||
--
|
||||
2.53.0
|
||||
|
||||
|
|
@ -1,71 +0,0 @@
|
|||
From 48af8a13dd12ecbd0569c328a56d1a7b61a59ca3 Mon Sep 17 00:00:00 2001
|
||||
From: Mill Chen <millchen@google.com>
|
||||
Date: Fri, 26 Sep 2025 09:02:26 +0000
|
||||
Subject: [PATCH] Check permission of the calling package in multi-pane devices
|
||||
|
||||
Bug: 430047417
|
||||
Test: manual test
|
||||
Flag: EXEMPT BUGFIX
|
||||
(cherry picked from commit bd4d57ade07792f2a9160acbe480603b30e79917)
|
||||
Cherrypick-From: https://googleplex-android-review.googlesource.com/q/commit:2860bd01810adb2d0f00fba8f327cdae3f20ab9d
|
||||
Merged-In: I91dafa77d07970fdf2628b4d9e89ca1c4b74194c
|
||||
Change-Id: I91dafa77d07970fdf2628b4d9e89ca1c4b74194c
|
||||
---
|
||||
AndroidManifest.xml | 2 +-
|
||||
.../settings/applications/AppInfoBase.java | 20 +++++++++++++++++++
|
||||
2 files changed, 21 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
|
||||
index ed19890456f..e2d249add13 100644
|
||||
--- a/AndroidManifest.xml
|
||||
+++ b/AndroidManifest.xml
|
||||
@@ -2488,7 +2488,7 @@
|
||||
android:name="Settings$AppUsageAccessSettingsActivity"
|
||||
android:exported="true"
|
||||
android:label="@string/usage_access_title">
|
||||
- <intent-filter>
|
||||
+ <intent-filter android:priority="1">
|
||||
<action android:name="android.settings.USAGE_ACCESS_SETTINGS"/>
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
<data android:scheme="package"/>
|
||||
diff --git a/src/com/android/settings/applications/AppInfoBase.java b/src/com/android/settings/applications/AppInfoBase.java
|
||||
index 02237b886d9..14e54eb5b03 100644
|
||||
--- a/src/com/android/settings/applications/AppInfoBase.java
|
||||
+++ b/src/com/android/settings/applications/AppInfoBase.java
|
||||
@@ -49,6 +49,7 @@ import androidx.fragment.app.Fragment;
|
||||
|
||||
import com.android.settings.SettingsActivity;
|
||||
import com.android.settings.SettingsPreferenceFragment;
|
||||
+import com.android.settings.activityembedding.ActivityEmbeddingUtils;
|
||||
import com.android.settings.applications.manageapplications.ManageApplications;
|
||||
import com.android.settings.core.SubSettingLauncher;
|
||||
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
|
||||
@@ -178,6 +179,25 @@ public abstract class AppInfoBase extends SettingsPreferenceFragment
|
||||
if (!(activity instanceof SettingsActivity)) {
|
||||
return false;
|
||||
}
|
||||
+ // Check the permission of the calling package if the device supports multi-pane.
|
||||
+ if (ActivityEmbeddingUtils.isEmbeddingActivityEnabled(activity)) {
|
||||
+ final String callingPackageName =
|
||||
+ ((SettingsActivity) activity).getInitialCallingPackage();
|
||||
+
|
||||
+ if (TextUtils.isEmpty(callingPackageName)) {
|
||||
+ Log.w(TAG, "Not able to get calling package name for permission check");
|
||||
+ return false;
|
||||
+ }
|
||||
+ if (mPm.checkPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL,
|
||||
+ callingPackageName)
|
||||
+ != PackageManager.PERMISSION_GRANTED) {
|
||||
+ Log.w(TAG, "Package " + callingPackageName + " does not have required permission "
|
||||
+ + Manifest.permission.INTERACT_ACROSS_USERS_FULL);
|
||||
+ return false;
|
||||
+ }
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
try {
|
||||
int callerUid = ActivityManager.getService().getLaunchedFromUid(
|
||||
activity.getActivityToken());
|
||||
--
|
||||
2.53.0
|
||||
|
||||
|
|
@ -1,597 +0,0 @@
|
|||
From c56a925678e3d0030a5a8b0417451a684374abfa Mon Sep 17 00:00:00 2001
|
||||
From: Shawn Lin <shawnlin@google.com>
|
||||
Date: Tue, 14 Oct 2025 08:08:58 +0000
|
||||
Subject: [PATCH] Fixed "Unlock your phone" unexpectedlly turned ON after OTA
|
||||
|
||||
If the new settings key is not set, we should use the values of the old
|
||||
keys as default value.
|
||||
|
||||
Bug: 444673089
|
||||
Test: atest FaceSettingsAppsPreferenceControllerTest
|
||||
FaceSettingsKeyguardUnlockPreferenceControllerTest
|
||||
FingerprintSettingsAppsPreferenceControllerTest
|
||||
FingerprintSettingsKeyguardUnlockPreferenceControllerTest
|
||||
Flag: EXEMPT BUGFIX
|
||||
(cherry picked from commit 05f0884146a093e6311d7a30232d6850a28368ef)
|
||||
Cherrypick-From: https://googleplex-android-review.googlesource.com/q/commit:feb931006ee2d56c146156d5bb1491117841ccf3
|
||||
Merged-In: I345defc78500c244e29e8595f5fbc705b95f4ba6
|
||||
Change-Id: I345defc78500c244e29e8595f5fbc705b95f4ba6
|
||||
---
|
||||
.../FaceSettingsAppsPreferenceController.java | 17 ++-
|
||||
...ngsKeyguardUnlockPreferenceController.java | 13 ++
|
||||
...printSettingsAppsPreferenceController.java | 17 ++-
|
||||
...ngsKeyguardUnlockPreferenceController.java | 13 ++
|
||||
...eSettingsAppsPreferenceControllerTest.java | 116 ++++++++++++++++++
|
||||
...eyguardUnlockPreferenceControllerTest.java | 90 ++++++++++++++
|
||||
...tSettingsAppsPreferenceControllerTest.java | 76 ++++++++++++
|
||||
...eyguardUnlockPreferenceControllerTest.java | 90 ++++++++++++++
|
||||
8 files changed, 428 insertions(+), 4 deletions(-)
|
||||
create mode 100644 tests/robotests/src/com/android/settings/biometrics/face/FaceSettingsAppsPreferenceControllerTest.java
|
||||
create mode 100644 tests/robotests/src/com/android/settings/biometrics/face/FaceSettingsKeyguardUnlockPreferenceControllerTest.java
|
||||
create mode 100644 tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsAppsPreferenceControllerTest.java
|
||||
create mode 100644 tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsKeyguardUnlockPreferenceControllerTest.java
|
||||
|
||||
diff --git a/src/com/android/settings/biometrics/face/FaceSettingsAppsPreferenceController.java b/src/com/android/settings/biometrics/face/FaceSettingsAppsPreferenceController.java
|
||||
index 24b0127d2689..c46b0f02cdc4 100644
|
||||
--- a/src/com/android/settings/biometrics/face/FaceSettingsAppsPreferenceController.java
|
||||
+++ b/src/com/android/settings/biometrics/face/FaceSettingsAppsPreferenceController.java
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.android.settings.biometrics.face;
|
||||
|
||||
+import static android.provider.Settings.Secure.BIOMETRIC_APP_ENABLED;
|
||||
import static android.provider.Settings.Secure.FACE_APP_ENABLED;
|
||||
|
||||
import android.app.settings.SettingsEnums;
|
||||
@@ -33,6 +34,7 @@
|
||||
|
||||
public class FaceSettingsAppsPreferenceController extends
|
||||
FaceSettingsPreferenceController {
|
||||
+ private static final int NOT_SET = -1;
|
||||
private static final int ON = 1;
|
||||
private static final int OFF = 0;
|
||||
private static final int DEFAULT = ON;
|
||||
@@ -53,12 +55,23 @@ public FaceSettingsAppsPreferenceController(@NonNull Context context, @NonNull S
|
||||
}
|
||||
}
|
||||
}
|
||||
+
|
||||
+ // For OTA case: if FACE_APP_ENABLED is not set and BIOMETRIC_APP_ENABLED is set, set the
|
||||
+ // default value of the former to that of the latter.
|
||||
+ final int defValue = Settings.Secure.getIntForUser(mContext.getContentResolver(),
|
||||
+ FACE_APP_ENABLED, NOT_SET, getUserId());
|
||||
+ final int oldDefValue = Settings.Secure.getIntForUser(mContext.getContentResolver(),
|
||||
+ BIOMETRIC_APP_ENABLED, NOT_SET, getUserId());
|
||||
+ if (defValue == NOT_SET && oldDefValue != NOT_SET) {
|
||||
+ Settings.Secure.putIntForUser(mContext.getContentResolver(),
|
||||
+ FACE_APP_ENABLED, oldDefValue, getUserId());
|
||||
+ }
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChecked() {
|
||||
- return Settings.Secure.getIntForUser(mContext.getContentResolver(), FACE_APP_ENABLED,
|
||||
- DEFAULT, getUserId()) == ON;
|
||||
+ return Settings.Secure.getIntForUser(mContext.getContentResolver(),
|
||||
+ FACE_APP_ENABLED, DEFAULT, getUserId()) == ON;
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/src/com/android/settings/biometrics/face/FaceSettingsKeyguardUnlockPreferenceController.java b/src/com/android/settings/biometrics/face/FaceSettingsKeyguardUnlockPreferenceController.java
|
||||
index 64b036b034cb..d8ad4f827ac5 100644
|
||||
--- a/src/com/android/settings/biometrics/face/FaceSettingsKeyguardUnlockPreferenceController.java
|
||||
+++ b/src/com/android/settings/biometrics/face/FaceSettingsKeyguardUnlockPreferenceController.java
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.android.settings.biometrics.face;
|
||||
|
||||
+import static android.provider.Settings.Secure.BIOMETRIC_KEYGUARD_ENABLED;
|
||||
import static android.provider.Settings.Secure.FACE_KEYGUARD_ENABLED;
|
||||
|
||||
import android.app.settings.SettingsEnums;
|
||||
@@ -32,6 +33,7 @@
|
||||
|
||||
public class FaceSettingsKeyguardUnlockPreferenceController extends
|
||||
FaceSettingsPreferenceController {
|
||||
+ private static final int NOT_SET = -1;
|
||||
private static final int ON = 1;
|
||||
private static final int OFF = 0;
|
||||
private static final int DEFAULT = ON;
|
||||
@@ -44,6 +46,17 @@ public FaceSettingsKeyguardUnlockPreferenceController(
|
||||
super(context, key);
|
||||
mFaceManager = Utils.getFaceManagerOrNull(context);
|
||||
mUserManager = context.getSystemService(UserManager.class);
|
||||
+
|
||||
+ // For OTA case: if FACE_KEYGUARD_ENABLED is not set and BIOMETRIC_KEYGUARD_ENABLED is set,
|
||||
+ // set the default value of the former to that of the latter.
|
||||
+ final int defValue = Settings.Secure.getIntForUser(mContext.getContentResolver(),
|
||||
+ FACE_KEYGUARD_ENABLED, NOT_SET, getUserId());
|
||||
+ final int oldDefValue = Settings.Secure.getIntForUser(mContext.getContentResolver(),
|
||||
+ BIOMETRIC_KEYGUARD_ENABLED, NOT_SET, getUserId());
|
||||
+ if (defValue == NOT_SET && oldDefValue != NOT_SET) {
|
||||
+ Settings.Secure.putIntForUser(mContext.getContentResolver(),
|
||||
+ FACE_KEYGUARD_ENABLED, oldDefValue, getUserId());
|
||||
+ }
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsAppsPreferenceController.java b/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsAppsPreferenceController.java
|
||||
index 63fc3dcef230..574d406e3821 100644
|
||||
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsAppsPreferenceController.java
|
||||
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsAppsPreferenceController.java
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.android.settings.biometrics.fingerprint;
|
||||
|
||||
+import static android.provider.Settings.Secure.BIOMETRIC_APP_ENABLED;
|
||||
import static android.provider.Settings.Secure.FINGERPRINT_APP_ENABLED;
|
||||
|
||||
import android.app.settings.SettingsEnums;
|
||||
@@ -31,6 +32,7 @@
|
||||
|
||||
public class FingerprintSettingsAppsPreferenceController
|
||||
extends FingerprintSettingsPreferenceController {
|
||||
+ private static final int NOT_SET = -1;
|
||||
private static final int ON = 1;
|
||||
private static final int OFF = 0;
|
||||
private static final int DEFAULT = ON;
|
||||
@@ -41,12 +43,23 @@ public FingerprintSettingsAppsPreferenceController(
|
||||
@NonNull Context context, @NonNull String key) {
|
||||
super(context, key);
|
||||
mFingerprintManager = Utils.getFingerprintManagerOrNull(context);
|
||||
+
|
||||
+ // For OTA case: if FINGERPRINT_APP_ENABLED is not set and BIOMETRIC_APP_ENABLED is set,
|
||||
+ // set the default value of the former to that of the latter.
|
||||
+ final int defValue = Settings.Secure.getIntForUser(mContext.getContentResolver(),
|
||||
+ FINGERPRINT_APP_ENABLED, NOT_SET, getUserId());
|
||||
+ final int oldDefValue = Settings.Secure.getIntForUser(mContext.getContentResolver(),
|
||||
+ BIOMETRIC_APP_ENABLED, NOT_SET, getUserId());
|
||||
+ if (defValue == NOT_SET && oldDefValue != NOT_SET) {
|
||||
+ Settings.Secure.putIntForUser(mContext.getContentResolver(),
|
||||
+ FINGERPRINT_APP_ENABLED, oldDefValue, getUserId());
|
||||
+ }
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChecked() {
|
||||
- return Settings.Secure.getIntForUser(mContext.getContentResolver(), FINGERPRINT_APP_ENABLED,
|
||||
- DEFAULT, getUserId()) == ON;
|
||||
+ return Settings.Secure.getIntForUser(mContext.getContentResolver(),
|
||||
+ FINGERPRINT_APP_ENABLED, DEFAULT, getUserId()) == ON;
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsKeyguardUnlockPreferenceController.java b/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsKeyguardUnlockPreferenceController.java
|
||||
index c572f2d85843..88f0a125d0aa 100644
|
||||
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsKeyguardUnlockPreferenceController.java
|
||||
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsKeyguardUnlockPreferenceController.java
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.android.settings.biometrics.fingerprint;
|
||||
|
||||
+import static android.provider.Settings.Secure.BIOMETRIC_KEYGUARD_ENABLED;
|
||||
import static android.provider.Settings.Secure.FINGERPRINT_KEYGUARD_ENABLED;
|
||||
|
||||
import android.app.settings.SettingsEnums;
|
||||
@@ -33,6 +34,7 @@
|
||||
public class FingerprintSettingsKeyguardUnlockPreferenceController
|
||||
extends FingerprintSettingsPreferenceController {
|
||||
|
||||
+ private static final int NOT_SET = -1;
|
||||
private static final int ON = 1;
|
||||
private static final int OFF = 0;
|
||||
private static final int DEFAULT = ON;
|
||||
@@ -45,6 +47,17 @@ public FingerprintSettingsKeyguardUnlockPreferenceController(
|
||||
super(context, key);
|
||||
mFingerprintManager = Utils.getFingerprintManagerOrNull(context);
|
||||
mUserManager = context.getSystemService(UserManager.class);
|
||||
+
|
||||
+ // For OTA case: if FINGERPRINT_KEYGUARD_ENABLED is not set and BIOMETRIC_KEYGUARD_ENABLED
|
||||
+ // is set, set the default value of the former to that of the latter.
|
||||
+ final int defValue = Settings.Secure.getIntForUser(mContext.getContentResolver(),
|
||||
+ FINGERPRINT_KEYGUARD_ENABLED, NOT_SET, getUserId());
|
||||
+ final int oldDefValue = Settings.Secure.getIntForUser(mContext.getContentResolver(),
|
||||
+ BIOMETRIC_KEYGUARD_ENABLED, NOT_SET, getUserId());
|
||||
+ if (defValue == NOT_SET && oldDefValue != NOT_SET) {
|
||||
+ Settings.Secure.putIntForUser(mContext.getContentResolver(),
|
||||
+ FINGERPRINT_KEYGUARD_ENABLED, oldDefValue, getUserId());
|
||||
+ }
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/tests/robotests/src/com/android/settings/biometrics/face/FaceSettingsAppsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/biometrics/face/FaceSettingsAppsPreferenceControllerTest.java
|
||||
new file mode 100644
|
||||
index 000000000000..676031c4951e
|
||||
--- /dev/null
|
||||
+++ b/tests/robotests/src/com/android/settings/biometrics/face/FaceSettingsAppsPreferenceControllerTest.java
|
||||
@@ -0,0 +1,116 @@
|
||||
+/*
|
||||
+ * Copyright (C) 2025 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.settings.biometrics.face;
|
||||
+
|
||||
+import static android.provider.Settings.Secure.BIOMETRIC_APP_ENABLED;
|
||||
+import static android.provider.Settings.Secure.FACE_APP_ENABLED;
|
||||
+
|
||||
+import static com.google.common.truth.Truth.assertThat;
|
||||
+
|
||||
+import static org.mockito.Mockito.when;
|
||||
+
|
||||
+import android.content.Context;
|
||||
+import android.hardware.biometrics.ComponentInfoInternal;
|
||||
+import android.hardware.biometrics.SensorProperties;
|
||||
+import android.hardware.face.FaceManager;
|
||||
+import android.hardware.face.FaceSensorProperties;
|
||||
+import android.hardware.face.FaceSensorPropertiesInternal;
|
||||
+import android.provider.Settings;
|
||||
+
|
||||
+import androidx.test.core.app.ApplicationProvider;
|
||||
+
|
||||
+import com.android.settings.testutils.FakeFeatureFactory;
|
||||
+import com.android.settings.testutils.shadow.ShadowSecureSettings;
|
||||
+import com.android.settings.testutils.shadow.ShadowUtils;
|
||||
+
|
||||
+import org.junit.After;
|
||||
+import org.junit.Before;
|
||||
+import org.junit.Rule;
|
||||
+import org.junit.Test;
|
||||
+import org.junit.runner.RunWith;
|
||||
+import org.mockito.Mock;
|
||||
+import org.mockito.Spy;
|
||||
+import org.mockito.junit.MockitoJUnit;
|
||||
+import org.mockito.junit.MockitoRule;
|
||||
+import org.robolectric.RobolectricTestRunner;
|
||||
+import org.robolectric.annotation.Config;
|
||||
+
|
||||
+import java.util.ArrayList;
|
||||
+
|
||||
+@RunWith(RobolectricTestRunner.class)
|
||||
+@Config(shadows = {ShadowSecureSettings.class})
|
||||
+public class FaceSettingsAppsPreferenceControllerTest {
|
||||
+ @Rule
|
||||
+ public final MockitoRule mMockitoRule = MockitoJUnit.rule();
|
||||
+ @Spy
|
||||
+ private Context mContext = ApplicationProvider.getApplicationContext();
|
||||
+ @Mock
|
||||
+ private FaceManager mFaceManager;
|
||||
+ private FaceSettingsAppsPreferenceController mController;
|
||||
+
|
||||
+ private FaceSensorPropertiesInternal mConvenienceSensorProperty =
|
||||
+ new FaceSensorPropertiesInternal(
|
||||
+ 0 /* sensorId */,
|
||||
+ SensorProperties.STRENGTH_CONVENIENCE,
|
||||
+ 1 /* maxEnrollmentsPerUser */,
|
||||
+ new ArrayList<ComponentInfoInternal>(),
|
||||
+ FaceSensorProperties.TYPE_UNKNOWN,
|
||||
+ true /* supportsFaceDetection */,
|
||||
+ true /* supportsSelfIllumination */,
|
||||
+ true /* resetLockoutRequiresChallenge */);
|
||||
+ private FakeFeatureFactory mFeatureFactory;
|
||||
+
|
||||
+ @Before
|
||||
+ public void setUp() {
|
||||
+ when(mContext.getSystemService(Context.FACE_SERVICE)).thenReturn(mFaceManager);
|
||||
+ final ArrayList<FaceSensorPropertiesInternal> list = new ArrayList<>();
|
||||
+ list.add(mConvenienceSensorProperty);
|
||||
+ when(mFaceManager.getSensorPropertiesInternal()).thenReturn(list);
|
||||
+ mFeatureFactory = FakeFeatureFactory.setupForTest();
|
||||
+ }
|
||||
+
|
||||
+ @After
|
||||
+ public void tearDown() {
|
||||
+ ShadowUtils.reset();
|
||||
+ }
|
||||
+
|
||||
+ @Test
|
||||
+ public void isChecked_BiometricAppEnableOff_FaceAppEnabledNotSet_returnFalse() {
|
||||
+ Settings.Secure.putIntForUser(mContext.getContentResolver(),
|
||||
+ BIOMETRIC_APP_ENABLED, 0, mContext.getUserId());
|
||||
+ Settings.Secure.putIntForUser(mContext.getContentResolver(),
|
||||
+ FACE_APP_ENABLED, -1, mContext.getUserId());
|
||||
+
|
||||
+ mController = new FaceSettingsAppsPreferenceController(
|
||||
+ mContext, "biometric_settings_face_app");
|
||||
+
|
||||
+ assertThat(mController.isChecked()).isFalse();
|
||||
+ }
|
||||
+
|
||||
+ @Test
|
||||
+ public void isChecked_BiometricAppEnableOff_FaceAppEnabledOn_returnTrue() {
|
||||
+ Settings.Secure.putIntForUser(mContext.getContentResolver(),
|
||||
+ BIOMETRIC_APP_ENABLED, 0, mContext.getUserId());
|
||||
+ Settings.Secure.putIntForUser(mContext.getContentResolver(),
|
||||
+ FACE_APP_ENABLED, 1, mContext.getUserId());
|
||||
+
|
||||
+ mController = new FaceSettingsAppsPreferenceController(
|
||||
+ mContext, "biometric_settings_face_app");
|
||||
+
|
||||
+ assertThat(mController.isChecked()).isTrue();
|
||||
+ }
|
||||
+}
|
||||
diff --git a/tests/robotests/src/com/android/settings/biometrics/face/FaceSettingsKeyguardUnlockPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/biometrics/face/FaceSettingsKeyguardUnlockPreferenceControllerTest.java
|
||||
new file mode 100644
|
||||
index 000000000000..837f31e3bd6f
|
||||
--- /dev/null
|
||||
+++ b/tests/robotests/src/com/android/settings/biometrics/face/FaceSettingsKeyguardUnlockPreferenceControllerTest.java
|
||||
@@ -0,0 +1,90 @@
|
||||
+/*
|
||||
+ * Copyright (C) 2025 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.settings.biometrics.face;
|
||||
+
|
||||
+import static android.provider.Settings.Secure.BIOMETRIC_KEYGUARD_ENABLED;
|
||||
+import static android.provider.Settings.Secure.FACE_KEYGUARD_ENABLED;
|
||||
+
|
||||
+import static com.google.common.truth.Truth.assertThat;
|
||||
+
|
||||
+import static org.mockito.Mockito.when;
|
||||
+
|
||||
+import android.content.Context;
|
||||
+import android.os.UserManager;
|
||||
+import android.provider.Settings;
|
||||
+
|
||||
+import androidx.test.core.app.ApplicationProvider;
|
||||
+
|
||||
+import com.android.settings.testutils.FakeFeatureFactory;
|
||||
+import com.android.settings.testutils.shadow.ShadowSecureSettings;
|
||||
+
|
||||
+import org.junit.Before;
|
||||
+import org.junit.Rule;
|
||||
+import org.junit.Test;
|
||||
+import org.junit.runner.RunWith;
|
||||
+import org.mockito.Mock;
|
||||
+import org.mockito.Spy;
|
||||
+import org.mockito.junit.MockitoJUnit;
|
||||
+import org.mockito.junit.MockitoRule;
|
||||
+import org.robolectric.RobolectricTestRunner;
|
||||
+import org.robolectric.annotation.Config;
|
||||
+
|
||||
+@RunWith(RobolectricTestRunner.class)
|
||||
+@Config(shadows = {ShadowSecureSettings.class})
|
||||
+public class FaceSettingsKeyguardUnlockPreferenceControllerTest {
|
||||
+ @Rule
|
||||
+ public final MockitoRule mMockitoRule = MockitoJUnit.rule();
|
||||
+ @Spy
|
||||
+ Context mContext = ApplicationProvider.getApplicationContext();
|
||||
+ private FaceSettingsKeyguardUnlockPreferenceController mController;
|
||||
+ private FakeFeatureFactory mFeatureFactory;
|
||||
+ @Mock
|
||||
+ private UserManager mUserManager;
|
||||
+
|
||||
+ @Before
|
||||
+ public void setUp() {
|
||||
+
|
||||
+ mFeatureFactory = FakeFeatureFactory.setupForTest();
|
||||
+ when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager);
|
||||
+ }
|
||||
+
|
||||
+ @Test
|
||||
+ public void isChecked_BiometricKeyguardEnabledOff_FaceKeyguardEnabledNotSet_returnFalse() {
|
||||
+ Settings.Secure.putIntForUser(mContext.getContentResolver(),
|
||||
+ BIOMETRIC_KEYGUARD_ENABLED, 0, mContext.getUserId());
|
||||
+ Settings.Secure.putIntForUser(mContext.getContentResolver(),
|
||||
+ FACE_KEYGUARD_ENABLED, -1, mContext.getUserId());
|
||||
+
|
||||
+ mController = new FaceSettingsKeyguardUnlockPreferenceController(
|
||||
+ mContext, "biometric_settings_face_keyguard");
|
||||
+
|
||||
+ assertThat(mController.isChecked()).isFalse();
|
||||
+ }
|
||||
+
|
||||
+ @Test
|
||||
+ public void isChecked_BiometricKeyguardEnabledOff_FaceKeyguardEnabledOn_returnTrue() {
|
||||
+ Settings.Secure.putIntForUser(mContext.getContentResolver(),
|
||||
+ BIOMETRIC_KEYGUARD_ENABLED, 0, mContext.getUserId());
|
||||
+ Settings.Secure.putIntForUser(mContext.getContentResolver(),
|
||||
+ FACE_KEYGUARD_ENABLED, 1, mContext.getUserId());
|
||||
+
|
||||
+ mController = new FaceSettingsKeyguardUnlockPreferenceController(
|
||||
+ mContext, "biometric_settings_face_keyguard");
|
||||
+
|
||||
+ assertThat(mController.isChecked()).isTrue();
|
||||
+ }
|
||||
+}
|
||||
diff --git a/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsAppsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsAppsPreferenceControllerTest.java
|
||||
new file mode 100644
|
||||
index 000000000000..841cec2f3de6
|
||||
--- /dev/null
|
||||
+++ b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsAppsPreferenceControllerTest.java
|
||||
@@ -0,0 +1,76 @@
|
||||
+/*
|
||||
+ * Copyright (C) 2025 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.settings.biometrics.fingerprint;
|
||||
+
|
||||
+import static android.provider.Settings.Secure.BIOMETRIC_APP_ENABLED;
|
||||
+import static android.provider.Settings.Secure.FINGERPRINT_APP_ENABLED;
|
||||
+
|
||||
+import static com.google.common.truth.Truth.assertThat;
|
||||
+
|
||||
+import android.content.Context;
|
||||
+import android.provider.Settings;
|
||||
+
|
||||
+import androidx.test.core.app.ApplicationProvider;
|
||||
+
|
||||
+import com.android.settings.testutils.FakeFeatureFactory;
|
||||
+import com.android.settings.testutils.shadow.ShadowSecureSettings;
|
||||
+
|
||||
+import org.junit.Before;
|
||||
+import org.junit.Test;
|
||||
+import org.junit.runner.RunWith;
|
||||
+import org.robolectric.RobolectricTestRunner;
|
||||
+import org.robolectric.annotation.Config;
|
||||
+
|
||||
+@RunWith(RobolectricTestRunner.class)
|
||||
+@Config(shadows = {ShadowSecureSettings.class})
|
||||
+public class FingerprintSettingsAppsPreferenceControllerTest {
|
||||
+ private Context mContext;
|
||||
+ private FingerprintSettingsAppsPreferenceController mController;
|
||||
+ private FakeFeatureFactory mFeatureFactory;
|
||||
+
|
||||
+ @Before
|
||||
+ public void setUp() {
|
||||
+ mContext = ApplicationProvider.getApplicationContext();
|
||||
+ mFeatureFactory = FakeFeatureFactory.setupForTest();
|
||||
+ }
|
||||
+
|
||||
+ @Test
|
||||
+ public void isChecked_BiometricAppEnableOff_FingerprintAppEnabledNotSet_returnFalse() {
|
||||
+ Settings.Secure.putIntForUser(mContext.getContentResolver(),
|
||||
+ BIOMETRIC_APP_ENABLED, 0, mContext.getUserId());
|
||||
+ Settings.Secure.putIntForUser(mContext.getContentResolver(),
|
||||
+ FINGERPRINT_APP_ENABLED, -1, mContext.getUserId());
|
||||
+
|
||||
+ mController = new FingerprintSettingsAppsPreferenceController(
|
||||
+ mContext, "biometric_settings_fingerprint_app");
|
||||
+
|
||||
+ assertThat(mController.isChecked()).isFalse();
|
||||
+ }
|
||||
+
|
||||
+ @Test
|
||||
+ public void isChecked_BiometricAppEnableOff_FingerprintAppEnabledOn_returnTrue() {
|
||||
+ Settings.Secure.putIntForUser(mContext.getContentResolver(),
|
||||
+ BIOMETRIC_APP_ENABLED, 0, mContext.getUserId());
|
||||
+ Settings.Secure.putIntForUser(mContext.getContentResolver(),
|
||||
+ FINGERPRINT_APP_ENABLED, 1, mContext.getUserId());
|
||||
+
|
||||
+ mController = new FingerprintSettingsAppsPreferenceController(
|
||||
+ mContext, "biometric_settings_fingerprint_app");
|
||||
+
|
||||
+ assertThat(mController.isChecked()).isTrue();
|
||||
+ }
|
||||
+}
|
||||
diff --git a/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsKeyguardUnlockPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsKeyguardUnlockPreferenceControllerTest.java
|
||||
new file mode 100644
|
||||
index 000000000000..119fda8bbf28
|
||||
--- /dev/null
|
||||
+++ b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsKeyguardUnlockPreferenceControllerTest.java
|
||||
@@ -0,0 +1,90 @@
|
||||
+/*
|
||||
+ * Copyright (C) 2025 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.settings.biometrics.fingerprint;
|
||||
+
|
||||
+import static android.provider.Settings.Secure.BIOMETRIC_KEYGUARD_ENABLED;
|
||||
+import static android.provider.Settings.Secure.FINGERPRINT_KEYGUARD_ENABLED;
|
||||
+
|
||||
+import static com.google.common.truth.Truth.assertThat;
|
||||
+
|
||||
+import static org.mockito.Mockito.when;
|
||||
+
|
||||
+import android.content.Context;
|
||||
+import android.os.UserManager;
|
||||
+import android.provider.Settings;
|
||||
+
|
||||
+import androidx.test.core.app.ApplicationProvider;
|
||||
+
|
||||
+import com.android.settings.testutils.FakeFeatureFactory;
|
||||
+import com.android.settings.testutils.shadow.ShadowSecureSettings;
|
||||
+
|
||||
+import org.junit.Before;
|
||||
+import org.junit.Rule;
|
||||
+import org.junit.Test;
|
||||
+import org.junit.runner.RunWith;
|
||||
+import org.mockito.Mock;
|
||||
+import org.mockito.Spy;
|
||||
+import org.mockito.junit.MockitoJUnit;
|
||||
+import org.mockito.junit.MockitoRule;
|
||||
+import org.robolectric.RobolectricTestRunner;
|
||||
+import org.robolectric.annotation.Config;
|
||||
+
|
||||
+@RunWith(RobolectricTestRunner.class)
|
||||
+@Config(shadows = {ShadowSecureSettings.class})
|
||||
+public class FingerprintSettingsKeyguardUnlockPreferenceControllerTest {
|
||||
+ @Rule
|
||||
+ public final MockitoRule mMockitoRule = MockitoJUnit.rule();
|
||||
+ @Spy
|
||||
+ Context mContext = ApplicationProvider.getApplicationContext();
|
||||
+ private FingerprintSettingsKeyguardUnlockPreferenceController mController;
|
||||
+ private FakeFeatureFactory mFeatureFactory;
|
||||
+ @Mock
|
||||
+ private UserManager mUserManager;
|
||||
+
|
||||
+ @Before
|
||||
+ public void setUp() {
|
||||
+ mFeatureFactory = FakeFeatureFactory.setupForTest();
|
||||
+ when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager);
|
||||
+ }
|
||||
+
|
||||
+ @Test
|
||||
+ public void
|
||||
+ isChecked_BiometricKeyguardEnabledOff_FingerprintKeyguardEnabledNotSet_returnFalse() {
|
||||
+ Settings.Secure.putIntForUser(mContext.getContentResolver(),
|
||||
+ BIOMETRIC_KEYGUARD_ENABLED, 0, mContext.getUserId());
|
||||
+ Settings.Secure.putIntForUser(mContext.getContentResolver(),
|
||||
+ FINGERPRINT_KEYGUARD_ENABLED, -1, mContext.getUserId());
|
||||
+
|
||||
+ mController = new FingerprintSettingsKeyguardUnlockPreferenceController(
|
||||
+ mContext, "biometric_settings_fingerprint_keyguard");
|
||||
+
|
||||
+ assertThat(mController.isChecked()).isFalse();
|
||||
+ }
|
||||
+
|
||||
+ @Test
|
||||
+ public void isChecked_BiometricKeyguardEnabledOff_FingerprintKeyguardEnabledOn_returnTrue() {
|
||||
+ Settings.Secure.putIntForUser(mContext.getContentResolver(),
|
||||
+ BIOMETRIC_KEYGUARD_ENABLED, 0, mContext.getUserId());
|
||||
+ Settings.Secure.putIntForUser(mContext.getContentResolver(),
|
||||
+ FINGERPRINT_KEYGUARD_ENABLED, 1, mContext.getUserId());
|
||||
+
|
||||
+ mController = new FingerprintSettingsKeyguardUnlockPreferenceController(
|
||||
+ mContext, "biometric_settings_fingerprint_keyguard");
|
||||
+
|
||||
+ assertThat(mController.isChecked()).isTrue();
|
||||
+ }
|
||||
+}
|
||||
|
|
@ -1,68 +0,0 @@
|
|||
From f0271f36388ec9630d89ff8b3ee4cb22e2ca3eaf Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Pierre-Cl=C3=A9ment=20Tosi?= <ptosi@google.com>
|
||||
Date: Tue, 28 Oct 2025 09:46:06 +0000
|
||||
Subject: [PATCH] vmbase,pvmfw: aarch64: Clean dcache to PoC not PoU
|
||||
|
||||
Some SoCs (with a unified cache before the PoC) might not flush the data
|
||||
to main memory when performing CMOs to PoU so perform them to PoC.
|
||||
|
||||
Test: b/434562039#comment35
|
||||
Bug: 434562039
|
||||
Bug: 455777515
|
||||
Flag: EXEMPT CVE_FIX
|
||||
(cherry picked from commit a6f64040dba5a3aae3f67c68e2a754a5c946610d)
|
||||
Cherrypick-From: https://googleplex-android-review.googlesource.com/q/commit:ab5f74693d42e114af5ac238cca0bcb4b17698ac
|
||||
Merged-In: Id2398e9bcf8dcf7f7a10d254d8eb411d39e109db
|
||||
Change-Id: Id2398e9bcf8dcf7f7a10d254d8eb411d39e109db
|
||||
---
|
||||
guest/pvmfw/src/arch/aarch64/payload.rs | 6 +++---
|
||||
libs/libvmbase/src/arch.rs | 2 +-
|
||||
2 files changed, 4 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/guest/pvmfw/src/arch/aarch64/payload.rs b/guest/pvmfw/src/arch/aarch64/payload.rs
|
||||
index 77e9a31..8c2242e 100644
|
||||
--- a/guest/pvmfw/src/arch/aarch64/payload.rs
|
||||
+++ b/guest/pvmfw/src/arch/aarch64/payload.rs
|
||||
@@ -91,7 +91,7 @@ pub fn jump_to_payload(entrypoint: usize, slices: &MemorySlices) -> ! {
|
||||
"b.lo 0b",
|
||||
|
||||
// Flush d-cache over .data & .bss (including skipped region).
|
||||
- "0: dc cvau, {cache_line}",
|
||||
+ "0: dc cvac, {cache_line}",
|
||||
"add {cache_line}, {cache_line}, {dcache_line_size}",
|
||||
"cmp {cache_line}, {scratch_end}",
|
||||
"b.lo 0b",
|
||||
@@ -103,7 +103,7 @@ pub fn jump_to_payload(entrypoint: usize, slices: &MemorySlices) -> ! {
|
||||
"b.lo 0b",
|
||||
|
||||
// Flush d-cache over stack region.
|
||||
- "0: dc cvau, {cache_line}",
|
||||
+ "0: dc cvac, {cache_line}",
|
||||
"add {cache_line}, {cache_line}, {dcache_line_size}",
|
||||
"cmp {cache_line}, {stack_end}",
|
||||
"b.lo 0b",
|
||||
@@ -115,7 +115,7 @@ pub fn jump_to_payload(entrypoint: usize, slices: &MemorySlices) -> ! {
|
||||
"b.lo 0b",
|
||||
|
||||
// Flush d-cache over EH stack region.
|
||||
- "0: dc cvau, {cache_line}",
|
||||
+ "0: dc cvac, {cache_line}",
|
||||
"add {cache_line}, {cache_line}, {dcache_line_size}",
|
||||
"cmp {cache_line}, {eh_stack_end}",
|
||||
"b.lo 0b",
|
||||
diff --git a/libs/libvmbase/src/arch.rs b/libs/libvmbase/src/arch.rs
|
||||
index 29d3a32..e25745b 100644
|
||||
--- a/libs/libvmbase/src/arch.rs
|
||||
+++ b/libs/libvmbase/src/arch.rs
|
||||
@@ -47,7 +47,7 @@ pub(crate) fn flush_region(start: usize, size: usize) {
|
||||
let end = start + size;
|
||||
let start = crate::util::unchecked_align_down(start, line_size);
|
||||
for line in (start..end).step_by(line_size) {
|
||||
- crate::dc!("cvau", line);
|
||||
+ crate::dc!("cvac", line);
|
||||
}
|
||||
} else {
|
||||
compile_error!("Unsupported target_arch")
|
||||
--
|
||||
2.53.0
|
||||
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
From 69a25763cdb46c8f23fe9eb976132acbe2af82d6 Mon Sep 17 00:00:00 2001
|
||||
From: Himanshu Arora <hmarora@google.com>
|
||||
Date: Fri, 24 Oct 2025 16:47:37 +0000
|
||||
Subject: [PATCH] Fix ACCESS_MEDIA_LOCATION bypass via SAF picker
|
||||
|
||||
When an app uses a picker to access media files, the picker should respect the app's permissions. Currently, it is possible to bypass the ACCESS_MEDIA_LOCATION permission and get unredacted location data.
|
||||
|
||||
This change fixes this by having MediaProvider check the permissions of the app on whose behalf the media is being opened. When a `mediaCapabilitiesUid` is passed, MediaProvider now checks if that UID has the necessary permissions.
|
||||
|
||||
Bug: 326211886
|
||||
Test: manual
|
||||
Flag: EXEMPT BUGFIX
|
||||
Cherrypick-From: https://googleplex-android-review.googlesource.com/q/commit:e5e47f93838e1e9a3a3a520f7c89229fc041a8c3
|
||||
Merged-In: I7ad51535d5ae8a3803162f688c4794edbbcfb167
|
||||
Change-Id: I7ad51535d5ae8a3803162f688c4794edbbcfb167
|
||||
---
|
||||
.../providers/media/MediaProvider.java | 20 +++++++++++++++++--
|
||||
1 file changed, 18 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/com/android/providers/media/MediaProvider.java b/src/com/android/providers/media/MediaProvider.java
|
||||
index 0d75628c5..4a09b7500 100644
|
||||
--- a/src/com/android/providers/media/MediaProvider.java
|
||||
+++ b/src/com/android/providers/media/MediaProvider.java
|
||||
@@ -10253,7 +10253,7 @@ public class MediaProvider extends ContentProvider {
|
||||
|
||||
// Figure out if we need to redact contents
|
||||
final boolean redactionNeeded = isRedactionNeededForOpenViaContentResolver(redactedUri,
|
||||
- ownerPackageName, file);
|
||||
+ ownerPackageName, file, opts);
|
||||
long[] redactionRanges;
|
||||
try {
|
||||
redactionRanges = redactionNeeded ? RedactionUtils.getRedactionRanges(file)
|
||||
@@ -10372,12 +10372,28 @@ public class MediaProvider extends ContentProvider {
|
||||
}
|
||||
|
||||
private boolean isRedactionNeededForOpenViaContentResolver(Uri redactedUri,
|
||||
- String ownerPackageName, File file) {
|
||||
+ String ownerPackageName, File file, Bundle opts) {
|
||||
// Redacted Uris should always redact information
|
||||
if (redactedUri != null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
+ // If the caller provides a media capabilities UID, we check if that UID has the
|
||||
+ // PERMISSION_IS_REDACTION_NEEDED permission. If so, we redact the data. This is
|
||||
+ // used for cases where an app is acting on behalf of another app, and we need
|
||||
+ // to respect the capabilities of the app for which the action is being performed.
|
||||
+ if (opts != null) {
|
||||
+ final int mediaCapabilitiesUid = opts.getInt(MediaStore.EXTRA_MEDIA_CAPABILITIES_UID);
|
||||
+ if (mediaCapabilitiesUid > 0) {
|
||||
+ final LocalCallingIdentity identity = LocalCallingIdentity.fromExternal(
|
||||
+ getContext(),
|
||||
+ mUserCache, mediaCapabilitiesUid, null, null);
|
||||
+ if (identity.hasPermission(PERMISSION_IS_REDACTION_NEEDED)) {
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
final boolean callerIsOwner = Objects.equals(getCallingPackageOrSelf(), ownerPackageName);
|
||||
if (callerIsOwner) {
|
||||
return false;
|
||||
--
|
||||
2.53.0
|
||||
|
||||
|
|
@ -1,91 +0,0 @@
|
|||
From 119013a3d7e8f1eab671bce4c6a85748752081ed Mon Sep 17 00:00:00 2001
|
||||
From: Garvita Jain <garvitajain@google.com>
|
||||
Date: Mon, 1 Dec 2025 11:02:37 +0000
|
||||
Subject: [PATCH] Throw exception on MediaStore createRequest for non-existent
|
||||
uri
|
||||
|
||||
Throw IllegalArgument exception if a caller requests
|
||||
CREATE_WRITE/DELETE/.._REQUEST for a uri that does not exist in the
|
||||
Files table at the time of request.
|
||||
|
||||
BUG: 418773439
|
||||
Test: atest MediaProviderTests
|
||||
Flag: EXEMPT bugfix
|
||||
Cherrypick-From: https://googleplex-android-review.googlesource.com/q/commit:268fc3fb0a438abbc710687a9590cb80b3c0e8bc
|
||||
Cherrypick-From: https://googleplex-android-review.googlesource.com/q/commit:973f11ad05506303f6bbb3fd6275c3a2b824b2e8
|
||||
Merged-In: I00a3b15d8dbcd19afaec3980f7d7a07122bef640
|
||||
Change-Id: I00a3b15d8dbcd19afaec3980f7d7a07122bef640
|
||||
---
|
||||
.../android/providers/media/MediaProvider.java | 16 ++++++++++++++++
|
||||
.../providers/media/MediaProviderTest.java | 18 ++++++++++++++++--
|
||||
2 files changed, 32 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/com/android/providers/media/MediaProvider.java b/src/com/android/providers/media/MediaProvider.java
|
||||
index 4a09b7500..b9fc95667 100644
|
||||
--- a/src/com/android/providers/media/MediaProvider.java
|
||||
+++ b/src/com/android/providers/media/MediaProvider.java
|
||||
@@ -8383,6 +8383,22 @@ public class MediaProvider extends ContentProvider {
|
||||
}
|
||||
}
|
||||
|
||||
+ // Do not allow to create request if the list contains a uri which does not exist
|
||||
+ final LocalCallingIdentity token = clearLocalCallingIdentity();
|
||||
+ try {
|
||||
+ for (Uri uri : uris) {
|
||||
+ try (Cursor c = queryForSingleItem(uri, new String[]{FileColumns._ID}, null, null,
|
||||
+ null)) {
|
||||
+ // queryForSingleItem method throws FileNotFoundException if no items were
|
||||
+ // found, or multiple items were found, or there was trouble reading the data.
|
||||
+ } catch (FileNotFoundException e) {
|
||||
+ throw new IllegalArgumentException("Invalid Uri: " + uri, e);
|
||||
+ }
|
||||
+ }
|
||||
+ } finally {
|
||||
+ restoreLocalCallingIdentity(token);
|
||||
+ }
|
||||
+
|
||||
final Context context = getContext();
|
||||
final Intent intent = new Intent(method, null, context, PermissionActivity.class);
|
||||
extras.putInt(EXTRA_CALLING_PACKAGE_UID, getCallingUidOrSelf());
|
||||
diff --git a/tests/src/com/android/providers/media/MediaProviderTest.java b/tests/src/com/android/providers/media/MediaProviderTest.java
|
||||
index 21cb56e48..660276ce3 100644
|
||||
--- a/tests/src/com/android/providers/media/MediaProviderTest.java
|
||||
+++ b/tests/src/com/android/providers/media/MediaProviderTest.java
|
||||
@@ -39,6 +39,7 @@ import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
+import static org.junit.Assume.assumeTrue;
|
||||
|
||||
import android.Manifest;
|
||||
import android.content.ContentInterface;
|
||||
@@ -334,11 +335,24 @@ public class MediaProviderTest {
|
||||
*/
|
||||
@Test
|
||||
public void testCreateRequest() throws Exception {
|
||||
- final Collection<Uri> uris = Arrays.asList(
|
||||
- MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY, 42));
|
||||
+ final ContentValues values = new ContentValues();
|
||||
+ values.put(MediaColumns.DISPLAY_NAME, "test.mp3");
|
||||
+ values.put(MediaColumns.MIME_TYPE, "audio/mpeg");
|
||||
+ final Uri uri = sIsolatedResolver.insert(
|
||||
+ MediaStore.Audio.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY), values);
|
||||
+ assumeTrue(uri != null);
|
||||
+ final Collection<Uri> uris = List.of(uri);
|
||||
assertNotNull(MediaStore.createWriteRequest(sIsolatedResolver, uris));
|
||||
}
|
||||
|
||||
+ @Test
|
||||
+ public void testCreateRequest_invalidUri_throwsException() throws Exception {
|
||||
+ final Collection<Uri> uris = List.of(
|
||||
+ MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY, 42));
|
||||
+ assertThrows(IllegalArgumentException.class,
|
||||
+ () -> MediaStore.createWriteRequest(sIsolatedResolver, uris));
|
||||
+ }
|
||||
+
|
||||
@Test
|
||||
public void testRequestThumbnail_noAccess_throwsSecurityException() throws Exception {
|
||||
final File dir = Environment
|
||||
--
|
||||
2.53.0
|
||||
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
From 80a267ed1ac714acff455e85ae28c1732777d5b6 Mon Sep 17 00:00:00 2001
|
||||
From: John Reck <jreck@google.com>
|
||||
Date: Thu, 13 Nov 2025 16:02:23 -0500
|
||||
Subject: [PATCH] Handle underflows in dng_opcode_MapTable
|
||||
|
||||
Bug: 456471290
|
||||
Test: sample image in bug && atest ImageDecoderTest
|
||||
Flag: EXEMPT BUGFIX
|
||||
Cherrypick-From: https://googleplex-android-review.googlesource.com/q/commit:90c04eb8818273d4df0773ec38cafceba504b151
|
||||
Cherrypick-From: https://googleplex-android-review.googlesource.com/q/commit:c40bd5325d326d5cc4f6a5944e0047542361dd58
|
||||
Merged-In: Icf182db2288952f189e8f6a6baf9cfb0eff4a5e9
|
||||
Change-Id: Icf182db2288952f189e8f6a6baf9cfb0eff4a5e9
|
||||
---
|
||||
source/dng_misc_opcodes.cpp | 16 +++++++++++-----
|
||||
1 file changed, 11 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/source/dng_misc_opcodes.cpp b/source/dng_misc_opcodes.cpp
|
||||
index 38ee103..49e63a8 100644
|
||||
--- a/source/dng_misc_opcodes.cpp
|
||||
+++ b/source/dng_misc_opcodes.cpp
|
||||
@@ -254,6 +254,7 @@ dng_rect dng_area_spec::Overlap (const dng_rect &tile) const
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
+DNG_ATTRIB_NO_SANITIZE("unsigned-integer-overflow")
|
||||
dng_rect dng_area_spec::ScaledOverlap (const dng_rect &tile) const
|
||||
{
|
||||
|
||||
@@ -560,12 +561,17 @@ void dng_opcode_MapTable::ProcessArea (dng_negative & /* negative */,
|
||||
|
||||
const uint16 *table = fBlackAdjustedTable.Get () ? fBlackAdjustedTable->Buffer_uint16 ()
|
||||
: fTable ->Buffer_uint16 ();
|
||||
-
|
||||
- for (uint32 plane = fAreaSpec.Plane ();
|
||||
- plane < fAreaSpec.Plane () + fAreaSpec.Planes () &&
|
||||
- plane < buffer.Planes ();
|
||||
- plane++)
|
||||
+// BEGIN GOOGLE MODIFICATION
|
||||
+ const uint32 planeStart = fAreaSpec.Plane ();
|
||||
+ const uint32 planeCount = fAreaSpec.Planes ();
|
||||
+ const uint32 bufferPlanes = buffer.Planes ();
|
||||
+
|
||||
+ for (uint32 plane = planeStart;
|
||||
+ plane < bufferPlanes &&
|
||||
+ plane - planeStart < planeCount;
|
||||
+ ++plane)
|
||||
{
|
||||
+// END GOOGLE MODIFICATION
|
||||
|
||||
DoMapArea16 (buffer.DirtyPixel_uint16 (overlap.t, overlap.l, plane),
|
||||
1,
|
||||
--
|
||||
2.53.0
|
||||
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,4 +1,4 @@
|
|||
From 2faf3f0cd32541bada7161dfaeed4e94ade7c6b0 Mon Sep 17 00:00:00 2001
|
||||
From ea0f283eec1e7750351302dbc2009fa905cef375 Mon Sep 17 00:00:00 2001
|
||||
From: Pierre-Hugues Husson <phh@phh.me>
|
||||
Date: Sat, 19 Feb 2022 08:20:25 -0500
|
||||
Subject: [PATCH] Add new mechanism to fake vendor props on a per-process basis
|
||||
|
|
@ -17,10 +17,10 @@ Squashed: Rework property overriding
|
|||
1 file changed, 79 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/libc/system_properties/system_properties.cpp b/libc/system_properties/system_properties.cpp
|
||||
index 6924ff1..e5ad330 100644
|
||||
index 1cb15c3df..40ff48bad 100644
|
||||
--- a/libc/system_properties/system_properties.cpp
|
||||
+++ b/libc/system_properties/system_properties.cpp
|
||||
@@ -36,6 +36,8 @@
|
||||
@@ -35,6 +35,8 @@
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
|
@ -29,9 +29,9 @@ index 6924ff1..e5ad330 100644
|
|||
|
||||
#include <new>
|
||||
|
||||
@@ -53,6 +55,79 @@
|
||||
@@ -50,6 +52,79 @@
|
||||
#define SERIAL_DIRTY(serial) ((serial)&1)
|
||||
#define SERIAL_VALUE_LEN(serial) ((serial) >> 24)
|
||||
#define APPCOMPAT_PREFIX "ro.appcompat_override."
|
||||
|
||||
+static char comm[128];
|
||||
+static bool self_ok = false;
|
||||
|
|
@ -109,7 +109,7 @@ index 6924ff1..e5ad330 100644
|
|||
static bool is_dir(const char* pathname) {
|
||||
struct stat info;
|
||||
if (stat(pathname, &info) == -1) {
|
||||
@@ -160,17 +235,19 @@ uint32_t SystemProperties::AreaSerial() {
|
||||
@@ -123,17 +198,19 @@ uint32_t SystemProperties::AreaSerial() {
|
||||
}
|
||||
|
||||
const prop_info* SystemProperties::Find(const char* name) {
|
||||
|
|
@ -130,7 +130,7 @@ index 6924ff1..e5ad330 100644
|
|||
+ return pa->find(newName);
|
||||
}
|
||||
|
||||
static bool is_appcompat_override(const char* name) {
|
||||
static bool is_read_only(const char* name) {
|
||||
--
|
||||
2.48.1
|
||||
2.40.0
|
||||
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
From dcd161729e17f8c34cdccd64284c5a4809e69951 Mon Sep 17 00:00:00 2001
|
||||
From f9be27ef60cd4ccca6803458ff29ee7a2236769c Mon Sep 17 00:00:00 2001
|
||||
From: Peter Cai <peter@typeblog.net>
|
||||
Date: Thu, 18 Aug 2022 15:44:46 -0400
|
||||
Subject: [PATCH 6/8] APM: Restore S, R and Q behavior respectively for
|
||||
Subject: [PATCH 1/4] APM: Restore S, R and Q behavior respectively for
|
||||
telephony audio
|
||||
|
||||
This conditionally reverts part of b2e5cb (T), 51c9cc (S) and afd4ce (R)
|
||||
|
|
@ -31,17 +31,17 @@ relying on the value of `ro.vndk.version`.
|
|||
|
||||
Change-Id: I56d36d2aef4319935cb88a3e4771b23c6d5b2145
|
||||
---
|
||||
.../managerdefault/AudioPolicyManager.cpp | 208 ++++++++++++------
|
||||
.../managerdefault/AudioPolicyManager.cpp | 103 ++++++++++++++++--
|
||||
.../managerdefault/AudioPolicyManager.h | 3 +
|
||||
2 files changed, 149 insertions(+), 62 deletions(-)
|
||||
2 files changed, 96 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
|
||||
index abf7655470..93692dac33 100644
|
||||
index 4573382a06..c218c7ce2d 100644
|
||||
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
|
||||
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
|
||||
@@ -779,6 +779,17 @@ status_t AudioPolicyManager::updateCallRoutingInternal(
|
||||
ALOGV("%s device rxDevice %s txDevice %s", __func__,
|
||||
rxDevices.itemAt(0)->toString().c_str(), txSourceDevice->toString().c_str());
|
||||
@@ -675,6 +675,17 @@ status_t AudioPolicyManager::updateCallRoutingInternal(
|
||||
disconnectTelephonyAudioSource(mCallRxSourceClient);
|
||||
disconnectTelephonyAudioSource(mCallTxSourceClient);
|
||||
|
||||
+ // release existing RX patch if any
|
||||
+ if (mCallRxPatch != 0) {
|
||||
|
|
@ -57,7 +57,7 @@ index abf7655470..93692dac33 100644
|
|||
auto telephonyRxModule =
|
||||
mHwModules.getModuleForDeviceType(AUDIO_DEVICE_IN_TELEPHONY_RX, AUDIO_FORMAT_DEFAULT);
|
||||
auto telephonyTxModule =
|
||||
@@ -801,9 +812,20 @@ status_t AudioPolicyManager::updateCallRoutingInternal(
|
||||
@@ -697,9 +708,20 @@ status_t AudioPolicyManager::updateCallRoutingInternal(
|
||||
ALOGE("%s() no telephony Tx and/or RX device", __func__);
|
||||
return INVALID_OPERATION;
|
||||
}
|
||||
|
|
@ -81,13 +81,13 @@ index abf7655470..93692dac33 100644
|
|||
} else {
|
||||
// If the RX device is on the primary HW module, then use legacy routing method for
|
||||
// voice calls via setOutputDevice() on primary output.
|
||||
@@ -825,7 +847,14 @@ status_t AudioPolicyManager::updateCallRoutingInternal(
|
||||
}
|
||||
muteWaitMs = setOutputDevices(__func__, mPrimaryOutput, rxDevices, true, delayMs);
|
||||
@@ -716,7 +738,14 @@ status_t AudioPolicyManager::updateCallRoutingInternal(
|
||||
if (!createRxPatch) {
|
||||
muteWaitMs = setOutputDevices(mPrimaryOutput, rxDevices, true, delayMs);
|
||||
} else { // create RX path audio patch
|
||||
- connectTelephonyRxAudioSource(delayMs);
|
||||
- connectTelephonyRxAudioSource();
|
||||
+ if (property_get_int32("ro.vndk.version", 31) >= 31) {
|
||||
+ connectTelephonyRxAudioSource(delayMs);
|
||||
+ connectTelephonyRxAudioSource();
|
||||
+ } else {
|
||||
+ // pre-S behavior: some devices do not support SW bridging correctly when HW bridge is
|
||||
+ // available through createAudioPatch(); startAudioSource() forces SW bridging.
|
||||
|
|
@ -97,22 +97,21 @@ index abf7655470..93692dac33 100644
|
|||
// If the TX device is on the primary HW module but RX device is
|
||||
// on other HW module, SinkMetaData of telephony input should handle it
|
||||
// assuming the device uses audio HAL V5.0 and above
|
||||
@@ -840,7 +869,13 @@ status_t AudioPolicyManager::updateCallRoutingInternal(
|
||||
@@ -731,7 +760,12 @@ status_t AudioPolicyManager::updateCallRoutingInternal(
|
||||
closeActiveClients(activeDesc);
|
||||
}
|
||||
}
|
||||
- connectTelephonyTxAudioSource(txSourceDevice, txSinkDevice, delayMs);
|
||||
+
|
||||
+ if (property_get_int32("ro.vndk.version", 33) >= 33) {
|
||||
+ connectTelephonyTxAudioSource(txSourceDevice, txSinkDevice, delayMs);
|
||||
+ } else {
|
||||
+ // pre-T behavior: hw bridging for tx too; skip the SwOutput
|
||||
+ mCallTxPatch = createTelephonyPatch(false /*isRx*/, txSourceDevice, delayMs);
|
||||
+ }
|
||||
} else {
|
||||
disconnectTelephonyAudioSource(mCallTxSourceClient);
|
||||
}
|
||||
@@ -850,6 +885,36 @@ status_t AudioPolicyManager::updateCallRoutingInternal(
|
||||
if (waitMs != nullptr) {
|
||||
*waitMs = muteWaitMs;
|
||||
@@ -739,6 +773,36 @@ status_t AudioPolicyManager::updateCallRoutingInternal(
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
|
|
@ -149,120 +148,25 @@ index abf7655470..93692dac33 100644
|
|||
bool AudioPolicyManager::isDeviceOfModule(
|
||||
const sp<DeviceDescriptor>& devDesc, const char *moduleId) const {
|
||||
sp<HwModule> module = mHwModules.getModuleFromName(moduleId);
|
||||
@@ -5777,83 +5842,102 @@ status_t AudioPolicyManager::createAudioPatchInternal(const struct audio_patch *
|
||||
@@ -4541,6 +4605,7 @@ status_t AudioPolicyManager::createAudioPatchInternal(const struct audio_patch *
|
||||
// in config XML to reach the sink so that is can be declared as available.
|
||||
audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
|
||||
sp<SwAudioOutputDescriptor> outputDesc;
|
||||
- if (!sourceDesc->isInternal()) {
|
||||
- // take care of dynamic routing for SwOutput selection,
|
||||
- audio_attributes_t attributes = sourceDesc->attributes();
|
||||
- audio_stream_type_t stream = sourceDesc->stream();
|
||||
- audio_attributes_t resultAttr;
|
||||
- audio_config_t config = AUDIO_CONFIG_INITIALIZER;
|
||||
- config.sample_rate = sourceDesc->config().sample_rate;
|
||||
- audio_channel_mask_t sourceMask = sourceDesc->config().channel_mask;
|
||||
- config.channel_mask =
|
||||
- (audio_channel_mask_get_representation(sourceMask)
|
||||
- == AUDIO_CHANNEL_REPRESENTATION_INDEX) ? sourceMask
|
||||
- : audio_channel_mask_in_to_out(sourceMask);
|
||||
- config.format = sourceDesc->config().format;
|
||||
- audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE;
|
||||
- DeviceIdVector selectedDeviceIds;
|
||||
- bool isRequestedDeviceForExclusiveUse = false;
|
||||
- output_type_t outputType;
|
||||
- bool isSpatialized;
|
||||
- bool isBitPerfect;
|
||||
- getOutputForAttrInt(&resultAttr, &output, AUDIO_SESSION_NONE, &attributes,
|
||||
- &stream, sourceDesc->uid(), &config, &flags,
|
||||
- &selectedDeviceIds, &isRequestedDeviceForExclusiveUse,
|
||||
- nullptr, &outputType, &isSpatialized, &isBitPerfect);
|
||||
- if (output == AUDIO_IO_HANDLE_NONE) {
|
||||
- ALOGV("%s no output for device %s",
|
||||
- __FUNCTION__, sinkDevice->toString().c_str());
|
||||
- return INVALID_OPERATION;
|
||||
- }
|
||||
- outputDesc = mOutputs.valueFor(output);
|
||||
- if (outputDesc->isDuplicated()) {
|
||||
- ALOGE("%s output is duplicated", __func__);
|
||||
- return INVALID_OPERATION;
|
||||
- }
|
||||
- bool closeOutput = outputDesc->mDirectOpenCount != 0;
|
||||
- sourceDesc->setSwOutput(outputDesc, closeOutput);
|
||||
- } else {
|
||||
- // Same for "raw patches" aka created from createAudioPatch API
|
||||
- std::set<audio_io_handle_t> outputs =
|
||||
- getOutputsForDevices(DeviceVector(sinkDevice), mOutputs);
|
||||
- // if the sink device is reachable via an opened output stream, request to
|
||||
- // go via this output stream by adding a second source to the patch
|
||||
- // description
|
||||
- output = selectOutput(outputs);
|
||||
- if (output == AUDIO_IO_HANDLE_NONE) {
|
||||
- ALOGE("%s no output available for internal patch sink", __func__);
|
||||
- return INVALID_OPERATION;
|
||||
- }
|
||||
- outputDesc = mOutputs.valueFor(output);
|
||||
- if (outputDesc->isDuplicated()) {
|
||||
- ALOGV("%s output for device %s is duplicated",
|
||||
+ if (sourceDesc != nullptr) { // Ignore indentation, we don't want to cuase huge conflicts...
|
||||
if (!sourceDesc->isInternal()) {
|
||||
// take care of dynamic routing for SwOutput selection,
|
||||
audio_attributes_t attributes = sourceDesc->attributes();
|
||||
@@ -4586,33 +4651,51 @@ status_t AudioPolicyManager::createAudioPatchInternal(const struct audio_patch *
|
||||
outputDesc = mOutputs.valueFor(output);
|
||||
if (outputDesc->isDuplicated()) {
|
||||
ALOGV("%s output for device %s is duplicated",
|
||||
- __func__, sinkDevice->toString().c_str());
|
||||
- return INVALID_OPERATION;
|
||||
+ if (sourceDesc != nullptr) {
|
||||
+ if (!sourceDesc->isInternal()) {
|
||||
+ // take care of dynamic routing for SwOutput selection,
|
||||
+ audio_attributes_t attributes = sourceDesc->attributes();
|
||||
+ audio_stream_type_t stream = sourceDesc->stream();
|
||||
+ audio_attributes_t resultAttr;
|
||||
+ audio_config_t config = AUDIO_CONFIG_INITIALIZER;
|
||||
+ config.sample_rate = sourceDesc->config().sample_rate;
|
||||
+ audio_channel_mask_t sourceMask = sourceDesc->config().channel_mask;
|
||||
+ config.channel_mask =
|
||||
+ (audio_channel_mask_get_representation(sourceMask)
|
||||
+ == AUDIO_CHANNEL_REPRESENTATION_INDEX) ? sourceMask
|
||||
+ : audio_channel_mask_in_to_out(sourceMask);
|
||||
+ config.format = sourceDesc->config().format;
|
||||
+ audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE;
|
||||
+ DeviceIdVector selectedDeviceIds;
|
||||
+ bool isRequestedDeviceForExclusiveUse = false;
|
||||
+ output_type_t outputType;
|
||||
+ bool isSpatialized;
|
||||
+ bool isBitPerfect;
|
||||
+ getOutputForAttrInt(&resultAttr, &output, AUDIO_SESSION_NONE, &attributes,
|
||||
+ &stream, sourceDesc->uid(), &config, &flags,
|
||||
+ &selectedDeviceIds, &isRequestedDeviceForExclusiveUse,
|
||||
+ nullptr, &outputType, &isSpatialized, &isBitPerfect);
|
||||
+ if (output == AUDIO_IO_HANDLE_NONE) {
|
||||
+ ALOGV("%s no output for device %s",
|
||||
+ __FUNCTION__, sinkDevice->toString().c_str());
|
||||
+ return INVALID_OPERATION;
|
||||
+ }
|
||||
+ outputDesc = mOutputs.valueFor(output);
|
||||
+ if (outputDesc->isDuplicated()) {
|
||||
+ ALOGE("%s output is duplicated", __func__);
|
||||
+ return INVALID_OPERATION;
|
||||
+ }
|
||||
+ bool closeOutput = outputDesc->mDirectOpenCount != 0;
|
||||
+ sourceDesc->setSwOutput(outputDesc, closeOutput);
|
||||
+ } else {
|
||||
+ // Same for "raw patches" aka created from createAudioPatch API
|
||||
+ std::set<audio_io_handle_t> outputs =
|
||||
+ getOutputsForDevices(DeviceVector(sinkDevice), mOutputs);
|
||||
+ // if the sink device is reachable via an opened output stream, request to
|
||||
+ // go via this output stream by adding a second source to the patch
|
||||
+ // description
|
||||
+ output = selectOutput(outputs);
|
||||
+ if (output == AUDIO_IO_HANDLE_NONE) {
|
||||
+ ALOGE("%s no output available for internal patch sink", __func__);
|
||||
+ return INVALID_OPERATION;
|
||||
+ }
|
||||
+ outputDesc = mOutputs.valueFor(output);
|
||||
+ if (outputDesc->isDuplicated()) {
|
||||
+ ALOGV("%s output for device %s is duplicated",
|
||||
+ __func__, sinkDevice->toString().c_str());
|
||||
+ return INVALID_OPERATION;
|
||||
+ }
|
||||
+ sourceDesc->setSwOutput(outputDesc, /* closeOutput= */ false);
|
||||
+ __func__, sinkDevice->toString().c_str());
|
||||
return INVALID_OPERATION;
|
||||
}
|
||||
- sourceDesc->setSwOutput(outputDesc, /* closeOutput= */ false);
|
||||
sourceDesc->setSwOutput(outputDesc, /* closeOutput= */ false);
|
||||
}
|
||||
+ }
|
||||
// create a software bridge in PatchPanel if:
|
||||
// - source and sink devices are on different HW modules OR
|
||||
// - audio HAL version is < 3.0
|
||||
|
|
@ -282,7 +186,7 @@ index abf7655470..93692dac33 100644
|
|||
}
|
||||
- sourceDesc->setUseSwBridge();
|
||||
+ if (sourceDesc == nullptr) {
|
||||
+ std::set<audio_io_handle_t> outputs =
|
||||
+ SortedVector<audio_io_handle_t> outputs =
|
||||
+ getOutputsForDevices(DeviceVector(sinkDevice), mOutputs);
|
||||
+ // if the sink device is reachable via an opened output stream, request to
|
||||
+ // go via this output stream by adding a second source to the patch
|
||||
|
|
@ -304,16 +208,16 @@ index abf7655470..93692dac33 100644
|
|||
outputDesc->toAudioPortConfig(&srcMixPortConfig, nullptr);
|
||||
// for volume control, we may need a valid stream
|
||||
srcMixPortConfig.ext.mix.usecase.stream =
|
||||
- (!sourceDesc->isInternal() || sourceDesc->isCallTx()) ?
|
||||
+ (sourceDesc != nullptr && (!sourceDesc->isInternal() || sourceDesc->isCallTx())) ?
|
||||
- (!sourceDesc->isInternal() || isCallTxAudioSource(sourceDesc)) ?
|
||||
+ ((sourceDesc != nullptr && !sourceDesc->isInternal()) || isCallTxAudioSource(sourceDesc)) ?
|
||||
mEngine->getStreamTypeForAttributes(sourceDesc->attributes()) :
|
||||
AUDIO_STREAM_PATCH;
|
||||
patchBuilder.addSource(srcMixPortConfig);
|
||||
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
|
||||
index 017da7cb4b..92f578dfa8 100644
|
||||
index a69e08871b..f8762016db 100644
|
||||
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
|
||||
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
|
||||
@@ -1089,6 +1089,9 @@ protected:
|
||||
@@ -944,6 +944,9 @@ protected:
|
||||
|
||||
SoundTriggerSessionCollection mSoundTriggerSessions;
|
||||
|
||||
|
|
@ -324,5 +228,5 @@ index 017da7cb4b..92f578dfa8 100644
|
|||
SourceClientCollection mAudioSources;
|
||||
|
||||
--
|
||||
2.53.0
|
||||
2.39.2
|
||||
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
From 4b8ff0ae0506a86828ab587b1012df16bc648574 Mon Sep 17 00:00:00 2001
|
||||
From 5ae18168ff97d9e4eb66fc6dc8e087bd0ead8f31 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Cai <peter@typeblog.net>
|
||||
Date: Wed, 24 Aug 2022 15:42:39 -0400
|
||||
Subject: [PATCH 1/8] APM: Optionally force-load audio policy for system-side
|
||||
Subject: [PATCH 2/4] APM: Optionally force-load audio policy for system-side
|
||||
bt audio HAL
|
||||
|
||||
Required to support our system-side bt audio implementation, i.e.
|
||||
|
|
@ -14,7 +14,7 @@ Change-Id: I279fff541a531f922f3fa55b8f14d00237db59ff
|
|||
1 file changed, 25 insertions(+)
|
||||
|
||||
diff --git a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
|
||||
index 6f19a7a..0883637 100644
|
||||
index d446e9667b..f5233f2a42 100644
|
||||
--- a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
|
||||
+++ b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
|
||||
@@ -25,6 +25,7 @@
|
||||
|
|
@ -25,7 +25,7 @@ index 6f19a7a..0883637 100644
|
|||
#include <utils/Log.h>
|
||||
#include <utils/StrongPointer.h>
|
||||
#include <utils/Errors.h>
|
||||
@@ -895,6 +896,30 @@ status_t PolicySerializer::deserialize(const char *configFile, AudioPolicyConfig
|
||||
@@ -890,6 +891,30 @@ status_t PolicySerializer::deserialize(const char *configFile, AudioPolicyConfig
|
||||
if (status != NO_ERROR) {
|
||||
return status;
|
||||
}
|
||||
|
|
@ -57,5 +57,5 @@ index 6f19a7a..0883637 100644
|
|||
|
||||
// Global Configuration
|
||||
--
|
||||
2.48.1
|
||||
2.39.2
|
||||
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
From dc8ee028e2571e2a3832a6c4ec390cccd63ccc3c Mon Sep 17 00:00:00 2001
|
||||
From d11e204968cbf01851042f03fe2a12aabbe84a93 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Cai <peter@typeblog.net>
|
||||
Date: Thu, 25 Aug 2022 13:30:29 -0400
|
||||
Subject: [PATCH 2/8] APM: Remove A2DP audio ports from the primary HAL
|
||||
Subject: [PATCH 3/4] APM: Remove A2DP audio ports from the primary HAL
|
||||
|
||||
These ports defined in the primary HAL are intended for A2DP offloading,
|
||||
however they do not work in general on GSIs, and will interfere with
|
||||
|
|
@ -16,7 +16,7 @@ Change-Id: I3305594a17285da113167b419543543f0ef71122
|
|||
1 file changed, 22 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
|
||||
index 0883637..0f7c903 100644
|
||||
index f5233f2a42..6630d06f6d 100644
|
||||
--- a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
|
||||
+++ b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
|
||||
@@ -26,6 +26,7 @@
|
||||
|
|
@ -40,7 +40,7 @@ index 0883637..0f7c903 100644
|
|||
}
|
||||
}
|
||||
if (!xmlStrcmp(cur->name, reinterpret_cast<const xmlChar*>(Trait::tag))) {
|
||||
@@ -683,6 +681,7 @@ std::variant<status_t, ModuleTraits::Element> PolicySerializer::deserialize<Modu
|
||||
@@ -679,6 +677,7 @@ std::variant<status_t, ModuleTraits::Element> PolicySerializer::deserialize<Modu
|
||||
ALOGE("%s: No %s found", __func__, Attributes::name);
|
||||
return BAD_VALUE;
|
||||
}
|
||||
|
|
@ -48,7 +48,7 @@ index 0883637..0f7c903 100644
|
|||
uint32_t versionMajor = 0, versionMinor = 0;
|
||||
std::string versionLiteral = getXmlAttribute(cur, Attributes::version);
|
||||
if (!versionLiteral.empty()) {
|
||||
@@ -708,6 +707,25 @@ std::variant<status_t, ModuleTraits::Element> PolicySerializer::deserialize<Modu
|
||||
@@ -704,6 +703,25 @@ std::variant<status_t, ModuleTraits::Element> PolicySerializer::deserialize<Modu
|
||||
if (status != NO_ERROR) {
|
||||
return status;
|
||||
}
|
||||
|
|
@ -75,5 +75,5 @@ index 0883637..0f7c903 100644
|
|||
|
||||
RouteTraits::Collection routes;
|
||||
--
|
||||
2.48.1
|
||||
2.39.2
|
||||
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
From 628ff965d6ade74843a58cab6fe58069ef0ec3ad Mon Sep 17 00:00:00 2001
|
||||
From: Emilian Peev <epeev@google.com>
|
||||
Date: Fri, 5 Aug 2022 17:28:06 -0700
|
||||
Subject: [PATCH 4/4] Camera: Avoid unnecessary close of buffer acquire fence
|
||||
fds
|
||||
|
||||
According to the gralloc lock documentation:
|
||||
The ownership of acquireFence is always transferred to the callee, even
|
||||
on errors.
|
||||
|
||||
Bug: 241455881
|
||||
Test: Manual using camera application
|
||||
Change-Id: Ieec34b54aaa7f0d773eccb593c3daaa3e41bae0b
|
||||
Merged-In: Ieec34b54aaa7f0d773eccb593c3daaa3e41bae0b
|
||||
---
|
||||
.../camera/libcameraservice/device3/Camera3OutputStream.cpp | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
|
||||
index 396104c4fd..c725aadb79 100644
|
||||
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
|
||||
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
|
||||
@@ -331,7 +331,7 @@ status_t Camera3OutputStream::fixUpHidlJpegBlobHeader(ANativeWindowBuffer* anwBu
|
||||
status_t res =
|
||||
gbLocker.lockAsync(
|
||||
GraphicBuffer::USAGE_SW_READ_OFTEN | GraphicBuffer::USAGE_SW_WRITE_RARELY,
|
||||
- &mapped, fenceFd.get());
|
||||
+ &mapped, fenceFd.release());
|
||||
if (res != OK) {
|
||||
ALOGE("%s: Failed to lock the buffer: %s (%d)", __FUNCTION__, strerror(-res), res);
|
||||
return res;
|
||||
@@ -1327,7 +1327,7 @@ void Camera3OutputStream::dumpImageToDisk(nsecs_t timestamp,
|
||||
void* mapped = nullptr;
|
||||
base::unique_fd fenceFd(dup(fence));
|
||||
status_t res = graphicBuffer->lockAsync(GraphicBuffer::USAGE_SW_READ_OFTEN, &mapped,
|
||||
- fenceFd.get());
|
||||
+ fenceFd.release());
|
||||
if (res != OK) {
|
||||
ALOGE("%s: Failed to lock the buffer: %s (%d)", __FUNCTION__, strerror(-res), res);
|
||||
return;
|
||||
--
|
||||
2.39.2
|
||||
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
From f1cacc04875356928c5b101b6cb0775ef7a5a10a Mon Sep 17 00:00:00 2001
|
||||
From 5e94fc70ba1963ed33eb6633702cce706b6814d1 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Cai <peter@typeblog.net>
|
||||
Date: Tue, 12 Oct 2021 21:37:22 -0400
|
||||
Subject: [PATCH 01/11] PackageParser: support glob matching for properties
|
||||
Subject: [PATCH 1/6] PackageParser: support glob matching for properties
|
||||
|
||||
Needed to make phh's vendor overlays work
|
||||
---
|
||||
|
|
@ -9,7 +9,7 @@ Needed to make phh's vendor overlays work
|
|||
1 file changed, 10 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
|
||||
index 7d69774ca8b1..1108b11c5007 100644
|
||||
index c15b3e0b80c3..05bb843c0c4d 100644
|
||||
--- a/core/java/android/content/pm/PackageParser.java
|
||||
+++ b/core/java/android/content/pm/PackageParser.java
|
||||
@@ -2545,8 +2545,16 @@ public class PackageParser {
|
||||
|
|
@ -32,5 +32,5 @@ index 7d69774ca8b1..1108b11c5007 100644
|
|||
}
|
||||
return true;
|
||||
--
|
||||
2.48.1
|
||||
2.41.0
|
||||
|
||||
|
|
@ -0,0 +1,163 @@
|
|||
From 3199a7f449d08acf306aafb180ccbcbacd993616 Mon Sep 17 00:00:00 2001
|
||||
From: Danny Lin <danny@kdrag0n.dev>
|
||||
Date: Sat, 16 Oct 2021 05:27:57 -0700
|
||||
Subject: [PATCH 2/6] Add support for app signature spoofing
|
||||
|
||||
This is needed by microG GmsCore to pretend to be the official Google
|
||||
Play Services package, because client apps check the package signature
|
||||
to make sure it matches Google's official certificate.
|
||||
|
||||
This was forward-ported from the Android 10 patch by gudenau:
|
||||
https://github.com/microg/android_packages_apps_GmsCore/pull/957
|
||||
|
||||
Changes made for Android 11:
|
||||
- Updated PackageInfo calls
|
||||
- Added new permission to public API surface, needed for
|
||||
PermissionController which is now an updatable APEX on 11
|
||||
- Added a dummy permission group to allow users to manage the
|
||||
permission through the PermissionController UI
|
||||
(by Vachounet <vachounet@live.fr>)
|
||||
- Updated location provider comment for conciseness
|
||||
|
||||
Changes made for Android 12:
|
||||
- Moved mayFakeSignature into lock-free Computer subclass
|
||||
- Always get permissions for packages that request signature spoofing
|
||||
(otherwise permissions are usually ommitted and thus the permission
|
||||
check doesn't work properly)
|
||||
- Optimize mayFakeSignature check order to improve performance
|
||||
|
||||
Changes made for Android 13:
|
||||
- Computer subclass is now an independent class.
|
||||
|
||||
Change-Id: Ied7d6ce0b83a2d2345c3abba0429998d86494a88
|
||||
---
|
||||
core/api/current.txt | 2 ++
|
||||
core/res/AndroidManifest.xml | 15 ++++++++++
|
||||
core/res/res/values/strings.xml | 12 ++++++++
|
||||
.../com/android/server/pm/ComputerEngine.java | 30 +++++++++++++++++--
|
||||
4 files changed, 56 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/core/api/current.txt b/core/api/current.txt
|
||||
index 487e57d114c9..04e69741b9fd 100644
|
||||
--- a/core/api/current.txt
|
||||
+++ b/core/api/current.txt
|
||||
@@ -87,6 +87,7 @@ package android {
|
||||
field public static final String DUMP = "android.permission.DUMP";
|
||||
field public static final String EXPAND_STATUS_BAR = "android.permission.EXPAND_STATUS_BAR";
|
||||
field public static final String FACTORY_TEST = "android.permission.FACTORY_TEST";
|
||||
+ field public static final String FAKE_PACKAGE_SIGNATURE = "android.permission.FAKE_PACKAGE_SIGNATURE";
|
||||
field public static final String FOREGROUND_SERVICE = "android.permission.FOREGROUND_SERVICE";
|
||||
field public static final String GET_ACCOUNTS = "android.permission.GET_ACCOUNTS";
|
||||
field public static final String GET_ACCOUNTS_PRIVILEGED = "android.permission.GET_ACCOUNTS_PRIVILEGED";
|
||||
@@ -222,6 +223,7 @@ package android {
|
||||
field public static final String CALL_LOG = "android.permission-group.CALL_LOG";
|
||||
field public static final String CAMERA = "android.permission-group.CAMERA";
|
||||
field public static final String CONTACTS = "android.permission-group.CONTACTS";
|
||||
+ field public static final String FAKE_PACKAGE = "android.permission-group.FAKE_PACKAGE";
|
||||
field public static final String LOCATION = "android.permission-group.LOCATION";
|
||||
field public static final String MICROPHONE = "android.permission-group.MICROPHONE";
|
||||
field public static final String NEARBY_DEVICES = "android.permission-group.NEARBY_DEVICES";
|
||||
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
|
||||
index 0e95e30a99b8..a456ac6b7129 100644
|
||||
--- a/core/res/AndroidManifest.xml
|
||||
+++ b/core/res/AndroidManifest.xml
|
||||
@@ -3569,6 +3569,21 @@
|
||||
android:description="@string/permdesc_getPackageSize"
|
||||
android:protectionLevel="normal" />
|
||||
|
||||
+ <!-- Dummy user-facing group for faking package signature -->
|
||||
+ <permission-group android:name="android.permission-group.FAKE_PACKAGE"
|
||||
+ android:label="@string/permgrouplab_fake_package_signature"
|
||||
+ android:description="@string/permgroupdesc_fake_package_signature"
|
||||
+ android:request="@string/permgrouprequest_fake_package_signature"
|
||||
+ android:priority="100" />
|
||||
+
|
||||
+ <!-- Allows an application to change the package signature as
|
||||
+ seen by applications -->
|
||||
+ <permission android:name="android.permission.FAKE_PACKAGE_SIGNATURE"
|
||||
+ android:permissionGroup="android.permission-group.UNDEFINED"
|
||||
+ android:protectionLevel="signature|privileged"
|
||||
+ android:label="@string/permlab_fakePackageSignature"
|
||||
+ android:description="@string/permdesc_fakePackageSignature" />
|
||||
+
|
||||
<!-- @deprecated No longer useful, see
|
||||
{@link android.content.pm.PackageManager#addPackageToPreferred}
|
||||
for details. -->
|
||||
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
|
||||
index 2091c0502b6f..6888edcf7d3c 100644
|
||||
--- a/core/res/res/values/strings.xml
|
||||
+++ b/core/res/res/values/strings.xml
|
||||
@@ -982,6 +982,18 @@
|
||||
|
||||
<!-- Permissions -->
|
||||
|
||||
+ <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
|
||||
+ <string name="permlab_fakePackageSignature">Spoof package signature</string>
|
||||
+ <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
|
||||
+ <string name="permdesc_fakePackageSignature">Allows the app to pretend to be a different app. Malicious applications might be able to use this to access private application data. Legitimate uses include an emulator pretending to be what it emulates. Grant this permission with caution only!</string>
|
||||
+ <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
|
||||
+ <string name="permgrouplab_fake_package_signature">Spoof package signature</string>
|
||||
+ <!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
|
||||
+ <string name="permgroupdesc_fake_package_signature">allow to spoof package signature</string>
|
||||
+ <!-- Message shown to the user when the apps requests permission from this group. If ever possible this should stay below 80 characters (assuming the parameters takes 20 characters). Don't abbreviate until the message reaches 120 characters though. [CHAR LIMIT=120] -->
|
||||
+ <string name="permgrouprequest_fake_package_signature">Allow
|
||||
+ <b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g></b> to spoof package signature?</string>
|
||||
+
|
||||
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
|
||||
<string name="permlab_statusBar">disable or modify status bar</string>
|
||||
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
|
||||
diff --git a/services/core/java/com/android/server/pm/ComputerEngine.java b/services/core/java/com/android/server/pm/ComputerEngine.java
|
||||
index 46b7460dff1b..40549962436f 100644
|
||||
--- a/services/core/java/com/android/server/pm/ComputerEngine.java
|
||||
+++ b/services/core/java/com/android/server/pm/ComputerEngine.java
|
||||
@@ -1603,6 +1603,29 @@ public class ComputerEngine implements Computer {
|
||||
return result;
|
||||
}
|
||||
|
||||
+ private boolean requestsFakeSignature(AndroidPackage p) {
|
||||
+ return p.getMetaData() != null &&
|
||||
+ p.getMetaData().getString("fake-signature") != null;
|
||||
+ }
|
||||
+
|
||||
+ private PackageInfo mayFakeSignature(AndroidPackage p, PackageInfo pi,
|
||||
+ Set<String> permissions) {
|
||||
+ try {
|
||||
+ if (p.getMetaData() != null &&
|
||||
+ p.getTargetSdkVersion() > Build.VERSION_CODES.LOLLIPOP_MR1) {
|
||||
+ String sig = p.getMetaData().getString("fake-signature");
|
||||
+ if (sig != null &&
|
||||
+ permissions.contains("android.permission.FAKE_PACKAGE_SIGNATURE")) {
|
||||
+ pi.signatures = new Signature[] {new Signature(sig)};
|
||||
+ }
|
||||
+ }
|
||||
+ } catch (Throwable t) {
|
||||
+ // We should never die because of any failures, this is system code!
|
||||
+ Log.w("PackageManagerService.FAKE_PACKAGE_SIGNATURE", t);
|
||||
+ }
|
||||
+ return pi;
|
||||
+ }
|
||||
+
|
||||
public final PackageInfo generatePackageInfo(PackageStateInternal ps,
|
||||
@PackageManager.PackageInfoFlagsBits long flags, int userId) {
|
||||
if (!mUserManager.exists(userId)) return null;
|
||||
@@ -1632,13 +1655,14 @@ public class ComputerEngine implements Computer {
|
||||
final int[] gids = (flags & PackageManager.GET_GIDS) == 0 ? EMPTY_INT_ARRAY
|
||||
: mPermissionManager.getGidsForUid(UserHandle.getUid(userId, ps.getAppId()));
|
||||
// Compute granted permissions only if package has requested permissions
|
||||
- final Set<String> permissions = ((flags & PackageManager.GET_PERMISSIONS) == 0
|
||||
+ final Set<String> permissions = (((flags & PackageManager.GET_PERMISSIONS) == 0
|
||||
+ && !requestsFakeSignature(p))
|
||||
|| ArrayUtils.isEmpty(p.getRequestedPermissions())) ? Collections.emptySet()
|
||||
: mPermissionManager.getGrantedPermissions(ps.getPackageName(), userId);
|
||||
|
||||
- PackageInfo packageInfo = PackageInfoUtils.generate(p, gids, flags,
|
||||
+ PackageInfo packageInfo = mayFakeSignature(p, PackageInfoUtils.generate(p, gids, flags,
|
||||
state.getFirstInstallTime(), ps.getLastUpdateTime(), permissions, state, userId,
|
||||
- ps);
|
||||
+ ps), permissions);
|
||||
|
||||
if (packageInfo == null) {
|
||||
return null;
|
||||
--
|
||||
2.41.0
|
||||
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
From 6dfab1c7d68ab6c7e4b8e2586b52fd56ed7b96aa Mon Sep 17 00:00:00 2001
|
||||
From 734839b7918f93cb746ebbe82179a9cbcf165424 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Cai <peter@typeblog.net>
|
||||
Date: Fri, 2 Sep 2022 21:36:06 -0400
|
||||
Subject: [PATCH 02/11] FrameworkParsingPackageUtils: Add glob matching support
|
||||
Subject: [PATCH 3/6] FrameworkParsingPackageUtils: Add glob matching support
|
||||
for properties
|
||||
|
||||
This is now required in addition to the one in PackageParser in order
|
||||
|
|
@ -13,7 +13,7 @@ Change-Id: Ie8679c0ffe03cead4a68bd2d0eb429f05af2d417
|
|||
1 file changed, 10 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/core/java/android/content/pm/parsing/FrameworkParsingPackageUtils.java b/core/java/android/content/pm/parsing/FrameworkParsingPackageUtils.java
|
||||
index 153dd9a93490..900151440ca9 100644
|
||||
index 3e1c5bb3d7ec..f15978c57574 100644
|
||||
--- a/core/java/android/content/pm/parsing/FrameworkParsingPackageUtils.java
|
||||
+++ b/core/java/android/content/pm/parsing/FrameworkParsingPackageUtils.java
|
||||
@@ -215,8 +215,16 @@ public class FrameworkParsingPackageUtils {
|
||||
|
|
@ -36,5 +36,5 @@ index 153dd9a93490..900151440ca9 100644
|
|||
}
|
||||
return true;
|
||||
--
|
||||
2.48.1
|
||||
2.41.0
|
||||
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
From 040ab38bb2f1ae7419cf652e62e9e2a7f279a7ab Mon Sep 17 00:00:00 2001
|
||||
From af0cbe50e889694dc72ab84c4e1af816bdd199b9 Mon Sep 17 00:00:00 2001
|
||||
From: Oliver Scott <olivercscott@gmail.com>
|
||||
Date: Thu, 8 Jul 2021 10:41:43 -0400
|
||||
Subject: [PATCH 03/11] Global VPN feature [1/2]
|
||||
Subject: [PATCH 4/6] Global VPN feature [1/2]
|
||||
|
||||
* Modify existing VPN user range functions to conditionally have traffic
|
||||
from all users pass through the global VPN.
|
||||
|
|
@ -22,16 +22,16 @@ Date: 2021-08-27 16:30:22 -0400
|
|||
Change-Id: I42616cc1f4e39e1dad739d81f6d5c55e218be995
|
||||
Signed-off-by: Mohammad Hasan Keramat J <ikeramat@protonmail.com>
|
||||
---
|
||||
core/java/android/provider/Settings.java | 6 ++++
|
||||
.../policy/SecurityControllerImpl.java | 8 ++++-
|
||||
.../com/android/server/connectivity/Vpn.java | 35 ++++++++++++++++---
|
||||
3 files changed, 44 insertions(+), 5 deletions(-)
|
||||
core/java/android/provider/Settings.java | 6 +++
|
||||
.../policy/SecurityControllerImpl.java | 8 +++-
|
||||
.../com/android/server/connectivity/Vpn.java | 37 +++++++++++++++++--
|
||||
3 files changed, 46 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
|
||||
index 6c7279e7421c..67f54eca2954 100644
|
||||
index 8d8379831e87..bd6cc1d4d7bf 100644
|
||||
--- a/core/java/android/provider/Settings.java
|
||||
+++ b/core/java/android/provider/Settings.java
|
||||
@@ -19101,6 +19101,12 @@ public final class Settings {
|
||||
@@ -16060,6 +16060,12 @@ public final class Settings {
|
||||
CLOCKWORK_HOME_READY,
|
||||
};
|
||||
|
||||
|
|
@ -45,10 +45,10 @@ index 6c7279e7421c..67f54eca2954 100644
|
|||
* Keys we no longer back up under the current schema, but want to continue to
|
||||
* process when restoring historical backup datasets.
|
||||
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
|
||||
index 5e9f524f43ca..5c004c57fb73 100644
|
||||
index ba947149d287..e5eb04c7818d 100644
|
||||
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
|
||||
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
|
||||
@@ -45,6 +45,7 @@ import android.os.Handler;
|
||||
@@ -39,6 +39,7 @@ import android.os.Handler;
|
||||
import android.os.RemoteException;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
|
|
@ -56,7 +56,7 @@ index 5e9f524f43ca..5c004c57fb73 100644
|
|||
import android.security.KeyChain;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.Log;
|
||||
@@ -389,8 +390,13 @@ public class SecurityControllerImpl implements SecurityController {
|
||||
@@ -332,8 +333,13 @@ public class SecurityControllerImpl implements SecurityController {
|
||||
@Override
|
||||
public void onUserSwitched(int newUserId) {
|
||||
mCurrentUserId = newUserId;
|
||||
|
|
@ -72,10 +72,10 @@ index 5e9f524f43ca..5c004c57fb73 100644
|
|||
mVpnUserId = newUserInfo.restrictedProfileParentId;
|
||||
} else {
|
||||
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
|
||||
index 7a2ca702a695..a99c8a7e14f9 100644
|
||||
index 8510de4ef201..7c02924a711d 100644
|
||||
--- a/services/core/java/com/android/server/connectivity/Vpn.java
|
||||
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
|
||||
@@ -826,6 +826,15 @@ public class Vpn {
|
||||
@@ -691,6 +691,15 @@ public class Vpn {
|
||||
return mAlwaysOn;
|
||||
}
|
||||
|
||||
|
|
@ -91,7 +91,7 @@ index 7a2ca702a695..a99c8a7e14f9 100644
|
|||
/**
|
||||
* Checks if a VPN app supports always-on mode.
|
||||
*
|
||||
@@ -1776,6 +1785,7 @@ public class Vpn {
|
||||
@@ -1559,6 +1568,7 @@ public class Vpn {
|
||||
try {
|
||||
// Restricted users are not allowed to create VPNs, they are tied to Owner
|
||||
enforceNotRestrictedUser();
|
||||
|
|
@ -99,7 +99,7 @@ index 7a2ca702a695..a99c8a7e14f9 100644
|
|||
|
||||
final PackageManager packageManager = mUserIdContext.getPackageManager();
|
||||
if (packageManager == null) {
|
||||
@@ -1930,7 +1940,7 @@ public class Vpn {
|
||||
@@ -1720,7 +1730,7 @@ public class Vpn {
|
||||
addUserToRanges(ranges, userId, allowedApplications, disallowedApplications);
|
||||
|
||||
// If the user can have restricted profiles, assign all its restricted profiles too
|
||||
|
|
@ -108,7 +108,7 @@ index 7a2ca702a695..a99c8a7e14f9 100644
|
|||
final long token = Binder.clearCallingIdentity();
|
||||
List<UserInfo> users;
|
||||
try {
|
||||
@@ -1939,7 +1949,8 @@ public class Vpn {
|
||||
@@ -1729,7 +1739,8 @@ public class Vpn {
|
||||
Binder.restoreCallingIdentity(token);
|
||||
}
|
||||
for (UserInfo user : users) {
|
||||
|
|
@ -118,25 +118,27 @@ index 7a2ca702a695..a99c8a7e14f9 100644
|
|||
addUserToRanges(ranges, user.id, allowedApplications, disallowedApplications);
|
||||
}
|
||||
}
|
||||
@@ -2024,7 +2035,7 @@ public class Vpn {
|
||||
Log.e(TAG, "Can not retrieve UserInfo for userId=" + userId);
|
||||
return;
|
||||
}
|
||||
@@ -1810,7 +1821,8 @@ public class Vpn {
|
||||
public void onUserAdded(int userId) {
|
||||
// If the user is restricted tie them to the parent user's VPN
|
||||
UserInfo user = mUserManager.getUserInfo(userId);
|
||||
- if (user.isRestricted() && user.restrictedProfileParentId == mUserId) {
|
||||
+ if ((user.isRestricted() && user.restrictedProfileParentId == mUserId) || isGlobalVpn()) {
|
||||
+ if ((user.isRestricted() && user.restrictedProfileParentId == mUserId) ||
|
||||
+ isGlobalVpn()) {
|
||||
synchronized(Vpn.this) {
|
||||
final Set<Range<Integer>> existingRanges = mNetworkCapabilities.getUids();
|
||||
if (existingRanges != null) {
|
||||
@@ -2061,7 +2072,7 @@ public class Vpn {
|
||||
Log.e(TAG, "Can not retrieve UserInfo for userId=" + userId);
|
||||
return;
|
||||
}
|
||||
@@ -1839,7 +1851,8 @@ public class Vpn {
|
||||
public void onUserRemoved(int userId) {
|
||||
// clean up if restricted
|
||||
UserInfo user = mUserManager.getUserInfo(userId);
|
||||
- if (user.isRestricted() && user.restrictedProfileParentId == mUserId) {
|
||||
+ if ((user.isRestricted() && user.restrictedProfileParentId == mUserId) || isGlobalVpn()) {
|
||||
+ if ((user.isRestricted() && user.restrictedProfileParentId == mUserId) ||
|
||||
+ isGlobalVpn()) {
|
||||
synchronized(Vpn.this) {
|
||||
final Set<Range<Integer>> existingRanges = mNetworkCapabilities.getUids();
|
||||
if (existingRanges != null) {
|
||||
@@ -2504,6 +2515,17 @@ public class Vpn {
|
||||
@@ -2278,6 +2291,17 @@ public class Vpn {
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -154,15 +156,15 @@ index 7a2ca702a695..a99c8a7e14f9 100644
|
|||
/**
|
||||
* Start legacy VPN, controlling native daemons as needed. Creates a
|
||||
* secondary thread to perform connection work, returning quickly.
|
||||
@@ -2587,6 +2609,7 @@ public class Vpn {
|
||||
@@ -2362,6 +2386,7 @@ public class Vpn {
|
||||
new UserHandle(mUserId))) {
|
||||
throw new SecurityException("Restricted users cannot establish VPNs");
|
||||
}
|
||||
+ enforceNotGlobalVpn();
|
||||
|
||||
// Load certificates.
|
||||
String privateKey = "";
|
||||
@@ -4146,6 +4169,7 @@ public class Vpn {
|
||||
final RouteInfo ipv4DefaultRoute = findIPv4DefaultRoute(egress);
|
||||
final String gateway = ipv4DefaultRoute.getGateway().getHostAddress();
|
||||
@@ -3859,6 +3884,7 @@ public class Vpn {
|
||||
|
||||
verifyCallingUidAndPackage(packageName);
|
||||
enforceNotRestrictedUser();
|
||||
|
|
@ -170,7 +172,7 @@ index 7a2ca702a695..a99c8a7e14f9 100644
|
|||
validateRequiredFeatures(profile);
|
||||
|
||||
if (profile.isRestrictedToTestNetworks) {
|
||||
@@ -4192,6 +4216,7 @@ public class Vpn {
|
||||
@@ -3901,6 +3927,7 @@ public class Vpn {
|
||||
|
||||
verifyCallingUidAndPackage(packageName);
|
||||
enforceNotRestrictedUser();
|
||||
|
|
@ -178,7 +180,7 @@ index 7a2ca702a695..a99c8a7e14f9 100644
|
|||
|
||||
final long token = Binder.clearCallingIdentity();
|
||||
try {
|
||||
@@ -4287,6 +4312,7 @@ public class Vpn {
|
||||
@@ -3964,6 +3991,7 @@ public class Vpn {
|
||||
requireNonNull(packageName, "No package name provided");
|
||||
|
||||
enforceNotRestrictedUser();
|
||||
|
|
@ -186,7 +188,7 @@ index 7a2ca702a695..a99c8a7e14f9 100644
|
|||
|
||||
// Prepare VPN for startup
|
||||
if (!prepare(packageName, null /* newPackage */, VpnManager.TYPE_VPN_PLATFORM)) {
|
||||
@@ -4409,6 +4435,7 @@ public class Vpn {
|
||||
@@ -4085,6 +4113,7 @@ public class Vpn {
|
||||
requireNonNull(packageName, "No package name provided");
|
||||
|
||||
enforceNotRestrictedUser();
|
||||
|
|
@ -195,5 +197,5 @@ index 7a2ca702a695..a99c8a7e14f9 100644
|
|||
// To stop the VPN profile, the caller must be the current prepared package and must be
|
||||
// running an Ikev2VpnProfile.
|
||||
--
|
||||
2.48.1
|
||||
2.41.0
|
||||
|
||||
|
|
@ -0,0 +1,236 @@
|
|||
From 628ab41923ce082cd68ab8d4a184823b62a75ab3 Mon Sep 17 00:00:00 2001
|
||||
From: dhacker29 <dhackerdvm@gmail.com>
|
||||
Date: Tue, 24 Nov 2015 01:53:47 -0500
|
||||
Subject: [PATCH 5/6] fw/b: Use ro.build.version.incremental to signal OTA
|
||||
upgrades
|
||||
|
||||
Squash of:
|
||||
|
||||
Author: dhacker29 <dhackerdvm@gmail.com>
|
||||
Date: Tue Nov 24 01:53:47 2015 -0500
|
||||
Core: Use ro.build.date to signal mIsUpgrade
|
||||
|
||||
M: We use a static fingerprint that is only changed when a new OEM build is released, so
|
||||
every flash shows Android is starting instead of upgrading. This will fix that.
|
||||
N: even though we dont have the dexopt sceen on N, this is still needed to delete the
|
||||
correct caches, and grant/deny specific runtime permissions like a true oem update
|
||||
would do.
|
||||
Updated for Nougat By: BeansTown106
|
||||
|
||||
Change-Id: I0e3ed5c8f0351e48944432ae6a0c5194ddeff1fa
|
||||
|
||||
Author: Sam Mortimer <sam@mortimer.me.uk>
|
||||
Date: Fri Sep 28 13:45:00 2018 -0700
|
||||
fw/b UserManagerService: Use ro.build.date to signal upgrades
|
||||
|
||||
*) We changed PackageManagerService to use Build.DATE instead of
|
||||
Build.FINGERPRINT to detect upgrade. Do the same for
|
||||
UserManagerService.
|
||||
*) Affects generation of preboot intent and app data migration.
|
||||
|
||||
Change-Id: I56887b7ca842afdcf3cf84b27b4c04667cf43307
|
||||
|
||||
Author: Wang Han <416810799@qq.com>
|
||||
Date: Sat Dec 29 23:33:20 2018 +0800
|
||||
ShortcutService: Use ro.build.date to signal package scanning
|
||||
|
||||
* Affects system apps scanning.
|
||||
|
||||
Change-Id: I5f6d6647929f5b5ae7e820b18e95bf5ed2ec8d1c
|
||||
|
||||
Author: maxwen <max.weninger@gmail.com>
|
||||
Date: Tue Nov 19 01:02:01 2019 +0100
|
||||
base: Use ro.build.date to clear cache dirs on update
|
||||
|
||||
instead of using ro.build.fingerprint we explictly need to use ro.build.date
|
||||
|
||||
Change-Id: Ib3e80e58eb8c9a21c108e9f5cd2dbdb7ada8e3a4
|
||||
|
||||
Author: maxwen <max.weninger@gmail.com>
|
||||
Date: Wed Oct 28 07:07:10 2020 -0400
|
||||
One more Build.FINGERPRINT to Build.DATE change
|
||||
|
||||
Change-Id: I13dbf3d7f6587d3fcd6591cc0f861b34b6d5561c
|
||||
|
||||
Change-Id: If0eb969ba509981f9209ffa37a949d9042ef4c2a
|
||||
---
|
||||
core/java/android/app/admin/SystemUpdateInfo.java | 4 ++--
|
||||
.../java/com/android/server/am/UserController.java | 3 ++-
|
||||
.../com/android/server/pm/PackageManagerService.java | 12 ++++++------
|
||||
.../core/java/com/android/server/pm/Settings.java | 4 ++--
|
||||
.../java/com/android/server/pm/ShortcutService.java | 2 +-
|
||||
.../com/android/server/pm/UserManagerService.java | 8 ++++----
|
||||
6 files changed, 17 insertions(+), 16 deletions(-)
|
||||
|
||||
diff --git a/core/java/android/app/admin/SystemUpdateInfo.java b/core/java/android/app/admin/SystemUpdateInfo.java
|
||||
index b88bf76c96ca..fdf2b3f54311 100644
|
||||
--- a/core/java/android/app/admin/SystemUpdateInfo.java
|
||||
+++ b/core/java/android/app/admin/SystemUpdateInfo.java
|
||||
@@ -132,7 +132,7 @@ public final class SystemUpdateInfo implements Parcelable {
|
||||
out.startTag(null, tag);
|
||||
out.attributeLong(null, ATTR_RECEIVED_TIME, mReceivedTime);
|
||||
out.attributeInt(null, ATTR_SECURITY_PATCH_STATE, mSecurityPatchState);
|
||||
- out.attribute(null, ATTR_ORIGINAL_BUILD , Build.FINGERPRINT);
|
||||
+ out.attribute(null, ATTR_ORIGINAL_BUILD , Build.VERSION.INCREMENTAL);
|
||||
out.endTag(null, tag);
|
||||
}
|
||||
|
||||
@@ -141,7 +141,7 @@ public final class SystemUpdateInfo implements Parcelable {
|
||||
public static SystemUpdateInfo readFromXml(TypedXmlPullParser parser) {
|
||||
// If an OTA has been applied (build fingerprint has changed), discard stale info.
|
||||
final String buildFingerprint = parser.getAttributeValue(null, ATTR_ORIGINAL_BUILD );
|
||||
- if (!Build.FINGERPRINT.equals(buildFingerprint)) {
|
||||
+ if (!Build.VERSION.INCREMENTAL.equals(buildFingerprint)) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
|
||||
index 44b186e1541f..9470a728389f 100644
|
||||
--- a/services/core/java/com/android/server/am/UserController.java
|
||||
+++ b/services/core/java/com/android/server/am/UserController.java
|
||||
@@ -71,6 +71,7 @@ import android.content.pm.PackagePartitions;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.os.BatteryStats;
|
||||
import android.os.Binder;
|
||||
+import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Debug;
|
||||
import android.os.Handler;
|
||||
@@ -761,7 +762,7 @@ class UserController implements Handler.Callback {
|
||||
// purposefully block sending BOOT_COMPLETED until after all
|
||||
// PRE_BOOT receivers are finished to avoid ANR'ing apps
|
||||
final UserInfo info = getUserInfo(userId);
|
||||
- if (!Objects.equals(info.lastLoggedInFingerprint, PackagePartitions.FINGERPRINT)
|
||||
+ if (!Objects.equals(info.lastLoggedInFingerprint, Build.VERSION.INCREMENTAL)
|
||||
|| SystemProperties.getBoolean("persist.pm.mock-upgrade", false)) {
|
||||
// Suppress double notifications for managed profiles that
|
||||
// were unlocked automatically as part of their parent user being
|
||||
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
|
||||
index 47860373156b..858bf1aad92f 100644
|
||||
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
|
||||
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
|
||||
@@ -1492,7 +1492,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService
|
||||
}
|
||||
|
||||
PackageManagerService m = new PackageManagerService(injector, onlyCore, factoryTest,
|
||||
- PackagePartitions.FINGERPRINT, Build.IS_ENG, Build.IS_USERDEBUG,
|
||||
+ Build.VERSION.INCREMENTAL, Build.IS_ENG, Build.IS_USERDEBUG,
|
||||
Build.VERSION.SDK_INT, Build.VERSION.INCREMENTAL);
|
||||
t.traceEnd(); // "create package manager"
|
||||
|
||||
@@ -1954,7 +1954,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService
|
||||
!buildFingerprint.equals(ver.fingerprint);
|
||||
if (mIsUpgrade) {
|
||||
PackageManagerServiceUtils.logCriticalInfo(Log.INFO, "Upgrading from "
|
||||
- + ver.fingerprint + " to " + PackagePartitions.FINGERPRINT);
|
||||
+ + ver.fingerprint + " to " + Build.VERSION.INCREMENTAL);
|
||||
}
|
||||
|
||||
mInitAppsHelper = new InitAppsHelper(this, mApexManager, mInstallPackageHelper,
|
||||
@@ -2068,8 +2068,8 @@ public class PackageManagerService implements PackageSender, TestUtilityService
|
||||
// allow... it would be nice to have some better way to handle
|
||||
// this situation.
|
||||
if (mIsUpgrade) {
|
||||
- Slog.i(TAG, "Build fingerprint changed from " + ver.fingerprint + " to "
|
||||
- + PackagePartitions.FINGERPRINT
|
||||
+ Slog.i(TAG, "Build incremental version changed from " + ver.fingerprint + " to "
|
||||
+ + Build.VERSION.INCREMENTAL
|
||||
+ "; regranting permissions for internal storage");
|
||||
}
|
||||
mPermissionManager.onStorageVolumeMounted(
|
||||
@@ -2091,7 +2091,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService
|
||||
// across OTAs and are used to drive profile verification (post OTA) and
|
||||
// profile compilation (without waiting to collect a fresh set of profiles).
|
||||
if (mIsUpgrade && !mOnlyCore) {
|
||||
- Slog.i(TAG, "Build fingerprint changed; clearing code caches");
|
||||
+ Slog.i(TAG, "Build incremental version changed; clearing code caches");
|
||||
for (int i = 0; i < packageSettings.size(); i++) {
|
||||
final PackageSetting ps = packageSettings.valueAt(i);
|
||||
if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, ps.getVolumeUuid())) {
|
||||
@@ -2102,7 +2102,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService
|
||||
| Installer.FLAG_CLEAR_APP_DATA_KEEP_ART_PROFILES);
|
||||
}
|
||||
}
|
||||
- ver.fingerprint = PackagePartitions.FINGERPRINT;
|
||||
+ ver.fingerprint = Build.VERSION.INCREMENTAL;
|
||||
}
|
||||
|
||||
// Defer the app data fixup until we are done with app data clearing above.
|
||||
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
|
||||
index cfd029346340..a9b624653b92 100644
|
||||
--- a/services/core/java/com/android/server/pm/Settings.java
|
||||
+++ b/services/core/java/com/android/server/pm/Settings.java
|
||||
@@ -445,7 +445,7 @@ public final class Settings implements Watchable, Snappable {
|
||||
public void forceCurrent() {
|
||||
sdkVersion = Build.VERSION.SDK_INT;
|
||||
databaseVersion = CURRENT_DATABASE_VERSION;
|
||||
- fingerprint = PackagePartitions.FINGERPRINT;
|
||||
+ fingerprint = Build.VERSION.INCREMENTAL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5527,7 +5527,7 @@ public final class Settings implements Watchable, Snappable {
|
||||
}
|
||||
|
||||
private String getExtendedFingerprint(long version) {
|
||||
- return PackagePartitions.FINGERPRINT + "?pc_version=" + version;
|
||||
+ return Build.VERSION.INCREMENTAL + "?pc_version=" + version;
|
||||
}
|
||||
|
||||
private static long uniformRandom(double low, double high) {
|
||||
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
|
||||
index a2b2983a8f35..4564e9dccc13 100644
|
||||
--- a/services/core/java/com/android/server/pm/ShortcutService.java
|
||||
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
|
||||
@@ -5168,7 +5168,7 @@ public class ShortcutService extends IShortcutService.Stub {
|
||||
|
||||
// Injection point.
|
||||
String injectBuildFingerprint() {
|
||||
- return Build.FINGERPRINT;
|
||||
+ return Build.VERSION.INCREMENTAL;
|
||||
}
|
||||
|
||||
final void wtf(String message) {
|
||||
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
|
||||
index 88aeb17dc2b4..af7b481dd311 100644
|
||||
--- a/services/core/java/com/android/server/pm/UserManagerService.java
|
||||
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
|
||||
@@ -4104,7 +4104,7 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
userInfo.creationTime = getCreationTime();
|
||||
userInfo.partial = true;
|
||||
userInfo.preCreated = preCreate;
|
||||
- userInfo.lastLoggedInFingerprint = PackagePartitions.FINGERPRINT;
|
||||
+ userInfo.lastLoggedInFingerprint = Build.VERSION.INCREMENTAL;
|
||||
if (userTypeDetails.hasBadge() && parentId != UserHandle.USER_NULL) {
|
||||
userInfo.profileBadge = getFreeProfileBadgeLU(parentId, userType);
|
||||
}
|
||||
@@ -5390,7 +5390,7 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
t.traceBegin("onBeforeStartUser-" + userId);
|
||||
final int userSerial = userInfo.serialNumber;
|
||||
// Migrate only if build fingerprints mismatch
|
||||
- boolean migrateAppsData = !PackagePartitions.FINGERPRINT.equals(
|
||||
+ boolean migrateAppsData = !Build.VERSION.INCREMENTAL.equals(
|
||||
userInfo.lastLoggedInFingerprint);
|
||||
t.traceBegin("prepareUserData");
|
||||
mUserDataPreparer.prepareUserData(userId, userSerial, StorageManager.FLAG_STORAGE_DE);
|
||||
@@ -5421,7 +5421,7 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
}
|
||||
final int userSerial = userInfo.serialNumber;
|
||||
// Migrate only if build fingerprints mismatch
|
||||
- boolean migrateAppsData = !PackagePartitions.FINGERPRINT.equals(
|
||||
+ boolean migrateAppsData = !Build.VERSION.INCREMENTAL.equals(
|
||||
userInfo.lastLoggedInFingerprint);
|
||||
|
||||
final TimingsTraceAndSlog t = new TimingsTraceAndSlog();
|
||||
@@ -5466,7 +5466,7 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
if (now > EPOCH_PLUS_30_YEARS) {
|
||||
userData.info.lastLoggedInTime = now;
|
||||
}
|
||||
- userData.info.lastLoggedInFingerprint = PackagePartitions.FINGERPRINT;
|
||||
+ userData.info.lastLoggedInFingerprint = Build.VERSION.INCREMENTAL;
|
||||
scheduleWriteUser(userData);
|
||||
}
|
||||
|
||||
--
|
||||
2.41.0
|
||||
|
||||
|
|
@ -0,0 +1,127 @@
|
|||
From 54e70eb7ce231f6a1bef4ffdedb6008b3a949820 Mon Sep 17 00:00:00 2001
|
||||
From: Andy CrossGate Yan <GeForce8800Ultra@gmail.com>
|
||||
Date: Sat, 15 Oct 2022 09:33:56 +0000
|
||||
Subject: [PATCH 6/6] Revert "Remove more FDE methods from StorageManager"
|
||||
|
||||
This reverts commit bd13f84152449a3ead6fa8604fd31f48c0224676.
|
||||
---
|
||||
.../android/os/storage/StorageManager.java | 69 ++++++++++++++++---
|
||||
.../internal/os/RoSystemProperties.java | 4 ++
|
||||
2 files changed, 65 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
|
||||
index d9604b3f0145..603612e82007 100644
|
||||
--- a/core/java/android/os/storage/StorageManager.java
|
||||
+++ b/core/java/android/os/storage/StorageManager.java
|
||||
@@ -1681,13 +1681,18 @@ public class StorageManager {
|
||||
}
|
||||
|
||||
/** {@hide}
|
||||
- * Is this device encrypted?
|
||||
- * <p>
|
||||
- * Note: all devices launching with Android 10 (API level 29) or later are
|
||||
- * required to be encrypted. This should only ever return false for
|
||||
- * in-development devices on which encryption has not yet been configured.
|
||||
- *
|
||||
- * @return true if encrypted, false if not encrypted
|
||||
+ * Is this device encryptable or already encrypted?
|
||||
+ * @return true for encryptable or encrypted
|
||||
+ * false not encrypted and not encryptable
|
||||
+ */
|
||||
+ public static boolean isEncryptable() {
|
||||
+ return RoSystemProperties.CRYPTO_ENCRYPTABLE;
|
||||
+ }
|
||||
+
|
||||
+ /** {@hide}
|
||||
+ * Is this device already encrypted?
|
||||
+ * @return true for encrypted. (Implies isEncryptable() == true)
|
||||
+ * false not encrypted
|
||||
*/
|
||||
public static boolean isEncrypted() {
|
||||
return RoSystemProperties.CRYPTO_ENCRYPTED;
|
||||
@@ -1696,7 +1701,7 @@ public class StorageManager {
|
||||
/** {@hide}
|
||||
* Is this device file encrypted?
|
||||
* @return true for file encrypted. (Implies isEncrypted() == true)
|
||||
- * false not encrypted or using "managed" encryption
|
||||
+ * false not encrypted or block encrypted
|
||||
*/
|
||||
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
|
||||
public static boolean isFileEncryptedNativeOnly() {
|
||||
@@ -1706,6 +1711,54 @@ public class StorageManager {
|
||||
return RoSystemProperties.CRYPTO_FILE_ENCRYPTED;
|
||||
}
|
||||
|
||||
+ /** {@hide}
|
||||
+ * Is this device block encrypted?
|
||||
+ * @return true for block encrypted. (Implies isEncrypted() == true)
|
||||
+ * false not encrypted or file encrypted
|
||||
+ */
|
||||
+ public static boolean isBlockEncrypted() {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ /** {@hide}
|
||||
+ * Is this device block encrypted with credentials?
|
||||
+ * @return true for crediential block encrypted.
|
||||
+ * (Implies isBlockEncrypted() == true)
|
||||
+ * false not encrypted, file encrypted or default block encrypted
|
||||
+ */
|
||||
+ public static boolean isNonDefaultBlockEncrypted() {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ /** {@hide}
|
||||
+ * Is this device in the process of being block encrypted?
|
||||
+ * @return true for encrypting.
|
||||
+ * false otherwise
|
||||
+ * Whether device isEncrypted at this point is undefined
|
||||
+ * Note that only system services and CryptKeeper will ever see this return
|
||||
+ * true - no app will ever be launched in this state.
|
||||
+ * Also note that this state will not change without a teardown of the
|
||||
+ * framework, so no service needs to check for changes during their lifespan
|
||||
+ */
|
||||
+ public static boolean isBlockEncrypting() {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ /** {@hide}
|
||||
+ * Is this device non default block encrypted and in the process of
|
||||
+ * prompting for credentials?
|
||||
+ * @return true for prompting for credentials.
|
||||
+ * (Implies isNonDefaultBlockEncrypted() == true)
|
||||
+ * false otherwise
|
||||
+ * Note that only system services and CryptKeeper will ever see this return
|
||||
+ * true - no app will ever be launched in this state.
|
||||
+ * Also note that this state will not change without a teardown of the
|
||||
+ * framework, so no service needs to check for changes during their lifespan
|
||||
+ */
|
||||
+ public static boolean inCryptKeeperBounce() {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
/** {@hide} */
|
||||
public static boolean isFileEncryptedEmulatedOnly() {
|
||||
return SystemProperties.getBoolean(StorageManager.PROP_EMULATE_FBE, false);
|
||||
diff --git a/core/java/com/android/internal/os/RoSystemProperties.java b/core/java/com/android/internal/os/RoSystemProperties.java
|
||||
index cccd80e82420..adb5c107bc62 100644
|
||||
--- a/core/java/com/android/internal/os/RoSystemProperties.java
|
||||
+++ b/core/java/com/android/internal/os/RoSystemProperties.java
|
||||
@@ -62,10 +62,14 @@ public class RoSystemProperties {
|
||||
public static final CryptoProperties.type_values CRYPTO_TYPE =
|
||||
CryptoProperties.type().orElse(CryptoProperties.type_values.NONE);
|
||||
// These are pseudo-properties
|
||||
+ public static final boolean CRYPTO_ENCRYPTABLE =
|
||||
+ CRYPTO_STATE != CryptoProperties.state_values.UNSUPPORTED;
|
||||
public static final boolean CRYPTO_ENCRYPTED =
|
||||
CRYPTO_STATE == CryptoProperties.state_values.ENCRYPTED;
|
||||
public static final boolean CRYPTO_FILE_ENCRYPTED =
|
||||
CRYPTO_TYPE == CryptoProperties.type_values.FILE;
|
||||
+ public static final boolean CRYPTO_BLOCK_ENCRYPTED =
|
||||
+ CRYPTO_TYPE == CryptoProperties.type_values.BLOCK;
|
||||
|
||||
public static final boolean CONTROL_PRIVAPP_PERMISSIONS_LOG =
|
||||
"log".equalsIgnoreCase(CONTROL_PRIVAPP_PERMISSIONS);
|
||||
--
|
||||
2.41.0
|
||||
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
From 6b4e5731c71d05638f3aa8a753daac72a79fa056 Mon Sep 17 00:00:00 2001
|
||||
From 9f88617d1af3f068efdff111984a7a631464a205 Mon Sep 17 00:00:00 2001
|
||||
From: Pierre-Hugues Husson <phh@phh.me>
|
||||
Date: Sun, 14 Nov 2021 13:47:29 -0500
|
||||
Subject: [PATCH] Pie MTK IMS calls static
|
||||
|
|
@ -10,10 +10,10 @@ Change-Id: I3dd66d436629d37c8ec795df6569736195ae570e
|
|||
1 file changed, 8 insertions(+)
|
||||
|
||||
diff --git a/src/java/com/android/ims/ImsManager.java b/src/java/com/android/ims/ImsManager.java
|
||||
index 43d1a10..d99bed3 100644
|
||||
index c41426d0..2c6d656f 100644
|
||||
--- a/src/java/com/android/ims/ImsManager.java
|
||||
+++ b/src/java/com/android/ims/ImsManager.java
|
||||
@@ -1708,6 +1708,14 @@ public class ImsManager implements FeatureUpdates {
|
||||
@@ -1667,6 +1667,14 @@ public class ImsManager implements FeatureUpdates {
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -29,5 +29,5 @@ index 43d1a10..d99bed3 100644
|
|||
* Push configuration updates to the ImsService implementation.
|
||||
*/
|
||||
--
|
||||
2.48.1
|
||||
2.40.0
|
||||
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
From 02041484d88e3c8a6cd62e1253f4b12b15be6852 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Cai <peter@typeblog.net>
|
||||
Date: Mon, 5 Sep 2022 14:02:37 -0400
|
||||
Subject: [PATCH 1/5] SubscriptionController: Do not override default calling
|
||||
account from third-party apps
|
||||
|
||||
When the user has selected a calling account from a third-party app as
|
||||
default, it should not be overridden by the rest of the telephony
|
||||
subsystem (e.g. SIM subcription updates, or default SIM slot selection).
|
||||
|
||||
Otherwise, it creates a somewhat annoying situation where the user has
|
||||
to keep re-selecting the desired calling account after every reboot.
|
||||
|
||||
Test: manual
|
||||
Change-Id: Iccab64e9b3b3ab4773bd8944d47c2006f229d472
|
||||
---
|
||||
.../internal/telephony/SubscriptionController.java | 11 ++++++++++-
|
||||
1 file changed, 10 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/java/com/android/internal/telephony/SubscriptionController.java b/src/java/com/android/internal/telephony/SubscriptionController.java
|
||||
index 82799bea8b..5105d3a183 100644
|
||||
--- a/src/java/com/android/internal/telephony/SubscriptionController.java
|
||||
+++ b/src/java/com/android/internal/telephony/SubscriptionController.java
|
||||
@@ -2855,8 +2855,17 @@ public class SubscriptionController extends ISub.Stub {
|
||||
subId);
|
||||
|
||||
TelecomManager telecomManager = mContext.getSystemService(TelecomManager.class);
|
||||
+ PhoneAccountHandle currentHandle = telecomManager.getUserSelectedOutgoingPhoneAccount();
|
||||
+ String currentPackageName =
|
||||
+ currentHandle == null ? null : currentHandle.getComponentName().getPackageName();
|
||||
+ boolean currentIsSim = "com.android.phone".equals(currentPackageName);
|
||||
+ // Do not override user selected outgoing calling account
|
||||
+ // if the user has selected a third-party app as default
|
||||
+ boolean shouldKeepOutgoingAccount = currentHandle != null && !currentIsSim;
|
||||
|
||||
- telecomManager.setUserSelectedOutgoingPhoneAccount(newHandle);
|
||||
+ if (!shouldKeepOutgoingAccount) {
|
||||
+ telecomManager.setUserSelectedOutgoingPhoneAccount(newHandle);
|
||||
+ }
|
||||
logd("[setDefaultVoiceSubId] requesting change to phoneAccountHandle=" + newHandle);
|
||||
|
||||
if (previousDefaultSub != getDefaultSubId()) {
|
||||
--
|
||||
2.40.0
|
||||
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
From bcaff4d8a493c657519ae50cf7f3661da6c4a46b Mon Sep 17 00:00:00 2001
|
||||
From: ironydelerium <42721860+ironydelerium@users.noreply.github.com>
|
||||
Date: Fri, 31 Dec 2021 02:20:28 -0800
|
||||
Subject: [PATCH 2/5] Reintroduce 'public void
|
||||
TelephonyMetrics.writeRilSendSms(int, int, int, int)'. (#8)
|
||||
|
||||
The MediaTek IMS package for Android Q, at the very least (likely for the rest, too)
|
||||
invoke this method in their `sendSms` method; Google, in their infinite wisdom,
|
||||
decided that this method needed a message ID passed in as well, changing the signature
|
||||
to 'public void TelephonyMetrics.writeRilSendSms(int, int, int, int, long)' and resulting
|
||||
in a MethodNotFoundException being raised in com.mediatek.ims, crashing it.
|
||||
|
||||
Fixes https://github.com/phhusson/treble_experimentations/issues/2125.
|
||||
|
||||
Co-authored-by: Sarah Vandomelen <sarah@sightworks.com>
|
||||
---
|
||||
.../telephony/metrics/TelephonyMetrics.java | 13 +++++++++++++
|
||||
1 file changed, 13 insertions(+)
|
||||
|
||||
diff --git a/src/java/com/android/internal/telephony/metrics/TelephonyMetrics.java b/src/java/com/android/internal/telephony/metrics/TelephonyMetrics.java
|
||||
index 3fdbfe0ed7..fb8011c3df 100644
|
||||
--- a/src/java/com/android/internal/telephony/metrics/TelephonyMetrics.java
|
||||
+++ b/src/java/com/android/internal/telephony/metrics/TelephonyMetrics.java
|
||||
@@ -2320,6 +2320,19 @@ public class TelephonyMetrics {
|
||||
smsSession.increaseExpectedResponse();
|
||||
}
|
||||
|
||||
+ /**
|
||||
+ * Write Send SMS event (backwards-compatible method for R and earlier IMS implementations)
|
||||
+ *
|
||||
+ * @param phoneId Phone id
|
||||
+ * @param rilSerial RIL request serial number
|
||||
+ * @param tech SMS RAT
|
||||
+ * @param format SMS format. Either {@link SmsMessage#FORMAT_3GPP} or
|
||||
+ * {@link SmsMessage#FORMAT_3GPP2}.
|
||||
+ */
|
||||
+ public void writeRilSendSms(int phoneId, int rilSerial, int tech, int format) {
|
||||
+ writeRilSendSms(phoneId, rilSerial, tech, format, 0);
|
||||
+ }
|
||||
+
|
||||
/**
|
||||
* Write Send SMS event using ImsService. Expecting response from
|
||||
* {@link #writeOnSmsSolicitedResponse}.
|
||||
--
|
||||
2.40.0
|
||||
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
From 9550951ff96e643d143da826cb9560da572850a1 Mon Sep 17 00:00:00 2001
|
||||
From: LuK1337 <priv.luk@gmail.com>
|
||||
Date: Fri, 21 Oct 2022 20:55:05 +0200
|
||||
Subject: [PATCH 3/5] Pass correct value to setPreferredNetworkType() for RIL
|
||||
version < 1.4
|
||||
|
||||
Change-Id: Id14be66a2ea4e85b6504bc03fd7d2f038185c17d
|
||||
---
|
||||
src/java/com/android/internal/telephony/RIL.java | 3 ++-
|
||||
.../com/android/internal/telephony/RadioNetworkProxy.java | 5 +++--
|
||||
2 files changed, 5 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/src/java/com/android/internal/telephony/RIL.java b/src/java/com/android/internal/telephony/RIL.java
|
||||
index 6de66527e1..0c1b7cdf8c 100644
|
||||
--- a/src/java/com/android/internal/telephony/RIL.java
|
||||
+++ b/src/java/com/android/internal/telephony/RIL.java
|
||||
@@ -2879,7 +2879,8 @@ public class RIL extends BaseCommands implements CommandsInterface {
|
||||
mMetrics.writeSetPreferredNetworkType(mPhoneId, networkType);
|
||||
|
||||
try {
|
||||
- networkProxy.setPreferredNetworkTypeBitmap(rr.mSerial, mAllowedNetworkTypesBitmask);
|
||||
+ networkProxy.setPreferredNetworkTypeBitmap(
|
||||
+ rr.mSerial, mAllowedNetworkTypesBitmask, networkType);
|
||||
} catch (RemoteException | RuntimeException e) {
|
||||
handleRadioProxyExceptionForRR(NETWORK_SERVICE, "setPreferredNetworkType", e);
|
||||
}
|
||||
diff --git a/src/java/com/android/internal/telephony/RadioNetworkProxy.java b/src/java/com/android/internal/telephony/RadioNetworkProxy.java
|
||||
index b88103510a..661fa56954 100644
|
||||
--- a/src/java/com/android/internal/telephony/RadioNetworkProxy.java
|
||||
+++ b/src/java/com/android/internal/telephony/RadioNetworkProxy.java
|
||||
@@ -379,16 +379,17 @@ public class RadioNetworkProxy extends RadioServiceProxy {
|
||||
* Call IRadioNetwork#setPreferredNetworkTypeBitmap
|
||||
* @param serial Serial number of request
|
||||
* @param networkTypesBitmask Preferred network types bitmask to set
|
||||
+ * @param networkType Preferred network type to set for RIL version < 1.4
|
||||
* @throws RemoteException
|
||||
*/
|
||||
- public void setPreferredNetworkTypeBitmap(int serial, int networkTypesBitmask)
|
||||
+ public void setPreferredNetworkTypeBitmap(int serial, int networkTypesBitmask, int networkType)
|
||||
throws RemoteException {
|
||||
if (isEmpty() || mHalVersion.greaterOrEqual(RIL.RADIO_HAL_VERSION_1_6)) return;
|
||||
if (mHalVersion.greaterOrEqual(RIL.RADIO_HAL_VERSION_1_4)) {
|
||||
((android.hardware.radio.V1_4.IRadio) mRadioProxy).setPreferredNetworkTypeBitmap(serial,
|
||||
RILUtils.convertToHalRadioAccessFamily(networkTypesBitmask));
|
||||
} else {
|
||||
- mRadioProxy.setPreferredNetworkType(serial, networkTypesBitmask);
|
||||
+ mRadioProxy.setPreferredNetworkType(serial, networkType);
|
||||
}
|
||||
}
|
||||
|
||||
--
|
||||
2.40.0
|
||||
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
From 9b29f5aa8f384499c4efccbf3b6333195ce034c3 Mon Sep 17 00:00:00 2001
|
||||
From c527732943bc02fd434cbecbd07787e2d429023d Mon Sep 17 00:00:00 2001
|
||||
From: ExactExampl <exactxmpl@pixelexperience.org>
|
||||
Date: Tue, 11 Oct 2022 12:38:00 +0300
|
||||
Subject: [PATCH 3/3] Conditionally revert "Block Binder thread until incoming
|
||||
Subject: [PATCH 4/5] Conditionally revert "Block Binder thread until incoming
|
||||
call process completes"
|
||||
|
||||
* Legacy IMS packages handling incoming calls in such a way that
|
||||
|
|
@ -13,42 +13,45 @@ This conditionally reverts commit 75c3dc9ba272b43971f519caba0382f9871c7d9d.
|
|||
|
||||
Change-Id: I55a8f3bbca4a2b9a6bc7511e9fe2d0884a8818e5
|
||||
---
|
||||
.../telephony/imsphone/ImsPhoneCallTracker.java | 15 ++++++++++++++-
|
||||
1 file changed, 14 insertions(+), 1 deletion(-)
|
||||
.../imsphone/ImsPhoneCallTracker.java | 18 ++++++++++++++----
|
||||
1 file changed, 14 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
|
||||
index 56963f3..5f97183 100644
|
||||
index 5968ba6fa1..86034f6fa1 100644
|
||||
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
|
||||
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
|
||||
@@ -70,6 +70,7 @@ import android.os.Registrant;
|
||||
@@ -50,6 +50,7 @@ import android.os.Registrant;
|
||||
import android.os.RegistrantList;
|
||||
import android.os.RemoteException;
|
||||
import android.os.SystemClock;
|
||||
+import android.os.SystemProperties;
|
||||
import android.os.UserHandle;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.provider.Settings;
|
||||
@@ -382,7 +383,19 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall {
|
||||
@Nullable
|
||||
public IImsCallSessionListener onIncomingCall(
|
||||
@NonNull IImsCallSession c, @Nullable String callId, @Nullable Bundle extras) {
|
||||
- return executeAndWaitForReturn(()-> processIncomingCall(c, callId, extras));
|
||||
import android.sysprop.TelephonyProperties;
|
||||
@@ -322,10 +323,19 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall {
|
||||
|
||||
@Override
|
||||
public void onIncomingCall(IImsCallSession c, Bundle extras) {
|
||||
- // we want to ensure we block this binder thread until incoming call setup completes
|
||||
- // as to avoid race conditions where the ImsService tries to update the state of the
|
||||
- // call before the listeners have been attached.
|
||||
- executeAndWait(()-> processIncomingCall(c, extras));
|
||||
+ final boolean shouldBlockBinderThreadOnIncomingCalls = SystemProperties.getBoolean(
|
||||
+ "ro.telephony.block_binder_thread_on_incoming_calls", true);
|
||||
+ if (shouldBlockBinderThreadOnIncomingCalls) {
|
||||
+ // we want to ensure we block this binder thread until incoming call setup completes
|
||||
+ // as to avoid race conditions where the ImsService tries to update the state of the
|
||||
+ // call before the listeners have been attached.
|
||||
+ return executeAndWaitForReturn(()-> processIncomingCall(c, callId, extras));
|
||||
+ executeAndWait(()-> processIncomingCall(c, extras));
|
||||
+ } else {
|
||||
+ // for legacy IMS we want to avoid blocking the binder thread, otherwise
|
||||
+ // we end up with half dead incoming calls with unattached call session
|
||||
+ return TelephonyUtils.runWithCleanCallingIdentity(()-> processIncomingCall(c, callId, extras),
|
||||
+ TelephonyUtils.runWithCleanCallingIdentity(()-> processIncomingCall(c, extras),
|
||||
+ mExecutor);
|
||||
+ }
|
||||
}
|
||||
|
||||
@Override
|
||||
--
|
||||
2.48.1
|
||||
2.40.0
|
||||
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
From b0d5af679ed66883cb537235abc443e6244acd23 Mon Sep 17 00:00:00 2001
|
||||
From 53160d33c83afe4f56862c3c12d4b61e2970209b Mon Sep 17 00:00:00 2001
|
||||
From: Pierre-Hugues Husson <phh@phh.me>
|
||||
Date: Mon, 6 Dec 2021 16:28:22 -0500
|
||||
Subject: [PATCH 1/3] Fix baseband being too long to fit into a 91 chars
|
||||
Subject: [PATCH 5/5] Fix baseband being too long to fit into a 91 chars
|
||||
property, preventing telephony subsystem from starting
|
||||
|
||||
Change-Id: I1762e4a8cc137626be89f350229d6be162bdaf57
|
||||
|
|
@ -10,10 +10,10 @@ Change-Id: I1762e4a8cc137626be89f350229d6be162bdaf57
|
|||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/java/com/android/internal/telephony/GsmCdmaPhone.java b/src/java/com/android/internal/telephony/GsmCdmaPhone.java
|
||||
index e3dcf92..e18a566 100644
|
||||
index 76a8d57246..9a72712c59 100644
|
||||
--- a/src/java/com/android/internal/telephony/GsmCdmaPhone.java
|
||||
+++ b/src/java/com/android/internal/telephony/GsmCdmaPhone.java
|
||||
@@ -2894,7 +2894,7 @@ public class GsmCdmaPhone extends Phone {
|
||||
@@ -3124,7 +3124,7 @@ public class GsmCdmaPhone extends Phone {
|
||||
String version = (String)ar.result;
|
||||
if (version != null) {
|
||||
int length = version.length();
|
||||
|
|
@ -23,5 +23,5 @@ index e3dcf92..e18a566 100644
|
|||
length <= MAX_VERSION_LEN ? version
|
||||
: version.substring(length - MAX_VERSION_LEN, length));
|
||||
--
|
||||
2.48.1
|
||||
2.40.0
|
||||
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
From a1028d0d30263605c7b8ef35209db8d458c6d5c5 Mon Sep 17 00:00:00 2001
|
||||
From 8cd54396bbf29cc977497b53c1464a80aea69825 Mon Sep 17 00:00:00 2001
|
||||
From: Danny Lin <danny@kdrag0n.dev>
|
||||
Date: Mon, 11 Oct 2021 20:48:44 -0700
|
||||
Subject: [PATCH 1/5] Expose themed icon setting in ThemePicker
|
||||
Subject: [PATCH 1/4] Expose themed icon setting in ThemePicker
|
||||
|
||||
Change-Id: I44e9288c3de13a3604b7a03857ec400753317d9a
|
||||
---
|
||||
|
|
@ -10,10 +10,10 @@ Change-Id: I44e9288c3de13a3604b7a03857ec400753317d9a
|
|||
2 files changed, 6 insertions(+)
|
||||
|
||||
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
|
||||
index 80a6b29..59ef70c 100644
|
||||
index 4f580e0bd6..d5b14e5bb9 100644
|
||||
--- a/AndroidManifest.xml
|
||||
+++ b/AndroidManifest.xml
|
||||
@@ -72,6 +72,9 @@
|
||||
@@ -67,6 +67,9 @@
|
||||
<meta-data
|
||||
android:name="com.android.launcher3.grid.control"
|
||||
android:value="${packageName}.grid_control" />
|
||||
|
|
@ -22,9 +22,9 @@ index 80a6b29..59ef70c 100644
|
|||
+ android:value="${packageName}.grid_control" />
|
||||
</activity>
|
||||
|
||||
<activity android:name="com.android.launcher3.widgetpicker.WidgetPickerActivity"
|
||||
</application>
|
||||
diff --git a/quickstep/AndroidManifest-launcher.xml b/quickstep/AndroidManifest-launcher.xml
|
||||
index d6aa886..080c4d6 100644
|
||||
index 7d7054f5a5..d2955c4327 100644
|
||||
--- a/quickstep/AndroidManifest-launcher.xml
|
||||
+++ b/quickstep/AndroidManifest-launcher.xml
|
||||
@@ -66,6 +66,9 @@
|
||||
|
|
@ -38,5 +38,5 @@ index d6aa886..080c4d6 100644
|
|||
|
||||
</application>
|
||||
--
|
||||
2.48.1
|
||||
2.40.1
|
||||
|
||||
|
|
@ -1,29 +1,28 @@
|
|||
From 2451fe73dbe4c76b736690f71584fbd7417611f5 Mon Sep 17 00:00:00 2001
|
||||
From 0d97b73a079dd81b0dd8c0bb512a926d37f76cf9 Mon Sep 17 00:00:00 2001
|
||||
From: Luca Stefani <luca.stefani.ge1@gmail.com>
|
||||
Date: Fri, 1 Nov 2019 23:17:59 +0100
|
||||
Subject: [PATCH 3/5] Properly expose GridCustomizationsProvider
|
||||
Subject: [PATCH 2/4] Properly expose GridCustomizationsProvider
|
||||
|
||||
Change-Id: I8268a215257ae0e399c56ac8b44cdfdff8cc92a0
|
||||
---
|
||||
AndroidManifest-common.xml | 5 ++++-
|
||||
1 file changed, 4 insertions(+), 1 deletion(-)
|
||||
AndroidManifest-common.xml | 4 +++-
|
||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/AndroidManifest-common.xml b/AndroidManifest-common.xml
|
||||
index c28ca1b..6eb9ecb 100644
|
||||
index 0c7b48fe66..1fe86ad022 100644
|
||||
--- a/AndroidManifest-common.xml
|
||||
+++ b/AndroidManifest-common.xml
|
||||
@@ -128,7 +128,10 @@
|
||||
@@ -137,7 +137,9 @@
|
||||
<provider
|
||||
android:name="com.android.launcher3.graphics.LauncherCustomizationProvider"
|
||||
android:authorities="${applicationId}.grid_control"
|
||||
android:name="com.android.launcher3.graphics.GridCustomizationsProvider"
|
||||
android:authorities="${packageName}.grid_control"
|
||||
- android:exported="true" />
|
||||
+ android:permission="android.permission.BIND_WALLPAPER"
|
||||
+ android:exported="true"
|
||||
+ android:writePermission="${packageName}.permission.WRITE_SETTINGS"
|
||||
+ android:readPermission="${packageName}.permission.READ_SETTINGS"/>
|
||||
+ android:readPermission="${packageName}.permission.READ_SETTINGS" />
|
||||
|
||||
<!--
|
||||
The settings activity. To extend point settings_fragment_name to appropriate fragment class
|
||||
--
|
||||
2.48.1
|
||||
2.40.1
|
||||
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
From 4fd73068a8fa6246676d52b6ae63f04341319520 Mon Sep 17 00:00:00 2001
|
||||
From: Danny Lin <danny@kdrag0n.dev>
|
||||
Date: Wed, 6 Oct 2021 22:45:33 -0700
|
||||
Subject: [PATCH 3/4] Fix all apps header color in dark mode
|
||||
|
||||
Change-Id: Ib2ce7f6e3c9b87a4626699cb54673d88392a5f41
|
||||
---
|
||||
res/values/styles.xml | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/res/values/styles.xml b/res/values/styles.xml
|
||||
index 5dc4f0afa1..f5d64729c8 100644
|
||||
--- a/res/values/styles.xml
|
||||
+++ b/res/values/styles.xml
|
||||
@@ -94,6 +94,7 @@
|
||||
<item name="android:colorControlHighlight">#19FFFFFF</item>
|
||||
<item name="android:colorPrimary">#FF212121</item>
|
||||
<item name="allAppsScrimColor">?android:attr/colorBackgroundFloating</item>
|
||||
+ <item name="allappsHeaderProtectionColor">@color/popup_color_tertiary_dark</item>
|
||||
<item name="allAppsNavBarScrimColor">#80000000</item>
|
||||
<item name="popupColorPrimary">@color/popup_color_primary_dark</item>
|
||||
<item name="popupColorSecondary">@color/popup_color_secondary_dark</item>
|
||||
--
|
||||
2.40.1
|
||||
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
From 19554ccc4bd4df815dd95dd5369bb76be73649de Mon Sep 17 00:00:00 2001
|
||||
From 8f1880d3576c0c6521e38558d56e55df92922c8a Mon Sep 17 00:00:00 2001
|
||||
From: Peter Cai <peter@typeblog.net>
|
||||
Date: Fri, 7 Jul 2023 18:13:32 -0400
|
||||
Subject: [PATCH 2/5] Disable QSB in BuildConfig
|
||||
Subject: [PATCH 4/4] Disable QSB in BuildConfig
|
||||
|
||||
Change-Id: I3150ef1d9b8c161ed2a6569d1ae75bba0060b36f
|
||||
---
|
||||
|
|
@ -9,7 +9,7 @@ Change-Id: I3150ef1d9b8c161ed2a6569d1ae75bba0060b36f
|
|||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src_build_config/com/android/launcher3/BuildConfig.java b/src_build_config/com/android/launcher3/BuildConfig.java
|
||||
index 3d39c37..96a8ab6 100644
|
||||
index 1f2e0e5387..ab6c528580 100644
|
||||
--- a/src_build_config/com/android/launcher3/BuildConfig.java
|
||||
+++ b/src_build_config/com/android/launcher3/BuildConfig.java
|
||||
@@ -24,7 +24,7 @@ public final class BuildConfig {
|
||||
|
|
@ -22,5 +22,5 @@ index 3d39c37..96a8ab6 100644
|
|||
/**
|
||||
* Flag to control various developer centric features
|
||||
--
|
||||
2.48.1
|
||||
2.40.1
|
||||
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
From 54fb88d3295c4ea4a904dbdc39eb11fe68c82687 Mon Sep 17 00:00:00 2001
|
||||
From 16c9311e41992ddd8d0bfb5a340cedbf001e3413 Mon Sep 17 00:00:00 2001
|
||||
From: Oliver Scott <olivercscott@gmail.com>
|
||||
Date: Thu, 8 Jul 2021 10:40:49 -0400
|
||||
Subject: [PATCH] Global VPN feature [2/2]
|
||||
|
|
@ -6,22 +6,22 @@ Subject: [PATCH] Global VPN feature [2/2]
|
|||
* Create a global VPN toggle for VPNs in the system user. It is only
|
||||
enabled when no VPN is active in any user.
|
||||
|
||||
Change-Id: If4a552b8f59bc15f53c324afa93a67e086b9c5a9
|
||||
Change-Id: Ic3b79beb635afe03642fce9473bc481239166566
|
||||
Signed-off-by: Mohammad Hasan Keramat J <ikeramat@protonmail.com>
|
||||
---
|
||||
res/values/strings.xml | 6 +++
|
||||
res/values/strings.xml | 5 ++
|
||||
res/xml/vpn_app_management.xml | 6 +++
|
||||
.../settings/vpn2/AppManagementFragment.java | 48 ++++++++++++++++++-
|
||||
3 files changed, 59 insertions(+), 1 deletion(-)
|
||||
3 files changed, 58 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/res/values/strings.xml b/res/values/strings.xml
|
||||
index ea5dbdff62b..964379e44aa 100644
|
||||
index 28b35b3fcf..29ca3882e9 100644
|
||||
--- a/res/values/strings.xml
|
||||
+++ b/res/values/strings.xml
|
||||
@@ -14949,4 +14949,10 @@
|
||||
<string name="safety_center_device_finder_search_terms"></string>
|
||||
<!-- Safety Center system component update search terms [CHAR LIMIT=NONE] -->
|
||||
<string name="safety_center_system_component_update_search_terms"></string>
|
||||
+
|
||||
@@ -14457,4 +14457,9 @@
|
||||
<!-- [CHAR LIMIT=NONE] Hint for QR code process failure -->
|
||||
<string name="bt_le_audio_qr_code_is_not_valid_format">QR code isn\u0027t a valid format</string>
|
||||
|
||||
+ <!-- VPN app management screen, global VPN -->
|
||||
+ <string name="global_vpn_title">Global VPN</string>
|
||||
+ <string name="global_vpn_summary">Force all traffic on the device through this VPN, including work profile and other users.</string>
|
||||
|
|
@ -29,12 +29,12 @@ index ea5dbdff62b..964379e44aa 100644
|
|||
+ <string name="global_vpn_summary_any_vpn_active">You need to disable all active VPN connections first to enable this</string>
|
||||
</resources>
|
||||
diff --git a/res/xml/vpn_app_management.xml b/res/xml/vpn_app_management.xml
|
||||
index dffbbbe3116..93df378fd76 100644
|
||||
index adc441d846..e00f23ccfa 100644
|
||||
--- a/res/xml/vpn_app_management.xml
|
||||
+++ b/res/xml/vpn_app_management.xml
|
||||
@@ -23,6 +23,12 @@
|
||||
android:key="version"
|
||||
@@ -31,6 +31,12 @@
|
||||
android:selectable="false"/>
|
||||
-->
|
||||
|
||||
+ <SwitchPreference
|
||||
+ android:key="global_vpn"
|
||||
|
|
@ -43,13 +43,13 @@ index dffbbbe3116..93df378fd76 100644
|
|||
+ android:summary="@string/global_vpn_summary" />
|
||||
+
|
||||
<com.android.settingslib.RestrictedSwitchPreference
|
||||
android:order="10"
|
||||
android:key="always_on_vpn"
|
||||
android:title="@string/vpn_menu_lockdown"
|
||||
diff --git a/src/com/android/settings/vpn2/AppManagementFragment.java b/src/com/android/settings/vpn2/AppManagementFragment.java
|
||||
index 00c8f5994ce..c4f447f44fb 100644
|
||||
index d4ee5b9c47..7a52e0c42c 100644
|
||||
--- a/src/com/android/settings/vpn2/AppManagementFragment.java
|
||||
+++ b/src/com/android/settings/vpn2/AppManagementFragment.java
|
||||
@@ -27,10 +27,12 @@ import android.content.pm.ApplicationInfo;
|
||||
@@ -28,10 +28,12 @@ import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
|
|
@ -61,16 +61,16 @@ index 00c8f5994ce..c4f447f44fb 100644
|
|||
+import android.provider.Settings;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
@@ -39,6 +41,7 @@ import androidx.annotation.VisibleForTesting;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import android.widget.TextView;
|
||||
@@ -41,6 +43,7 @@ import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.fragment.app.DialogFragment;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceViewHolder;
|
||||
+import androidx.preference.SwitchPreference;
|
||||
|
||||
import com.android.internal.net.VpnConfig;
|
||||
import com.android.internal.util.ArrayUtils;
|
||||
@@ -63,6 +66,7 @@ public class AppManagementFragment extends SettingsPreferenceFragment
|
||||
@@ -64,6 +67,7 @@ public class AppManagementFragment extends SettingsPreferenceFragment
|
||||
private static final String ARG_PACKAGE_NAME = "package";
|
||||
|
||||
private static final String KEY_VERSION = "version";
|
||||
|
|
@ -78,18 +78,18 @@ index 00c8f5994ce..c4f447f44fb 100644
|
|||
private static final String KEY_ALWAYS_ON_VPN = "always_on_vpn";
|
||||
private static final String KEY_LOCKDOWN_VPN = "lockdown_vpn";
|
||||
private static final String KEY_FORGET_VPN = "forget_vpn";
|
||||
@@ -80,6 +84,7 @@ public class AppManagementFragment extends SettingsPreferenceFragment
|
||||
@@ -79,6 +83,7 @@ public class AppManagementFragment extends SettingsPreferenceFragment
|
||||
private String mVpnLabel;
|
||||
|
||||
// UI preference
|
||||
private Preference mPreferenceVersion;
|
||||
+ private SwitchPreference mPreferenceGlobal;
|
||||
private RestrictedSwitchPreference mPreferenceAlwaysOn;
|
||||
private RestrictedSwitchPreference mPreferenceLockdown;
|
||||
private RestrictedPreference mPreferenceForget;
|
||||
@@ -126,10 +131,16 @@ public class AppManagementFragment extends SettingsPreferenceFragment
|
||||
mFeatureProvider = FeatureFactory.getFeatureFactory().getAdvancedVpnFeatureProvider();
|
||||
@@ -123,10 +128,16 @@ public class AppManagementFragment extends SettingsPreferenceFragment
|
||||
mDevicePolicyManager = getContext().getSystemService(DevicePolicyManager.class);
|
||||
mVpnManager = getContext().getSystemService(VpnManager.class);
|
||||
|
||||
mPreferenceVersion = findPreference(KEY_VERSION);
|
||||
+ mPreferenceGlobal = (SwitchPreference) findPreference(KEY_GLOBAL_VPN);
|
||||
mPreferenceAlwaysOn = (RestrictedSwitchPreference) findPreference(KEY_ALWAYS_ON_VPN);
|
||||
mPreferenceLockdown = (RestrictedSwitchPreference) findPreference(KEY_LOCKDOWN_VPN);
|
||||
|
|
@ -103,7 +103,7 @@ index 00c8f5994ce..c4f447f44fb 100644
|
|||
mPreferenceAlwaysOn.setOnPreferenceChangeListener(this);
|
||||
mPreferenceLockdown.setOnPreferenceChangeListener(this);
|
||||
mPreferenceForget.setOnPreferenceClickListener(this);
|
||||
@@ -163,6 +174,8 @@ public class AppManagementFragment extends SettingsPreferenceFragment
|
||||
@@ -204,6 +215,8 @@ public class AppManagementFragment extends SettingsPreferenceFragment
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
switch (preference.getKey()) {
|
||||
|
|
@ -112,7 +112,7 @@ index 00c8f5994ce..c4f447f44fb 100644
|
|||
case KEY_ALWAYS_ON_VPN:
|
||||
return onAlwaysOnVpnClick((Boolean) newValue, mPreferenceLockdown.isChecked());
|
||||
case KEY_LOCKDOWN_VPN:
|
||||
@@ -202,6 +215,11 @@ public class AppManagementFragment extends SettingsPreferenceFragment
|
||||
@@ -243,6 +256,11 @@ public class AppManagementFragment extends SettingsPreferenceFragment
|
||||
return setAlwaysOnVpnByUI(alwaysOnSetting, lockdown);
|
||||
}
|
||||
|
||||
|
|
@ -124,7 +124,7 @@ index 00c8f5994ce..c4f447f44fb 100644
|
|||
@Override
|
||||
public void onConfirmLockdown(Bundle options, boolean isEnabled, boolean isLockdown) {
|
||||
setAlwaysOnVpnByUI(isEnabled, isLockdown);
|
||||
@@ -235,7 +253,18 @@ public class AppManagementFragment extends SettingsPreferenceFragment
|
||||
@@ -276,7 +294,18 @@ public class AppManagementFragment extends SettingsPreferenceFragment
|
||||
final boolean alwaysOn = isVpnAlwaysOn();
|
||||
final boolean lockdown = alwaysOn
|
||||
&& VpnUtils.isAnyLockdownActive(getActivity());
|
||||
|
|
@ -144,7 +144,7 @@ index 00c8f5994ce..c4f447f44fb 100644
|
|||
mPreferenceAlwaysOn.setChecked(alwaysOn);
|
||||
mPreferenceLockdown.setChecked(lockdown);
|
||||
updateRestrictedViews();
|
||||
@@ -298,6 +327,11 @@ public class AppManagementFragment extends SettingsPreferenceFragment
|
||||
@@ -322,6 +351,11 @@ public class AppManagementFragment extends SettingsPreferenceFragment
|
||||
return mPackageName.equals(getAlwaysOnVpnPackage());
|
||||
}
|
||||
|
||||
|
|
@ -156,7 +156,7 @@ index 00c8f5994ce..c4f447f44fb 100644
|
|||
/**
|
||||
* @return false if the intent doesn't contain an existing package or can't retrieve activated
|
||||
* vpn info.
|
||||
@@ -352,6 +386,18 @@ public class AppManagementFragment extends SettingsPreferenceFragment
|
||||
@@ -376,6 +410,18 @@ public class AppManagementFragment extends SettingsPreferenceFragment
|
||||
return config != null && !TextUtils.equals(config.user, mPackageName);
|
||||
}
|
||||
|
||||
|
|
@ -176,5 +176,5 @@ index 00c8f5994ce..c4f447f44fb 100644
|
|||
private static final String TAG = "CannotConnect";
|
||||
private static final String ARG_VPN_LABEL = "label";
|
||||
--
|
||||
2.48.1
|
||||
2.40.0
|
||||
|
||||
|
|
@ -1,29 +1,26 @@
|
|||
From e2a0dd141fd1c7018cf93e46263ba1a613c7f725 Mon Sep 17 00:00:00 2001
|
||||
From 12224023faccc52724a443670bd77c6aa229ce58 Mon Sep 17 00:00:00 2001
|
||||
From: Luca Stefani <luca.stefani.ge1@gmail.com>
|
||||
Date: Fri, 1 Nov 2019 21:14:29 +0100
|
||||
Subject: [PATCH 1/4] Add wallpaper privapp whitelist
|
||||
Subject: [PATCH 1/5] Add wallpaper privapp whitelist
|
||||
|
||||
Change-Id: I044b1d9201ac0b8780fc37a387f401f3dd0ddeac
|
||||
---
|
||||
Android.bp | 9 ++++++++
|
||||
Android.bp | 10 +++++++++
|
||||
privapp_whitelist_com.android.wallpaper.xml | 24 +++++++++++++++++++++
|
||||
2 files changed, 33 insertions(+)
|
||||
2 files changed, 34 insertions(+)
|
||||
create mode 100644 privapp_whitelist_com.android.wallpaper.xml
|
||||
|
||||
diff --git a/Android.bp b/Android.bp
|
||||
index 589c23b..dcc7158 100644
|
||||
index 6d9ff8f6..ff9413ac 100644
|
||||
--- a/Android.bp
|
||||
+++ b/Android.bp
|
||||
@@ -151,9 +151,18 @@ android_app {
|
||||
@@ -117,5 +117,15 @@ android_app {
|
||||
platform_apis: true,
|
||||
manifest: "AndroidManifest.xml",
|
||||
additional_manifests: [":WallpaperPicker2_Manifest"],
|
||||
+
|
||||
+ required: ["privapp_whitelist_com.android.wallpaper.xml"],
|
||||
overrides: [
|
||||
"WallpaperPicker",
|
||||
"WallpaperPicker2",
|
||||
],
|
||||
static_libs: ["ThemePickerApplicationLib"],
|
||||
overrides: ["WallpaperPicker2"],
|
||||
}
|
||||
+
|
||||
+prebuilt_etc_xml {
|
||||
|
|
@ -35,7 +32,7 @@ index 589c23b..dcc7158 100644
|
|||
+}
|
||||
diff --git a/privapp_whitelist_com.android.wallpaper.xml b/privapp_whitelist_com.android.wallpaper.xml
|
||||
new file mode 100644
|
||||
index 0000000..e3f3b65
|
||||
index 00000000..e3f3b658
|
||||
--- /dev/null
|
||||
+++ b/privapp_whitelist_com.android.wallpaper.xml
|
||||
@@ -0,0 +1,24 @@
|
||||
|
|
@ -64,5 +61,5 @@ index 0000000..e3f3b65
|
|||
+ </privapp-permissions>
|
||||
+</permissions>
|
||||
--
|
||||
2.48.1
|
||||
2.40.0
|
||||
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
From 4b626d87eafd37bf950550f5c14b42f5eaab19eb Mon Sep 17 00:00:00 2001
|
||||
From: Danny Lin <danny@kdrag0n.dev>
|
||||
Date: Tue, 5 Oct 2021 19:00:36 -0700
|
||||
Subject: [PATCH 2/5] Override legacy WallpaperPicker app
|
||||
|
||||
Change-Id: I9a1907527eea0e8e7cd10bab64ba79c2c4006c59
|
||||
---
|
||||
Android.bp | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/Android.bp b/Android.bp
|
||||
index ff9413ac..dee08f45 100644
|
||||
--- a/Android.bp
|
||||
+++ b/Android.bp
|
||||
@@ -119,7 +119,7 @@ android_app {
|
||||
additional_manifests: [":WallpaperPicker2_Manifest"],
|
||||
|
||||
required: ["privapp_whitelist_com.android.wallpaper.xml"],
|
||||
- overrides: ["WallpaperPicker2"],
|
||||
+ overrides: ["WallpaperPicker2", "WallpaperPicker"],
|
||||
}
|
||||
|
||||
prebuilt_etc_xml {
|
||||
--
|
||||
2.40.0
|
||||
|
||||
|
|
@ -1,32 +1,33 @@
|
|||
From 7741fb8adcd7fedbe7e4d759659448c30189ec03 Mon Sep 17 00:00:00 2001
|
||||
From 0068121d698911e9bc86a224b3f9a2fb7bdc6cbc Mon Sep 17 00:00:00 2001
|
||||
From: LuK1337 <priv.luk@gmail.com>
|
||||
Date: Tue, 15 Sep 2020 03:27:19 +0200
|
||||
Subject: [PATCH 2/4] Add wallpaper default permissions
|
||||
Subject: [PATCH 3/5] Add wallpaper default permissions
|
||||
|
||||
Change-Id: If43a594da31fbab9280ce45b049737f6c534b620
|
||||
---
|
||||
Android.bp | 13 ++++++-
|
||||
Android.bp | 14 ++++++-
|
||||
default_permissions_com.android.wallpaper.xml | 37 +++++++++++++++++++
|
||||
2 files changed, 49 insertions(+), 1 deletion(-)
|
||||
2 files changed, 50 insertions(+), 1 deletion(-)
|
||||
create mode 100644 default_permissions_com.android.wallpaper.xml
|
||||
|
||||
diff --git a/Android.bp b/Android.bp
|
||||
index dcc7158..e4d94c4 100644
|
||||
index dee08f45..74479801 100644
|
||||
--- a/Android.bp
|
||||
+++ b/Android.bp
|
||||
@@ -151,7 +151,10 @@ android_app {
|
||||
platform_apis: true,
|
||||
@@ -118,7 +118,11 @@ android_app {
|
||||
manifest: "AndroidManifest.xml",
|
||||
additional_manifests: [":WallpaperPicker2_Manifest"],
|
||||
|
||||
- required: ["privapp_whitelist_com.android.wallpaper.xml"],
|
||||
+ required: [
|
||||
+ "privapp_whitelist_com.android.wallpaper.xml",
|
||||
+ "default_permissions_com.android.wallpaper.xml",
|
||||
+ ],
|
||||
overrides: [
|
||||
"WallpaperPicker",
|
||||
"WallpaperPicker2",
|
||||
@@ -166,3 +169,11 @@ prebuilt_etc_xml {
|
||||
+
|
||||
overrides: ["WallpaperPicker2", "WallpaperPicker"],
|
||||
}
|
||||
|
||||
@@ -129,3 +133,11 @@ prebuilt_etc_xml {
|
||||
filename_from_src: true,
|
||||
sub_dir: "permissions",
|
||||
}
|
||||
|
|
@ -40,7 +41,7 @@ index dcc7158..e4d94c4 100644
|
|||
+}
|
||||
diff --git a/default_permissions_com.android.wallpaper.xml b/default_permissions_com.android.wallpaper.xml
|
||||
new file mode 100644
|
||||
index 0000000..41b23ce
|
||||
index 00000000..41b23ce1
|
||||
--- /dev/null
|
||||
+++ b/default_permissions_com.android.wallpaper.xml
|
||||
@@ -0,0 +1,37 @@
|
||||
|
|
@ -82,5 +83,5 @@ index 0000000..41b23ce
|
|||
+ </exception>
|
||||
+</exceptions>
|
||||
--
|
||||
2.48.1
|
||||
2.40.0
|
||||
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
From f7b9605f848fd4282230b71c56075e92d090d527 Mon Sep 17 00:00:00 2001
|
||||
From e51787a4ad9f2a70d9d68cad29a8974244c2c0b6 Mon Sep 17 00:00:00 2001
|
||||
From: Luca Stefani <luca.stefani.ge1@gmail.com>
|
||||
Date: Fri, 1 Nov 2019 23:17:08 +0100
|
||||
Subject: [PATCH 3/4] Specify we read and write launcher settings
|
||||
Subject: [PATCH 4/5] Specify we read and write launcher settings
|
||||
|
||||
Change-Id: Ifc8196588443b007602118389ca76d34ab531f14
|
||||
---
|
||||
|
|
@ -9,10 +9,10 @@ Change-Id: Ifc8196588443b007602118389ca76d34ab531f14
|
|||
1 file changed, 3 insertions(+)
|
||||
|
||||
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
|
||||
index 7459868..c5ec358 100755
|
||||
index 4e71bcc6..26f4fce0 100755
|
||||
--- a/AndroidManifest.xml
|
||||
+++ b/AndroidManifest.xml
|
||||
@@ -62,6 +62,9 @@
|
||||
@@ -45,6 +45,9 @@
|
||||
</intent>
|
||||
</queries>
|
||||
|
||||
|
|
@ -23,5 +23,5 @@ index 7459868..c5ec358 100755
|
|||
tools:replace="android:icon,android:name"
|
||||
android:extractNativeLibs="false"
|
||||
--
|
||||
2.48.1
|
||||
2.40.0
|
||||
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
From 8bf494671a20e197e4e41d63fe9d942e16bb27dd Mon Sep 17 00:00:00 2001
|
||||
From 3156edaae20291237f095d2d5bb66e8ba0a4cea5 Mon Sep 17 00:00:00 2001
|
||||
From: Danny Lin <danny@kdrag0n.dev>
|
||||
Date: Tue, 5 Oct 2021 22:40:58 -0700
|
||||
Subject: [PATCH 4/4] Add permission for launcher preview rendering
|
||||
Subject: [PATCH 5/5] Add permission for launcher preview rendering
|
||||
|
||||
Change-Id: Ie707dcd98161e8f5993b0504295fddc3f395cd20
|
||||
---
|
||||
|
|
@ -10,10 +10,10 @@ Change-Id: Ie707dcd98161e8f5993b0504295fddc3f395cd20
|
|||
2 files changed, 2 insertions(+)
|
||||
|
||||
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
|
||||
index c5ec358..f7db26c 100755
|
||||
index 26f4fce0..40281cf9 100755
|
||||
--- a/AndroidManifest.xml
|
||||
+++ b/AndroidManifest.xml
|
||||
@@ -13,6 +13,7 @@
|
||||
@@ -8,6 +8,7 @@
|
||||
<uses-permission android:name="android.permission.CHANGE_OVERLAY_PACKAGES"/>
|
||||
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS"/>
|
||||
<uses-permission android:name="android.permission.SET_WALLPAPER_COMPONENT" />
|
||||
|
|
@ -22,7 +22,7 @@ index c5ec358..f7db26c 100755
|
|||
<uses-permission android:name="android.permission.MODIFY_DAY_NIGHT_MODE" />
|
||||
<uses-permission android:name="android.permission.CUSTOMIZE_SYSTEM_UI" />
|
||||
diff --git a/privapp_whitelist_com.android.wallpaper.xml b/privapp_whitelist_com.android.wallpaper.xml
|
||||
index e3f3b65..47133be 100644
|
||||
index e3f3b658..47133be8 100644
|
||||
--- a/privapp_whitelist_com.android.wallpaper.xml
|
||||
+++ b/privapp_whitelist_com.android.wallpaper.xml
|
||||
@@ -20,5 +20,6 @@
|
||||
|
|
@ -33,5 +33,5 @@ index e3f3b65..47133be 100644
|
|||
</privapp-permissions>
|
||||
</permissions>
|
||||
--
|
||||
2.48.1
|
||||
2.40.0
|
||||
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
From 08cae5289428f6a99f2a6d28145fa542d1288916 Mon Sep 17 00:00:00 2001
|
||||
From: "tzu-hsien.huang" <tzu-hsien.huang@mediatek.com>
|
||||
Date: Wed, 20 Jul 2022 15:12:01 +0800
|
||||
Subject: [PATCH 1/3] Additionally check le_set_event_mask command resturn
|
||||
status with UNSUPPORTED_LMP_OR_LL_PARAMETER
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
In GD BT stack, stack will check each return status of HCI Commands. E.g. reset , le_set_event_mask, set_event_mask …etc.
|
||||
In BT spec 5.2, SIG add some parameters for le_set_event_mask for le audio, like LE Terminate BIG Complete event: Supported.
|
||||
However, some legacy chips do not support LE Audio feature, and controller will return Status: Unsupported LMP Parameter Value when it receives this HCI Command
|
||||
When it checks the return value and find the status is not SUCCESS, it will cause FAIL and cannot be compatible with old legacy chip.
|
||||
After brushing GSI, Bluetooth will turn off automatically when it is turned on.
|
||||
So all CTS test will always fail.
|
||||
|
||||
Check le_set_event_mask command return status with SUCCESS or UNSUPPORTED_LMP_OR_LL_PARAMETER
|
||||
|
||||
Bug: 239662211
|
||||
Test: CtsBluetoothTestCases
|
||||
Change-Id: I2b0cede7f47eecd2124a386e958773289eb6f11c
|
||||
---
|
||||
system/gd/hci/controller.cc | 11 ++++++++++-
|
||||
1 file changed, 10 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/system/gd/hci/controller.cc b/system/gd/hci/controller.cc
|
||||
index 9dac2b6a84..50342d639e 100644
|
||||
--- a/system/gd/hci/controller.cc
|
||||
+++ b/system/gd/hci/controller.cc
|
||||
@@ -548,7 +548,7 @@ struct Controller::impl {
|
||||
void le_set_event_mask(uint64_t le_event_mask) {
|
||||
std::unique_ptr<LeSetEventMaskBuilder> packet = LeSetEventMaskBuilder::Create(le_event_mask);
|
||||
hci_->EnqueueCommand(std::move(packet), module_.GetHandler()->BindOnceOn(
|
||||
- this, &Controller::impl::check_status<LeSetEventMaskCompleteView>));
|
||||
+ this, &Controller::impl::check_event_mask_status<LeSetEventMaskCompleteView>));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
@@ -559,6 +559,15 @@ struct Controller::impl {
|
||||
ASSERT(status_view.GetStatus() == ErrorCode::SUCCESS);
|
||||
}
|
||||
|
||||
+ template <class T>
|
||||
+ void check_event_mask_status(CommandCompleteView view) {
|
||||
+ ASSERT(view.IsValid());
|
||||
+ auto status_view = T::Create(view);
|
||||
+ ASSERT(status_view.IsValid());
|
||||
+ ASSERT(status_view.GetStatus() == ErrorCode::SUCCESS ||
|
||||
+ status_view.GetStatus() == ErrorCode::UNSUPPORTED_LMP_OR_LL_PARAMETER);
|
||||
+ }
|
||||
+
|
||||
#define OP_CODE_MAPPING(name) \
|
||||
case OpCode::name: { \
|
||||
uint16_t index = (uint16_t)OpCodeIndex::name; \
|
||||
--
|
||||
2.40.1
|
||||
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
From 55a4e7e7158f50f3e8840b526e15d7c9f10423de Mon Sep 17 00:00:00 2001
|
||||
From: Peter Cai <peter@typeblog.net>
|
||||
Date: Wed, 24 Aug 2022 10:41:29 -0400
|
||||
Subject: [PATCH 2/3] gd: hci: Ignore unexpected status events
|
||||
|
||||
For some reason, on some old devices, the controller will report a
|
||||
remote to support SNIFF_SUBRATING even when it does not. Just ignore the
|
||||
error here (the status event comes from the failure response).
|
||||
|
||||
Change-Id: Ifb9a65fd77f21d15a8dc1ced9240194d38218ef6
|
||||
---
|
||||
system/gd/hci/hci_layer.cc | 15 +++++++--------
|
||||
1 file changed, 7 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/system/gd/hci/hci_layer.cc b/system/gd/hci/hci_layer.cc
|
||||
index 5def729ac8..9c235294bb 100644
|
||||
--- a/system/gd/hci/hci_layer.cc
|
||||
+++ b/system/gd/hci/hci_layer.cc
|
||||
@@ -195,14 +195,13 @@ struct HciLayer::impl {
|
||||
EventView::Create(PacketView<kLittleEndian>(std::make_shared<std::vector<uint8_t>>(std::vector<uint8_t>()))));
|
||||
command_queue_.front().GetCallback<CommandCompleteView>()->Invoke(move(command_complete_view));
|
||||
} else {
|
||||
- ASSERT_LOG(
|
||||
- command_queue_.front().waiting_for_status_ == is_status,
|
||||
- "0x%02hx (%s) was not expecting %s event",
|
||||
- op_code,
|
||||
- OpCodeText(op_code).c_str(),
|
||||
- logging_id.c_str());
|
||||
-
|
||||
- command_queue_.front().GetCallback<TResponse>()->Invoke(move(response_view));
|
||||
+ if (command_queue_.front().waiting_for_status_ == is_status) {
|
||||
+ command_queue_.front().GetCallback<TResponse>()->Invoke(move(response_view));
|
||||
+ } else {
|
||||
+ CommandCompleteView command_complete_view = CommandCompleteView::Create(
|
||||
+ EventView::Create(PacketView<kLittleEndian>(std::make_shared<std::vector<uint8_t>>(std::vector<uint8_t>()))));
|
||||
+ command_queue_.front().GetCallback<CommandCompleteView>()->Invoke(move(command_complete_view));
|
||||
+ }
|
||||
}
|
||||
|
||||
command_queue_.pop_front();
|
||||
--
|
||||
2.40.1
|
||||
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
From f2d820597f4dcbb08e4e0c9026dc1d56fe7b3bfd Mon Sep 17 00:00:00 2001
|
||||
From: Peter Cai <peter@typeblog.net>
|
||||
Date: Wed, 24 Aug 2022 15:45:18 -0400
|
||||
Subject: [PATCH 3/3] audio_hal_interface: Optionally use sysbta HAL
|
||||
|
||||
Required to support sysbta, our system-side bt audio implementation.
|
||||
|
||||
Change-Id: I59973e6ec84c5923be8a7c67b36b2e237f000860
|
||||
---
|
||||
system/audio_hal_interface/aidl/client_interface_aidl.cc | 6 +++---
|
||||
system/audio_hal_interface/aidl/client_interface_aidl.h | 7 +++++++
|
||||
system/audio_hal_interface/hal_version_manager.cc | 9 ++++++++-
|
||||
3 files changed, 18 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/system/audio_hal_interface/aidl/client_interface_aidl.cc b/system/audio_hal_interface/aidl/client_interface_aidl.cc
|
||||
index 9af28031f7..5a9dbbccad 100644
|
||||
--- a/system/audio_hal_interface/aidl/client_interface_aidl.cc
|
||||
+++ b/system/audio_hal_interface/aidl/client_interface_aidl.cc
|
||||
@@ -56,7 +56,7 @@ BluetoothAudioClientInterface::BluetoothAudioClientInterface(
|
||||
|
||||
bool BluetoothAudioClientInterface::is_aidl_available() {
|
||||
return AServiceManager_isDeclared(
|
||||
- kDefaultAudioProviderFactoryInterface.c_str());
|
||||
+ audioProviderFactoryInterface().c_str());
|
||||
}
|
||||
|
||||
std::vector<AudioCapabilities>
|
||||
@@ -72,7 +72,7 @@ BluetoothAudioClientInterface::GetAudioCapabilities(SessionType session_type) {
|
||||
}
|
||||
auto provider_factory = IBluetoothAudioProviderFactory::fromBinder(
|
||||
::ndk::SpAIBinder(AServiceManager_waitForService(
|
||||
- kDefaultAudioProviderFactoryInterface.c_str())));
|
||||
+ audioProviderFactoryInterface().c_str())));
|
||||
|
||||
if (provider_factory == nullptr) {
|
||||
LOG(ERROR) << __func__ << ", can't get capability from unknown factory";
|
||||
@@ -99,7 +99,7 @@ void BluetoothAudioClientInterface::FetchAudioProvider() {
|
||||
}
|
||||
auto provider_factory = IBluetoothAudioProviderFactory::fromBinder(
|
||||
::ndk::SpAIBinder(AServiceManager_waitForService(
|
||||
- kDefaultAudioProviderFactoryInterface.c_str())));
|
||||
+ audioProviderFactoryInterface().c_str())));
|
||||
|
||||
if (provider_factory == nullptr) {
|
||||
LOG(ERROR) << __func__ << ", can't get capability from unknown factory";
|
||||
diff --git a/system/audio_hal_interface/aidl/client_interface_aidl.h b/system/audio_hal_interface/aidl/client_interface_aidl.h
|
||||
index 17abefe8fe..07dd11266f 100644
|
||||
--- a/system/audio_hal_interface/aidl/client_interface_aidl.h
|
||||
+++ b/system/audio_hal_interface/aidl/client_interface_aidl.h
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "bluetooth_audio_port_impl.h"
|
||||
#include "common/message_loop_thread.h"
|
||||
#include "transport_instance.h"
|
||||
+#include "osi/include/properties.h"
|
||||
|
||||
#define BLUETOOTH_AUDIO_HAL_PROP_DISABLED \
|
||||
"persist.bluetooth.bluetooth_audio_hal.disabled"
|
||||
@@ -117,6 +118,12 @@ class BluetoothAudioClientInterface {
|
||||
// "android.hardware.bluetooth.audio.IBluetoothAudioProviderFactory/default";
|
||||
static inline const std::string kDefaultAudioProviderFactoryInterface =
|
||||
std::string() + IBluetoothAudioProviderFactory::descriptor + "/default";
|
||||
+ static inline const std::string kSystemAudioProviderFactoryInterface =
|
||||
+ std::string() + IBluetoothAudioProviderFactory::descriptor + "/sysbta";
|
||||
+ static inline const std::string audioProviderFactoryInterface() {
|
||||
+ return osi_property_get_bool("persist.bluetooth.system_audio_hal.enabled", false)
|
||||
+ ? kSystemAudioProviderFactoryInterface : kDefaultAudioProviderFactoryInterface;
|
||||
+ }
|
||||
|
||||
private:
|
||||
IBluetoothTransportInstance* transport_;
|
||||
diff --git a/system/audio_hal_interface/hal_version_manager.cc b/system/audio_hal_interface/hal_version_manager.cc
|
||||
index a2c192f37d..c3d1cf35c2 100644
|
||||
--- a/system/audio_hal_interface/hal_version_manager.cc
|
||||
+++ b/system/audio_hal_interface/hal_version_manager.cc
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <memory>
|
||||
|
||||
#include "aidl/audio_aidl_interfaces.h"
|
||||
+#include "osi/include/properties.h"
|
||||
|
||||
namespace bluetooth {
|
||||
namespace audio {
|
||||
@@ -33,6 +34,12 @@ using ::aidl::android::hardware::bluetooth::audio::
|
||||
|
||||
static const std::string kDefaultAudioProviderFactoryInterface =
|
||||
std::string() + IBluetoothAudioProviderFactory::descriptor + "/default";
|
||||
+static const std::string kSystemAudioProviderFactoryInterface =
|
||||
+ std::string() + IBluetoothAudioProviderFactory::descriptor + "/sysbta";
|
||||
+static inline const std::string audioProviderFactoryInterface() {
|
||||
+ return osi_property_get_bool("persist.bluetooth.system_audio_hal.enabled", false)
|
||||
+ ? kSystemAudioProviderFactoryInterface : kDefaultAudioProviderFactoryInterface;
|
||||
+}
|
||||
|
||||
std::unique_ptr<HalVersionManager> HalVersionManager::instance_ptr =
|
||||
std::make_unique<HalVersionManager>();
|
||||
@@ -92,7 +99,7 @@ HalVersionManager::GetProvidersFactory_2_0() {
|
||||
|
||||
HalVersionManager::HalVersionManager() {
|
||||
if (AServiceManager_checkService(
|
||||
- kDefaultAudioProviderFactoryInterface.c_str()) != nullptr) {
|
||||
+ audioProviderFactoryInterface().c_str()) != nullptr) {
|
||||
hal_version_ = BluetoothAudioHalVersion::VERSION_AIDL_V1;
|
||||
return;
|
||||
}
|
||||
--
|
||||
2.40.1
|
||||
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
From 8ca700fc18d9b276ab89ac2b9996f689fc63b17f Mon Sep 17 00:00:00 2001
|
||||
From: Michael Bestas <mkbestas@lineageos.org>
|
||||
Date: Wed, 30 Oct 2024 19:45:19 +0200
|
||||
Subject: [PATCH] Conditionally use Unix epoch time for build incremental
|
||||
|
||||
Incremental version is used in various places to invalidate caches.
|
||||
Setting BUILD_NUMBER directly causes unnecessary rebuilds due to
|
||||
environment variable changes, so simply set it to Unix epoch unless
|
||||
BUILD_NUMBER is explicitly set.
|
||||
|
||||
Change-Id: Id590df48ae1b73b63039f185644103d66a4bbbb3
|
||||
---
|
||||
core/sysprop.mk | 6 +++++-
|
||||
1 file changed, 5 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/core/sysprop.mk b/core/sysprop.mk
|
||||
index 4c040e4..ccf4e95 100644
|
||||
--- a/core/sysprop.mk
|
||||
+++ b/core/sysprop.mk
|
||||
@@ -75,7 +75,11 @@ define generate-common-build-props
|
||||
echo "ro.$(1).build.id?=$(BUILD_ID)" >> $(2);\
|
||||
echo "ro.$(1).build.tags?=$(BUILD_VERSION_TAGS)" >> $(2);\
|
||||
echo "ro.$(1).build.type=$(TARGET_BUILD_VARIANT)" >> $(2);\
|
||||
- echo "ro.$(1).build.version.incremental=$(BUILD_NUMBER_FROM_FILE)" >> $(2);\
|
||||
+ if [[ $(BUILD_NUMBER_FROM_FILE) =~ ^eng\. ]]; then \
|
||||
+ echo "ro.$(1).build.version.incremental=`$(DATE_FROM_FILE) +%s`" >> $(2);\
|
||||
+ else \
|
||||
+ echo "ro.$(1).build.version.incremental=$(BUILD_NUMBER_FROM_FILE)" >> $(2);\
|
||||
+ fi; \
|
||||
echo "ro.$(1).build.version.release=$(PLATFORM_VERSION_LAST_STABLE)" >> $(2);\
|
||||
echo "ro.$(1).build.version.release_or_codename=$(PLATFORM_VERSION)" >> $(2);\
|
||||
echo "ro.$(1).build.version.sdk=$(PLATFORM_SDK_VERSION)" >> $(2);\
|
||||
--
|
||||
2.48.1
|
||||
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
From 0d846cfe054d24e81f52e971a0aeb89061e1b269 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Bestas <mkbestas@lineageos.org>
|
||||
Date: Wed, 30 Oct 2024 19:53:42 +0200
|
||||
Subject: [PATCH] Conditionally use Unix epoch time for build incremental
|
||||
|
||||
Incremental version is used in various places to invalidate caches.
|
||||
Setting BUILD_NUMBER directly causes unnecessary rebuilds due to
|
||||
environment variable changes, so simply set it to Unix epoch unless
|
||||
BUILD_NUMBER is explicitly set.
|
||||
|
||||
Change-Id: Id590df48ae1b73b63039f185644103d66a4bbbb3
|
||||
---
|
||||
scripts/gen_build_prop.py | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
diff --git a/scripts/gen_build_prop.py b/scripts/gen_build_prop.py
|
||||
index 97dce08..c230400 100644
|
||||
--- a/scripts/gen_build_prop.py
|
||||
+++ b/scripts/gen_build_prop.py
|
||||
@@ -107,6 +107,9 @@ def parse_args():
|
||||
if args.build_thumbprint_file:
|
||||
config["BuildThumbprint"] = args.build_thumbprint_file.read().strip()
|
||||
|
||||
+ if config["BuildNumber"].startswith("eng."):
|
||||
+ config["BuildNumber"] = config["DateUtc"]
|
||||
+
|
||||
append_additional_system_props(args)
|
||||
append_additional_vendor_props(args)
|
||||
append_additional_product_props(args)
|
||||
--
|
||||
2.48.1
|
||||
|
||||
|
|
@ -1,56 +0,0 @@
|
|||
From 4dea053fa9aa1e435cf856107e30fe66983b0ab0 Mon Sep 17 00:00:00 2001
|
||||
From: ponces <ponces26@gmail.com>
|
||||
Date: Mon, 24 Oct 2022 09:38:34 +0100
|
||||
Subject: [PATCH 3/8] voip: Fix high pitched voice on Qualcomm devices
|
||||
|
||||
Change-Id: I6d314912169776b76d07d8c0301ec5249c1870a2
|
||||
---
|
||||
.../common/managerdefinitions/src/Serializer.cpp | 12 +++++++++++-
|
||||
1 file changed, 11 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
|
||||
index 0f7c903..c4474cf 100644
|
||||
--- a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
|
||||
+++ b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
|
||||
@@ -252,6 +252,7 @@ private:
|
||||
std::string mChannelMasksSeparator = ",";
|
||||
std::string mSamplingRatesSeparator = ",";
|
||||
std::string mFlagsSeparator = "|";
|
||||
+ std::string mMixPortName = "";
|
||||
|
||||
// Children: ModulesTraits, VolumeTraits, SurroundSoundTraits (optional)
|
||||
};
|
||||
@@ -426,13 +427,21 @@ PolicySerializer::deserialize<AudioProfileTraits>(
|
||||
std::string samplingRates = getXmlAttribute(cur, Attributes::samplingRates);
|
||||
std::string format = getXmlAttribute(cur, Attributes::format);
|
||||
std::string channels = getXmlAttribute(cur, Attributes::channelMasks);
|
||||
+ ChannelTraits::Collection channelsMask = channelMasksFromString(channels, mChannelMasksSeparator.c_str());
|
||||
+
|
||||
+ // This breaks in-game voice chat and audio in some messaging apps causing it to play with a higher pitch and speed
|
||||
+ bool disableStereoVoip = property_get_bool("persist.sys.phh.disable_stereo_voip", false);
|
||||
+ if (disableStereoVoip && mMixPortName == "voip_rx") {
|
||||
+ ALOGI("%s: disabling stereo support on voip_rx", __func__);
|
||||
+ channelsMask = channelMasksFromString("AUDIO_CHANNEL_OUT_MONO", ",");
|
||||
+ }
|
||||
|
||||
if (mIgnoreVendorExtensions && maybeVendorExtension(format)) {
|
||||
ALOGI("%s: vendor extension format \"%s\" skipped", __func__, format.c_str());
|
||||
return NO_INIT;
|
||||
}
|
||||
AudioProfileTraits::Element profile = new AudioProfile(formatFromString(format, gDynamicFormat),
|
||||
- channelMasksFromString(channels, mChannelMasksSeparator.c_str()),
|
||||
+ channelsMask,
|
||||
samplingRatesFromString(samplingRates, mSamplingRatesSeparator.c_str()));
|
||||
|
||||
profile->setDynamicFormat(profile->getFormat() == gDynamicFormat);
|
||||
@@ -449,6 +458,7 @@ std::variant<status_t, MixPortTraits::Element> PolicySerializer::deserialize<Mix
|
||||
using Attributes = MixPortTraits::Attributes;
|
||||
|
||||
std::string name = getXmlAttribute(child, Attributes::name);
|
||||
+ mMixPortName = name;
|
||||
if (name.empty()) {
|
||||
ALOGE("%s: No %s found", __func__, Attributes::name);
|
||||
return BAD_VALUE;
|
||||
--
|
||||
2.48.1
|
||||
|
||||
|
|
@ -1,131 +0,0 @@
|
|||
From af3c89d5b149e3de06da5669844204c20e697927 Mon Sep 17 00:00:00 2001
|
||||
From: Pierre-Hugues Husson <phh@phh.me>
|
||||
Date: Mon, 5 Aug 2019 18:09:50 +0200
|
||||
Subject: [PATCH 4/8] Fix BT in-call on CAF devices
|
||||
|
||||
See https://github.com/phhusson/treble_experimentations/issues/374
|
||||
|
||||
In Qualcomm's BSP audio_policy_configuration.xml, one route is missing,
|
||||
from primary output and telephony to BT SCO.
|
||||
|
||||
Add it if we detect telephony and bt sco, but no such route.
|
||||
|
||||
Change-Id: Ifea0f88276ec9a0811f3cb1973c4b06f2c82077b
|
||||
---
|
||||
.../managerdefinitions/src/Serializer.cpp | 93 +++++++++++++++++++
|
||||
1 file changed, 93 insertions(+)
|
||||
|
||||
diff --git a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
|
||||
index c4474cf..c1df8f2 100644
|
||||
--- a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
|
||||
+++ b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
|
||||
@@ -676,6 +676,98 @@ std::variant<status_t, RouteTraits::Element> PolicySerializer::deserialize<Route
|
||||
return route;
|
||||
}
|
||||
|
||||
+static void fixupQualcommBtScoRoute(RouteTraits::Collection& routes, DevicePortTraits::Collection& devicePorts, HwModule* ctx) {
|
||||
+ // On many Qualcomm devices, there is a BT SCO Headset Mic => primary input mix
|
||||
+ // But Telephony Rx => BT SCO Headset route is missing
|
||||
+ // When we detect such case, add the missing route
|
||||
+
|
||||
+ // If we have:
|
||||
+ // <route type="mix" sink="Telephony Tx" sources="voice_tx"/>
|
||||
+ // <route type="mix" sink="primary input" sources="Built-In Mic,Built-In Back Mic,Wired Headset Mic,BT SCO Headset Mic"/>
|
||||
+ // <devicePort tagName="BT SCO Headset" type="AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET" role="sink" />
|
||||
+ // And no <route type="mix" sink="BT SCO Headset" />
|
||||
+
|
||||
+ // Add:
|
||||
+ // <route type="mix" sink="BT SCO Headset" sources="primary output,deep_buffer,compressed_offload,Telephony Rx"/>
|
||||
+ bool foundBtScoHeadsetDevice = false;
|
||||
+ for(const auto& device: devicePorts) {
|
||||
+ if(device->getTagName() == "BT SCO Headset") {
|
||||
+ foundBtScoHeadsetDevice = true;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ if(!foundBtScoHeadsetDevice) {
|
||||
+ ALOGE("No BT SCO Headset device found, don't patch policy");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ bool foundTelephony = false;
|
||||
+ bool foundBtScoInput = false;
|
||||
+ bool foundScoHeadsetRoute = false;
|
||||
+ for(const auto& route: routes) {
|
||||
+ ALOGE("Looking at route %d\n", route->getType());
|
||||
+ if(route->getType() != AUDIO_ROUTE_MIX)
|
||||
+ continue;
|
||||
+ auto sink = route->getSink();
|
||||
+ ALOGE("... With sink %s\n", sink->getTagName().c_str());
|
||||
+ if(sink->getTagName() == "Telephony Tx") {
|
||||
+ foundTelephony = true;
|
||||
+ continue;
|
||||
+ }
|
||||
+ if(sink->getTagName() == "BT SCO Headset") {
|
||||
+ foundScoHeadsetRoute = true;
|
||||
+ break;
|
||||
+ }
|
||||
+ for(const auto& source: route->getSources()) {
|
||||
+ ALOGE("... With source %s\n", source->getTagName().c_str());
|
||||
+ if(source->getTagName() == "BT SCO Headset Mic") {
|
||||
+ foundBtScoInput = true;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ //The route we want to add is already there
|
||||
+ ALOGE("Done looking for existing routes");
|
||||
+ if(foundScoHeadsetRoute)
|
||||
+ return;
|
||||
+
|
||||
+ ALOGE("No existing route found... %d %d", foundTelephony ? 1 : 0, foundBtScoInput ? 1 : 0);
|
||||
+ //We couldn't find the routes we assume are required for the function we want to add
|
||||
+ if(!foundTelephony || !foundBtScoInput)
|
||||
+ return;
|
||||
+ ALOGE("Adding our own.");
|
||||
+
|
||||
+ // Add:
|
||||
+ // <route type="mix" sink="BT SCO Headset" sources="primary output,deep_buffer,compressed_offload,Telephony Rx"/>
|
||||
+ AudioRoute *newRoute = new AudioRoute(AUDIO_ROUTE_MIX);
|
||||
+
|
||||
+ auto sink = ctx->findPortByTagName("BT SCO Headset");
|
||||
+ ALOGE("Got sink %p\n", sink.get());
|
||||
+ newRoute->setSink(sink);
|
||||
+
|
||||
+ Vector<sp<PolicyAudioPort>> sources;
|
||||
+ for(const auto& sourceName: {
|
||||
+ "primary output",
|
||||
+ "deep_buffer",
|
||||
+ "compressed_offload",
|
||||
+ "Telephony Rx"
|
||||
+ }) {
|
||||
+ auto source = ctx->findPortByTagName(sourceName);
|
||||
+ ALOGE("Got source %p\n", source.get());
|
||||
+ if (source.get() != nullptr) {
|
||||
+ sources.add(source);
|
||||
+ source->addRoute(newRoute);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ newRoute->setSources(sources);
|
||||
+
|
||||
+ sink->addRoute(newRoute);
|
||||
+
|
||||
+ auto ret = routes.add(newRoute);
|
||||
+ ALOGE("route add returned %zd", ret);
|
||||
+}
|
||||
+
|
||||
template<>
|
||||
std::variant<status_t, ModuleTraits::Element> PolicySerializer::deserialize<ModuleTraits>(
|
||||
const xmlNode *cur, ModuleTraits::PtrSerializingCtx ctx)
|
||||
@@ -743,6 +835,7 @@ std::variant<status_t, ModuleTraits::Element> PolicySerializer::deserialize<Modu
|
||||
if (status != NO_ERROR) {
|
||||
return status;
|
||||
}
|
||||
+ fixupQualcommBtScoRoute(routes, devicePorts, module.get());
|
||||
module->setRoutes(routes);
|
||||
|
||||
for (const xmlNode *children = cur->xmlChildrenNode; children != NULL;
|
||||
--
|
||||
2.48.1
|
||||
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
From 30a90653ced81dc64b52765ff454293893705c7e Mon Sep 17 00:00:00 2001
|
||||
From: Pierre-Hugues Husson <phh@phh.me>
|
||||
Date: Mon, 21 Dec 2020 20:19:11 +0100
|
||||
Subject: [PATCH 5/8] Make camera IDs filter-out optional
|
||||
|
||||
Nowadays most people have Camera 2 apps, and would like to have all
|
||||
cameras, rather than limit which cameras are available.
|
||||
Add a property for that.
|
||||
---
|
||||
.../common/CameraProviderManager.cpp | 14 +++++++++-----
|
||||
1 file changed, 9 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp
|
||||
index 7032db0..b72a16c 100644
|
||||
--- a/services/camera/libcameraservice/common/CameraProviderManager.cpp
|
||||
+++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp
|
||||
@@ -327,7 +327,9 @@ std::vector<std::string> CameraProviderManager::getAPI1CompatibleCameraDeviceIds
|
||||
// API1 app doesn't handle logical and physical camera devices well. So
|
||||
// for each camera facing, only take the first id advertised by HAL in
|
||||
// all [logical, physical1, physical2, ...] id combos, and filter out the rest.
|
||||
- filterLogicalCameraIdsLocked(providerDeviceIds);
|
||||
+ if(!property_get_bool("persist.sys.phh.include_all_cameras", false)) {
|
||||
+ filterLogicalCameraIdsLocked(providerDeviceIds);
|
||||
+ }
|
||||
collectDeviceIdsLocked(providerDeviceIds, publicDeviceIds, systemDeviceIds);
|
||||
}
|
||||
auto sortFunc =
|
||||
@@ -1135,10 +1137,12 @@ SystemCameraKind CameraProviderManager::ProviderInfo::DeviceInfo3::getSystemCame
|
||||
|
||||
// Go through the capabilities and check if it has
|
||||
// ANDROID_REQUEST_AVAILABLE_CAPABILITIES_SYSTEM_CAMERA
|
||||
- for (size_t i = 0; i < entryCap.count; ++i) {
|
||||
- uint8_t capability = entryCap.data.u8[i];
|
||||
- if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_SYSTEM_CAMERA) {
|
||||
- return SystemCameraKind::SYSTEM_ONLY_CAMERA;
|
||||
+ if(!property_get_bool("persist.sys.phh.include_all_cameras", false)) {
|
||||
+ for (size_t i = 0; i < entryCap.count; ++i) {
|
||||
+ uint8_t capability = entryCap.data.u8[i];
|
||||
+ if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_SYSTEM_CAMERA) {
|
||||
+ return SystemCameraKind::SYSTEM_ONLY_CAMERA;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
return SystemCameraKind::PUBLIC;
|
||||
--
|
||||
2.48.1
|
||||
|
||||
|
|
@ -1,82 +0,0 @@
|
|||
From 0dce546c459c5e8aa316996d6e63d2d5c20e79e7 Mon Sep 17 00:00:00 2001
|
||||
From: Pierre-Hugues Husson <phh@phh.me>
|
||||
Date: Fri, 13 Jun 2025 18:32:08 -0400
|
||||
Subject: [PATCH 7/8] Revert "Remove framework support for audio HIDL HAL V5"
|
||||
|
||||
This reverts commit 559e9765c5352686c9b3954a3c930f614c338196.
|
||||
---
|
||||
media/libaudiohal/Android.bp | 1 +
|
||||
media/libaudiohal/FactoryHal.cpp | 3 ++-
|
||||
media/libaudiohal/impl/Android.bp | 26 ++++++++++++++++++++++++++
|
||||
3 files changed, 29 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/media/libaudiohal/Android.bp b/media/libaudiohal/Android.bp
|
||||
index 09f4282..9f37e6c 100644
|
||||
--- a/media/libaudiohal/Android.bp
|
||||
+++ b/media/libaudiohal/Android.bp
|
||||
@@ -23,6 +23,7 @@ cc_library_shared {
|
||||
],
|
||||
|
||||
required: [
|
||||
+ "libaudiohal@5.0",
|
||||
"libaudiohal@6.0",
|
||||
"libaudiohal@7.0",
|
||||
"libaudiohal@7.1",
|
||||
diff --git a/media/libaudiohal/FactoryHal.cpp b/media/libaudiohal/FactoryHal.cpp
|
||||
index 2c30693..15cb297 100644
|
||||
--- a/media/libaudiohal/FactoryHal.cpp
|
||||
+++ b/media/libaudiohal/FactoryHal.cpp
|
||||
@@ -50,11 +50,12 @@ using InterfaceName = std::pair<std::string, std::string>;
|
||||
* This list need to keep sync with AudioHalVersionInfo.VERSIONS in
|
||||
* media/java/android/media/AudioHalVersionInfo.java.
|
||||
*/
|
||||
-static const std::array<AudioHalVersionInfo, 4> sAudioHALVersions = {
|
||||
+static const std::array<AudioHalVersionInfo, 5> sAudioHALVersions = {
|
||||
AudioHalVersionInfo(AudioHalVersionInfo::Type::AIDL, 1, 0),
|
||||
AudioHalVersionInfo(AudioHalVersionInfo::Type::HIDL, 7, 1),
|
||||
AudioHalVersionInfo(AudioHalVersionInfo::Type::HIDL, 7, 0),
|
||||
AudioHalVersionInfo(AudioHalVersionInfo::Type::HIDL, 6, 0),
|
||||
+ AudioHalVersionInfo(AudioHalVersionInfo::Type::HIDL, 5, 0),
|
||||
};
|
||||
|
||||
static const std::map<AudioHalVersionInfo::Type, InterfaceName> sDevicesHALInterfaces = {
|
||||
diff --git a/media/libaudiohal/impl/Android.bp b/media/libaudiohal/impl/Android.bp
|
||||
index 00f3929..3585402 100644
|
||||
--- a/media/libaudiohal/impl/Android.bp
|
||||
+++ b/media/libaudiohal/impl/Android.bp
|
||||
@@ -82,6 +82,32 @@ cc_defaults {
|
||||
],
|
||||
}
|
||||
|
||||
+cc_library_shared {
|
||||
+ name: "libaudiohal@5.0",
|
||||
+ defaults: [
|
||||
+ "libaudiohal_default",
|
||||
+ "libaudiohal_hidl_default",
|
||||
+ ],
|
||||
+ srcs: [
|
||||
+ ":audio_core_hal_client_sources",
|
||||
+ ":audio_effect_hidl_hal_client_sources",
|
||||
+ "EffectsFactoryHalEntry.cpp",
|
||||
+ ],
|
||||
+ shared_libs: [
|
||||
+ "android.hardware.audio.common@5.0",
|
||||
+ "android.hardware.audio.common@5.0-util",
|
||||
+ "android.hardware.audio.effect@5.0",
|
||||
+ "android.hardware.audio.effect@5.0-util",
|
||||
+ "android.hardware.audio@5.0",
|
||||
+ "android.hardware.audio@5.0-util",
|
||||
+ ],
|
||||
+ cflags: [
|
||||
+ "-DMAJOR_VERSION=5",
|
||||
+ "-DMINOR_VERSION=0",
|
||||
+ "-include common/all-versions/VersionMacro.h",
|
||||
+ ],
|
||||
+}
|
||||
+
|
||||
cc_library_shared {
|
||||
name: "libaudiohal@6.0",
|
||||
defaults: [
|
||||
--
|
||||
2.48.1
|
||||
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
From 2a64996bc03b5dafaf66f534550c3cec167e137f Mon Sep 17 00:00:00 2001
|
||||
From: Pierre-Hugues Husson <phh@phh.me>
|
||||
Date: Sat, 21 Jun 2025 16:48:04 -0400
|
||||
Subject: [PATCH 8/8] Tell Unihertz/Agold we are not a GSI. Fixes aux cam on
|
||||
Jelly Max
|
||||
|
||||
Change-Id: I0feb30f978d4fd0b71c731dc3de70fda744099df
|
||||
---
|
||||
services/camera/libcameraservice/Android.bp | 1 +
|
||||
.../common/aidl/AidlProviderInfo.cpp | 13 +++++++++++++
|
||||
2 files changed, 14 insertions(+)
|
||||
|
||||
diff --git a/services/camera/libcameraservice/Android.bp b/services/camera/libcameraservice/Android.bp
|
||||
index f9cbc0e..b114caa 100644
|
||||
--- a/services/camera/libcameraservice/Android.bp
|
||||
+++ b/services/camera/libcameraservice/Android.bp
|
||||
@@ -116,6 +116,7 @@ cc_defaults {
|
||||
"android.hardware.camera.provider@2.6",
|
||||
"android.hardware.camera.provider@2.7",
|
||||
"android.hardware.camera.provider-V3-ndk",
|
||||
+ "vendor.mediatek.hardware.agolddaemon-V1-ndk",
|
||||
"libaidlcommonsupport",
|
||||
"libbinderthreadstateutils",
|
||||
"libcameraservice_device_independent",
|
||||
diff --git a/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp b/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp
|
||||
index 8b66e4c..3a20699 100644
|
||||
--- a/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp
|
||||
+++ b/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp
|
||||
@@ -34,6 +34,8 @@
|
||||
#include <utils/SessionConfigurationUtils.h>
|
||||
#include <utils/Trace.h>
|
||||
|
||||
+#include <aidl/vendor/mediatek/hardware/agolddaemon/IAgoldDaemon.h>
|
||||
+
|
||||
namespace {
|
||||
const bool kEnableLazyHal(property_get_bool("ro.camera.enableLazyHal", false));
|
||||
} // anonymous namespace
|
||||
@@ -159,6 +161,17 @@ status_t AidlProviderInfo::initializeAidlProvider(
|
||||
__FUNCTION__, mProviderName.c_str(), mDeviceState);
|
||||
notifyDeviceStateChange(currentDeviceState);
|
||||
|
||||
+
|
||||
+ if (true) {
|
||||
+ auto svc = aidl::vendor::mediatek::hardware::agolddaemon::IAgoldDaemon::fromBinder(
|
||||
+ ndk::SpAIBinder(AServiceManager_checkService("vendor.mediatek.hardware.agolddaemon.IAgoldDaemon/default")));
|
||||
+
|
||||
+ if (svc != nullptr) {
|
||||
+ ALOGE("Got agold aidl hal");
|
||||
+ svc->setNotGsi("NotGsi");
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
res = setUpVendorTags();
|
||||
if (res != OK) {
|
||||
ALOGE("%s: Unable to set up vendor tags from provider '%s'",
|
||||
--
|
||||
2.48.1
|
||||
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
From fd5ebbeaa37e185e6f64f421308348dff61fe6b4 Mon Sep 17 00:00:00 2001
|
||||
From: Andy CrossGate Yan <GeForce8800Ultra@gmail.com>
|
||||
Date: Wed, 2 Aug 2023 20:59:53 +0800
|
||||
Subject: [PATCH 04/11] Restore getSimStateForSlotIndex in SubscriptionManager
|
||||
|
||||
MTK IMS still needs it here
|
||||
|
||||
Change-Id: I41bac57c68055f369232359a464642daab94403b
|
||||
---
|
||||
.../android/telephony/SubscriptionManager.java | 14 ++++++++++++++
|
||||
1 file changed, 14 insertions(+)
|
||||
|
||||
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
|
||||
index 8b926fadb456..8aff3c6228d4 100644
|
||||
--- a/telephony/java/android/telephony/SubscriptionManager.java
|
||||
+++ b/telephony/java/android/telephony/SubscriptionManager.java
|
||||
@@ -2970,6 +2970,20 @@ public class SubscriptionManager {
|
||||
return TelephonyManager.getDefault().isNetworkRoaming(subId);
|
||||
}
|
||||
|
||||
+ /**
|
||||
+ * Returns a constant indicating the state of sim for the slot index.
|
||||
+ *
|
||||
+ * @param slotIndex Logical SIM slot index.
|
||||
+ *
|
||||
+ * @see TelephonyManager.SimState
|
||||
+ *
|
||||
+ * @hide
|
||||
+ */
|
||||
+ @TelephonyManager.SimState
|
||||
+ public static int getSimStateForSlotIndex(int slotIndex) {
|
||||
+ return TelephonyManager.getSimStateForSlotIndex(slotIndex);
|
||||
+ }
|
||||
+
|
||||
/**
|
||||
* Set a field in the subscription database. Note not all fields are supported.
|
||||
*
|
||||
--
|
||||
2.48.1
|
||||
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
From fd4089abdb370931ce525d607d47d1cf0fbaf6e4 Mon Sep 17 00:00:00 2001
|
||||
From: Andy CrossGate Yan <GeForce8800Ultra@gmail.com>
|
||||
Date: Sat, 12 Aug 2023 20:11:17 +0800
|
||||
Subject: [PATCH 05/11] Add runWithCleanCallingIdentity variant with both
|
||||
executor and return value
|
||||
|
||||
This complements the fixup to ImsPhoneCallTracker (in fw/o/t) for U
|
||||
|
||||
Change-Id: If444290787025e130dce4bdeaf92372ae32793fe
|
||||
---
|
||||
.../telephony/util/TelephonyUtils.java | 30 +++++++++++++++++++
|
||||
1 file changed, 30 insertions(+)
|
||||
|
||||
diff --git a/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java b/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java
|
||||
index 4224338918f4..3bbecf0f2065 100644
|
||||
--- a/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java
|
||||
+++ b/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java
|
||||
@@ -47,7 +47,9 @@ import com.android.internal.telephony.ITelephony;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
+import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
+import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Supplier;
|
||||
@@ -159,6 +161,34 @@ public final class TelephonyUtils {
|
||||
}
|
||||
}
|
||||
|
||||
+ /**
|
||||
+ * Convenience method for running the provided action in the provided
|
||||
+ * executor enclosed in
|
||||
+ * {@link Binder#clearCallingIdentity}/{@link Binder#restoreCallingIdentity} and return
|
||||
+ * the result.
|
||||
+ *
|
||||
+ * Any exception thrown by the given action will need to be handled by caller.
|
||||
+ *
|
||||
+ */
|
||||
+ public static <T> T runWithCleanCallingIdentity(
|
||||
+ @NonNull Supplier<T> action, @NonNull Executor executor) {
|
||||
+ if (action != null) {
|
||||
+ if (executor != null) {
|
||||
+ try {
|
||||
+ return CompletableFuture.supplyAsync(
|
||||
+ () -> runWithCleanCallingIdentity(action), executor).get();
|
||||
+ } catch (ExecutionException | InterruptedException e) {
|
||||
+ Log.w(LOG_TAG, "TelephonyUtils : runWithCleanCallingIdentity exception: "
|
||||
+ + e.getMessage());
|
||||
+ return null;
|
||||
+ }
|
||||
+ } else {
|
||||
+ return runWithCleanCallingIdentity(action);
|
||||
+ }
|
||||
+ }
|
||||
+ return null;
|
||||
+ }
|
||||
+
|
||||
/**
|
||||
* Filter values in bundle to only basic types.
|
||||
*/
|
||||
--
|
||||
2.48.1
|
||||
|
||||
|
|
@ -1,150 +0,0 @@
|
|||
From b9c9a170e01a5f390e98a512635788398e0c887b Mon Sep 17 00:00:00 2001
|
||||
From: dhacker29 <dhackerdvm@gmail.com>
|
||||
Date: Tue, 24 Nov 2015 01:53:47 -0500
|
||||
Subject: [PATCH 06/11] fw/b: Use ro.build.version.incremental to signal OTA
|
||||
upgrades
|
||||
|
||||
Co-authored-by: maxwen <max.weninger@gmail.com>
|
||||
Co-authored-by: Sam Mortimer <sam@mortimer.me.uk>
|
||||
Co-authored-by: Wang Han <416810799@qq.com>
|
||||
Change-Id: If0eb969ba509981f9209ffa37a949d9042ef4c2a
|
||||
---
|
||||
core/java/android/app/admin/SystemUpdateInfo.java | 4 ++--
|
||||
core/java/android/content/pm/PackagePartitions.java | 2 +-
|
||||
.../java/com/android/server/appwidget/AppWidgetXmlUtil.java | 4 ++--
|
||||
.../java/com/android/server/pm/PackageManagerService.java | 5 +++--
|
||||
.../com/android/server/pm/PackageManagerServiceUtils.java | 3 +--
|
||||
services/core/java/com/android/server/pm/Settings.java | 2 +-
|
||||
.../core/java/com/android/server/pm/ShortcutService.java | 2 +-
|
||||
7 files changed, 11 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/core/java/android/app/admin/SystemUpdateInfo.java b/core/java/android/app/admin/SystemUpdateInfo.java
|
||||
index 9e6c91f4ec31..7459b0e05e3a 100644
|
||||
--- a/core/java/android/app/admin/SystemUpdateInfo.java
|
||||
+++ b/core/java/android/app/admin/SystemUpdateInfo.java
|
||||
@@ -133,7 +133,7 @@ public final class SystemUpdateInfo implements Parcelable {
|
||||
out.startTag(null, tag);
|
||||
out.attributeLong(null, ATTR_RECEIVED_TIME, mReceivedTime);
|
||||
out.attributeInt(null, ATTR_SECURITY_PATCH_STATE, mSecurityPatchState);
|
||||
- out.attribute(null, ATTR_ORIGINAL_BUILD , Build.FINGERPRINT);
|
||||
+ out.attribute(null, ATTR_ORIGINAL_BUILD , Build.VERSION.INCREMENTAL);
|
||||
out.endTag(null, tag);
|
||||
}
|
||||
|
||||
@@ -142,7 +142,7 @@ public final class SystemUpdateInfo implements Parcelable {
|
||||
public static SystemUpdateInfo readFromXml(TypedXmlPullParser parser) {
|
||||
// If an OTA has been applied (build fingerprint has changed), discard stale info.
|
||||
final String buildFingerprint = parser.getAttributeValue(null, ATTR_ORIGINAL_BUILD );
|
||||
- if (!Build.FINGERPRINT.equals(buildFingerprint)) {
|
||||
+ if (!Build.VERSION.INCREMENTAL.equals(buildFingerprint)) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
diff --git a/core/java/android/content/pm/PackagePartitions.java b/core/java/android/content/pm/PackagePartitions.java
|
||||
index ff80e614be58..da3b68ecf789 100644
|
||||
--- a/core/java/android/content/pm/PackagePartitions.java
|
||||
+++ b/core/java/android/content/pm/PackagePartitions.java
|
||||
@@ -131,7 +131,7 @@ public class PackagePartitions {
|
||||
final String partitionName = SYSTEM_PARTITIONS.get(i).getName();
|
||||
digestProperties[i] = "ro." + partitionName + ".build.fingerprint";
|
||||
}
|
||||
- digestProperties[SYSTEM_PARTITIONS.size()] = "ro.build.fingerprint"; // build fingerprint
|
||||
+ digestProperties[SYSTEM_PARTITIONS.size()] = "ro.build.version.incremental";
|
||||
return SystemProperties.digestOf(digestProperties);
|
||||
}
|
||||
|
||||
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetXmlUtil.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetXmlUtil.java
|
||||
index ce9130ad5cbf..737ecae1cc94 100644
|
||||
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetXmlUtil.java
|
||||
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetXmlUtil.java
|
||||
@@ -117,7 +117,7 @@ public class AppWidgetXmlUtil {
|
||||
out.attributeInt(null, ATTR_WIDGET_FEATURES, info.widgetFeatures);
|
||||
out.attributeInt(null, ATTR_DESCRIPTION_RES, info.descriptionRes);
|
||||
out.attributeBoolean(null, ATTR_PROVIDER_INHERITANCE, info.isExtendedFromAppWidgetProvider);
|
||||
- out.attribute(null, ATTR_OS_FINGERPRINT, Build.FINGERPRINT);
|
||||
+ out.attribute(null, ATTR_OS_FINGERPRINT, Build.VERSION.INCREMENTAL);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -128,7 +128,7 @@ public class AppWidgetXmlUtil {
|
||||
@NonNull final TypedXmlPullParser parser) {
|
||||
Objects.requireNonNull(parser);
|
||||
final String fingerprint = parser.getAttributeValue(null, ATTR_OS_FINGERPRINT);
|
||||
- if (!Build.FINGERPRINT.equals(fingerprint)) {
|
||||
+ if (!Build.VERSION.INCREMENTAL.equals(fingerprint)) {
|
||||
return null;
|
||||
}
|
||||
final AppWidgetProviderInfo info = new AppWidgetProviderInfo();
|
||||
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
|
||||
index 64a9381ad342..2d9abbb2dfdd 100644
|
||||
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
|
||||
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
|
||||
@@ -2243,7 +2243,8 @@ public class PackageManagerService implements PackageSender, TestUtilityService
|
||||
if (mIsUpgrade) {
|
||||
PackageManagerServiceUtils.logCriticalInfo(Log.INFO,
|
||||
"Upgrading from " + ver.fingerprint + " (" + ver.buildFingerprint + ") to "
|
||||
- + PackagePartitions.FINGERPRINT + " (" + Build.FINGERPRINT + ")");
|
||||
+ + PackagePartitions.FINGERPRINT
|
||||
+ + " (" + Build.VERSION.INCREMENTAL + ")");
|
||||
}
|
||||
mPriorSdkVersion = mIsUpgrade ? ver.sdkVersion : -1;
|
||||
mPriorSdkVersionFull = mIsUpgrade ? ver.sdkVersionFull : -1;
|
||||
@@ -2402,7 +2403,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService
|
||||
| Installer.FLAG_CLEAR_APP_DATA_KEEP_ART_PROFILES);
|
||||
}
|
||||
}
|
||||
- ver.buildFingerprint = Build.FINGERPRINT;
|
||||
+ ver.buildFingerprint = Build.VERSION.INCREMENTAL;
|
||||
ver.fingerprint = PackagePartitions.FINGERPRINT;
|
||||
}
|
||||
|
||||
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
|
||||
index fbdf9af3d068..121dc089d666 100644
|
||||
--- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
|
||||
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
|
||||
@@ -1332,8 +1332,6 @@ public class PackageManagerServiceUtils {
|
||||
// that starts with "eng." to signify that this is an engineering build and not
|
||||
// destined for release.
|
||||
if (isUserDebugBuild && incrementalVersion.startsWith("eng.")) {
|
||||
- Slog.w(TAG, "Wiping cache directory because the system partition changed.");
|
||||
-
|
||||
// Heuristic: If the /system directory has been modified recently due to an "adb sync"
|
||||
// or a regular make, then blow away the cache. Note that mtimes are *NOT* reliable
|
||||
// in general and should not be used for production changes. In this specific case,
|
||||
@@ -1341,6 +1339,7 @@ public class PackageManagerServiceUtils {
|
||||
File frameworkDir =
|
||||
new File(Environment.getRootDirectory(), "framework");
|
||||
if (cacheDir.lastModified() < frameworkDir.lastModified()) {
|
||||
+ Slog.w(TAG, "Wiping cache directory because the system partition changed.");
|
||||
FileUtils.deleteContents(cacheBaseDir);
|
||||
cacheDir = FileUtils.createDir(cacheBaseDir, cacheName);
|
||||
}
|
||||
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
|
||||
index 960564b6955f..d4bc94593c38 100644
|
||||
--- a/services/core/java/com/android/server/pm/Settings.java
|
||||
+++ b/services/core/java/com/android/server/pm/Settings.java
|
||||
@@ -514,7 +514,7 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile
|
||||
}
|
||||
|
||||
databaseVersion = CURRENT_DATABASE_VERSION;
|
||||
- buildFingerprint = Build.FINGERPRINT;
|
||||
+ buildFingerprint = Build.VERSION.INCREMENTAL;
|
||||
fingerprint = PackagePartitions.FINGERPRINT;
|
||||
}
|
||||
}
|
||||
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
|
||||
index 65ee4e7e7574..be1b3c17f598 100644
|
||||
--- a/services/core/java/com/android/server/pm/ShortcutService.java
|
||||
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
|
||||
@@ -5104,7 +5104,7 @@ public class ShortcutService extends IShortcutService.Stub {
|
||||
|
||||
// Injection point.
|
||||
String injectBuildFingerprint() {
|
||||
- return Build.FINGERPRINT;
|
||||
+ return Build.VERSION.INCREMENTAL;
|
||||
}
|
||||
|
||||
// Injection point.
|
||||
--
|
||||
2.48.1
|
||||
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
From d9532e977969b9a1b47986db5191cdfa2cdc9b24 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Cai <peter@typeblog.net>
|
||||
Date: Sat, 21 Dec 2024 11:04:35 -0500
|
||||
Subject: [PATCH 07/11] Add support for treating virtual biometric sensors as
|
||||
real ones
|
||||
|
||||
This happens on Unihertz Jelly Max. They forgot to change their sensor
|
||||
instance name from "virtual" to something else.
|
||||
|
||||
Change-Id: I106d41cd078e6b1e354c72ec35fa240a44397c5e
|
||||
---
|
||||
.../fingerprint/FingerprintSensorConfigurations.java | 7 ++++++-
|
||||
1 file changed, 6 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/core/java/android/hardware/fingerprint/FingerprintSensorConfigurations.java b/core/java/android/hardware/fingerprint/FingerprintSensorConfigurations.java
|
||||
index 586830c8d189..d7fcfdb6df2b 100644
|
||||
--- a/core/java/android/hardware/fingerprint/FingerprintSensorConfigurations.java
|
||||
+++ b/core/java/android/hardware/fingerprint/FingerprintSensorConfigurations.java
|
||||
@@ -29,6 +29,7 @@ import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceManager;
|
||||
+import android.os.SystemProperties;
|
||||
import android.util.Log;
|
||||
import android.util.Slog;
|
||||
|
||||
@@ -172,6 +173,10 @@ public class FingerprintSensorConfigurations implements Parcelable {
|
||||
* @return real fqName
|
||||
*/
|
||||
public static String remapFqName(String fqName) {
|
||||
+ if (SystemProperties.getBoolean("persist.sys.phh.virtual_sensors_are_real", false)) {
|
||||
+ return fqName;
|
||||
+ }
|
||||
+
|
||||
if (!fqName.contains(IFingerprint.DESCRIPTOR + "/virtual")) {
|
||||
return fqName; //no remap needed for real hardware HAL
|
||||
} else {
|
||||
@@ -185,7 +190,7 @@ public class FingerprintSensorConfigurations implements Parcelable {
|
||||
* @return aidl interface
|
||||
*/
|
||||
public static IFingerprint getIFingerprint(String fqName) {
|
||||
- if (fqName.contains("virtual")) {
|
||||
+ if (fqName.contains("virtual") && !SystemProperties.getBoolean("persist.sys.phh.virtual_sensors_are_real", false)) {
|
||||
String fqNameMapped = remapFqName(fqName);
|
||||
Slog.i(TAG, "getIFingerprint fqName is mapped: " + fqName + "->" + fqNameMapped);
|
||||
try {
|
||||
--
|
||||
2.48.1
|
||||
|
||||
|
|
@ -1,87 +0,0 @@
|
|||
From a8bf72679c4d49b733f792eab2c6035e3ad2e563 Mon Sep 17 00:00:00 2001
|
||||
From: Pranav Vashi <neobuddy89@gmail.com>
|
||||
Date: Sat, 21 Sep 2024 13:44:09 +0530
|
||||
Subject: [PATCH 08/11] WebView: Add check before setting default or fallback
|
||||
provider
|
||||
|
||||
Signed-off-by: Pranav Vashi <neobuddy89@gmail.com>
|
||||
---
|
||||
.../webkit/WebViewUpdateServiceImpl2.java | 34 ++++++++++++++-----
|
||||
1 file changed, 26 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl2.java b/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl2.java
|
||||
index a5a02cdedf97..86a9de980217 100644
|
||||
--- a/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl2.java
|
||||
+++ b/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl2.java
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.android.server.webkit;
|
||||
|
||||
+import android.app.AppGlobals;
|
||||
import android.annotation.Nullable;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
@@ -112,7 +113,7 @@ class WebViewUpdateServiceImpl2 {
|
||||
|
||||
WebViewProviderInfo defaultProvider = null;
|
||||
for (WebViewProviderInfo provider : webviewProviders) {
|
||||
- if (provider.availableByDefault) {
|
||||
+ if (provider.availableByDefault && isPackageAvailable(provider.packageName)) {
|
||||
defaultProvider = provider;
|
||||
break;
|
||||
}
|
||||
@@ -181,6 +182,15 @@ class WebViewUpdateServiceImpl2 {
|
||||
}
|
||||
}
|
||||
|
||||
+ private static boolean isPackageAvailable(String packageName) {
|
||||
+ try {
|
||||
+ AppGlobals.getInitialApplication().getPackageManager().getPackageInfo(packageName, 0);
|
||||
+ return true;
|
||||
+ } catch (NameNotFoundException e) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
private boolean shouldTriggerRepairLocked() {
|
||||
if (mAttemptedToRepairBefore) {
|
||||
return false;
|
||||
@@ -207,12 +217,20 @@ class WebViewUpdateServiceImpl2 {
|
||||
}
|
||||
mAttemptedToRepairBefore = true;
|
||||
}
|
||||
- Slog.w(
|
||||
- TAG,
|
||||
- "No provider available for all users, trying to install and enable "
|
||||
- + mDefaultProvider.packageName);
|
||||
- mSystemInterface.installExistingPackageForAllUsers(mDefaultProvider.packageName);
|
||||
- mSystemInterface.enablePackageForAllUsers(mDefaultProvider.packageName, true);
|
||||
+
|
||||
+ WebViewProviderInfo[] webviewProviders = mSystemInterface.getWebViewPackages();
|
||||
+ WebViewProviderInfo fallbackProvider = getFallbackProvider(webviewProviders);
|
||||
+ if (fallbackProvider != null) {
|
||||
+ Slog.w(TAG, "No valid provider, trying to install and enable "
|
||||
+ + fallbackProvider.packageName);
|
||||
+ mSystemInterface.installExistingPackageForAllUsers(fallbackProvider.packageName);
|
||||
+ mSystemInterface.enablePackageForAllUsers(fallbackProvider.packageName, true);
|
||||
+ } else {
|
||||
+ Slog.w(TAG, "No provider available for all users, trying to install and enable "
|
||||
+ + mDefaultProvider.packageName);
|
||||
+ mSystemInterface.installExistingPackageForAllUsers(mDefaultProvider.packageName);
|
||||
+ mSystemInterface.enablePackageForAllUsers(mDefaultProvider.packageName, true);
|
||||
+ }
|
||||
}
|
||||
|
||||
public void prepareWebViewInSystemServer() {
|
||||
@@ -690,7 +708,7 @@ class WebViewUpdateServiceImpl2 {
|
||||
*/
|
||||
private static WebViewProviderInfo getFallbackProvider(WebViewProviderInfo[] webviewPackages) {
|
||||
for (WebViewProviderInfo provider : webviewPackages) {
|
||||
- if (provider.isFallback) {
|
||||
+ if (provider.isFallback && isPackageAvailable(provider.packageName)) {
|
||||
return provider;
|
||||
}
|
||||
}
|
||||
--
|
||||
2.48.1
|
||||
|
||||
|
|
@ -1,237 +0,0 @@
|
|||
From 8bcf24fb910f67331a33e3ef1d5c1de87f30617a Mon Sep 17 00:00:00 2001
|
||||
From: LuK1337 <priv.luk@gmail.com>
|
||||
Date: Mon, 19 Feb 2024 16:20:04 +0100
|
||||
Subject: [PATCH 09/11] Allow signature spoofing for microG Companion/Services
|
||||
|
||||
This patch enables signature spoofing when the following conditions are
|
||||
met:
|
||||
* Build is debuggable (userdebug/eng)
|
||||
* Package name is com.android.vending or com.google.android.gms
|
||||
* Package is signed with microG release keys
|
||||
* Fake signature is correct
|
||||
|
||||
Additionally, we let these apps be forceQueryable if they so desire.
|
||||
|
||||
Change-Id: I8fc82ed266a2cc59636b662c7ea7e29c94f509b5
|
||||
---
|
||||
.../com/android/server/pm/AppsFilterImpl.java | 2 +
|
||||
.../com/android/server/pm/ComputerEngine.java | 55 +++++++++++++++++++
|
||||
services/core/jni/Android.bp | 7 +++
|
||||
.../com_android_server_pm_ComputerEngine.cpp | 38 +++++++++++++
|
||||
services/core/jni/onload.cpp | 2 +
|
||||
5 files changed, 104 insertions(+)
|
||||
create mode 100644 services/core/jni/com_android_server_pm_ComputerEngine.cpp
|
||||
|
||||
diff --git a/services/core/java/com/android/server/pm/AppsFilterImpl.java b/services/core/java/com/android/server/pm/AppsFilterImpl.java
|
||||
index 319e09216208..135fb7b8b22e 100644
|
||||
--- a/services/core/java/com/android/server/pm/AppsFilterImpl.java
|
||||
+++ b/services/core/java/com/android/server/pm/AppsFilterImpl.java
|
||||
@@ -36,6 +36,7 @@ import static com.android.server.pm.AppsFilterUtils.canQueryAsUpdateOwner;
|
||||
import static com.android.server.pm.AppsFilterUtils.canQueryViaComponents;
|
||||
import static com.android.server.pm.AppsFilterUtils.canQueryViaPackage;
|
||||
import static com.android.server.pm.AppsFilterUtils.canQueryViaUsesLibrary;
|
||||
+import static com.android.server.pm.ComputerEngine.isMicrogSigned;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
@@ -608,6 +609,7 @@ public final class AppsFilterImpl extends AppsFilterLocked implements Watchable,
|
||||
newIsForceQueryable = mForceQueryable.contains(newPkgSetting.getAppId())
|
||||
/* shared user that is already force queryable */
|
||||
|| newPkgSetting.isForceQueryableOverride() /* adb override */
|
||||
+ || (newPkg.isForceQueryable() && isMicrogSigned(newPkg))
|
||||
|| (newPkgSetting.isSystem() && (mSystemAppsQueryable
|
||||
|| newPkg.isForceQueryable()
|
||||
|| ArrayUtils.contains(mForceQueryableByDevicePackageNames,
|
||||
diff --git a/services/core/java/com/android/server/pm/ComputerEngine.java b/services/core/java/com/android/server/pm/ComputerEngine.java
|
||||
index 3f0c0e1aead4..b45c45f4feb1 100644
|
||||
--- a/services/core/java/com/android/server/pm/ComputerEngine.java
|
||||
+++ b/services/core/java/com/android/server/pm/ComputerEngine.java
|
||||
@@ -103,6 +103,7 @@ import android.content.pm.UserPackage;
|
||||
import android.content.pm.VersionedPackage;
|
||||
import android.os.Binder;
|
||||
import android.os.Build;
|
||||
+import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.os.ParcelableException;
|
||||
import android.os.PatternMatcher;
|
||||
@@ -175,6 +176,7 @@ import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
+import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
@@ -420,6 +422,10 @@ public class ComputerEngine implements Computer {
|
||||
private final PackageManagerInternal.ExternalSourcesPolicy mExternalSourcesPolicy;
|
||||
private final CrossProfileIntentResolverEngine mCrossProfileIntentResolverEngine;
|
||||
|
||||
+ // Signatures used by microG
|
||||
+ private static final Signature MICROG_FAKE_SIGNATURE = new Signature("308204433082032ba003020102020900c2e08746644a308d300d06092a864886f70d01010405003074310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e205669657731143012060355040a130b476f6f676c6520496e632e3110300e060355040b1307416e64726f69643110300e06035504031307416e64726f6964301e170d3038303832313233313333345a170d3336303130373233313333345a3074310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e205669657731143012060355040a130b476f6f676c6520496e632e3110300e060355040b1307416e64726f69643110300e06035504031307416e64726f696430820120300d06092a864886f70d01010105000382010d00308201080282010100ab562e00d83ba208ae0a966f124e29da11f2ab56d08f58e2cca91303e9b754d372f640a71b1dcb130967624e4656a7776a92193db2e5bfb724a91e77188b0e6a47a43b33d9609b77183145ccdf7b2e586674c9e1565b1f4c6a5955bff251a63dabf9c55c27222252e875e4f8154a645f897168c0b1bfc612eabf785769bb34aa7984dc7e2ea2764cae8307d8c17154d7ee5f64a51a44a602c249054157dc02cd5f5c0e55fbef8519fbe327f0b1511692c5a06f19d18385f5c4dbc2d6b93f68cc2979c70e18ab93866b3bd5db8999552a0e3b4c99df58fb918bedc182ba35e003c1b4b10dd244a8ee24fffd333872ab5221985edab0fc0d0b145b6aa192858e79020103a381d93081d6301d0603551d0e04160414c77d8cc2211756259a7fd382df6be398e4d786a53081a60603551d2304819e30819b8014c77d8cc2211756259a7fd382df6be398e4d786a5a178a4763074310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e205669657731143012060355040a130b476f6f676c6520496e632e3110300e060355040b1307416e64726f69643110300e06035504031307416e64726f6964820900c2e08746644a308d300c0603551d13040530030101ff300d06092a864886f70d010104050003820101006dd252ceef85302c360aaace939bcff2cca904bb5d7a1661f8ae46b2994204d0ff4a68c7ed1a531ec4595a623ce60763b167297a7ae35712c407f208f0cb109429124d7b106219c084ca3eb3f9ad5fb871ef92269a8be28bf16d44c8d9a08e6cb2f005bb3fe2cb96447e868e731076ad45b33f6009ea19c161e62641aa99271dfd5228c5c587875ddb7f452758d661f6cc0cccb7352e424cc4365c523532f7325137593c4ae341f4db41edda0d0b1071a7c440f0fe9ea01cb627ca674369d084bd2fd911ff06cdbf2cfa10dc0f893ae35762919048c7efc64c7144178342f70581c9de573af55b390dd7fdb9418631895d5f759f30112687ff621410c069308a");
|
||||
+ private static final Signature MICROG_REAL_SIGNATURE = new Signature("308202ed308201d5a003020102020426ffa009300d06092a864886f70d01010b05003027310b300906035504061302444531183016060355040a130f4e4f47415050532050726f6a656374301e170d3132313030363132303533325a170d3337303933303132303533325a3027310b300906035504061302444531183016060355040a130f4e4f47415050532050726f6a65637430820122300d06092a864886f70d01010105000382010f003082010a02820101009a8d2a5336b0eaaad89ce447828c7753b157459b79e3215dc962ca48f58c2cd7650df67d2dd7bda0880c682791f32b35c504e43e77b43c3e4e541f86e35a8293a54fb46e6b16af54d3a4eda458f1a7c8bc1b7479861ca7043337180e40079d9cdccb7e051ada9b6c88c9ec635541e2ebf0842521c3024c826f6fd6db6fd117c74e859d5af4db04448965ab5469b71ce719939a06ef30580f50febf96c474a7d265bb63f86a822ff7b643de6b76e966a18553c2858416cf3309dd24278374bdd82b4404ef6f7f122cec93859351fc6e5ea947e3ceb9d67374fe970e593e5cd05c905e1d24f5a5484f4aadef766e498adf64f7cf04bddd602ae8137b6eea40722d0203010001a321301f301d0603551d0e04160414110b7aa9ebc840b20399f69a431f4dba6ac42a64300d06092a864886f70d01010b0500038201010007c32ad893349cf86952fb5a49cfdc9b13f5e3c800aece77b2e7e0e9c83e34052f140f357ec7e6f4b432dc1ed542218a14835acd2df2deea7efd3fd5e8f1c34e1fb39ec6a427c6e6f4178b609b369040ac1f8844b789f3694dc640de06e44b247afed11637173f36f5886170fafd74954049858c6096308fc93c1bc4dd5685fa7a1f982a422f2a3b36baa8c9500474cf2af91c39cbec1bc898d10194d368aa5e91f1137ec115087c31962d8f76cd120d28c249cf76f4c70f5baa08c70a7234ce4123be080cee789477401965cfe537b924ef36747e8caca62dfefdd1a6288dcb1c4fd2aaa6131a7ad254e9742022cfd597d2ca5c660ce9e41ff537e5a4041e37");
|
||||
+
|
||||
// PackageManagerService attributes that are primitives are referenced through the
|
||||
// pms object directly. Primitives are the only attributes so referenced.
|
||||
protected final PackageManagerService mService;
|
||||
@@ -1476,6 +1482,49 @@ public class ComputerEngine implements Computer {
|
||||
return result;
|
||||
}
|
||||
|
||||
+ private static native boolean isDebuggable();
|
||||
+
|
||||
+ public static boolean isMicrogSigned(AndroidPackage p) {
|
||||
+ if (!isDebuggable()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ // Allowlist the following apps:
|
||||
+ // * com.android.vending - microG Companion
|
||||
+ // * com.google.android.gms - microG Services
|
||||
+ if (!p.getPackageName().equals("com.android.vending") &&
|
||||
+ !p.getPackageName().equals("com.google.android.gms")) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ return Signature.areExactMatch(
|
||||
+ p.getSigningDetails(), new Signature[]{MICROG_REAL_SIGNATURE});
|
||||
+ }
|
||||
+
|
||||
+ private static Optional<Signature> generateFakeSignature(AndroidPackage p) {
|
||||
+ if (!isMicrogSigned(p)) {
|
||||
+ return Optional.empty();
|
||||
+ }
|
||||
+
|
||||
+ Bundle metadata = p.getMetaData();
|
||||
+ if (metadata == null) {
|
||||
+ return Optional.empty();
|
||||
+ }
|
||||
+
|
||||
+ String fakeSignatureStr = metadata.getString("fake-signature");
|
||||
+ if (TextUtils.isEmpty(fakeSignatureStr)) {
|
||||
+ return Optional.empty();
|
||||
+ }
|
||||
+
|
||||
+ // Only MICROG_FAKE_SIGNATURE can be faked
|
||||
+ Signature fakeSignature = new Signature(fakeSignatureStr);
|
||||
+ if (!fakeSignature.equals(MICROG_FAKE_SIGNATURE)) {
|
||||
+ return Optional.empty();
|
||||
+ }
|
||||
+
|
||||
+ return Optional.of(fakeSignature);
|
||||
+ }
|
||||
+
|
||||
public final PackageInfo generatePackageInfo(PackageStateInternal ps,
|
||||
@PackageManager.PackageInfoFlagsBits long flags, int userId) {
|
||||
if (!mUserManager.exists(userId)) return null;
|
||||
@@ -1531,6 +1580,7 @@ public class ComputerEngine implements Computer {
|
||||
mApexManager.getActivePackageNameForApexModuleName(apexModuleName));
|
||||
}
|
||||
}
|
||||
+
|
||||
if (Flags.verificationService()) {
|
||||
final DeveloperVerificationStatusInternal developerVerificationStatusInternal =
|
||||
ps.getDeveloperVerificationStatusInternal();
|
||||
@@ -1539,6 +1589,11 @@ public class ComputerEngine implements Computer {
|
||||
developerVerificationStatusInternal.isAppMetadataVerified());
|
||||
}
|
||||
}
|
||||
+
|
||||
+ generateFakeSignature(p).ifPresent(fakeSignature -> {
|
||||
+ packageInfo.signatures = new Signature[]{fakeSignature};
|
||||
+ });
|
||||
+
|
||||
return packageInfo;
|
||||
} else if ((flags & (MATCH_UNINSTALLED_PACKAGES | MATCH_ARCHIVED_PACKAGES)) != 0
|
||||
&& PackageUserStateUtils.isAvailable(state, flags)) {
|
||||
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
|
||||
index 6bd4e821b3d7..109abd5330be 100644
|
||||
--- a/services/core/jni/Android.bp
|
||||
+++ b/services/core/jni/Android.bp
|
||||
@@ -70,6 +70,7 @@ cc_library_static {
|
||||
"com_android_server_vibrator_VibratorManagerService.cpp",
|
||||
"com_android_server_pdb_PersistentDataBlockService.cpp",
|
||||
"com_android_server_am_LowMemDetector.cpp",
|
||||
+ "com_android_server_pm_ComputerEngine.cpp",
|
||||
"com_android_server_pm_PackageManagerShellCommandDataLoader.cpp",
|
||||
"com_android_server_sensor_SensorService.cpp",
|
||||
"com_android_server_utils_LongMethodTracer.cpp",
|
||||
@@ -95,6 +96,12 @@ cc_library_static {
|
||||
header_libs: [
|
||||
"bionic_libc_platform_headers",
|
||||
],
|
||||
+
|
||||
+ product_variables: {
|
||||
+ debuggable: {
|
||||
+ cflags: ["-DANDROID_DEBUGGABLE"],
|
||||
+ }
|
||||
+ },
|
||||
}
|
||||
|
||||
cc_defaults {
|
||||
diff --git a/services/core/jni/com_android_server_pm_ComputerEngine.cpp b/services/core/jni/com_android_server_pm_ComputerEngine.cpp
|
||||
new file mode 100644
|
||||
index 000000000000..bbe298097a2a
|
||||
--- /dev/null
|
||||
+++ b/services/core/jni/com_android_server_pm_ComputerEngine.cpp
|
||||
@@ -0,0 +1,38 @@
|
||||
+/*
|
||||
+ * Copyright (C) 2024 The LineageOS 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.
|
||||
+ */
|
||||
+
|
||||
+#include <nativehelper/JNIHelp.h>
|
||||
+
|
||||
+namespace android {
|
||||
+
|
||||
+static bool isDebuggable(JNIEnv* env) {
|
||||
+#ifdef ANDROID_DEBUGGABLE
|
||||
+ return true;
|
||||
+#else
|
||||
+ return false;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static const JNINativeMethod method_table[] = {
|
||||
+ {"isDebuggable", "()Z", (void*)isDebuggable},
|
||||
+};
|
||||
+
|
||||
+int register_android_server_com_android_server_pm_ComputerEngine(JNIEnv* env) {
|
||||
+ return jniRegisterNativeMethods(env, "com/android/server/pm/ComputerEngine",
|
||||
+ method_table, NELEM(method_table));
|
||||
+}
|
||||
+
|
||||
+} // namespace android
|
||||
diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp
|
||||
index d50b0f909ab6..f9d952e16469 100644
|
||||
--- a/services/core/jni/onload.cpp
|
||||
+++ b/services/core/jni/onload.cpp
|
||||
@@ -58,6 +58,7 @@ int register_android_server_utils_AnrTimer(JNIEnv *env);
|
||||
int register_android_server_utils_LazyJniRegistrar(JNIEnv* env);
|
||||
int register_com_android_server_soundtrigger_middleware_AudioSessionProviderImpl(JNIEnv* env);
|
||||
int register_com_android_server_soundtrigger_middleware_ExternalCaptureStateTracker(JNIEnv* env);
|
||||
+int register_android_server_com_android_server_pm_ComputerEngine(JNIEnv* env);
|
||||
int register_android_server_com_android_server_pm_PackageManagerShellCommandDataLoader(JNIEnv* env);
|
||||
int register_android_server_AdbDebuggingManager(JNIEnv* env);
|
||||
int register_android_server_FaceService(JNIEnv* env);
|
||||
@@ -125,6 +126,7 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
|
||||
register_android_server_utils_LazyJniRegistrar(env);
|
||||
register_com_android_server_soundtrigger_middleware_AudioSessionProviderImpl(env);
|
||||
register_com_android_server_soundtrigger_middleware_ExternalCaptureStateTracker(env);
|
||||
+ register_android_server_com_android_server_pm_ComputerEngine(env);
|
||||
register_android_server_com_android_server_pm_PackageManagerShellCommandDataLoader(env);
|
||||
register_android_server_AdbDebuggingManager(env);
|
||||
register_android_server_FaceService(env);
|
||||
--
|
||||
2.48.1
|
||||
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
From 483f4160dbadf1b26eb9cb0952abfdaac27d2934 Mon Sep 17 00:00:00 2001
|
||||
From: Jonathan Klee <jonathan.klee@e.email>
|
||||
Date: Thu, 12 Dec 2024 15:27:57 +0100
|
||||
Subject: [PATCH 10/11] Allow spoofing signingInfo for microG
|
||||
Companion/Services
|
||||
|
||||
- Spoof PackageInfo signingInfo + signatures so that
|
||||
G suite apps do not complain anymore.
|
||||
|
||||
Change-Id: I86f182c9e1d18b0e997803842577a90ef740cfd1
|
||||
Signed-off-by: althafvly <althafvly@gmail.com>
|
||||
---
|
||||
.../java/com/android/server/pm/ComputerEngine.java | 13 +++++++++++++
|
||||
1 file changed, 13 insertions(+)
|
||||
|
||||
diff --git a/services/core/java/com/android/server/pm/ComputerEngine.java b/services/core/java/com/android/server/pm/ComputerEngine.java
|
||||
index b45c45f4feb1..4f75642a6b56 100644
|
||||
--- a/services/core/java/com/android/server/pm/ComputerEngine.java
|
||||
+++ b/services/core/java/com/android/server/pm/ComputerEngine.java
|
||||
@@ -170,6 +170,7 @@ import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
+import java.security.cert.CertificateException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
@@ -1592,6 +1593,18 @@ public class ComputerEngine implements Computer {
|
||||
|
||||
generateFakeSignature(p).ifPresent(fakeSignature -> {
|
||||
packageInfo.signatures = new Signature[]{fakeSignature};
|
||||
+ try {
|
||||
+ packageInfo.signingInfo = new SigningInfo(
|
||||
+ new SigningDetails(
|
||||
+ packageInfo.signatures,
|
||||
+ SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V3,
|
||||
+ SigningDetails.toSigningKeys(packageInfo.signatures),
|
||||
+ null
|
||||
+ )
|
||||
+ );
|
||||
+ } catch (CertificateException e) {
|
||||
+ Slog.e(TAG, "Caught an exception when creating signing keys: ", e);
|
||||
+ }
|
||||
});
|
||||
|
||||
return packageInfo;
|
||||
--
|
||||
2.48.1
|
||||
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
From 0c3206a48449e15abb7fc1d5cd4a5839bbad25c9 Mon Sep 17 00:00:00 2001
|
||||
From: Pierre-Hugues Husson <phh@phh.me>
|
||||
Date: Sat, 3 Dec 2022 17:13:24 -0500
|
||||
Subject: [PATCH 11/11] Set old fingerprint sensors to security "strong"
|
||||
|
||||
This allows removing config_biometric_sensors from overlays, which led
|
||||
to Pixels not booting, because they are using AIDL biometric sensor, and
|
||||
despite its name, config_biometric_sensors is HIDL-specific
|
||||
---
|
||||
.../core/java/com/android/server/biometrics/AuthService.java | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/services/core/java/com/android/server/biometrics/AuthService.java b/services/core/java/com/android/server/biometrics/AuthService.java
|
||||
index fe3fa44d5e55..141b595c6fcc 100644
|
||||
--- a/services/core/java/com/android/server/biometrics/AuthService.java
|
||||
+++ b/services/core/java/com/android/server/biometrics/AuthService.java
|
||||
@@ -854,7 +854,7 @@ public class AuthService extends SystemService {
|
||||
final int firstApiLevel = SystemProperties.getInt(SYSPROP_FIRST_API_LEVEL, 0);
|
||||
final int apiLevel = SystemProperties.getInt(SYSPROP_API_LEVEL, firstApiLevel);
|
||||
String[] configStrings = mInjector.getConfiguration(getContext());
|
||||
- if (configStrings.length == 0 && apiLevel == Build.VERSION_CODES.R) {
|
||||
+ if (configStrings.length == 0 && apiLevel <= Build.VERSION_CODES.R) {
|
||||
// For backwards compatibility with R where biometrics could work without being
|
||||
// configured in config_biometric_sensors. In the absence of a vendor provided
|
||||
// configuration, we assume the weakest biometric strength (i.e. convenience).
|
||||
@@ -1039,7 +1039,7 @@ public class AuthService extends SystemService {
|
||||
if (pm.hasSystemFeature(PackageManager.FEATURE_FACE)) {
|
||||
modalities.add(String.valueOf(BiometricAuthenticator.TYPE_FACE));
|
||||
}
|
||||
- final String strength = String.valueOf(Authenticators.BIOMETRIC_CONVENIENCE);
|
||||
+ final String strength = String.valueOf(Authenticators.BIOMETRIC_STRONG);
|
||||
final String[] configStrings = new String[modalities.size()];
|
||||
for (int i = 0; i < modalities.size(); ++i) {
|
||||
final String id = String.valueOf(i);
|
||||
--
|
||||
2.48.1
|
||||
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
From ac782b35e6bd52bc2a20ce6987c93671a2d06b38 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Cai <peter@typeblog.net>
|
||||
Date: Sun, 6 Oct 2024 09:06:48 -0400
|
||||
Subject: [PATCH 1/3] sensorservice: Add support for ignoring broken sensors
|
||||
|
||||
This allows those sensors to be replaced by SensorFusion when possible.
|
||||
|
||||
Change-Id: I5509ee1f54fdf4838f6e3b109819a689f483cfc4
|
||||
---
|
||||
services/sensorservice/SensorDevice.cpp | 17 +++++++++++++++++
|
||||
1 file changed, 17 insertions(+)
|
||||
|
||||
diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp
|
||||
index 9c4d1ace15..5a95096fdb 100644
|
||||
--- a/services/sensorservice/SensorDevice.cpp
|
||||
+++ b/services/sensorservice/SensorDevice.cpp
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "SensorDevice.h"
|
||||
|
||||
#include <android-base/logging.h>
|
||||
+#include <android-base/properties.h>
|
||||
#include <android/util/ProtoOutputStream.h>
|
||||
#include <com_android_frameworks_sensorservice_flags.h>
|
||||
#include <cutils/atomic.h>
|
||||
@@ -32,6 +33,8 @@
|
||||
#include <condition_variable>
|
||||
#include <cstddef>
|
||||
#include <mutex>
|
||||
+#include <sstream>
|
||||
+#include <string>
|
||||
#include <thread>
|
||||
|
||||
#include "AidlSensorHalWrapper.h"
|
||||
@@ -86,10 +89,24 @@ void SensorDevice::initializeSensorList() {
|
||||
auto list = mHalWrapper->getSensorsList();
|
||||
const size_t count = list.size();
|
||||
|
||||
+ auto sensorFilter = base::GetProperty("persist.sys.phh.sensor_filter", "");
|
||||
+
|
||||
mActivationCount.setCapacity(count);
|
||||
Info model;
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
sensor_t sensor = list[i];
|
||||
+ std::string vendorNamePair = std::string(sensor.vendor) + ":" + std::string(sensor.name);
|
||||
+
|
||||
+ std::istringstream iss(sensorFilter);
|
||||
+ std::string item;
|
||||
+ bool shouldIgnore = false;
|
||||
+ while (std::getline(iss, item, ';')) {
|
||||
+ if (item == vendorNamePair) {
|
||||
+ shouldIgnore = true;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (shouldIgnore) continue;
|
||||
|
||||
if (sensor.type < DEVICE_PRIVATE_BASE) {
|
||||
sensor.resolution = SensorDeviceUtils::resolutionForSensor(sensor);
|
||||
--
|
||||
2.48.1
|
||||
|
||||
|
|
@ -1,298 +0,0 @@
|
|||
From 3538055ef9c7b426302939144d4b8ac077242471 Mon Sep 17 00:00:00 2001
|
||||
From: Pierre-Hugues Husson <phh@phh.me>
|
||||
Date: Sat, 25 Nov 2023 08:15:28 -0500
|
||||
Subject: [PATCH 2/3] Add MTK GED KPI support to fix broken Mediatek gpufreq
|
||||
|
||||
Mediatek GPU scheduler likes to have the timestamps of the frames to be
|
||||
able to adjust DVFS.
|
||||
Technically this isn't completely needed, because it looks like DVFS can
|
||||
work once we started triggering /proc/ged. But now that the work is
|
||||
done, let's do it completely.
|
||||
|
||||
In benchmarks on Poco X4 GT, before this patch result is 1500, after is
|
||||
5700. If we disable the patch after enabling it without rebooting, it
|
||||
goes to 5400. So looks like GED KPI thingy does try to do a bit more
|
||||
than just standard DVFS.
|
||||
|
||||
Thanks @sarthakroy2002 for the help and support (other people helped as
|
||||
well)
|
||||
|
||||
Change-Id: Ic29a231ea8651efd598083611197aaa9e3c1fbbe
|
||||
---
|
||||
libs/gui/Surface.cpp | 203 +++++++++++++++++++++++++++++++++
|
||||
libs/gui/include/gui/Surface.h | 3 +
|
||||
2 files changed, 206 insertions(+)
|
||||
|
||||
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
|
||||
index cabc1773e0..61bb18a54d 100644
|
||||
--- a/libs/gui/Surface.cpp
|
||||
+++ b/libs/gui/Surface.cpp
|
||||
@@ -26,6 +26,9 @@
|
||||
#include <deque>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
+#include <sys/ioctl.h>
|
||||
+#include <fcntl.h>
|
||||
+#include <unistd.h>
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
@@ -57,6 +60,10 @@
|
||||
|
||||
#include <gui/BufferItem.h>
|
||||
|
||||
+#include <android-base/properties.h>
|
||||
+
|
||||
+#include <binder/IPCThreadState.h>
|
||||
+
|
||||
#include <com_android_graphics_libgui_flags.h>
|
||||
|
||||
namespace android {
|
||||
@@ -103,6 +110,37 @@ bool isInterceptorRegistrationOp(int op) {
|
||||
}
|
||||
|
||||
} // namespace
|
||||
+ //
|
||||
+#define GED_MAGIC 'g'
|
||||
+#define GED_BRIDGE_COMMAND_GPU_TIMESTAMP 103
|
||||
+#define GED_IOWR(INDEX) _IOWR(GED_MAGIC, INDEX, GED_BRIDGE_PACKAGE)
|
||||
+#define GED_BRIDGE_IO_GPU_TIMESTAMP \
|
||||
+ GED_IOWR(GED_BRIDGE_COMMAND_GPU_TIMESTAMP)
|
||||
+typedef struct _GED_BRIDGE_PACKAGE {
|
||||
+ unsigned int ui32FunctionID;
|
||||
+ int i32Size;
|
||||
+ void *pvParamIn;
|
||||
+ int i32InBufferSize;
|
||||
+ void *pvParamOut;
|
||||
+ int i32OutBufferSize;
|
||||
+} GED_BRIDGE_PACKAGE;
|
||||
+
|
||||
+struct GED_BRIDGE_IN_GPU_TIMESTAMP {
|
||||
+ int pid;
|
||||
+ uint64_t ullWnd;
|
||||
+ int32_t i32FrameID;
|
||||
+ int fence_fd;
|
||||
+ int QedBuffer_length;
|
||||
+ int isSF;
|
||||
+};
|
||||
+
|
||||
+struct GED_BRIDGE_OUT_GPU_TIMESTAMP {
|
||||
+ int eError;
|
||||
+ int is_ged_kpi_enabled;
|
||||
+};
|
||||
+
|
||||
+static int doMtkGedKpi = -1;
|
||||
+static int ged_fd = -1;
|
||||
|
||||
Surface::ProducerDeathListenerProxy::ProducerDeathListenerProxy(wp<SurfaceListener> surfaceListener)
|
||||
: mSurfaceListener(surfaceListener) {}
|
||||
@@ -175,6 +213,47 @@ Surface::Surface(const sp<IGraphicBufferProducer>& bufferProducer, bool controll
|
||||
mSwapIntervalZero = false;
|
||||
mMaxBufferCount = NUM_BUFFER_SLOTS;
|
||||
mSurfaceControlHandle = surfaceControlHandle;
|
||||
+
|
||||
+ if (doMtkGedKpi == -1) {
|
||||
+ doMtkGedKpi = android::base::GetIntProperty("persist.sys.phh.mtk_ged_kpi", 0);
|
||||
+ }
|
||||
+
|
||||
+ if (ged_fd == -1 && doMtkGedKpi == 1) {
|
||||
+ ALOGE("Opening ged");
|
||||
+ ged_fd = open("/proc/ged", O_RDONLY);
|
||||
+ ALOGE("Opening ged ret = %d", ged_fd);
|
||||
+ {
|
||||
+ struct GED_BRIDGE_IN_GPU_TIMESTAMP in = {
|
||||
+ .pid = 0,
|
||||
+ //.ullWnd = (uint64_t)(intptr_t)this,
|
||||
+ .ullWnd = 0,
|
||||
+ .i32FrameID = 0,
|
||||
+ .fence_fd = 0,
|
||||
+ .isSF = 0,
|
||||
+ .QedBuffer_length = 0,
|
||||
+ };
|
||||
+ struct GED_BRIDGE_OUT_GPU_TIMESTAMP out;
|
||||
+ memset(&in, 0, sizeof(in));
|
||||
+ GED_BRIDGE_PACKAGE package = {
|
||||
+ .ui32FunctionID = GED_BRIDGE_IO_GPU_TIMESTAMP,
|
||||
+ .i32Size = sizeof(GED_BRIDGE_PACKAGE),
|
||||
+ .pvParamIn = &in,
|
||||
+ .i32InBufferSize = sizeof(in),
|
||||
+ .pvParamOut = &out,
|
||||
+ .i32OutBufferSize = sizeof(out),
|
||||
+ };
|
||||
+ if (ged_fd >= 0) {
|
||||
+ int ret = ioctl(ged_fd, GED_BRIDGE_IO_GPU_TIMESTAMP, &package);
|
||||
+ ALOGE("First null timestamp ioctl returned %d %d %d", ret, out.eError, out.is_ged_kpi_enabled);
|
||||
+ if (out.is_ged_kpi_enabled != 1) {
|
||||
+ ALOGE("is_ged_kpi_enabled reported disabled");
|
||||
+ doMtkGedKpi = 0;
|
||||
+ }
|
||||
+ } else {
|
||||
+ ALOGE("No /proc/ged");
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
|
||||
Surface::~Surface() {
|
||||
@@ -754,6 +833,36 @@ int Surface::dequeueBuffer(sp<GraphicBuffer>* buffer, int* fenceFd) {
|
||||
}
|
||||
}
|
||||
|
||||
+ if (mGraphicBufferProducer != nullptr && ged_fd >= 0) {
|
||||
+ uint64_t uniqueId;
|
||||
+ mGraphicBufferProducer->getUniqueId(&uniqueId);
|
||||
+
|
||||
+ const int32_t dupFenceFd = fence->isValid() ? fence->dup() : -1;
|
||||
+
|
||||
+ struct GED_BRIDGE_IN_GPU_TIMESTAMP in = {
|
||||
+ .pid = mPid,
|
||||
+ .ullWnd = uniqueId,
|
||||
+ .i32FrameID = static_cast<int32_t>(reinterpret_cast<intptr_t>(gbuf->handle)) & 0x3fffffff,
|
||||
+ .fence_fd = dupFenceFd,
|
||||
+ .isSF = mIsSurfaceFlinger ? 1 : 0,
|
||||
+ .QedBuffer_length = -2,
|
||||
+ };
|
||||
+ struct GED_BRIDGE_OUT_GPU_TIMESTAMP out;
|
||||
+ memset(&out, 0, sizeof(out));
|
||||
+ GED_BRIDGE_PACKAGE package = {
|
||||
+ .ui32FunctionID = GED_BRIDGE_IO_GPU_TIMESTAMP,
|
||||
+ .i32Size = sizeof(GED_BRIDGE_PACKAGE),
|
||||
+ .pvParamIn = &in,
|
||||
+ .i32InBufferSize = sizeof(in),
|
||||
+ .pvParamOut = &out,
|
||||
+ .i32OutBufferSize = sizeof(out),
|
||||
+ };
|
||||
+
|
||||
+ int ret = ioctl(ged_fd, GED_BRIDGE_IO_GPU_TIMESTAMP, &package);
|
||||
+ ALOGV("GPU timestamp ioctl returned %d %d %d %d", ret, out.eError, out.is_ged_kpi_enabled, in.i32FrameID);
|
||||
+
|
||||
+ close(dupFenceFd);
|
||||
+ }
|
||||
if (fence->isValid()) {
|
||||
*fenceFd = fence->dup();
|
||||
if (*fenceFd == -1) {
|
||||
@@ -1322,6 +1431,60 @@ void Surface::onBufferQueuedLocked(int slot, sp<Fence> fence,
|
||||
}
|
||||
|
||||
mQueueBufferCondition.broadcast();
|
||||
+ if (mGraphicBufferProducer != nullptr && ged_fd >= 0) {
|
||||
+ sp<GraphicBuffer>& gbuf(mSlots[slot].buffer);
|
||||
+ uint64_t uniqueId;
|
||||
+ mGraphicBufferProducer->getUniqueId(&uniqueId);
|
||||
+
|
||||
+ const int32_t dupFenceFd = fence->isValid() ? fence->dup() : -1;
|
||||
+ // onQueue
|
||||
+ {
|
||||
+ struct GED_BRIDGE_IN_GPU_TIMESTAMP in = {
|
||||
+ .pid = mPid,
|
||||
+ .ullWnd = uniqueId,
|
||||
+ .i32FrameID = static_cast<int32_t>(reinterpret_cast<intptr_t>(gbuf->handle)) & 0x3fffffff,
|
||||
+ .fence_fd = dupFenceFd,
|
||||
+ .isSF = mIsSurfaceFlinger ? 1 : 0,
|
||||
+ .QedBuffer_length = static_cast<int>(output.numPendingBuffers),
|
||||
+ };
|
||||
+ struct GED_BRIDGE_OUT_GPU_TIMESTAMP out;
|
||||
+ memset(&out, 0, sizeof(out));
|
||||
+ GED_BRIDGE_PACKAGE package = {
|
||||
+ .ui32FunctionID = GED_BRIDGE_IO_GPU_TIMESTAMP,
|
||||
+ .i32Size = sizeof(GED_BRIDGE_PACKAGE),
|
||||
+ .pvParamIn = &in,
|
||||
+ .i32InBufferSize = sizeof(in),
|
||||
+ .pvParamOut = &out,
|
||||
+ .i32OutBufferSize = sizeof(out),
|
||||
+ };
|
||||
+ int ret = ioctl(ged_fd, GED_BRIDGE_IO_GPU_TIMESTAMP, &package);
|
||||
+ ALOGV("GPU timestamp ioctl returned %d %d %d", ret, out.eError, in.i32FrameID);
|
||||
+ }
|
||||
+ // acquire
|
||||
+ {
|
||||
+ struct GED_BRIDGE_IN_GPU_TIMESTAMP in = {
|
||||
+ .pid = mPid,
|
||||
+ .isSF = mIsSurfaceFlinger ? 1 : 0,
|
||||
+ .ullWnd = uniqueId,
|
||||
+ .i32FrameID = static_cast<int32_t>(reinterpret_cast<intptr_t>(gbuf->handle)) & 0x3fffffff,
|
||||
+ .fence_fd = dupFenceFd,
|
||||
+ .QedBuffer_length = -1,
|
||||
+ };
|
||||
+ struct GED_BRIDGE_OUT_GPU_TIMESTAMP out;
|
||||
+ memset(&out, 0, sizeof(out));
|
||||
+ GED_BRIDGE_PACKAGE package = {
|
||||
+ .ui32FunctionID = GED_BRIDGE_IO_GPU_TIMESTAMP,
|
||||
+ .i32Size = sizeof(GED_BRIDGE_PACKAGE),
|
||||
+ .pvParamIn = &in,
|
||||
+ .i32InBufferSize = sizeof(in),
|
||||
+ .pvParamOut = &in,
|
||||
+ .i32OutBufferSize = sizeof(out),
|
||||
+ };
|
||||
+ int ret = ioctl(ged_fd, GED_BRIDGE_IO_GPU_TIMESTAMP, &package);
|
||||
+ ALOGV("GPU timestamp ioctl returned %d %d %d", ret, out.eError, in.i32FrameID);
|
||||
+ }
|
||||
+ close(dupFenceFd);
|
||||
+ }
|
||||
|
||||
if (CC_UNLIKELY(atrace_is_tag_enabled(ATRACE_TAG_GRAPHICS))) {
|
||||
static gui::FenceMonitor gpuCompletionThread("GPU completion");
|
||||
@@ -2196,6 +2359,46 @@ int Surface::connect(int api, const sp<SurfaceListener>& listener, bool reportBu
|
||||
SURF_LOGE_IF(idErr != NO_ERROR, "Unable to get ID from IGBP: %d", idErr);
|
||||
mIsConnected = true;
|
||||
}
|
||||
+
|
||||
+ // For MTK GED KPI, we need to grab the Surface owner's PID
|
||||
+ // and also know whether that owner is surfaceflinger
|
||||
+ if (api == NATIVE_WINDOW_API_EGL && ged_fd >= 0) {
|
||||
+ IPCThreadState *ipc = IPCThreadState::selfOrNull();
|
||||
+ const sp<IBinder>& token = IInterface::asBinder(mGraphicBufferProducer);
|
||||
+ mPid = (token != NULL && NULL != token->localBinder())
|
||||
+ ? getpid()
|
||||
+ : (ipc != nullptr)?ipc->getCallingPid():-1;
|
||||
+
|
||||
+ // We've got caller PID. Now checking whether it is surfaceflinger
|
||||
+ char cmdline[128];
|
||||
+ char path[128];
|
||||
+ snprintf(path, sizeof(path)-1, "/proc/%d/cmdline", mPid);
|
||||
+ int fd = open(path, O_RDONLY);
|
||||
+ read(fd, cmdline, sizeof(cmdline)-1);
|
||||
+ // Normally cmdline is already \0-separated, but well
|
||||
+ for(unsigned i=0; i<sizeof(cmdline); i++)
|
||||
+ if(cmdline[i] == '\n')
|
||||
+ cmdline[i] = 0;
|
||||
+ cmdline[sizeof(cmdline)-1] = 0;
|
||||
+
|
||||
+ close(fd);
|
||||
+
|
||||
+ // Truncate to last / (also called basename)
|
||||
+ const char *c = strrchr(cmdline, '/');
|
||||
+ if (c != nullptr) {
|
||||
+ c = c+1;
|
||||
+ } else {
|
||||
+ c = cmdline;
|
||||
+ }
|
||||
+ if(strcmp(c, "surfaceflinger") == 0) {
|
||||
+ ALOGE("is surfaceflinger = 1");
|
||||
+ mIsSurfaceFlinger = true;
|
||||
+ } else {
|
||||
+ ALOGE("is surfaceflinger = 0");
|
||||
+ mIsSurfaceFlinger = false;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
if (!err && api == NATIVE_WINDOW_API_CPU) {
|
||||
mConnectedToCpu = true;
|
||||
// Clear the dirty region in case we're switching from a non-CPU API
|
||||
diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h
|
||||
index 9a6e75c333..7927d5724e 100644
|
||||
--- a/libs/gui/include/gui/Surface.h
|
||||
+++ b/libs/gui/include/gui/Surface.h
|
||||
@@ -769,6 +769,9 @@ protected:
|
||||
mutable std::mutex mDebugMutex;
|
||||
String8 mDebugName GUARDED_BY(mDebugMutex) = String8("not-connected");
|
||||
uint64_t mId GUARDED_BY(mDebugMutex) = 0;
|
||||
+
|
||||
+ pid_t mPid;
|
||||
+ bool mIsSurfaceFlinger;
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
--
|
||||
2.48.1
|
||||
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
From c2b6e8a02414e16061792edf643ef10d7f0605cc Mon Sep 17 00:00:00 2001
|
||||
From: Peter Cai <peter@typeblog.net>
|
||||
Date: Sat, 1 Nov 2025 22:56:26 -0400
|
||||
Subject: [PATCH 3/3] inputflinger: Allow ignoring touch devices using a
|
||||
special device type
|
||||
|
||||
This allows us to ignore the capacitive input on Titan 2's keyboard by
|
||||
default. The keyboard is not really well supported by AOSP and we'll
|
||||
probably need to come up with a uinput implementation.
|
||||
|
||||
Change-Id: I80774697739edaeb4ec6ae492282f5ebaaad44a7
|
||||
---
|
||||
services/inputflinger/reader/InputDevice.cpp | 6 ++++++
|
||||
1 file changed, 6 insertions(+)
|
||||
|
||||
diff --git a/services/inputflinger/reader/InputDevice.cpp b/services/inputflinger/reader/InputDevice.cpp
|
||||
index b0d805ba34..e0ccd2790c 100644
|
||||
--- a/services/inputflinger/reader/InputDevice.cpp
|
||||
+++ b/services/inputflinger/reader/InputDevice.cpp
|
||||
@@ -557,6 +557,12 @@ std::vector<std::unique_ptr<InputMapper>> InputDevice::createMappers(
|
||||
ftl::Flags<InputDeviceClass> classes = contextPtr.getDeviceClasses();
|
||||
std::vector<std::unique_ptr<InputMapper>> mappers;
|
||||
|
||||
+ std::string deviceTypeString = contextPtr.getConfiguration().getString("touch.deviceType").value_or("");
|
||||
+
|
||||
+ if (deviceTypeString == "ignore") {
|
||||
+ return mappers;
|
||||
+ }
|
||||
+
|
||||
// Switch-like devices.
|
||||
if (classes.test(InputDeviceClass::SWITCH)) {
|
||||
mappers.push_back(createInputMapper<SwitchInputMapper>(contextPtr, readerConfig));
|
||||
--
|
||||
2.48.1
|
||||
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
From 2094e455ceba808defae7cd312a3beb499824bf3 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Cai <peter@typeblog.net>
|
||||
Date: Mon, 5 Sep 2022 14:02:37 -0400
|
||||
Subject: [PATCH 2/3] SubscriptionController: Do not override default calling
|
||||
account from third-party apps
|
||||
|
||||
When the user has selected a calling account from a third-party app as
|
||||
default, it should not be overridden by the rest of the telephony
|
||||
subsystem (e.g. SIM subcription updates, or default SIM slot selection).
|
||||
|
||||
Otherwise, it creates a somewhat annoying situation where the user has
|
||||
to keep re-selecting the desired calling account after every reboot.
|
||||
|
||||
Test: manual
|
||||
Change-Id: Iccab64e9b3b3ab4773bd8944d47c2006f229d472
|
||||
---
|
||||
.../SubscriptionManagerService.java | 18 +++++++++++++++++-
|
||||
1 file changed, 17 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java b/src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java
|
||||
index 4c12127..f48e405 100644
|
||||
--- a/src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java
|
||||
+++ b/src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java
|
||||
@@ -88,6 +88,7 @@ import android.util.Base64;
|
||||
import android.util.EventLog;
|
||||
import android.util.IndentingPrintWriter;
|
||||
import android.util.LocalLog;
|
||||
+import android.util.Log;
|
||||
|
||||
import com.android.internal.R;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
@@ -3321,7 +3322,22 @@ public class SubscriptionManagerService extends ISub.Stub {
|
||||
|
||||
TelecomManager telecomManager = mContext.getSystemService(TelecomManager.class);
|
||||
if (telecomManager != null) {
|
||||
- telecomManager.setUserSelectedOutgoingPhoneAccount(newHandle);
|
||||
+ PhoneAccountHandle currentHandle = telecomManager.getUserSelectedOutgoingPhoneAccount();
|
||||
+ log("[setDefaultVoiceSubId] current phoneAccountHandle=" + currentHandle);
|
||||
+
|
||||
+ String currentPackageName =
|
||||
+ currentHandle == null ? null : currentHandle.getComponentName().getPackageName();
|
||||
+ boolean currentIsSim = "com.android.phone".equals(currentPackageName);
|
||||
+ // Do not override user selected outgoing calling account
|
||||
+ // if the user has selected a third-party app as default
|
||||
+ boolean shouldKeepOutgoingAccount = currentHandle != null && !currentIsSim;
|
||||
+
|
||||
+ if (!shouldKeepOutgoingAccount) {
|
||||
+ telecomManager.setUserSelectedOutgoingPhoneAccount(newHandle);
|
||||
+ log("[setDefaultVoiceSubId] change to phoneAccountHandle=" + newHandle);
|
||||
+ } else {
|
||||
+ log("[setDefaultVoiceSubId] default phoneAccountHandle not changed.");
|
||||
+ }
|
||||
}
|
||||
|
||||
updateDefaultSubId();
|
||||
--
|
||||
2.48.1
|
||||
|
||||
|
|
@ -1,101 +0,0 @@
|
|||
From 2aa4bc8eeaca6c10513488376fa18577f95edeb8 Mon Sep 17 00:00:00 2001
|
||||
From: Danny Lin <danny@kdrag0n.dev>
|
||||
Date: Sat, 15 Nov 2025 19:12:04 -0500
|
||||
Subject: [PATCH 4/5] Launcher3: Reduce app label text size
|
||||
|
||||
The default 13-point label size can barely fit any app names on modern
|
||||
phone form factors without ellipsizing. Reducing the size to 12 points
|
||||
allows us to fit most apps names, and upon visual inspection, it appears
|
||||
to be the same size as that of Pixel Launcher.
|
||||
|
||||
Change-Id: I6ad63c14237f1f38c86ec02059b03896e5dd3a77
|
||||
---
|
||||
res/xml/device_profiles.xml | 18 +++++++++---------
|
||||
1 file changed, 9 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/res/xml/device_profiles.xml b/res/xml/device_profiles.xml
|
||||
index 5fac66f..ff75d58 100644
|
||||
--- a/res/xml/device_profiles.xml
|
||||
+++ b/res/xml/device_profiles.xml
|
||||
@@ -33,7 +33,7 @@
|
||||
launcher:minWidthDps="255"
|
||||
launcher:minHeightDps="300"
|
||||
launcher:iconImageSize="48"
|
||||
- launcher:iconTextSize="13.0"
|
||||
+ launcher:iconTextSize="12.0"
|
||||
launcher:allAppsBorderSpace="16"
|
||||
launcher:allAppsCellHeight="104"
|
||||
launcher:canBeDefault="true" />
|
||||
@@ -43,7 +43,7 @@
|
||||
launcher:minWidthDps="255"
|
||||
launcher:minHeightDps="400"
|
||||
launcher:iconImageSize="48"
|
||||
- launcher:iconTextSize="13.0"
|
||||
+ launcher:iconTextSize="12.0"
|
||||
launcher:allAppsBorderSpace="16"
|
||||
launcher:allAppsCellHeight="104"
|
||||
launcher:canBeDefault="true" />
|
||||
@@ -68,7 +68,7 @@
|
||||
launcher:minWidthDps="275"
|
||||
launcher:minHeightDps="420"
|
||||
launcher:iconImageSize="48"
|
||||
- launcher:iconTextSize="13.0"
|
||||
+ launcher:iconTextSize="12.0"
|
||||
launcher:allAppsBorderSpace="16"
|
||||
launcher:allAppsCellHeight="104"
|
||||
launcher:canBeDefault="true" />
|
||||
@@ -78,7 +78,7 @@
|
||||
launcher:minWidthDps="255"
|
||||
launcher:minHeightDps="450"
|
||||
launcher:iconImageSize="48"
|
||||
- launcher:iconTextSize="13.0"
|
||||
+ launcher:iconTextSize="12.0"
|
||||
launcher:allAppsBorderSpace="16"
|
||||
launcher:allAppsCellHeight="104"
|
||||
launcher:canBeDefault="true" />
|
||||
@@ -88,7 +88,7 @@
|
||||
launcher:minWidthDps="296"
|
||||
launcher:minHeightDps="491.33"
|
||||
launcher:iconImageSize="48"
|
||||
- launcher:iconTextSize="13.0"
|
||||
+ launcher:iconTextSize="12.0"
|
||||
launcher:allAppsBorderSpace="16"
|
||||
launcher:allAppsCellHeight="104"
|
||||
launcher:canBeDefault="true" />
|
||||
@@ -98,7 +98,7 @@
|
||||
launcher:minWidthDps="359"
|
||||
launcher:minHeightDps="567"
|
||||
launcher:iconImageSize="54"
|
||||
- launcher:iconTextSize="13.0"
|
||||
+ launcher:iconTextSize="12.0"
|
||||
launcher:allAppsBorderSpace="16"
|
||||
launcher:allAppsCellHeight="104"
|
||||
launcher:canBeDefault="true" />
|
||||
@@ -108,7 +108,7 @@
|
||||
launcher:minWidthDps="335"
|
||||
launcher:minHeightDps="567"
|
||||
launcher:iconImageSize="54"
|
||||
- launcher:iconTextSize="13.0"
|
||||
+ launcher:iconTextSize="12.0"
|
||||
launcher:allAppsBorderSpace="16"
|
||||
launcher:allAppsCellHeight="104"
|
||||
launcher:canBeDefault="true" />
|
||||
@@ -153,7 +153,7 @@
|
||||
launcher:minWidthDps="255"
|
||||
launcher:minHeightDps="400"
|
||||
launcher:iconImageSize="48"
|
||||
- launcher:iconTextSize="13.0"
|
||||
+ launcher:iconTextSize="12.0"
|
||||
launcher:allAppsBorderSpace="16"
|
||||
launcher:allAppsCellHeight="104"
|
||||
launcher:canBeDefault="true" />
|
||||
@@ -248,4 +248,4 @@
|
||||
|
||||
</grid-option>
|
||||
|
||||
-</profiles>
|
||||
\ No newline at end of file
|
||||
+</profiles>
|
||||
--
|
||||
2.48.1
|
||||
|
||||
|
|
@ -1,127 +0,0 @@
|
|||
From 460bd8190290a2e49f07207f15d7f28555661336 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Bestas <mkbestas@gmail.com>
|
||||
Date: Sat, 15 Nov 2025 19:19:18 -0500
|
||||
Subject: [PATCH 5/5] Launcher3: Make taskbar start aligned in all grid sizes
|
||||
|
||||
This fixes taskbar overlapping navigation on Pixel Fold devices
|
||||
|
||||
Change-Id: I26393f96ed85d8f53259eb1670a01c5de950eb59
|
||||
---
|
||||
res/xml/device_profiles.xml | 24 ++++++++++++++++++++++++
|
||||
1 file changed, 24 insertions(+)
|
||||
|
||||
diff --git a/res/xml/device_profiles.xml b/res/xml/device_profiles.xml
|
||||
index ff75d58..acb41ef 100644
|
||||
--- a/res/xml/device_profiles.xml
|
||||
+++ b/res/xml/device_profiles.xml
|
||||
@@ -36,6 +36,8 @@
|
||||
launcher:iconTextSize="12.0"
|
||||
launcher:allAppsBorderSpace="16"
|
||||
launcher:allAppsCellHeight="104"
|
||||
+ launcher:startAlignTaskbar="true"
|
||||
+ launcher:startAlignTaskbarLandscape="true"
|
||||
launcher:canBeDefault="true" />
|
||||
|
||||
<display-option
|
||||
@@ -46,6 +48,8 @@
|
||||
launcher:iconTextSize="12.0"
|
||||
launcher:allAppsBorderSpace="16"
|
||||
launcher:allAppsCellHeight="104"
|
||||
+ launcher:startAlignTaskbar="true"
|
||||
+ launcher:startAlignTaskbarLandscape="true"
|
||||
launcher:canBeDefault="true" />
|
||||
|
||||
</grid-option>
|
||||
@@ -71,6 +75,8 @@
|
||||
launcher:iconTextSize="12.0"
|
||||
launcher:allAppsBorderSpace="16"
|
||||
launcher:allAppsCellHeight="104"
|
||||
+ launcher:startAlignTaskbar="true"
|
||||
+ launcher:startAlignTaskbarLandscape="true"
|
||||
launcher:canBeDefault="true" />
|
||||
|
||||
<display-option
|
||||
@@ -81,6 +87,8 @@
|
||||
launcher:iconTextSize="12.0"
|
||||
launcher:allAppsBorderSpace="16"
|
||||
launcher:allAppsCellHeight="104"
|
||||
+ launcher:startAlignTaskbar="true"
|
||||
+ launcher:startAlignTaskbarLandscape="true"
|
||||
launcher:canBeDefault="true" />
|
||||
|
||||
<display-option
|
||||
@@ -91,6 +99,8 @@
|
||||
launcher:iconTextSize="12.0"
|
||||
launcher:allAppsBorderSpace="16"
|
||||
launcher:allAppsCellHeight="104"
|
||||
+ launcher:startAlignTaskbar="true"
|
||||
+ launcher:startAlignTaskbarLandscape="true"
|
||||
launcher:canBeDefault="true" />
|
||||
|
||||
<display-option
|
||||
@@ -101,6 +111,8 @@
|
||||
launcher:iconTextSize="12.0"
|
||||
launcher:allAppsBorderSpace="16"
|
||||
launcher:allAppsCellHeight="104"
|
||||
+ launcher:startAlignTaskbar="true"
|
||||
+ launcher:startAlignTaskbarLandscape="true"
|
||||
launcher:canBeDefault="true" />
|
||||
|
||||
<display-option
|
||||
@@ -111,6 +123,8 @@
|
||||
launcher:iconTextSize="12.0"
|
||||
launcher:allAppsBorderSpace="16"
|
||||
launcher:allAppsCellHeight="104"
|
||||
+ launcher:startAlignTaskbar="true"
|
||||
+ launcher:startAlignTaskbarLandscape="true"
|
||||
launcher:canBeDefault="true" />
|
||||
|
||||
</grid-option>
|
||||
@@ -136,6 +150,8 @@
|
||||
launcher:iconTextSize="14.4"
|
||||
launcher:allAppsBorderSpace="16"
|
||||
launcher:allAppsCellHeight="104"
|
||||
+ launcher:startAlignTaskbar="true"
|
||||
+ launcher:startAlignTaskbarLandscape="true"
|
||||
launcher:canBeDefault="true" />
|
||||
|
||||
<display-option
|
||||
@@ -146,6 +162,8 @@
|
||||
launcher:iconTextSize="14.4"
|
||||
launcher:allAppsBorderSpace="16"
|
||||
launcher:allAppsCellHeight="104"
|
||||
+ launcher:startAlignTaskbar="true"
|
||||
+ launcher:startAlignTaskbarLandscape="true"
|
||||
launcher:canBeDefault="true" />
|
||||
|
||||
<display-option
|
||||
@@ -156,6 +174,8 @@
|
||||
launcher:iconTextSize="12.0"
|
||||
launcher:allAppsBorderSpace="16"
|
||||
launcher:allAppsCellHeight="104"
|
||||
+ launcher:startAlignTaskbar="true"
|
||||
+ launcher:startAlignTaskbarLandscape="true"
|
||||
launcher:canBeDefault="true" />
|
||||
|
||||
</grid-option>
|
||||
@@ -203,6 +223,8 @@
|
||||
launcher:allAppsBorderSpaceLandscape="16"
|
||||
launcher:hotseatBarBottomSpace="76"
|
||||
launcher:hotseatBarBottomSpaceLandscape="40"
|
||||
+ launcher:startAlignTaskbar="true"
|
||||
+ launcher:startAlignTaskbarLandscape="true"
|
||||
launcher:canBeDefault="true" />
|
||||
|
||||
</grid-option>
|
||||
@@ -244,6 +266,8 @@
|
||||
launcher:iconTextSize="12"
|
||||
launcher:allAppsBorderSpace="16"
|
||||
launcher:allAppsCellHeight="104"
|
||||
+ launcher:startAlignTaskbar="true"
|
||||
+ launcher:startAlignTaskbarLandscape="true"
|
||||
launcher:canBeDefault="true" />
|
||||
|
||||
</grid-option>
|
||||
--
|
||||
2.48.1
|
||||
|
||||
|
|
@ -1,192 +0,0 @@
|
|||
From b1a7d84905f802ac4081d65c2e993f6036c001d2 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Cai <peter@typeblog.net>
|
||||
Date: Wed, 24 Aug 2022 15:45:18 -0400
|
||||
Subject: [PATCH 1/2] audio_hal_interface: Optionally use sysbta HAL
|
||||
|
||||
Required to support sysbta, our system-side bt audio implementation.
|
||||
|
||||
Change-Id: I59973e6ec84c5923be8a7c67b36b2e237f000860
|
||||
---
|
||||
.../aidl/a2dp/client_interface_aidl.cc | 8 ++++----
|
||||
.../aidl/a2dp/client_interface_aidl.h | 7 +++++++
|
||||
.../audio_hal_interface/aidl/client_interface_aidl.cc | 8 ++++----
|
||||
.../audio_hal_interface/aidl/client_interface_aidl.h | 7 +++++++
|
||||
system/audio_hal_interface/hal_version_manager.cc | 11 +++++++++--
|
||||
5 files changed, 31 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/system/audio_hal_interface/aidl/a2dp/client_interface_aidl.cc b/system/audio_hal_interface/aidl/a2dp/client_interface_aidl.cc
|
||||
index 201cae8..ec238d5 100644
|
||||
--- a/system/audio_hal_interface/aidl/a2dp/client_interface_aidl.cc
|
||||
+++ b/system/audio_hal_interface/aidl/a2dp/client_interface_aidl.cc
|
||||
@@ -59,7 +59,7 @@ BluetoothAudioClientInterface::~BluetoothAudioClientInterface() {
|
||||
bool BluetoothAudioClientInterface::IsValid() const { return provider_ != nullptr; }
|
||||
|
||||
bool BluetoothAudioClientInterface::is_aidl_available() {
|
||||
- return AServiceManager_isDeclared(kDefaultAudioProviderFactoryInterface.c_str());
|
||||
+ return AServiceManager_isDeclared(audioProviderFactoryInterface().c_str());
|
||||
}
|
||||
|
||||
std::vector<AudioCapabilities> BluetoothAudioClientInterface::GetAudioCapabilities() const {
|
||||
@@ -73,7 +73,7 @@ std::vector<AudioCapabilities> BluetoothAudioClientInterface::GetAudioCapabiliti
|
||||
return capabilities;
|
||||
}
|
||||
auto provider_factory = IBluetoothAudioProviderFactory::fromBinder(::ndk::SpAIBinder(
|
||||
- AServiceManager_waitForService(kDefaultAudioProviderFactoryInterface.c_str())));
|
||||
+ AServiceManager_waitForService(audioProviderFactoryInterface().c_str())));
|
||||
|
||||
if (provider_factory == nullptr) {
|
||||
log::error("can't get capability from unknown factory");
|
||||
@@ -98,7 +98,7 @@ BluetoothAudioClientInterface::GetProviderInfo(
|
||||
|
||||
if (provider_factory == nullptr) {
|
||||
provider_factory = IBluetoothAudioProviderFactory::fromBinder(::ndk::SpAIBinder(
|
||||
- AServiceManager_waitForService(kDefaultAudioProviderFactoryInterface.c_str())));
|
||||
+ AServiceManager_waitForService(audioProviderFactoryInterface().c_str())));
|
||||
}
|
||||
|
||||
if (provider_factory == nullptr) {
|
||||
@@ -174,7 +174,7 @@ void BluetoothAudioClientInterface::FetchAudioProvider() {
|
||||
// re-registered, so we need to re-fetch the service.
|
||||
for (int retry_no = 0; retry_no < kFetchAudioProviderRetryNumber; ++retry_no) {
|
||||
auto provider_factory = IBluetoothAudioProviderFactory::fromBinder(::ndk::SpAIBinder(
|
||||
- AServiceManager_waitForService(kDefaultAudioProviderFactoryInterface.c_str())));
|
||||
+ AServiceManager_waitForService(audioProviderFactoryInterface().c_str())));
|
||||
|
||||
if (provider_factory == nullptr) {
|
||||
log::error("can't get capability from unknown factory");
|
||||
diff --git a/system/audio_hal_interface/aidl/a2dp/client_interface_aidl.h b/system/audio_hal_interface/aidl/a2dp/client_interface_aidl.h
|
||||
index e492fde..a24ffef 100644
|
||||
--- a/system/audio_hal_interface/aidl/a2dp/client_interface_aidl.h
|
||||
+++ b/system/audio_hal_interface/aidl/a2dp/client_interface_aidl.h
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "bta/le_audio/broadcaster/broadcaster_types.h"
|
||||
#include "bta/le_audio/le_audio_types.h"
|
||||
#include "transport_instance.h"
|
||||
+#include "osi/include/properties.h"
|
||||
|
||||
// Keep after audio_aidl_interfaces.h because of <base/logging.h>
|
||||
// conflicting definitions.
|
||||
@@ -164,6 +165,12 @@ protected:
|
||||
// "android.hardware.bluetooth.audio.IBluetoothAudioProviderFactory/default";
|
||||
static inline const std::string kDefaultAudioProviderFactoryInterface =
|
||||
std::string() + IBluetoothAudioProviderFactory::descriptor + "/default";
|
||||
+ static inline const std::string kSystemAudioProviderFactoryInterface =
|
||||
+ std::string() + IBluetoothAudioProviderFactory::descriptor + "/sysbta";
|
||||
+ static inline const std::string audioProviderFactoryInterface() {
|
||||
+ return osi_property_get_bool("persist.bluetooth.system_audio_hal.enabled", false)
|
||||
+ ? kSystemAudioProviderFactoryInterface : kDefaultAudioProviderFactoryInterface;
|
||||
+ }
|
||||
|
||||
private:
|
||||
IBluetoothTransportInstance* transport_;
|
||||
diff --git a/system/audio_hal_interface/aidl/client_interface_aidl.cc b/system/audio_hal_interface/aidl/client_interface_aidl.cc
|
||||
index c1ce661..401fd5b 100644
|
||||
--- a/system/audio_hal_interface/aidl/client_interface_aidl.cc
|
||||
+++ b/system/audio_hal_interface/aidl/client_interface_aidl.cc
|
||||
@@ -73,7 +73,7 @@ BluetoothAudioClientInterface::BluetoothAudioClientInterface(IBluetoothTransport
|
||||
bool BluetoothAudioClientInterface::IsValid() const { return provider_ != nullptr; }
|
||||
|
||||
bool BluetoothAudioClientInterface::is_aidl_available() {
|
||||
- return AServiceManager_isDeclared(kDefaultAudioProviderFactoryInterface.c_str());
|
||||
+ return AServiceManager_isDeclared(audioProviderFactoryInterface().c_str());
|
||||
}
|
||||
|
||||
std::vector<AudioCapabilities> BluetoothAudioClientInterface::GetAudioCapabilities() const {
|
||||
@@ -87,7 +87,7 @@ std::vector<AudioCapabilities> BluetoothAudioClientInterface::GetAudioCapabiliti
|
||||
return capabilities;
|
||||
}
|
||||
auto provider_factory = IBluetoothAudioProviderFactory::fromBinder(::ndk::SpAIBinder(
|
||||
- AServiceManager_waitForService(kDefaultAudioProviderFactoryInterface.c_str())));
|
||||
+ AServiceManager_waitForService(audioProviderFactoryInterface().c_str())));
|
||||
|
||||
if (provider_factory == nullptr) {
|
||||
log::error("can't get capability from unknown factory");
|
||||
@@ -112,7 +112,7 @@ BluetoothAudioClientInterface::GetProviderInfo(
|
||||
|
||||
if (provider_factory == nullptr) {
|
||||
provider_factory = IBluetoothAudioProviderFactory::fromBinder(::ndk::SpAIBinder(
|
||||
- AServiceManager_waitForService(kDefaultAudioProviderFactoryInterface.c_str())));
|
||||
+ AServiceManager_waitForService(audioProviderFactoryInterface().c_str())));
|
||||
}
|
||||
|
||||
if (provider_factory == nullptr) {
|
||||
@@ -144,7 +144,7 @@ void BluetoothAudioClientInterface::FetchAudioProvider() {
|
||||
// re-registered, so we need to re-fetch the service.
|
||||
for (int retry_no = 0; retry_no < kFetchAudioProviderRetryNumber; ++retry_no) {
|
||||
auto provider_factory = IBluetoothAudioProviderFactory::fromBinder(::ndk::SpAIBinder(
|
||||
- AServiceManager_waitForService(kDefaultAudioProviderFactoryInterface.c_str())));
|
||||
+ AServiceManager_waitForService(audioProviderFactoryInterface().c_str())));
|
||||
|
||||
if (provider_factory == nullptr) {
|
||||
log::error("can't get capability from unknown factory");
|
||||
diff --git a/system/audio_hal_interface/aidl/client_interface_aidl.h b/system/audio_hal_interface/aidl/client_interface_aidl.h
|
||||
index a3c6038..ee5901e 100644
|
||||
--- a/system/audio_hal_interface/aidl/client_interface_aidl.h
|
||||
+++ b/system/audio_hal_interface/aidl/client_interface_aidl.h
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "bta/le_audio/broadcaster/broadcaster_types.h"
|
||||
#include "bta/le_audio/le_audio_types.h"
|
||||
#include "transport_instance.h"
|
||||
+#include "osi/include/properties.h"
|
||||
|
||||
namespace bluetooth {
|
||||
namespace audio {
|
||||
@@ -150,6 +151,12 @@ protected:
|
||||
// "android.hardware.bluetooth.audio.IBluetoothAudioProviderFactory/default";
|
||||
static inline const std::string kDefaultAudioProviderFactoryInterface =
|
||||
std::string() + IBluetoothAudioProviderFactory::descriptor + "/default";
|
||||
+ static inline const std::string kSystemAudioProviderFactoryInterface =
|
||||
+ std::string() + IBluetoothAudioProviderFactory::descriptor + "/sysbta";
|
||||
+ static inline const std::string audioProviderFactoryInterface() {
|
||||
+ return osi_property_get_bool("persist.bluetooth.system_audio_hal.enabled", false)
|
||||
+ ? kSystemAudioProviderFactoryInterface : kDefaultAudioProviderFactoryInterface;
|
||||
+ }
|
||||
|
||||
private:
|
||||
IBluetoothTransportInstance* transport_;
|
||||
diff --git a/system/audio_hal_interface/hal_version_manager.cc b/system/audio_hal_interface/hal_version_manager.cc
|
||||
index 1a92c1a..bb27167 100644
|
||||
--- a/system/audio_hal_interface/hal_version_manager.cc
|
||||
+++ b/system/audio_hal_interface/hal_version_manager.cc
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <android/hidl/manager/1.2/IServiceManager.h>
|
||||
#include <bluetooth/log.h>
|
||||
#include <hidl/ServiceManagement.h>
|
||||
+#include "osi/include/properties.h"
|
||||
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
@@ -34,6 +35,12 @@ using ::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProviderFactor
|
||||
|
||||
static const std::string kDefaultAudioProviderFactoryInterface =
|
||||
std::string() + IBluetoothAudioProviderFactory::descriptor + "/default";
|
||||
+static const std::string kSystemAudioProviderFactoryInterface =
|
||||
+ std::string() + IBluetoothAudioProviderFactory::descriptor + "/sysbta";
|
||||
+static inline const std::string audioProviderFactoryInterface() {
|
||||
+ return osi_property_get_bool("persist.bluetooth.system_audio_hal.enabled", false)
|
||||
+ ? kSystemAudioProviderFactoryInterface : kDefaultAudioProviderFactoryInterface;
|
||||
+}
|
||||
|
||||
std::string toString(BluetoothAudioHalTransport transport) {
|
||||
switch (transport) {
|
||||
@@ -74,7 +81,7 @@ BluetoothAudioHalVersion GetAidlInterfaceVersion() {
|
||||
static auto aidl_version = []() -> BluetoothAudioHalVersion {
|
||||
int version = 0;
|
||||
auto provider_factory = IBluetoothAudioProviderFactory::fromBinder(::ndk::SpAIBinder(
|
||||
- AServiceManager_waitForService(kDefaultAudioProviderFactoryInterface.c_str())));
|
||||
+ AServiceManager_waitForService(audioProviderFactoryInterface().c_str())));
|
||||
|
||||
if (provider_factory == nullptr) {
|
||||
log::error("getInterfaceVersion: Can't get aidl version from unknown factory");
|
||||
@@ -139,7 +146,7 @@ android::sp<IBluetoothAudioProvidersFactory_2_0> HalVersionManager::GetProviders
|
||||
|
||||
HalVersionManager::HalVersionManager() {
|
||||
hal_transport_ = BluetoothAudioHalTransport::UNKNOWN;
|
||||
- if (AServiceManager_checkService(kDefaultAudioProviderFactoryInterface.c_str()) != nullptr) {
|
||||
+ if (AServiceManager_checkService(audioProviderFactoryInterface().c_str()) != nullptr) {
|
||||
hal_version_ = GetAidlInterfaceVersion();
|
||||
hal_transport_ = BluetoothAudioHalTransport::AIDL;
|
||||
return;
|
||||
--
|
||||
2.48.1
|
||||
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
From 4caa96b99ee81fb3ff2da51e5f5a53fead2b407a Mon Sep 17 00:00:00 2001
|
||||
From: DerTeufel <dominik-kassel@gmx.de>
|
||||
Date: Wed, 4 Jan 2023 21:39:37 +0100
|
||||
Subject: [PATCH 2/2] Don't crash on status:UNSUPPORTED_REMOTE_OR_LMP_FEATURE
|
||||
|
||||
especially 'opcode:0x811 (SNIFF_SUBRATING)' which is the only one I had observed
|
||||
|
||||
Change-Id: Ic57d6631185370cbfdeafdac00801c6ca27fb755
|
||||
---
|
||||
system/gd/hci/hci_layer.cc | 6 ++++--
|
||||
1 file changed, 4 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/system/gd/hci/hci_layer.cc b/system/gd/hci/hci_layer.cc
|
||||
index 0ab2036..7c1e773 100644
|
||||
--- a/system/gd/hci/hci_layer.cc
|
||||
+++ b/system/gd/hci/hci_layer.cc
|
||||
@@ -255,8 +255,10 @@ struct HciLayer::impl {
|
||||
using WaitingFor = CommandQueueEntry::WaitingFor;
|
||||
WaitingFor waiting_for = command_queue_.front().waiting_for_;
|
||||
CommandStatusView status_view = CommandStatusView::Create(event);
|
||||
- if (is_vendor_specific && (is_status && waiting_for == WaitingFor::COMPLETE) &&
|
||||
- (status_view.IsValid() && status_view.GetStatus() == ErrorCode::UNKNOWN_HCI_COMMAND)) {
|
||||
+ if ((is_vendor_specific && (is_status && waiting_for == WaitingFor::COMPLETE) &&
|
||||
+ (status_view.IsValid() && status_view.GetStatus() == ErrorCode::UNKNOWN_HCI_COMMAND)) ||
|
||||
+ ((is_status && waiting_for == WaitingFor::COMPLETE) &&
|
||||
+ (status_view.IsValid() && status_view.GetStatus() == ErrorCode::UNSUPPORTED_REMOTE_OR_LMP_FEATURE))) {
|
||||
// If this is a command status of a vendor specific command, and command complete is expected,
|
||||
// we can't treat this as hard failure since we have no way of probing this lack of support at
|
||||
// earlier time. Instead we let the command complete handler handle a empty Command Complete
|
||||
--
|
||||
2.48.1
|
||||
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
From 8ded06db0162f1b34307d97b39ee5f2c1fb1412f Mon Sep 17 00:00:00 2001
|
||||
From: Peter Cai <peter@typeblog.net>
|
||||
Date: Sat, 16 Mar 2024 15:27:27 -0400
|
||||
Subject: [PATCH] Revert "drop support for V gsi on pixel 5 R base kernel"
|
||||
|
||||
This reverts commit bbbd18a71368a80f689b924dcf82062c2ee351b2.
|
||||
---
|
||||
..._android_server_connectivity_ClatCoordinator.cpp | 13 +++++++++++++
|
||||
1 file changed, 13 insertions(+)
|
||||
|
||||
diff --git a/service/jni/com_android_server_connectivity_ClatCoordinator.cpp b/service/jni/com_android_server_connectivity_ClatCoordinator.cpp
|
||||
index 70991eb..437e78f 100644
|
||||
--- a/service/jni/com_android_server_connectivity_ClatCoordinator.cpp
|
||||
+++ b/service/jni/com_android_server_connectivity_ClatCoordinator.cpp
|
||||
@@ -91,6 +91,11 @@ static void verifyPerms(const char * const path,
|
||||
|
||||
#undef ALOGF
|
||||
|
||||
+bool isGsiImage() {
|
||||
+ // this implementation matches 2 other places in the codebase (same function name too)
|
||||
+ return !access("/system/system_ext/etc/init/init.gsi.rc", F_OK);
|
||||
+}
|
||||
+
|
||||
static const char* kClatdDir = "/apex/com.android.tethering/bin/for-system";
|
||||
static const char* kClatdBin = "/apex/com.android.tethering/bin/for-system/clatd";
|
||||
|
||||
@@ -132,6 +137,14 @@ static void verifyClatPerms() {
|
||||
|
||||
#undef V2
|
||||
|
||||
+ // HACK: Some old vendor kernels lack ~5.10 backport of 'bpffs selinux genfscon' support.
|
||||
+ // This is *NOT* supported, but let's allow, at least for now, U+ GSI to boot on them.
|
||||
+ // (without this hack pixel5 R vendor + U gsi breaks)
|
||||