Merge "Expose VCN APIs for framework code" into aosp-main-future
diff --git a/AconfigFlags.bp b/AconfigFlags.bp
index 403bb74..9b611d9 100644
--- a/AconfigFlags.bp
+++ b/AconfigFlags.bp
@@ -53,7 +53,7 @@
"android.media.tv.flags-aconfig-java",
"android.multiuser.flags-aconfig-java",
"android.net.platform.flags-aconfig-java",
- "android.net.vcn.flags-aconfig-java",
+ "android.net.vcn.flags-aconfig-java-export",
"android.net.wifi.flags-aconfig-java",
"android.nfc.flags-aconfig-java",
"android.os.flags-aconfig-java",
@@ -106,6 +106,7 @@
"framework_graphics_flags_java_lib",
"hwui_flags_java_lib",
"interaction_jank_monitor_flags_lib",
+ "keystore2_flags_java-framework",
"libcore_exported_aconfig_flags_lib",
"libgui_flags_java_lib",
"power_flags_lib",
@@ -1099,16 +1100,21 @@
}
// VCN
+// TODO:376339506 Move the VCN code, the flag declaration and
+// java_aconfig_library to framework-connectivity-b
aconfig_declarations {
name: "android.net.vcn.flags-aconfig",
package: "android.net.vcn",
- container: "system",
+ container: "com.android.tethering",
+ exportable: true,
srcs: ["core/java/android/net/vcn/*.aconfig"],
}
java_aconfig_library {
- name: "android.net.vcn.flags-aconfig-java",
+ name: "android.net.vcn.flags-aconfig-java-export",
aconfig_declarations: "android.net.vcn.flags-aconfig",
+ mode: "exported",
+ min_sdk_version: "35",
defaults: ["framework-minus-apex-aconfig-java-defaults"],
}
diff --git a/Android.bp b/Android.bp
index e537480..35cc35a 100644
--- a/Android.bp
+++ b/Android.bp
@@ -107,7 +107,6 @@
":android.hardware.radio.data-V3-java-source",
":android.hardware.radio.network-V3-java-source",
":android.hardware.radio.voice-V3-java-source",
- ":android.hardware.security.keymint-V3-java-source",
":android.hardware.security.secureclock-V1-java-source",
":android.hardware.thermal-V2-java-source",
":android.hardware.tv.tuner-V3-java-source",
@@ -116,7 +115,6 @@
":android.security.legacykeystore-java-source",
":android.security.maintenance-java-source",
":android.security.metrics-java-source",
- ":android.system.keystore2-V4-java-source",
":android.hardware.cas-V1-java-source",
":credstore_aidl",
":dumpstate_aidl",
@@ -151,7 +149,16 @@
":framework-javastream-protos",
":statslog-framework-java-gen", // FrameworkStatsLog.java
":audio_policy_configuration_V7_0",
- ],
+ ] + select(release_flag("RELEASE_ATTEST_MODULES"), {
+ true: [
+ ":android.hardware.security.keymint-V4-java-source",
+ ":android.system.keystore2-V5-java-source",
+ ],
+ default: [
+ ":android.hardware.security.keymint-V3-java-source",
+ ":android.system.keystore2-V4-java-source",
+ ],
+ }),
}
java_library {
@@ -391,6 +398,8 @@
"ext",
"framework-updatable-stubs-module_libs_api",
"unsupportedappusage",
+ // TODO(b/379770939): remove prod version of flags from other containers in framework
+ "aconfig_storage_stub",
],
sdk_version: "core_platform",
static_libs: [
diff --git a/FF_LEADS_OWNERS b/FF_LEADS_OWNERS
new file mode 100644
index 0000000..a650c6b
--- /dev/null
+++ b/FF_LEADS_OWNERS
@@ -0,0 +1,10 @@
+bills@google.com
+carmenjackson@google.com
+nalini@google.com
+nosh@google.com
+olilan@google.com
+philipcuadra@google.com
+rajekumar@google.com
+shayba@google.com
+timmurray@google.com
+zezeozue@google.com
diff --git a/cmds/interrupter/Android.bp b/cmds/interrupter/Android.bp
deleted file mode 100644
index d7f744d..0000000
--- a/cmds/interrupter/Android.bp
+++ /dev/null
@@ -1,20 +0,0 @@
-package {
- // See: http://go/android-license-faq
- // A large-scale-change added 'default_applicable_licenses' to import
- // all of the 'license_kinds' from "frameworks_base_license"
- // to get the below license kinds:
- // SPDX-license-identifier-Apache-2.0
- default_applicable_licenses: ["frameworks_base_license"],
-}
-
-cc_library_shared {
- name: "interrupter",
- host_supported: true,
- srcs: ["interrupter.c"],
- cflags: [
- "-Wall",
- "-Werror",
- "-Wunused",
- "-Wunreachable-code",
- ],
-}
diff --git a/cmds/interrupter/interrupter.c b/cmds/interrupter/interrupter.c
deleted file mode 100644
index ae55515..0000000
--- a/cmds/interrupter/interrupter.c
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright 2012, 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.
- */
-
-
-/**
- * The probability of a syscall failing from 0.0 to 1.0
- */
-#define PROBABILITY 0.9
-
-
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-
-/* for various intercepted calls */
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-/* For builds on glibc */
-#define __USE_GNU
-#include <dlfcn.h>
-
-#include "interrupter.h"
-
-static int probability = PROBABILITY * RAND_MAX;
-
-static int maybe_interrupt() {
- if (rand() < probability) {
- return 1;
- }
- return 0;
-}
-
-DEFINE_INTERCEPT(read, ssize_t, int, void*, size_t);
-DEFINE_INTERCEPT(write, ssize_t, int, const void*, size_t);
-DEFINE_INTERCEPT(accept, int, int, struct sockaddr*, socklen_t*);
-DEFINE_INTERCEPT(creat, int, const char*, mode_t);
diff --git a/cmds/interrupter/interrupter.h b/cmds/interrupter/interrupter.h
deleted file mode 100644
index 9ad0277e..0000000
--- a/cmds/interrupter/interrupter.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright 2012, 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.
- */
-
-#define CONCATENATE(arg1, arg2) CONCATENATE1(arg1, arg2)
-#define CONCATENATE1(arg1, arg2) CONCATENATE2(arg1, arg2)
-#define CONCATENATE2(arg1, arg2) arg1##arg2
-
-#define INTERRUPTER(sym) \
- if (real_##sym == NULL) \
- __init_##sym(); \
- if (maybe_interrupt()) { \
- errno = EINTR; \
- return -1; \
- }
-
-#define CALL_FUNCTION_1(sym, ret, type1) \
-ret (*real_##sym)(type1) = NULL; \
-ret sym(type1 arg1) { \
- INTERRUPTER(sym) \
- return real_##sym(arg1); \
-}
-
-#define CALL_FUNCTION_2(sym, ret, type1, type2) \
-ret (*real_##sym)(type1, type2) = NULL; \
-ret sym(type1 arg1, type2 arg2) { \
- INTERRUPTER(sym) \
- return real_##sym(arg1, arg2); \
-}
-
-#define CALL_FUNCTION_3(sym, ret, type1, type2, type3) \
-ret (*real_##sym)(type1, type2, type3) = NULL; \
-ret sym(type1 arg1, type2 arg2, type3 arg3) { \
- INTERRUPTER(sym) \
- return real_##sym(arg1, arg2, arg3); \
-}
-
-#define CALL_FUNCTION_4(sym, ret, type1, type2, type3, type4) \
-ret (*real_##sym)(type1, type2, type3, type4) = NULL; \
-ret sym(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \
- INTERRUPTER(sym) \
- return real_##sym(arg1, arg2, arg3, arg4); \
-}
-
-#define CALL_FUNCTION_5(sym, ret, type1, type2, type3, type4, type5) \
-ret (*real_##sym)(type1, type2, type3, type4, type5) = NULL; \
-ret sym(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) { \
- INTERRUPTER(sym) \
- return real_##sym(arg1, arg2, arg3, arg4, arg5); \
-}
-
-#define DEFINE_INTERCEPT_N(N, sym, ret, ...) \
-static void __init_##sym(void); \
-CONCATENATE(CALL_FUNCTION_, N)(sym, ret, __VA_ARGS__) \
-static void __init_##sym(void) { \
- real_##sym = dlsym(RTLD_NEXT, #sym); \
- if (real_##sym == NULL) { \
- fprintf(stderr, "Error hooking " #sym ": %s\n", dlerror()); \
- } \
-}
-
-#define INTERCEPT_NARG(...) INTERCEPT_NARG_N(__VA_ARGS__, INTERCEPT_RSEQ_N())
-#define INTERCEPT_NARG_N(...) INTERCEPT_ARG_N(__VA_ARGS__)
-#define INTERCEPT_ARG_N(_1, _2, _3, _4, _5, _6, _7, _8, N, ...) N
-#define INTERCEPT_RSEQ_N() 8, 7, 6, 5, 4, 3, 2, 1, 0
-
-#define DEFINE_INTERCEPT(sym, ret, ...) DEFINE_INTERCEPT_N(INTERCEPT_NARG(__VA_ARGS__), sym, ret, __VA_ARGS__)
diff --git a/cmds/uiautomator/library/core-src/com/android/uiautomator/core/AccessibilityNodeInfoDumper.java b/cmds/uiautomator/library/core-src/com/android/uiautomator/core/AccessibilityNodeInfoDumper.java
index f726361..a88796c3 100644
--- a/cmds/uiautomator/library/core-src/com/android/uiautomator/core/AccessibilityNodeInfoDumper.java
+++ b/cmds/uiautomator/library/core-src/com/android/uiautomator/core/AccessibilityNodeInfoDumper.java
@@ -217,6 +217,9 @@
serializer.attribute("", "selected", Boolean.toString(node.isSelected()));
serializer.attribute("", "bounds", AccessibilityNodeInfoHelper.getVisibleBoundsInScreen(
node, width, height).toShortString());
+ serializer.attribute("", "drawing-order", Integer.toString(node.getDrawingOrder()));
+ serializer.attribute("", "hint", safeCharSeqToString(node.getHintText()));
+
int count = node.getChildCount();
for (int i = 0; i < count; i++) {
AccessibilityNodeInfo child = node.getChild(i);
diff --git a/core/api/current.txt b/core/api/current.txt
index b918d96..aa1098b 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -13172,6 +13172,7 @@
field public static final String FEATURE_BACKUP = "android.software.backup";
field public static final String FEATURE_BLUETOOTH = "android.hardware.bluetooth";
field public static final String FEATURE_BLUETOOTH_LE = "android.hardware.bluetooth_le";
+ field @FlaggedApi("com.android.ranging.flags.ranging_cs_enabled") public static final String FEATURE_BLUETOOTH_LE_CHANNEL_SOUNDING = "android.hardware.bluetooth_le.channel_sounding";
field public static final String FEATURE_CAMERA = "android.hardware.camera";
field public static final String FEATURE_CAMERA_ANY = "android.hardware.camera.any";
field public static final String FEATURE_CAMERA_AR = "android.hardware.camera.ar";
@@ -22841,7 +22842,6 @@
method public boolean isVendor();
field @FlaggedApi("android.media.codec.in_process_sw_audio_codec") public static final int SECURITY_MODEL_MEMORY_SAFE = 1; // 0x1
field @FlaggedApi("android.media.codec.in_process_sw_audio_codec") public static final int SECURITY_MODEL_SANDBOXED = 0; // 0x0
- field @FlaggedApi("android.media.codec.in_process_sw_audio_codec") public static final int SECURITY_MODEL_TRUSTED_CONTENT_ONLY = 2; // 0x2
}
public static final class MediaCodecInfo.AudioCapabilities {
@@ -23732,7 +23732,6 @@
field public static final int COLOR_TRANSFER_ST2084 = 6; // 0x6
field @FlaggedApi("android.media.codec.in_process_sw_audio_codec") public static final int FLAG_SECURITY_MODEL_MEMORY_SAFE = 2; // 0x2
field @FlaggedApi("android.media.codec.in_process_sw_audio_codec") public static final int FLAG_SECURITY_MODEL_SANDBOXED = 1; // 0x1
- field @FlaggedApi("android.media.codec.in_process_sw_audio_codec") public static final int FLAG_SECURITY_MODEL_TRUSTED_CONTENT_ONLY = 4; // 0x4
field public static final String KEY_AAC_DRC_ALBUM_MODE = "aac-drc-album-mode";
field public static final String KEY_AAC_DRC_ATTENUATION_FACTOR = "aac-drc-cut-level";
field public static final String KEY_AAC_DRC_BOOST_FACTOR = "aac-drc-boost-level";
@@ -33308,7 +33307,7 @@
}
public interface IBinder {
- method @FlaggedApi("android.os.binder_frozen_state_change_callback") public default void addFrozenStateChangeCallback(@NonNull android.os.IBinder.FrozenStateChangeCallback) throws android.os.RemoteException;
+ method @FlaggedApi("android.os.binder_frozen_state_change_callback") public default void addFrozenStateChangeCallback(@NonNull java.util.concurrent.Executor, @NonNull android.os.IBinder.FrozenStateChangeCallback) throws android.os.RemoteException;
method public void dump(@NonNull java.io.FileDescriptor, @Nullable String[]) throws android.os.RemoteException;
method public void dumpAsync(@NonNull java.io.FileDescriptor, @Nullable String[]) throws android.os.RemoteException;
method @Nullable public String getInterfaceDescriptor() throws android.os.RemoteException;
@@ -33932,6 +33931,7 @@
method public void finishBroadcast();
method public Object getBroadcastCookie(int);
method public E getBroadcastItem(int);
+ method @FlaggedApi("android.os.binder_frozen_state_change_callback") @Nullable public java.util.concurrent.Executor getExecutor();
method @FlaggedApi("android.os.binder_frozen_state_change_callback") public int getFrozenCalleePolicy();
method @FlaggedApi("android.os.binder_frozen_state_change_callback") public int getMaxQueueSize();
method public Object getRegisteredCallbackCookie(int);
@@ -33952,6 +33952,7 @@
@FlaggedApi("android.os.binder_frozen_state_change_callback") public static final class RemoteCallbackList.Builder<E extends android.os.IInterface> {
ctor public RemoteCallbackList.Builder(int);
method @NonNull public android.os.RemoteCallbackList<E> build();
+ method @NonNull public android.os.RemoteCallbackList.Builder setExecutor(@NonNull java.util.concurrent.Executor);
method @NonNull public android.os.RemoteCallbackList.Builder setInterfaceDiedCallback(@NonNull android.os.RemoteCallbackList.Builder.InterfaceDiedCallback<E>);
method @NonNull public android.os.RemoteCallbackList.Builder setMaxQueueSize(int);
}
@@ -46077,6 +46078,8 @@
method public long getDataUsageBytes();
method public long getDataUsageTime();
method @NonNull public int[] getNetworkTypes();
+ method @FlaggedApi("com.android.internal.telephony.flags.subscription_plan_allow_status_and_end_date") @Nullable public java.time.ZonedDateTime getPlanEndDate();
+ method @FlaggedApi("com.android.internal.telephony.flags.subscription_plan_allow_status_and_end_date") public int getSubscriptionStatus();
method @Nullable public CharSequence getSummary();
method @Nullable public CharSequence getTitle();
method public void writeToParcel(android.os.Parcel, int);
@@ -46087,6 +46090,11 @@
field public static final int LIMIT_BEHAVIOR_DISABLED = 0; // 0x0
field public static final int LIMIT_BEHAVIOR_THROTTLED = 2; // 0x2
field public static final int LIMIT_BEHAVIOR_UNKNOWN = -1; // 0xffffffff
+ field @FlaggedApi("com.android.internal.telephony.flags.subscription_plan_allow_status_and_end_date") public static final int SUBSCRIPTION_STATUS_ACTIVE = 1; // 0x1
+ field @FlaggedApi("com.android.internal.telephony.flags.subscription_plan_allow_status_and_end_date") public static final int SUBSCRIPTION_STATUS_INACTIVE = 2; // 0x2
+ field @FlaggedApi("com.android.internal.telephony.flags.subscription_plan_allow_status_and_end_date") public static final int SUBSCRIPTION_STATUS_SUSPENDED = 4; // 0x4
+ field @FlaggedApi("com.android.internal.telephony.flags.subscription_plan_allow_status_and_end_date") public static final int SUBSCRIPTION_STATUS_TRIAL = 3; // 0x3
+ field @FlaggedApi("com.android.internal.telephony.flags.subscription_plan_allow_status_and_end_date") public static final int SUBSCRIPTION_STATUS_UNKNOWN = 0; // 0x0
field public static final long TIME_UNKNOWN = -1L; // 0xffffffffffffffffL
}
@@ -46098,6 +46106,7 @@
method public android.telephony.SubscriptionPlan.Builder setDataLimit(long, int);
method public android.telephony.SubscriptionPlan.Builder setDataUsage(long, long);
method @NonNull public android.telephony.SubscriptionPlan.Builder setNetworkTypes(@NonNull int[]);
+ method @FlaggedApi("com.android.internal.telephony.flags.subscription_plan_allow_status_and_end_date") @NonNull public android.telephony.SubscriptionPlan.Builder setSubscriptionStatus(int);
method public android.telephony.SubscriptionPlan.Builder setSummary(@Nullable CharSequence);
method public android.telephony.SubscriptionPlan.Builder setTitle(@Nullable CharSequence);
}
diff --git a/core/java/Android.bp b/core/java/Android.bp
index d4f24ee..165b481 100644
--- a/core/java/Android.bp
+++ b/core/java/Android.bp
@@ -667,43 +667,8 @@
// protolog end
-// Whether to enable read-only system feature codegen.
-gen_readonly_feature_apis = select(release_flag("RELEASE_USE_SYSTEM_FEATURE_BUILD_FLAGS"), {
- true: "true",
- false: "false",
- default: "false",
-})
-
-// Generates com.android.internal.pm.RoSystemFeatures, optionally compiling in
-// details about fixed system features defined by build flags. When disabled,
-// the APIs are simply passthrough stubs with no meaningful side effects.
-// TODO(b/203143243): Implement the `--feature=` aggregation directly with a native soong module.
-genrule {
+java_system_features_srcs {
name: "systemfeatures-gen-srcs",
- cmd: "$(location systemfeatures-gen-tool) com.android.internal.pm.RoSystemFeatures " +
- // --readonly=false (default) makes the codegen an effective no-op passthrough API.
- " --readonly=" + gen_readonly_feature_apis +
- " --feature=AUTOMOTIVE:" + select(release_flag("RELEASE_SYSTEM_FEATURE_AUTOMOTIVE"), {
- any @ value: value,
- default: "",
- }) + " --feature=EMBEDDED:" + select(release_flag("RELEASE_SYSTEM_FEATURE_EMBEDDED"), {
- any @ value: value,
- default: "",
- }) + " --feature=LEANBACK:" + select(release_flag("RELEASE_SYSTEM_FEATURE_LEANBACK"), {
- any @ value: value,
- default: "",
- }) + " --feature=PC:" + select(release_flag("RELEASE_SYSTEM_FEATURE_PC"), {
- any @ value: value,
- default: "",
- }) + " --feature=TELEVISION:" + select(release_flag("RELEASE_SYSTEM_FEATURE_TELEVISION"), {
- any @ value: value,
- default: "",
- }) + " --feature=WATCH:" + select(release_flag("RELEASE_SYSTEM_FEATURE_WATCH"), {
- any @ value: value,
- default: "",
- }) + " > $(out)",
- out: [
- "RoSystemFeatures.java",
- ],
- tools: ["systemfeatures-gen-tool"],
+ full_class_name: "com.android.internal.pm.RoSystemFeatures",
+ visibility: ["//visibility:private"],
}
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 0b33313..7e65439 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -4499,7 +4499,6 @@
* @see #DISPLAY_HASH_SERVICE
* @see android.view.displayhash.DisplayHashManager
*/
- // TODO(b/347269120): Re-add @Nullable
public abstract Object getSystemService(@ServiceName @NonNull String name);
/**
@@ -4545,7 +4544,6 @@
*/
@SuppressWarnings("unchecked")
@RavenwoodKeep
- // TODO(b/347269120): Re-add @Nullable
public final <T> T getSystemService(@NonNull Class<T> serviceClass) {
// Because subclasses may override getSystemService(String) we cannot
// perform a lookup by class alone. We must first map the class to its
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index 79fa6ea..77aa628 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -953,7 +953,6 @@
}
@Override
- // TODO(b/347269120): Re-add @Nullable
public Object getSystemService(String name) {
return mBase.getSystemService(name);
}
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index 481e6b5..a398c3f 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -451,6 +451,13 @@
* Value of {@link #colorMode} indicating that the activity should use a
* high dynamic range if the presentation display supports it.
*
+ * <p>Note: This does not impact SurfaceViews or SurfaceControls, as those have their own
+ * independent HDR support.</p>
+ *
+ * <p><b>Important:</b> Although this value was added in API 26, it is strongly recommended
+ * to avoid using it until API 34 which is when HDR support for the UI toolkit was officially
+ * added.</p>
+ *
* @see android.R.attr#colorMode
*/
public static final int COLOR_MODE_HDR = 2;
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 9ba5b39..caa22e2 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -3164,6 +3164,16 @@
/**
* Feature for {@link #getSystemAvailableFeatures} and
+ * {@link #hasSystemFeature}: The device is capable of ranging with
+ * other devices using channel sounding via Bluetooth Low Energy radio.
+ */
+ @FlaggedApi(com.android.ranging.flags.Flags.FLAG_RANGING_CS_ENABLED)
+ @SdkConstant(SdkConstantType.FEATURE)
+ public static final String FEATURE_BLUETOOTH_LE_CHANNEL_SOUNDING =
+ "android.hardware.bluetooth_le.channel_sounding";
+
+ /**
+ * Feature for {@link #getSystemAvailableFeatures} and
* {@link #hasSystemFeature}: The device has a camera facing away
* from the screen.
*/
diff --git a/core/java/android/net/vcn/flags.aconfig b/core/java/android/net/vcn/flags.aconfig
index 1b2c575..b461f95 100644
--- a/core/java/android/net/vcn/flags.aconfig
+++ b/core/java/android/net/vcn/flags.aconfig
@@ -1,5 +1,5 @@
package: "android.net.vcn"
-container: "system"
+container: "com.android.tethering"
flag {
name: "safe_mode_config"
@@ -15,14 +15,4 @@
description: "Expose APIs from VCN for mainline migration"
is_exported: true
bug: "376339506"
-}
-
-flag {
- name: "fix_config_garbage_collection"
- namespace: "vcn"
- description: "Handle race condition in subscription change"
- bug: "370862489"
- metadata {
- purpose: PURPOSE_BUGFIX
- }
}
\ No newline at end of file
diff --git a/core/java/android/os/BinderProxy.java b/core/java/android/os/BinderProxy.java
index 3b5a99e..01222cd 100644
--- a/core/java/android/os/BinderProxy.java
+++ b/core/java/android/os/BinderProxy.java
@@ -36,6 +36,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
@@ -651,28 +652,39 @@
private native boolean unlinkToDeathNative(DeathRecipient recipient, int flags);
/**
- * This list is to hold strong reference to the frozen state callbacks. The callbacks are only
- * weakly referenced by JNI so the strong references here are needed to keep the callbacks
- * around until the proxy is GC'ed.
+ * This map is to hold strong reference to the frozen state callbacks.
+ *
+ * The callbacks are only weakly referenced by JNI so the strong references here are needed to
+ * keep the callbacks around until the proxy is GC'ed.
+ *
+ * The key is the original callback passed into {@link #addFrozenStateChangeCallback}. The value
+ * is the wrapped callback created in {@link #addFrozenStateChangeCallback} to dispatch the
+ * calls on the desired executor.
*/
- private List<FrozenStateChangeCallback> mFrozenStateChangeCallbacks =
- Collections.synchronizedList(new ArrayList<>());
+ private Map<FrozenStateChangeCallback, FrozenStateChangeCallback> mFrozenStateChangeCallbacks =
+ Collections.synchronizedMap(new HashMap<>());
/**
* See {@link IBinder#addFrozenStateChangeCallback(FrozenStateChangeCallback)}
*/
- public void addFrozenStateChangeCallback(FrozenStateChangeCallback callback)
+ public void addFrozenStateChangeCallback(Executor executor, FrozenStateChangeCallback callback)
throws RemoteException {
- addFrozenStateChangeCallbackNative(callback);
- mFrozenStateChangeCallbacks.add(callback);
+ FrozenStateChangeCallback wrappedCallback = (who, state) ->
+ executor.execute(() -> callback.onFrozenStateChanged(who, state));
+ addFrozenStateChangeCallbackNative(wrappedCallback);
+ mFrozenStateChangeCallbacks.put(callback, wrappedCallback);
}
/**
* See {@link IBinder#removeFrozenStateChangeCallback}
*/
- public boolean removeFrozenStateChangeCallback(FrozenStateChangeCallback callback) {
- mFrozenStateChangeCallbacks.remove(callback);
- return removeFrozenStateChangeCallbackNative(callback);
+ public boolean removeFrozenStateChangeCallback(FrozenStateChangeCallback callback)
+ throws IllegalArgumentException {
+ FrozenStateChangeCallback wrappedCallback = mFrozenStateChangeCallbacks.remove(callback);
+ if (wrappedCallback == null) {
+ throw new IllegalArgumentException("callback not found");
+ }
+ return removeFrozenStateChangeCallbackNative(wrappedCallback);
}
private native void addFrozenStateChangeCallbackNative(FrozenStateChangeCallback callback)
diff --git a/core/java/android/os/ConcurrentMessageQueue/MessageQueue.java b/core/java/android/os/ConcurrentMessageQueue/MessageQueue.java
index b2d9260..57ce421 100644
--- a/core/java/android/os/ConcurrentMessageQueue/MessageQueue.java
+++ b/core/java/android/os/ConcurrentMessageQueue/MessageQueue.java
@@ -52,7 +52,7 @@
* {@link Looper#myQueue() Looper.myQueue()}.
*/
@RavenwoodKeepWholeClass
-@RavenwoodRedirectionClass("MessageQueue_host")
+@RavenwoodRedirectionClass("MessageQueue_ravenwood")
public final class MessageQueue {
private static final String TAG = "ConcurrentMessageQueue";
private static final boolean DEBUG = false;
diff --git a/core/java/android/os/IBinder.java b/core/java/android/os/IBinder.java
index a997f4c..8cfd324 100644
--- a/core/java/android/os/IBinder.java
+++ b/core/java/android/os/IBinder.java
@@ -16,6 +16,7 @@
package android.os;
+import android.annotation.CallbackExecutor;
import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.NonNull;
@@ -25,6 +26,7 @@
import java.io.FileDescriptor;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.concurrent.Executor;
/**
* Base interface for a remotable object, the core part of a lightweight
@@ -397,12 +399,31 @@
@interface State {
}
+ /**
+ * Represents the frozen state of the remote process.
+ *
+ * While in this state, the remote process won't be able to receive and handle a
+ * transaction. Therefore, any asynchronous transactions will be buffered and delivered when
+ * the process is unfrozen, and any synchronous transactions will result in an error.
+ *
+ * Buffered transactions may be stale by the time that the process is unfrozen and handles
+ * them. To avoid overwhelming the remote process with stale events or overflowing their
+ * buffers, it's best to avoid sending binder transactions to a frozen process.
+ */
int STATE_FROZEN = 0;
+
+ /**
+ * Represents the unfrozen state of the remote process.
+ *
+ * In this state, the process hosting the object can execute and is not restricted
+ * by the freezer from using the CPU or responding to binder transactions.
+ */
int STATE_UNFROZEN = 1;
/**
* Interface for receiving a callback when the process hosting an IBinder
* has changed its frozen state.
+ *
* @param who The IBinder whose hosting process has changed state.
* @param state The latest state.
*/
@@ -427,16 +448,32 @@
* <p>You will only receive state change notifications for remote binders, as local binders by
* definition can't be frozen without you being frozen too.</p>
*
+ * @param executor The executor on which to run the callback.
+ * @param callback The callback used to deliver state change notifications.
+ *
* <p>@throws {@link UnsupportedOperationException} if the kernel binder driver does not support
* this feature.
*/
@FlaggedApi(Flags.FLAG_BINDER_FROZEN_STATE_CHANGE_CALLBACK)
- default void addFrozenStateChangeCallback(@NonNull FrozenStateChangeCallback callback)
+ default void addFrozenStateChangeCallback(
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull FrozenStateChangeCallback callback)
throws RemoteException {
throw new UnsupportedOperationException();
}
/**
+ * Same as {@link #addFrozenStateChangeCallback(Executor, FrozenStateChangeCallback)} except
+ * that callbacks are invoked on a binder thread.
+ *
+ * @hide
+ */
+ default void addFrozenStateChangeCallback(@NonNull FrozenStateChangeCallback callback)
+ throws RemoteException {
+ addFrozenStateChangeCallback(Runnable::run, callback);
+ }
+
+ /**
* Unregister a {@link FrozenStateChangeCallback}. The callback will no longer be invoked when
* the hosting process changes its frozen state.
*/
diff --git a/core/java/android/os/LegacyMessageQueue/MessageQueue.java b/core/java/android/os/LegacyMessageQueue/MessageQueue.java
index 4474e7e..d0635cb 100644
--- a/core/java/android/os/LegacyMessageQueue/MessageQueue.java
+++ b/core/java/android/os/LegacyMessageQueue/MessageQueue.java
@@ -43,7 +43,7 @@
* {@link Looper#myQueue() Looper.myQueue()}.
*/
@RavenwoodKeepWholeClass
-@RavenwoodRedirectionClass("MessageQueue_host")
+@RavenwoodRedirectionClass("MessageQueue_ravenwood")
public final class MessageQueue {
private static final String TAG = "MessageQueue";
private static final boolean DEBUG = false;
diff --git a/core/java/android/os/LockedMessageQueue/MessageQueue.java b/core/java/android/os/LockedMessageQueue/MessageQueue.java
index f1affce..84b87aa 100644
--- a/core/java/android/os/LockedMessageQueue/MessageQueue.java
+++ b/core/java/android/os/LockedMessageQueue/MessageQueue.java
@@ -46,7 +46,7 @@
* {@link Looper#myQueue() Looper.myQueue()}.
*/
@RavenwoodKeepWholeClass
-@RavenwoodRedirectionClass("MessageQueue_host")
+@RavenwoodRedirectionClass("MessageQueue_ravenwood")
public final class MessageQueue {
private static final String TAG = "LockedMessageQueue";
private static final boolean DEBUG = false;
diff --git a/core/java/android/os/OWNERS b/core/java/android/os/OWNERS
index 24e1d66..e63b664 100644
--- a/core/java/android/os/OWNERS
+++ b/core/java/android/os/OWNERS
@@ -128,3 +128,6 @@
# Dropbox
per-file DropBoxManager* = mwachens@google.com
+
+# Flags
+per-file flags.aconfig = file:/FF_LEADS_OWNERS
diff --git a/core/java/android/os/RemoteCallbackList.java b/core/java/android/os/RemoteCallbackList.java
index 91c482fa..4123209 100644
--- a/core/java/android/os/RemoteCallbackList.java
+++ b/core/java/android/os/RemoteCallbackList.java
@@ -16,6 +16,7 @@
package android.os;
+import android.annotation.CallbackExecutor;
import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.NonNull;
@@ -29,6 +30,7 @@
import java.lang.annotation.RetentionPolicy;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.Executor;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
@@ -134,6 +136,7 @@
private final @FrozenCalleePolicy int mFrozenCalleePolicy;
private final int mMaxQueueSize;
+ private final Executor mExecutor;
private final class Interface implements IBinder.DeathRecipient,
IBinder.FrozenStateChangeCallback {
@@ -197,7 +200,7 @@
void maybeSubscribeToFrozenCallback() throws RemoteException {
if (mFrozenCalleePolicy != FROZEN_CALLEE_POLICY_UNSET) {
try {
- mBinder.addFrozenStateChangeCallback(this);
+ mBinder.addFrozenStateChangeCallback(mExecutor, this);
} catch (UnsupportedOperationException e) {
// The kernel does not support frozen notifications. In this case we want to
// silently fall back to FROZEN_CALLEE_POLICY_UNSET. This is done by simply
@@ -211,7 +214,7 @@
if (mFrozenCalleePolicy != FROZEN_CALLEE_POLICY_UNSET) {
try {
mBinder.removeFrozenStateChangeCallback(this);
- } catch (UnsupportedOperationException e) {
+ } catch (UnsupportedOperationException | IllegalArgumentException e) {
// The kernel does not support frozen notifications. Ignore the error and move
// on.
}
@@ -237,6 +240,7 @@
private @FrozenCalleePolicy int mFrozenCalleePolicy;
private int mMaxQueueSize = DEFAULT_MAX_QUEUE_SIZE;
private InterfaceDiedCallback mInterfaceDiedCallback;
+ private Executor mExecutor;
/**
* Creates a Builder for {@link RemoteCallbackList}.
@@ -285,6 +289,18 @@
}
/**
+ * Sets the executor to be used when invoking callbacks asynchronously.
+ *
+ * This is only used when callbacks need to be invoked asynchronously, e.g. when the process
+ * hosting a callback becomes unfrozen. Callbacks that can be invoked immediately run on the
+ * same thread that calls {@link #broadcast} synchronously.
+ */
+ public @NonNull Builder setExecutor(@NonNull @CallbackExecutor Executor executor) {
+ mExecutor = executor;
+ return this;
+ }
+
+ /**
* For notifying when the process hosting a callback interface has died.
*
* @param <E> The remote callback interface type.
@@ -308,15 +324,21 @@
* @return The built {@link RemoteCallbackList} object.
*/
public @NonNull RemoteCallbackList<E> build() {
+ Executor executor = mExecutor;
+ if (executor == null && mFrozenCalleePolicy != FROZEN_CALLEE_POLICY_UNSET) {
+ // TODO Throw an exception here once the existing API caller is updated to provide
+ // an executor.
+ executor = new HandlerExecutor(Handler.getMain());
+ }
if (mInterfaceDiedCallback != null) {
- return new RemoteCallbackList<E>(mFrozenCalleePolicy, mMaxQueueSize) {
+ return new RemoteCallbackList<E>(mFrozenCalleePolicy, mMaxQueueSize, executor) {
@Override
public void onCallbackDied(E deadInterface, Object cookie) {
mInterfaceDiedCallback.onInterfaceDied(this, deadInterface, cookie);
}
};
}
- return new RemoteCallbackList<E>(mFrozenCalleePolicy, mMaxQueueSize);
+ return new RemoteCallbackList<E>(mFrozenCalleePolicy, mMaxQueueSize, executor);
}
}
@@ -341,13 +363,23 @@
}
/**
+ * Returns the executor used when invoking callbacks asynchronously.
+ *
+ * @return The executor.
+ */
+ @FlaggedApi(Flags.FLAG_BINDER_FROZEN_STATE_CHANGE_CALLBACK)
+ public @Nullable Executor getExecutor() {
+ return mExecutor;
+ }
+
+ /**
* Creates a RemoteCallbackList with {@link #FROZEN_CALLEE_POLICY_UNSET}. This is equivalent to
* <pre>
* new RemoteCallbackList.Build(RemoteCallbackList.FROZEN_CALLEE_POLICY_UNSET).build()
* </pre>
*/
public RemoteCallbackList() {
- this(FROZEN_CALLEE_POLICY_UNSET, DEFAULT_MAX_QUEUE_SIZE);
+ this(FROZEN_CALLEE_POLICY_UNSET, DEFAULT_MAX_QUEUE_SIZE, null);
}
/**
@@ -362,10 +394,14 @@
* recipient's process is frozen. Once the limit is reached, the oldest callbacks would be
* dropped to keep the size under limit. Ignored except for
* {@link #FROZEN_CALLEE_POLICY_ENQUEUE_ALL}.
+ *
+ * @param executor The executor used when invoking callbacks asynchronously.
*/
- private RemoteCallbackList(@FrozenCalleePolicy int frozenCalleePolicy, int maxQueueSize) {
+ private RemoteCallbackList(@FrozenCalleePolicy int frozenCalleePolicy, int maxQueueSize,
+ @CallbackExecutor Executor executor) {
mFrozenCalleePolicy = frozenCalleePolicy;
mMaxQueueSize = maxQueueSize;
+ mExecutor = executor;
}
/**
diff --git a/core/java/android/os/SemiConcurrentMessageQueue/MessageQueue.java b/core/java/android/os/SemiConcurrentMessageQueue/MessageQueue.java
index 80c24a9..9df5a95 100644
--- a/core/java/android/os/SemiConcurrentMessageQueue/MessageQueue.java
+++ b/core/java/android/os/SemiConcurrentMessageQueue/MessageQueue.java
@@ -50,7 +50,7 @@
* {@link Looper#myQueue() Looper.myQueue()}.
*/
@RavenwoodKeepWholeClass
-@RavenwoodRedirectionClass("MessageQueue_host")
+@RavenwoodRedirectionClass("MessageQueue_ravenwood")
public final class MessageQueue {
private static final String TAG = "SemiConcurrentMessageQueue";
private static final boolean DEBUG = false;
diff --git a/core/java/android/telephony/SubscriptionPlan.java b/core/java/android/telephony/SubscriptionPlan.java
index 7b48a16..4c59a85 100644
--- a/core/java/android/telephony/SubscriptionPlan.java
+++ b/core/java/android/telephony/SubscriptionPlan.java
@@ -18,6 +18,7 @@
import android.annotation.BytesLong;
import android.annotation.CurrentTimeMillisLong;
+import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -28,6 +29,7 @@
import android.util.Range;
import android.util.RecurrenceRule;
+import com.android.internal.telephony.flags.Flags;
import com.android.internal.util.Preconditions;
import java.lang.annotation.Retention;
@@ -83,6 +85,33 @@
/** Value indicating a timestamp is unknown. */
public static final long TIME_UNKNOWN = -1;
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = { "SUBSCRIPTION_STATUS_" }, value = {
+ SUBSCRIPTION_STATUS_UNKNOWN,
+ SUBSCRIPTION_STATUS_ACTIVE,
+ SUBSCRIPTION_STATUS_INACTIVE,
+ SUBSCRIPTION_STATUS_TRIAL,
+ SUBSCRIPTION_STATUS_SUSPENDED
+ })
+ public @interface SubscriptionStatus {}
+
+ /** Subscription status is unknown. */
+ @FlaggedApi(Flags.FLAG_SUBSCRIPTION_PLAN_ALLOW_STATUS_AND_END_DATE)
+ public static final int SUBSCRIPTION_STATUS_UNKNOWN = 0;
+ /** Subscription is active. */
+ @FlaggedApi(Flags.FLAG_SUBSCRIPTION_PLAN_ALLOW_STATUS_AND_END_DATE)
+ public static final int SUBSCRIPTION_STATUS_ACTIVE = 1;
+ /** Subscription is inactive. */
+ @FlaggedApi(Flags.FLAG_SUBSCRIPTION_PLAN_ALLOW_STATUS_AND_END_DATE)
+ public static final int SUBSCRIPTION_STATUS_INACTIVE = 2;
+ /** Subscription is in a trial period. */
+ @FlaggedApi(Flags.FLAG_SUBSCRIPTION_PLAN_ALLOW_STATUS_AND_END_DATE)
+ public static final int SUBSCRIPTION_STATUS_TRIAL = 3;
+ /** Subscription is suspended. */
+ @FlaggedApi(Flags.FLAG_SUBSCRIPTION_PLAN_ALLOW_STATUS_AND_END_DATE)
+ public static final int SUBSCRIPTION_STATUS_SUSPENDED = 4;
+
private final RecurrenceRule cycleRule;
private CharSequence title;
private CharSequence summary;
@@ -91,6 +120,7 @@
private long dataUsageBytes = BYTES_UNKNOWN;
private long dataUsageTime = TIME_UNKNOWN;
private @NetworkType int[] networkTypes;
+ private int mSubscriptionStatus = SUBSCRIPTION_STATUS_UNKNOWN;
private SubscriptionPlan(RecurrenceRule cycleRule) {
this.cycleRule = Preconditions.checkNotNull(cycleRule);
@@ -107,6 +137,7 @@
dataUsageBytes = source.readLong();
dataUsageTime = source.readLong();
networkTypes = source.createIntArray();
+ mSubscriptionStatus = source.readInt();
}
@Override
@@ -124,6 +155,7 @@
dest.writeLong(dataUsageBytes);
dest.writeLong(dataUsageTime);
dest.writeIntArray(networkTypes);
+ dest.writeInt(mSubscriptionStatus);
}
@Override
@@ -137,13 +169,14 @@
.append(" dataUsageBytes=").append(dataUsageBytes)
.append(" dataUsageTime=").append(dataUsageTime)
.append(" networkTypes=").append(Arrays.toString(networkTypes))
+ .append(" subscriptionStatus=").append(mSubscriptionStatus)
.append("}").toString();
}
@Override
public int hashCode() {
return Objects.hash(cycleRule, title, summary, dataLimitBytes, dataLimitBehavior,
- dataUsageBytes, dataUsageTime, Arrays.hashCode(networkTypes));
+ dataUsageBytes, dataUsageTime, Arrays.hashCode(networkTypes), mSubscriptionStatus);
}
@Override
@@ -157,7 +190,8 @@
&& dataLimitBehavior == other.dataLimitBehavior
&& dataUsageBytes == other.dataUsageBytes
&& dataUsageTime == other.dataUsageTime
- && Arrays.equals(networkTypes, other.networkTypes);
+ && Arrays.equals(networkTypes, other.networkTypes)
+ && mSubscriptionStatus == other.mSubscriptionStatus;
}
return false;
}
@@ -179,6 +213,13 @@
return cycleRule;
}
+ /** Return the end date of this plan, or null if no end date exists. */
+ @FlaggedApi(Flags.FLAG_SUBSCRIPTION_PLAN_ALLOW_STATUS_AND_END_DATE)
+ public @Nullable ZonedDateTime getPlanEndDate() {
+ // ZonedDateTime is immutable, so no need to create a defensive copy.
+ return cycleRule.end;
+ }
+
/** Return the short title of this plan. */
public @Nullable CharSequence getTitle() {
return title;
@@ -238,6 +279,16 @@
}
/**
+ * Returns the status of the subscription plan.
+ *
+ * @return The subscription status, or {@link #SUBSCRIPTION_STATUS_UNKNOWN} if not available.
+ */
+ @FlaggedApi(Flags.FLAG_SUBSCRIPTION_PLAN_ALLOW_STATUS_AND_END_DATE)
+ public @SubscriptionStatus int getSubscriptionStatus() {
+ return mSubscriptionStatus;
+ }
+
+ /**
* Builder for a {@link SubscriptionPlan}.
*/
public static class Builder {
@@ -382,5 +433,21 @@
TelephonyManager.getAllNetworkTypes().length);
return this;
}
+
+ /**
+ * Set the subscription status.
+ *
+ * @param subscriptionStatus the current subscription status
+ */
+ @FlaggedApi(Flags.FLAG_SUBSCRIPTION_PLAN_ALLOW_STATUS_AND_END_DATE)
+ public @NonNull Builder setSubscriptionStatus(@SubscriptionStatus int subscriptionStatus) {
+ if (subscriptionStatus < SUBSCRIPTION_STATUS_UNKNOWN
+ || subscriptionStatus > SUBSCRIPTION_STATUS_SUSPENDED) {
+ throw new IllegalArgumentException(
+ "Subscription status must be defined with a valid value");
+ }
+ plan.mSubscriptionStatus = subscriptionStatus;
+ return this;
+ }
}
}
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index f7745d1..f0d2a34 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -899,7 +899,8 @@
/**
* Sets the desired amount of HDR headroom to be used when HDR content is presented on this
- * SurfaceView.
+ * SurfaceView. This is expressed as the ratio of maximum HDR white point over the SDR
+ * white point, not as absolute nits.
*
* <p>By default the system will choose an amount of HDR headroom that is appropriate
* for the underlying device capabilities & bit-depth of the panel. However, for some types
@@ -913,6 +914,10 @@
* See {@link Display#getHdrSdrRatio()} for more information as well as how to query the
* current value.</p>
*
+ * <p>Note: This API operates independently of both the
+ * {@link Window#setColorMode Widow color mode} and the
+ * {@link Window#setDesiredHdrHeadroom Window desiredHdrHeadroom}</p>
+ *
* @param desiredHeadroom The amount of HDR headroom that is desired. Must be >= 1.0 (no HDR)
* and <= 10,000.0. Passing 0.0 will reset to the default, automatically
* chosen value.
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 0582afe..cbee563 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -1334,6 +1334,9 @@
* <p>The requested color mode is not guaranteed to be honored. Please refer to
* {@link #getColorMode()} for more information.</p>
*
+ * <p>Note: This does not impact SurfaceViews or SurfaceControls, as those have their own
+ * independent color mode and HDR parameters.</p>
+ *
* @see #getColorMode()
* @see Display#isWideColorGamut()
* @see Configuration#isScreenWideColorGamut()
@@ -1361,6 +1364,9 @@
* See {@link Display#getHdrSdrRatio()} for more information as well as how to query the
* current value.</p>
*
+ * <p>Note: This does not impact SurfaceViews or SurfaceControls, as those have their own
+ * independent desired HDR headroom and HDR capabilities.</p>
+ *
* @param desiredHeadroom The amount of HDR headroom that is desired. Must be >= 1.0 (no HDR)
* and <= 10,000.0. Passing 0.0 will reset to the default, automatically
* chosen value.
diff --git a/core/tests/coretests/BinderFrozenStateChangeCallbackTestApp/src/com/android/frameworks/coretests/bfscctestapp/BfsccTestAppCmdService.java b/core/tests/coretests/BinderFrozenStateChangeCallbackTestApp/src/com/android/frameworks/coretests/bfscctestapp/BfsccTestAppCmdService.java
index fe54aa8..945147d 100644
--- a/core/tests/coretests/BinderFrozenStateChangeCallbackTestApp/src/com/android/frameworks/coretests/bfscctestapp/BfsccTestAppCmdService.java
+++ b/core/tests/coretests/BinderFrozenStateChangeCallbackTestApp/src/com/android/frameworks/coretests/bfscctestapp/BfsccTestAppCmdService.java
@@ -18,6 +18,8 @@
import android.app.Service;
import android.content.Intent;
+import android.os.Handler;
+import android.os.HandlerExecutor;
import android.os.IBinder;
import android.os.RemoteException;
@@ -36,6 +38,7 @@
@Override
public void listenTo(IBinder binder) throws RemoteException {
binder.addFrozenStateChangeCallback(
+ new HandlerExecutor(Handler.getMain()),
(IBinder who, int state) -> mNotifications.offer(state));
}
diff --git a/core/tests/coretests/src/android/os/BinderFrozenStateChangeNotificationTest.java b/core/tests/coretests/src/android/os/BinderFrozenStateChangeNotificationTest.java
index 195a18a..523fe1a 100644
--- a/core/tests/coretests/src/android/os/BinderFrozenStateChangeNotificationTest.java
+++ b/core/tests/coretests/src/android/os/BinderFrozenStateChangeNotificationTest.java
@@ -200,7 +200,7 @@
IBinder.FrozenStateChangeCallback callback =
(IBinder who, int state) -> results.offer(who);
try {
- binder.addFrozenStateChangeCallback(callback);
+ binder.addFrozenStateChangeCallback(new HandlerExecutor(Handler.getMain()), callback);
} catch (UnsupportedOperationException e) {
return;
}
@@ -227,7 +227,7 @@
final IBinder.FrozenStateChangeCallback callback =
(IBinder who, int state) ->
queue.offer(state == IBinder.FrozenStateChangeCallback.STATE_FROZEN);
- binder.addFrozenStateChangeCallback(callback);
+ binder.addFrozenStateChangeCallback(new HandlerExecutor(Handler.getMain()), callback);
return callback;
} catch (UnsupportedOperationException e) {
return null;
diff --git a/core/tests/coretests/src/com/android/internal/os/BinderDeathDispatcherTest.java b/core/tests/coretests/src/com/android/internal/os/BinderDeathDispatcherTest.java
index 67de25e..7511887 100644
--- a/core/tests/coretests/src/com/android/internal/os/BinderDeathDispatcherTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BinderDeathDispatcherTest.java
@@ -42,6 +42,7 @@
import org.junit.runner.RunWith;
import java.io.FileDescriptor;
+import java.util.concurrent.Executor;
@SmallTest
@RunWith(AndroidJUnit4.class)
@@ -125,7 +126,7 @@
}
@Override
- public void addFrozenStateChangeCallback(FrozenStateChangeCallback callback)
+ public void addFrozenStateChangeCallback(Executor e, FrozenStateChangeCallback callback)
throws RemoteException {
}
diff --git a/core/tests/systemproperties/src/android/os/SystemPropertiesTest.java b/core/tests/systemproperties/src/android/os/SystemPropertiesTest.java
index 75aca1b..7ce2ed8 100644
--- a/core/tests/systemproperties/src/android/os/SystemPropertiesTest.java
+++ b/core/tests/systemproperties/src/android/os/SystemPropertiesTest.java
@@ -23,10 +23,11 @@
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
-import android.platform.test.ravenwood.RavenwoodConfig;
+import android.platform.test.ravenwood.RavenwoodRule;
import androidx.test.filters.SmallTest;
+import org.junit.Rule;
import org.junit.Test;
import java.util.Objects;
@@ -39,8 +40,8 @@
private static final String PERSIST_KEY = "persist.sys.testkey";
private static final String NONEXIST_KEY = "doesnotexist_2341431";
- @RavenwoodConfig.Config
- public static final RavenwoodConfig mRavenwood = new RavenwoodConfig.Builder()
+ @Rule
+ public final RavenwoodRule mRavenwood = new RavenwoodRule.Builder()
.setSystemPropertyMutable(KEY, null)
.setSystemPropertyMutable(UNSET_KEY, null)
.setSystemPropertyMutable(PERSIST_KEY, null)
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index 96edd63..782db35 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -1876,6 +1876,8 @@
* Codecs with this security model is not included in
* {@link MediaCodecList#REGULAR_CODECS}, but included in
* {@link MediaCodecList#ALL_CODECS}.
+ *
+ * @hide
*/
@FlaggedApi(FLAG_IN_PROCESS_SW_AUDIO_CODEC)
public static final int SECURITY_MODEL_TRUSTED_CONTENT_ONLY = 2;
diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java
index bd65b2e..bc09aee 100644
--- a/media/java/android/media/MediaFormat.java
+++ b/media/java/android/media/MediaFormat.java
@@ -1748,6 +1748,7 @@
(1 << MediaCodecInfo.SECURITY_MODEL_MEMORY_SAFE);
/**
* Flag for {@link MediaCodecInfo#SECURITY_MODEL_TRUSTED_CONTENT_ONLY}.
+ * @hide
*/
@FlaggedApi(FLAG_IN_PROCESS_SW_AUDIO_CODEC)
public static final int FLAG_SECURITY_MODEL_TRUSTED_CONTENT_ONLY =
@@ -1759,8 +1760,7 @@
* The associated value is a flag of the following values:
* {@link FLAG_SECURITY_MODEL_SANDBOXED},
* {@link FLAG_SECURITY_MODEL_MEMORY_SAFE},
- * {@link FLAG_SECURITY_MODEL_TRUSTED_CONTENT_ONLY}. The default value is
- * {@link FLAG_SECURITY_MODEL_SANDBOXED}.
+ * The default value is {@link FLAG_SECURITY_MODEL_SANDBOXED}.
* <p>
* When passed to {@link MediaCodecList#findDecoderForFormat} or
* {@link MediaCodecList#findEncoderForFormat}, MediaCodecList filters
diff --git a/native/graphics/jni/Android.bp b/native/graphics/jni/Android.bp
index 0fb3049..962f54d 100644
--- a/native/graphics/jni/Android.bp
+++ b/native/graphics/jni/Android.bp
@@ -45,8 +45,10 @@
header_libs: [
"jni_headers",
+ "native_headers",
"libhwui_internal_headers",
],
+ export_header_lib_headers: ["native_headers"],
static_libs: ["libarect"],
diff --git a/nfc/api/current.txt b/nfc/api/current.txt
index 00812042..7ae2eafa 100644
--- a/nfc/api/current.txt
+++ b/nfc/api/current.txt
@@ -81,11 +81,14 @@
method @FlaggedApi("android.nfc.enable_nfc_reader_option") public boolean isReaderOptionSupported();
method public boolean isSecureNfcEnabled();
method public boolean isSecureNfcSupported();
+ method @FlaggedApi("android.nfc.nfc_check_tag_intent_preference") public boolean isTagIntentAllowed();
+ method @FlaggedApi("android.nfc.nfc_check_tag_intent_preference") public boolean isTagIntentAppPreferenceSupported();
method @FlaggedApi("android.nfc.enable_nfc_charging") public boolean isWlcEnabled();
method @FlaggedApi("android.nfc.enable_nfc_set_discovery_tech") public void resetDiscoveryTechnology(@NonNull android.app.Activity);
method @FlaggedApi("android.nfc.enable_nfc_set_discovery_tech") public void setDiscoveryTechnology(@NonNull android.app.Activity, int, int);
method @FlaggedApi("android.nfc.nfc_observe_mode") public boolean setObserveModeEnabled(boolean);
field public static final String ACTION_ADAPTER_STATE_CHANGED = "android.nfc.action.ADAPTER_STATE_CHANGED";
+ field @FlaggedApi("android.nfc.nfc_check_tag_intent_preference") public static final String ACTION_CHANGE_TAG_INTENT_PREFERENCE = "android.nfc.action.CHANGE_TAG_INTENT_PREFERENCE";
field public static final String ACTION_NDEF_DISCOVERED = "android.nfc.action.NDEF_DISCOVERED";
field @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO) public static final String ACTION_PREFERRED_PAYMENT_CHANGED = "android.nfc.action.PREFERRED_PAYMENT_CHANGED";
field public static final String ACTION_TAG_DISCOVERED = "android.nfc.action.TAG_DISCOVERED";
@@ -225,6 +228,10 @@
field public static final String CATEGORY_PAYMENT = "payment";
field public static final String EXTRA_CATEGORY = "category";
field public static final String EXTRA_SERVICE_COMPONENT = "component";
+ field @FlaggedApi("android.nfc.nfc_event_listener") public static final int NFC_INTERNAL_ERROR_COMMAND_TIMEOUT = 3; // 0x3
+ field @FlaggedApi("android.nfc.nfc_event_listener") public static final int NFC_INTERNAL_ERROR_NFC_CRASH_RESTART = 1; // 0x1
+ field @FlaggedApi("android.nfc.nfc_event_listener") public static final int NFC_INTERNAL_ERROR_NFC_HARDWARE_ERROR = 2; // 0x2
+ field @FlaggedApi("android.nfc.nfc_event_listener") public static final int NFC_INTERNAL_ERROR_UNKNOWN = 0; // 0x0
field @FlaggedApi("android.nfc.nfc_override_recover_routing_table") public static final int PROTOCOL_AND_TECHNOLOGY_ROUTE_DEFAULT = 3; // 0x3
field @FlaggedApi("android.nfc.nfc_override_recover_routing_table") public static final int PROTOCOL_AND_TECHNOLOGY_ROUTE_DH = 0; // 0x0
field @FlaggedApi("android.nfc.nfc_override_recover_routing_table") public static final int PROTOCOL_AND_TECHNOLOGY_ROUTE_ESE = 1; // 0x1
@@ -236,8 +243,13 @@
}
@FlaggedApi("android.nfc.nfc_event_listener") public static interface CardEmulation.NfcEventListener {
+ method @FlaggedApi("android.nfc.nfc_event_listener") public default void onAidConflictOccurred(@NonNull String);
+ method @FlaggedApi("android.nfc.nfc_event_listener") public default void onAidNotRouted(@NonNull String);
+ method @FlaggedApi("android.nfc.nfc_event_listener") public default void onInternalErrorReported(int);
+ method @FlaggedApi("android.nfc.nfc_event_listener") public default void onNfcStateChanged(int);
method @FlaggedApi("android.nfc.nfc_event_listener") public default void onObserveModeStateChanged(boolean);
method @FlaggedApi("android.nfc.nfc_event_listener") public default void onPreferredServiceChanged(boolean);
+ method @FlaggedApi("android.nfc.nfc_event_listener") public default void onRemoteFieldChanged(boolean);
}
public abstract class HostApduService extends android.app.Service {
diff --git a/nfc/api/system-current.txt b/nfc/api/system-current.txt
index 79a0607..15814ed 100644
--- a/nfc/api/system-current.txt
+++ b/nfc/api/system-current.txt
@@ -11,7 +11,6 @@
method @NonNull @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public java.util.Map<java.lang.String,java.lang.Boolean> getTagIntentAppPreferenceForUser(int);
method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public boolean isControllerAlwaysOn();
method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public boolean isControllerAlwaysOnSupported();
- method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean isTagIntentAppPreferenceSupported();
method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public void registerControllerAlwaysOnListener(@NonNull java.util.concurrent.Executor, @NonNull android.nfc.NfcAdapter.ControllerAlwaysOnListener);
method @FlaggedApi("android.nfc.nfc_vendor_cmd") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void registerNfcVendorNciCallback(@NonNull java.util.concurrent.Executor, @NonNull android.nfc.NfcAdapter.NfcVendorNciCallback);
method @FlaggedApi("android.nfc.enable_nfc_charging") public void registerWlcStateListener(@NonNull java.util.concurrent.Executor, @NonNull android.nfc.NfcAdapter.WlcStateListener);
@@ -57,6 +56,7 @@
@FlaggedApi("android.nfc.nfc_oem_extension") public final class NfcOemExtension {
method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void clearPreference();
+ method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public int forceRoutingTableCommit();
method @FlaggedApi("android.nfc.nfc_oem_extension") @NonNull public java.util.List<java.lang.String> getActiveNfceeList();
method @FlaggedApi("android.nfc.nfc_oem_extension") @NonNull @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public android.nfc.RoutingStatus getRoutingStatus();
method @FlaggedApi("android.nfc.nfc_oem_extension") @NonNull @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public java.util.List<android.nfc.NfcRoutingTableEntry> getRoutingTable();
@@ -73,6 +73,9 @@
method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void synchronizeScreenState();
method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void triggerInitialization();
method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void unregisterCallback(@NonNull android.nfc.NfcOemExtension.Callback);
+ field public static final int COMMIT_ROUTING_STATUS_FAILED = 3; // 0x3
+ field public static final int COMMIT_ROUTING_STATUS_FAILED_UPDATE_IN_PROGRESS = 6; // 0x6
+ field public static final int COMMIT_ROUTING_STATUS_OK = 0; // 0x0
field @FlaggedApi("android.nfc.nfc_oem_extension") public static final int DISABLE = 0; // 0x0
field @FlaggedApi("android.nfc.nfc_oem_extension") public static final int ENABLE_DEFAULT = 1; // 0x1
field @FlaggedApi("android.nfc.nfc_oem_extension") public static final int ENABLE_EE = 3; // 0x3
@@ -93,9 +96,11 @@
method public void onDisableRequested(@NonNull java.util.function.Consumer<java.lang.Boolean>);
method public void onDisableStarted();
method public void onEeListenActivated(boolean);
+ method public void onEeUpdated();
method public void onEnableFinished(int);
method public void onEnableRequested(@NonNull java.util.function.Consumer<java.lang.Boolean>);
method public void onEnableStarted();
+ method public void onExtractOemPackages(@NonNull android.nfc.NdefMessage, @NonNull java.util.function.Consumer<java.util.List<java.lang.String>>);
method public void onGetOemAppSearchIntent(@NonNull java.util.List<java.lang.String>, @NonNull java.util.function.Consumer<android.content.Intent>);
method public void onHceEventReceived(int);
method public void onLaunchHceAppChooserActivity(@NonNull String, @NonNull java.util.List<android.nfc.cardemulation.ApduServiceInfo>, @NonNull android.content.ComponentName, @NonNull String);
@@ -106,7 +111,7 @@
method public void onReaderOptionChanged(boolean);
method public void onRfDiscoveryStarted(boolean);
method public void onRfFieldActivated(boolean);
- method public void onRoutingChanged();
+ method public void onRoutingChanged(@NonNull java.util.function.Consumer<java.lang.Boolean>);
method public void onRoutingTableFull();
method public void onStateUpdated(int);
method public void onTagConnected(boolean);
diff --git a/nfc/java/android/nfc/INfcAdapter.aidl b/nfc/java/android/nfc/INfcAdapter.aidl
index 40fd068..a08b55f 100644
--- a/nfc/java/android/nfc/INfcAdapter.aidl
+++ b/nfc/java/android/nfc/INfcAdapter.aidl
@@ -120,4 +120,6 @@
boolean isTagPresent();
List<Entry> getRoutingTableEntryList();
void indicateDataMigration(boolean inProgress, String pkg);
+ int commitRouting();
+ boolean isTagIntentAllowed(in String pkg, in int Userid);
}
diff --git a/nfc/java/android/nfc/INfcEventListener.aidl b/nfc/java/android/nfc/INfcEventListener.aidl
index 5162c26..774d8f8 100644
--- a/nfc/java/android/nfc/INfcEventListener.aidl
+++ b/nfc/java/android/nfc/INfcEventListener.aidl
@@ -8,4 +8,9 @@
oneway interface INfcEventListener {
void onPreferredServiceChanged(in ComponentNameAndUser ComponentNameAndUser);
void onObserveModeStateChanged(boolean isEnabled);
+ void onAidConflictOccurred(in String aid);
+ void onAidNotRouted(in String aid);
+ void onNfcStateChanged(in int nfcState);
+ void onRemoteFieldChanged(boolean isDetected);
+ void onInternalErrorReported(in int errorType);
}
\ No newline at end of file
diff --git a/nfc/java/android/nfc/INfcOemExtensionCallback.aidl b/nfc/java/android/nfc/INfcOemExtensionCallback.aidl
index fb793b0..e5eac0b 100644
--- a/nfc/java/android/nfc/INfcOemExtensionCallback.aidl
+++ b/nfc/java/android/nfc/INfcOemExtensionCallback.aidl
@@ -41,17 +41,19 @@
void onEnableFinished(int status);
void onDisableFinished(int status);
void onTagDispatch(in ResultReceiver isSkipped);
- void onRoutingChanged();
+ void onRoutingChanged(in ResultReceiver isSkipped);
void onHceEventReceived(int action);
void onReaderOptionChanged(boolean enabled);
void onCardEmulationActivated(boolean isActivated);
void onRfFieldActivated(boolean isActivated);
void onRfDiscoveryStarted(boolean isDiscoveryStarted);
void onEeListenActivated(boolean isActivated);
+ void onEeUpdated();
void onGetOemAppSearchIntent(in List<String> firstPackage, in ResultReceiver intentConsumer);
void onNdefMessage(in Tag tag, in NdefMessage message, in ResultReceiver hasOemExecutableContent);
void onLaunchHceAppChooserActivity(in String selectedAid, in List<ApduServiceInfo> services, in ComponentName failedComponent, in String category);
void onLaunchHceTapAgainActivity(in ApduServiceInfo service, in String category);
void onRoutingTableFull();
void onLogEventNotified(in OemLogItems item);
+ void onExtractOemPackages(in NdefMessage message, in ResultReceiver packageReceiver);
}
diff --git a/nfc/java/android/nfc/NfcAdapter.java b/nfc/java/android/nfc/NfcAdapter.java
index c5d8191..056844f 100644
--- a/nfc/java/android/nfc/NfcAdapter.java
+++ b/nfc/java/android/nfc/NfcAdapter.java
@@ -49,6 +49,7 @@
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
+import android.os.UserHandle;
import android.util.Log;
import java.io.IOException;
@@ -2505,22 +2506,22 @@
}
/**
- * Checks if the device supports Tag application preference.
+ * Checks if the device supports Tag Intent App Preference functionality.
+ *
+ * When supported, {@link #ACTION_NDEF_DISCOVERED}, {@link #ACTION_TECH_DISCOVERED} or
+ * {@link #ACTION_TAG_DISCOVERED} will not be dispatched to an Activity if
+ * {@link isTagIntentAllowed} returns {@code false}.
*
* @return {@code true} if the device supports Tag application preference, {@code false}
* otherwise
* @throws UnsupportedOperationException if FEATURE_NFC is unavailable
- *
- * @hide
*/
- @SystemApi
- @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
+ @FlaggedApi(Flags.FLAG_NFC_CHECK_TAG_INTENT_PREFERENCE)
public boolean isTagIntentAppPreferenceSupported() {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
return callServiceReturn(() -> sService.isTagIntentAppPreferenceSupported(), false);
-
}
/**
@@ -2895,4 +2896,42 @@
}
return mNfcOemExtension;
}
+
+ /**
+ * Activity action: Bring up the settings page that allows the user to enable or disable tag
+ * intent reception for apps.
+ *
+ * <p>This will direct user to the settings page shows a list that asks users whether
+ * they want to allow or disallow the package to start an activity when a tag is discovered.
+ *
+ */
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ @FlaggedApi(Flags.FLAG_NFC_CHECK_TAG_INTENT_PREFERENCE)
+ public static final String ACTION_CHANGE_TAG_INTENT_PREFERENCE =
+ "android.nfc.action.CHANGE_TAG_INTENT_PREFERENCE";
+
+ /**
+ * Checks whether the user has disabled the calling app from receiving NFC tag intents.
+ *
+ * <p>This method checks whether the caller package name is either not present in the user
+ * disabled list or is explicitly allowed by the user.
+ *
+ * @return {@code true} if an app is either not present in the list or is added to the list
+ * with the flag set to {@code true}. Otherwise, it returns {@code false}.
+ * It also returns {@code true} if {@link isTagIntentAppPreferenceSupported} returns
+ * {@code false}.
+ *
+ * @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
+ */
+ @FlaggedApi(Flags.FLAG_NFC_CHECK_TAG_INTENT_PREFERENCE)
+ public boolean isTagIntentAllowed() {
+ if (!sHasNfcFeature) {
+ throw new UnsupportedOperationException();
+ }
+ if (!isTagIntentAppPreferenceSupported()) {
+ return true;
+ }
+ return callServiceReturn(() -> sService.isTagIntentAllowed(mContext.getPackageName(),
+ UserHandle.myUserId()), false);
+ }
}
diff --git a/nfc/java/android/nfc/NfcOemExtension.java b/nfc/java/android/nfc/NfcOemExtension.java
index c677cd6..9ed678f 100644
--- a/nfc/java/android/nfc/NfcOemExtension.java
+++ b/nfc/java/android/nfc/NfcOemExtension.java
@@ -23,6 +23,7 @@
import android.Manifest;
import android.annotation.CallbackExecutor;
+import android.annotation.DurationMillisLong;
import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.NonNull;
@@ -193,6 +194,30 @@
public @interface StatusCode {}
/**
+ * Routing commit succeeded.
+ */
+ public static final int COMMIT_ROUTING_STATUS_OK = 0;
+ /**
+ * Routing commit failed.
+ */
+ public static final int COMMIT_ROUTING_STATUS_FAILED = 3;
+ /**
+ * Routing commit failed due to the update is in progress.
+ */
+ public static final int COMMIT_ROUTING_STATUS_FAILED_UPDATE_IN_PROGRESS = 6;
+
+ /**
+ * Status codes returned when calling {@link #forceRoutingTableCommit()}
+ * @hide
+ */
+ @IntDef(prefix = "COMMIT_ROUTING_STATUS_", value = {
+ COMMIT_ROUTING_STATUS_OK,
+ COMMIT_ROUTING_STATUS_FAILED,
+ COMMIT_ROUTING_STATUS_FAILED_UPDATE_IN_PROGRESS,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface CommitRoutingStatusCode {}
+ /**
* Interface for Oem extensions for NFC.
*/
public interface Callback {
@@ -285,8 +310,12 @@
/**
* Notifies routing configuration is changed.
+ * @param isCommitRoutingSkipped The {@link Consumer} to be
+ * completed. If routing commit should be skipped,
+ * the {@link Consumer#accept(Object)} should be called with
+ * {@link Boolean#TRUE}, otherwise call with {@link Boolean#FALSE}.
*/
- void onRoutingChanged();
+ void onRoutingChanged(@NonNull Consumer<Boolean> isCommitRoutingSkipped);
/**
* API to activate start stop cpu boost on hce event.
@@ -338,6 +367,15 @@
void onEeListenActivated(boolean isActivated);
/**
+ * Notifies that some NFCEE (NFC Execution Environment) has been updated.
+ *
+ * <p> This indicates that some applet has been installed/updated/removed in
+ * one of the NFCEE's.
+ * </p>
+ */
+ void onEeUpdated();
+
+ /**
* Gets the intent to find the OEM package in the OEM App market. If the consumer returns
* {@code null} or a timeout occurs, the intent from the first available package will be
* used instead.
@@ -403,6 +441,19 @@
* @param item the log items that contains log information of NFC event.
*/
void onLogEventNotified(@NonNull OemLogItems item);
+
+ /**
+ * Callback to to extract OEM defined packages from given NDEF message when
+ * a NFC tag is detected. These are used to handle NFC tags encoded with a
+ * proprietary format for storing app name (Android native app format).
+ *
+ * @param message NDEF message containing OEM package names
+ * @param packageConsumer The {@link Consumer} to be completed.
+ * The {@link Consumer#accept(Object)} should be called with
+ * the list of package names.
+ */
+ void onExtractOemPackages(@NonNull NdefMessage message,
+ @NonNull Consumer<List<String>> packageConsumer);
}
@@ -603,12 +654,12 @@
/**
* Pauses NFC tag reader mode polling for a {@code timeoutInMs} millisecond.
* In case of {@code timeoutInMs} is zero or invalid polling will be stopped indefinitely
- * use {@link #resumePolling() to resume the polling.
- * @param timeoutInMs the pause polling duration in millisecond
+ * use {@link #resumePolling()} to resume the polling.
+ * @param timeoutInMs the pause polling duration in millisecond, ranging from 0 to 40000.
*/
@FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
@RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
- public void pausePolling(int timeoutInMs) {
+ public void pausePolling(@DurationMillisLong int timeoutInMs) {
NfcAdapter.callService(() -> NfcAdapter.sService.pausePolling(timeoutInMs));
}
@@ -739,6 +790,18 @@
return result;
}
+ /**
+ * API to force a routing table commit.
+ * @return a {@link StatusCode} to indicate if commit routing succeeded or not
+ */
+ @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS)
+ @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
+ @CommitRoutingStatusCode
+ public int forceRoutingTableCommit() {
+ return NfcAdapter.callServiceReturn(
+ () -> NfcAdapter.sService.commitRouting(), COMMIT_ROUTING_STATUS_FAILED);
+ }
+
private final class NfcOemExtensionCallback extends INfcOemExtensionCallback.Stub {
@Override
@@ -776,6 +839,12 @@
}
@Override
+ public void onEeUpdated() throws RemoteException {
+ mCallbackMap.forEach((cb, ex) ->
+ handleVoidCallback(null, (Object input) -> cb.onEeUpdated(), ex));
+ }
+
+ @Override
public void onStateUpdated(int state) throws RemoteException {
mCallbackMap.forEach((cb, ex) ->
handleVoidCallback(state, cb::onStateUpdated, ex));
@@ -842,9 +911,10 @@
new ReceiverWrapper<>(isSkipped), cb::onTagDispatch, ex));
}
@Override
- public void onRoutingChanged() throws RemoteException {
+ public void onRoutingChanged(ResultReceiver isSkipped) throws RemoteException {
mCallbackMap.forEach((cb, ex) ->
- handleVoidCallback(null, (Object input) -> cb.onRoutingChanged(), ex));
+ handleVoidCallback(
+ new ReceiverWrapper<>(isSkipped), cb::onRoutingChanged, ex));
}
@Override
public void onHceEventReceived(int action) throws RemoteException {
@@ -923,6 +993,15 @@
handleVoidCallback(item, cb::onLogEventNotified, ex));
}
+ @Override
+ public void onExtractOemPackages(NdefMessage message, ResultReceiver packageConsumer)
+ throws RemoteException {
+ mCallbackMap.forEach((cb, ex) ->
+ handleVoid2ArgCallback(message,
+ new ReceiverWrapper<>(packageConsumer),
+ cb::onExtractOemPackages, ex));
+ }
+
private <T> void handleVoidCallback(
T input, Consumer<T> callbackMethod, Executor executor) {
synchronized (mLock) {
@@ -1033,8 +1112,14 @@
Bundle bundle = new Bundle();
bundle.putParcelable("intent", (Intent) result);
mResultReceiver.send(0, bundle);
+ } else if (result instanceof List<?> list) {
+ if (list.stream().allMatch(String.class::isInstance)) {
+ Bundle bundle = new Bundle();
+ bundle.putStringArray("packageNames",
+ list.stream().map(pkg -> (String) pkg).toArray(String[]::new));
+ mResultReceiver.send(0, bundle);
+ }
}
-
}
@Override
diff --git a/nfc/java/android/nfc/cardemulation/CardEmulation.java b/nfc/java/android/nfc/cardemulation/CardEmulation.java
index 8917524..24ff7ab 100644
--- a/nfc/java/android/nfc/cardemulation/CardEmulation.java
+++ b/nfc/java/android/nfc/cardemulation/CardEmulation.java
@@ -947,7 +947,7 @@
*
* @param service The ComponentName of the service
* @param status true to enable, false to disable
- * @return true if preferred service is successfully set or unset, otherwise return false.
+ * @return status code defined in {@link SetServiceEnabledStatusCode}
*
* @hide
*/
@@ -1144,6 +1144,40 @@
};
}
+ @FlaggedApi(android.nfc.Flags.FLAG_NFC_EVENT_LISTENER)
+ public static final int NFC_INTERNAL_ERROR_UNKNOWN = 0;
+
+ /**
+ * This error is reported when the NFC command watchdog restarts the NFC stack.
+ */
+ @FlaggedApi(android.nfc.Flags.FLAG_NFC_EVENT_LISTENER)
+ public static final int NFC_INTERNAL_ERROR_NFC_CRASH_RESTART = 1;
+
+ /**
+ * This error is reported when the NFC controller does not respond or there's an NCI transport
+ * error.
+ */
+ @FlaggedApi(android.nfc.Flags.FLAG_NFC_EVENT_LISTENER)
+ public static final int NFC_INTERNAL_ERROR_NFC_HARDWARE_ERROR = 2;
+
+ /**
+ * This error is reported when the NFC stack times out while waiting for a response to a command
+ * sent to the NFC hardware.
+ */
+ @FlaggedApi(android.nfc.Flags.FLAG_NFC_EVENT_LISTENER)
+ public static final int NFC_INTERNAL_ERROR_COMMAND_TIMEOUT = 3;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @FlaggedApi(android.nfc.Flags.FLAG_NFC_EVENT_LISTENER)
+ @IntDef(prefix = "NFC_INTERNAL_ERROR_", value = {
+ NFC_INTERNAL_ERROR_UNKNOWN,
+ NFC_INTERNAL_ERROR_NFC_CRASH_RESTART,
+ NFC_INTERNAL_ERROR_NFC_HARDWARE_ERROR,
+ NFC_INTERNAL_ERROR_COMMAND_TIMEOUT,
+ })
+ public @interface NfcInternalErrorType {}
+
/** Listener for preferred service state changes. */
@FlaggedApi(android.nfc.Flags.FLAG_NFC_EVENT_LISTENER)
public interface NfcEventListener {
@@ -1166,6 +1200,57 @@
*/
@FlaggedApi(android.nfc.Flags.FLAG_NFC_EVENT_LISTENER)
default void onObserveModeStateChanged(boolean isEnabled) {}
+
+ /**
+ * This method is called when an AID conflict is detected during an NFC transaction. This
+ * can happen when multiple services are registered for the same AID.
+ *
+ * @param aid The AID that is in conflict
+ */
+ @FlaggedApi(android.nfc.Flags.FLAG_NFC_EVENT_LISTENER)
+ default void onAidConflictOccurred(@NonNull String aid) {}
+
+ /**
+ * This method is called when an AID is not routed to any service during an NFC
+ * transaction. This can happen when no service is registered for the given AID.
+ *
+ * @param aid the AID that was not routed
+ */
+ @FlaggedApi(android.nfc.Flags.FLAG_NFC_EVENT_LISTENER)
+ default void onAidNotRouted(@NonNull String aid) {}
+
+ /**
+ * This method is called when the NFC state changes.
+ *
+ * @see NfcAdapter#getAdapterState()
+ *
+ * @param state The new NFC state
+ */
+ @FlaggedApi(android.nfc.Flags.FLAG_NFC_EVENT_LISTENER)
+ default void onNfcStateChanged(@NfcAdapter.AdapterState int state) {}
+ /**
+ * This method is called when the NFC controller is in card emulation mode and an NFC
+ * reader's field is either detected or lost.
+ *
+ * @param isDetected true if an NFC reader is detected, false if it is lost
+ */
+ @FlaggedApi(android.nfc.Flags.FLAG_NFC_EVENT_LISTENER)
+ default void onRemoteFieldChanged(boolean isDetected) {}
+
+ /**
+ * This method is called when an internal error is reported by the NFC stack.
+ *
+ * No action is required in response to these events as the NFC stack will automatically
+ * attempt to recover. These errors are reported for informational purposes only.
+ *
+ * Note that these errors can be reported when performing various internal NFC operations
+ * (such as during device shutdown) and cannot always be explicitly correlated with NFC
+ * transaction failures.
+ *
+ * @param errorType The type of the internal error
+ */
+ @FlaggedApi(android.nfc.Flags.FLAG_NFC_EVENT_LISTENER)
+ default void onInternalErrorReported(@NfcInternalErrorType int errorType) {}
}
private final ArrayMap<NfcEventListener, Executor> mNfcEventListeners = new ArrayMap<>();
@@ -1185,25 +1270,61 @@
mContext.getPackageName(),
componentNameAndUser.getComponentName()
.getPackageName());
- synchronized (mNfcEventListeners) {
- mNfcEventListeners.forEach(
- (listener, executor) -> {
- executor.execute(
- () -> listener.onPreferredServiceChanged(isPreferred));
- });
- }
+ callListeners(listener -> listener.onPreferredServiceChanged(isPreferred));
}
public void onObserveModeStateChanged(boolean isEnabled) {
if (!android.nfc.Flags.nfcEventListener()) {
return;
}
+ callListeners(listener -> listener.onObserveModeStateChanged(isEnabled));
+ }
+
+ public void onAidConflictOccurred(String aid) {
+ if (!android.nfc.Flags.nfcEventListener()) {
+ return;
+ }
+ callListeners(listener -> listener.onAidConflictOccurred(aid));
+ }
+
+ public void onAidNotRouted(String aid) {
+ if (!android.nfc.Flags.nfcEventListener()) {
+ return;
+ }
+ callListeners(listener -> listener.onAidNotRouted(aid));
+ }
+
+ public void onNfcStateChanged(int state) {
+ if (!android.nfc.Flags.nfcEventListener()) {
+ return;
+ }
+ callListeners(listener -> listener.onNfcStateChanged(state));
+ }
+
+ public void onRemoteFieldChanged(boolean isDetected) {
+ if (!android.nfc.Flags.nfcEventListener()) {
+ return;
+ }
+ callListeners(listener -> listener.onRemoteFieldChanged(isDetected));
+ }
+
+ public void onInternalErrorReported(@NfcInternalErrorType int errorType) {
+ if (!android.nfc.Flags.nfcEventListener()) {
+ return;
+ }
+ callListeners(listener -> listener.onInternalErrorReported(errorType));
+ }
+
+ interface ListenerCall {
+ void invoke(NfcEventListener listener);
+ }
+
+ private void callListeners(ListenerCall listenerCall) {
synchronized (mNfcEventListeners) {
mNfcEventListeners.forEach(
- (listener, executor) -> {
- executor.execute(
- () -> listener.onObserveModeStateChanged(isEnabled));
- });
+ (listener, executor) -> {
+ executor.execute(() -> listenerCall.invoke(listener));
+ });
}
}
};
diff --git a/nfc/java/android/nfc/flags.aconfig b/nfc/java/android/nfc/flags.aconfig
index 8a37aa2..ee287ab 100644
--- a/nfc/java/android/nfc/flags.aconfig
+++ b/nfc/java/android/nfc/flags.aconfig
@@ -181,3 +181,11 @@
description: "Enable set service enabled for category other"
bug: "338157113"
}
+
+flag {
+ name: "nfc_check_tag_intent_preference"
+ is_exported: true
+ namespace: "nfc"
+ description: "App can check its tag intent preference status"
+ bug: "335916336"
+}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/OWNERS b/packages/SettingsProvider/src/com/android/providers/settings/OWNERS
index 0b71816..b0086c1 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/OWNERS
+++ b/packages/SettingsProvider/src/com/android/providers/settings/OWNERS
@@ -1 +1,2 @@
-per-file WritableNamespacePrefixes.java = cbrubaker@google.com,tedbauer@google.com
+per-file WritableNamespacePrefixes.java = mpgroover@google.com,tedbauer@google.com
+per-file WritableNamespaces.java = mpgroover@google.com,tedbauer@google.com
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/OWNERS b/packages/SystemUI/src/com/android/systemui/statusbar/OWNERS
index c019f30..72b03bf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/OWNERS
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/OWNERS
@@ -14,7 +14,7 @@
per-file *Keyboard* = file:../keyguard/OWNERS
per-file *Keyguard* = set noparent
per-file *Keyguard* = file:../keyguard/OWNERS
-per-file *Notification* = set noparent
+# Not setting noparent here, since *Notification* also matches some status bar notification chips files (statusbar/chips/notification) which should be owned by the status bar team.
per-file *Notification* = file:notification/OWNERS
# Not setting noparent here, since *Mode* matches many other classes (e.g., *ViewModel*)
per-file *Mode* = file:notification/OWNERS
diff --git a/ravenwood/TEST_MAPPING b/ravenwood/TEST_MAPPING
index 607592b..cb54e9f 100644
--- a/ravenwood/TEST_MAPPING
+++ b/ravenwood/TEST_MAPPING
@@ -113,10 +113,6 @@
"host": true
},
{
- "name": "FrameworksMockingServicesTestsRavenwood",
- "host": true
- },
- {
"name": "FrameworksServicesTestsRavenwood_Compat",
"host": true
},
diff --git a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodAwareTestRunner.java b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodAwareTestRunner.java
index 869d854..9b71f80 100644
--- a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodAwareTestRunner.java
+++ b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodAwareTestRunner.java
@@ -30,6 +30,8 @@
import androidx.test.platform.app.InstrumentationRegistry;
+import com.android.ravenwood.common.RavenwoodCommonUtils;
+
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runner.Runner;
@@ -229,7 +231,9 @@
s.evaluate();
onAfter(description, scope, order, null);
} catch (Throwable t) {
- if (onAfter(description, scope, order, t)) {
+ var shouldReportFailure = RavenwoodCommonUtils.runIgnoringException(
+ () -> onAfter(description, scope, order, t));
+ if (shouldReportFailure == null || shouldReportFailure) {
throw t;
}
}
diff --git a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuntimeEnvironmentController.java b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuntimeEnvironmentController.java
index 678a97b..979076e 100644
--- a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuntimeEnvironmentController.java
+++ b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuntimeEnvironmentController.java
@@ -22,6 +22,8 @@
import static com.android.ravenwood.common.RavenwoodCommonUtils.RAVENWOOD_RESOURCE_APK;
import static com.android.ravenwood.common.RavenwoodCommonUtils.RAVENWOOD_VERBOSE_LOGGING;
import static com.android.ravenwood.common.RavenwoodCommonUtils.RAVENWOOD_VERSION_JAVA_SYSPROP;
+import static com.android.ravenwood.common.RavenwoodCommonUtils.parseNullableInt;
+import static com.android.ravenwood.common.RavenwoodCommonUtils.withDefault;
import static org.junit.Assert.assertThrows;
import static org.mockito.ArgumentMatchers.any;
@@ -39,6 +41,7 @@
import android.content.res.Resources;
import android.os.Binder;
import android.os.Build;
+import android.os.Build.VERSION_CODES;
import android.os.Bundle;
import android.os.HandlerThread;
import android.os.Looper;
@@ -64,6 +67,7 @@
import com.android.server.LocalServices;
import com.android.server.compat.PlatformCompat;
+import org.junit.internal.management.ManagementFactory;
import org.junit.runner.Description;
import java.io.File;
@@ -154,6 +158,13 @@
private static RavenwoodAwareTestRunner sRunner;
private static RavenwoodSystemProperties sProps;
+ private static final int DEFAULT_TARGET_SDK_LEVEL = VERSION_CODES.CUR_DEVELOPMENT;
+ private static final String DEFAULT_PACKAGE_NAME = "com.android.ravenwoodtests.defaultname";
+
+ private static int sTargetSdkLevel;
+ private static String sTestPackageName;
+ private static String sTargetPackageName;
+
/**
* Initialize the global environment.
*/
@@ -194,6 +205,8 @@
// Some process-wide initialization. (maybe redirect stdout/stderr)
RavenwoodCommonUtils.loadJniLibrary(LIBRAVENWOOD_INITIALIZER_NAME);
+ dumpCommandLineArgs();
+
// We haven't initialized liblog yet, so directly write to System.out here.
RavenwoodCommonUtils.log(TAG, "globalInitInner()");
@@ -235,9 +248,22 @@
System.setProperty("android.junit.runner",
"androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner");
+ loadRavenwoodProperties();
+
assertMockitoVersion();
}
+ private static void loadRavenwoodProperties() {
+ var props = RavenwoodSystemProperties.readProperties("ravenwood.properties");
+
+ sTargetSdkLevel = withDefault(
+ parseNullableInt(props.get("targetSdkVersionInt")), DEFAULT_TARGET_SDK_LEVEL);
+ sTargetPackageName = withDefault(props.get("packageName"), DEFAULT_PACKAGE_NAME);
+ sTestPackageName = withDefault(props.get("instPackageName"), sTargetPackageName);
+
+ // TODO(b/377765941) Read them from the manifest too?
+ }
+
/**
* Initialize the environment.
*/
@@ -256,7 +282,9 @@
initInner(runner.mState.getConfig());
} catch (Exception th) {
Log.e(TAG, "init() failed", th);
- reset();
+
+ RavenwoodCommonUtils.runIgnoringException(()-> reset());
+
SneakyThrow.sneakyThrow(th);
}
}
@@ -267,6 +295,14 @@
Thread.setDefaultUncaughtExceptionHandler(sUncaughtExceptionHandler);
}
+ config.mTargetPackageName = sTargetPackageName;
+ config.mTestPackageName = sTestPackageName;
+ config.mTargetSdkLevel = sTargetSdkLevel;
+
+ Log.i(TAG, "TargetPackageName=" + sTargetPackageName);
+ Log.i(TAG, "TestPackageName=" + sTestPackageName);
+ Log.i(TAG, "TargetSdkLevel=" + sTargetSdkLevel);
+
RavenwoodRuntimeState.sUid = config.mUid;
RavenwoodRuntimeState.sPid = config.mPid;
RavenwoodRuntimeState.sTargetSdkLevel = config.mTargetSdkLevel;
@@ -349,8 +385,11 @@
* Partially re-initialize after each test method invocation
*/
public static void reinit() {
- var config = sRunner.mState.getConfig();
- Binder.restoreCallingIdentity(packBinderIdentityToken(false, config.mUid, config.mPid));
+ // sRunner could be null, if there was a failure in the initialization.
+ if (sRunner != null) {
+ var config = sRunner.mState.getConfig();
+ Binder.restoreCallingIdentity(packBinderIdentityToken(false, config.mUid, config.mPid));
+ }
}
private static void initializeCompatIds(RavenwoodConfig config) {
@@ -380,6 +419,9 @@
/**
* De-initialize.
+ *
+ * Note, we call this method when init() fails too, so this method should deal with
+ * any partially-initialized states.
*/
public static void reset() {
if (RAVENWOOD_VERBOSE_LOGGING) {
@@ -411,7 +453,9 @@
config.mState.mSystemServerContext.cleanUp();
}
- Looper.getMainLooper().quit();
+ if (Looper.getMainLooper() != null) {
+ Looper.getMainLooper().quit();
+ }
Looper.clearMainLooperForTest();
ActivityManager.reset$ravenwood();
@@ -547,4 +591,18 @@
+ " access to system property '" + key + "' denied via RavenwoodConfig");
}
}
+
+ private static void dumpCommandLineArgs() {
+ Log.i(TAG, "JVM arguments:");
+
+ // Note, we use the wrapper in JUnit4, not the actual class (
+ // java.lang.management.ManagementFactory), because we can't see the later at the build
+ // because this source file is compiled for the device target, where ManagementFactory
+ // doesn't exist.
+ var args = ManagementFactory.getRuntimeMXBean().getInputArguments();
+
+ for (var arg : args) {
+ Log.i(TAG, " " + arg);
+ }
+ }
}
diff --git a/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodConfig.java b/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodConfig.java
index 3ed8b0a..7ca9239 100644
--- a/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodConfig.java
+++ b/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodConfig.java
@@ -22,7 +22,6 @@
import android.annotation.Nullable;
import android.app.Instrumentation;
import android.content.Context;
-import android.os.Build;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
@@ -30,16 +29,12 @@
import java.lang.annotation.Target;
import java.util.ArrayList;
import java.util.List;
-import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;
/**
- * Represents how to configure the ravenwood environment for a test class.
- *
- * If a ravenwood test class has a public static field with the {@link Config} annotation,
- * Ravenwood will extract the config from it and initializes the environment. The type of the
- * field must be of {@link RavenwoodConfig}.
+ * @deprecated This class will be removed. Reach out to g/ravenwood if you need any features in it.
*/
+@Deprecated
public final class RavenwoodConfig {
/**
* Use this to mark a field as the configuration.
@@ -66,7 +61,7 @@
String mTestPackageName;
String mTargetPackageName;
- int mTargetSdkLevel = Build.VERSION_CODES.CUR_DEVELOPMENT;
+ int mTargetSdkLevel;
final RavenwoodSystemProperties mSystemProperties = new RavenwoodSystemProperties();
@@ -91,12 +86,6 @@
return RavenwoodRule.isOnRavenwood();
}
- private void setDefaults() {
- if (mTargetPackageName == null) {
- mTargetPackageName = mTestPackageName;
- }
- }
-
public static class Builder {
private final RavenwoodConfig mConfig = new RavenwoodConfig();
@@ -120,28 +109,27 @@
}
/**
- * Configure the package name of the test, which corresponds to
- * {@link Instrumentation#getContext()}.
+ * @deprecated no longer used. Package name is set in the build file. (for now)
*/
+ @Deprecated
public Builder setPackageName(@NonNull String packageName) {
- mConfig.mTestPackageName = Objects.requireNonNull(packageName);
return this;
}
/**
- * Configure the package name of the target app, which corresponds to
- * {@link Instrumentation#getTargetContext()}. Defaults to {@link #setPackageName}.
+ * @deprecated no longer used. Package name is set in the build file. (for now)
*/
+ @Deprecated
public Builder setTargetPackageName(@NonNull String packageName) {
- mConfig.mTargetPackageName = Objects.requireNonNull(packageName);
return this;
}
+
/**
- * Configure the target SDK level of the test.
+ * @deprecated no longer used. Target SDK level is set in the build file. (for now)
*/
+ @Deprecated
public Builder setTargetSdkLevel(int sdkLevel) {
- mConfig.mTargetSdkLevel = sdkLevel;
return this;
}
@@ -154,33 +142,31 @@
}
/**
- * Configure the given system property as immutable for the duration of the test.
- * Read access to the key is allowed, and write access will fail. When {@code value} is
- * {@code null}, the value is left as undefined.
- *
- * All properties in the {@code debug.*} namespace are automatically mutable, with no
- * developer action required.
- *
- * Has no effect on non-Ravenwood environments.
+ * @deprecated Use {@link RavenwoodRule.Builder#setSystemPropertyImmutable(String, Object)}
*/
+ @Deprecated
public Builder setSystemPropertyImmutable(@NonNull String key,
@Nullable Object value) {
+ return this;
+ }
+
+ /**
+ * @deprecated Use {@link RavenwoodRule.Builder#setSystemPropertyMutable(String, Object)}
+ */
+ @Deprecated
+ public Builder setSystemPropertyMutable(@NonNull String key,
+ @Nullable Object value) {
+ return this;
+ }
+
+ Builder setSystemPropertyImmutableReal(@NonNull String key,
+ @Nullable Object value) {
mConfig.mSystemProperties.setValue(key, value);
mConfig.mSystemProperties.setAccessReadOnly(key);
return this;
}
- /**
- * Configure the given system property as mutable for the duration of the test.
- * Both read and write access to the key is allowed, and its value will be reset between
- * each test. When {@code value} is {@code null}, the value is left as undefined.
- *
- * All properties in the {@code debug.*} namespace are automatically mutable, with no
- * developer action required.
- *
- * Has no effect on non-Ravenwood environments.
- */
- public Builder setSystemPropertyMutable(@NonNull String key,
+ Builder setSystemPropertyMutableReal(@NonNull String key,
@Nullable Object value) {
mConfig.mSystemProperties.setValue(key, value);
mConfig.mSystemProperties.setAccessReadWrite(key);
@@ -205,7 +191,6 @@
}
public RavenwoodConfig build() {
- mConfig.setDefaults();
return mConfig;
}
}
diff --git a/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodRule.java b/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodRule.java
index bfa3802..5681a90 100644
--- a/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodRule.java
+++ b/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodRule.java
@@ -36,10 +36,8 @@
import java.util.regex.Pattern;
/**
- * @deprecated Use {@link RavenwoodConfig} to configure the ravenwood environment instead.
- * A {@link RavenwoodRule} is no longer needed for {@link DisabledOnRavenwood}. To get the
- * {@link Context} and {@link Instrumentation}, use
- * {@link androidx.test.platform.app.InstrumentationRegistry} instead.
+ * @deprecated This class is undergoing a major change. Reach out to g/ravenwood if you need
+ * any featues in it.
*/
@Deprecated
public final class RavenwoodRule implements TestRule {
@@ -128,11 +126,10 @@
}
/**
- * Configure the identity of this process to be the given package name for the duration
- * of the test. Has no effect on non-Ravenwood environments.
+ * @deprecated no longer used.
*/
+ @Deprecated
public Builder setPackageName(@NonNull String packageName) {
- mBuilder.setPackageName(packageName);
return this;
}
@@ -155,7 +152,7 @@
* Has no effect on non-Ravenwood environments.
*/
public Builder setSystemPropertyImmutable(@NonNull String key, @Nullable Object value) {
- mBuilder.setSystemPropertyImmutable(key, value);
+ mBuilder.setSystemPropertyImmutableReal(key, value);
return this;
}
@@ -170,7 +167,7 @@
* Has no effect on non-Ravenwood environments.
*/
public Builder setSystemPropertyMutable(@NonNull String key, @Nullable Object value) {
- mBuilder.setSystemPropertyMutable(key, value);
+ mBuilder.setSystemPropertyMutableReal(key, value);
return this;
}
diff --git a/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodSystemProperties.java b/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodSystemProperties.java
index 3e4619f..9bd376a 100644
--- a/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodSystemProperties.java
+++ b/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodSystemProperties.java
@@ -52,7 +52,7 @@
"vendor_dlkm",
};
- private static Map<String, String> readProperties(String propFile) {
+ static Map<String, String> readProperties(String propFile) {
// Use an ordered map just for cleaner dump log.
final Map<String, String> ret = new LinkedHashMap<>();
try {
@@ -60,7 +60,7 @@
.map(String::trim)
.filter(s -> !s.startsWith("#"))
.map(s -> s.split("\\s*=\\s*", 2))
- .filter(a -> a.length == 2)
+ .filter(a -> a.length == 2 && a[1].length() > 0)
.forEach(a -> ret.put(a[0], a[1]));
} catch (IOException e) {
throw new RuntimeException(e);
diff --git a/ravenwood/runtime-common-src/com/android/ravenwood/common/RavenwoodCommonUtils.java b/ravenwood/runtime-common-src/com/android/ravenwood/common/RavenwoodCommonUtils.java
index 520f050..2a04d44 100644
--- a/ravenwood/runtime-common-src/com/android/ravenwood/common/RavenwoodCommonUtils.java
+++ b/ravenwood/runtime-common-src/com/android/ravenwood/common/RavenwoodCommonUtils.java
@@ -30,6 +30,7 @@
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
+import java.util.function.Supplier;
public class RavenwoodCommonUtils {
private static final String TAG = "RavenwoodCommonUtils";
@@ -277,11 +278,55 @@
(isStatic ? "static" : "")));
}
+ /**
+ * Run a supplier and swallow the exception, if any.
+ *
+ * It's a dangerous function. Only use it in an exception handler where we don't want to crash.
+ */
+ @Nullable
+ public static <T> T runIgnoringException(@NonNull Supplier<T> s) {
+ try {
+ return s.get();
+ } catch (Throwable th) {
+ log(TAG, "Warning: Exception detected! " + getStackTraceString(th));
+ }
+ return null;
+ }
+
+ /**
+ * Run a runnable and swallow the exception, if any.
+ *
+ * It's a dangerous function. Only use it in an exception handler where we don't want to crash.
+ */
+ public static void runIgnoringException(@NonNull Runnable r) {
+ runIgnoringException(() -> {
+ r.run();
+ return null;
+ });
+ }
+
@NonNull
- public static String getStackTraceString(@Nullable Throwable th) {
+ public static String getStackTraceString(@NonNull Throwable th) {
StringWriter stringWriter = new StringWriter();
PrintWriter writer = new PrintWriter(stringWriter);
th.printStackTrace(writer);
return stringWriter.toString();
}
+
+ /** Same as {@link Integer#parseInt(String)} but accepts null and returns null. */
+ @Nullable
+ public static Integer parseNullableInt(@Nullable String value) {
+ if (value == null) {
+ return null;
+ }
+ return Integer.parseInt(value);
+ }
+
+ /**
+ * @return {@code value} if it's non-null. Otherwise, returns {@code def}.
+ */
+ @Nullable
+ public static <T> T withDefault(@Nullable T value, @Nullable T def) {
+ return value != null ? value : def;
+ }
}
diff --git a/ravenwood/tests/bivalentinst/Android.bp b/ravenwood/tests/bivalentinst/Android.bp
index 41e45e5..31e3bcc 100644
--- a/ravenwood/tests/bivalentinst/Android.bp
+++ b/ravenwood/tests/bivalentinst/Android.bp
@@ -27,6 +27,9 @@
"junit",
"truth",
],
+
+ package_name: "com.android.ravenwood.bivalentinsttest_self_inst",
+
resource_apk: "RavenwoodBivalentInstTest_self_inst_device",
auto_gen_config: true,
}
@@ -53,6 +56,10 @@
"truth",
],
resource_apk: "RavenwoodBivalentInstTestTarget",
+
+ package_name: "com.android.ravenwood.bivalentinst_target_app",
+ inst_package_name: "com.android.ravenwood.bivalentinsttest_nonself_inst",
+
inst_resource_apk: "RavenwoodBivalentInstTest_nonself_inst_device",
auto_gen_config: true,
}
diff --git a/ravenwood/tests/bivalentinst/test/com/android/ravenwoodtest/bivalentinst/RavenwoodInstrumentationTest_nonself.java b/ravenwood/tests/bivalentinst/test/com/android/ravenwoodtest/bivalentinst/RavenwoodInstrumentationTest_nonself.java
index 92d43d7..db252d8 100644
--- a/ravenwood/tests/bivalentinst/test/com/android/ravenwoodtest/bivalentinst/RavenwoodInstrumentationTest_nonself.java
+++ b/ravenwood/tests/bivalentinst/test/com/android/ravenwoodtest/bivalentinst/RavenwoodInstrumentationTest_nonself.java
@@ -19,8 +19,6 @@
import android.app.Instrumentation;
import android.content.Context;
-import android.platform.test.ravenwood.RavenwoodConfig;
-import android.platform.test.ravenwood.RavenwoodConfig.Config;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.platform.app.InstrumentationRegistry;
@@ -39,11 +37,6 @@
private static final String TEST_PACKAGE_NAME =
"com.android.ravenwood.bivalentinsttest_nonself_inst";
- @Config
- public static final RavenwoodConfig sConfig = new RavenwoodConfig.Builder()
- .setPackageName(TEST_PACKAGE_NAME)
- .setTargetPackageName(TARGET_PACKAGE_NAME)
- .build();
private static Instrumentation sInstrumentation;
private static Context sTestContext;
diff --git a/ravenwood/tests/bivalentinst/test/com/android/ravenwoodtest/bivalentinst/RavenwoodInstrumentationTest_self.java b/ravenwood/tests/bivalentinst/test/com/android/ravenwoodtest/bivalentinst/RavenwoodInstrumentationTest_self.java
index 2f35923..94b1861 100644
--- a/ravenwood/tests/bivalentinst/test/com/android/ravenwoodtest/bivalentinst/RavenwoodInstrumentationTest_self.java
+++ b/ravenwood/tests/bivalentinst/test/com/android/ravenwoodtest/bivalentinst/RavenwoodInstrumentationTest_self.java
@@ -19,8 +19,6 @@
import android.app.Instrumentation;
import android.content.Context;
-import android.platform.test.ravenwood.RavenwoodConfig;
-import android.platform.test.ravenwood.RavenwoodConfig.Config;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.platform.app.InstrumentationRegistry;
@@ -40,13 +38,6 @@
private static final String TEST_PACKAGE_NAME =
"com.android.ravenwood.bivalentinsttest_self_inst";
- @Config
- public static final RavenwoodConfig sConfig = new RavenwoodConfig.Builder()
- .setPackageName(TEST_PACKAGE_NAME)
- .setTargetPackageName(TARGET_PACKAGE_NAME)
- .build();
-
-
private static Instrumentation sInstrumentation;
private static Context sTestContext;
private static Context sTargetContext;
diff --git a/ravenwood/tests/bivalenttest/Android.bp b/ravenwood/tests/bivalenttest/Android.bp
index 40e6672..ac545df 100644
--- a/ravenwood/tests/bivalenttest/Android.bp
+++ b/ravenwood/tests/bivalenttest/Android.bp
@@ -84,6 +84,8 @@
android_ravenwood_test {
name: "RavenwoodBivalentTest",
defaults: ["ravenwood-bivalent-defaults"],
+ target_sdk_version: "34",
+ package_name: "com.android.ravenwoodtest.bivalenttest",
auto_gen_config: true,
}
diff --git a/ravenwood/tests/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodConfigTest.java b/ravenwood/tests/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodConfigTest.java
index a5a16c1..306c2b39 100644
--- a/ravenwood/tests/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodConfigTest.java
+++ b/ravenwood/tests/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodConfigTest.java
@@ -20,8 +20,6 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assume.assumeTrue;
-import android.platform.test.ravenwood.RavenwoodConfig;
-
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.platform.app.InstrumentationRegistry;
@@ -33,13 +31,7 @@
*/
@RunWith(AndroidJUnit4.class)
public class RavenwoodConfigTest {
- private static final String PACKAGE_NAME = "com.test";
-
- @RavenwoodConfig.Config
- public static RavenwoodConfig sConfig =
- new RavenwoodConfig.Builder()
- .setPackageName(PACKAGE_NAME)
- .build();
+ private static final String PACKAGE_NAME = "com.android.ravenwoodtest.bivalenttest";
@Test
public void testConfig() {
diff --git a/ravenwood/tests/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/compat/RavenwoodCompatFrameworkTest.kt b/ravenwood/tests/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/compat/RavenwoodCompatFrameworkTest.kt
index a95760d..882c91c 100644
--- a/ravenwood/tests/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/compat/RavenwoodCompatFrameworkTest.kt
+++ b/ravenwood/tests/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/compat/RavenwoodCompatFrameworkTest.kt
@@ -16,8 +16,6 @@
package com.android.ravenwoodtest.bivalenttest.compat
import android.app.compat.CompatChanges
-import android.os.Build
-import android.platform.test.ravenwood.RavenwoodConfig
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.internal.ravenwood.RavenwoodEnvironment.CompatIdsForTest
import org.junit.Assert
@@ -26,14 +24,6 @@
@RunWith(AndroidJUnit4::class)
class RavenwoodCompatFrameworkTest {
- companion object {
- @JvmField // Expose as a raw field, not as a property.
- @RavenwoodConfig.Config
- val config = RavenwoodConfig.Builder()
- .setTargetSdkLevel(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
- .build()
- }
-
@Test
fun testEnabled() {
Assert.assertTrue(CompatChanges.isChangeEnabled(CompatIdsForTest.TEST_COMPAT_ID_1))
@@ -53,4 +43,4 @@
fun testEnabledAfterUForUApps() {
Assert.assertFalse(CompatChanges.isChangeEnabled(CompatIdsForTest.TEST_COMPAT_ID_4))
}
-}
\ No newline at end of file
+}
diff --git a/ravenwood/tests/coretest/test/com/android/ravenwoodtest/runnercallbacktests/RavenwoodRunnerConfigValidationTest.java b/ravenwood/tests/coretest/test/com/android/ravenwoodtest/runnercallbacktests/RavenwoodRunnerConfigValidationTest.java
index 02d1073..f94b98b 100644
--- a/ravenwood/tests/coretest/test/com/android/ravenwoodtest/runnercallbacktests/RavenwoodRunnerConfigValidationTest.java
+++ b/ravenwood/tests/coretest/test/com/android/ravenwoodtest/runnercallbacktests/RavenwoodRunnerConfigValidationTest.java
@@ -24,6 +24,7 @@
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.platform.app.InstrumentationRegistry;
+import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestRule;
@@ -32,6 +33,10 @@
/**
* Test for @Config field extraction and validation.
+ *
+ * TODO(b/377765941) Most of the tests here will be obsolete and deleted with b/377765941, but
+ * some of the tests may need to be re-implemented one way or another. (e.g. the package name
+ * test.) Until that happens, we'll keep all tests here but add an {@code @Ignore} instead.
*/
@NoRavenizer // This class shouldn't be executed with RavenwoodAwareTestRunner.
public class RavenwoodRunnerConfigValidationTest extends RavenwoodRunnerTestBase {
@@ -59,6 +64,7 @@
testRunFinished: 1,0,0,0
""")
// CHECKSTYLE:ON
+ @Ignore // Package name is no longer set via config.
public static class ConfigInBaseClassTest extends ConfigInBaseClass {
@Test
public void test() {
@@ -83,6 +89,7 @@
testRunFinished: 1,0,0,0
""")
// CHECKSTYLE:ON
+ @Ignore // Package name is no longer set via config.
public static class ConfigOverridingTest extends ConfigInBaseClass {
static String PACKAGE_NAME_OVERRIDE = "com.ConfigOverridingTest";
@@ -376,6 +383,7 @@
testRunFinished: 1,0,0,0
""")
// CHECKSTYLE:ON
+ @Ignore // Package name is no longer set via config.
public static class RuleInBaseClassSuccessTest extends RuleInBaseClass {
@Test
@@ -437,6 +445,7 @@
testRunFinished: 1,1,0,0
""")
// CHECKSTYLE:ON
+ @Ignore // Package name is no longer set via config.
public static class RuleWithDifferentTypeInBaseClassSuccessTest extends RuleWithDifferentTypeInBaseClass {
@Test
diff --git a/ravenwood/tests/coretest/test/com/android/ravenwoodtest/runnercallbacktests/RavenwoodRunnerTestBase.java b/ravenwood/tests/coretest/test/com/android/ravenwoodtest/runnercallbacktests/RavenwoodRunnerTestBase.java
index f7a2198..0e3d053 100644
--- a/ravenwood/tests/coretest/test/com/android/ravenwoodtest/runnercallbacktests/RavenwoodRunnerTestBase.java
+++ b/ravenwood/tests/coretest/test/com/android/ravenwoodtest/runnercallbacktests/RavenwoodRunnerTestBase.java
@@ -25,6 +25,8 @@
import junitparams.JUnitParamsRunner;
import junitparams.Parameters;
+
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.Description;
import org.junit.runner.JUnitCore;
@@ -103,6 +105,7 @@
var thisClass = this.getClass();
var ret = Arrays.stream(thisClass.getNestMembers())
.filter((c) -> c.getAnnotation(Expected.class) != null)
+ .filter((c) -> c.getAnnotation(Ignore.class) == null)
.toArray(Class[]::new);
assertThat(ret.length).isGreaterThan(0);
diff --git a/ravenwood/tests/runtime-test/Android.bp b/ravenwood/tests/runtime-test/Android.bp
index 0c0df1f..c352003 100644
--- a/ravenwood/tests/runtime-test/Android.bp
+++ b/ravenwood/tests/runtime-test/Android.bp
@@ -9,7 +9,7 @@
android_ravenwood_test {
name: "RavenwoodRuntimeTest",
-
+ target_sdk_version: "34",
libs: [
"ravenwood-helper-runtime",
],
diff --git a/ravenwood/tests/services-test/test/com/android/ravenwoodtest/servicestest/RavenwoodServicesTest.java b/ravenwood/tests/services-test/test/com/android/ravenwoodtest/servicestest/RavenwoodServicesTest.java
index f0ab3d6..4aae1e1 100644
--- a/ravenwood/tests/services-test/test/com/android/ravenwoodtest/servicestest/RavenwoodServicesTest.java
+++ b/ravenwood/tests/services-test/test/com/android/ravenwoodtest/servicestest/RavenwoodServicesTest.java
@@ -24,7 +24,6 @@
import android.content.Context;
import android.hardware.SerialManager;
import android.hardware.SerialManagerInternal;
-import android.platform.test.annotations.DisabledOnRavenwood;
import android.platform.test.ravenwood.RavenwoodConfig;
import android.platform.test.ravenwood.RavenwoodConfig.Config;
diff --git a/ravenwood/texts/ravenwood-annotation-allowed-classes.txt b/ravenwood/texts/ravenwood-annotation-allowed-classes.txt
index 39e0cf9..c196a09 100644
--- a/ravenwood/texts/ravenwood-annotation-allowed-classes.txt
+++ b/ravenwood/texts/ravenwood-annotation-allowed-classes.txt
@@ -2,6 +2,9 @@
com.android.internal.ravenwood.*
+com.android.server.FgThread
+com.android.server.ServiceThread
+
com.android.internal.display.BrightnessSynchronizer
com.android.internal.util.ArrayUtils
com.android.internal.logging.MetricsLogger
@@ -371,4 +374,3 @@
com.android.server.compat.*
com.android.internal.compat.*
android.app.AppCompatCallbacks
-
diff --git a/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/Validator.kt b/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/Validator.kt
index 8ec0932..61e254b 100644
--- a/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/Validator.kt
+++ b/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/Validator.kt
@@ -43,7 +43,7 @@
}
var allOk = true
- log.i("Checking ${cn.name.toHumanReadableClassName()}")
+ log.v("Checking ${cn.name.toHumanReadableClassName()}")
// See if there's any class that extends a legacy base class.
// But ignore the base classes in android.test.
diff --git a/services/Android.bp b/services/Android.bp
index cc20d70..437e6ef 100644
--- a/services/Android.bp
+++ b/services/Android.bp
@@ -195,7 +195,17 @@
module_type: "java_library",
config_namespace: "system_services",
bool_variables: ["without_vibrator"],
- properties: ["vintf_fragments"],
+ properties: ["vintf_fragment_modules"],
+}
+
+vintf_fragment {
+ name: "manifest_services.xml",
+ src: "manifest_services.xml",
+}
+
+vintf_fragment {
+ name: "manifest_services_android.frameworks.vibrator.xml",
+ src: "manifest_services_android.frameworks.vibrator.xml",
}
system_java_library {
@@ -265,11 +275,11 @@
soong_config_variables: {
without_vibrator: {
- vintf_fragments: [
+ vintf_fragment_modules: [
"manifest_services.xml",
],
conditions_default: {
- vintf_fragments: [
+ vintf_fragment_modules: [
"manifest_services.xml",
"manifest_services_android.frameworks.vibrator.xml",
],
diff --git a/services/core/java/com/android/server/SystemConfig.java b/services/core/java/com/android/server/SystemConfig.java
index 9b987e9..8c83ad7 100644
--- a/services/core/java/com/android/server/SystemConfig.java
+++ b/services/core/java/com/android/server/SystemConfig.java
@@ -1319,6 +1319,7 @@
}
XmlUtils.skipCurrentTag(parser);
} break;
+ case "disabled-in-sku":
case "disabled-until-used-preinstalled-carrier-app": {
if (allowAppConfigs) {
String pkgname = parser.getAttributeValue(null, "package");
@@ -1335,6 +1336,24 @@
}
XmlUtils.skipCurrentTag(parser);
} break;
+ case "enabled-in-sku-override": {
+ if (allowAppConfigs) {
+ String pkgname = parser.getAttributeValue(null, "package");
+ if (pkgname == null) {
+ Slog.w(TAG,
+ "<" + name + "> without "
+ + "package in " + permFile + " at "
+ + parser.getPositionDescription());
+ } else if (!mDisabledUntilUsedPreinstalledCarrierApps.remove(pkgname)) {
+ Slog.w(TAG,
+ "<" + name + "> packagename:" + pkgname + " not included"
+ + "in disabled-in-sku");
+ }
+ } else {
+ logNotAllowedInPartition(name, permFile, parser);
+ }
+ XmlUtils.skipCurrentTag(parser);
+ } break;
case "privapp-permissions": {
if (allowPrivappPermissions) {
// privapp permissions from system, apex, vendor, product and
diff --git a/services/core/java/com/android/server/VcnManagementService.java b/services/core/java/com/android/server/VcnManagementService.java
index 06e6c8b..2012f56 100644
--- a/services/core/java/com/android/server/VcnManagementService.java
+++ b/services/core/java/com/android/server/VcnManagementService.java
@@ -48,7 +48,6 @@
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
-import android.net.vcn.Flags;
import android.net.vcn.IVcnManagementService;
import android.net.vcn.IVcnStatusCallback;
import android.net.vcn.IVcnUnderlyingNetworkPolicyListener;
@@ -890,20 +889,11 @@
while (configsIterator.hasNext()) {
final ParcelUuid subGrp = configsIterator.next();
- if (Flags.fixConfigGarbageCollection()) {
- if (!subGroups.contains(subGrp)) {
- // Trim subGrps with no more subscriptions; must have moved to another subGrp
- logDbg("Garbage collect VcnConfig for group=" + subGrp);
- configsIterator.remove();
- shouldWrite = true;
- }
- } else {
- final List<SubscriptionInfo> subscriptions = subMgr.getSubscriptionsInGroup(subGrp);
- if (subscriptions == null || subscriptions.isEmpty()) {
- // Trim subGrps with no more subscriptions; must have moved to another subGrp
- configsIterator.remove();
- shouldWrite = true;
- }
+ if (!subGroups.contains(subGrp)) {
+ // Trim subGrps with no more subscriptions; must have moved to another subGrp
+ logDbg("Garbage collect VcnConfig for group=" + subGrp);
+ configsIterator.remove();
+ shouldWrite = true;
}
}
diff --git a/services/core/java/com/android/server/am/CachedAppOptimizer.java b/services/core/java/com/android/server/am/CachedAppOptimizer.java
index 416c110..2323fe9 100644
--- a/services/core/java/com/android/server/am/CachedAppOptimizer.java
+++ b/services/core/java/com/android/server/am/CachedAppOptimizer.java
@@ -2122,7 +2122,7 @@
Slog.d(TAG_AM,
"Performing native compaction for pid=" + pid
+ " type=" + compactProfile.name());
- Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "compactSystem");
+ Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "compactNative");
try {
mProcessDependencies.performCompaction(compactProfile, pid);
} catch (Exception e) {
diff --git a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
index 8743860..f1965f6 100644
--- a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
+++ b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
@@ -500,7 +500,7 @@
proto.write(StorageRequestMessage.FlagOverrideMessage.FLAG_NAME, flagName);
proto.write(StorageRequestMessage.FlagOverrideMessage.FLAG_VALUE, flagValue);
proto.write(StorageRequestMessage.FlagOverrideMessage.OVERRIDE_TYPE, isLocal
- ? StorageRequestMessage.LOCAL_ON_REBOOT
+ ? StorageRequestMessage.LOCAL_IMMEDIATE
: StorageRequestMessage.SERVER_ON_REBOOT);
proto.end(msgToken);
proto.end(msgsToken);
diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java
index feef540..b0c4359 100644
--- a/services/core/java/com/android/server/biometrics/BiometricService.java
+++ b/services/core/java/com/android/server/biometrics/BiometricService.java
@@ -101,6 +101,7 @@
import java.util.Random;
import java.util.Set;
import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.CopyOnWriteArrayList;
import java.util.function.Supplier;
/**
@@ -132,7 +133,7 @@
IGateKeeperService mGateKeeper;
// Get and cache the available biometric authenticators and their associated info.
- final ArrayList<BiometricSensor> mSensors = new ArrayList<>();
+ final CopyOnWriteArrayList<BiometricSensor> mSensors = new CopyOnWriteArrayList<>();
@VisibleForTesting
BiometricStrengthController mBiometricStrengthController;
@@ -156,13 +157,13 @@
@NonNull private final Set<Integer> mSensorsPendingInvalidation;
public static InvalidationTracker start(@NonNull Context context,
- @NonNull ArrayList<BiometricSensor> sensors,
- int userId, int fromSensorId, @NonNull IInvalidationCallback clientCallback) {
+ @NonNull List<BiometricSensor> sensors, int userId,
+ int fromSensorId, @NonNull IInvalidationCallback clientCallback) {
return new InvalidationTracker(context, sensors, userId, fromSensorId, clientCallback);
}
private InvalidationTracker(@NonNull Context context,
- @NonNull ArrayList<BiometricSensor> sensors, int userId,
+ @NonNull List<BiometricSensor> sensors, int userId,
int fromSensorId, @NonNull IInvalidationCallback clientCallback) {
mClientCallback = clientCallback;
mSensorsPendingInvalidation = new ArraySet<>();
@@ -844,7 +845,7 @@
@android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
@Override
- public synchronized void registerAuthenticator(int id, int modality,
+ public void registerAuthenticator(int id, int modality,
@Authenticators.Types int strength,
@NonNull IBiometricAuthenticator authenticator) {
diff --git a/services/core/java/com/android/server/biometrics/PreAuthInfo.java b/services/core/java/com/android/server/biometrics/PreAuthInfo.java
index b2c616a..bc38f65 100644
--- a/services/core/java/com/android/server/biometrics/PreAuthInfo.java
+++ b/services/core/java/com/android/server/biometrics/PreAuthInfo.java
@@ -216,10 +216,6 @@
return BIOMETRIC_NO_HARDWARE;
}
- if (sensor.modality == TYPE_FACE && biometricCameraManager.isAnyCameraUnavailable()) {
- return BIOMETRIC_HARDWARE_NOT_DETECTED;
- }
-
final boolean wasStrongEnough =
Utils.isAtLeastStrength(sensor.oemStrength, requestedStrength);
final boolean isStrongEnough =
@@ -231,6 +227,10 @@
return BIOMETRIC_INSUFFICIENT_STRENGTH;
}
+ if (sensor.modality == TYPE_FACE && biometricCameraManager.isAnyCameraUnavailable()) {
+ return BIOMETRIC_HARDWARE_NOT_DETECTED;
+ }
+
try {
if (!sensor.impl.isHardwareDetected(opPackageName)) {
return BIOMETRIC_HARDWARE_NOT_DETECTED;
diff --git a/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java b/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java
index 82d5d4d..e8786be 100644
--- a/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java
+++ b/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java
@@ -677,10 +677,11 @@
* Start the timeout for the watchdog.
*/
public void startWatchdog() {
- if (mCurrentOperation == null) {
+ final BiometricSchedulerOperation operation = mCurrentOperation;
+ if (operation == null) {
+ Slog.e(TAG, "Current operation is null,no need to start watchdog");
return;
}
- final BiometricSchedulerOperation operation = mCurrentOperation;
mHandler.postDelayed(() -> {
if (operation == mCurrentOperation && !operation.isFinished()) {
Counter.logIncrement("biometric.value_scheduler_watchdog_triggered_count");
diff --git a/services/core/java/com/android/server/display/color/TintController.java b/services/core/java/com/android/server/display/color/TintController.java
index 716661d..68dc80f 100644
--- a/services/core/java/com/android/server/display/color/TintController.java
+++ b/services/core/java/com/android/server/display/color/TintController.java
@@ -19,6 +19,7 @@
import android.animation.ValueAnimator;
import android.content.Context;
import android.util.Slog;
+import com.android.internal.annotations.GuardedBy;
import java.io.PrintWriter;
@@ -29,23 +30,33 @@
*/
private static final long TRANSITION_DURATION = 3000L;
+ private final Object mLock = new Object();
+
+ @GuardedBy("mLock")
private ValueAnimator mAnimator;
+ @GuardedBy("mLock")
private Boolean mIsActivated;
public ValueAnimator getAnimator() {
- return mAnimator;
+ synchronized (mLock) {
+ return mAnimator;
+ }
}
public void setAnimator(ValueAnimator animator) {
- mAnimator = animator;
+ synchronized (mLock) {
+ mAnimator = animator;
+ }
}
/**
* Cancel the animator if it's still running.
*/
public void cancelAnimator() {
- if (mAnimator != null) {
- mAnimator.cancel();
+ synchronized (mLock) {
+ if (mAnimator != null) {
+ mAnimator.cancel();
+ }
}
}
@@ -53,22 +64,30 @@
* End the animator if it's still running, jumping to the end state.
*/
public void endAnimator() {
- if (mAnimator != null) {
- mAnimator.end();
- mAnimator = null;
+ synchronized (mLock) {
+ if (mAnimator != null) {
+ mAnimator.end();
+ mAnimator = null;
+ }
}
}
public void setActivated(Boolean isActivated) {
- mIsActivated = isActivated;
+ synchronized (mLock) {
+ mIsActivated = isActivated;
+ }
}
public boolean isActivated() {
- return mIsActivated != null && mIsActivated;
+ synchronized (mLock) {
+ return mIsActivated != null && mIsActivated;
+ }
}
public boolean isActivatedStateNotSet() {
- return mIsActivated == null;
+ synchronized (mLock) {
+ return mIsActivated == null;
+ }
}
public long getTransitionDurationMilliseconds() {
diff --git a/services/core/java/com/android/server/input/InputShellCommand.java b/services/core/java/com/android/server/input/InputShellCommand.java
index 4c5a3c2..d8cf68e 100644
--- a/services/core/java/com/android/server/input/InputShellCommand.java
+++ b/services/core/java/com/android/server/input/InputShellCommand.java
@@ -472,6 +472,7 @@
}
}
}
+ event = KeyEvent.changeTimeRepeat(event, SystemClock.uptimeMillis(), 0);
injectKeyEvent(KeyEvent.changeAction(event, KeyEvent.ACTION_UP), async);
}
diff --git a/services/core/java/com/android/server/pm/OWNERS b/services/core/java/com/android/server/pm/OWNERS
index e8fc577..62b89f32 100644
--- a/services/core/java/com/android/server/pm/OWNERS
+++ b/services/core/java/com/android/server/pm/OWNERS
@@ -38,19 +38,19 @@
per-file SaferIntentUtils.java = topjohnwu@google.com
# shortcuts
-per-file LauncherAppsService.java = omakoto@google.com, yamasani@google.com, sunnygoyal@google.com, mett@google.com, pinyaoting@google.com
-per-file ShareTargetInfo.java = omakoto@google.com, yamasani@google.com, sunnygoyal@google.com, mett@google.com, pinyaoting@google.com
-per-file ShortcutBitmapSaver.java = omakoto@google.com, yamasani@google.com, sunnygoyal@google.com, mett@google.com, pinyaoting@google.com
-per-file ShortcutDumpFiles.java = omakoto@google.com, yamasani@google.com, sunnygoyal@google.com, mett@google.com, pinyaoting@google.com
-per-file ShortcutLauncher.java = omakoto@google.com, yamasani@google.com, sunnygoyal@google.com, mett@google.com, pinyaoting@google.com
-per-file ShortcutNonPersistentUser.java = omakoto@google.com, yamasani@google.com, sunnygoyal@google.com, mett@google.com, pinyaoting@google.com
-per-file ShortcutPackage.java = omakoto@google.com, yamasani@google.com, sunnygoyal@google.com, mett@google.com, pinyaoting@google.com
-per-file ShortcutPackageInfo.java = omakoto@google.com, yamasani@google.com, sunnygoyal@google.com, mett@google.com, pinyaoting@google.com
-per-file ShortcutPackageItem.java = omakoto@google.com, yamasani@google.com, sunnygoyal@google.com, mett@google.com, pinyaoting@google.com
-per-file ShortcutParser.java = omakoto@google.com, yamasani@google.com, sunnygoyal@google.com, mett@google.com, pinyaoting@google.com
-per-file ShortcutRequestPinProcessor.java = omakoto@google.com, yamasani@google.com, sunnygoyal@google.com, mett@google.com, pinyaoting@google.com
-per-file ShortcutService.java = omakoto@google.com, yamasani@google.com, sunnygoyal@google.com, mett@google.com, pinyaoting@google.com
-per-file ShortcutUser.java = omakoto@google.com, yamasani@google.com, sunnygoyal@google.com, mett@google.com, pinyaoting@google.com
+per-file LauncherAppsService.java = pinyaoting@google.com, sunnygoyal@google.com
+per-file ShareTargetInfo.java = pinyaoting@google.com, sunnygoyal@google.com
+per-file ShortcutBitmapSaver.java = pinyaoting@google.com, sunnygoyal@google.com
+per-file ShortcutDumpFiles.java = pinyaoting@google.com, sunnygoyal@google.com
+per-file ShortcutLauncher.java = pinyaoting@google.com, sunnygoyal@google.com
+per-file ShortcutNonPersistentUser.java = pinyaoting@google.com, sunnygoyal@google.com
+per-file ShortcutPackage.java = pinyaoting@google.com, sunnygoyal@google.com
+per-file ShortcutPackageInfo.java = pinyaoting@google.com, sunnygoyal@google.com
+per-file ShortcutPackageItem.java = pinyaoting@google.com, sunnygoyal@google.com
+per-file ShortcutParser.java = pinyaoting@google.com, sunnygoyal@google.com
+per-file ShortcutRequestPinProcessor.java = pinyaoting@google.com, sunnygoyal@google.com
+per-file ShortcutService.java = pinyaoting@google.com, sunnygoyal@google.com
+per-file ShortcutUser.java = pinyaoting@google.com, sunnygoyal@google.com
# background install control service
-per-file BackgroundInstall* = file:BACKGROUND_INSTALL_OWNERS
\ No newline at end of file
+per-file BackgroundInstall* = file:BACKGROUND_INSTALL_OWNERS
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index c71bb13..3758341 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -3022,7 +3022,10 @@
if (com.android.ranging.flags.Flags.rangingStackEnabled()) {
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_UWB)
|| context.getPackageManager().hasSystemFeature(
- PackageManager.FEATURE_WIFI_RTT)) {
+ PackageManager.FEATURE_WIFI_RTT)
+ || (com.android.ranging.flags.Flags.rangingCsEnabled()
+ && context.getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_BLUETOOTH_LE_CHANNEL_SOUNDING))) {
t.traceBegin("RangingService");
// TODO: b/375264320 - Remove after RELEASE_RANGING_STACK is ramped to next.
try {
diff --git a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
index 4e86888..e307e52 100644
--- a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
+++ b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
@@ -144,6 +144,10 @@
public void onBootPhase(int phase) {
if (phase == PHASE_SYSTEM_SERVICES_READY) {
UsbManager usbManager = getContext().getSystemService(UsbManager.class);
+ if (usbManager == null) {
+ mAdbActive = false;
+ return;
+ }
mAdbActive = ((usbManager.getCurrentFunctions() & UsbManager.FUNCTION_ADB) == 1);
Log.d(LOG_TAG, "ADB is " + mAdbActive + " on system startup");
}
diff --git a/services/tests/apexsystemservices/services/Android.bp b/services/tests/apexsystemservices/services/Android.bp
index 477ea4c..70d84dc 100644
--- a/services/tests/apexsystemservices/services/Android.bp
+++ b/services/tests/apexsystemservices/services/Android.bp
@@ -17,4 +17,5 @@
],
visibility: ["//frameworks/base/services/tests/apexsystemservices:__subpackages__"],
apex_available: ["//apex_available:anyapex"],
+ compile_dex: true,
}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/PreAuthInfoTest.java b/services/tests/servicestests/src/com/android/server/biometrics/PreAuthInfoTest.java
index b758f57..bf499c7 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/PreAuthInfoTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/PreAuthInfoTest.java
@@ -21,6 +21,7 @@
import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT;
import static android.hardware.biometrics.BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE;
import static android.hardware.biometrics.BiometricManager.BIOMETRIC_ERROR_NOT_ENABLED_FOR_APPS;
+import static android.hardware.biometrics.BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE;
import static com.android.server.biometrics.sensors.LockoutTracker.LOCKOUT_NONE;
@@ -64,6 +65,7 @@
public final CheckFlagsRule mCheckFlagsRule =
DeviceFlagsValueProvider.createCheckFlagsRule();
+ private static final int USER_ID = 0;
private static final int SENSOR_ID_FINGERPRINT = 0;
private static final int SENSOR_ID_FACE = 1;
private static final String TEST_PACKAGE_NAME = "PreAuthInfoTestPackage";
@@ -304,6 +306,20 @@
assertThat(promptInfo.getNegativeButtonText()).isEqualTo(TEST_PACKAGE_NAME);
}
+ @Test
+ public void prioritizeStrengthErrorBeforeCameraUnavailableError() throws Exception {
+ final BiometricSensor sensor = getFaceSensorWithStrength(
+ BiometricManager.Authenticators.BIOMETRIC_WEAK);
+ final PromptInfo promptInfo = new PromptInfo();
+ promptInfo.setAuthenticators(BiometricManager.Authenticators.BIOMETRIC_STRONG);
+ promptInfo.setNegativeButtonText(TEST_PACKAGE_NAME);
+ final PreAuthInfo preAuthInfo = PreAuthInfo.create(mTrustManager, mDevicePolicyManager,
+ mSettingObserver, List.of(sensor), USER_ID , promptInfo, TEST_PACKAGE_NAME,
+ false /* checkDevicePolicyManager */, mContext, mBiometricCameraManager);
+
+ assertThat(preAuthInfo.getCanAuthenticateResult()).isEqualTo(BIOMETRIC_ERROR_NO_HARDWARE);
+ }
+
private BiometricSensor getFingerprintSensor() {
BiometricSensor sensor = new BiometricSensor(mContext, SENSOR_ID_FINGERPRINT,
TYPE_FINGERPRINT, BiometricManager.Authenticators.BIOMETRIC_STRONG,
@@ -322,9 +338,10 @@
return sensor;
}
- private BiometricSensor getFaceSensor() {
+ private BiometricSensor getFaceSensorWithStrength(
+ @BiometricManager.Authenticators.Types int sensorStrength) {
BiometricSensor sensor = new BiometricSensor(mContext, SENSOR_ID_FACE, TYPE_FACE,
- BiometricManager.Authenticators.BIOMETRIC_STRONG, mFaceAuthenticator) {
+ sensorStrength, mFaceAuthenticator) {
@Override
boolean confirmationAlwaysRequired(int userId) {
return false;
@@ -338,4 +355,8 @@
return sensor;
}
+
+ private BiometricSensor getFaceSensor() {
+ return getFaceSensorWithStrength(BiometricManager.Authenticators.BIOMETRIC_STRONG);
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java b/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java
index 3bc089f..842c441 100644
--- a/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java
+++ b/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java
@@ -691,6 +691,40 @@
assertThat(actual).isEqualTo(expected);
}
+ /**
+ * Tests that readPermissions works correctly for the tags:
+ * disabled-in-sku, enabled-in-sku-override.
+ * I.e. that disabled-in-sku add package to block list and
+ * enabled-in-sku-override removes package from the list.
+ */
+ @Test
+ public void testDisablePackageInSku() throws Exception {
+ final String disable_in_sku =
+ "<config>\n"
+ + " <disabled-in-sku package=\"com.sony.product1.app\"/>\n"
+ + " <disabled-in-sku package=\"com.sony.product2.app\"/>\n"
+ + "</config>\n";
+
+ final String enable_in_sku_override =
+ "<config>\n"
+ + " <enabled-in-sku-override package=\"com.sony.product2.app\"/>\n"
+ + "</config>\n";
+
+ final File folder1 = createTempSubfolder("folder1");
+ createTempFile(folder1, "permissionFile1.xml", disable_in_sku);
+
+ final File folder2 = createTempSubfolder("folder2");
+ createTempFile(folder2, "permissionFile2.xml", enable_in_sku_override);
+
+ readPermissions(folder1, /* Grant all permission flags */ ~0);
+ readPermissions(folder2, /* Grant all permission flags */ ~0);
+
+ final ArraySet<String> blocklist = mSysConfig.getDisabledUntilUsedPreinstalledCarrierApps();
+
+ assertThat(blocklist).contains("com.sony.product1.app");
+ assertThat(blocklist).doesNotContain("com.sony.product2.app");
+ }
+
private void parseSharedLibraries(String contents) throws IOException {
File folder = createTempSubfolder("permissions_folder");
createTempFile(folder, "permissions.xml", contents);
diff --git a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
index 3828a71..4ab8e6a 100644
--- a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
+++ b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
@@ -70,7 +70,6 @@
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import android.net.Uri;
-import android.net.vcn.Flags;
import android.net.vcn.IVcnStatusCallback;
import android.net.vcn.IVcnUnderlyingNetworkPolicyListener;
import android.net.vcn.VcnConfig;
@@ -293,8 +292,6 @@
doReturn(Collections.singleton(TRANSPORT_WIFI))
.when(mMockDeps)
.getRestrictedTransports(any(), any(), any());
-
- mSetFlagsRule.enableFlags(Flags.FLAG_FIX_CONFIG_GARBAGE_COLLECTION);
}