summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.prebuilt_info/prebuilt_info_packages_CtsShim_apk__arm_CtsShimPriv_apk.asciipb3
-rw-r--r--.prebuilt_info/prebuilt_info_packages_CtsShim_apk__arm_CtsShim_apk.asciipb3
-rw-r--r--.prebuilt_info/prebuilt_info_packages_CtsShim_apk__x86_CtsShimPriv_apk.asciipb3
-rw-r--r--.prebuilt_info/prebuilt_info_packages_CtsShim_apk__x86_CtsShim_apk.asciipb3
-rw-r--r--apex/appsearch/service/java/com/android/server/appsearch/AppSearchConfig.java249
-rw-r--r--apex/appsearch/service/java/com/android/server/appsearch/stats/PlatformLogger.java70
-rw-r--r--core/api/current.txt235
-rw-r--r--core/api/removed.txt8
-rw-r--r--core/api/system-current.txt42
-rw-r--r--core/api/test-current.txt19
-rw-r--r--core/java/android/app/ActivityManager.java3
-rw-r--r--core/java/android/app/ActivityThread.java28
-rw-r--r--core/java/android/app/AppOpsManager.java177
-rw-r--r--core/java/android/app/AppOpsManagerInternal.java40
-rw-r--r--core/java/android/app/ContextImpl.java8
-rw-r--r--core/java/android/app/Notification.java13
-rw-r--r--core/java/android/app/SystemServiceRegistry.java9
-rw-r--r--core/java/android/content/AttributionSource.java131
-rw-r--r--core/java/android/content/ContentProvider.java13
-rw-r--r--core/java/android/content/Context.java8
-rw-r--r--core/java/android/content/PermissionChecker.java139
-rw-r--r--core/java/android/hardware/camera2/params/OutputConfiguration.java12
-rw-r--r--core/java/android/hardware/fingerprint/IUdfpsOverlayController.aidl4
-rwxr-xr-xcore/java/android/os/Build.java2
-rw-r--r--core/java/android/os/VibrationEffect.java11
-rw-r--r--core/java/android/permission/IPermissionManager.aidl2
-rw-r--r--core/java/android/permission/PermissionCheckerManager.java186
-rw-r--r--core/java/android/permission/PermissionManager.java5
-rw-r--r--core/java/android/provider/Settings.java16
-rw-r--r--core/java/android/speech/RecognitionService.java125
-rw-r--r--core/java/android/view/IWindowSession.aidl14
-rw-r--r--core/java/android/view/SurfaceControl.java7
-rw-r--r--core/java/android/view/ViewRootImpl.java7
-rw-r--r--core/java/android/view/WindowlessWindowManager.java5
-rw-r--r--core/java/android/widget/EdgeEffect.java56
-rw-r--r--core/java/com/android/internal/app/AbstractResolverComparator.java12
-rw-r--r--core/java/com/android/internal/app/AppPredictionServiceResolverComparator.java17
-rw-r--r--core/java/com/android/internal/app/ChooserActivity.java7
-rw-r--r--core/java/com/android/internal/app/ChooserActivityLogger.java20
-rw-r--r--core/java/com/android/internal/app/ChooserListAdapter.java6
-rw-r--r--core/java/com/android/internal/app/IAppOpsActiveCallback.aidl3
-rw-r--r--core/java/com/android/internal/app/IAppOpsService.aidl11
-rw-r--r--core/java/com/android/internal/app/ResolverListController.java2
-rw-r--r--core/java/com/android/internal/app/ResolverRankerServiceResolverComparator.java4
-rw-r--r--core/java/com/android/internal/content/F2fsUtils.java296
-rw-r--r--core/java/com/android/internal/content/OWNERS5
-rw-r--r--core/jni/Android.bp4
-rw-r--r--core/jni/AndroidRuntime.cpp4
-rw-r--r--core/jni/android_media_AudioRecord.cpp20
-rw-r--r--core/jni/android_media_AudioTrack.cpp12
-rw-r--r--core/jni/com_android_internal_content_F2fsUtils.cpp84
-rw-r--r--core/jni/permission_utils.cpp71
-rw-r--r--core/res/AndroidManifest.xml8
-rw-r--r--core/res/res/values/config.xml3
-rw-r--r--core/res/res/values/dimens.xml4
-rw-r--r--core/res/res/values/public.xml336
-rw-r--r--core/res/res/values/symbols.xml3
-rw-r--r--core/res/res/values/themes_device_defaults.xml129
-rw-r--r--core/tests/coretests/src/android/os/VibrationEffectTest.java5
-rw-r--r--core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java51
-rw-r--r--core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java3
-rw-r--r--data/etc/privapp-permissions-platform.xml1
-rw-r--r--libs/WindowManager/Shell/res/values/dimen.xml5
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java13
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java4
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/tasksurfacehelper/TaskSurfaceHelper.java (renamed from core/jni/permission_utils.h)15
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/tasksurfacehelper/TaskSurfaceHelperController.java60
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/tasksurfacehelper/TaskSurfaceHelperControllerTest.java58
-rw-r--r--libs/androidfw/TEST_MAPPING5
-rw-r--r--media/java/android/media/AudioRecord.java85
-rw-r--r--media/java/android/media/MediaPlayer.java18
-rw-r--r--media/java/android/media/MediaRecorder.java24
-rw-r--r--media/java/android/media/audiofx/AudioEffect.java18
-rw-r--r--media/java/android/media/audiofx/Visualizer.java17
-rw-r--r--media/java/android/media/permission/PermissionUtil.java18
-rw-r--r--media/jni/Android.bp2
-rw-r--r--media/jni/android_media_MediaPlayer.cpp12
-rw-r--r--media/jni/android_media_MediaRecorder.cpp14
-rw-r--r--media/jni/audioeffect/Android.bp5
-rw-r--r--media/jni/audioeffect/Visualizer.cpp6
-rw-r--r--media/jni/audioeffect/Visualizer.h8
-rw-r--r--media/jni/audioeffect/android_media_AudioEffect.cpp16
-rw-r--r--media/jni/audioeffect/android_media_Visualizer.cpp16
-rw-r--r--media/jni/soundpool/Android.bp2
-rw-r--r--media/jni/soundpool/Stream.cpp11
-rw-r--r--packages/CtsShim/apk/arm/CtsShim.apkbin5485 -> 5483 bytes
-rw-r--r--packages/CtsShim/apk/arm/CtsShimPriv.apkbin31627 -> 31624 bytes
-rw-r--r--packages/CtsShim/apk/x86/CtsShim.apkbin5485 -> 5483 bytes
-rw-r--r--packages/CtsShim/apk/x86/CtsShimPriv.apkbin24252 -> 24257 bytes
-rw-r--r--packages/SettingsLib/CollapsingToolbarBaseActivity/res/values/dimens.xml8
-rw-r--r--packages/SettingsLib/CollapsingToolbarBaseActivity/src/com/android/settingslib/collapsingtoolbar/AdjustableToolbarLayout.java39
-rw-r--r--packages/SettingsLib/MainSwitchPreference/res/layout-v31/settingslib_main_switch_bar.xml1
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java11
-rw-r--r--packages/SystemUI/res/drawable/screenshot_edit_background.xml33
-rw-r--r--packages/SystemUI/res/drawable/screenshot_save_background.xml33
-rw-r--r--packages/SystemUI/res/layout/long_screenshot.xml6
-rw-r--r--packages/SystemUI/res/layout/qs_paged_page.xml6
-rw-r--r--packages/SystemUI/res/values/styles.xml5
-rw-r--r--packages/SystemUI/src/com/android/keyguard/LockIconView.java36
-rw-r--r--packages/SystemUI/src/com/android/systemui/SystemUIFactory.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/SidefpsController.java90
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/SidefpsView.java40
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java96
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt74
-rw-r--r--packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java20
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerTest.kt72
-rw-r--r--services/core/java/com/android/server/am/ActiveServices.java9
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java73
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerUtils.java8
-rw-r--r--services/core/java/com/android/server/am/AssistDataRequester.java56
-rw-r--r--services/core/java/com/android/server/app/GameManagerService.java13
-rw-r--r--services/core/java/com/android/server/appop/AppOpsService.java347
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/UdfpsHelper.java13
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java12
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java12
-rw-r--r--services/core/java/com/android/server/location/injector/SystemEmergencyHelper.java30
-rw-r--r--services/core/java/com/android/server/location/provider/LocationProviderManager.java16
-rw-r--r--services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java2
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java64
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerService.java286
-rw-r--r--services/core/java/com/android/server/policy/AppOpsPolicy.java34
-rw-r--r--services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java139
-rw-r--r--services/core/java/com/android/server/vibrator/ClippingAmplitudeAndFrequencyAdapter.java80
-rw-r--r--services/core/java/com/android/server/vibrator/DeviceVibrationEffectAdapter.java154
-rw-r--r--services/core/java/com/android/server/vibrator/RampToStepAdapter.java93
-rw-r--r--services/core/java/com/android/server/vibrator/StepToRampAdapter.java65
-rw-r--r--services/core/java/com/android/server/vibrator/VibrationEffectAdapters.java92
-rw-r--r--services/core/java/com/android/server/vibrator/VibrationEffectModifier.java26
-rw-r--r--services/core/java/com/android/server/vibrator/VibrationThread.java2
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java13
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerService.java2
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java22
-rw-r--r--services/core/java/com/android/server/wm/DisplayPolicy.java3
-rw-r--r--services/core/java/com/android/server/wm/Session.java5
-rw-r--r--services/core/java/com/android/server/wm/SystemGesturesPointerEventListener.java18
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java37
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java4
-rw-r--r--services/tests/mockingservicestests/Android.bp6
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/appsearch/AppSearchConfigTest.java286
-rw-r--r--services/tests/servicestests/src/com/android/server/appop/AppOpsActiveWatcherTest.java11
-rw-r--r--services/tests/servicestests/src/com/android/server/appsearch/stats/PlatformLoggerTest.java96
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/CrossProfileAppsServiceImplTest.java20
-rw-r--r--services/tests/servicestests/src/com/android/server/vibrator/DeviceVibrationEffectAdapterTest.java59
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java45
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java33
-rw-r--r--tools/aapt/SdkConstants.h1
-rw-r--r--tools/aapt2/SdkConstants.cpp3
-rw-r--r--tools/aapt2/SdkConstants.h1
-rwxr-xr-xtools/finalize_res/finalize_res.py41
159 files changed, 4420 insertions, 1754 deletions
diff --git a/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__arm_CtsShimPriv_apk.asciipb b/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__arm_CtsShimPriv_apk.asciipb
index cfcb4e7d69b1..80317e4634f3 100644
--- a/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__arm_CtsShimPriv_apk.asciipb
+++ b/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__arm_CtsShimPriv_apk.asciipb
@@ -1,6 +1,6 @@
drops {
android_build_drop {
- build_id: "7351002"
+ build_id: "7396576"
target: "CtsShim"
source_file: "aosp_arm64/CtsShimPriv.apk"
}
@@ -9,4 +9,5 @@ drops {
version_group: ""
git_project: "platform/frameworks/base"
git_branch: "sc-dev"
+ transform: TRANSFORM_NONE
}
diff --git a/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__arm_CtsShim_apk.asciipb b/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__arm_CtsShim_apk.asciipb
index 0948e47561a8..3605b6d0433b 100644
--- a/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__arm_CtsShim_apk.asciipb
+++ b/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__arm_CtsShim_apk.asciipb
@@ -1,6 +1,6 @@
drops {
android_build_drop {
- build_id: "7351002"
+ build_id: "7396576"
target: "CtsShim"
source_file: "aosp_arm64/CtsShim.apk"
}
@@ -9,4 +9,5 @@ drops {
version_group: ""
git_project: "platform/frameworks/base"
git_branch: "sc-dev"
+ transform: TRANSFORM_NONE
}
diff --git a/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__x86_CtsShimPriv_apk.asciipb b/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__x86_CtsShimPriv_apk.asciipb
index db6447525a18..025ec3a9fdaf 100644
--- a/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__x86_CtsShimPriv_apk.asciipb
+++ b/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__x86_CtsShimPriv_apk.asciipb
@@ -1,6 +1,6 @@
drops {
android_build_drop {
- build_id: "7351002"
+ build_id: "7396576"
target: "CtsShim"
source_file: "aosp_x86_64/CtsShimPriv.apk"
}
@@ -9,4 +9,5 @@ drops {
version_group: ""
git_project: "platform/frameworks/base"
git_branch: "sc-dev"
+ transform: TRANSFORM_NONE
}
diff --git a/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__x86_CtsShim_apk.asciipb b/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__x86_CtsShim_apk.asciipb
index 80812df718f8..e19235a12f8f 100644
--- a/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__x86_CtsShim_apk.asciipb
+++ b/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__x86_CtsShim_apk.asciipb
@@ -1,6 +1,6 @@
drops {
android_build_drop {
- build_id: "7351002"
+ build_id: "7396576"
target: "CtsShim"
source_file: "aosp_x86_64/CtsShim.apk"
}
@@ -9,4 +9,5 @@ drops {
version_group: ""
git_project: "platform/frameworks/base"
git_branch: "sc-dev"
+ transform: TRANSFORM_NONE
}
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchConfig.java b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchConfig.java
new file mode 100644
index 000000000000..6e81afcdc912
--- /dev/null
+++ b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchConfig.java
@@ -0,0 +1,249 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.appsearch;
+
+import android.annotation.NonNull;
+import android.os.Bundle;
+import android.provider.DeviceConfig;
+import android.provider.DeviceConfig.OnPropertiesChangedListener;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.Objects;
+import java.util.concurrent.Executor;
+
+/**
+ * It contains all the keys for the flags, as well as caches some of latest flag values from
+ * DeviceConfig.
+ *
+ * <p>Though the latest flag values can always be retrieved by calling {@code
+ * DeviceConfig.getProperty}, we want to cache some of those values. For example, the sampling
+ * intervals for logging, they are needed for each api call and it would be a little expensive to
+ * call
+ * {@code DeviceConfig.getProperty} every time.
+ *
+ * <p>Listener is registered to DeviceConfig keep the cached value up to date.
+ *
+ * <p>This class is thread-safe.
+ *
+ * @hide
+ */
+public final class AppSearchConfig implements AutoCloseable {
+ /**
+ * It would be used as default min time interval between samples in millis if there is no value
+ * set for {@link AppSearchConfig#KEY_MIN_TIME_INTERVAL_BETWEEN_SAMPLES_MILLIS} in DeviceConfig.
+ */
+ @VisibleForTesting
+ static final long DEFAULT_MIN_TIME_INTERVAL_BETWEEN_SAMPLES_MILLIS = 50;
+
+ /**
+ * It would be used as default sampling interval if there is no value
+ * set for {@link AppSearchConfig#KEY_SAMPLING_INTERVAL_DEFAULT} in DeviceConfig.
+ */
+ @VisibleForTesting
+ static final int DEFAULT_SAMPLING_INTERVAL = 10;
+
+ /*
+ * Keys for ALL the flags stored in DeviceConfig.
+ */
+ public static final String KEY_MIN_TIME_INTERVAL_BETWEEN_SAMPLES_MILLIS =
+ "min_time_interval_between_samples_millis";
+ public static final String KEY_SAMPLING_INTERVAL_DEFAULT = "sampling_interval_default";
+ public static final String KEY_SAMPLING_INTERVAL_FOR_BATCH_CALL_STATS =
+ "sampling_interval_for_batch_call_stats";
+ public static final String KEY_SAMPLING_INTERVAL_FOR_PUT_DOCUMENT_STATS =
+ "sampling_interval_for_put_document_stats";
+
+ // Array contains all the corresponding keys for the cached values.
+ private static final String[] KEYS_TO_ALL_CACHED_VALUES = {
+ KEY_MIN_TIME_INTERVAL_BETWEEN_SAMPLES_MILLIS,
+ KEY_SAMPLING_INTERVAL_DEFAULT,
+ KEY_SAMPLING_INTERVAL_FOR_BATCH_CALL_STATS,
+ KEY_SAMPLING_INTERVAL_FOR_PUT_DOCUMENT_STATS
+ };
+
+ // Lock needed for all the operations in this class.
+ private final Object mLock = new Object();
+
+ /**
+ * Bundle to hold all the cached flag values corresponding to
+ * {@link AppSearchConfig#KEYS_TO_ALL_CACHED_VALUES}.
+ */
+ @GuardedBy("mLock")
+ private final Bundle mBundleLocked = new Bundle();
+
+
+ @GuardedBy("mLock")
+ private boolean mIsClosedLocked = false;
+
+ /** Listener to update cached flag values from DeviceConfig. */
+ private final OnPropertiesChangedListener mOnDeviceConfigChangedListener =
+ properties -> {
+ if (!properties.getNamespace().equals(DeviceConfig.NAMESPACE_APPSEARCH)) {
+ return;
+ }
+
+ updateCachedValues(properties);
+ };
+
+ /**
+ * Creates an instance of {@link AppSearchConfig}.
+ *
+ * @param executor used to fetch and cache the flag values from DeviceConfig during creation or
+ * config change.
+ */
+ @NonNull
+ public static AppSearchConfig create(@NonNull Executor executor) {
+ Objects.requireNonNull(executor);
+ AppSearchConfig configManager = new AppSearchConfig();
+ configManager.initialize(executor);
+ return configManager;
+ }
+
+ private AppSearchConfig() {
+ }
+
+ /**
+ * Initializes the {@link AppSearchConfig}
+ *
+ * <p>It fetches the custom properties from DeviceConfig if available.
+ *
+ * @param executor listener would be run on to handle P/H flag change.
+ */
+ private void initialize(@NonNull Executor executor) {
+ executor.execute(() -> {
+ // Attach the callback to get updates on those properties.
+ DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_APPSEARCH,
+ executor,
+ mOnDeviceConfigChangedListener);
+
+ DeviceConfig.Properties properties = DeviceConfig.getProperties(
+ DeviceConfig.NAMESPACE_APPSEARCH, KEYS_TO_ALL_CACHED_VALUES);
+ updateCachedValues(properties);
+ });
+ }
+
+ // TODO(b/173532925) check this will be called. If we have a singleton instance for this
+ // class, probably we don't need it.
+ @Override
+ public void close() {
+ synchronized (mLock) {
+ if (mIsClosedLocked) {
+ return;
+ }
+
+ DeviceConfig.removeOnPropertiesChangedListener(mOnDeviceConfigChangedListener);
+ mIsClosedLocked = true;
+ }
+ }
+
+ /** Returns cached value for minTimeIntervalBetweenSamplesMillis. */
+ public long getCachedMinTimeIntervalBetweenSamplesMillis() {
+ synchronized (mLock) {
+ throwIfClosedLocked();
+ return mBundleLocked.getLong(KEY_MIN_TIME_INTERVAL_BETWEEN_SAMPLES_MILLIS,
+ DEFAULT_MIN_TIME_INTERVAL_BETWEEN_SAMPLES_MILLIS);
+ }
+ }
+
+ /**
+ * Returns cached value for default sampling interval for all the stats NOT listed in
+ * the configuration.
+ *
+ * <p>For example, sampling_interval=10 means that one out of every 10 stats was logged.
+ */
+ public int getCachedSamplingIntervalDefault() {
+ synchronized (mLock) {
+ throwIfClosedLocked();
+ return mBundleLocked.getInt(KEY_SAMPLING_INTERVAL_DEFAULT, DEFAULT_SAMPLING_INTERVAL);
+ }
+ }
+
+ /**
+ * Returns cached value for sampling interval for batch calls.
+ *
+ * <p>For example, sampling_interval=10 means that one out of every 10 stats was logged.
+ */
+ public int getCachedSamplingIntervalForBatchCallStats() {
+ synchronized (mLock) {
+ throwIfClosedLocked();
+ return mBundleLocked.getInt(KEY_SAMPLING_INTERVAL_FOR_BATCH_CALL_STATS,
+ getCachedSamplingIntervalDefault());
+ }
+ }
+
+ /**
+ * Returns cached value for sampling interval for putDocument.
+ *
+ * <p>For example, sampling_interval=10 means that one out of every 10 stats was logged.
+ */
+ public int getCachedSamplingIntervalForPutDocumentStats() {
+ synchronized (mLock) {
+ throwIfClosedLocked();
+ return mBundleLocked.getInt(KEY_SAMPLING_INTERVAL_FOR_PUT_DOCUMENT_STATS,
+ getCachedSamplingIntervalDefault());
+ }
+ }
+
+ @GuardedBy("mLock")
+ private void throwIfClosedLocked() {
+ if (mIsClosedLocked) {
+ throw new IllegalStateException("Trying to use a closed AppSearchConfig instance.");
+ }
+ }
+
+ private void updateCachedValues(@NonNull DeviceConfig.Properties properties) {
+ for (String key : properties.getKeyset()) {
+ updateCachedValue(key, properties);
+ }
+ }
+
+ private void updateCachedValue(@NonNull String key,
+ @NonNull DeviceConfig.Properties properties) {
+ if (properties.getString(key, /*defaultValue=*/ null) == null) {
+ // Key is missing or value is just null. That is not expected if the key is
+ // defined in the configuration.
+ //
+ // We choose NOT to put the default value in the bundle.
+ // Instead, we let the getters handle what default value should be returned.
+ //
+ // Also we keep the old value in the bundle. So getters can still
+ // return last valid value.
+ return;
+ }
+
+ switch (key) {
+ case KEY_MIN_TIME_INTERVAL_BETWEEN_SAMPLES_MILLIS:
+ synchronized (mLock) {
+ mBundleLocked.putLong(key,
+ properties.getLong(key,
+ DEFAULT_MIN_TIME_INTERVAL_BETWEEN_SAMPLES_MILLIS));
+ }
+ break;
+ case KEY_SAMPLING_INTERVAL_DEFAULT:
+ case KEY_SAMPLING_INTERVAL_FOR_BATCH_CALL_STATS:
+ case KEY_SAMPLING_INTERVAL_FOR_PUT_DOCUMENT_STATS:
+ synchronized (mLock) {
+ mBundleLocked.putInt(key, properties.getInt(key, DEFAULT_SAMPLING_INTERVAL));
+ }
+ break;
+ default:
+ break;
+ }
+ }
+}
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/stats/PlatformLogger.java b/apex/appsearch/service/java/com/android/server/appsearch/stats/PlatformLogger.java
index abcf1611ab04..7d0ce415502b 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/stats/PlatformLogger.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/stats/PlatformLogger.java
@@ -72,7 +72,7 @@ public final class PlatformLogger implements AppSearchLogger {
*
* <p> We can have correct extrapolated number by adding those counts back when we log
* the same type of stats next time. E.g. the true count of an event could be estimated as:
- * SUM(sampling_ratio * (num_skipped_sample + 1)) as est_count
+ * SUM(sampling_interval * (num_skipped_sample + 1)) as est_count
*
* <p>The key to the SparseArray is {@link CallStats.CallType}
*/
@@ -105,42 +105,42 @@ public final class PlatformLogger implements AppSearchLogger {
// logging again.
private final long mMinTimeIntervalBetweenSamplesMillis;
- // Default sampling ratio for all types of stats
- private final int mDefaultSamplingRatio;
+ // Default sampling interval for all types of stats
+ private final int mDefaultSamplingInterval;
/**
- * Sampling ratios for different types of stats
+ * Sampling intervals for different types of stats
*
* <p>This SparseArray is passed by client and is READ-ONLY. The key to that SparseArray is
* {@link CallStats.CallType}
*
- * <p>If sampling ratio is missing for certain stats type,
- * {@link Config#mDefaultSamplingRatio} will be used.
+ * <p>If sampling interval is missing for certain stats type,
+ * {@link Config#mDefaultSamplingInterval} will be used.
*
- * <p>E.g. sampling ratio=10 means that one out of every 10 stats was logged. If sampling
- * ratio is 1, we will log each sample and it acts as if the sampling is disabled.
+ * <p>E.g. sampling interval=10 means that one out of every 10 stats was logged. If sampling
+ * interval is 1, we will log each sample and it acts as if the sampling is disabled.
*/
@NonNull
- private final SparseIntArray mSamplingRatios;
+ private final SparseIntArray mSamplingIntervals;
/**
* Configuration for {@link PlatformLogger}
*
* @param minTimeIntervalBetweenSamplesMillis minimum time interval apart in Milliseconds
* required for two consecutive stats logged
- * @param defaultSamplingRatio default sampling ratio
- * @param samplingRatios SparseArray to customize sampling ratio for
+ * @param defaultSamplingInterval default sampling interval
+ * @param samplingIntervals SparseArray to customize sampling interval for
* different stat types
*/
public Config(long minTimeIntervalBetweenSamplesMillis,
- int defaultSamplingRatio,
- @NonNull SparseIntArray samplingRatios) {
+ int defaultSamplingInterval,
+ @NonNull SparseIntArray samplingIntervals) {
// TODO(b/173532925) Probably we can get rid of those three after we have p/h flags
// for them.
- // e.g. we can just call DeviceConfig.get(SAMPLING_RATIO_FOR_PUT_DOCUMENTS).
+ // e.g. we can just call DeviceConfig.get(SAMPLING_INTERVAL_FOR_PUT_DOCUMENTS).
mMinTimeIntervalBetweenSamplesMillis = minTimeIntervalBetweenSamplesMillis;
- mDefaultSamplingRatio = defaultSamplingRatio;
- mSamplingRatios = samplingRatios;
+ mDefaultSamplingInterval = defaultSamplingInterval;
+ mSamplingIntervals = samplingIntervals;
}
}
@@ -150,14 +150,14 @@ public final class PlatformLogger implements AppSearchLogger {
static final class ExtraStats {
// UID for the calling package of the stats.
final int mPackageUid;
- // sampling ratio for the call type of the stats.
- final int mSamplingRatio;
+ // sampling interval for the call type of the stats.
+ final int mSamplingInterval;
// number of samplings skipped before the current one for the same call type.
final int mSkippedSampleCount;
- ExtraStats(int packageUid, int samplingRatio, int skippedSampleCount) {
+ ExtraStats(int packageUid, int samplingInterval, int skippedSampleCount) {
mPackageUid = packageUid;
- mSamplingRatio = samplingRatio;
+ mSamplingInterval = samplingInterval;
mSkippedSampleCount = skippedSampleCount;
}
}
@@ -224,7 +224,7 @@ public final class PlatformLogger implements AppSearchLogger {
*
* @return removed UID for the package, or {@code INVALID_UID} if package was not previously
* cached.
- */
+ */
public int removeCachedUidForPackage(@NonNull String packageName) {
// TODO(b/173532925) This needs to be called when we get PACKAGE_REMOVED intent
Objects.requireNonNull(packageName);
@@ -243,7 +243,7 @@ public final class PlatformLogger implements AppSearchLogger {
try {
int hashCodeForDatabase = calculateHashCodeMd5(database);
AppSearchStatsLog.write(AppSearchStatsLog.APP_SEARCH_CALL_STATS_REPORTED,
- extraStats.mSamplingRatio,
+ extraStats.mSamplingInterval,
extraStats.mSkippedSampleCount,
extraStats.mPackageUid,
hashCodeForDatabase,
@@ -275,7 +275,7 @@ public final class PlatformLogger implements AppSearchLogger {
try {
int hashCodeForDatabase = calculateHashCodeMd5(database);
AppSearchStatsLog.write(AppSearchStatsLog.APP_SEARCH_PUT_DOCUMENT_STATS_REPORTED,
- extraStats.mSamplingRatio,
+ extraStats.mSamplingInterval,
extraStats.mSkippedSampleCount,
extraStats.mPackageUid,
hashCodeForDatabase,
@@ -312,7 +312,7 @@ public final class PlatformLogger implements AppSearchLogger {
try {
int hashCodeForDatabase = calculateHashCodeMd5(database);
AppSearchStatsLog.write(AppSearchStatsLog.APP_SEARCH_QUERY_STATS_REPORTED,
- extraStats.mSamplingRatio,
+ extraStats.mSamplingInterval,
extraStats.mSkippedSampleCount,
extraStats.mPackageUid,
hashCodeForDatabase,
@@ -355,7 +355,7 @@ public final class PlatformLogger implements AppSearchLogger {
ExtraStats extraStats = createExtraStatsLocked(/*packageName=*/ null,
CallStats.CALL_TYPE_INITIALIZE);
AppSearchStatsLog.write(AppSearchStatsLog.APP_SEARCH_INITIALIZE_STATS_REPORTED,
- extraStats.mSamplingRatio,
+ extraStats.mSamplingInterval,
extraStats.mSkippedSampleCount,
extraStats.mPackageUid,
stats.getStatusCode(),
@@ -428,14 +428,14 @@ public final class PlatformLogger implements AppSearchLogger {
packageUid = getPackageUidAsUserLocked(packageName);
}
- int samplingRatio = mConfig.mSamplingRatios.get(callType,
- mConfig.mDefaultSamplingRatio);
+ int samplingInterval = mConfig.mSamplingIntervals.get(callType,
+ mConfig.mDefaultSamplingInterval);
int skippedSampleCount = mSkippedSampleCountLocked.get(callType,
/*valueOfKeyIfNotFound=*/ 0);
mSkippedSampleCountLocked.put(callType, 0);
- return new ExtraStats(packageUid, samplingRatio, skippedSampleCount);
+ return new ExtraStats(packageUid, samplingInterval, skippedSampleCount);
}
/**
@@ -450,11 +450,11 @@ public final class PlatformLogger implements AppSearchLogger {
// rate limiting.
@VisibleForTesting
boolean shouldLogForTypeLocked(@CallStats.CallType int callType) {
- int samplingRatio = mConfig.mSamplingRatios.get(callType,
- mConfig.mDefaultSamplingRatio);
+ int samplingInterval = mConfig.mSamplingIntervals.get(callType,
+ mConfig.mDefaultSamplingInterval);
// Sampling
- if (!shouldSample(samplingRatio)) {
+ if (!shouldSample(samplingInterval)) {
return false;
}
@@ -475,15 +475,15 @@ public final class PlatformLogger implements AppSearchLogger {
/**
* Checks if the stats should be "sampled"
*
- * @param samplingRatio sampling ratio
+ * @param samplingInterval sampling interval
* @return if the stats should be sampled
*/
- private boolean shouldSample(int samplingRatio) {
- if (samplingRatio <= 0) {
+ private boolean shouldSample(int samplingInterval) {
+ if (samplingInterval <= 0) {
return false;
}
- return mRng.nextInt((int) samplingRatio) == 0;
+ return mRng.nextInt((int) samplingInterval) == 0;
}
/**
diff --git a/core/api/current.txt b/core/api/current.txt
index 4c61afea3b59..1de47b548a5c 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -246,7 +246,6 @@ package android {
public static final class R.attr {
ctor public R.attr();
- field public static final int __removed3;
field public static final int absListViewStyle = 16842858; // 0x101006a
field public static final int accessibilityEventTypes = 16843648; // 0x1010380
field public static final int accessibilityFeedbackType = 16843650; // 0x1010382
@@ -308,7 +307,7 @@ package android {
field public static final int allowAudioPlaybackCapture = 16844289; // 0x1010601
field public static final int allowBackup = 16843392; // 0x1010280
field public static final int allowClearUserData = 16842757; // 0x1010005
- field public static final int allowClickWhenDisabled;
+ field public static final int allowClickWhenDisabled = 16844312; // 0x1010618
field public static final int allowEmbedded = 16843765; // 0x10103f5
field public static final int allowNativeHeapPointerTagging = 16844306; // 0x1010612
field public static final int allowParallelSyncs = 16843570; // 0x1010332
@@ -339,8 +338,8 @@ package android {
field public static final int apiKey = 16843281; // 0x1010211
field public static final int appCategory = 16844101; // 0x1010545
field public static final int appComponentFactory = 16844154; // 0x101057a
- field public static final int attributionTags;
- field public static final int attributionsAreUserVisible;
+ field public static final int attributionTags = 16844354; // 0x1010642
+ field public static final int attributionsAreUserVisible = 16844363; // 0x101064b
field public static final int author = 16843444; // 0x10102b4
field public static final int authorities = 16842776; // 0x1010018
field public static final int autoAdvanceViewId = 16843535; // 0x101030f
@@ -406,7 +405,7 @@ package android {
field public static final int calendarViewShown = 16843596; // 0x101034c
field public static final int calendarViewStyle = 16843613; // 0x101035d
field public static final int canControlMagnification = 16844039; // 0x1010507
- field public static final int canPauseRecording;
+ field public static final int canPauseRecording = 16844314; // 0x101061a
field public static final int canPerformGestures = 16844045; // 0x101050d
field public static final int canRecord = 16844060; // 0x101051c
field @Deprecated public static final int canRequestEnhancedWebAccessibility = 16843736; // 0x10103d8
@@ -448,7 +447,7 @@ package android {
field public static final int clickable = 16842981; // 0x10100e5
field public static final int clipChildren = 16842986; // 0x10100ea
field public static final int clipOrientation = 16843274; // 0x101020a
- field public static final int clipToOutline;
+ field public static final int clipToOutline = 16844328; // 0x1010628
field public static final int clipToPadding = 16842987; // 0x10100eb
field public static final int closeIcon = 16843905; // 0x1010481
field @Deprecated public static final int codes = 16843330; // 0x1010242
@@ -518,7 +517,7 @@ package android {
field public static final int dashGap = 16843175; // 0x10101a7
field public static final int dashWidth = 16843174; // 0x10101a6
field public static final int data = 16842798; // 0x101002e
- field public static final int dataExtractionRules;
+ field public static final int dataExtractionRules = 16844350; // 0x101063e
field public static final int datePickerDialogTheme = 16843948; // 0x10104ac
field public static final int datePickerMode = 16843955; // 0x10104b3
field public static final int datePickerStyle = 16843612; // 0x101035c
@@ -540,8 +539,8 @@ package android {
field public static final int detailSocialSummary = 16843428; // 0x10102a4
field public static final int detailsElementBackground = 16843598; // 0x101034e
field public static final int dial = 16843010; // 0x1010102
- field public static final int dialTint;
- field public static final int dialTintMode;
+ field public static final int dialTint = 16844342; // 0x1010636
+ field public static final int dialTintMode = 16844343; // 0x1010637
field public static final int dialogCornerRadius = 16844145; // 0x1010571
field public static final int dialogIcon = 16843252; // 0x10101f4
field public static final int dialogLayout = 16843255; // 0x10101f7
@@ -595,7 +594,7 @@ package android {
field public static final int editTextStyle = 16842862; // 0x101006e
field @Deprecated public static final int editable = 16843115; // 0x101016b
field public static final int editorExtras = 16843300; // 0x1010224
- field public static final int effectColor;
+ field public static final int effectColor = 16844361; // 0x1010649
field public static final int elegantTextHeight = 16843869; // 0x101045d
field public static final int elevation = 16843840; // 0x1010440
field public static final int ellipsize = 16842923; // 0x10100ab
@@ -675,7 +674,7 @@ package android {
field @Deprecated public static final int fontProviderCerts = 16844125; // 0x101055d
field @Deprecated public static final int fontProviderPackage = 16844119; // 0x1010557
field @Deprecated public static final int fontProviderQuery = 16844113; // 0x1010551
- field public static final int fontProviderSystemFontFamily;
+ field public static final int fontProviderSystemFontFamily = 16844322; // 0x1010622
field public static final int fontStyle = 16844095; // 0x101053f
field public static final int fontVariationSettings = 16844144; // 0x1010570
field public static final int fontWeight = 16844083; // 0x1010533
@@ -739,14 +738,14 @@ package android {
field public static final int groupIndicator = 16843019; // 0x101010b
field public static final int gwpAsanMode = 16844310; // 0x1010616
field public static final int hand_hour = 16843011; // 0x1010103
- field public static final int hand_hourTint;
- field public static final int hand_hourTintMode;
+ field public static final int hand_hourTint = 16844344; // 0x1010638
+ field public static final int hand_hourTintMode = 16844345; // 0x1010639
field public static final int hand_minute = 16843012; // 0x1010104
- field public static final int hand_minuteTint;
- field public static final int hand_minuteTintMode;
- field public static final int hand_second;
- field public static final int hand_secondTint;
- field public static final int hand_secondTintMode;
+ field public static final int hand_minuteTint = 16844346; // 0x101063a
+ field public static final int hand_minuteTintMode = 16844347; // 0x101063b
+ field public static final int hand_second = 16844323; // 0x1010623
+ field public static final int hand_secondTint = 16844348; // 0x101063c
+ field public static final int hand_secondTintMode = 16844349; // 0x101063d
field public static final int handle = 16843354; // 0x101025a
field public static final int handleProfiling = 16842786; // 0x1010022
field public static final int hapticFeedbackEnabled = 16843358; // 0x101025e
@@ -830,7 +829,7 @@ package android {
field public static final int installLocation = 16843447; // 0x10102b7
field public static final int interactiveUiTimeout = 16844181; // 0x1010595
field public static final int interpolator = 16843073; // 0x1010141
- field public static final int isAccessibilityTool;
+ field public static final int isAccessibilityTool = 16844353; // 0x1010641
field public static final int isAlwaysSyncable = 16843571; // 0x1010333
field public static final int isAsciiCapable = 16843753; // 0x10103e9
field public static final int isAuxiliary = 16843647; // 0x101037f
@@ -872,8 +871,8 @@ package android {
field public static final int keyboardNavigationCluster = 16844096; // 0x1010540
field public static final int keycode = 16842949; // 0x10100c5
field public static final int killAfterRestore = 16843420; // 0x101029c
- field public static final int knownCerts;
- field public static final int lStar;
+ field public static final int knownCerts = 16844330; // 0x101062a
+ field public static final int lStar = 16844359; // 0x1010647
field public static final int label = 16842753; // 0x1010001
field public static final int labelFor = 16843718; // 0x10103c6
field @Deprecated public static final int labelTextSize = 16843317; // 0x1010235
@@ -983,8 +982,8 @@ package android {
field public static final int maxLines = 16843091; // 0x1010153
field public static final int maxLongVersionCode = 16844163; // 0x1010583
field public static final int maxRecents = 16843846; // 0x1010446
- field public static final int maxResizeHeight;
- field public static final int maxResizeWidth;
+ field public static final int maxResizeHeight = 16844339; // 0x1010633
+ field public static final int maxResizeWidth = 16844338; // 0x1010632
field public static final int maxRows = 16843059; // 0x1010133
field public static final int maxSdkVersion = 16843377; // 0x1010271
field public static final int maxWidth = 16843039; // 0x101011f
@@ -993,7 +992,7 @@ package android {
field public static final int measureWithLargestChild = 16843476; // 0x10102d4
field public static final int mediaRouteButtonStyle = 16843693; // 0x10103ad
field public static final int mediaRouteTypes = 16843694; // 0x10103ae
- field public static final int memtagMode;
+ field public static final int memtagMode = 16844324; // 0x1010624
field public static final int menuCategory = 16843230; // 0x10101de
field public static final int mimeGroup = 16844309; // 0x1010615
field public static final int mimeType = 16842790; // 0x1010026
@@ -1017,7 +1016,7 @@ package android {
field public static final int multiArch = 16843918; // 0x101048e
field public static final int multiprocess = 16842771; // 0x1010013
field public static final int name = 16842755; // 0x1010003
- field public static final int nativeHeapZeroInitialized;
+ field public static final int nativeHeapZeroInitialized = 16844325; // 0x1010625
field public static final int navigationBarColor = 16843858; // 0x1010452
field public static final int navigationBarDividerColor = 16844141; // 0x101056d
field public static final int navigationContentDescription = 16843969; // 0x10104c1
@@ -1087,13 +1086,13 @@ package android {
field public static final int panelTextAppearance = 16842850; // 0x1010062
field public static final int parentActivityName = 16843687; // 0x10103a7
field @Deprecated public static final int password = 16843100; // 0x101015c
- field public static final int passwordsActivity;
+ field public static final int passwordsActivity = 16844351; // 0x101063f
field public static final int path = 16842794; // 0x101002a
- field public static final int pathAdvancedPattern;
+ field public static final int pathAdvancedPattern = 16844320; // 0x1010620
field public static final int pathData = 16843781; // 0x1010405
field public static final int pathPattern = 16842796; // 0x101002c
field public static final int pathPrefix = 16842795; // 0x101002b
- field public static final int pathSuffix;
+ field public static final int pathSuffix = 16844318; // 0x101061e
field public static final int patternPathData = 16843978; // 0x10104ca
field public static final int permission = 16842758; // 0x1010006
field public static final int permissionFlags = 16843719; // 0x10103c7
@@ -1130,7 +1129,7 @@ package android {
field public static final int presentationTheme = 16843712; // 0x10103c0
field public static final int preserveLegacyExternalStorage = 16844308; // 0x1010614
field public static final int previewImage = 16843482; // 0x10102da
- field public static final int previewLayout;
+ field public static final int previewLayout = 16844327; // 0x1010627
field public static final int primaryContentAlpha = 16844114; // 0x1010552
field public static final int priority = 16842780; // 0x101001c
field public static final int privateImeOptions = 16843299; // 0x1010223
@@ -1187,8 +1186,8 @@ package android {
field public static final int reqNavigation = 16843306; // 0x101022a
field public static final int reqTouchScreen = 16843303; // 0x1010227
field public static final int requestLegacyExternalStorage = 16844291; // 0x1010603
- field public static final int requestRawExternalStorageAccess;
- field public static final int requireDeviceScreenOn;
+ field public static final int requestRawExternalStorageAccess = 16844357; // 0x1010645
+ field public static final int requireDeviceScreenOn = 16844317; // 0x101061d
field public static final int requireDeviceUnlock = 16843756; // 0x10103ec
field public static final int required = 16843406; // 0x101028e
field public static final int requiredAccountType = 16843734; // 0x10103d6
@@ -1213,7 +1212,7 @@ package android {
field public static final int right = 16843183; // 0x10101af
field public static final int ringtonePreferenceStyle = 16842899; // 0x1010093
field public static final int ringtoneType = 16843257; // 0x10101f9
- field public static final int rollbackDataPolicy;
+ field public static final int rollbackDataPolicy = 16844311; // 0x1010617
field public static final int rotation = 16843558; // 0x1010326
field public static final int rotationAnimation = 16844090; // 0x101053a
field public static final int rotationX = 16843559; // 0x1010327
@@ -1274,7 +1273,7 @@ package android {
field public static final int segmentedButtonStyle = 16843568; // 0x1010330
field public static final int selectAllOnFocus = 16843102; // 0x101015e
field public static final int selectable = 16843238; // 0x10101e6
- field public static final int selectableAsDefault;
+ field public static final int selectableAsDefault = 16844352; // 0x1010640
field public static final int selectableItemBackground = 16843534; // 0x101030e
field public static final int selectableItemBackgroundBorderless = 16843868; // 0x101045c
field @Deprecated public static final int selectedDateVerticalBar = 16843591; // 0x1010347
@@ -1302,7 +1301,7 @@ package android {
field public static final int showDefault = 16843258; // 0x10101fa
field public static final int showDividers = 16843561; // 0x1010329
field public static final int showForAllUsers = 16844015; // 0x10104ef
- field public static final int showInInputMethodPicker;
+ field public static final int showInInputMethodPicker = 16844360; // 0x1010648
field public static final int showMetadataInPreview = 16844079; // 0x101052f
field @Deprecated public static final int showOnLockScreen = 16843721; // 0x10103c9
field public static final int showSilent = 16843259; // 0x10101fb
@@ -1325,17 +1324,17 @@ package android {
field public static final int spinnerMode = 16843505; // 0x10102f1
field public static final int spinnerStyle = 16842881; // 0x1010081
field public static final int spinnersShown = 16843595; // 0x101034b
- field public static final int splashScreenTheme;
+ field public static final int splashScreenTheme = 16844337; // 0x1010631
field public static final int splitMotionEvents = 16843503; // 0x10102ef
field public static final int splitName = 16844105; // 0x1010549
field public static final int splitTrack = 16843852; // 0x101044c
field public static final int spotShadowAlpha = 16843967; // 0x10104bf
field public static final int src = 16843033; // 0x1010119
field public static final int ssp = 16843747; // 0x10103e3
- field public static final int sspAdvancedPattern;
+ field public static final int sspAdvancedPattern = 16844321; // 0x1010621
field public static final int sspPattern = 16843749; // 0x10103e5
field public static final int sspPrefix = 16843748; // 0x10103e4
- field public static final int sspSuffix;
+ field public static final int sspSuffix = 16844319; // 0x101061f
field public static final int stackFromBottom = 16843005; // 0x10100fd
field public static final int stackViewStyle = 16843838; // 0x101043e
field public static final int starStyle = 16842882; // 0x1010082
@@ -1408,7 +1407,7 @@ package android {
field public static final int supportsRtl = 16843695; // 0x10103af
field public static final int supportsSwitchingToNextInputMethod = 16843755; // 0x10103eb
field public static final int supportsUploading = 16843419; // 0x101029b
- field public static final int suppressesSpellChecker;
+ field public static final int suppressesSpellChecker = 16844355; // 0x1010643
field public static final int switchMinWidth = 16843632; // 0x1010370
field public static final int switchPadding = 16843633; // 0x1010371
field public static final int switchPreferenceStyle = 16843629; // 0x101036d
@@ -1423,8 +1422,8 @@ package android {
field public static final int tabWidgetStyle = 16842883; // 0x1010083
field public static final int tag = 16842961; // 0x10100d1
field public static final int targetActivity = 16843266; // 0x1010202
- field public static final int targetCellHeight;
- field public static final int targetCellWidth;
+ field public static final int targetCellHeight = 16844341; // 0x1010635
+ field public static final int targetCellWidth = 16844340; // 0x1010634
field public static final int targetClass = 16842799; // 0x101002f
field @Deprecated public static final int targetDescriptions = 16843680; // 0x10103a0
field public static final int targetId = 16843740; // 0x10103dc
@@ -1594,7 +1593,7 @@ package android {
field public static final int useLevel = 16843167; // 0x101019f
field public static final int userVisible = 16843409; // 0x1010291
field public static final int usesCleartextTraffic = 16844012; // 0x10104ec
- field public static final int usesPermissionFlags;
+ field public static final int usesPermissionFlags = 16844356; // 0x1010644
field public static final int value = 16842788; // 0x1010024
field public static final int valueFrom = 16843486; // 0x10102de
field public static final int valueTo = 16843487; // 0x10102df
@@ -1649,10 +1648,10 @@ package android {
field public static final int windowAllowReturnTransitionOverlap = 16843835; // 0x101043b
field public static final int windowAnimationStyle = 16842926; // 0x10100ae
field public static final int windowBackground = 16842836; // 0x1010054
- field public static final int windowBackgroundBlurRadius;
+ field public static final int windowBackgroundBlurRadius = 16844331; // 0x101062b
field public static final int windowBackgroundFallback = 16844035; // 0x1010503
- field public static final int windowBlurBehindEnabled;
- field public static final int windowBlurBehindRadius;
+ field public static final int windowBlurBehindEnabled = 16844316; // 0x101061c
+ field public static final int windowBlurBehindRadius = 16844315; // 0x101061b
field public static final int windowClipToOutline = 16843947; // 0x10104ab
field public static final int windowCloseOnTouchOutside = 16843611; // 0x101035b
field public static final int windowContentOverlay = 16842841; // 0x1010059
@@ -1671,7 +1670,7 @@ package android {
field public static final int windowHideAnimation = 16842935; // 0x10100b7
field public static final int windowIsFloating = 16842839; // 0x1010057
field public static final int windowIsTranslucent = 16842840; // 0x1010058
- field public static final int windowLayoutAffinity;
+ field public static final int windowLayoutAffinity = 16844313; // 0x1010619
field public static final int windowLayoutInDisplayCutoutMode = 16844166; // 0x1010586
field public static final int windowLightNavigationBar = 16844140; // 0x101056c
field public static final int windowLightStatusBar = 16844000; // 0x10104e0
@@ -1690,11 +1689,11 @@ package android {
field public static final int windowShowAnimation = 16842934; // 0x10100b6
field public static final int windowShowWallpaper = 16843410; // 0x1010292
field public static final int windowSoftInputMode = 16843307; // 0x101022b
- field public static final int windowSplashScreenAnimatedIcon;
- field public static final int windowSplashScreenAnimationDuration;
- field public static final int windowSplashScreenBackground;
- field public static final int windowSplashScreenBrandingImage;
- field public static final int windowSplashScreenIconBackgroundColor;
+ field public static final int windowSplashScreenAnimatedIcon = 16844333; // 0x101062d
+ field public static final int windowSplashScreenAnimationDuration = 16844334; // 0x101062e
+ field public static final int windowSplashScreenBackground = 16844332; // 0x101062c
+ field public static final int windowSplashScreenBrandingImage = 16844335; // 0x101062f
+ field public static final int windowSplashScreenIconBackgroundColor = 16844336; // 0x1010630
field @Deprecated public static final int windowSplashscreenContent = 16844132; // 0x1010564
field @Deprecated public static final int windowSwipeToDismiss = 16843763; // 0x10103f3
field public static final int windowTitleBackgroundStyle = 16842844; // 0x101005c
@@ -1742,71 +1741,71 @@ package android {
field @Deprecated public static final int secondary_text_dark_nodisable = 17170438; // 0x1060006
field @Deprecated public static final int secondary_text_light = 17170439; // 0x1060007
field @Deprecated public static final int secondary_text_light_nodisable = 17170440; // 0x1060008
- field public static final int system_accent1_0;
- field public static final int system_accent1_10;
- field public static final int system_accent1_100;
- field public static final int system_accent1_1000;
- field public static final int system_accent1_200;
- field public static final int system_accent1_300;
- field public static final int system_accent1_400;
- field public static final int system_accent1_50;
- field public static final int system_accent1_500;
- field public static final int system_accent1_600;
- field public static final int system_accent1_700;
- field public static final int system_accent1_800;
- field public static final int system_accent1_900;
- field public static final int system_accent2_0;
- field public static final int system_accent2_10;
- field public static final int system_accent2_100;
- field public static final int system_accent2_1000;
- field public static final int system_accent2_200;
- field public static final int system_accent2_300;
- field public static final int system_accent2_400;
- field public static final int system_accent2_50;
- field public static final int system_accent2_500;
- field public static final int system_accent2_600;
- field public static final int system_accent2_700;
- field public static final int system_accent2_800;
- field public static final int system_accent2_900;
- field public static final int system_accent3_0;
- field public static final int system_accent3_10;
- field public static final int system_accent3_100;
- field public static final int system_accent3_1000;
- field public static final int system_accent3_200;
- field public static final int system_accent3_300;
- field public static final int system_accent3_400;
- field public static final int system_accent3_50;
- field public static final int system_accent3_500;
- field public static final int system_accent3_600;
- field public static final int system_accent3_700;
- field public static final int system_accent3_800;
- field public static final int system_accent3_900;
- field public static final int system_neutral1_0;
- field public static final int system_neutral1_10;
- field public static final int system_neutral1_100;
- field public static final int system_neutral1_1000;
- field public static final int system_neutral1_200;
- field public static final int system_neutral1_300;
- field public static final int system_neutral1_400;
- field public static final int system_neutral1_50;
- field public static final int system_neutral1_500;
- field public static final int system_neutral1_600;
- field public static final int system_neutral1_700;
- field public static final int system_neutral1_800;
- field public static final int system_neutral1_900;
- field public static final int system_neutral2_0;
- field public static final int system_neutral2_10;
- field public static final int system_neutral2_100;
- field public static final int system_neutral2_1000;
- field public static final int system_neutral2_200;
- field public static final int system_neutral2_300;
- field public static final int system_neutral2_400;
- field public static final int system_neutral2_50;
- field public static final int system_neutral2_500;
- field public static final int system_neutral2_600;
- field public static final int system_neutral2_700;
- field public static final int system_neutral2_800;
- field public static final int system_neutral2_900;
+ field public static final int system_accent1_0 = 17170487; // 0x1060037
+ field public static final int system_accent1_10 = 17170488; // 0x1060038
+ field public static final int system_accent1_100 = 17170490; // 0x106003a
+ field public static final int system_accent1_1000 = 17170499; // 0x1060043
+ field public static final int system_accent1_200 = 17170491; // 0x106003b
+ field public static final int system_accent1_300 = 17170492; // 0x106003c
+ field public static final int system_accent1_400 = 17170493; // 0x106003d
+ field public static final int system_accent1_50 = 17170489; // 0x1060039
+ field public static final int system_accent1_500 = 17170494; // 0x106003e
+ field public static final int system_accent1_600 = 17170495; // 0x106003f
+ field public static final int system_accent1_700 = 17170496; // 0x1060040
+ field public static final int system_accent1_800 = 17170497; // 0x1060041
+ field public static final int system_accent1_900 = 17170498; // 0x1060042
+ field public static final int system_accent2_0 = 17170500; // 0x1060044
+ field public static final int system_accent2_10 = 17170501; // 0x1060045
+ field public static final int system_accent2_100 = 17170503; // 0x1060047
+ field public static final int system_accent2_1000 = 17170512; // 0x1060050
+ field public static final int system_accent2_200 = 17170504; // 0x1060048
+ field public static final int system_accent2_300 = 17170505; // 0x1060049
+ field public static final int system_accent2_400 = 17170506; // 0x106004a
+ field public static final int system_accent2_50 = 17170502; // 0x1060046
+ field public static final int system_accent2_500 = 17170507; // 0x106004b
+ field public static final int system_accent2_600 = 17170508; // 0x106004c
+ field public static final int system_accent2_700 = 17170509; // 0x106004d
+ field public static final int system_accent2_800 = 17170510; // 0x106004e
+ field public static final int system_accent2_900 = 17170511; // 0x106004f
+ field public static final int system_accent3_0 = 17170513; // 0x1060051
+ field public static final int system_accent3_10 = 17170514; // 0x1060052
+ field public static final int system_accent3_100 = 17170516; // 0x1060054
+ field public static final int system_accent3_1000 = 17170525; // 0x106005d
+ field public static final int system_accent3_200 = 17170517; // 0x1060055
+ field public static final int system_accent3_300 = 17170518; // 0x1060056
+ field public static final int system_accent3_400 = 17170519; // 0x1060057
+ field public static final int system_accent3_50 = 17170515; // 0x1060053
+ field public static final int system_accent3_500 = 17170520; // 0x1060058
+ field public static final int system_accent3_600 = 17170521; // 0x1060059
+ field public static final int system_accent3_700 = 17170522; // 0x106005a
+ field public static final int system_accent3_800 = 17170523; // 0x106005b
+ field public static final int system_accent3_900 = 17170524; // 0x106005c
+ field public static final int system_neutral1_0 = 17170461; // 0x106001d
+ field public static final int system_neutral1_10 = 17170462; // 0x106001e
+ field public static final int system_neutral1_100 = 17170464; // 0x1060020
+ field public static final int system_neutral1_1000 = 17170473; // 0x1060029
+ field public static final int system_neutral1_200 = 17170465; // 0x1060021
+ field public static final int system_neutral1_300 = 17170466; // 0x1060022
+ field public static final int system_neutral1_400 = 17170467; // 0x1060023
+ field public static final int system_neutral1_50 = 17170463; // 0x106001f
+ field public static final int system_neutral1_500 = 17170468; // 0x1060024
+ field public static final int system_neutral1_600 = 17170469; // 0x1060025
+ field public static final int system_neutral1_700 = 17170470; // 0x1060026
+ field public static final int system_neutral1_800 = 17170471; // 0x1060027
+ field public static final int system_neutral1_900 = 17170472; // 0x1060028
+ field public static final int system_neutral2_0 = 17170474; // 0x106002a
+ field public static final int system_neutral2_10 = 17170475; // 0x106002b
+ field public static final int system_neutral2_100 = 17170477; // 0x106002d
+ field public static final int system_neutral2_1000 = 17170486; // 0x1060036
+ field public static final int system_neutral2_200 = 17170478; // 0x106002e
+ field public static final int system_neutral2_300 = 17170479; // 0x106002f
+ field public static final int system_neutral2_400 = 17170480; // 0x1060030
+ field public static final int system_neutral2_50 = 17170476; // 0x106002c
+ field public static final int system_neutral2_500 = 17170481; // 0x1060031
+ field public static final int system_neutral2_600 = 17170482; // 0x1060032
+ field public static final int system_neutral2_700 = 17170483; // 0x1060033
+ field public static final int system_neutral2_800 = 17170484; // 0x1060034
+ field public static final int system_neutral2_900 = 17170485; // 0x1060035
field public static final int tab_indicator_text = 17170441; // 0x1060009
field @Deprecated public static final int tertiary_text_dark = 17170448; // 0x1060010
field @Deprecated public static final int tertiary_text_light = 17170449; // 0x1060011
@@ -1822,8 +1821,8 @@ package android {
field public static final int dialog_min_width_minor = 17104900; // 0x1050004
field public static final int notification_large_icon_height = 17104902; // 0x1050006
field public static final int notification_large_icon_width = 17104901; // 0x1050005
- field public static final int system_app_widget_background_radius;
- field public static final int system_app_widget_inner_radius;
+ field public static final int system_app_widget_background_radius = 17104904; // 0x1050008
+ field public static final int system_app_widget_inner_radius = 17104905; // 0x1050009
field public static final int thumbnail_height = 17104897; // 0x1050001
field public static final int thumbnail_width = 17104898; // 0x1050002
}
@@ -30797,7 +30796,7 @@ package android.os {
field public static final int P = 28; // 0x1c
field public static final int Q = 29; // 0x1d
field public static final int R = 30; // 0x1e
- field public static final int S = 10000; // 0x2710
+ field public static final int S = 31; // 0x1f
}
public final class Bundle extends android.os.BaseBundle implements java.lang.Cloneable android.os.Parcelable {
diff --git a/core/api/removed.txt b/core/api/removed.txt
index 57e1598b4c33..bf8642223ef5 100644
--- a/core/api/removed.txt
+++ b/core/api/removed.txt
@@ -1,12 +1,4 @@
// Signature format: 2.0
-package android {
-
- public static final class R.dimen {
- field public static final int __removed_system_app_widget_internal_padding;
- }
-
-}
-
package android.app {
public class Notification implements android.os.Parcelable {
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 7072bbeade29..2d73aa67ed1a 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -317,10 +317,10 @@ package android {
public static final class R.attr {
field public static final int allowClearUserDataOnFailedRestore = 16844288; // 0x1010600
- field public static final int hotwordDetectionService;
+ field public static final int hotwordDetectionService = 16844326; // 0x1010626
field public static final int isVrOnly = 16844152; // 0x1010578
field public static final int minExtensionVersion = 16844305; // 0x1010611
- field public static final int playHomeTransitionSound;
+ field public static final int playHomeTransitionSound = 16844358; // 0x1010646
field public static final int requiredSystemPropertyName = 16844133; // 0x1010565
field public static final int requiredSystemPropertyValue = 16844134; // 0x1010566
field public static final int sdkVersion = 16844304; // 0x1010610
@@ -353,8 +353,8 @@ package android {
}
public static final class R.string {
- field public static final int config_customMediaKeyDispatcher;
- field public static final int config_customMediaSessionPolicyProvider;
+ field public static final int config_customMediaKeyDispatcher = 17039404; // 0x104002c
+ field public static final int config_customMediaSessionPolicyProvider = 17039405; // 0x104002d
field public static final int config_defaultAssistant = 17039393; // 0x1040021
field public static final int config_defaultBrowser = 17039394; // 0x1040022
field public static final int config_defaultCallRedirection = 17039397; // 0x1040025
@@ -367,24 +367,24 @@ package android {
field public static final int config_helpIntentNameKey = 17039390; // 0x104001e
field public static final int config_helpPackageNameKey = 17039387; // 0x104001b
field public static final int config_helpPackageNameValue = 17039388; // 0x104001c
- field public static final int config_systemActivityRecognizer;
- field public static final int config_systemAmbientAudioIntelligence;
- field public static final int config_systemAudioIntelligence;
- field public static final int config_systemAutomotiveCluster;
- field public static final int config_systemAutomotiveProjection;
- field public static final int config_systemCompanionDeviceProvider;
- field public static final int config_systemContacts;
+ field public static final int config_systemActivityRecognizer = 17039416; // 0x1040038
+ field public static final int config_systemAmbientAudioIntelligence = 17039411; // 0x1040033
+ field public static final int config_systemAudioIntelligence = 17039412; // 0x1040034
+ field public static final int config_systemAutomotiveCluster = 17039400; // 0x1040028
+ field public static final int config_systemAutomotiveProjection = 17039401; // 0x1040029
+ field public static final int config_systemCompanionDeviceProvider = 17039417; // 0x1040039
+ field public static final int config_systemContacts = 17039403; // 0x104002b
field public static final int config_systemGallery = 17039399; // 0x1040027
- field public static final int config_systemNotificationIntelligence;
- field public static final int config_systemShell;
- field public static final int config_systemSpeechRecognizer;
- field public static final int config_systemTelevisionNotificationHandler;
- field public static final int config_systemTextIntelligence;
- field public static final int config_systemUi;
- field public static final int config_systemUiIntelligence;
- field public static final int config_systemVisualIntelligence;
- field public static final int config_systemWellbeing;
- field public static final int config_systemWifiCoexManager;
+ field public static final int config_systemNotificationIntelligence = 17039413; // 0x1040035
+ field public static final int config_systemShell = 17039402; // 0x104002a
+ field public static final int config_systemSpeechRecognizer = 17039406; // 0x104002e
+ field public static final int config_systemTelevisionNotificationHandler = 17039409; // 0x1040031
+ field public static final int config_systemTextIntelligence = 17039414; // 0x1040036
+ field public static final int config_systemUi = 17039418; // 0x104003a
+ field public static final int config_systemUiIntelligence = 17039410; // 0x1040032
+ field public static final int config_systemVisualIntelligence = 17039415; // 0x1040037
+ field public static final int config_systemWellbeing = 17039408; // 0x1040030
+ field public static final int config_systemWifiCoexManager = 17039407; // 0x104002f
}
public static final class R.style {
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 2f795f0e103f..2bae1907daec 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -51,7 +51,7 @@ package android {
}
public static final class R.attr {
- field public static final int requestForegroundServiceExemption;
+ field public static final int requestForegroundServiceExemption = 16844362; // 0x101064a
}
public static final class R.bool {
@@ -63,8 +63,8 @@ package android {
public static final class R.string {
field public static final int config_defaultAssistant = 17039393; // 0x1040021
field public static final int config_defaultDialer = 17039395; // 0x1040023
- field public static final int config_systemAutomotiveCluster;
- field public static final int config_systemAutomotiveProjection;
+ field public static final int config_systemAutomotiveCluster = 17039400; // 0x1040028
+ field public static final int config_systemAutomotiveProjection = 17039401; // 0x1040029
field public static final int config_systemGallery = 17039399; // 0x1040027
}
@@ -201,6 +201,11 @@ package android.app {
method @RequiresPermission("android.permission.MANAGE_APPOPS") public void setHistoryParameters(int, long, int);
method @RequiresPermission("android.permission.MANAGE_APP_OPS_MODES") public void setMode(int, int, String, int);
method public static int strOpToOp(@NonNull String);
+ field public static final int ATTRIBUTION_CHAIN_ID_NONE = -1; // 0xffffffff
+ field public static final int ATTRIBUTION_FLAGS_NONE = 0; // 0x0
+ field public static final int ATTRIBUTION_FLAG_ACCESSOR = 1; // 0x1
+ field public static final int ATTRIBUTION_FLAG_INTERMEDIARY = 2; // 0x2
+ field public static final int ATTRIBUTION_FLAG_RECEIVER = 4; // 0x4
field public static final int HISTORICAL_MODE_DISABLED = 0; // 0x0
field public static final int HISTORICAL_MODE_ENABLED_ACTIVE = 1; // 0x1
field public static final int HISTORICAL_MODE_ENABLED_PASSIVE = 2; // 0x2
@@ -230,6 +235,10 @@ package android.app {
method public void offsetBeginAndEndTime(long);
}
+ public static interface AppOpsManager.OnOpActiveChangedListener {
+ method public default void onOpActiveChanged(@NonNull String, int, @NonNull String, @Nullable String, boolean, int, int);
+ }
+
public class BroadcastOptions {
ctor public BroadcastOptions(@NonNull android.os.Bundle);
method public int getMaxManifestReceiverApiLevel();
@@ -669,7 +678,7 @@ package android.content {
public final class AttributionSource implements android.os.Parcelable {
ctor public AttributionSource(int, @Nullable String, @Nullable String);
- ctor public AttributionSource(int, @Nullable String, @Nullable String, @Nullable android.content.AttributionSource);
+ ctor public AttributionSource(int, @Nullable String, @Nullable String, @NonNull android.os.IBinder);
ctor public AttributionSource(int, @Nullable String, @Nullable String, @Nullable java.util.Set<java.lang.String>, @Nullable android.content.AttributionSource);
}
@@ -2041,7 +2050,7 @@ package android.permission {
public final class PermissionManager {
method @NonNull @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public java.util.List<android.permission.PermGroupUsage> getIndicatorAppOpUsageData();
method @NonNull @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public java.util.List<android.permission.PermGroupUsage> getIndicatorAppOpUsageData(boolean);
- method @NonNull public android.content.AttributionSource registerAttributionSource(@NonNull android.content.AttributionSource);
+ method public void registerAttributionSource(@NonNull android.content.AttributionSource);
}
}
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 6d2d0238ed37..91e2d88ad7cb 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -779,6 +779,9 @@ public class ActivityManager {
/** @hide requestType for assist context: generate full AssistStructure for autofill. */
public static final int ASSIST_CONTEXT_AUTOFILL = 2;
+ /** @hide requestType for assist context: generate AssistContent but not AssistStructure. */
+ public static final int ASSIST_CONTEXT_CONTENT = 3;
+
/** @hide Flag for registerUidObserver: report changes in process state. */
public static final int UID_OBSERVER_PROCSTATE = 1<<0;
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 7149096ee806..02ab3143eed9 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -3843,6 +3843,8 @@ public final class ActivityThread extends ClientTransactionHandler
// - it does not call onProvideAssistData()
// - it needs an IAutoFillCallback
boolean forAutofill = cmd.requestType == ActivityManager.ASSIST_CONTEXT_AUTOFILL;
+ // When only the AssistContent is requested, omit the AsssistStructure
+ boolean requestedOnlyContent = cmd.requestType == ActivityManager.ASSIST_CONTEXT_CONTENT;
// TODO: decide if lastSessionId logic applies to autofill sessions
if (mLastSessionId != cmd.sessionId) {
@@ -3869,8 +3871,11 @@ public final class ActivityThread extends ClientTransactionHandler
r.activity.onProvideAssistData(data);
referrer = r.activity.onProvideReferrer();
}
- if (cmd.requestType == ActivityManager.ASSIST_CONTEXT_FULL || forAutofill) {
- structure = new AssistStructure(r.activity, forAutofill, cmd.flags);
+ if (cmd.requestType == ActivityManager.ASSIST_CONTEXT_FULL || forAutofill
+ || requestedOnlyContent) {
+ if (!requestedOnlyContent) {
+ structure = new AssistStructure(r.activity, forAutofill, cmd.flags);
+ }
Intent activityIntent = r.activity.getIntent();
boolean notSecure = r.window == null ||
(r.window.getAttributes().flags
@@ -3892,18 +3897,21 @@ public final class ActivityThread extends ClientTransactionHandler
r.activity.onProvideAssistContent(content);
}
}
-
- }
- if (structure == null) {
- structure = new AssistStructure();
}
- // TODO: decide if lastSessionId logic applies to autofill sessions
+ if (!requestedOnlyContent) {
+ if (structure == null) {
+ structure = new AssistStructure();
+ }
+
+ // TODO: decide if lastSessionId logic applies to autofill sessions
- structure.setAcquisitionStartTime(startTime);
- structure.setAcquisitionEndTime(SystemClock.uptimeMillis());
+ structure.setAcquisitionStartTime(startTime);
+ structure.setAcquisitionEndTime(SystemClock.uptimeMillis());
+
+ mLastAssistStructures.add(new WeakReference<>(structure));
+ }
- mLastAssistStructures.add(new WeakReference<>(structure));
IActivityTaskManager mgr = ActivityTaskManager.getService();
try {
mgr.reportAssistContextExtras(cmd.requestToken, data, structure, content, referrer);
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 1415212ef07d..eb14c11e7e3c 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -708,6 +708,62 @@ public class AppOpsManager {
}
}
+ /**
+ * Attribution chain flag: specifies that this is the accessor. When
+ * an app A accesses the data that is then passed to app B that is then
+ * passed to C, we call app A accessor, app B intermediary, and app C
+ * receiver. If A accesses the data for itself, then it is the accessor
+ * and the receiver.
+ * @hide
+ */
+ @TestApi
+ public static final int ATTRIBUTION_FLAG_ACCESSOR = 0x1;
+
+ /**
+ * Attribution chain flag: specifies that this is the intermediary. When
+ * an app A accesses the data that is then passed to app B that is then
+ * passed to C, we call app A accessor, app B intermediary, and app C
+ * receiver. If A accesses the data for itself, then it is the accessor
+ * and the receiver.
+ * @hide
+ */
+ @TestApi
+ public static final int ATTRIBUTION_FLAG_INTERMEDIARY = 0x2;
+
+ /**
+ * Attribution chain flag: specifies that this is the receiver. When
+ * an app A accesses the data that is then passed to app B that is then
+ * passed to C, we call app A accessor, app B intermediary, and app C
+ * receiver. If A accesses the data for itself, then it is the accessor
+ * and the receiver.
+ * @hide
+ */
+ @TestApi
+ public static final int ATTRIBUTION_FLAG_RECEIVER = 0x4;
+
+ /**
+ * No attribution flags.
+ * @hide
+ */
+ @TestApi
+ public static final int ATTRIBUTION_FLAGS_NONE = 0x0;
+
+ /**
+ * No attribution chain id.
+ * @hide
+ */
+ @TestApi
+ public static final int ATTRIBUTION_CHAIN_ID_NONE = -1;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(flag = true, prefix = { "FLAG_" }, value = {
+ ATTRIBUTION_FLAG_ACCESSOR,
+ ATTRIBUTION_FLAG_INTERMEDIARY,
+ ATTRIBUTION_FLAG_RECEIVER
+ })
+ public @interface AttributionFlags {}
+
// These constants are redefined here to work around a metalava limitation/bug where
// @IntDef is not able to see @hide symbols when they are hidden via package hiding:
// frameworks/base/core/java/com/android/internal/package.html
@@ -7063,6 +7119,25 @@ public class AppOpsManager {
*/
void onOpActiveChanged(@NonNull String op, int uid, @NonNull String packageName,
boolean active);
+
+ /**
+ * Called when the active state of an app-op changes.
+ *
+ * @param op The operation that changed.
+ * @param uid The UID performing the operation.
+ * @param packageName The package performing the operation.
+ * @param attributionTag The operation's attribution tag.
+ * @param active Whether the operation became active or inactive.
+ * @param attributionFlags the attribution flags for this operation.
+ * @param attributionChainId the unique id of the attribution chain this op is a part of.
+ * @hide
+ */
+ @TestApi
+ default void onOpActiveChanged(@NonNull String op, int uid, @NonNull String packageName,
+ @Nullable String attributionTag, boolean active, @AttributionFlags
+ int attributionFlags, int attributionChainId) {
+ onOpActiveChanged(op, uid, packageName, active);
+ }
}
/**
@@ -7684,14 +7759,17 @@ public class AppOpsManager {
}
cb = new IAppOpsActiveCallback.Stub() {
@Override
- public void opActiveChanged(int op, int uid, String packageName, boolean active) {
+ public void opActiveChanged(int op, int uid, String packageName,
+ String attributionTag, boolean active, @AttributionFlags
+ int attributionFlags, int attributionChainId) {
executor.execute(() -> {
if (callback instanceof OnOpActiveChangedInternalListener) {
((OnOpActiveChangedInternalListener) callback).onOpActiveChanged(op,
uid, packageName, active);
}
if (sOpToString[op] != null) {
- callback.onOpActiveChanged(sOpToString[op], uid, packageName, active);
+ callback.onOpActiveChanged(sOpToString[op], uid, packageName,
+ attributionTag, active, attributionFlags, attributionChainId);
}
});
}
@@ -8169,8 +8247,9 @@ public class AppOpsManager {
public int noteProxyOp(int op, @Nullable String proxiedPackageName, int proxiedUid,
@Nullable String proxiedAttributionTag, @Nullable String message) {
return noteProxyOp(op, new AttributionSource(mContext.getAttributionSource(),
- new AttributionSource(proxiedUid, proxiedPackageName, proxiedAttributionTag)),
- message, /*skipProxyOperation*/ false);
+ new AttributionSource(proxiedUid, proxiedPackageName, proxiedAttributionTag,
+ mContext.getAttributionSource().getToken())), message,
+ /*skipProxyOperation*/ false);
}
/**
@@ -8255,8 +8334,8 @@ public class AppOpsManager {
int proxiedUid, @Nullable String proxiedAttributionTag, @Nullable String message) {
return noteProxyOpNoThrow(strOpToOp(op), new AttributionSource(
mContext.getAttributionSource(), new AttributionSource(proxiedUid,
- proxiedPackageName, proxiedAttributionTag)), message,
- /*skipProxyOperation*/ false);
+ proxiedPackageName, proxiedAttributionTag, mContext.getAttributionSource()
+ .getToken())), message,/*skipProxyOperation*/ false);
}
/**
@@ -8592,6 +8671,29 @@ public class AppOpsManager {
*/
public int startOpNoThrow(int op, int uid, @NonNull String packageName,
boolean startIfModeDefault, @Nullable String attributionTag, @Nullable String message) {
+ return startOpNoThrow(mContext.getAttributionSource().getToken(), op, uid, packageName,
+ startIfModeDefault, attributionTag, message);
+ }
+
+ /**
+ * @see #startOpNoThrow(String, int, String, String, String)
+ *
+ * @hide
+ */
+ public int startOpNoThrow(@NonNull IBinder token, int op, int uid, @NonNull String packageName,
+ boolean startIfModeDefault, @Nullable String attributionTag, @Nullable String message) {
+ return startOpNoThrow(token, op, uid, packageName, startIfModeDefault, attributionTag,
+ message, ATTRIBUTION_FLAGS_NONE, ATTRIBUTION_CHAIN_ID_NONE);
+ }
+
+ /**
+ * @see #startOpNoThrow(String, int, String, String, String)
+ *
+ * @hide
+ */
+ public int startOpNoThrow(@NonNull IBinder token, int op, int uid, @NonNull String packageName,
+ boolean startIfModeDefault, @Nullable String attributionTag, @Nullable String message,
+ @AttributionFlags int attributionFlags, int attributionChainId) {
try {
collectNoteOpCallsForValidation(op);
int collectionMode = getNotedOpCollectionMode(uid, packageName, op);
@@ -8604,9 +8706,9 @@ public class AppOpsManager {
}
}
- SyncNotedAppOp syncOp = mService.startOperation(getClientId(), op, uid, packageName,
+ SyncNotedAppOp syncOp = mService.startOperation(token, op, uid, packageName,
attributionTag, startIfModeDefault, collectionMode == COLLECT_ASYNC, message,
- shouldCollectMessage);
+ shouldCollectMessage, attributionFlags, attributionChainId);
if (syncOp.getOpMode() == MODE_ALLOWED) {
if (collectionMode == COLLECT_SELF) {
@@ -8643,8 +8745,9 @@ public class AppOpsManager {
public int startProxyOp(@NonNull String op, int proxiedUid, @NonNull String proxiedPackageName,
@Nullable String proxiedAttributionTag, @Nullable String message) {
return startProxyOp(op, new AttributionSource(mContext.getAttributionSource(),
- new AttributionSource(proxiedUid, proxiedPackageName, proxiedAttributionTag)),
- message, /*skipProxyOperation*/ false);
+ new AttributionSource(proxiedUid, proxiedPackageName, proxiedAttributionTag,
+ mContext.getAttributionSource().getToken())), message,
+ /*skipProxyOperation*/ false);
}
/**
@@ -8690,8 +8793,9 @@ public class AppOpsManager {
@Nullable String message) {
return startProxyOpNoThrow(AppOpsManager.strOpToOp(op), new AttributionSource(
mContext.getAttributionSource(), new AttributionSource(proxiedUid,
- proxiedPackageName, proxiedAttributionTag)), message,
- /*skipProxyOperation*/ false);
+ proxiedPackageName, proxiedAttributionTag,
+ mContext.getAttributionSource().getToken())), message,
+ /*skipProxyOperation*/ false);
}
/**
@@ -8705,6 +8809,23 @@ public class AppOpsManager {
*/
public int startProxyOpNoThrow(int op, @NonNull AttributionSource attributionSource,
@Nullable String message, boolean skipProxyOperation) {
+ return startProxyOpNoThrow(op, attributionSource, message, skipProxyOperation,
+ ATTRIBUTION_FLAGS_NONE, ATTRIBUTION_FLAGS_NONE, ATTRIBUTION_CHAIN_ID_NONE);
+ }
+
+ /**
+ * Like {@link #startProxyOp(String, AttributionSource, String)} but instead
+ * of throwing a {@link SecurityException} it returns {@link #MODE_ERRORED} and
+ * the checks is for the attribution chain specified by the {@link AttributionSource}.
+ *
+ * @see #startProxyOp(String, AttributionSource, String)
+ *
+ * @hide
+ */
+ public int startProxyOpNoThrow(int op, @NonNull AttributionSource attributionSource,
+ @Nullable String message, boolean skipProxyOperation, @AttributionFlags
+ int proxyAttributionFlags, @AttributionFlags int proxiedAttributionFlags,
+ int attributionChainId) {
try {
collectNoteOpCallsForValidation(op);
int collectionMode = getNotedOpCollectionMode(
@@ -8719,9 +8840,10 @@ public class AppOpsManager {
}
}
- SyncNotedAppOp syncOp = mService.startProxyOperation(getClientId(), op,
+ SyncNotedAppOp syncOp = mService.startProxyOperation(op,
attributionSource, false, collectionMode == COLLECT_ASYNC, message,
- shouldCollectMessage, skipProxyOperation);
+ shouldCollectMessage, skipProxyOperation, proxyAttributionFlags,
+ proxiedAttributionFlags, attributionChainId);
if (syncOp.getOpMode() == MODE_ALLOWED) {
if (collectionMode == COLLECT_SELF) {
@@ -8785,8 +8907,18 @@ public class AppOpsManager {
*/
public void finishOp(int op, int uid, @NonNull String packageName,
@Nullable String attributionTag) {
+ finishOp(mContext.getAttributionSource().getToken(), op, uid, packageName, attributionTag);
+ }
+
+ /**
+ * @see #finishOp(String, int, String, String)
+ *
+ * @hide
+ */
+ public void finishOp(IBinder token, int op, int uid, @NonNull String packageName,
+ @Nullable String attributionTag) {
try {
- mService.finishOperation(getClientId(), op, uid, packageName, attributionTag);
+ mService.finishOperation(token, op, uid, packageName, attributionTag);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -8807,23 +8939,26 @@ public class AppOpsManager {
public void finishProxyOp(@NonNull String op, int proxiedUid,
@NonNull String proxiedPackageName, @Nullable String proxiedAttributionTag) {
finishProxyOp(op, new AttributionSource(mContext.getAttributionSource(),
- new AttributionSource(proxiedUid, proxiedPackageName, proxiedAttributionTag)));
+ new AttributionSource(proxiedUid, proxiedPackageName, proxiedAttributionTag,
+ mContext.getAttributionSource().getToken())), /*skipProxyOperation*/ false);
}
/**
* Report that an application is no longer performing an operation that had previously
- * been started with {@link #startProxyOp(String, AttributionSource, String)}. There is no
- * validation of input or result; the parameters supplied here must be the exact same ones
- * previously passed in when starting the operation.
+ * been started with {@link #startProxyOp(String, AttributionSource, String, boolean)}. There
+ * is no validation of input or result; the parameters supplied here must be the exact same
+ * ones previously passed in when starting the operation.
*
* @param op The operation which was started
* @param attributionSource The permission identity for which to finish
+ * @param skipProxyOperation Whether to skip the proxy finish.
*
* @hide
*/
- public void finishProxyOp(@NonNull String op, @NonNull AttributionSource attributionSource) {
+ public void finishProxyOp(@NonNull String op, @NonNull AttributionSource attributionSource,
+ boolean skipProxyOperation) {
try {
- mService.finishProxyOperation(getClientId(), strOpToOp(op), attributionSource);
+ mService.finishProxyOperation(strOpToOp(op), attributionSource, skipProxyOperation);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/app/AppOpsManagerInternal.java b/core/java/android/app/AppOpsManagerInternal.java
index 2de0ddb17646..a757e32d0d75 100644
--- a/core/java/android/app/AppOpsManagerInternal.java
+++ b/core/java/android/app/AppOpsManagerInternal.java
@@ -16,6 +16,7 @@
package android.app;
+import android.app.AppOpsManager.AttributionFlags;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.AttributionSource;
@@ -24,13 +25,13 @@ import android.util.SparseArray;
import android.util.SparseIntArray;
import com.android.internal.app.IAppOpsCallback;
+import com.android.internal.util.function.DecFunction;
import com.android.internal.util.function.HeptFunction;
import com.android.internal.util.function.HexFunction;
-import com.android.internal.util.function.NonaFunction;
-import com.android.internal.util.function.OctFunction;
import com.android.internal.util.function.QuadFunction;
import com.android.internal.util.function.QuintFunction;
import com.android.internal.util.function.TriFunction;
+import com.android.internal.util.function.UndecFunction;
/**
* App ops service local interface.
@@ -52,8 +53,8 @@ public abstract class AppOpsManagerInternal {
* @return The app op check result.
*/
int checkOperation(int code, int uid, String packageName, @Nullable String attributionTag,
- boolean raw,
- QuintFunction<Integer, Integer, String, String, Boolean, Integer> superImpl);
+ boolean raw, QuintFunction<Integer, Integer, String, String, Boolean, Integer>
+ superImpl);
/**
* Allows overriding check audio operation behavior.
@@ -116,20 +117,22 @@ public abstract class AppOpsManagerInternal {
* @param shouldCollectAsyncNotedOp If an {@link AsyncNotedAppOp} should be collected
* @param message The message in the async noted op
* @param shouldCollectMessage whether to collect messages
+ * @param attributionFlags the attribution flags for this operation.
+ * @param attributionChainId the unique id of the attribution chain this op is a part of.
* @param superImpl The super implementation.
* @return The app op note result.
*/
SyncNotedAppOp startOperation(IBinder token, int code, int uid,
@Nullable String packageName, @Nullable String attributionTag,
boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp,
- @Nullable String message, boolean shouldCollectMessage, @NonNull NonaFunction<
- IBinder, Integer, Integer, String, String, Boolean, Boolean, String,
- Boolean, SyncNotedAppOp> superImpl);
+ @Nullable String message, boolean shouldCollectMessage,
+ @AttributionFlags int attributionFlags, int attributionChainId,
+ @NonNull UndecFunction<IBinder, Integer, Integer, String, String, Boolean,
+ Boolean, String, Boolean, Integer, Integer, SyncNotedAppOp> superImpl);
/**
* Allows overriding start proxy operation behavior.
*
- * @param token The client state.
* @param code The op code to start.
* @param attributionSource The permission identity of the caller.
* @param startIfModeDefault Whether to start the op of the mode is default.
@@ -137,26 +140,29 @@ public abstract class AppOpsManagerInternal {
* @param message The message in the async noted op
* @param shouldCollectMessage whether to collect messages
* @param skipProxyOperation Whether to skip the proxy portion of the operation
+ * @param proxyAttributionFlags The attribution flags for the proxy.
+ * @param proxiedAttributionFlags The attribution flags for the proxied.
+ * @oaram attributionChainId The id of the attribution chain this operation is a part of.
* @param superImpl The super implementation.
* @return The app op note result.
*/
- SyncNotedAppOp startProxyOperation(IBinder token, int code,
- @NonNull AttributionSource attributionSource, boolean startIfModeDefault,
- boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage,
- boolean skipProxyOperation, @NonNull OctFunction<IBinder, Integer,
- AttributionSource, Boolean, Boolean, String, Boolean, Boolean,
+ SyncNotedAppOp startProxyOperation(int code, @NonNull AttributionSource attributionSource,
+ boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp, String message,
+ boolean shouldCollectMessage, boolean skipProxyOperation, @AttributionFlags
+ int proxyAttributionFlags, @AttributionFlags int proxiedAttributionFlags,
+ int attributionChainId, @NonNull DecFunction<Integer, AttributionSource, Boolean,
+ Boolean, String, Boolean, Boolean, Integer, Integer, Integer,
SyncNotedAppOp> superImpl);
/**
* Allows overriding finish proxy op.
*
- * @param clientId Client state token.
* @param code The op code to finish.
* @param attributionSource The permission identity of the caller.
*/
- void finishProxyOperation(IBinder clientId, int code,
- @NonNull AttributionSource attributionSource,
- @NonNull TriFunction<IBinder, Integer, AttributionSource, Void> superImpl);
+ void finishProxyOperation(int code, @NonNull AttributionSource attributionSource,
+ boolean skipProxyOperation,
+ @NonNull TriFunction<Integer, AttributionSource, Boolean, Void> superImpl);
}
/**
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index daef8b1eae08..16b6ea5bcf42 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -3157,13 +3157,7 @@ class ContextImpl extends Context {
// If we want to access protected data on behalf of another app we need to
// tell the OS that we opt in to participate in the attribution chain.
if (nextAttributionSource != null) {
- // If an app happened to stub the internal OS for testing the registration method
- // can return null. In this case we keep the current untrusted attribution source.
- final AttributionSource registeredAttributionSource = getSystemService(
- PermissionManager.class).registerAttributionSource(attributionSource);
- if (registeredAttributionSource != null) {
- return registeredAttributionSource;
- }
+ getSystemService(PermissionManager.class).registerAttributionSource(attributionSource);
}
return attributionSource;
}
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 64b100f838ba..30ddd20b312c 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -9804,10 +9804,6 @@ public class Notification implements Parcelable
* <p>Apps sending bubbles may set this flag so that the bubble is posted <b>without</b>
* the associated notification in the notification shade.</p>
*
- * <p>Apps sending bubbles can only apply this flag when the app is in the foreground,
- * otherwise the flag is not respected. The app is considered foreground if it is visible
- * and on the screen, note that a foreground service does not qualify.</p>
- *
* <p>Generally this flag should only be set by the app if the user has performed an
* action to request or create a bubble, or if the user has seen the content in the
* notification and the notification is no longer relevant. </p>
@@ -9958,10 +9954,6 @@ public class Notification implements Parcelable
* <p>Apps sending bubbles may set this flag so that the bubble is posted <b>without</b>
* the associated notification in the notification shade.</p>
*
- * <p>Apps sending bubbles can only apply this flag when the app is in the foreground,
- * otherwise the flag is not respected. The app is considered foreground if it is visible
- * and on the screen, note that a foreground service does not qualify.</p>
- *
* <p>Generally the app should only set this flag if the user has performed an
* action to request or create a bubble, or if the user has seen the content in the
* notification and the notification is no longer relevant. </p>
@@ -10349,11 +10341,6 @@ public class Notification implements Parcelable
* Sets whether the bubble will be posted <b>without</b> the associated notification in
* the notification shade.
*
- * <p>This flag has no effect if the app posting the bubble is not in the foreground.
- * The app is considered foreground if it is visible and on the screen, note that
- * a foreground service does not qualify.
- * </p>
- *
* <p>Generally, this flag should only be set if the user has performed an action to
* request or create a bubble, or if the user has seen the content in the notification
* and the notification is no longer relevant.</p>
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 91dad2a1f13c..871d48b07a20 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -186,6 +186,7 @@ import android.os.incremental.IIncrementalService;
import android.os.incremental.IncrementalManager;
import android.os.storage.StorageManager;
import android.permission.LegacyPermissionManager;
+import android.permission.PermissionCheckerManager;
import android.permission.PermissionControllerManager;
import android.permission.PermissionManager;
import android.print.IPrintManager;
@@ -1334,6 +1335,14 @@ public final class SystemServiceRegistry {
ctx.getMainThreadHandler());
}});
+ registerService(Context.PERMISSION_CHECKER_SERVICE, PermissionCheckerManager.class,
+ new CachedServiceFetcher<PermissionCheckerManager>() {
+ @Override
+ public PermissionCheckerManager createService(ContextImpl ctx)
+ throws ServiceNotFoundException {
+ return new PermissionCheckerManager(ctx.getOuterContext());
+ }});
+
registerService(Context.DYNAMIC_SYSTEM_SERVICE, DynamicSystemManager.class,
new CachedServiceFetcher<DynamicSystemManager>() {
@Override
diff --git a/core/java/android/content/AttributionSource.java b/core/java/android/content/AttributionSource.java
index 7ab731f15ad2..1dda6374a474 100644
--- a/core/java/android/content/AttributionSource.java
+++ b/core/java/android/content/AttributionSource.java
@@ -21,6 +21,7 @@ import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.TestApi;
+import android.app.ActivityThread;
import android.os.Binder;
import android.os.Build;
import android.os.IBinder;
@@ -94,14 +95,22 @@ public final class AttributionSource implements Parcelable {
@TestApi
public AttributionSource(int uid, @Nullable String packageName,
@Nullable String attributionTag) {
- this(uid, packageName, attributionTag, /*next*/ null);
+ this(uid, packageName, attributionTag, new Binder());
}
/** @hide */
@TestApi
public AttributionSource(int uid, @Nullable String packageName,
- @Nullable String attributionTag, @Nullable AttributionSource next) {
- this(uid, packageName, attributionTag, /*renouncedPermissions*/ null, next);
+ @Nullable String attributionTag, @NonNull IBinder token) {
+ this(uid, packageName, attributionTag, token, /*renouncedPermissions*/ null,
+ /*next*/ null);
+ }
+
+ /** @hide */
+ public AttributionSource(int uid, @Nullable String packageName,
+ @Nullable String attributionTag, @NonNull IBinder token,
+ @Nullable AttributionSource next) {
+ this(uid, packageName, attributionTag, token, /*renouncedPermissions*/ null, next);
}
/** @hide */
@@ -109,28 +118,32 @@ public final class AttributionSource implements Parcelable {
public AttributionSource(int uid, @Nullable String packageName,
@Nullable String attributionTag, @Nullable Set<String> renouncedPermissions,
@Nullable AttributionSource next) {
- this(uid, packageName, attributionTag, /*token*/ null, (renouncedPermissions != null)
+ this(uid, packageName, attributionTag, (renouncedPermissions != null)
? renouncedPermissions.toArray(new String[0]) : null, next);
}
/** @hide */
- public AttributionSource(@NonNull AttributionSource current,
- @Nullable AttributionSource next) {
+ public AttributionSource(@NonNull AttributionSource current, @Nullable AttributionSource next) {
this(current.getUid(), current.getPackageName(), current.getAttributionTag(),
- /*token*/ null, /*renouncedPermissions*/ null, next);
+ current.getToken(), current.mAttributionSourceState.renouncedPermissions, next);
}
AttributionSource(int uid, @Nullable String packageName, @Nullable String attributionTag,
- @Nullable IBinder token, @Nullable String[] renouncedPermissions,
+ @Nullable String[] renouncedPermissions, @Nullable AttributionSource next) {
+ this(uid, packageName, attributionTag, new Binder(), renouncedPermissions, next);
+ }
+
+ AttributionSource(int uid, @Nullable String packageName, @Nullable String attributionTag,
+ @NonNull IBinder token, @Nullable String[] renouncedPermissions,
@Nullable AttributionSource next) {
mAttributionSourceState = new AttributionSourceState();
mAttributionSourceState.uid = uid;
+ mAttributionSourceState.token = token;
mAttributionSourceState.packageName = packageName;
mAttributionSourceState.attributionTag = attributionTag;
- mAttributionSourceState.token = token;
mAttributionSourceState.renouncedPermissions = renouncedPermissions;
mAttributionSourceState.next = (next != null) ? new AttributionSourceState[]
- {next.mAttributionSourceState} : null;
+ {next.mAttributionSourceState} : new AttributionSourceState[0];
}
AttributionSource(@NonNull Parcel in) {
@@ -145,18 +158,12 @@ public final class AttributionSource implements Parcelable {
/** @hide */
public AttributionSource withNextAttributionSource(@Nullable AttributionSource next) {
return new AttributionSource(getUid(), getPackageName(), getAttributionTag(),
- getToken(), mAttributionSourceState.renouncedPermissions, next);
- }
-
- /** @hide */
- public AttributionSource withToken(@Nullable IBinder token) {
- return new AttributionSource(getUid(), getPackageName(), getAttributionTag(),
- token, mAttributionSourceState.renouncedPermissions, getNext());
+ mAttributionSourceState.renouncedPermissions, next);
}
/** @hide */
public AttributionSource withPackageName(@Nullable String packageName) {
- return new AttributionSource(getUid(), packageName, getAttributionTag(), getToken(),
+ return new AttributionSource(getUid(), packageName, getAttributionTag(),
mAttributionSourceState.renouncedPermissions, getNext());
}
@@ -165,6 +172,45 @@ public final class AttributionSource implements Parcelable {
return mAttributionSourceState;
}
+ /** @hide */
+ public @NonNull ScopedParcelState asScopedParcelState() {
+ return new ScopedParcelState(this);
+ }
+
+ /** @hide */
+ public static AttributionSource myAttributionSource() {
+ return new AttributionSource(Process.myUid(), ActivityThread.currentOpPackageName(),
+ /*attributionTag*/ null, (String[]) /*renouncedPermissions*/ null, /*next*/ null);
+ }
+
+ /**
+ * This is a scoped object that exposes the content of an attribution source
+ * as a parcel. This is useful when passing one to native and avoid custom
+ * conversion logic from Java to native state that needs to be kept in sync
+ * as attribution source evolves. This way we use the same logic for passing
+ * to native as the ones for passing in an IPC - in both cases this is the
+ * same auto generated code.
+ *
+ * @hide
+ */
+ public static class ScopedParcelState implements AutoCloseable {
+ private final Parcel mParcel;
+
+ public @NonNull Parcel getParcel() {
+ return mParcel;
+ }
+
+ public ScopedParcelState(AttributionSource attributionSource) {
+ mParcel = Parcel.obtain();
+ attributionSource.writeToParcel(mParcel, 0);
+ mParcel.setDataPosition(0);
+ }
+
+ public void close() {
+ mParcel.recycle();
+ }
+ }
+
/**
* If you are handling an IPC and you don't trust the caller you need to validate
* whether the attribution source is one for the calling app to prevent the caller
@@ -209,7 +255,8 @@ public final class AttributionSource implements Parcelable {
"attributionTag = " + mAttributionSourceState.attributionTag + ", " +
"token = " + mAttributionSourceState.token + ", " +
"next = " + (mAttributionSourceState.next != null
- ? mAttributionSourceState.next[0]: null) +
+ && mAttributionSourceState.next.length > 0
+ ? mAttributionSourceState.next[0] : null) +
" }";
}
return super.toString();
@@ -221,7 +268,8 @@ public final class AttributionSource implements Parcelable {
* @hide
*/
public int getNextUid() {
- if (mAttributionSourceState.next != null) {
+ if (mAttributionSourceState.next != null
+ && mAttributionSourceState.next.length > 0) {
return mAttributionSourceState.next[0].uid;
}
return Process.INVALID_UID;
@@ -233,26 +281,42 @@ public final class AttributionSource implements Parcelable {
* @hide
*/
public @Nullable String getNextPackageName() {
- if (mAttributionSourceState.next != null) {
+ if (mAttributionSourceState.next != null
+ && mAttributionSourceState.next.length > 0) {
return mAttributionSourceState.next[0].packageName;
}
return null;
}
/**
- * @return The nexxt package's attribution tag that would receive
+ * @return The next package's attribution tag that would receive
* the permission protected data.
*
* @hide
*/
public @Nullable String getNextAttributionTag() {
- if (mAttributionSourceState.next != null) {
+ if (mAttributionSourceState.next != null
+ && mAttributionSourceState.next.length > 0) {
return mAttributionSourceState.next[0].attributionTag;
}
return null;
}
/**
+ * @return The next package's token that would receive
+ * the permission protected data.
+ *
+ * @hide
+ */
+ public @Nullable IBinder getNextToken() {
+ if (mAttributionSourceState.next != null
+ && mAttributionSourceState.next.length > 0) {
+ return mAttributionSourceState.next[0].token;
+ }
+ return null;
+ }
+
+ /**
* Checks whether this attribution source can be trusted. That is whether
* the app it refers to created it and provided to the attribution chain.
*
@@ -311,7 +375,7 @@ public final class AttributionSource implements Parcelable {
*
* @hide
*/
- public @Nullable IBinder getToken() {
+ public @NonNull IBinder getToken() {
return mAttributionSourceState.token;
}
@@ -319,7 +383,8 @@ public final class AttributionSource implements Parcelable {
* The next app to receive the permission protected data.
*/
public @Nullable AttributionSource getNext() {
- if (mNextCached == null && mAttributionSourceState.next != null) {
+ if (mNextCached == null && mAttributionSourceState.next != null
+ && mAttributionSourceState.next.length > 0) {
mNextCached = new AttributionSource(mAttributionSourceState.next[0]);
}
return mNextCached;
@@ -442,7 +507,7 @@ public final class AttributionSource implements Parcelable {
@RequiresPermission(android.Manifest.permission.RENOUNCE_PERMISSIONS)
public @NonNull Builder setRenouncedPermissions(@Nullable Set<String> value) {
checkNotUsed();
- mBuilderFieldsSet |= 0x10;
+ mBuilderFieldsSet |= 0x8;
mAttributionSourceState.renouncedPermissions = (value != null)
? value.toArray(new String[0]) : null;
return this;
@@ -453,9 +518,9 @@ public final class AttributionSource implements Parcelable {
*/
public @NonNull Builder setNext(@Nullable AttributionSource value) {
checkNotUsed();
- mBuilderFieldsSet |= 0x20;
+ mBuilderFieldsSet |= 0x10;
mAttributionSourceState.next = (value != null) ? new AttributionSourceState[]
- {value.mAttributionSourceState} : null;
+ {value.mAttributionSourceState} : mAttributionSourceState.next;
return this;
}
@@ -471,14 +536,16 @@ public final class AttributionSource implements Parcelable {
mAttributionSourceState.attributionTag = null;
}
if ((mBuilderFieldsSet & 0x8) == 0) {
- mAttributionSourceState.token = null;
- }
- if ((mBuilderFieldsSet & 0x10) == 0) {
mAttributionSourceState.renouncedPermissions = null;
}
- if ((mBuilderFieldsSet & 0x20) == 0) {
+ if ((mBuilderFieldsSet & 0x10) == 0) {
mAttributionSourceState.next = null;
}
+ mAttributionSourceState.token = new Binder();
+ if (mAttributionSourceState.next == null) {
+ // The NDK aidl backend doesn't support null parcelable arrays.
+ mAttributionSourceState.next = new AttributionSourceState[0];
+ }
return new AttributionSource(mAttributionSourceState);
}
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index 88686a309ee4..dc29c5e25f3c 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -49,6 +49,7 @@ import android.os.RemoteException;
import android.os.Trace;
import android.os.UserHandle;
import android.os.storage.StorageManager;
+import android.permission.PermissionCheckerManager;
import android.text.TextUtils;
import android.util.Log;
@@ -670,7 +671,7 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall
}
}
- @PermissionChecker.PermissionResult
+ @PermissionCheckerManager.PermissionResult
private void enforceFilePermission(@NonNull AttributionSource attributionSource,
Uri uri, String mode)
throws FileNotFoundException, SecurityException {
@@ -687,7 +688,7 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall
}
}
- @PermissionChecker.PermissionResult
+ @PermissionCheckerManager.PermissionResult
private int enforceReadPermission(@NonNull AttributionSource attributionSource, Uri uri)
throws SecurityException {
final int result = enforceReadPermissionInner(uri, attributionSource);
@@ -705,7 +706,7 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall
return PermissionChecker.PERMISSION_GRANTED;
}
- @PermissionChecker.PermissionResult
+ @PermissionCheckerManager.PermissionResult
private int enforceWritePermission(@NonNull AttributionSource attributionSource, Uri uri)
throws SecurityException {
final int result = enforceWritePermissionInner(uri, attributionSource);
@@ -738,7 +739,7 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall
* Verify that calling app holds both the given permission and any app-op
* associated with that permission.
*/
- @PermissionChecker.PermissionResult
+ @PermissionCheckerManager.PermissionResult
private int checkPermission(String permission,
@NonNull AttributionSource attributionSource) {
if (Binder.getCallingPid() == Process.myPid()) {
@@ -753,7 +754,7 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall
}
/** {@hide} */
- @PermissionChecker.PermissionResult
+ @PermissionCheckerManager.PermissionResult
protected int enforceReadPermissionInner(Uri uri,
@NonNull AttributionSource attributionSource) throws SecurityException {
final Context context = getContext();
@@ -836,7 +837,7 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall
}
/** {@hide} */
- @PermissionChecker.PermissionResult
+ @PermissionCheckerManager.PermissionResult
protected int enforceWritePermissionInner(Uri uri,
@NonNull AttributionSource attributionSource) throws SecurityException {
final Context context = getContext();
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 886cd7f48d35..ea0e321377c8 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -4836,6 +4836,14 @@ public abstract class Context {
public static final String PERMISSION_CONTROLLER_SERVICE = "permission_controller";
/**
+ * Official published name of the (internal) permission checker service.
+ *
+ * @see #getSystemService(String)
+ * @hide
+ */
+ public static final String PERMISSION_CHECKER_SERVICE = "permission_checker";
+
+ /**
* Use with {@link #getSystemService(String) to retrieve an
* {@link android.apphibernation.AppHibernationManager}} for
* communicating with the hibernation service.
diff --git a/core/java/android/content/PermissionChecker.java b/core/java/android/content/PermissionChecker.java
index 66e088359459..a167cb3d851f 100644
--- a/core/java/android/content/PermissionChecker.java
+++ b/core/java/android/content/PermissionChecker.java
@@ -16,19 +16,14 @@
package android.content;
-import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.AppOpsManager;
import android.os.Binder;
-import android.os.IBinder;
import android.os.Process;
-import android.os.RemoteException;
-import android.os.ServiceManager;
import android.permission.IPermissionChecker;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
+import android.permission.PermissionCheckerManager;
+import android.permission.PermissionCheckerManager.PermissionResult;
/**
* This class provides permission check APIs that verify both the
@@ -75,7 +70,7 @@ public final class PermissionChecker {
*
* @hide
*/
- public static final int PERMISSION_GRANTED = IPermissionChecker.PERMISSION_GRANTED;
+ public static final int PERMISSION_GRANTED = PermissionCheckerManager.PERMISSION_GRANTED;
/**
* The permission is denied. Applicable only to runtime and app op permissions.
@@ -89,7 +84,8 @@ public final class PermissionChecker {
*
* @hide
*/
- public static final int PERMISSION_SOFT_DENIED = IPermissionChecker.PERMISSION_SOFT_DENIED;
+ public static final int PERMISSION_SOFT_DENIED =
+ PermissionCheckerManager.PERMISSION_SOFT_DENIED;
/**
* The permission is denied.
@@ -103,18 +99,12 @@ public final class PermissionChecker {
*
* @hide
*/
- public static final int PERMISSION_HARD_DENIED = IPermissionChecker.PERMISSION_HARD_DENIED;
+ public static final int PERMISSION_HARD_DENIED =
+ PermissionCheckerManager.PERMISSION_HARD_DENIED;
/** Constant when the PID for which we check permissions is unknown. */
public static final int PID_UNKNOWN = -1;
- /** @hide */
- @IntDef({PERMISSION_GRANTED,
- PERMISSION_SOFT_DENIED,
- PERMISSION_HARD_DENIED})
- @Retention(RetentionPolicy.SOURCE)
- public @interface PermissionResult {}
-
private static volatile IPermissionChecker sService;
private PermissionChecker() {
@@ -157,7 +147,7 @@ public final class PermissionChecker {
*
* @see #checkPermissionForPreflight(Context, String, int, int, String)
*/
- @PermissionResult
+ @PermissionCheckerManager.PermissionResult
public static int checkPermissionForDataDelivery(@NonNull Context context,
@NonNull String permission, int pid, int uid, @Nullable String packageName,
@Nullable String attributionTag, @Nullable String message, boolean startDataDelivery) {
@@ -321,19 +311,13 @@ public final class PermissionChecker {
message, startDataDelivery, /*fromDatasource*/ false);
}
+ @SuppressWarnings("ConstantConditions")
private static int checkPermissionForDataDeliveryCommon(@NonNull Context context,
@NonNull String permission, @NonNull AttributionSource attributionSource,
@Nullable String message, boolean startDataDelivery, boolean fromDatasource) {
- // If the check failed in the middle of the chain, finish any started op.
- try {
- final int result = getPermissionCheckerService().checkPermission(permission,
- attributionSource.asState(), message, true /*forDataDelivery*/,
- startDataDelivery, fromDatasource);
- return result;
- } catch (RemoteException e) {
- e.rethrowFromSystemServer();
- }
- return PERMISSION_HARD_DENIED;
+ return context.getSystemService(PermissionCheckerManager.class).checkPermission(permission,
+ attributionSource.asState(), message, true /*forDataDelivery*/, startDataDelivery,
+ fromDatasource, AppOpsManager.OP_NONE);
}
/**
@@ -365,17 +349,13 @@ public final class PermissionChecker {
* @see #checkPermissionForPreflight(Context, String, AttributionSource)
*/
@PermissionResult
+ @SuppressWarnings("ConstantConditions")
public static int checkPermissionAndStartDataDelivery(@NonNull Context context,
@NonNull String permission, @NonNull AttributionSource attributionSource,
@Nullable String message) {
- try {
- return getPermissionCheckerService().checkPermission(permission,
- attributionSource.asState(), message, true /*forDataDelivery*/,
- /*startDataDelivery*/ true, /*fromDatasource*/ false);
- } catch (RemoteException e) {
- e.rethrowFromSystemServer();
- }
- return PERMISSION_HARD_DENIED;
+ return context.getSystemService(PermissionCheckerManager.class).checkPermission(
+ permission, attributionSource.asState(), message, true /*forDataDelivery*/,
+ /*startDataDelivery*/ true, /*fromDatasource*/ false, AppOpsManager.OP_NONE);
}
/**
@@ -404,17 +384,13 @@ public final class PermissionChecker {
* @see #finishDataDelivery(Context, String, AttributionSource)
*/
@PermissionResult
+ @SuppressWarnings("ConstantConditions")
public static int startOpForDataDelivery(@NonNull Context context,
@NonNull String opName, @NonNull AttributionSource attributionSource,
@Nullable String message) {
- try {
- return getPermissionCheckerService().checkOp(
- AppOpsManager.strOpToOp(opName), attributionSource.asState(), message,
- true /*forDataDelivery*/, true /*startDataDelivery*/);
- } catch (RemoteException e) {
- e.rethrowFromSystemServer();
- }
- return PERMISSION_HARD_DENIED;
+ return context.getSystemService(PermissionCheckerManager.class).checkOp(
+ AppOpsManager.strOpToOp(opName), attributionSource.asState(), message,
+ true /*forDataDelivery*/, true /*startDataDelivery*/);
}
/**
@@ -428,13 +404,32 @@ public final class PermissionChecker {
* @see #startOpForDataDelivery(Context, String, AttributionSource, String)
* @see #checkPermissionAndStartDataDelivery(Context, String, AttributionSource, String)
*/
+ @SuppressWarnings("ConstantConditions")
public static void finishDataDelivery(@NonNull Context context, @NonNull String op,
@NonNull AttributionSource attributionSource) {
- try {
- getPermissionCheckerService().finishDataDelivery(op, attributionSource.asState());
- } catch (RemoteException e) {
- e.rethrowFromSystemServer();
- }
+ context.getSystemService(PermissionCheckerManager.class).finishDataDelivery(
+ AppOpsManager.strOpToOp(op), attributionSource.asState(),
+ /*fromDatasource*/ false);
+ }
+
+ /**
+ * Finishes an ongoing op for data access chain described by the given {@link
+ * AttributionSource}. Call this method if you are the datasource which would
+ * not finish an op for your attribution source as it was not started.
+ *
+ * @param context Context for accessing resources.
+ * @param op The op to finish.
+ * @param attributionSource The identity for which finish op.
+ *
+ * @see #startOpForDataDelivery(Context, String, AttributionSource, String)
+ * @see #checkPermissionAndStartDataDelivery(Context, String, AttributionSource, String)
+ */
+ @SuppressWarnings("ConstantConditions")
+ public static void finishDataDeliveryFromDatasource(@NonNull Context context,
+ @NonNull String op, @NonNull AttributionSource attributionSource) {
+ context.getSystemService(PermissionCheckerManager.class).finishDataDelivery(
+ AppOpsManager.strOpToOp(op), attributionSource.asState(),
+ /*fromDatasource*/ true);
}
/**
@@ -466,17 +461,13 @@ public final class PermissionChecker {
* @see #checkOpForDataDelivery(Context, String, AttributionSource, String)
*/
@PermissionResult
+ @SuppressWarnings("ConstantConditions")
public static int checkOpForPreflight(@NonNull Context context,
@NonNull String opName, @NonNull AttributionSource attributionSource,
@Nullable String message) {
- try {
- return getPermissionCheckerService().checkOp(AppOpsManager.strOpToOp(opName),
- attributionSource.asState(), message, false /*forDataDelivery*/,
- false /*startDataDelivery*/);
- } catch (RemoteException e) {
- e.rethrowFromSystemServer();
- }
- return PERMISSION_HARD_DENIED;
+ return context.getSystemService(PermissionCheckerManager.class).checkOp(
+ AppOpsManager.strOpToOp(opName), attributionSource.asState(), message,
+ false /*forDataDelivery*/, false /*startDataDelivery*/);
}
/**
@@ -505,17 +496,13 @@ public final class PermissionChecker {
* @see #checkOpForPreflight(Context, String, AttributionSource, String)
*/
@PermissionResult
+ @SuppressWarnings("ConstantConditions")
public static int checkOpForDataDelivery(@NonNull Context context,
@NonNull String opName, @NonNull AttributionSource attributionSource,
@Nullable String message) {
- try {
- return getPermissionCheckerService().checkOp(AppOpsManager.strOpToOp(opName),
- attributionSource.asState(), message, true /*forDataDelivery*/,
- false /*startDataDelivery*/);
- } catch (RemoteException e) {
- e.rethrowFromSystemServer();
- }
- return PERMISSION_HARD_DENIED;
+ return context.getSystemService(PermissionCheckerManager.class).checkOp(
+ AppOpsManager.strOpToOp(opName), attributionSource.asState(), message,
+ true /*forDataDelivery*/, false /*startDataDelivery*/);
}
/**
@@ -584,16 +571,13 @@ public final class PermissionChecker {
* String, boolean)
*/
@PermissionResult
+ @SuppressWarnings("ConstantConditions")
public static int checkPermissionForPreflight(@NonNull Context context,
@NonNull String permission, @NonNull AttributionSource attributionSource) {
- try {
- return getPermissionCheckerService().checkPermission(permission,
- attributionSource.asState(), null /*message*/, false /*forDataDelivery*/,
- /*startDataDelivery*/ false, /*fromDatasource*/ false);
- } catch (RemoteException e) {
- e.rethrowFromSystemServer();
- }
- return PERMISSION_HARD_DENIED;
+ return context.getSystemService(PermissionCheckerManager.class)
+ .checkPermission(permission, attributionSource.asState(), null /*message*/,
+ false /*forDataDelivery*/, /*startDataDelivery*/ false, /*fromDatasource*/ false,
+ AppOpsManager.OP_NONE);
}
/**
@@ -827,13 +811,4 @@ public final class PermissionChecker {
return checkPermissionForPreflight(context, permission, Binder.getCallingPid(),
Binder.getCallingUid(), packageName);
}
-
- private static @NonNull IPermissionChecker getPermissionCheckerService() {
- // Race is fine, we may end up looking up the same instance twice, no big deal.
- if (sService == null) {
- final IBinder service = ServiceManager.getService("permission_checker");
- sService = IPermissionChecker.Stub.asInterface(service);
- }
- return sService;
- }
}
diff --git a/core/java/android/hardware/camera2/params/OutputConfiguration.java b/core/java/android/hardware/camera2/params/OutputConfiguration.java
index 0662f160a009..8dfb787bb3ab 100644
--- a/core/java/android/hardware/camera2/params/OutputConfiguration.java
+++ b/core/java/android/hardware/camera2/params/OutputConfiguration.java
@@ -846,6 +846,14 @@ public final class OutputConfiguration implements Parcelable {
return 0;
}
+ private static int[] convertIntegerToIntList(List<Integer> integerList) {
+ int[] integerArray = new int[integerList.size()];
+ for (int i = 0; i < integerList.size(); i++) {
+ integerArray[i] = integerList.get(i);
+ }
+ return integerArray;
+ }
+
@Override
public void writeToParcel(Parcel dest, int flags) {
if (dest == null) {
@@ -861,7 +869,9 @@ public final class OutputConfiguration implements Parcelable {
dest.writeTypedList(mSurfaces);
dest.writeString(mPhysicalCameraId);
dest.writeInt(mIsMultiResolution ? 1 : 0);
- dest.writeList(mSensorPixelModesUsed);
+ // writeList doesn't seem to work well with Integer list.
+ dest.writeIntArray(convertIntegerToIntList(mSensorPixelModesUsed));
+ //dest.writeArray(mSensorPixelModesUsed.toArray());
}
/**
diff --git a/core/java/android/hardware/fingerprint/IUdfpsOverlayController.aidl b/core/java/android/hardware/fingerprint/IUdfpsOverlayController.aidl
index d2cb5bfe6910..f18360ff4108 100644
--- a/core/java/android/hardware/fingerprint/IUdfpsOverlayController.aidl
+++ b/core/java/android/hardware/fingerprint/IUdfpsOverlayController.aidl
@@ -35,6 +35,10 @@ oneway interface IUdfpsOverlayController {
// Hides the overlay.
void hideUdfpsOverlay(int sensorId);
+ // Good image captured. Turn off HBM. Success/Reject comes after, which is when hideUdfpsOverlay
+ // will be called.
+ void onAcquiredGood(int sensorId);
+
// Notifies of enrollment progress changes.
void onEnrollmentProgress(int sensorId, int remaining);
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 900659b5ae54..a5b7e995293a 100755
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -1086,7 +1086,7 @@ public class Build {
/**
* S.
*/
- public static final int S = CUR_DEVELOPMENT;
+ public static final int S = 31;
}
/** The type of build, like "user" or "eng". */
diff --git a/core/java/android/os/VibrationEffect.java b/core/java/android/os/VibrationEffect.java
index 781800dd49ce..a0cbbfe3327b 100644
--- a/core/java/android/os/VibrationEffect.java
+++ b/core/java/android/os/VibrationEffect.java
@@ -182,6 +182,11 @@ public abstract class VibrationEffect implements Parcelable {
* @return The desired effect.
*/
public static VibrationEffect createOneShot(long milliseconds, int amplitude) {
+ if (amplitude == 0) {
+ throw new IllegalArgumentException(
+ "amplitude must either be DEFAULT_AMPLITUDE, "
+ + "or between 1 and 255 inclusive (amplitude=" + amplitude + ")");
+ }
return createWaveform(new long[]{milliseconds}, new int[]{amplitude}, -1 /* repeat */);
}
@@ -581,22 +586,16 @@ public abstract class VibrationEffect implements Parcelable {
public void validate() {
int segmentCount = mSegments.size();
boolean hasNonZeroDuration = false;
- boolean hasNonZeroAmplitude = false;
for (int i = 0; i < segmentCount; i++) {
VibrationEffectSegment segment = mSegments.get(i);
segment.validate();
// A segment with unknown duration = -1 still counts as a non-zero duration.
hasNonZeroDuration |= segment.getDuration() != 0;
- hasNonZeroAmplitude |= segment.hasNonZeroAmplitude();
}
if (!hasNonZeroDuration) {
throw new IllegalArgumentException("at least one timing must be non-zero"
+ " (segments=" + mSegments + ")");
}
- if (!hasNonZeroAmplitude) {
- throw new IllegalArgumentException("at least one amplitude must be non-zero"
- + " (segments=" + mSegments + ")");
- }
if (mRepeatIndex != -1) {
Preconditions.checkArgumentInRange(mRepeatIndex, 0, segmentCount - 1,
"repeat index must be within the bounds of the segments (segments.length="
diff --git a/core/java/android/permission/IPermissionManager.aidl b/core/java/android/permission/IPermissionManager.aidl
index ef075e1efbff..9ab69552f1a0 100644
--- a/core/java/android/permission/IPermissionManager.aidl
+++ b/core/java/android/permission/IPermissionManager.aidl
@@ -87,7 +87,7 @@ interface IPermissionManager {
boolean isAutoRevokeExempted(String packageName, int userId);
- AttributionSource registerAttributionSource(in AttributionSource source);
+ void registerAttributionSource(in AttributionSource source);
boolean isRegisteredAttributionSource(in AttributionSource source);
}
diff --git a/core/java/android/permission/PermissionCheckerManager.java b/core/java/android/permission/PermissionCheckerManager.java
new file mode 100644
index 000000000000..7523816250b0
--- /dev/null
+++ b/core/java/android/permission/PermissionCheckerManager.java
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.permission;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.AppOpsManager;
+import android.content.AttributionSourceState;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Objects;
+
+/**
+ * Manager for checking runtime and app op permissions. This is a temporary
+ * class and we may fold its function in the PermissionManager once the
+ * permission re-architecture starts falling into place. The main benefit
+ * of this class is to allow context level caching.
+ *
+ * @hide
+ */
+public class PermissionCheckerManager {
+
+ /**
+ * The permission is granted.
+ */
+ public static final int PERMISSION_GRANTED = IPermissionChecker.PERMISSION_GRANTED;
+
+ /**
+ * The permission is denied. Applicable only to runtime and app op permissions.
+ *
+ * <p>Returned when:
+ * <ul>
+ * <li>the runtime permission is granted, but the corresponding app op is denied
+ * for runtime permissions.</li>
+ * <li>the app ops is ignored for app op permissions.</li>
+ * </ul>
+ */
+ public static final int PERMISSION_SOFT_DENIED = IPermissionChecker.PERMISSION_SOFT_DENIED;
+
+ /**
+ * The permission is denied.
+ *
+ * <p>Returned when:
+ * <ul>
+ * <li>the permission is denied for non app op permissions.</li>
+ * <li>the app op is denied or app op is {@link AppOpsManager#MODE_DEFAULT}
+ * and permission is denied.</li>
+ * </ul>
+ */
+ public static final int PERMISSION_HARD_DENIED = IPermissionChecker.PERMISSION_HARD_DENIED;
+
+ /** @hide */
+ @IntDef({PERMISSION_GRANTED,
+ PERMISSION_SOFT_DENIED,
+ PERMISSION_HARD_DENIED})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface PermissionResult {}
+
+ @NonNull
+ private final Context mContext;
+
+ @NonNull
+ private final IPermissionChecker mService;
+
+ @NonNull
+ private final PackageManager mPackageManager;
+
+ public PermissionCheckerManager(@NonNull Context context)
+ throws ServiceManager.ServiceNotFoundException {
+ mContext = context;
+ mService = IPermissionChecker.Stub.asInterface(ServiceManager.getServiceOrThrow(
+ Context.PERMISSION_CHECKER_SERVICE));
+ mPackageManager = context.getPackageManager();
+ }
+
+ /**
+ * Checks a permission by validating the entire attribution source chain. If the
+ * permission is associated with an app op the op is also noted/started for the
+ * entire attribution chain.
+ *
+ * @param permission The permission
+ * @param attributionSource The attribution chain to check.
+ * @param message Message associated with the permission if permission has an app op
+ * @param forDataDelivery Whether the check is for delivering data if permission has an app op
+ * @param startDataDelivery Whether to start data delivery (start op) if permission has
+ * an app op
+ * @param fromDatasource Whether the check is by a datasource (skip checks for the
+ * first attribution source in the chain as this is the datasource)
+ * @param attributedOp Alternative app op to attribute
+ * @return The permission check result.
+ */
+ @PermissionResult
+ public int checkPermission(@NonNull String permission,
+ @NonNull AttributionSourceState attributionSource, @Nullable String message,
+ boolean forDataDelivery, boolean startDataDelivery, boolean fromDatasource,
+ int attributedOp) {
+ Objects.requireNonNull(permission);
+ Objects.requireNonNull(attributionSource);
+ // Fast path for non-runtime, non-op permissions where the attribution chain has
+ // length one. This is the majority of the cases and we want these to be fast by
+ // hitting the local in process permission cache.
+ if (AppOpsManager.permissionToOpCode(permission) == AppOpsManager.OP_NONE) {
+ if (fromDatasource) {
+ if (attributionSource.next != null && attributionSource.next.length > 0) {
+ return mContext.checkPermission(permission, attributionSource.next[0].pid,
+ attributionSource.next[0].uid) == PackageManager.PERMISSION_GRANTED
+ ? PERMISSION_GRANTED : PERMISSION_HARD_DENIED;
+ }
+ } else {
+ return (mContext.checkPermission(permission, attributionSource.pid,
+ attributionSource.uid) == PackageManager.PERMISSION_GRANTED)
+ ? PERMISSION_GRANTED : PERMISSION_HARD_DENIED;
+ }
+ }
+ try {
+ return mService.checkPermission(permission, attributionSource, message, forDataDelivery,
+ startDataDelivery, fromDatasource, attributedOp);
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ return PERMISSION_HARD_DENIED;
+ }
+
+ /**
+ * Finishes an app op by validating the entire attribution source chain.
+ *
+ * @param op The op to finish.
+ * @param attributionSource The attribution chain to finish.
+ * @param fromDatasource Whether the finish is by a datasource (skip finish for the
+ * first attribution source in the chain as this is the datasource)
+ */
+ public void finishDataDelivery(int op, @NonNull AttributionSourceState attributionSource,
+ boolean fromDatasource) {
+ Objects.requireNonNull(attributionSource);
+ try {
+ mService.finishDataDelivery(op, attributionSource, fromDatasource);
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Checks an app op by validating the entire attribution source chain. The op is
+ * also noted/started for the entire attribution chain.
+ *
+ * @param op The op to check.
+ * @param attributionSource The attribution chain to check.
+ * @param message Message associated with the permission if permission has an app op
+ * @param forDataDelivery Whether the check is for delivering data if permission has an app op
+ * @param startDataDelivery Whether to start data delivery (start op) if permission has
+ * an app op
+ * @return The op check result.
+ */
+ @PermissionResult
+ public int checkOp(int op, @NonNull AttributionSourceState attributionSource,
+ @Nullable String message, boolean forDataDelivery, boolean startDataDelivery) {
+ Objects.requireNonNull(attributionSource);
+ try {
+ return mService.checkOp(op, attributionSource, message, forDataDelivery,
+ startDataDelivery);
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ return PERMISSION_HARD_DENIED;
+ }
+}
diff --git a/core/java/android/permission/PermissionManager.java b/core/java/android/permission/PermissionManager.java
index d490e7a7b454..f3cc35b32223 100644
--- a/core/java/android/permission/PermissionManager.java
+++ b/core/java/android/permission/PermissionManager.java
@@ -1156,13 +1156,12 @@ public final class PermissionManager {
* @hide
*/
@TestApi
- public @NonNull AttributionSource registerAttributionSource(@NonNull AttributionSource source) {
+ public void registerAttributionSource(@NonNull AttributionSource source) {
try {
- return mPermissionManager.registerAttributionSource(source);
+ mPermissionManager.registerAttributionSource(source);
} catch (RemoteException e) {
e.rethrowFromSystemServer();
}
- return null;
}
/**
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 13e5cda7cca3..cb87653718c2 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -6661,6 +6661,20 @@ public final class Settings {
public static final String COMPLETED_CATEGORY_PREFIX = "suggested.completed_category.";
/**
+ * Whether or not compress blocks should be released on install.
+ * <p>The setting only determines if the platform will attempt to release
+ * compress blocks; it does not guarantee that the files will have their
+ * compress blocks released. Compression is currently only supported on
+ * some f2fs filesystems.
+ * <p>
+ * Type: int (0 for false, 1 for true)
+ *
+ * @hide
+ */
+ public static final String RELEASE_COMPRESS_BLOCKS_ON_INSTALL =
+ "release_compress_blocks_on_install";
+
+ /**
* List of input methods that are currently enabled. This is a string
* containing the IDs of all enabled input methods, each ID separated
* by ':'.
@@ -11060,7 +11074,7 @@ public final class Settings {
* @hide
*/
@UnsupportedAppUsage
- @Readable(maxTargetSdk = Build.VERSION_CODES.R)
+ @Readable
public static final String MOBILE_DATA = "mobile_data";
/**
diff --git a/core/java/android/speech/RecognitionService.java b/core/java/android/speech/RecognitionService.java
index bb48757988e9..b9ff5e7be86a 100644
--- a/core/java/android/speech/RecognitionService.java
+++ b/core/java/android/speech/RecognitionService.java
@@ -65,22 +65,20 @@ public abstract class RecognitionService extends Service {
private static final String TAG = "RecognitionService";
/** Debugging flag */
- private static final boolean DBG = true;
-
- private static final String RECORD_AUDIO_APP_OP =
- AppOpsManager.permissionToOp(Manifest.permission.RECORD_AUDIO);
- private static final int RECORD_AUDIO_APP_OP_CODE =
- AppOpsManager.permissionToOpCode(Manifest.permission.RECORD_AUDIO);
+ private static final boolean DBG = false;
/** Binder of the recognition service */
private RecognitionServiceBinder mBinder = new RecognitionServiceBinder(this);
/**
* The current callback of an application that invoked the
+ *
* {@link RecognitionService#onStartListening(Intent, Callback)} method
*/
private Callback mCurrentCallback = null;
+ private boolean mStartedDataDelivery;
+
private static final int MSG_START_LISTENING = 1;
private static final int MSG_STOP_LISTENING = 2;
@@ -120,6 +118,11 @@ public abstract class RecognitionService extends Service {
mCurrentCallback = new Callback(listener, attributionSource);
RecognitionService.this.onStartListening(intent, mCurrentCallback);
+ if (!checkPermissionAndStartDataDelivery()) {
+ listener.onError(SpeechRecognizer.ERROR_INSUFFICIENT_PERMISSIONS);
+ Log.i(TAG, "caller doesn't have permission:"
+ + Manifest.permission.RECORD_AUDIO);
+ }
} else {
listener.onError(SpeechRecognizer.ERROR_RECOGNIZER_BUSY);
Log.i(TAG, "concurrent startListening received - ignoring this call");
@@ -152,13 +155,15 @@ public abstract class RecognitionService extends Service {
Log.w(TAG, "cancel called by client who did not call startListening - ignoring");
} else { // the correct state
RecognitionService.this.onCancel(mCurrentCallback);
- mCurrentCallback = null;
+ dispatchClearCallback();
if (DBG) Log.d(TAG, "canceling - setting mCurrentCallback to null");
}
}
private void dispatchClearCallback() {
+ finishDataDelivery();
mCurrentCallback = null;
+ mStartedDataDelivery = false;
}
private class StartListeningArgs {
@@ -177,7 +182,30 @@ public abstract class RecognitionService extends Service {
/**
* Notifies the service that it should start listening for speech.
- *
+ *
+ * <p> If you are recognizing speech from the microphone, in this callback you
+ * should create an attribution context for the caller such that when you access
+ * the mic the caller would be properly blamed (and their permission checked in
+ * the process) for accessing the microphone and that you served as a proxy for
+ * this sensitive data (and your permissions would be checked in the process).
+ * You should also open the mic in this callback via the attribution context
+ * and close the mic before returning the recognized result. If you don't do
+ * that then the caller would be blamed and you as being a proxy as well as you
+ * would get one more blame on yourself when you open the microphone.
+ *
+ * <pre>
+ * Context attributionContext = context.createContext(new ContextParams.Builder()
+ * .setNextAttributionSource(callback.getCallingAttributionSource())
+ * .build());
+ *
+ * AudioRecord recorder = AudioRecord.Builder()
+ * .setContext(attributionContext);
+ * . . .
+ * .build();
+ *
+ * recorder.startRecording()
+ * </pre>
+ *
* @param recognizerIntent contains parameters for the recognition to be performed. The intent
* may also contain optional extras, see {@link RecognizerIntent}. If these values are
* not set explicitly, default values should be used by the recognizer.
@@ -335,57 +363,13 @@ public abstract class RecognitionService extends Service {
return mCallingAttributionSource;
}
- boolean maybeStartAttribution() {
- if (DBG) {
- Log.i(TAG, "Starting attribution");
- }
-
- if (DBG && isProxyingRecordAudioToCaller()) {
- Log.i(TAG, "Proxying already in progress, not starting the attribution");
- }
-
- if (!isProxyingRecordAudioToCaller()) {
+ @NonNull Context getAttributionContextForCaller() {
+ if (mAttributionContext == null) {
mAttributionContext = createContext(new ContextParams.Builder()
.setNextAttributionSource(mCallingAttributionSource)
.build());
-
- final int result = PermissionChecker.checkPermissionAndStartDataDelivery(
- RecognitionService.this,
- Manifest.permission.RECORD_AUDIO,
- mAttributionContext.getAttributionSource(),
- /*message*/ null);
-
- return result == PermissionChecker.PERMISSION_GRANTED;
- }
- return false;
- }
-
- void maybeFinishAttribution() {
- if (DBG) {
- Log.i(TAG, "Finishing attribution");
- }
-
- if (DBG && !isProxyingRecordAudioToCaller()) {
- Log.i(TAG, "Not proxying currently, not finishing the attribution");
- }
-
- if (isProxyingRecordAudioToCaller()) {
- PermissionChecker.finishDataDelivery(
- RecognitionService.this,
- RECORD_AUDIO_APP_OP,
- mAttributionContext.getAttributionSource());
-
- mAttributionContext = null;
}
- }
-
- private boolean isProxyingRecordAudioToCaller() {
- final AppOpsManager appOpsManager = getSystemService(AppOpsManager.class);
- return appOpsManager.isProxying(
- RECORD_AUDIO_APP_OP_CODE,
- getAttributionTag(),
- mCallingAttributionSource.getUid(),
- mCallingAttributionSource.getPackageName());
+ return mAttributionContext;
}
}
@@ -435,4 +419,35 @@ public abstract class RecognitionService extends Service {
mServiceRef.clear();
}
}
+
+ private boolean checkPermissionAndStartDataDelivery() {
+ if (isPerformingDataDelivery()) {
+ return true;
+ }
+ if (PermissionChecker.checkPermissionAndStartDataDelivery(
+ RecognitionService.this, Manifest.permission.RECORD_AUDIO,
+ mCurrentCallback.getAttributionContextForCaller().getAttributionSource(),
+ /*message*/ null) == PermissionChecker.PERMISSION_GRANTED) {
+ mStartedDataDelivery = true;
+ }
+ return mStartedDataDelivery;
+ }
+
+ void finishDataDelivery() {
+ if (mStartedDataDelivery) {
+ mStartedDataDelivery = false;
+ final String op = AppOpsManager.permissionToOp(Manifest.permission.RECORD_AUDIO);
+ PermissionChecker.finishDataDelivery(RecognitionService.this, op,
+ mCurrentCallback.getAttributionContextForCaller().getAttributionSource());
+ }
+ }
+
+ @SuppressWarnings("ConstantCondition")
+ private boolean isPerformingDataDelivery() {
+ final int op = AppOpsManager.permissionToOpCode(Manifest.permission.RECORD_AUDIO);
+ final AppOpsManager appOpsManager = getSystemService(AppOpsManager.class);
+ return appOpsManager.isProxying(op, getAttributionTag(),
+ mCurrentCallback.getCallingAttributionSource().getUid(),
+ mCurrentCallback.getCallingAttributionSource().getPackageName());
+ }
}
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index ce649cc7c2b2..7bad5cbfbdc3 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -267,20 +267,6 @@ interface IWindowSession {
oneway void updatePointerIcon(IWindow window);
/**
- * Reparent the top layers for a display to the requested SurfaceControl. The display that is
- * going to be re-parented (the displayId passed in) needs to have been created by the same
- * process that is requesting the re-parent. This is to ensure clients can't just re-parent
- * display content info to any SurfaceControl, as this would be a security issue.
- *
- * @param window The window which owns the SurfaceControl. This indicates the z-order of the
- * windows of this display against the windows on the parent display.
- * @param sc The SurfaceControl that the top level layers for the display should be re-parented
- * to.
- * @param displayId The id of the display to be re-parented.
- */
- oneway void reparentDisplayContent(IWindow window, in SurfaceControl sc, int displayId);
-
- /**
* Update the location of a child display in its parent window. This enables windows in the
* child display to compute the global transformation matrix.
*
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 45c49352afff..f34cd8f9de50 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -34,7 +34,6 @@ import android.annotation.Size;
import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Bitmap;
-import android.graphics.BLASTBufferQueue;
import android.graphics.ColorSpace;
import android.graphics.GraphicBuffer;
import android.graphics.Matrix;
@@ -647,6 +646,12 @@ public final class SurfaceControl implements Parcelable {
public static final int METADATA_OWNER_PID = 6;
/**
+ * game mode for the layer - used for metrics
+ * @hide
+ */
+ public static final int METADATA_GAME_MODE = 8;
+
+ /**
* A wrapper around HardwareBuffer that contains extra information about how to
* interpret the screenshot HardwareBuffer.
*
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index afd6878da429..67cf85cee9ac 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -2783,7 +2783,7 @@ public final class ViewRootImpl implements ViewParent,
& WindowManagerGlobal.RELAYOUT_RES_DRAG_RESIZING_DOCKED) != 0;
final boolean dragResizing = freeformResizing || dockedResizing;
if (mSurfaceControl.isValid()) {
- updateOpacity(params, dragResizing);
+ updateOpacity(mWindowAttributes, dragResizing);
}
if (DEBUG_LAYOUT) Log.v(mTag, "relayout: frame=" + frame.toShortString()
@@ -7749,9 +7749,10 @@ public final class ViewRootImpl implements ViewParent,
return relayoutResult;
}
- private void updateOpacity(@Nullable WindowManager.LayoutParams params, boolean dragResizing) {
+ private void updateOpacity(WindowManager.LayoutParams params, boolean dragResizing) {
boolean opaque = false;
- if (params != null && !PixelFormat.formatHasAlpha(params.format)
+
+ if (!PixelFormat.formatHasAlpha(params.format)
// Don't make surface with surfaceInsets opaque as they display a
// translucent shadow.
&& params.surfaceInsets.left == 0
diff --git a/core/java/android/view/WindowlessWindowManager.java b/core/java/android/view/WindowlessWindowManager.java
index 72d403e1f867..ae54f51f35d1 100644
--- a/core/java/android/view/WindowlessWindowManager.java
+++ b/core/java/android/view/WindowlessWindowManager.java
@@ -444,11 +444,6 @@ public class WindowlessWindowManager implements IWindowSession {
}
@Override
- public void reparentDisplayContent(android.view.IWindow window, android.view.SurfaceControl sc,
- int displayId) {
- }
-
- @Override
public void updateDisplayContentLocation(android.view.IWindow window, int x, int y,
int displayId) {
}
diff --git a/core/java/android/widget/EdgeEffect.java b/core/java/android/widget/EdgeEffect.java
index 207385d12d90..f2827f3fec73 100644
--- a/core/java/android/widget/EdgeEffect.java
+++ b/core/java/android/widget/EdgeEffect.java
@@ -16,6 +16,7 @@
package android.widget;
+import android.animation.ValueAnimator;
import android.annotation.ColorInt;
import android.annotation.IntDef;
import android.annotation.NonNull;
@@ -76,6 +77,11 @@ public class EdgeEffect {
public static final BlendMode DEFAULT_BLEND_MODE = BlendMode.SRC_ATOP;
/**
+ * Completely disable edge effect
+ */
+ private static final int TYPE_NONE = -1;
+
+ /**
* Use a color edge glow for the edge effect.
*/
private static final int TYPE_GLOW = 0;
@@ -114,7 +120,7 @@ public class EdgeEffect {
private static final float ON_ABSORB_VELOCITY_ADJUSTMENT = 13f;
/** @hide */
- @IntDef({TYPE_GLOW, TYPE_STRETCH})
+ @IntDef({TYPE_NONE, TYPE_GLOW, TYPE_STRETCH})
@Retention(RetentionPolicy.SOURCE)
public @interface EdgeEffectType {
}
@@ -195,6 +201,12 @@ public class EdgeEffect {
private float mBaseGlowScale;
private float mDisplacement = 0.5f;
private float mTargetDisplacement = 0.5f;
+
+ /**
+ * Current edge effect type, consumers should always query
+ * {@link #getCurrentEdgeEffectBehavior()} instead of this parameter
+ * directly in case animations have been disabled (ex. for accessibility reasons)
+ */
private @EdgeEffectType int mEdgeEffectType = TYPE_GLOW;
private Matrix mTmpMatrix = null;
private float[] mTmpPoints = null;
@@ -227,6 +239,15 @@ public class EdgeEffect {
mPaint.setBlendMode(DEFAULT_BLEND_MODE);
}
+ @EdgeEffectType
+ private int getCurrentEdgeEffectBehavior() {
+ if (!ValueAnimator.areAnimatorsEnabled()) {
+ return TYPE_NONE;
+ } else {
+ return mEdgeEffectType;
+ }
+ }
+
/**
* Set the size of this edge effect in pixels.
*
@@ -302,14 +323,19 @@ public class EdgeEffect {
* Values may be from 0-1.
*/
public void onPull(float deltaDistance, float displacement) {
+ int edgeEffectBehavior = getCurrentEdgeEffectBehavior();
+ if (edgeEffectBehavior == TYPE_NONE) {
+ finish();
+ return;
+ }
final long now = AnimationUtils.currentAnimationTimeMillis();
mTargetDisplacement = displacement;
if (mState == STATE_PULL_DECAY && now - mStartTime < mDuration
- && mEdgeEffectType == TYPE_GLOW) {
+ && edgeEffectBehavior == TYPE_GLOW) {
return;
}
if (mState != STATE_PULL) {
- if (mEdgeEffectType == TYPE_STRETCH) {
+ if (edgeEffectBehavior == TYPE_STRETCH) {
// Restore the mPullDistance to the fraction it is currently showing -- we want
// to "catch" the current stretch value.
mPullDistance = mDistance;
@@ -342,7 +368,7 @@ public class EdgeEffect {
mGlowAlphaFinish = mGlowAlpha;
mGlowScaleYFinish = mGlowScaleY;
- if (mEdgeEffectType == TYPE_STRETCH && mDistance == 0) {
+ if (edgeEffectBehavior == TYPE_STRETCH && mDistance == 0) {
mState = STATE_IDLE;
}
}
@@ -377,13 +403,17 @@ public class EdgeEffect {
* 0 and <code>deltaDistance</code>.
*/
public float onPullDistance(float deltaDistance, float displacement) {
+ int edgeEffectBehavior = getCurrentEdgeEffectBehavior();
+ if (edgeEffectBehavior == TYPE_NONE) {
+ return 0f;
+ }
float finalDistance = Math.max(0f, deltaDistance + mDistance);
float delta = finalDistance - mDistance;
if (delta == 0f && mDistance == 0f) {
return 0f; // No pull, don't do anything.
}
- if (mState != STATE_PULL && mState != STATE_PULL_DECAY && mEdgeEffectType == TYPE_GLOW) {
+ if (mState != STATE_PULL && mState != STATE_PULL_DECAY && edgeEffectBehavior == TYPE_GLOW) {
// Catch the edge glow in the middle of an animation.
mPullDistance = mDistance;
mState = STATE_PULL;
@@ -442,11 +472,12 @@ public class EdgeEffect {
* @param velocity Velocity at impact in pixels per second.
*/
public void onAbsorb(int velocity) {
- if (mEdgeEffectType == TYPE_STRETCH) {
+ int edgeEffectBehavior = getCurrentEdgeEffectBehavior();
+ if (edgeEffectBehavior == TYPE_STRETCH) {
mState = STATE_RECEDE;
mVelocity = velocity * ON_ABSORB_VELOCITY_ADJUSTMENT;
mStartTime = AnimationUtils.currentAnimationTimeMillis();
- } else {
+ } else if (edgeEffectBehavior == TYPE_GLOW) {
mState = STATE_ABSORB;
mVelocity = 0;
velocity = Math.min(Math.max(MIN_VELOCITY, Math.abs(velocity)), MAX_VELOCITY);
@@ -470,6 +501,8 @@ public class EdgeEffect {
mGlowAlphaStart,
Math.min(velocity * VELOCITY_GLOW_FACTOR * .00001f, MAX_ALPHA));
mTargetDisplacement = 0.5f;
+ } else {
+ finish();
}
}
@@ -532,7 +565,8 @@ public class EdgeEffect {
* animation
*/
public boolean draw(Canvas canvas) {
- if (mEdgeEffectType == TYPE_GLOW) {
+ int edgeEffectBehavior = getCurrentEdgeEffectBehavior();
+ if (edgeEffectBehavior == TYPE_GLOW) {
update();
final int count = canvas.save();
@@ -549,7 +583,7 @@ public class EdgeEffect {
mPaint.setAlpha((int) (0xff * mGlowAlpha));
canvas.drawCircle(centerX, centerY, mRadius, mPaint);
canvas.restoreToCount(count);
- } else if (canvas instanceof RecordingCanvas) {
+ } else if (edgeEffectBehavior == TYPE_STRETCH && canvas instanceof RecordingCanvas) {
if (mState == STATE_RECEDE) {
updateSpring();
}
@@ -604,8 +638,8 @@ public class EdgeEffect {
);
}
} else {
- // This is TYPE_STRETCH and drawing into a Canvas that isn't a Recording Canvas,
- // so no effect can be shown. Just end the effect.
+ // Animations have been disabled or this is TYPE_STRETCH and drawing into a Canvas
+ // that isn't a Recording Canvas, so no effect can be shown. Just end the effect.
mState = STATE_IDLE;
mDistance = 0;
mVelocity = 0;
diff --git a/core/java/com/android/internal/app/AbstractResolverComparator.java b/core/java/com/android/internal/app/AbstractResolverComparator.java
index ea3f1b1fc04c..40ada0b2ffdc 100644
--- a/core/java/com/android/internal/app/AbstractResolverComparator.java
+++ b/core/java/com/android/internal/app/AbstractResolverComparator.java
@@ -64,6 +64,7 @@ public abstract class AbstractResolverComparator implements Comparator<ResolvedC
private static final int WATCHDOG_TIMEOUT_MILLIS = 500;
private final Comparator<ResolveInfo> mAzComparator;
+ private ChooserActivityLogger mChooserActivityLogger;
protected final Handler mHandler = new Handler(Looper.getMainLooper()) {
public void handleMessage(Message msg) {
@@ -85,6 +86,9 @@ public abstract class AbstractResolverComparator implements Comparator<ResolvedC
}
mHandler.removeMessages(RANKER_SERVICE_RESULT);
afterCompute();
+ if (mChooserActivityLogger != null) {
+ mChooserActivityLogger.logSharesheetAppShareRankingTimeout();
+ }
break;
default:
@@ -131,6 +135,14 @@ public abstract class AbstractResolverComparator implements Comparator<ResolvedC
mAfterCompute = afterCompute;
}
+ void setChooserActivityLogger(ChooserActivityLogger chooserActivityLogger) {
+ mChooserActivityLogger = chooserActivityLogger;
+ }
+
+ ChooserActivityLogger getChooserActivityLogger() {
+ return mChooserActivityLogger;
+ }
+
protected final void afterCompute() {
final AfterCompute afterCompute = mAfterCompute;
if (afterCompute != null) {
diff --git a/core/java/com/android/internal/app/AppPredictionServiceResolverComparator.java b/core/java/com/android/internal/app/AppPredictionServiceResolverComparator.java
index b76ef0fd4ed8..bc9eff04636d 100644
--- a/core/java/com/android/internal/app/AppPredictionServiceResolverComparator.java
+++ b/core/java/com/android/internal/app/AppPredictionServiceResolverComparator.java
@@ -61,17 +61,19 @@ class AppPredictionServiceResolverComparator extends AbstractResolverComparator
private ResolverRankerServiceResolverComparator mResolverRankerService;
AppPredictionServiceResolverComparator(
- Context context,
- Intent intent,
- String referrerPackage,
- AppPredictor appPredictor,
- UserHandle user) {
+ Context context,
+ Intent intent,
+ String referrerPackage,
+ AppPredictor appPredictor,
+ UserHandle user,
+ ChooserActivityLogger chooserActivityLogger) {
super(context, intent);
mContext = context;
mIntent = intent;
mAppPredictor = appPredictor;
mUser = user;
mReferrerPackage = referrerPackage;
+ setChooserActivityLogger(chooserActivityLogger);
}
@Override
@@ -116,8 +118,9 @@ class AppPredictionServiceResolverComparator extends AbstractResolverComparator
// APS for chooser is disabled. Fallback to resolver.
mResolverRankerService =
new ResolverRankerServiceResolverComparator(
- mContext, mIntent, mReferrerPackage,
- () -> mHandler.sendEmptyMessage(RANKER_SERVICE_RESULT));
+ mContext, mIntent, mReferrerPackage,
+ () -> mHandler.sendEmptyMessage(RANKER_SERVICE_RESULT),
+ getChooserActivityLogger());
mResolverRankerService.compute(targets);
} else {
Log.i(TAG, "AppPredictionService response received");
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 28c2774cabb0..08db74f5e351 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -2591,7 +2591,8 @@ public class ChooserActivity extends ResolverActivity implements
boolean filterLastUsed, ResolverListController resolverListController) {
return new ChooserListAdapter(context, payloadIntents, initialIntents, rList,
filterLastUsed, resolverListController, this,
- this, context.getPackageManager());
+ this, context.getPackageManager(),
+ getChooserActivityLogger());
}
@VisibleForTesting
@@ -2600,11 +2601,11 @@ public class ChooserActivity extends ResolverActivity implements
AbstractResolverComparator resolverComparator;
if (appPredictor != null) {
resolverComparator = new AppPredictionServiceResolverComparator(this, getTargetIntent(),
- getReferrerPackageName(), appPredictor, userHandle);
+ getReferrerPackageName(), appPredictor, userHandle, getChooserActivityLogger());
} else {
resolverComparator =
new ResolverRankerServiceResolverComparator(this, getTargetIntent(),
- getReferrerPackageName(), null);
+ getReferrerPackageName(), null, getChooserActivityLogger());
}
return new ChooserListController(
diff --git a/core/java/com/android/internal/app/ChooserActivityLogger.java b/core/java/com/android/internal/app/ChooserActivityLogger.java
index 47d83346d038..321730786471 100644
--- a/core/java/com/android/internal/app/ChooserActivityLogger.java
+++ b/core/java/com/android/internal/app/ChooserActivityLogger.java
@@ -75,6 +75,20 @@ public interface ChooserActivityLogger {
}
/**
+ * Logs a UiEventReported event for the system sharesheet app share ranking timing out.
+ */
+ default void logSharesheetAppShareRankingTimeout() {
+ log(SharesheetStandardEvent.SHARESHEET_APP_SHARE_RANKING_TIMEOUT, getInstanceId());
+ }
+
+ /**
+ * Logs a UiEventReported event for the system sharesheet when direct share row is empty.
+ */
+ default void logSharesheetEmptyDirectShareRow() {
+ log(SharesheetStandardEvent.SHARESHEET_EMPTY_DIRECT_SHARE_ROW, getInstanceId());
+ }
+
+ /**
* Logs a UiEventReported event for a given share activity
* @param event
* @param instanceId
@@ -168,7 +182,11 @@ public interface ChooserActivityLogger {
@UiEvent(doc = "Sharesheet direct targets is fully populated.")
SHARESHEET_DIRECT_LOAD_COMPLETE(323),
@UiEvent(doc = "Sharesheet direct targets timed out.")
- SHARESHEET_DIRECT_LOAD_TIMEOUT(324);
+ SHARESHEET_DIRECT_LOAD_TIMEOUT(324),
+ @UiEvent(doc = "Sharesheet app share ranking timed out.")
+ SHARESHEET_APP_SHARE_RANKING_TIMEOUT(831),
+ @UiEvent(doc = "Sharesheet empty direct share row.")
+ SHARESHEET_EMPTY_DIRECT_SHARE_ROW(828);
private final int mId;
SharesheetStandardEvent(int id) {
diff --git a/core/java/com/android/internal/app/ChooserListAdapter.java b/core/java/com/android/internal/app/ChooserListAdapter.java
index cc2b12a99d79..87737ca9c3af 100644
--- a/core/java/com/android/internal/app/ChooserListAdapter.java
+++ b/core/java/com/android/internal/app/ChooserListAdapter.java
@@ -79,6 +79,7 @@ public class ChooserListAdapter extends ResolverListAdapter {
private final ChooserListCommunicator mChooserListCommunicator;
private final SelectableTargetInfo.SelectableTargetInfoCommunicator
mSelectableTargetInfoCommunicator;
+ private final ChooserActivityLogger mChooserActivityLogger;
private int mNumShortcutResults = 0;
private Map<DisplayResolveInfo, LoadIconTask> mIconLoaders = new HashMap<>();
@@ -104,7 +105,8 @@ public class ChooserListAdapter extends ResolverListAdapter {
boolean filterLastUsed, ResolverListController resolverListController,
ChooserListCommunicator chooserListCommunicator,
SelectableTargetInfo.SelectableTargetInfoCommunicator selectableTargetInfoCommunicator,
- PackageManager packageManager) {
+ PackageManager packageManager,
+ ChooserActivityLogger chooserActivityLogger) {
// Don't send the initial intents through the shared ResolverActivity path,
// we want to separate them into a different section.
super(context, payloadIntents, null, rList, filterLastUsed,
@@ -115,6 +117,7 @@ public class ChooserListAdapter extends ResolverListAdapter {
mChooserListCommunicator = chooserListCommunicator;
createPlaceHolders();
mSelectableTargetInfoCommunicator = selectableTargetInfoCommunicator;
+ mChooserActivityLogger = chooserActivityLogger;
if (initialIntents != null) {
for (int i = 0; i < initialIntents.length; i++) {
@@ -590,6 +593,7 @@ public class ChooserListAdapter extends ResolverListAdapter {
mServiceTargets.removeIf(o -> o instanceof ChooserActivity.PlaceHolderTargetInfo);
if (mServiceTargets.isEmpty()) {
mServiceTargets.add(new ChooserActivity.EmptyTargetInfo());
+ mChooserActivityLogger.logSharesheetEmptyDirectShareRow();
}
notifyDataSetChanged();
}
diff --git a/core/java/com/android/internal/app/IAppOpsActiveCallback.aidl b/core/java/com/android/internal/app/IAppOpsActiveCallback.aidl
index 510af770d126..ae6ad326e7b1 100644
--- a/core/java/com/android/internal/app/IAppOpsActiveCallback.aidl
+++ b/core/java/com/android/internal/app/IAppOpsActiveCallback.aidl
@@ -18,5 +18,6 @@ package com.android.internal.app;
// Iterface to observe op active changes
oneway interface IAppOpsActiveCallback {
- void opActiveChanged(int op, int uid, String packageName, boolean active);
+ void opActiveChanged(int op, int uid, String packageName, String attributionTag,
+ boolean active, int attributionFlags, int attributionChainId);
}
diff --git a/core/java/com/android/internal/app/IAppOpsService.aidl b/core/java/com/android/internal/app/IAppOpsService.aidl
index c112d09d40e4..9ad457200700 100644
--- a/core/java/com/android/internal/app/IAppOpsService.aidl
+++ b/core/java/com/android/internal/app/IAppOpsService.aidl
@@ -41,7 +41,8 @@ interface IAppOpsService {
boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage);
SyncNotedAppOp startOperation(IBinder clientId, int code, int uid, String packageName,
@nullable String attributionTag, boolean startIfModeDefault,
- boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage);
+ boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage,
+ int attributionFlags, int attributionChainId);
@UnsupportedAppUsage
void finishOperation(IBinder clientId, int code, int uid, String packageName,
@nullable String attributionTag);
@@ -57,10 +58,12 @@ interface IAppOpsService {
SyncNotedAppOp noteProxyOperation(int code, in AttributionSource attributionSource,
boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage,
boolean skipProxyOperation);
- SyncNotedAppOp startProxyOperation(IBinder clientId, int code, in AttributionSource attributionSource,
+ SyncNotedAppOp startProxyOperation(int code, in AttributionSource attributionSource,
boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp, String message,
- boolean shouldCollectMessage, boolean skipProxyOperation);
- void finishProxyOperation(IBinder clientId, int code, in AttributionSource attributionSource);
+ boolean shouldCollectMessage, boolean skipProxyOperation, int proxyAttributionFlags,
+ int proxiedAttributionFlags, int attributionChainId);
+ void finishProxyOperation(int code, in AttributionSource attributionSource,
+ boolean skipProxyOperation);
// Remaining methods are only used in Java.
int checkPackage(int uid, String packageName);
diff --git a/core/java/com/android/internal/app/ResolverListController.java b/core/java/com/android/internal/app/ResolverListController.java
index 2b59907cf86b..10ac1bc6ac3d 100644
--- a/core/java/com/android/internal/app/ResolverListController.java
+++ b/core/java/com/android/internal/app/ResolverListController.java
@@ -70,7 +70,7 @@ public class ResolverListController {
UserHandle userHandle) {
this(context, pm, targetIntent, referrerPackage, launchedFromUid, userHandle,
new ResolverRankerServiceResolverComparator(
- context, targetIntent, referrerPackage, null));
+ context, targetIntent, referrerPackage, null, null));
}
public ResolverListController(
diff --git a/core/java/com/android/internal/app/ResolverRankerServiceResolverComparator.java b/core/java/com/android/internal/app/ResolverRankerServiceResolverComparator.java
index 286945037ab7..cb946c0dcf99 100644
--- a/core/java/com/android/internal/app/ResolverRankerServiceResolverComparator.java
+++ b/core/java/com/android/internal/app/ResolverRankerServiceResolverComparator.java
@@ -85,7 +85,8 @@ class ResolverRankerServiceResolverComparator extends AbstractResolverComparator
private CountDownLatch mConnectSignal;
public ResolverRankerServiceResolverComparator(Context context, Intent intent,
- String referrerPackage, AfterCompute afterCompute) {
+ String referrerPackage, AfterCompute afterCompute,
+ ChooserActivityLogger chooserActivityLogger) {
super(context, intent);
mCollator = Collator.getInstance(context.getResources().getConfiguration().locale);
mReferrerPackage = referrerPackage;
@@ -97,6 +98,7 @@ class ResolverRankerServiceResolverComparator extends AbstractResolverComparator
mAction = intent.getAction();
mRankerServiceName = new ComponentName(mContext, this.getClass());
setCallBack(afterCompute);
+ setChooserActivityLogger(chooserActivityLogger);
}
@Override
diff --git a/core/java/com/android/internal/content/F2fsUtils.java b/core/java/com/android/internal/content/F2fsUtils.java
new file mode 100644
index 000000000000..27f1b308ed9c
--- /dev/null
+++ b/core/java/com/android/internal/content/F2fsUtils.java
@@ -0,0 +1,296 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.content;
+
+import android.annotation.NonNull;
+import android.content.ContentResolver;
+import android.os.Environment;
+import android.os.incremental.IncrementalManager;
+import android.provider.Settings.Secure;
+import android.text.TextUtils;
+import android.util.Slog;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Utility methods to work with the f2fs file system.
+ */
+public final class F2fsUtils {
+ private static final String TAG = "F2fsUtils";
+ private static final boolean DEBUG_F2FS = false;
+
+ /** Directory containing kernel features */
+ private static final File sKernelFeatures =
+ new File("/sys/fs/f2fs/features");
+ /** File containing features enabled on "/data" */
+ private static final File sUserDataFeatures =
+ new File("/dev/sys/fs/by-name/userdata/features");
+ private static final File sDataDirectory = Environment.getDataDirectory();
+ /** Name of the compression feature */
+ private static final String COMPRESSION_FEATURE = "compression";
+
+ private static final boolean sKernelCompressionAvailable;
+ private static final boolean sUserDataCompressionAvailable;
+
+ static {
+ sKernelCompressionAvailable = isCompressionEnabledInKernel();
+ if (!sKernelCompressionAvailable) {
+ if (DEBUG_F2FS) {
+ Slog.d(TAG, "f2fs compression DISABLED; feature not part of the kernel");
+ }
+ }
+ sUserDataCompressionAvailable = isCompressionEnabledOnUserData();
+ if (!sUserDataCompressionAvailable) {
+ if (DEBUG_F2FS) {
+ Slog.d(TAG, "f2fs compression DISABLED; feature not enabled on filesystem");
+ }
+ }
+ }
+
+ /**
+ * Releases compressed blocks from eligible installation artifacts.
+ * <p>
+ * Modern f2fs implementations starting in {@code S} support compression
+ * natively within the file system. The data blocks of specific installation
+ * artifacts [eg. .apk, .so, ...] can be compressed at the file system level,
+ * making them look and act like any other uncompressed file, but consuming
+ * a fraction of the space.
+ * <p>
+ * However, the unused space is not free'd automatically. Instead, we must
+ * manually tell the file system to release the extra blocks [the delta between
+ * the compressed and uncompressed block counts] back to the free pool.
+ * <p>
+ * Because of how compression works within the file system, once the blocks
+ * have been released, the file becomes read-only and cannot be modified until
+ * the free'd blocks have again been reserved from the free pool.
+ */
+ public static void releaseCompressedBlocks(ContentResolver resolver, File file) {
+ if (!sKernelCompressionAvailable || !sUserDataCompressionAvailable) {
+ return;
+ }
+
+ // NOTE: Retrieving this setting means we need to delay releasing cblocks
+ // of any APKs installed during the PackageManagerService constructor. Instead
+ // of being able to release them in the constructor, they can only be released
+ // immediately prior to the system being available. When we no longer need to
+ // read this setting, move cblock release back to the package manager constructor.
+ final boolean releaseCompressBlocks =
+ Secure.getInt(resolver, Secure.RELEASE_COMPRESS_BLOCKS_ON_INSTALL, 1) != 0;
+ if (!releaseCompressBlocks) {
+ if (DEBUG_F2FS) {
+ Slog.d(TAG, "SKIP; release compress blocks not enabled");
+ }
+ return;
+ }
+ if (!isCompressionAllowed(file)) {
+ if (DEBUG_F2FS) {
+ Slog.d(TAG, "SKIP; compression not allowed");
+ }
+ return;
+ }
+ final File[] files = getFilesToRelease(file);
+ if (files == null || files.length == 0) {
+ if (DEBUG_F2FS) {
+ Slog.d(TAG, "SKIP; no files to compress");
+ }
+ return;
+ }
+ for (int i = files.length - 1; i >= 0; --i) {
+ final long releasedBlocks = nativeReleaseCompressedBlocks(files[i].getAbsolutePath());
+ if (DEBUG_F2FS) {
+ Slog.d(TAG, "RELEASED " + releasedBlocks + " blocks"
+ + " from \"" + files[i] + "\"");
+ }
+ }
+ }
+
+ /**
+ * Returns {@code true} if compression is allowed on the file system containing
+ * the given file.
+ * <p>
+ * NOTE: The return value does not mean if the given file, or any other file
+ * on the same file system, is actually compressed. It merely determines whether
+ * not files <em>may</em> be compressed.
+ */
+ private static boolean isCompressionAllowed(@NonNull File file) {
+ final String filePath;
+ try {
+ filePath = file.getCanonicalPath();
+ } catch (IOException e) {
+ if (DEBUG_F2FS) {
+ Slog.d(TAG, "f2fs compression DISABLED; could not determine path");
+ }
+ return false;
+ }
+ if (IncrementalManager.isIncrementalPath(filePath)) {
+ if (DEBUG_F2FS) {
+ Slog.d(TAG, "f2fs compression DISABLED; file on incremental fs");
+ }
+ return false;
+ }
+ if (!isChild(sDataDirectory, filePath)) {
+ if (DEBUG_F2FS) {
+ Slog.d(TAG, "f2fs compression DISABLED; file not on /data");
+ }
+ return false;
+ }
+ if (DEBUG_F2FS) {
+ Slog.d(TAG, "f2fs compression ENABLED");
+ }
+ return true;
+ }
+
+ /**
+ * Returns {@code true} if the given child is a descendant of the base.
+ */
+ private static boolean isChild(@NonNull File base, @NonNull String childPath) {
+ try {
+ base = base.getCanonicalFile();
+
+ File parentFile = new File(childPath).getCanonicalFile();
+ while (parentFile != null) {
+ if (base.equals(parentFile)) {
+ return true;
+ }
+ parentFile = parentFile.getParentFile();
+ }
+ return false;
+ } catch (IOException ignore) {
+ return false;
+ }
+ }
+
+ /**
+ * Returns whether or not the compression feature is enabled in the kernel.
+ * <p>
+ * NOTE: This doesn't mean compression is enabled on a particular file system
+ * or any files have been compressed. Only that the functionality is enabled
+ * on the device.
+ */
+ private static boolean isCompressionEnabledInKernel() {
+ final File[] features = sKernelFeatures.listFiles();
+ if (features == null || features.length == 0) {
+ if (DEBUG_F2FS) {
+ Slog.d(TAG, "ERROR; no kernel features");
+ }
+ return false;
+ }
+ for (int i = features.length - 1; i >= 0; --i) {
+ final File feature = features[i];
+ if (COMPRESSION_FEATURE.equals(features[i].getName())) {
+ if (DEBUG_F2FS) {
+ Slog.d(TAG, "FOUND kernel compression feature");
+ }
+ return true;
+ }
+ }
+ if (DEBUG_F2FS) {
+ Slog.d(TAG, "ERROR; kernel compression feature not found");
+ }
+ return false;
+ }
+
+ /**
+ * Returns whether or not the compression feature is enabled on user data [ie. "/data"].
+ * <p>
+ * NOTE: This doesn't mean any files have been compressed. Only that the functionality
+ * is enabled on the file system.
+ */
+ private static boolean isCompressionEnabledOnUserData() {
+ if (!sUserDataFeatures.exists()
+ || !sUserDataFeatures.isFile()
+ || !sUserDataFeatures.canRead()) {
+ if (DEBUG_F2FS) {
+ Slog.d(TAG, "ERROR; filesystem features not available");
+ }
+ return false;
+ }
+ final List<String> configLines;
+ try {
+ configLines = Files.readAllLines(sUserDataFeatures.toPath());
+ } catch (IOException ignore) {
+ if (DEBUG_F2FS) {
+ Slog.d(TAG, "ERROR; couldn't read filesystem features");
+ }
+ return false;
+ }
+ if (configLines == null
+ || configLines.size() > 1
+ || TextUtils.isEmpty(configLines.get(0))) {
+ if (DEBUG_F2FS) {
+ Slog.d(TAG, "ERROR; no filesystem features");
+ }
+ return false;
+ }
+ final String[] features = configLines.get(0).split(",");
+ for (int i = features.length - 1; i >= 0; --i) {
+ if (COMPRESSION_FEATURE.equals(features[i].trim())) {
+ if (DEBUG_F2FS) {
+ Slog.d(TAG, "FOUND filesystem compression feature");
+ }
+ return true;
+ }
+ }
+ if (DEBUG_F2FS) {
+ Slog.d(TAG, "ERROR; filesystem compression feature not found");
+ }
+ return false;
+ }
+
+ /**
+ * Returns all files contained within the directory at any depth from the given path.
+ */
+ private static List<File> getFilesRecursive(@NonNull File path) {
+ final File[] allFiles = path.listFiles();
+ if (allFiles == null) {
+ return null;
+ }
+ final ArrayList<File> files = new ArrayList<>();
+ for (File f : allFiles) {
+ if (f.isDirectory()) {
+ files.addAll(getFilesRecursive(f));
+ } else if (f.isFile()) {
+ files.add(f);
+ }
+ }
+ return files;
+ }
+
+ /**
+ * Returns all files contained within the directory at any depth from the given path.
+ */
+ private static File[] getFilesToRelease(@NonNull File codePath) {
+ final List<File> files = getFilesRecursive(codePath);
+ if (files == null) {
+ if (codePath.isFile()) {
+ return new File[] { codePath };
+ }
+ return null;
+ }
+ if (files.size() == 0) {
+ return null;
+ }
+ return files.toArray(new File[files.size()]);
+ }
+
+ private static native long nativeReleaseCompressedBlocks(String path);
+
+}
diff --git a/core/java/com/android/internal/content/OWNERS b/core/java/com/android/internal/content/OWNERS
new file mode 100644
index 000000000000..c42bee69410d
--- /dev/null
+++ b/core/java/com/android/internal/content/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 36137
+include /core/java/android/content/pm/OWNERS
+
+per-file ReferrerIntent.aidl = file:/services/core/java/com/android/server/am/OWNERS
+per-file ReferrerIntent.java = file:/services/core/java/com/android/server/am/OWNERS
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index 146863342f47..314299d83020 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -84,6 +84,7 @@ cc_library_shared {
android: {
srcs: [
"AndroidRuntime.cpp",
+ "com_android_internal_content_F2fsUtils.cpp",
"com_android_internal_content_NativeLibraryHelper.cpp",
"com_google_android_gles_jni_EGLImpl.cpp",
"com_google_android_gles_jni_GLImpl.cpp", // TODO: .arm
@@ -222,7 +223,6 @@ cc_library_shared {
"fd_utils.cpp",
"android_hardware_input_InputWindowHandle.cpp",
"android_hardware_input_InputApplicationHandle.cpp",
- "permission_utils.cpp",
],
static_libs: [
@@ -241,7 +241,6 @@ cc_library_shared {
"audioflinger-aidl-cpp",
"av-types-aidl-cpp",
"android.hardware.camera.device@3.2",
- "media_permission-aidl-cpp",
"libandroidicu",
"libbpf_android",
"libnetdbpf",
@@ -258,6 +257,7 @@ cc_library_shared {
"libgraphicsenv",
"libgui",
"libmediandk",
+ "libpermission",
"libsensor",
"libinput",
"libcamera_client",
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 7e8fc7e6ba4f..00652ac99e58 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -98,7 +98,6 @@ extern int register_android_media_AudioVolumeGroupChangeHandler(JNIEnv *env);
extern int register_android_media_MicrophoneInfo(JNIEnv *env);
extern int register_android_media_ToneGenerator(JNIEnv *env);
extern int register_android_media_midi(JNIEnv *env);
-extern int register_android_media_permission_Identity(JNIEnv* env);
namespace android {
@@ -190,6 +189,7 @@ extern int register_android_content_res_ObbScanner(JNIEnv* env);
extern int register_android_content_res_Configuration(JNIEnv* env);
extern int register_android_animation_PropertyValuesHolder(JNIEnv *env);
extern int register_android_security_Scrypt(JNIEnv *env);
+extern int register_com_android_internal_content_F2fsUtils(JNIEnv* env);
extern int register_com_android_internal_content_NativeLibraryHelper(JNIEnv *env);
extern int register_com_android_internal_content_om_OverlayConfig(JNIEnv *env);
extern int register_com_android_internal_net_NetworkUtilsInternal(JNIEnv* env);
@@ -1591,7 +1591,6 @@ static const RegJNIRec gRegJNI[] = {
REG_JNI(register_android_media_RemoteDisplay),
REG_JNI(register_android_media_ToneGenerator),
REG_JNI(register_android_media_midi),
- REG_JNI(register_android_media_permission_Identity),
REG_JNI(register_android_opengl_classes),
REG_JNI(register_android_server_NetworkManagementSocketTagger),
@@ -1621,6 +1620,7 @@ static const RegJNIRec gRegJNI[] = {
REG_JNI(register_android_animation_PropertyValuesHolder),
REG_JNI(register_android_security_Scrypt),
+ REG_JNI(register_com_android_internal_content_F2fsUtils),
REG_JNI(register_com_android_internal_content_NativeLibraryHelper),
REG_JNI(register_com_android_internal_os_DmabufInfoReader),
REG_JNI(register_com_android_internal_os_FuseAppLoop),
diff --git a/core/jni/android_media_AudioRecord.cpp b/core/jni/android_media_AudioRecord.cpp
index 83dc1e0bb0d9..bce4ed78eda1 100644
--- a/core/jni/android_media_AudioRecord.cpp
+++ b/core/jni/android_media_AudioRecord.cpp
@@ -22,13 +22,15 @@
#include <jni.h>
#include <nativehelper/JNIHelp.h>
#include "core_jni_helpers.h"
-#include "permission_utils.h"
#include <utils/Log.h>
#include <media/AudioRecord.h>
#include <media/MicrophoneInfo.h>
#include <vector>
+#include <android/content/AttributionSourceState.h>
+#include <android_os_Parcel.h>
+
#include <nativehelper/ScopedUtfChars.h>
#include "android_media_AudioFormat.h"
@@ -38,10 +40,8 @@
#include "android_media_MicrophoneInfo.h"
#include "android_media_AudioAttributes.h"
-// ----------------------------------------------------------------------------
-using android::media::permission::convertIdentity;
-using android::media::permission::Identity;
+// ----------------------------------------------------------------------------
using namespace android;
@@ -189,7 +189,7 @@ static jint android_media_AudioRecord_setup(JNIEnv *env, jobject thiz, jobject w
jobject jaa, jintArray jSampleRate, jint channelMask,
jint channelIndexMask, jint audioFormat,
jint buffSizeInBytes, jintArray jSession,
- jobject jIdentity, jlong nativeRecordInJavaObj,
+ jobject jAttributionSource, jlong nativeRecordInJavaObj,
jint sharedAudioHistoryMs) {
//ALOGV(">> Entering android_media_AudioRecord_setup");
//ALOGV("sampleRate=%d, audioFormat=%d, channel mask=%x, buffSizeInBytes=%d "
@@ -260,14 +260,18 @@ static jint android_media_AudioRecord_setup(JNIEnv *env, jobject thiz, jobject w
size_t bytesPerSample = audio_bytes_per_sample(format);
if (buffSizeInBytes == 0) {
- ALOGE("Error creating AudioRecord: frameCount is 0.");
+ ALOGE("Error creating AudioRecord: frameCount is 0.");
return (jint) AUDIORECORD_ERROR_SETUP_ZEROFRAMECOUNT;
}
size_t frameSize = channelCount * bytesPerSample;
size_t frameCount = buffSizeInBytes / frameSize;
// create an uninitialized AudioRecord object
- lpRecorder = new AudioRecord(convertIdentity(env, jIdentity));
+ Parcel* parcel = parcelForJavaObject(env, jAttributionSource);
+ android::content::AttributionSourceState attributionSource;
+ attributionSource.readFromParcel(parcel);
+
+ lpRecorder = new AudioRecord(attributionSource);
// read the AudioAttributes values
auto paa = JNIAudioAttributeHelper::makeUnique();
@@ -912,7 +916,7 @@ static const JNINativeMethod gMethods[] = {
{"native_start", "(II)I", (void *)android_media_AudioRecord_start},
{"native_stop", "()V", (void *)android_media_AudioRecord_stop},
{"native_setup",
- "(Ljava/lang/Object;Ljava/lang/Object;[IIIII[ILandroid/media/permission/Identity;JI)I",
+ "(Ljava/lang/Object;Ljava/lang/Object;[IIIII[ILandroid/os/Parcel;JI)I",
(void *)android_media_AudioRecord_setup},
{"native_finalize", "()V", (void *)android_media_AudioRecord_finalize},
{"native_release", "()V", (void *)android_media_AudioRecord_release},
diff --git a/core/jni/android_media_AudioTrack.cpp b/core/jni/android_media_AudioTrack.cpp
index de5df202ba4e..73d2d8d949cd 100644
--- a/core/jni/android_media_AudioTrack.cpp
+++ b/core/jni/android_media_AudioTrack.cpp
@@ -48,7 +48,6 @@
using namespace android;
using ::android::media::VolumeShaper;
-using ::android::media::permission::Identity;
// ----------------------------------------------------------------------------
static const char* const kClassPathName = "android/media/AudioTrack";
@@ -330,9 +329,10 @@ static jint android_media_AudioTrack_setup(JNIEnv *env, jobject thiz, jobject we
// create the native AudioTrack object
ScopedUtfChars opPackageNameStr(env, opPackageName);
// TODO b/182469354: make consistent with AudioRecord
- Identity identity = Identity();
- identity.packageName = std::string(opPackageNameStr.c_str());
- lpTrack = new AudioTrack(identity);
+ AttributionSourceState attributionSource;
+ attributionSource.packageName = std::string(opPackageNameStr.c_str());
+ attributionSource.token = sp<BBinder>::make();
+ lpTrack = new AudioTrack(attributionSource);
// read the AudioAttributes values
auto paa = JNIAudioAttributeHelper::makeUnique();
@@ -395,7 +395,7 @@ static jint android_media_AudioTrack_setup(JNIEnv *env, jobject thiz, jobject we
offload ? AudioTrack::TRANSFER_SYNC_NOTIF_CALLBACK
: AudioTrack::TRANSFER_SYNC,
(offload || encapsulationMode) ? &offloadInfo : NULL,
- Identity(), // default uid, pid values
+ AttributionSourceState(), // default uid, pid values
paa.get());
break;
@@ -421,7 +421,7 @@ static jint android_media_AudioTrack_setup(JNIEnv *env, jobject thiz, jobject we
sessionId, // audio session ID
AudioTrack::TRANSFER_SHARED,
NULL, // default offloadInfo
- Identity(), // default uid, pid values
+ AttributionSourceState(), // default uid, pid values
paa.get());
break;
diff --git a/core/jni/com_android_internal_content_F2fsUtils.cpp b/core/jni/com_android_internal_content_F2fsUtils.cpp
new file mode 100644
index 000000000000..8b9d59c416a0
--- /dev/null
+++ b/core/jni/com_android_internal_content_F2fsUtils.cpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2021 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 LOG_TAG "F2fsUtils"
+
+#include "core_jni_helpers.h"
+
+#include <nativehelper/ScopedUtfChars.h>
+#include <nativehelper/jni_macros.h>
+
+#include <sys/ioctl.h>
+#include <sys/types.h>
+
+#include <linux/f2fs.h>
+#include <linux/fs.h>
+
+#include <android-base/unique_fd.h>
+
+#include <utils/Log.h>
+
+#include <errno.h>
+#include <fcntl.h>
+
+#include <array>
+
+using namespace std::literals;
+
+namespace android {
+
+static jlong com_android_internal_content_F2fsUtils_nativeReleaseCompressedBlocks(JNIEnv *env,
+ jclass clazz,
+ jstring path) {
+ unsigned long long blkcnt;
+ int ret;
+ ScopedUtfChars filePath(env, path);
+
+ android::base::unique_fd fd(open(filePath.c_str(), O_RDONLY | O_CLOEXEC, 0));
+ if (fd < 0) {
+ ALOGW("Failed to open file: %s (%d)\n", filePath.c_str(), errno);
+ return 0;
+ }
+
+ long flags = 0;
+ ret = ioctl(fd, FS_IOC_GETFLAGS, &flags);
+ if (ret < 0) {
+ ALOGW("Failed to get flags for file: %s (%d)\n", filePath.c_str(), errno);
+ return 0;
+ }
+ if ((flags & FS_COMPR_FL) == 0) {
+ return 0;
+ }
+
+ ret = ioctl(fd, F2FS_IOC_RELEASE_COMPRESS_BLOCKS, &blkcnt);
+ if (ret < 0) {
+ return -errno;
+ }
+ return blkcnt;
+}
+
+static const std::array gMethods = {
+ MAKE_JNI_NATIVE_METHOD(
+ "nativeReleaseCompressedBlocks", "(Ljava/lang/String;)J",
+ com_android_internal_content_F2fsUtils_nativeReleaseCompressedBlocks),
+};
+
+int register_com_android_internal_content_F2fsUtils(JNIEnv *env) {
+ return RegisterMethodsOrDie(env, "com/android/internal/content/F2fsUtils", gMethods.data(),
+ gMethods.size());
+}
+
+}; // namespace android
diff --git a/core/jni/permission_utils.cpp b/core/jni/permission_utils.cpp
deleted file mode 100644
index 2b7ef9999491..000000000000
--- a/core/jni/permission_utils.cpp
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2021 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.
- */
-
-#include "permission_utils.h"
-#include "core_jni_helpers.h"
-
-static struct {
- jfieldID fieldUid; // Identity.uid
- jfieldID fieldPid; // Identity.pid
- jfieldID fieldPackageName; // Identity.packageName
- jfieldID fieldAttributionTag; // Identity.attributionTag
-} javaIdentityFields;
-
-static const JNINativeMethod method_table[] = {
- // no static methods, currently
-};
-
-int register_android_media_permission_Identity(JNIEnv* env) {
- jclass identityClass = android::FindClassOrDie(env, "android/media/permission/Identity");
- javaIdentityFields.fieldUid = android::GetFieldIDOrDie(env, identityClass, "uid", "I");
- javaIdentityFields.fieldPid = android::GetFieldIDOrDie(env, identityClass, "pid", "I");
- javaIdentityFields.fieldPackageName =
- android::GetFieldIDOrDie(env, identityClass, "packageName", "Ljava/lang/String;");
- javaIdentityFields.fieldAttributionTag =
- android::GetFieldIDOrDie(env, identityClass, "attributionTag", "Ljava/lang/String;");
-
- return android::RegisterMethodsOrDie(env, "android/media/permission/Identity", method_table,
- NELEM(method_table));
-}
-
-namespace android::media::permission {
-
-Identity convertIdentity(JNIEnv* env, const jobject& jIdentity) {
- Identity identity;
-
- identity.uid = env->GetIntField(jIdentity, javaIdentityFields.fieldUid);
- identity.pid = env->GetIntField(jIdentity, javaIdentityFields.fieldPid);
-
- jstring packageNameStr = static_cast<jstring>(
- env->GetObjectField(jIdentity, javaIdentityFields.fieldPackageName));
- if (packageNameStr == nullptr) {
- identity.packageName = std::nullopt;
- } else {
- identity.packageName = std::string(ScopedUtfChars(env, packageNameStr).c_str());
- }
-
- jstring attributionTagStr = static_cast<jstring>(
- env->GetObjectField(jIdentity, javaIdentityFields.fieldAttributionTag));
- if (attributionTagStr == nullptr) {
- identity.attributionTag = std::nullopt;
- } else {
- identity.attributionTag = std::string(ScopedUtfChars(env, attributionTagStr).c_str());
- }
-
- return identity;
-}
-
-} // namespace android::media::permission
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index f457c5626fba..6b6cbea94009 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1625,16 +1625,16 @@
<eat-comment />
<!-- Allows an application to modify and remove existing voicemails in the system.
- <p>Protection level: signature|privileged
+ <p>Protection level: signature|privileged|role
-->
<permission android:name="com.android.voicemail.permission.WRITE_VOICEMAIL"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged|role" />
<!-- Allows an application to read voicemails in the system.
- <p>Protection level: signature|privileged
+ <p>Protection level: signature|privileged|role
-->
<permission android:name="com.android.voicemail.permission.READ_VOICEMAIL"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged|role" />
<!-- ======================================= -->
<!-- Permissions for accessing location info -->
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index c864cd66b117..e5f458849b9a 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1971,6 +1971,9 @@
<string name="config_systemActivityRecognizer" translatable="false"></string>
<!-- The name of the package that will hold the system ui role -->
<string name="config_systemUi" translatable="false">com.android.systemui</string>
+ <!-- The name of the package that will hold the television remote service role.
+ TODO(b/189347385) make this a @SystemAPI -->
+ <string name="config_systemTelevisionRemoteService" translatable="false">@string/config_tvRemoteServicePackage</string>
<!-- The name of the package that will be allowed to change its components' label/icon. -->
<string name="config_overrideComponentUiPackage" translatable="false">com.android.stk</string>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index d3343060a819..ea93520502d5 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -939,4 +939,8 @@
<!-- System-provided padding for inner views on app widgets. The resolved value of this resource may change at runtime. @removed -->
<dimen name="__removed_system_app_widget_internal_padding">16dp</dimen>
+ <!-- The width/height of the icon view on staring surface. -->
+ <dimen name="starting_surface_icon_size">160dp</dimen>
+ <!-- The default width/height of the icon on the spec of adaptive icon drawable. -->
+ <dimen name="starting_surface_default_icon_size">108dp</dimen>
</resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index ef5cfe33c661..2403a605972e 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -3027,222 +3027,178 @@
<public type="bool" name="config_assistantOnTopOfDream" id="0x01110005" />
<!-- @hide @TestApi -->
<public type="bool" name="config_remoteInsetsControllerControlsSystemBars" id="0x01110006" />
- <!-- ===============================================================
- Resources added in version S of the platform
-
- NOTE: add <public> elements within a <staging-public-group> like so:
- <staging-public-group type="attr" first-id="0x01010531">
- <public name="exampleAttr1" />
- <public name="exampleAttr2" />
- </staging-public-group>
-
- To add a new public-group block, choose an id value that is 1 greater
- than the last of that item above. For example, the last "attr" id
- value above is 0x01010530, so the public-group of attrs below has
- the id value of 0x01010531.
+ <!-- ===============================================================
+ Resources added in version S of the platform
=============================================================== -->
- <eat-comment />
+ <eat-comment />
- <staging-public-group type="attr" first-id="0x01010617">
- <public name="rollbackDataPolicy" />
- <public name="allowClickWhenDisabled" />
- <public name="windowLayoutAffinity" />
- <public name="canPauseRecording" />
- <public name="windowBlurBehindRadius"/>
- <public name="windowBlurBehindEnabled"/>
- <public name="requireDeviceScreenOn" />
- <public name="pathSuffix" />
- <public name="sspSuffix" />
- <public name="pathAdvancedPattern" />
- <public name="sspAdvancedPattern" />
- <public name="fontProviderSystemFontFamily" />
- <public name="hand_second" />
- <public name="memtagMode" />
- <public name="nativeHeapZeroInitialized" />
+ <public type="attr" name="rollbackDataPolicy" id="0x01010617" />
+ <public type="attr" name="allowClickWhenDisabled" id="0x01010618" />
+ <public type="attr" name="windowLayoutAffinity" id="0x01010619" />
+ <public type="attr" name="canPauseRecording" id="0x0101061a" />
+ <public type="attr" name="windowBlurBehindRadius" id="0x0101061b" />
+ <public type="attr" name="windowBlurBehindEnabled" id="0x0101061c" />
+ <public type="attr" name="requireDeviceScreenOn" id="0x0101061d" />
+ <public type="attr" name="pathSuffix" id="0x0101061e" />
+ <public type="attr" name="sspSuffix" id="0x0101061f" />
+ <public type="attr" name="pathAdvancedPattern" id="0x01010620" />
+ <public type="attr" name="sspAdvancedPattern" id="0x01010621" />
+ <public type="attr" name="fontProviderSystemFontFamily" id="0x01010622" />
+ <public type="attr" name="hand_second" id="0x01010623" />
+ <public type="attr" name="memtagMode" id="0x01010624" />
+ <public type="attr" name="nativeHeapZeroInitialized" id="0x01010625" />
<!-- @hide @SystemApi -->
- <public name="hotwordDetectionService" />
- <public name="previewLayout" />
- <public name="clipToOutline" />
- <public name="__removed3" />
- <public name="knownCerts" />
- <public name="windowBackgroundBlurRadius"/>
- <public name="windowSplashScreenBackground"/>
- <public name="windowSplashScreenAnimatedIcon"/>
- <public name="windowSplashScreenAnimationDuration"/>
- <public name="windowSplashScreenBrandingImage"/>
- <public name="windowSplashScreenIconBackgroundColor"/>
- <public name="splashScreenTheme" />
- <public name="maxResizeWidth" />
- <public name="maxResizeHeight" />
- <public name="targetCellWidth" />
- <public name="targetCellHeight" />
- <public name="dialTint"/>
- <public name="dialTintMode"/>
- <public name="hand_hourTint"/>
- <public name="hand_hourTintMode"/>
- <public name="hand_minuteTint"/>
- <public name="hand_minuteTintMode"/>
- <public name="hand_secondTint"/>
- <public name="hand_secondTintMode"/>
- <public name="dataExtractionRules"/>
- <public name="passwordsActivity"/>
- <public name="selectableAsDefault"/>
- <public name="isAccessibilityTool"/>
- <public name="attributionTags"/>
- <public name="suppressesSpellChecker" />
- <public name="usesPermissionFlags" />
- <public name="requestRawExternalStorageAccess" />
+ <public type="attr" name="hotwordDetectionService" id="0x01010626" />
+ <public type="attr" name="previewLayout" id="0x01010627" />
+ <public type="attr" name="clipToOutline" id="0x01010628" />
+ <!-- <public type="attr" name="__removed3" id="0x01010629" /> -->
+ <public type="attr" name="knownCerts" id="0x0101062a" />
+ <public type="attr" name="windowBackgroundBlurRadius" id="0x0101062b" />
+ <public type="attr" name="windowSplashScreenBackground" id="0x0101062c" />
+ <public type="attr" name="windowSplashScreenAnimatedIcon" id="0x0101062d" />
+ <public type="attr" name="windowSplashScreenAnimationDuration" id="0x0101062e" />
+ <public type="attr" name="windowSplashScreenBrandingImage" id="0x0101062f" />
+ <public type="attr" name="windowSplashScreenIconBackgroundColor" id="0x01010630" />
+ <public type="attr" name="splashScreenTheme" id="0x01010631" />
+ <public type="attr" name="maxResizeWidth" id="0x01010632" />
+ <public type="attr" name="maxResizeHeight" id="0x01010633" />
+ <public type="attr" name="targetCellWidth" id="0x01010634" />
+ <public type="attr" name="targetCellHeight" id="0x01010635" />
+ <public type="attr" name="dialTint" id="0x01010636" />
+ <public type="attr" name="dialTintMode" id="0x01010637" />
+ <public type="attr" name="hand_hourTint" id="0x01010638" />
+ <public type="attr" name="hand_hourTintMode" id="0x01010639" />
+ <public type="attr" name="hand_minuteTint" id="0x0101063a" />
+ <public type="attr" name="hand_minuteTintMode" id="0x0101063b" />
+ <public type="attr" name="hand_secondTint" id="0x0101063c" />
+ <public type="attr" name="hand_secondTintMode" id="0x0101063d" />
+ <public type="attr" name="dataExtractionRules" id="0x0101063e" />
+ <public type="attr" name="passwordsActivity" id="0x0101063f" />
+ <public type="attr" name="selectableAsDefault" id="0x01010640" />
+ <public type="attr" name="isAccessibilityTool" id="0x01010641" />
+ <public type="attr" name="attributionTags" id="0x01010642" />
+ <public type="attr" name="suppressesSpellChecker" id="0x01010643" />
+ <public type="attr" name="usesPermissionFlags" id="0x01010644" />
+ <public type="attr" name="requestRawExternalStorageAccess" id="0x01010645" />
<!-- @hide @SystemApi -->
- <public name="playHomeTransitionSound" />
- <public name="lStar" />
- <public name="showInInputMethodPicker" />
- <public name="effectColor" />
+ <public type="attr" name="playHomeTransitionSound" id="0x01010646" />
+ <public type="attr" name="lStar" id="0x01010647" />
+ <public type="attr" name="showInInputMethodPicker" id="0x01010648" />
+ <public type="attr" name="effectColor" id="0x01010649" />
<!-- @hide @TestApi -->
- <public name="requestForegroundServiceExemption" />
- <public name="attributionsAreUserVisible" />
- </staging-public-group>
-
- <staging-public-group type="drawable" first-id="0x010800b5">
- <!-- drawable definitions go here -->
- </staging-public-group>
-
- <staging-public-group type="color" first-id="0x0106001d">
- <!-- color definitions go here -->
-
- <!-- Material design dynamic system palette:-->
- <!-- Neutral colors for background and text -->
- <public name="system_neutral1_0" />
- <public name="system_neutral1_10" />
- <public name="system_neutral1_50" />
- <public name="system_neutral1_100" />
- <public name="system_neutral1_200" />
- <public name="system_neutral1_300" />
- <public name="system_neutral1_400" />
- <public name="system_neutral1_500" />
- <public name="system_neutral1_600" />
- <public name="system_neutral1_700" />
- <public name="system_neutral1_800" />
- <public name="system_neutral1_900" />
- <public name="system_neutral1_1000" />
- <public name="system_neutral2_0" />
- <public name="system_neutral2_10" />
- <public name="system_neutral2_50" />
- <public name="system_neutral2_100" />
- <public name="system_neutral2_200" />
- <public name="system_neutral2_300" />
- <public name="system_neutral2_400" />
- <public name="system_neutral2_500" />
- <public name="system_neutral2_600" />
- <public name="system_neutral2_700" />
- <public name="system_neutral2_800" />
- <public name="system_neutral2_900" />
- <public name="system_neutral2_1000" />
- <!-- Accent colors, for buttons and UI decorations -->
- <public name="system_accent1_0" />
- <public name="system_accent1_10" />
- <public name="system_accent1_50" />
- <public name="system_accent1_100" />
- <public name="system_accent1_200" />
- <public name="system_accent1_300" />
- <public name="system_accent1_400" />
- <public name="system_accent1_500" />
- <public name="system_accent1_600" />
- <public name="system_accent1_700" />
- <public name="system_accent1_800" />
- <public name="system_accent1_900" />
- <public name="system_accent1_1000" />
- <public name="system_accent2_0" />
- <public name="system_accent2_10" />
- <public name="system_accent2_50" />
- <public name="system_accent2_100" />
- <public name="system_accent2_200" />
- <public name="system_accent2_300" />
- <public name="system_accent2_400" />
- <public name="system_accent2_500" />
- <public name="system_accent2_600" />
- <public name="system_accent2_700" />
- <public name="system_accent2_800" />
- <public name="system_accent2_900" />
- <public name="system_accent2_1000" />
- <public name="system_accent3_0" />
- <public name="system_accent3_10" />
- <public name="system_accent3_50" />
- <public name="system_accent3_100" />
- <public name="system_accent3_200" />
- <public name="system_accent3_300" />
- <public name="system_accent3_400" />
- <public name="system_accent3_500" />
- <public name="system_accent3_600" />
- <public name="system_accent3_700" />
- <public name="system_accent3_800" />
- <public name="system_accent3_900" />
- <public name="system_accent3_1000" />
- </staging-public-group>
-
- <staging-public-group type="dimen" first-id="0x01050008">
- <!-- dimension definitions go here -->
-
- <!-- System-provided dimensions for app widgets. -->
- <public name="system_app_widget_background_radius" />
- <public name="system_app_widget_inner_radius" />
- <public name="__removed_system_app_widget_internal_padding" />
- </staging-public-group>
-
- <staging-public-group type="bool" first-id="0x01110007">
- <!-- boolean definitions go here -->
- </staging-public-group>
-
- <staging-public-group type="style" first-id="0x010302e5">
- <!-- style definitions go here -->
- </staging-public-group>
-
- <staging-public-group type="string" first-id="0x01040028">
+ <public type="attr" name="requestForegroundServiceExemption" id="0x0101064a" />
+ <public type="attr" name="attributionsAreUserVisible" id="0x0101064b" />
+
+ <public type="color" name="system_neutral1_0" id="0x0106001d" />
+ <public type="color" name="system_neutral1_10" id="0x0106001e" />
+ <public type="color" name="system_neutral1_50" id="0x0106001f" />
+ <public type="color" name="system_neutral1_100" id="0x01060020" />
+ <public type="color" name="system_neutral1_200" id="0x01060021" />
+ <public type="color" name="system_neutral1_300" id="0x01060022" />
+ <public type="color" name="system_neutral1_400" id="0x01060023" />
+ <public type="color" name="system_neutral1_500" id="0x01060024" />
+ <public type="color" name="system_neutral1_600" id="0x01060025" />
+ <public type="color" name="system_neutral1_700" id="0x01060026" />
+ <public type="color" name="system_neutral1_800" id="0x01060027" />
+ <public type="color" name="system_neutral1_900" id="0x01060028" />
+ <public type="color" name="system_neutral1_1000" id="0x01060029" />
+ <public type="color" name="system_neutral2_0" id="0x0106002a" />
+ <public type="color" name="system_neutral2_10" id="0x0106002b" />
+ <public type="color" name="system_neutral2_50" id="0x0106002c" />
+ <public type="color" name="system_neutral2_100" id="0x0106002d" />
+ <public type="color" name="system_neutral2_200" id="0x0106002e" />
+ <public type="color" name="system_neutral2_300" id="0x0106002f" />
+ <public type="color" name="system_neutral2_400" id="0x01060030" />
+ <public type="color" name="system_neutral2_500" id="0x01060031" />
+ <public type="color" name="system_neutral2_600" id="0x01060032" />
+ <public type="color" name="system_neutral2_700" id="0x01060033" />
+ <public type="color" name="system_neutral2_800" id="0x01060034" />
+ <public type="color" name="system_neutral2_900" id="0x01060035" />
+ <public type="color" name="system_neutral2_1000" id="0x01060036" />
+ <public type="color" name="system_accent1_0" id="0x01060037" />
+ <public type="color" name="system_accent1_10" id="0x01060038" />
+ <public type="color" name="system_accent1_50" id="0x01060039" />
+ <public type="color" name="system_accent1_100" id="0x0106003a" />
+ <public type="color" name="system_accent1_200" id="0x0106003b" />
+ <public type="color" name="system_accent1_300" id="0x0106003c" />
+ <public type="color" name="system_accent1_400" id="0x0106003d" />
+ <public type="color" name="system_accent1_500" id="0x0106003e" />
+ <public type="color" name="system_accent1_600" id="0x0106003f" />
+ <public type="color" name="system_accent1_700" id="0x01060040" />
+ <public type="color" name="system_accent1_800" id="0x01060041" />
+ <public type="color" name="system_accent1_900" id="0x01060042" />
+ <public type="color" name="system_accent1_1000" id="0x01060043" />
+ <public type="color" name="system_accent2_0" id="0x01060044" />
+ <public type="color" name="system_accent2_10" id="0x01060045" />
+ <public type="color" name="system_accent2_50" id="0x01060046" />
+ <public type="color" name="system_accent2_100" id="0x01060047" />
+ <public type="color" name="system_accent2_200" id="0x01060048" />
+ <public type="color" name="system_accent2_300" id="0x01060049" />
+ <public type="color" name="system_accent2_400" id="0x0106004a" />
+ <public type="color" name="system_accent2_500" id="0x0106004b" />
+ <public type="color" name="system_accent2_600" id="0x0106004c" />
+ <public type="color" name="system_accent2_700" id="0x0106004d" />
+ <public type="color" name="system_accent2_800" id="0x0106004e" />
+ <public type="color" name="system_accent2_900" id="0x0106004f" />
+ <public type="color" name="system_accent2_1000" id="0x01060050" />
+ <public type="color" name="system_accent3_0" id="0x01060051" />
+ <public type="color" name="system_accent3_10" id="0x01060052" />
+ <public type="color" name="system_accent3_50" id="0x01060053" />
+ <public type="color" name="system_accent3_100" id="0x01060054" />
+ <public type="color" name="system_accent3_200" id="0x01060055" />
+ <public type="color" name="system_accent3_300" id="0x01060056" />
+ <public type="color" name="system_accent3_400" id="0x01060057" />
+ <public type="color" name="system_accent3_500" id="0x01060058" />
+ <public type="color" name="system_accent3_600" id="0x01060059" />
+ <public type="color" name="system_accent3_700" id="0x0106005a" />
+ <public type="color" name="system_accent3_800" id="0x0106005b" />
+ <public type="color" name="system_accent3_900" id="0x0106005c" />
+ <public type="color" name="system_accent3_1000" id="0x0106005d" />
+
+ <public type="dimen" name="system_app_widget_background_radius" id="0x01050008" />
+ <public type="dimen" name="system_app_widget_inner_radius" id="0x01050009" />
+
<!-- @hide @SystemApi @TestApi -->
- <public name="config_systemAutomotiveCluster" />
+ <public type="string" name="config_systemAutomotiveCluster" id="0x01040028" />
<!-- @hide @SystemApi @TestApi -->
- <public name="config_systemAutomotiveProjection" />
+ <public type="string" name="config_systemAutomotiveProjection" id="0x01040029" />
<!-- @hide @SystemApi -->
- <public name="config_systemShell" />
+ <public type="string" name="config_systemShell" id="0x0104002a" />
<!-- @hide @SystemApi -->
- <public name="config_systemContacts" />
+ <public type="string" name="config_systemContacts" id="0x0104002b" />
<!-- @hide @SystemApi -->
- <public name="config_customMediaKeyDispatcher" />
+ <public type="string" name="config_customMediaKeyDispatcher" id="0x0104002c" />
<!-- @hide @SystemApi -->
- <public name="config_customMediaSessionPolicyProvider" />
+ <public type="string" name="config_customMediaSessionPolicyProvider" id="0x0104002d" />
<!-- @hide @SystemApi -->
- <public name="config_systemSpeechRecognizer" />
+ <public type="string" name="config_systemSpeechRecognizer" id="0x0104002e" />
<!-- @hide @SystemApi -->
- <public name="config_systemWifiCoexManager" />
+ <public type="string" name="config_systemWifiCoexManager" id="0x0104002f" />
<!-- @hide @SystemApi -->
- <public name="config_systemWellbeing" />
+ <public type="string" name="config_systemWellbeing" id="0x01040030" />
<!-- @hide @SystemApi -->
- <public name="config_systemTelevisionNotificationHandler" />
+ <public type="string" name="config_systemTelevisionNotificationHandler" id="0x01040031" />
<!-- @hide @SystemApi -->
- <public name="config_systemUiIntelligence" />
+ <public type="string" name="config_systemUiIntelligence" id="0x01040032" />
<!-- @hide @SystemApi -->
- <public name="config_systemAmbientAudioIntelligence" />
+ <public type="string" name="config_systemAmbientAudioIntelligence" id="0x01040033" />
<!-- @hide @SystemApi -->
- <public name="config_systemAudioIntelligence" />
+ <public type="string" name="config_systemAudioIntelligence" id="0x01040034" />
<!-- @hide @SystemApi -->
- <public name="config_systemNotificationIntelligence" />
+ <public type="string" name="config_systemNotificationIntelligence" id="0x01040035" />
<!-- @hide @SystemApi -->
- <public name="config_systemTextIntelligence" />
+ <public type="string" name="config_systemTextIntelligence" id="0x01040036" />
<!-- @hide @SystemApi -->
- <public name="config_systemVisualIntelligence" />
+ <public type="string" name="config_systemVisualIntelligence" id="0x01040037" />
<!-- @hide @SystemApi -->
- <public name="config_systemActivityRecognizer" />
+ <public type="string" name="config_systemActivityRecognizer" id="0x01040038" />
<!-- @hide @SystemApi -->
- <public name="config_systemCompanionDeviceProvider"/>
+ <public type="string" name="config_systemCompanionDeviceProvider" id="0x01040039" />
<!-- @hide @SystemApi -->
- <public name="config_systemUi" />
+ <public type="string" name="config_systemUi" id="0x0104003a" />
<!-- @hide For use by platform and tools only. Developers should not specify this value. -->
- <public name="config_defaultRingtoneVibrationSound"/>
- </staging-public-group>
-
- <staging-public-group type="id" first-id="0x01020055">
- <!-- id definitions go here -->
- </staging-public-group>
+ <public type="string" name="config_defaultRingtoneVibrationSound" id="0x0104003b" />
<!-- ===============================================================
DO NOT ADD UN-GROUPED ITEMS HERE
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index f30f40a3cfc2..374cea77f6a0 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -4389,4 +4389,7 @@
<java-symbol type="bool" name="config_supportsMicToggle" />
<java-symbol type="bool" name="config_supportsCamToggle" />
+
+ <java-symbol type="dimen" name="starting_surface_icon_size" />
+ <java-symbol type="dimen" name="starting_surface_default_icon_size" />
</resources>
diff --git a/core/res/res/values/themes_device_defaults.xml b/core/res/res/values/themes_device_defaults.xml
index 97acd5b9bf1e..9d0a42d8ecd4 100644
--- a/core/res/res/values/themes_device_defaults.xml
+++ b/core/res/res/values/themes_device_defaults.xml
@@ -232,6 +232,9 @@ easier.
<item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
+ <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item>
+ <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item>
+ <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item>
<item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
<item name="colorForeground">@color/foreground_device_default_dark</item>
<item name="colorForegroundInverse">@color/foreground_device_default_light</item>
@@ -261,6 +264,9 @@ easier.
<item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
+ <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item>
+ <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item>
+ <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item>
<item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
<item name="colorForeground">@color/foreground_device_default_dark</item>
<item name="colorForegroundInverse">@color/foreground_device_default_light</item>
@@ -307,6 +313,9 @@ easier.
<item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
+ <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item>
+ <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item>
+ <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item>
<item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
<item name="colorForeground">@color/foreground_device_default_dark</item>
<item name="colorForegroundInverse">@color/foreground_device_default_light</item>
@@ -355,6 +364,9 @@ easier.
<item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
+ <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item>
+ <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item>
+ <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item>
<item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
<item name="colorForeground">@color/foreground_device_default_dark</item>
<item name="colorForegroundInverse">@color/foreground_device_default_light</item>
@@ -402,6 +414,9 @@ easier.
<item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
+ <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item>
+ <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item>
+ <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item>
<item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
<item name="colorForeground">@color/foreground_device_default_dark</item>
<item name="colorForegroundInverse">@color/foreground_device_default_light</item>
@@ -464,6 +479,9 @@ easier.
<item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
+ <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item>
+ <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item>
+ <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item>
<item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
<item name="colorForeground">@color/foreground_device_default_dark</item>
<item name="colorForegroundInverse">@color/foreground_device_default_light</item>
@@ -503,6 +521,9 @@ easier.
<item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
+ <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item>
+ <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item>
+ <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item>
<item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
<item name="colorForeground">@color/foreground_device_default_dark</item>
<item name="colorForegroundInverse">@color/foreground_device_default_light</item>
@@ -548,6 +569,9 @@ easier.
<item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
+ <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item>
+ <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item>
+ <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item>
<item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
<item name="colorForeground">@color/foreground_device_default_dark</item>
<item name="colorForegroundInverse">@color/foreground_device_default_light</item>
@@ -594,6 +618,9 @@ easier.
<item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
+ <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item>
+ <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item>
+ <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item>
<item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
<item name="colorForeground">@color/foreground_device_default_dark</item>
<item name="colorForegroundInverse">@color/foreground_device_default_light</item>
@@ -656,6 +683,9 @@ easier.
<item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
+ <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item>
+ <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item>
+ <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item>
<item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
<item name="colorForeground">@color/foreground_device_default_dark</item>
<item name="colorForegroundInverse">@color/foreground_device_default_light</item>
@@ -703,6 +733,9 @@ easier.
<item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
+ <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item>
+ <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item>
+ <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item>
<item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
<item name="colorForeground">@color/foreground_device_default_dark</item>
<item name="colorForegroundInverse">@color/foreground_device_default_light</item>
@@ -748,6 +781,9 @@ easier.
<item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
+ <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item>
+ <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item>
+ <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item>
<item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
<item name="colorForeground">@color/foreground_device_default_dark</item>
<item name="colorForegroundInverse">@color/foreground_device_default_light</item>
@@ -795,6 +831,9 @@ easier.
<item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
+ <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item>
+ <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item>
+ <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item>
<item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
<item name="colorForeground">@color/foreground_device_default_dark</item>
<item name="colorForegroundInverse">@color/foreground_device_default_light</item>
@@ -841,6 +880,9 @@ easier.
<item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
+ <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item>
+ <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item>
+ <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item>
<item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
<item name="colorForeground">@color/foreground_device_default_dark</item>
<item name="colorForegroundInverse">@color/foreground_device_default_light</item>
@@ -887,6 +929,9 @@ easier.
<item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
+ <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item>
+ <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item>
+ <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item>
<item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
<item name="colorForeground">@color/foreground_device_default_dark</item>
<item name="colorForegroundInverse">@color/foreground_device_default_light</item>
@@ -933,6 +978,9 @@ easier.
<item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
+ <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
+ <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
+ <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
<item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
<item name="colorForeground">@color/foreground_device_default_light</item>
<item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
@@ -979,6 +1027,9 @@ easier.
<item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
+ <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
+ <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
+ <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
<item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
<item name="colorForeground">@color/foreground_device_default_light</item>
<item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
@@ -1029,6 +1080,9 @@ easier.
<item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
+ <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item>
+ <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item>
+ <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item>
<item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
<item name="colorForeground">@color/foreground_device_default_dark</item>
<item name="colorForegroundInverse">@color/foreground_device_default_light</item>
@@ -1076,6 +1130,9 @@ easier.
<item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
+ <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item>
+ <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item>
+ <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item>
<item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
<item name="colorForeground">@color/foreground_device_default_dark</item>
<item name="colorForegroundInverse">@color/foreground_device_default_light</item>
@@ -1120,6 +1177,9 @@ easier.
<item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
+ <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item>
+ <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item>
+ <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item>
<item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
<item name="colorForeground">@color/foreground_device_default_dark</item>
<item name="colorForegroundInverse">@color/foreground_device_default_light</item>
@@ -1318,6 +1378,9 @@ easier.
<item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
+ <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
+ <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
+ <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
<item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
<item name="colorForeground">@color/foreground_device_default_light</item>
<item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
@@ -1348,6 +1411,9 @@ easier.
<item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
+ <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
+ <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
+ <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
<item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
<item name="colorForeground">@color/foreground_device_default_light</item>
<item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
@@ -1393,6 +1459,9 @@ easier.
<item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
+ <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
+ <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
+ <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
<item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
<item name="colorForeground">@color/foreground_device_default_light</item>
<item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
@@ -1439,6 +1508,9 @@ easier.
<item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
+ <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
+ <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
+ <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
<item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
<item name="colorForeground">@color/foreground_device_default_light</item>
<item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
@@ -1487,6 +1559,9 @@ easier.
<item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
+ <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
+ <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
+ <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
<item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
<item name="colorForeground">@color/foreground_device_default_light</item>
<item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
@@ -1534,6 +1609,9 @@ easier.
<item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
+ <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
+ <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
+ <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
<item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
<item name="colorForeground">@color/foreground_device_default_light</item>
<item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
@@ -1598,6 +1676,9 @@ easier.
<item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
+ <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
+ <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
+ <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
<item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
<item name="colorForeground">@color/foreground_device_default_light</item>
<item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
@@ -1636,6 +1717,9 @@ easier.
<item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
+ <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
+ <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
+ <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
<item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
<item name="colorForeground">@color/foreground_device_default_light</item>
<item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
@@ -1684,6 +1768,9 @@ easier.
<item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
+ <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
+ <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
+ <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
<item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
<item name="colorForeground">@color/foreground_device_default_light</item>
<item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
@@ -1733,6 +1820,9 @@ easier.
<item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
+ <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
+ <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
+ <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
<item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
<item name="colorForeground">@color/foreground_device_default_light</item>
<item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
@@ -1781,6 +1871,9 @@ easier.
<item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
+ <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
+ <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
+ <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
<item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
<item name="colorForeground">@color/foreground_device_default_light</item>
<item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
@@ -1811,6 +1904,9 @@ easier.
<item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
+ <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
+ <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
+ <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
<item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
<item name="colorForeground">@color/foreground_device_default_light</item>
<item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
@@ -1842,6 +1938,9 @@ easier.
<item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
+ <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
+ <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
+ <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
<item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
<item name="colorForeground">@color/foreground_device_default_light</item>
<item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
@@ -1892,6 +1991,9 @@ easier.
<item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
+ <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
+ <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
+ <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
<item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
<item name="colorForeground">@color/foreground_device_default_light</item>
<item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
@@ -1940,6 +2042,9 @@ easier.
<item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
+ <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
+ <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
+ <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
<item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
<item name="colorForeground">@color/foreground_device_default_light</item>
<item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
@@ -1987,6 +2092,9 @@ easier.
<item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
+ <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
+ <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
+ <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
<item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
<item name="colorForeground">@color/foreground_device_default_light</item>
<item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
@@ -2033,6 +2141,9 @@ easier.
<item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
+ <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
+ <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
+ <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
<item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
<item name="colorForeground">@color/foreground_device_default_light</item>
<item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
@@ -2079,6 +2190,9 @@ easier.
<item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
+ <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
+ <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
+ <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
<item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
<item name="colorForeground">@color/foreground_device_default_light</item>
<item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
@@ -2123,6 +2237,9 @@ easier.
<item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
+ <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
+ <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
+ <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
<item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
<item name="colorForeground">@color/foreground_device_default_light</item>
<item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
@@ -2285,6 +2402,9 @@ easier.
<item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
+ <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item>
+ <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item>
+ <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item>
<item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
<item name="colorForeground">@color/foreground_device_default_dark</item>
<item name="colorForegroundInverse">@color/foreground_device_default_light</item>
@@ -2330,6 +2450,9 @@ easier.
<item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
+ <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
+ <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
+ <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
<item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
<item name="colorForeground">@color/foreground_device_default_light</item>
<item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
@@ -2385,6 +2508,9 @@ easier.
<item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
+ <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
+ <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
+ <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
<item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
<item name="colorForeground">@color/foreground_device_default_light</item>
<item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
@@ -2433,6 +2559,9 @@ easier.
<item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
+ <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
+ <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
+ <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
<item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
<item name="colorForeground">@color/foreground_device_default_light</item>
<item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
diff --git a/core/tests/coretests/src/android/os/VibrationEffectTest.java b/core/tests/coretests/src/android/os/VibrationEffectTest.java
index 009665fa1f53..6cbfffc96116 100644
--- a/core/tests/coretests/src/android/os/VibrationEffectTest.java
+++ b/core/tests/coretests/src/android/os/VibrationEffectTest.java
@@ -102,7 +102,9 @@ public class VibrationEffectTest {
assertThrows(IllegalArgumentException.class,
() -> VibrationEffect.createOneShot(1, -2).validate());
assertThrows(IllegalArgumentException.class,
- () -> VibrationEffect.createOneShot(1, 256).validate());
+ () -> VibrationEffect.createOneShot(1, 0).validate());
+ assertThrows(IllegalArgumentException.class,
+ () -> VibrationEffect.createOneShot(-1, 255).validate());
}
@Test
@@ -117,6 +119,7 @@ public class VibrationEffectTest {
@Test
public void testValidateWaveform() {
VibrationEffect.createWaveform(TEST_TIMINGS, TEST_AMPLITUDES, -1).validate();
+ VibrationEffect.createWaveform(new long[]{10, 10}, new int[] {0, 0}, -1).validate();
VibrationEffect.createWaveform(TEST_TIMINGS, TEST_AMPLITUDES, 0).validate();
VibrationEffect.startWaveform()
.addStep(/* amplitude= */ 1, /* duration= */ 10)
diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
index 19c27639a00d..6e34a3322e35 100644
--- a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
@@ -1857,6 +1857,57 @@ public class ChooserActivityTest {
}
@Test
+ public void testEmptyDirectRowLogging() throws InterruptedException {
+ Intent sendIntent = createSendTextIntent();
+ // We need app targets for direct targets to get displayed
+ List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
+ when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
+ Mockito.anyBoolean(),
+ Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
+
+ // Start activity
+ final ChooserWrapperActivity activity = mActivityRule
+ .launchActivity(Intent.createChooser(sendIntent, null));
+
+ // Thread.sleep shouldn't be a thing in an integration test but it's
+ // necessary here because of the way the code is structured
+ Thread.sleep(3000);
+
+ assertThat("Chooser should have 2 app targets",
+ activity.getAdapter().getCount(), is(2));
+ assertThat("Chooser should have no direct targets",
+ activity.getAdapter().getSelectableServiceTargetCount(), is(0));
+
+ ChooserActivityLoggerFake logger =
+ (ChooserActivityLoggerFake) activity.getChooserActivityLogger();
+ assertThat(logger.numCalls(), is(6));
+ // first one should be SHARESHEET_TRIGGERED uievent
+ assertThat(logger.get(0).atomId, is(FrameworkStatsLog.UI_EVENT_REPORTED));
+ assertThat(logger.get(0).event.getId(),
+ is(ChooserActivityLogger.SharesheetStandardEvent.SHARESHEET_TRIGGERED.getId()));
+ // second one should be SHARESHEET_STARTED event
+ assertThat(logger.get(1).atomId, is(FrameworkStatsLog.SHARESHEET_STARTED));
+ assertThat(logger.get(1).intent, is(Intent.ACTION_SEND));
+ assertThat(logger.get(1).mimeType, is("text/plain"));
+ assertThat(logger.get(1).packageName, is("com.android.frameworks.coretests"));
+ assertThat(logger.get(1).appProvidedApp, is(0));
+ assertThat(logger.get(1).appProvidedDirect, is(0));
+ assertThat(logger.get(1).isWorkprofile, is(false));
+ assertThat(logger.get(1).previewType, is(3));
+ // third one should be SHARESHEET_APP_LOAD_COMPLETE uievent
+ assertThat(logger.get(2).atomId, is(FrameworkStatsLog.UI_EVENT_REPORTED));
+ assertThat(logger.get(2).event.getId(),
+ is(ChooserActivityLogger
+ .SharesheetStandardEvent.SHARESHEET_APP_LOAD_COMPLETE.getId()));
+ // fourth and fifth are just artifacts of test set-up
+ // sixth one should be ranking atom with SHARESHEET_EMPTY_DIRECT_SHARE_ROW event
+ assertThat(logger.get(5).atomId, is(FrameworkStatsLog.UI_EVENT_REPORTED));
+ assertThat(logger.get(5).event.getId(),
+ is(ChooserActivityLogger
+ .SharesheetStandardEvent.SHARESHEET_EMPTY_DIRECT_SHARE_ROW.getId()));
+ }
+
+ @Test
public void testCopyTextToClipboardLogging() throws Exception {
Intent sendIntent = createSendTextIntent();
List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java b/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
index 16a2fbd6465e..9fcab0923f2d 100644
--- a/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
@@ -68,7 +68,8 @@ public class ChooserWrapperActivity extends ChooserActivity {
: sOverrides.packageManager;
return new ChooserListAdapter(context, payloadIntents, initialIntents, rList,
filterLastUsed, resolverListController,
- this, this, packageManager);
+ this, this, packageManager,
+ getChooserActivityLogger());
}
ChooserListAdapter getAdapter() {
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 8d4739dbc255..99d71675ffa9 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -153,7 +153,6 @@ applications that come with the platform
<permission name="android.permission.PACKAGE_USAGE_STATS" />
<permission name="android.permission.CHANGE_COMPONENT_ENABLED_STATE" />
<permission name="android.permission.MODIFY_AUDIO_ROUTING" />
- <permission name="android.permission.GET_RUNTIME_PERMISSION_GROUP_MAPPING" />
</privapp-permissions>
<privapp-permissions package="com.android.phone">
diff --git a/libs/WindowManager/Shell/res/values/dimen.xml b/libs/WindowManager/Shell/res/values/dimen.xml
index ce8ce51b1d5e..3caff35c8a9d 100644
--- a/libs/WindowManager/Shell/res/values/dimen.xml
+++ b/libs/WindowManager/Shell/res/values/dimen.xml
@@ -180,11 +180,6 @@
individual_bubble_size + some padding. -->
<dimen name="bubble_stack_user_education_side_inset">72dp</dimen>
- <!-- The width/height of the icon view on staring surface. -->
- <dimen name="starting_surface_icon_size">160dp</dimen>
- <!-- The default width/height of the icon on the spec of adaptive icon drawable. -->
- <dimen name="default_icon_size">108dp</dimen>
-
<!-- The width/height of the size compat restart button. -->
<dimen name="size_compat_button_size">48dp</dimen>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
index 94d13eab4299..a88be3198502 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
@@ -399,6 +399,19 @@ public class ShellTaskOrganizer extends TaskOrganizer {
}
}
+ /** Helper to set int metadata on the Surface corresponding to the task id. */
+ public void setSurfaceMetadata(int taskId, int key, int value) {
+ synchronized (mLock) {
+ final TaskAppearedInfo info = mTasks.get(taskId);
+ if (info == null || info.getLeash() == null) {
+ return;
+ }
+ SurfaceControl.Transaction t = new SurfaceControl.Transaction();
+ t.setMetadata(info.getLeash(), key, value);
+ t.apply();
+ }
+ }
+
private boolean updateTaskListenerIfNeeded(RunningTaskInfo taskInfo, SurfaceControl leash,
TaskListener oldListener, TaskListener newListener) {
if (oldListener == newListener) return false;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java
index 84a9ce52ffdc..1d37a128da0c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java
@@ -124,9 +124,9 @@ public class SplashscreenContentDrawer {
private void updateDensity() {
mIconSize = mContext.getResources().getDimensionPixelSize(
- com.android.wm.shell.R.dimen.starting_surface_icon_size);
+ com.android.internal.R.dimen.starting_surface_icon_size);
mDefaultIconSize = mContext.getResources().getDimensionPixelSize(
- com.android.wm.shell.R.dimen.default_icon_size);
+ com.android.internal.R.dimen.starting_surface_default_icon_size);
mBrandingImageWidth = mContext.getResources().getDimensionPixelSize(
com.android.wm.shell.R.dimen.starting_surface_brand_image_width);
mBrandingImageHeight = mContext.getResources().getDimensionPixelSize(
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
index bdc8ff1f9882..ff91d827b280 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
@@ -29,6 +29,7 @@ import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
+import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.hardware.display.DisplayManager;
import android.os.IBinder;
@@ -215,6 +216,7 @@ public class StartingSurfaceDrawer {
WindowManager.LayoutParams.TYPE_APPLICATION_STARTING);
params.setFitInsetsSides(0);
params.setFitInsetsTypes(0);
+ params.format = PixelFormat.TRANSLUCENT;
int windowFlags = WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED
| WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
diff --git a/core/jni/permission_utils.h b/libs/WindowManager/Shell/src/com/android/wm/shell/tasksurfacehelper/TaskSurfaceHelper.java
index d625bb6ba30a..fbbd09faee9b 100644
--- a/core/jni/permission_utils.h
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/tasksurfacehelper/TaskSurfaceHelper.java
@@ -14,14 +14,13 @@
* limitations under the License.
*/
-#pragma once
+package com.android.wm.shell.tasksurfacehelper;
-#include <android/media/permission/Identity.h>
-#include <jni.h>
-
-namespace android::media::permission {
+/**
+ * Interface to communicate with a Task's SurfaceControl.
+ */
+public interface TaskSurfaceHelper {
-Identity convertIdentity(JNIEnv* env, const jobject& jIdentity);
+ /** Sets the METADATA_GAME_MODE for the layer corresponding to the task **/
+ default void setGameModeForTask(int taskId, int gameMode) {}
}
-
-int register_android_media_permission_Identity(JNIEnv* env);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/tasksurfacehelper/TaskSurfaceHelperController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/tasksurfacehelper/TaskSurfaceHelperController.java
new file mode 100644
index 000000000000..b459b9fcd0b2
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/tasksurfacehelper/TaskSurfaceHelperController.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.tasksurfacehelper;
+
+import android.view.SurfaceControl;
+
+import com.android.wm.shell.ShellTaskOrganizer;
+import com.android.wm.shell.common.ShellExecutor;
+
+/**
+ * Intermediary controller that communicates with {@link ShellTaskOrganizer} to send commands
+ * to SurfaceControl.
+ */
+public class TaskSurfaceHelperController {
+
+ private final ShellTaskOrganizer mTaskOrganizer;
+ private final ShellExecutor mMainExecutor;
+ private final TaskSurfaceHelperImpl mImpl = new TaskSurfaceHelperImpl();
+
+ public TaskSurfaceHelperController(ShellTaskOrganizer taskOrganizer,
+ ShellExecutor mainExecutor) {
+ mTaskOrganizer = taskOrganizer;
+ mMainExecutor = mainExecutor;
+ }
+
+ public TaskSurfaceHelper asTaskSurfaceHelper() {
+ return mImpl;
+ }
+
+ /**
+ * Sends a Transaction to set the game mode metadata on the
+ * corresponding SurfaceControl
+ */
+ public void setGameModeForTask(int taskId, int gameMode) {
+ mTaskOrganizer.setSurfaceMetadata(taskId, SurfaceControl.METADATA_GAME_MODE, gameMode);
+ }
+
+ private class TaskSurfaceHelperImpl implements TaskSurfaceHelper {
+ @Override
+ public void setGameModeForTask(int taskId, int gameMode) {
+ mMainExecutor.execute(() -> {
+ TaskSurfaceHelperController.this.setGameModeForTask(taskId, gameMode);
+ });
+ }
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/tasksurfacehelper/TaskSurfaceHelperControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/tasksurfacehelper/TaskSurfaceHelperControllerTest.java
new file mode 100644
index 000000000000..d6142753b48a
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/tasksurfacehelper/TaskSurfaceHelperControllerTest.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.tasksurfacehelper;
+
+import static org.mockito.Mockito.verify;
+
+import android.platform.test.annotations.Presubmit;
+import android.testing.AndroidTestingRunner;
+import android.view.SurfaceControl;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.wm.shell.ShellTaskOrganizer;
+import com.android.wm.shell.common.ShellExecutor;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@Presubmit
+@RunWith(AndroidTestingRunner.class)
+@SmallTest
+public class TaskSurfaceHelperControllerTest {
+ private TaskSurfaceHelperController mTaskSurfaceHelperController;
+ @Mock
+ private ShellTaskOrganizer mMockTaskOrganizer;
+ @Mock
+ private ShellExecutor mMockShellExecutor;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ mTaskSurfaceHelperController = new TaskSurfaceHelperController(
+ mMockTaskOrganizer, mMockShellExecutor);
+ }
+
+ @Test
+ public void testSetGameModeForTask() {
+ mTaskSurfaceHelperController.setGameModeForTask(/*taskId*/1, /*gameMode*/3);
+ verify(mMockTaskOrganizer).setSurfaceMetadata(1, SurfaceControl.METADATA_GAME_MODE, 3);
+ }
+}
diff --git a/libs/androidfw/TEST_MAPPING b/libs/androidfw/TEST_MAPPING
index 8a5c06d1eef9..9ebc9969a730 100644
--- a/libs/androidfw/TEST_MAPPING
+++ b/libs/androidfw/TEST_MAPPING
@@ -2,9 +2,6 @@
"presubmit": [
{
"name": "CtsResourcesLoaderTests"
- },
- {
- "name": "ResourcesHardeningTest"
}
]
-} \ No newline at end of file
+}
diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java
index 0d44a8580ef9..7c6ae28bdd30 100644
--- a/media/java/android/media/AudioRecord.java
+++ b/media/java/android/media/AudioRecord.java
@@ -16,8 +16,6 @@
package android.media;
-import static android.media.permission.PermissionUtil.myIdentity;
-
import android.annotation.CallbackExecutor;
import android.annotation.FloatRange;
import android.annotation.IntDef;
@@ -29,12 +27,13 @@ import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.app.ActivityThread;
import android.compat.annotation.UnsupportedAppUsage;
+import android.content.AttributionSource;
+import android.content.AttributionSource.ScopedParcelState;
import android.content.Context;
import android.media.MediaRecorder.Source;
import android.media.audiopolicy.AudioMix;
import android.media.audiopolicy.AudioPolicy;
import android.media.metrics.LogSessionId;
-import android.media.permission.Identity;
import android.media.projection.MediaProjection;
import android.os.Binder;
import android.os.Build;
@@ -42,6 +41,7 @@ import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
+import android.os.Parcel;
import android.os.PersistableBundle;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -381,7 +381,8 @@ public class AudioRecord implements AudioRouting, MicrophoneDirection,
* {@link AudioManager#AUDIO_SESSION_ID_GENERATE} if the session isn't known at construction
* time. See also {@link AudioManager#generateAudioSessionId()} to obtain a session ID before
* construction.
- * @param context An optional context to pull an attribution tag from.
+ * @param context An optional context on whose behalf the recoding is performed.
+ *
* @throws IllegalArgumentException
*/
private AudioRecord(AudioAttributes attributes, AudioFormat format, int bufferSizeInBytes,
@@ -449,10 +450,11 @@ public class AudioRecord implements AudioRouting, MicrophoneDirection,
audioBuffSizeCheck(bufferSizeInBytes);
- Identity identity = myIdentity(context);
- if (identity.packageName == null) {
+ AttributionSource attributionSource = (context != null)
+ ? context.getAttributionSource() : AttributionSource.myAttributionSource();
+ if (attributionSource.getPackageName() == null) {
// Command line utility
- identity.packageName = "uid:" + Binder.getCallingUid();
+ attributionSource = attributionSource.withPackageName("uid:" + Binder.getCallingUid());
}
int[] sampleRate = new int[] {mSampleRate};
@@ -461,14 +463,15 @@ public class AudioRecord implements AudioRouting, MicrophoneDirection,
//TODO: update native initialization when information about hardware init failure
// due to capture device already open is available.
- int initResult = native_setup(new WeakReference<AudioRecord>(this),
- mAudioAttributes, sampleRate, mChannelMask, mChannelIndexMask,
- mAudioFormat, mNativeBufferSizeInBytes,
- session, identity, 0 /*nativeRecordInJavaObj*/,
- maxSharedAudioHistoryMs);
- if (initResult != SUCCESS) {
- loge("Error code "+initResult+" when initializing native AudioRecord object.");
- return; // with mState == STATE_UNINITIALIZED
+ try (ScopedParcelState attributionSourceState = attributionSource.asScopedParcelState()) {
+ int initResult = native_setup(new WeakReference<AudioRecord>(this), mAudioAttributes,
+ sampleRate, mChannelMask, mChannelIndexMask, mAudioFormat,
+ mNativeBufferSizeInBytes, session, attributionSourceState.getParcel(),
+ 0 /*nativeRecordInJavaObj*/, maxSharedAudioHistoryMs);
+ if (initResult != SUCCESS) {
+ loge("Error code " + initResult + " when initializing native AudioRecord object.");
+ return; // with mState == STATE_UNINITIALIZED
+ }
}
mSampleRate = sampleRate[0];
@@ -512,23 +515,27 @@ public class AudioRecord implements AudioRouting, MicrophoneDirection,
*/
/* package */ void deferred_connect(long nativeRecordInJavaObj) {
if (mState != STATE_INITIALIZED) {
- int[] session = { 0 };
- int[] rates = { 0 };
+ int[] session = {0};
+ int[] rates = {0};
//TODO: update native initialization when information about hardware init failure
// due to capture device already open is available.
// Note that for this native_setup, we are providing an already created/initialized
// *Native* AudioRecord, so the attributes parameters to native_setup() are ignored.
- int initResult = native_setup(new WeakReference<AudioRecord>(this),
- null /*mAudioAttributes*/,
- rates /*mSampleRates*/,
- 0 /*mChannelMask*/,
- 0 /*mChannelIndexMask*/,
- 0 /*mAudioFormat*/,
- 0 /*mNativeBufferSizeInBytes*/,
- session,
- myIdentity(null),
- nativeRecordInJavaObj,
- 0);
+ final int initResult;
+ try (ScopedParcelState attributionSourceState = AttributionSource.myAttributionSource()
+ .asScopedParcelState()) {
+ initResult = native_setup(new WeakReference<>(this),
+ null /*mAudioAttributes*/,
+ rates /*mSampleRates*/,
+ 0 /*mChannelMask*/,
+ 0 /*mChannelIndexMask*/,
+ 0 /*mAudioFormat*/,
+ 0 /*mNativeBufferSizeInBytes*/,
+ session,
+ attributionSourceState.getParcel(),
+ nativeRecordInJavaObj,
+ 0);
+ }
if (initResult != SUCCESS) {
loge("Error code "+initResult+" when initializing native AudioRecord object.");
return; // with mState == STATE_UNINITIALIZED
@@ -620,8 +627,8 @@ public class AudioRecord implements AudioRouting, MicrophoneDirection,
/**
* Sets the context the record belongs to. This context will be used to pull information,
- * such as attribution tags, which will be associated with the AudioRecord. However, the
- * context itself will not be retained by the AudioRecord.
+ * such as {@link android.content.AttributionSource}, which will be associated with
+ * the AudioRecord. However, the context itself will not be retained by the AudioRecord.
* @param context a non-null {@link Context} instance
* @return the same Builder instance.
*/
@@ -2216,7 +2223,7 @@ public class AudioRecord implements AudioRouting, MicrophoneDirection,
//--------------------
/**
- * @deprecated Use native_setup that takes an Identity object
+ * @deprecated Use native_setup that takes an {@link AttributionSource} object
* @return
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R,
@@ -2227,18 +2234,20 @@ public class AudioRecord implements AudioRouting, MicrophoneDirection,
int[] sampleRate, int channelMask, int channelIndexMask, int audioFormat,
int buffSizeInBytes, int[] sessionId, String opPackageName,
long nativeRecordInJavaObj) {
- Identity identity = myIdentity(null);
- identity.packageName = opPackageName;
-
- return native_setup(audiorecordThis, attributes, sampleRate, channelMask, channelIndexMask,
- audioFormat, buffSizeInBytes, sessionId, identity, nativeRecordInJavaObj, 0);
+ AttributionSource attributionSource = AttributionSource.myAttributionSource()
+ .withPackageName(opPackageName);
+ try (ScopedParcelState attributionSourceState = attributionSource.asScopedParcelState()) {
+ return native_setup(audiorecordThis, attributes, sampleRate, channelMask,
+ channelIndexMask, audioFormat, buffSizeInBytes, sessionId,
+ attributionSourceState.getParcel(), nativeRecordInJavaObj, 0);
+ }
}
private native int native_setup(Object audiorecordThis,
Object /*AudioAttributes*/ attributes,
int[] sampleRate, int channelMask, int channelIndexMask, int audioFormat,
- int buffSizeInBytes, int[] sessionId, Identity identity, long nativeRecordInJavaObj,
- int maxSharedAudioHistoryMs);
+ int buffSizeInBytes, int[] sessionId, @NonNull Parcel attributionSource,
+ long nativeRecordInJavaObj, int maxSharedAudioHistoryMs);
// TODO remove: implementation calls directly into implementation of native_release()
private native void native_finalize();
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 2d8babdc9f94..4f761ba0bf6a 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -18,7 +18,6 @@ package android.media;
import static android.Manifest.permission.BIND_IMS_SERVICE;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
-import static android.media.permission.PermissionUtil.myIdentity;
import android.annotation.CallbackExecutor;
import android.annotation.IntDef;
@@ -28,6 +27,8 @@ import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.app.ActivityThread;
import android.compat.annotation.UnsupportedAppUsage;
+import android.content.AttributionSource;
+import android.content.AttributionSource.ScopedParcelState;
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.Context;
@@ -35,7 +36,6 @@ import android.content.res.AssetFileDescriptor;
import android.graphics.SurfaceTexture;
import android.media.SubtitleController.Anchor;
import android.media.SubtitleTrack.RenderingWidget;
-import android.media.permission.Identity;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
@@ -56,7 +56,6 @@ import android.provider.Settings;
import android.system.ErrnoException;
import android.system.Os;
import android.system.OsConstants;
-import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.Log;
import android.util.Pair;
@@ -685,14 +684,18 @@ public class MediaPlayer extends PlayerBase
mTimeProvider = new TimeProvider(this);
mOpenSubtitleSources = new Vector<InputStream>();
- Identity identity = myIdentity(null);
+ AttributionSource attributionSource = AttributionSource.myAttributionSource();
// set the package name to empty if it was null
- identity.packageName = TextUtils.emptyIfNull(identity.packageName);
+ if (attributionSource.getPackageName() == null) {
+ attributionSource = attributionSource.withPackageName("");
+ }
/* Native setup requires a weak reference to our object.
* It's easier to create it here than in C++.
*/
- native_setup(new WeakReference<MediaPlayer>(this), identity);
+ try (ScopedParcelState attributionSourceState = attributionSource.asScopedParcelState()) {
+ native_setup(new WeakReference<MediaPlayer>(this), attributionSourceState.getParcel());
+ }
baseRegisterPlayer(sessionId);
}
@@ -2475,7 +2478,8 @@ public class MediaPlayer extends PlayerBase
private native final int native_setMetadataFilter(Parcel request);
private static native final void native_init();
- private native void native_setup(Object mediaplayerThis, @NonNull Identity identity);
+ private native void native_setup(Object mediaplayerThis,
+ @NonNull Parcel attributionSource);
private native final void native_finalize();
/**
diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java
index 499034ea7c41..1efd4c6846e6 100644
--- a/media/java/android/media/MediaRecorder.java
+++ b/media/java/android/media/MediaRecorder.java
@@ -16,8 +16,6 @@
package android.media;
-import static android.media.permission.PermissionUtil.myIdentity;
-
import android.annotation.CallbackExecutor;
import android.annotation.FloatRange;
import android.annotation.IntDef;
@@ -27,14 +25,16 @@ import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.app.ActivityThread;
import android.compat.annotation.UnsupportedAppUsage;
+import android.content.AttributionSource;
+import android.content.AttributionSource.ScopedParcelState;
import android.content.Context;
import android.hardware.Camera;
import android.media.metrics.LogSessionId;
-import android.media.permission.Identity;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
+import android.os.Parcel;
import android.os.PersistableBundle;
import android.util.ArrayMap;
import android.util.Log;
@@ -163,8 +163,11 @@ public class MediaRecorder implements AudioRouting,
/* Native setup requires a weak reference to our object.
* It's easier to create it here than in C++.
*/
- native_setup(new WeakReference<MediaRecorder>(this),
- ActivityThread.currentPackageName(), myIdentity(context));
+ try (ScopedParcelState attributionSourceState = context.getAttributionSource()
+ .asScopedParcelState()) {
+ native_setup(new WeakReference<>(this), ActivityThread.currentPackageName(),
+ attributionSourceState.getParcel());
+ }
}
/**
@@ -1894,14 +1897,15 @@ public class MediaRecorder implements AudioRouting,
publicAlternatives = "{@link MediaRecorder}")
private void native_setup(Object mediarecorderThis,
String clientName, String opPackageName) throws IllegalStateException {
- Identity identity = myIdentity(null);
- identity.packageName = opPackageName;
-
- native_setup(mediarecorderThis, clientName, identity);
+ AttributionSource attributionSource = AttributionSource.myAttributionSource()
+ .withPackageName(opPackageName);
+ try (ScopedParcelState attributionSourceState = attributionSource.asScopedParcelState()) {
+ native_setup(mediarecorderThis, clientName, attributionSourceState.getParcel());
+ }
}
private native void native_setup(Object mediarecorderThis,
- String clientName, Identity identity)
+ String clientName, @NonNull Parcel attributionSource)
throws IllegalStateException;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
diff --git a/media/java/android/media/audiofx/AudioEffect.java b/media/java/android/media/audiofx/AudioEffect.java
index fd3c4057ad21..70bb9608f1c2 100644
--- a/media/java/android/media/audiofx/AudioEffect.java
+++ b/media/java/android/media/audiofx/AudioEffect.java
@@ -16,8 +16,6 @@
package android.media.audiofx;
-import static android.media.permission.PermissionUtil.myIdentity;
-
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
@@ -26,10 +24,11 @@ import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
+import android.content.AttributionSource;
+import android.content.AttributionSource.ScopedParcelState;
import android.media.AudioDeviceAttributes;
import android.media.AudioDeviceInfo;
import android.media.AudioSystem;
-import android.media.permission.Identity;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
@@ -518,10 +517,13 @@ public class AudioEffect {
// native initialization
// TODO b/182469354: Make consistent with AudioRecord
- int initResult = native_setup(new WeakReference<AudioEffect>(this),
- type.toString(), uuid.toString(), priority, audioSession,
- deviceType, deviceAddress,
- id, desc, myIdentity(null), probe);
+ int initResult;
+ try (ScopedParcelState attributionSourceState = AttributionSource.myAttributionSource()
+ .asScopedParcelState()) {
+ initResult = native_setup(new WeakReference<>(this), type.toString(), uuid.toString(),
+ priority, audioSession, deviceType, deviceAddress, id, desc,
+ attributionSourceState.getParcel(), probe);
+ }
if (initResult != SUCCESS && initResult != ALREADY_EXISTS) {
Log.e(TAG, "Error code " + initResult
+ " when initializing AudioEffect.");
@@ -1388,7 +1390,7 @@ public class AudioEffect {
private native final int native_setup(Object audioeffect_this, String type,
String uuid, int priority, int audioSession,
int deviceType, String deviceAddress, int[] id, Object[] desc,
- Identity identity, boolean probe);
+ @NonNull Parcel attributionSource, boolean probe);
private native final void native_finalize();
diff --git a/media/java/android/media/audiofx/Visualizer.java b/media/java/android/media/audiofx/Visualizer.java
index 58c9e650bb90..3349277ede3b 100644
--- a/media/java/android/media/audiofx/Visualizer.java
+++ b/media/java/android/media/audiofx/Visualizer.java
@@ -16,12 +16,13 @@
package android.media.audiofx;
-import static android.media.permission.PermissionUtil.myIdentity;
-
+import android.annotation.NonNull;
import android.compat.annotation.UnsupportedAppUsage;
-import android.media.permission.Identity;
+import android.content.AttributionSource;
+import android.content.AttributionSource.ScopedParcelState;
import android.os.Handler;
import android.os.Looper;
+import android.os.Parcel;
import android.util.Log;
import com.android.internal.annotations.GuardedBy;
@@ -222,8 +223,12 @@ public class Visualizer {
// native initialization
// TODO b/182469354: make consistent with AudioRecord
- int result = native_setup(new WeakReference<Visualizer>(this), audioSession, id,
- myIdentity(null));
+ int result;
+ try (ScopedParcelState attributionSourceState = AttributionSource.myAttributionSource()
+ .asScopedParcelState()) {
+ result = native_setup(new WeakReference<>(this), audioSession, id,
+ attributionSourceState.getParcel());
+ }
if (result != SUCCESS && result != ALREADY_EXISTS) {
Log.e(TAG, "Error code "+result+" when initializing Visualizer.");
switch (result) {
@@ -690,7 +695,7 @@ public class Visualizer {
private native final int native_setup(Object audioeffect_this,
int audioSession,
int[] id,
- Identity identity);
+ @NonNull Parcel attributionSource);
@GuardedBy("mStateLock")
private native final void native_finalize();
diff --git a/media/java/android/media/permission/PermissionUtil.java b/media/java/android/media/permission/PermissionUtil.java
index 92fe8820570c..b08d111db89c 100644
--- a/media/java/android/media/permission/PermissionUtil.java
+++ b/media/java/android/media/permission/PermissionUtil.java
@@ -51,24 +51,6 @@ import java.util.Objects;
* @hide
*/
public class PermissionUtil {
- /**
- * Create an identity for the current process and the passed context.
- *
- * @param context The process the identity is for. If {@code null}, the process's default
- * identity is chosen.
- * @return The identity for the current process and context
- */
- public static @NonNull Identity myIdentity(@Nullable Context context) {
- Identity identity = new Identity();
-
- identity.pid = Process.myPid();
- identity.uid = Process.myUid();
- identity.packageName = context != null ? context.getOpPackageName()
- : ActivityThread.currentOpPackageName();
- identity.attributionTag = context != null ? context.getAttributionTag() : null;
-
- return identity;
- }
/**
* Authenticate an originator, where the binder call is coming from a middleman.
diff --git a/media/jni/Android.bp b/media/jni/Android.bp
index d49790e3ecd3..bc73f6ad1ad2 100644
--- a/media/jni/Android.bp
+++ b/media/jni/Android.bp
@@ -51,6 +51,7 @@ cc_library_shared {
shared_libs: [
"audioclient-types-aidl-cpp",
"av-types-aidl-cpp",
+ "framework-permission-aidl-cpp",
"libandroid_runtime",
"libaudioclient",
"libnativehelper",
@@ -85,7 +86,6 @@ cc_library_shared {
"android.hardware.drm@1.4",
"android.hidl.memory@1.0",
"android.hidl.token@1.0-utils",
- "media_permission-aidl-cpp",
],
header_libs: [
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index a3607597f05e..2636ab227646 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -17,7 +17,6 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "MediaPlayer-JNI"
-#include "permission_utils.h"
#include "utils/Log.h"
#include <media/mediaplayer.h>
@@ -80,8 +79,6 @@ static StateExceptionFields gStateExceptionFields;
using namespace android;
using media::VolumeShaper;
-using media::permission::Identity;
-using media::permission::convertIdentity;
// ----------------------------------------------------------------------------
@@ -949,11 +946,14 @@ android_media_MediaPlayer_native_init(JNIEnv *env)
static void
android_media_MediaPlayer_native_setup(JNIEnv *env, jobject thiz, jobject weak_this,
- jobject jIdentity)
+ jobject jAttributionSource)
{
ALOGV("native_setup");
- sp<MediaPlayer> mp = new MediaPlayer(convertIdentity(env, jIdentity));
+ Parcel* parcel = parcelForJavaObject(env, jAttributionSource);
+ android::content::AttributionSourceState attributionSource;
+ attributionSource.readFromParcel(parcel);
+ sp<MediaPlayer> mp = new MediaPlayer(attributionSource);
if (mp == NULL) {
jniThrowException(env, "java/lang/RuntimeException", "Out of memory");
return;
@@ -1409,7 +1409,7 @@ static const JNINativeMethod gMethods[] = {
{"native_setMetadataFilter", "(Landroid/os/Parcel;)I", (void *)android_media_MediaPlayer_setMetadataFilter},
{"native_getMetadata", "(ZZLandroid/os/Parcel;)Z", (void *)android_media_MediaPlayer_getMetadata},
{"native_init", "()V", (void *)android_media_MediaPlayer_native_init},
- {"native_setup", "(Ljava/lang/Object;Landroid/media/permission/Identity;)V",(void *)android_media_MediaPlayer_native_setup},
+ {"native_setup", "(Ljava/lang/Object;Landroid/os/Parcel;)V",(void *)android_media_MediaPlayer_native_setup},
{"native_finalize", "()V", (void *)android_media_MediaPlayer_native_finalize},
{"getAudioSessionId", "()I", (void *)android_media_MediaPlayer_get_audio_session_id},
{"native_setAudioSessionId", "(I)V", (void *)android_media_MediaPlayer_set_audio_session_id},
diff --git a/media/jni/android_media_MediaRecorder.cpp b/media/jni/android_media_MediaRecorder.cpp
index 66411233216f..7ef0f7709408 100644
--- a/media/jni/android_media_MediaRecorder.cpp
+++ b/media/jni/android_media_MediaRecorder.cpp
@@ -24,7 +24,6 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "MediaRecorderJNI"
-#include "permission_utils.h"
#include <utils/Log.h>
#include <gui/Surface.h>
@@ -46,13 +45,13 @@
#include <system/audio.h>
#include <android_runtime/android_view_Surface.h>
+#include <android/content/AttributionSourceState.h>
+#include <android_os_Parcel.h>
// ----------------------------------------------------------------------------
using namespace android;
-using android::media::permission::convertIdentity;
-
// ----------------------------------------------------------------------------
// helper function to extract a native Camera object from a Camera Java object
@@ -620,11 +619,14 @@ android_media_MediaRecorder_native_init(JNIEnv *env)
static void
android_media_MediaRecorder_native_setup(JNIEnv *env, jobject thiz, jobject weak_this,
- jstring packageName, jobject jIdentity)
+ jstring packageName, jobject jAttributionSource)
{
ALOGV("setup");
- sp<MediaRecorder> mr = new MediaRecorder(convertIdentity(env, jIdentity));
+ Parcel* parcel = parcelForJavaObject(env, jAttributionSource);
+ android::content::AttributionSourceState attributionSource;
+ attributionSource.readFromParcel(parcel);
+ sp<MediaRecorder> mr = new MediaRecorder(attributionSource);
if (mr == NULL) {
jniThrowException(env, "java/lang/RuntimeException", "Out of memory");
@@ -871,7 +873,7 @@ static const JNINativeMethod gMethods[] = {
{"native_reset", "()V", (void *)android_media_MediaRecorder_native_reset},
{"release", "()V", (void *)android_media_MediaRecorder_release},
{"native_init", "()V", (void *)android_media_MediaRecorder_native_init},
- {"native_setup", "(Ljava/lang/Object;Ljava/lang/String;Landroid/media/permission/Identity;)V",
+ {"native_setup", "(Ljava/lang/Object;Ljava/lang/String;Landroid/os/Parcel;)V",
(void *)android_media_MediaRecorder_native_setup},
{"native_finalize", "()V", (void *)android_media_MediaRecorder_native_finalize},
{"native_setInputSurface", "(Landroid/view/Surface;)V", (void *)android_media_MediaRecorder_setInputSurface },
diff --git a/media/jni/audioeffect/Android.bp b/media/jni/audioeffect/Android.bp
index bfed983c8bce..2ddfacf3884a 100644
--- a/media/jni/audioeffect/Android.bp
+++ b/media/jni/audioeffect/Android.bp
@@ -19,6 +19,7 @@ cc_library_shared {
],
shared_libs: [
+ "framework-permission-aidl-cpp",
"liblog",
"libcutils",
"libutils",
@@ -27,11 +28,11 @@ cc_library_shared {
"libaudioclient",
"libaudioutils",
"libaudiofoundation",
- "media_permission-aidl-cpp",
+ "libbinder"
],
export_shared_lib_headers: [
- "media_permission-aidl-cpp",
+ "framework-permission-aidl-cpp",
],
version_script: "exports.lds",
diff --git a/media/jni/audioeffect/Visualizer.cpp b/media/jni/audioeffect/Visualizer.cpp
index 8a52456849f0..84a8d5122470 100644
--- a/media/jni/audioeffect/Visualizer.cpp
+++ b/media/jni/audioeffect/Visualizer.cpp
@@ -28,14 +28,16 @@
#include <cutils/bitops.h>
#include <utils/Thread.h>
+#include <android/content/AttributionSourceState.h>
+
#include "Visualizer.h"
namespace android {
// ---------------------------------------------------------------------------
-Visualizer::Visualizer (const Identity& identity)
- : AudioEffect(identity)
+Visualizer::Visualizer (const android::content::AttributionSourceState& attributionSource)
+ : AudioEffect(attributionSource)
{
}
diff --git a/media/jni/audioeffect/Visualizer.h b/media/jni/audioeffect/Visualizer.h
index 3ee91f0f8b1e..aa07ce8055ae 100644
--- a/media/jni/audioeffect/Visualizer.h
+++ b/media/jni/audioeffect/Visualizer.h
@@ -20,9 +20,7 @@
#include <media/AudioEffect.h>
#include <system/audio_effects/effect_visualizer.h>
#include <utils/Thread.h>
-#include "android/media/permission/Identity.h"
-
-using namespace android::media::permission;
+#include "android/content/AttributionSourceState.h"
/**
* The Visualizer class enables application to retrieve part of the currently playing audio for
@@ -68,9 +66,9 @@ public:
/* Constructor.
* See AudioEffect constructor for details on parameters.
*/
- explicit Visualizer(const Identity& identity);
+ explicit Visualizer(const android::content::AttributionSourceState& attributionSource);
- ~Visualizer();
+ ~Visualizer();
/**
* Initialize an uninitialized Visualizer.
diff --git a/media/jni/audioeffect/android_media_AudioEffect.cpp b/media/jni/audioeffect/android_media_AudioEffect.cpp
index 953b7e01c983..3a8decdad18f 100644
--- a/media/jni/audioeffect/android_media_AudioEffect.cpp
+++ b/media/jni/audioeffect/android_media_AudioEffect.cpp
@@ -25,7 +25,9 @@
#include <nativehelper/JNIHelp.h>
#include <android_runtime/AndroidRuntime.h>
#include "media/AudioEffect.h"
-#include "permission_utils.h"
+
+#include <android/content/AttributionSourceState.h>
+#include <android_os_Parcel.h>
#include <nativehelper/ScopedUtfChars.h>
@@ -35,8 +37,6 @@
using namespace android;
-using media::permission::convertIdentity;
-
#define AUDIOEFFECT_SUCCESS 0
#define AUDIOEFFECT_ERROR (-1)
#define AUDIOEFFECT_ERROR_ALREADY_EXISTS (-2)
@@ -273,7 +273,7 @@ static jint
android_media_AudioEffect_native_setup(JNIEnv *env, jobject thiz, jobject weak_this,
jstring type, jstring uuid, jint priority, jint sessionId,
jint deviceType, jstring deviceAddress,
- jintArray jId, jobjectArray javadesc, jobject jIdentity, jboolean probe)
+ jintArray jId, jobjectArray javadesc, jobject jAttributionSource, jboolean probe)
{
ALOGV("android_media_AudioEffect_native_setup");
AudioEffectJniStorage* lpJniStorage = NULL;
@@ -285,6 +285,8 @@ android_media_AudioEffect_native_setup(JNIEnv *env, jobject thiz, jobject weak_t
effect_descriptor_t desc;
jobject jdesc;
AudioDeviceTypeAddr device;
+ AttributionSourceState attributionSource;
+ Parcel* parcel = NULL;
setAudioEffect(env, thiz, 0);
@@ -338,7 +340,9 @@ android_media_AudioEffect_native_setup(JNIEnv *env, jobject thiz, jobject weak_t
}
// create the native AudioEffect object
- lpAudioEffect = new AudioEffect(convertIdentity(env, jIdentity));
+ parcel = parcelForJavaObject(env, jAttributionSource);
+ attributionSource.readFromParcel(parcel);
+ lpAudioEffect = new AudioEffect(attributionSource);
if (lpAudioEffect == 0) {
ALOGE("Error creating AudioEffect");
goto setup_failure;
@@ -774,7 +778,7 @@ android_media_AudioEffect_native_queryPreProcessings(JNIEnv *env, jclass clazz _
// Dalvik VM type signatures
static const JNINativeMethod gMethods[] = {
{"native_init", "()V", (void *)android_media_AudioEffect_native_init},
- {"native_setup", "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;IIILjava/lang/String;[I[Ljava/lang/Object;Landroid/media/permission/Identity;Z)I",
+ {"native_setup", "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;IIILjava/lang/String;[I[Ljava/lang/Object;Landroid/os/Parcel;Z)I",
(void *)android_media_AudioEffect_native_setup},
{"native_finalize", "()V", (void *)android_media_AudioEffect_native_finalize},
{"native_release", "()V", (void *)android_media_AudioEffect_native_release},
diff --git a/media/jni/audioeffect/android_media_Visualizer.cpp b/media/jni/audioeffect/android_media_Visualizer.cpp
index 439715cbb811..b30f00fdf7de 100644
--- a/media/jni/audioeffect/android_media_Visualizer.cpp
+++ b/media/jni/audioeffect/android_media_Visualizer.cpp
@@ -25,12 +25,16 @@
#include <android_runtime/AndroidRuntime.h>
#include <utils/threads.h>
#include "Visualizer.h"
-#include "permission_utils.h"
#include <nativehelper/ScopedUtfChars.h>
+#include <android/content/AttributionSourceState.h>
+#include <android_os_Parcel.h>
+
using namespace android;
+using content::AttributionSourceState;
+
#define VISUALIZER_SUCCESS 0
#define VISUALIZER_ERROR (-1)
#define VISUALIZER_ERROR_ALREADY_EXISTS (-2)
@@ -348,13 +352,15 @@ static void android_media_visualizer_effect_callback(int32_t event,
static jint
android_media_visualizer_native_setup(JNIEnv *env, jobject thiz, jobject weak_this,
- jint sessionId, jintArray jId, jobject jIdentity)
+ jint sessionId, jintArray jId, jobject jAttributionSource)
{
ALOGV("android_media_visualizer_native_setup");
VisualizerJniStorage* lpJniStorage = NULL;
int lStatus = VISUALIZER_ERROR_NO_MEMORY;
sp<Visualizer> lpVisualizer;
jint* nId = NULL;
+ AttributionSourceState attributionSource;
+ Parcel* parcel = nullptr;
setVisualizer(env, thiz, 0);
@@ -381,7 +387,9 @@ android_media_visualizer_native_setup(JNIEnv *env, jobject thiz, jobject weak_th
}
// create the native Visualizer object
- lpVisualizer = new Visualizer(convertIdentity(env, jIdentity));
+ parcel = parcelForJavaObject(env, jAttributionSource);
+ attributionSource.readFromParcel(parcel);
+ lpVisualizer = sp<Visualizer>::make(attributionSource);
if (lpVisualizer == 0) {
ALOGE("Error creating Visualizer");
goto setup_failure;
@@ -678,7 +686,7 @@ android_media_setPeriodicCapture(JNIEnv *env, jobject thiz, jint rate, jboolean
// Dalvik VM type signatures
static const JNINativeMethod gMethods[] = {
{"native_init", "()V", (void *)android_media_visualizer_native_init},
- {"native_setup", "(Ljava/lang/Object;I[ILandroid/media/permission/Identity;)I",
+ {"native_setup", "(Ljava/lang/Object;I[ILandroid/os/Parcel;)I",
(void *)android_media_visualizer_native_setup},
{"native_finalize", "()V", (void *)android_media_visualizer_native_finalize},
{"native_release", "()V", (void *)android_media_visualizer_native_release},
diff --git a/media/jni/soundpool/Android.bp b/media/jni/soundpool/Android.bp
index 4227cd8cbb29..ee473f5deb15 100644
--- a/media/jni/soundpool/Android.bp
+++ b/media/jni/soundpool/Android.bp
@@ -126,6 +126,7 @@ cc_library_shared {
],
shared_libs: [
+ "framework-permission-aidl-cpp",
"libaudioutils",
"liblog",
"libcutils",
@@ -135,7 +136,6 @@ cc_library_shared {
"libaudioclient",
"libmediandk",
"libbinder",
- "media_permission-aidl-cpp",
],
cflags: [
diff --git a/media/jni/soundpool/Stream.cpp b/media/jni/soundpool/Stream.cpp
index 95fe000bd2c2..bbbef3853b23 100644
--- a/media/jni/soundpool/Stream.cpp
+++ b/media/jni/soundpool/Stream.cpp
@@ -17,7 +17,7 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "SoundPool::Stream"
#include <utils/Log.h>
-#include<android/media/permission/Identity.h>
+#include <android/content/AttributionSourceState.h>
#include "Stream.h"
@@ -25,8 +25,6 @@
namespace android::soundpool {
-using media::permission::Identity;
-
Stream::~Stream()
{
ALOGV("%s(%p)", __func__, this);
@@ -330,15 +328,16 @@ void Stream::play_l(const std::shared_ptr<Sound>& sound, int32_t nextStreamID,
// do not create a new audio track if current track is compatible with sound parameters
- Identity identity = Identity();
- identity.packageName = mStreamManager->getOpPackageName();
+ android::content::AttributionSourceState attributionSource;
+ attributionSource.packageName = mStreamManager->getOpPackageName();
+ attributionSource.token = sp<BBinder>::make();
// TODO b/182469354 make consistent with AudioRecord, add util for native source
newTrack = new AudioTrack(streamType, sampleRate, sound->getFormat(),
channelMask, sound->getIMemory(), AUDIO_OUTPUT_FLAG_FAST,
staticCallback, userData,
0 /*default notification frames*/, AUDIO_SESSION_ALLOCATE,
AudioTrack::TRANSFER_DEFAULT,
- nullptr /*offloadInfo*/, identity,
+ nullptr /*offloadInfo*/, attributionSource,
mStreamManager->getAttributes(),
false /*doNotReconnect*/, 1.0f /*maxRequiredSpeed*/);
// Set caller name so it can be logged in destructor.
diff --git a/packages/CtsShim/apk/arm/CtsShim.apk b/packages/CtsShim/apk/arm/CtsShim.apk
index ca69a28a04b4..bb6dfa3a4ede 100644
--- a/packages/CtsShim/apk/arm/CtsShim.apk
+++ b/packages/CtsShim/apk/arm/CtsShim.apk
Binary files differ
diff --git a/packages/CtsShim/apk/arm/CtsShimPriv.apk b/packages/CtsShim/apk/arm/CtsShimPriv.apk
index d7cfb969c728..2835d57474d9 100644
--- a/packages/CtsShim/apk/arm/CtsShimPriv.apk
+++ b/packages/CtsShim/apk/arm/CtsShimPriv.apk
Binary files differ
diff --git a/packages/CtsShim/apk/x86/CtsShim.apk b/packages/CtsShim/apk/x86/CtsShim.apk
index ca69a28a04b4..bb6dfa3a4ede 100644
--- a/packages/CtsShim/apk/x86/CtsShim.apk
+++ b/packages/CtsShim/apk/x86/CtsShim.apk
Binary files differ
diff --git a/packages/CtsShim/apk/x86/CtsShimPriv.apk b/packages/CtsShim/apk/x86/CtsShimPriv.apk
index 84c34010a212..2e1a78989b70 100644
--- a/packages/CtsShim/apk/x86/CtsShimPriv.apk
+++ b/packages/CtsShim/apk/x86/CtsShimPriv.apk
Binary files differ
diff --git a/packages/SettingsLib/CollapsingToolbarBaseActivity/res/values/dimens.xml b/packages/SettingsLib/CollapsingToolbarBaseActivity/res/values/dimens.xml
index f0cdaf603ba1..626fd3aa49f5 100644
--- a/packages/SettingsLib/CollapsingToolbarBaseActivity/res/values/dimens.xml
+++ b/packages/SettingsLib/CollapsingToolbarBaseActivity/res/values/dimens.xml
@@ -16,10 +16,12 @@
-->
<resources>
<!-- Collapsing toolbar layout dimensions -->
- <dimen name="toolbar_one_line_height">226dp</dimen>
- <dimen name="toolbar_two_lines_height">270dp</dimen>
- <dimen name="toolbar_three_lines_height">314dp</dimen>
+ <dimen name="toolbar_one_line_height">216dp</dimen>
+ <dimen name="toolbar_two_lines_height">260dp</dimen>
+ <dimen name="toolbar_three_lines_height">304dp</dimen>
<dimen name="scrim_visible_height_trigger">174dp</dimen>
+ <dimen name="scrim_visible_height_trigger_two_lines">218dp</dimen>
+ <dimen name="scrim_visible_height_trigger_three_lines">262dp</dimen>
<dimen name="expanded_title_margin_start">24dp</dimen>
<dimen name="expanded_title_margin_end">24dp</dimen>
</resources> \ No newline at end of file
diff --git a/packages/SettingsLib/CollapsingToolbarBaseActivity/src/com/android/settingslib/collapsingtoolbar/AdjustableToolbarLayout.java b/packages/SettingsLib/CollapsingToolbarBaseActivity/src/com/android/settingslib/collapsingtoolbar/AdjustableToolbarLayout.java
index b3053ac76b55..0e7e595a3f04 100644
--- a/packages/SettingsLib/CollapsingToolbarBaseActivity/src/com/android/settingslib/collapsingtoolbar/AdjustableToolbarLayout.java
+++ b/packages/SettingsLib/CollapsingToolbarBaseActivity/src/com/android/settingslib/collapsingtoolbar/AdjustableToolbarLayout.java
@@ -26,12 +26,9 @@ import androidx.annotation.Nullable;
import com.google.android.material.appbar.CollapsingToolbarLayout;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-
/**
- * A customized version of CollapsingToolbarLayout that can apply different font size based on
- * the line count of its title.
+ * A customized version of CollapsingToolbarLayout that can apply different font size based on the
+ * line count of its title.
*/
public class AdjustableToolbarLayout extends CollapsingToolbarLayout {
@@ -59,43 +56,25 @@ public class AdjustableToolbarLayout extends CollapsingToolbarLayout {
public void onLayoutChange(View v, int left, int top, int right, int bottom,
int oldLeft, int oldTop, int oldRight, int oldBottom) {
v.removeOnLayoutChangeListener(this);
- final int count = getLineCountWithReflection();
+ final int count = getLineCount();
if (count > TOOLBAR_MAX_LINE_NUMBER) {
final ViewGroup.LayoutParams lp = getLayoutParams();
lp.height = getResources()
.getDimensionPixelSize(R.dimen.toolbar_three_lines_height);
+ setScrimVisibleHeightTrigger(
+ getResources().getDimensionPixelSize(
+ R.dimen.scrim_visible_height_trigger_three_lines));
setLayoutParams(lp);
} else if (count == TOOLBAR_MAX_LINE_NUMBER) {
final ViewGroup.LayoutParams lp = getLayoutParams();
lp.height = getResources()
.getDimensionPixelSize(R.dimen.toolbar_two_lines_height);
+ setScrimVisibleHeightTrigger(
+ getResources().getDimensionPixelSize(
+ R.dimen.scrim_visible_height_trigger_two_lines));
setLayoutParams(lp);
}
}
});
}
-
- /**
- * Returns a number of title line count for CollapsingToolbarLayout so that facilitates the
- * determination to apply what kind of font size. Since the title of CollapsingToolbarLayout is
- * drawn in a canvas and the text process is wrapped in a CollapsingTextHelper, the way we used
- * here is to get the line count from the CollapsingTextHelper via Java Reflection.
- */
- private int getLineCountWithReflection() {
- try {
- final Field textHelperField =
- this.getClass().getSuperclass().getDeclaredField("collapsingTextHelper");
- textHelperField.setAccessible(true);
- final Object textHelperObj = textHelperField.get(this);
-
- final Field layoutField = textHelperObj.getClass().getDeclaredField("textLayout");
- layoutField.setAccessible(true);
- final Object layoutObj = layoutField.get(textHelperObj);
-
- final Method method = layoutObj.getClass().getDeclaredMethod("getLineCount");
- return (int) method.invoke(layoutObj);
- } catch (Exception e) {
- return 0;
- }
- }
}
diff --git a/packages/SettingsLib/MainSwitchPreference/res/layout-v31/settingslib_main_switch_bar.xml b/packages/SettingsLib/MainSwitchPreference/res/layout-v31/settingslib_main_switch_bar.xml
index 010b9ba4324b..2d214fe65c64 100644
--- a/packages/SettingsLib/MainSwitchPreference/res/layout-v31/settingslib_main_switch_bar.xml
+++ b/packages/SettingsLib/MainSwitchPreference/res/layout-v31/settingslib_main_switch_bar.xml
@@ -48,7 +48,6 @@
android:layout_width="@dimen/settingslib_restricted_icon_size"
android:layout_height="@dimen/settingslib_restricted_icon_size"
android:tint="?android:attr/colorAccent"
- android:theme="@android:style/Theme.Material"
android:layout_gravity="center_vertical"
android:layout_marginEnd="@dimen/settingslib_restricted_icon_margin_end"
android:src="@*android:drawable/ic_info"
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java
index 2dbfef039197..83a6973ffec6 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java
@@ -139,6 +139,17 @@ public class RestrictedPreferenceHelper {
}
/**
+ * @return EnforcedAdmin if we have been passed the restriction in the xml.
+ */
+ public EnforcedAdmin checkRestrictionEnforced() {
+ if (mAttrUserRestriction == null) {
+ return null;
+ }
+ return RestrictedLockUtilsInternal.checkIfRestrictionEnforced(mContext,
+ mAttrUserRestriction, UserHandle.myUserId());
+ }
+
+ /**
* Disable this preference based on the enforce admin.
*
* @param admin details of the admin who enforced the restriction. If it is
diff --git a/packages/SystemUI/res/drawable/screenshot_edit_background.xml b/packages/SystemUI/res/drawable/screenshot_edit_background.xml
new file mode 100644
index 000000000000..5c3c12c572f6
--- /dev/null
+++ b/packages/SystemUI/res/drawable/screenshot_edit_background.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2021 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.
+ -->
+<!-- Long screenshot edit FAB background -->
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+ android:color="?android:textColorPrimary">
+ <item android:id="@android:id/background">
+ <shape android:shape="rectangle">
+ <solid android:color="?androidprv:attr/colorAccentSecondary"/>
+ <corners android:radius="16dp"/>
+ </shape>
+ </item>
+ <item android:id="@android:id/mask">
+ <shape android:shape="rectangle">
+ <solid android:color="?android:textColorPrimary"/>
+ <corners android:radius="16dp"/>
+ </shape>
+ </item>
+</ripple> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/screenshot_save_background.xml b/packages/SystemUI/res/drawable/screenshot_save_background.xml
new file mode 100644
index 000000000000..cfd2dc214477
--- /dev/null
+++ b/packages/SystemUI/res/drawable/screenshot_save_background.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2021 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.
+ -->
+<!-- Long screenshot save button background -->
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+ android:color="?android:textColorPrimary">
+ <item android:id="@android:id/background">
+ <shape android:shape="rectangle">
+ <solid android:color="?androidprv:attr/colorAccentSecondary"/>
+ <corners android:radius="20dp"/>
+ </shape>
+ </item>
+ <item android:id="@android:id/mask">
+ <shape android:shape="rectangle">
+ <solid android:color="?android:textColorPrimary"/>
+ <corners android:radius="20dp"/>
+ </shape>
+ </item>
+</ripple> \ No newline at end of file
diff --git a/packages/SystemUI/res/layout/long_screenshot.xml b/packages/SystemUI/res/layout/long_screenshot.xml
index de3384657d9d..8e30aecd6a27 100644
--- a/packages/SystemUI/res/layout/long_screenshot.xml
+++ b/packages/SystemUI/res/layout/long_screenshot.xml
@@ -28,11 +28,11 @@
android:id="@+id/save"
style="@android:style/Widget.DeviceDefault.Button.Colored"
android:layout_width="wrap_content"
- android:layout_height="wrap_content"
+ android:layout_height="40dp"
android:text="@string/save"
android:layout_marginStart="8dp"
android:layout_marginTop="4dp"
- android:backgroundTint="?androidprv:attr/colorAccentSecondary"
+ android:background="@drawable/screenshot_save_background"
android:textColor="?android:textColorSecondary"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
@@ -114,7 +114,7 @@
android:layout_marginBottom="16dp"
android:layout_marginEnd="16dp"
style="@android:style/Widget.DeviceDefault.Button.Colored"
- android:backgroundTint="?androidprv:attr/colorAccentSecondary"
+ android:background="@drawable/screenshot_edit_background"
android:src="@drawable/ic_screenshot_edit"
android:contentDescription="@string/screenshot_edit_label"
android:tint="?android:textColorSecondary"
diff --git a/packages/SystemUI/res/layout/qs_paged_page.xml b/packages/SystemUI/res/layout/qs_paged_page.xml
index a4f0a0c85d41..98804fc80b50 100644
--- a/packages/SystemUI/res/layout/qs_paged_page.xml
+++ b/packages/SystemUI/res/layout/qs_paged_page.xml
@@ -18,4 +18,8 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/tile_page"
android:layout_width="match_parent"
- android:layout_height="match_parent"/>
+ android:layout_height="match_parent"
+ android:paddingStart="@dimen/notification_side_paddings"
+ android:paddingEnd="@dimen/notification_side_paddings"
+ android:clipChildren="false"
+ android:clipToPadding="false" />
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 6a848fbd2a26..46511682464b 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -642,7 +642,7 @@
<item name="android:tint">?android:attr/textColorPrimary</item>
<item name="android:stateListAnimator">@anim/media_button_state_list_animator</item>
<item name="android:padding">12dp</item>
- <item name="android:scaleType">fitCenter</item>
+ <item name="android:scaleType">centerInside</item>
</style>
<style name="MediaPlayer.OutlineButton">
@@ -662,7 +662,8 @@
<style name="MediaPlayer.AppIcon">
<item name="android:background">@drawable/qs_media_icon_background</item>
- <item name="android:backgroundTint">?android:attr/textColorPrimary</item>
+ <item name="android:backgroundTint">@color/media_player_solid_button_bg</item>
+ <item name="android:padding">4dp</item>
</style>
<style name="MediaPlayer.Album">
diff --git a/packages/SystemUI/src/com/android/keyguard/LockIconView.java b/packages/SystemUI/src/com/android/keyguard/LockIconView.java
index eff412e49836..423bd5626da9 100644
--- a/packages/SystemUI/src/com/android/keyguard/LockIconView.java
+++ b/packages/SystemUI/src/com/android/keyguard/LockIconView.java
@@ -21,7 +21,6 @@ import android.content.Context;
import android.graphics.PointF;
import android.graphics.RectF;
import android.util.AttributeSet;
-import android.view.Surface;
import android.widget.FrameLayout;
import android.widget.ImageView;
@@ -30,44 +29,25 @@ import android.widget.ImageView;
*/
public class LockIconView extends ImageView {
@NonNull private final RectF mSensorRect;
- @NonNull private final Context mContext;
-
@NonNull private PointF mLockIconCenter = new PointF(0f, 0f);
private int mRadius;
public LockIconView(Context context, AttributeSet attrs) {
super(context, attrs);
- mContext = context;
mSensorRect = new RectF();
}
void setLocation(@NonNull PointF center, int radius) {
mLockIconCenter = center;
mRadius = radius;
- }
- // The "h" and "w" are the display's height and width relative to its current rotation.
- private void updateSensorRect(int h, int w) {
- // mSensorProps coordinates assume portrait mode.
+ // mSensorProps coordinates assume portrait mode which is OK b/c the keyguard is always in
+ // portrait.
mSensorRect.set(mLockIconCenter.x - mRadius,
mLockIconCenter.y - mRadius,
mLockIconCenter.x + mRadius,
mLockIconCenter.y + mRadius);
- // Transform mSensorRect if the device is in landscape mode.
- switch (mContext.getDisplay().getRotation()) {
- case Surface.ROTATION_90:
- mSensorRect.set(mSensorRect.top, h - mSensorRect.right, mSensorRect.bottom,
- h - mSensorRect.left);
- break;
- case Surface.ROTATION_270:
- mSensorRect.set(w - mSensorRect.bottom, mSensorRect.left, w - mSensorRect.top,
- mSensorRect.right);
- break;
- default:
- // Do nothing to stay in portrait mode.
- }
-
setX(mSensorRect.left);
setY(mSensorRect.top);
setLayoutParams(new FrameLayout.LayoutParams(
@@ -76,18 +56,6 @@ public class LockIconView extends ImageView {
}
@Override
- protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- super.onLayout(changed, left, top, right, bottom);
- // Always re-compute the layout regardless of whether "changed" is true. It is usually false
- // when the device goes from landscape to seascape and vice versa, but mSensorRect and
- // its dependencies need to be recalculated to stay at the same physical location on the
- // screen.
- final int w = getLayoutParams().width;
- final int h = getLayoutParams().height;
- updateSensorRect(h, w);
- }
-
- @Override
public boolean hasOverlappingRendering() {
return false;
}
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
index e6fe0600b9b8..a28223de2bf1 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
@@ -117,7 +117,8 @@ public class SystemUIFactory {
.setAppPairs(mWMComponent.getAppPairs())
.setTaskViewFactory(mWMComponent.getTaskViewFactory())
.setTransitions(mWMComponent.getTransitions())
- .setStartingSurface(mWMComponent.getStartingSurface());
+ .setStartingSurface(mWMComponent.getStartingSurface())
+ .setTaskSurfaceHelper(mWMComponent.getTaskSurfaceHelper());
} else {
// TODO: Call on prepareSysUIComponentBuilder but not with real components. Other option
// is separating this logic into newly creating SystemUITestsFactory.
@@ -132,8 +133,8 @@ public class SystemUIFactory {
.setAppPairs(Optional.ofNullable(null))
.setTaskViewFactory(Optional.ofNullable(null))
.setTransitions(Transitions.createEmptyForTesting())
- .setStartingSurface(Optional.ofNullable(null));
-
+ .setStartingSurface(Optional.ofNullable(null))
+ .setTaskSurfaceHelper(Optional.ofNullable(null));
}
mSysUIComponent = builder.build();
if (mInitializeComponents) {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
index 146f430c88a1..f8e4bdc83fbb 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
@@ -693,7 +693,6 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
@Override
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
-
// UdfpsController is not BiometricPrompt-specific. It can be active for keyguard or
// enrollment.
if (mUdfpsController != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/SidefpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/SidefpsController.java
index 7fc67bcf79e0..a52296a71960 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/SidefpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/SidefpsController.java
@@ -26,9 +26,11 @@ import android.graphics.PixelFormat;
import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import android.hardware.fingerprint.ISidefpsController;
+import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
+import android.view.Surface;
import android.view.WindowManager;
import com.android.internal.annotations.VisibleForTesting;
@@ -45,20 +47,19 @@ import javax.inject.Inject;
@SysUISingleton
public class SidefpsController {
private static final String TAG = "SidefpsController";
- // TODO (b/188690214): define and retrieve values from framework via SensorProps
- static final int DISPLAY_HEIGHT = 1804;
- static final int DISPLAY_WIDTH = 2208;
- static final int SFPS_INDICATOR_HEIGHT = 225;
- static final int SFPS_Y = 500;
- static final int SFPS_INDICATOR_WIDTH = 50;
-
- @Nullable private SidefpsView mView;
- private final FingerprintManager mFingerprintManager;
- private final Context mContext;
+ @NonNull private final Context mContext;
@NonNull private final LayoutInflater mInflater;
+ private final FingerprintManager mFingerprintManager;
private final WindowManager mWindowManager;
private final DelayableExecutor mFgExecutor;
+ // TODO: update mDisplayHeight and mDisplayWidth for multi-display devices
+ private final int mDisplayHeight;
+ private final int mDisplayWidth;
+
private boolean mIsVisible = false;
+ @Nullable private SidefpsView mView;
+
+ static final int SFPS_AFFORDANCE_WIDTH = 50; // in default portrait mode
@NonNull
private final ISidefpsController mSidefpsControllerImpl = new ISidefpsController.Stub() {
@@ -110,6 +111,11 @@ public class SidefpsController {
WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
mCoreLayoutParams.privateFlags = WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY;
+ DisplayMetrics displayMetrics = new DisplayMetrics();
+ windowManager.getDefaultDisplay().getMetrics(displayMetrics);
+ mDisplayHeight = displayMetrics.heightPixels;
+ mDisplayWidth = displayMetrics.widthPixels;
+
mFingerprintManager.setSidefpsController(mSidefpsControllerImpl);
}
@@ -122,7 +128,6 @@ public class SidefpsController {
void hide() {
if (mView != null) {
- Log.v(TAG, "hideUdfpsOverlay | removing window");
mWindowManager.removeView(mView);
mView.setOnTouchListener(null);
mView.setOnHoverListener(null);
@@ -132,13 +137,14 @@ public class SidefpsController {
}
}
+
void onConfigurationChanged() {
- // If overlay was hidden, it should remain hidden
- if (!mIsVisible) {
+ // If mView is null or if view is hidden, then return.
+ if (mView == null || !mIsVisible) {
return;
}
- // If the overlay needs to be shown, destroy the current overlay, and re-create and show
- // the overlay with the updated LayoutParams.
+ // If the overlay needs to be displayed with a new configuration, destroy the current
+ // overlay, and re-create and show the overlay with the updated LayoutParams.
hide();
show();
}
@@ -148,6 +154,25 @@ public class SidefpsController {
for (FingerprintSensorPropertiesInternal props :
mFingerprintManager.getSensorPropertiesInternal()) {
if (props.isAnySidefpsType()) {
+ // TODO(b/188690214): L155-L173 can be removed once sensorLocationX,
+ // sensorLocationY, and sensorRadius are defined in sensorProps by the HAL
+ int sensorLocationX = 25;
+ int sensorLocationY = 610;
+ int sensorRadius = 112;
+
+ FingerprintSensorPropertiesInternal tempProps =
+ new FingerprintSensorPropertiesInternal(
+ props.sensorId,
+ props.sensorStrength,
+ props.maxEnrollmentsPerUser,
+ props.componentInfo,
+ props.sensorType,
+ props.resetLockoutRequiresHardwareAuthToken,
+ sensorLocationX,
+ sensorLocationY,
+ sensorRadius
+ );
+ props = tempProps;
return props;
}
}
@@ -166,17 +191,30 @@ public class SidefpsController {
*/
private WindowManager.LayoutParams computeLayoutParams() {
mCoreLayoutParams.flags = getCoreLayoutParamFlags();
-
- // Default dimensions assume portrait mode.
- mCoreLayoutParams.x = DISPLAY_WIDTH - SFPS_INDICATOR_WIDTH;
- mCoreLayoutParams.y = SFPS_Y;
- mCoreLayoutParams.height = SFPS_INDICATOR_HEIGHT;
- mCoreLayoutParams.width = SFPS_INDICATOR_WIDTH;
-
- /*
- TODO (b/188692405): recalculate coordinates for non-portrait configurations and folding
- states
- */
+ // Y value of top of affordance in portrait mode, X value of left of affordance in landscape
+ int sfpsLocationY = mSensorProps.sensorLocationY - mSensorProps.sensorRadius;
+ int sfpsAffordanceHeight = mSensorProps.sensorRadius * 2;
+
+ // Calculate coordinates of drawable area for the fps affordance, accounting for orientation
+ switch (mContext.getDisplay().getRotation()) {
+ case Surface.ROTATION_90:
+ mCoreLayoutParams.x = sfpsLocationY;
+ mCoreLayoutParams.y = 0;
+ mCoreLayoutParams.height = SFPS_AFFORDANCE_WIDTH;
+ mCoreLayoutParams.width = sfpsAffordanceHeight;
+ break;
+ case Surface.ROTATION_270:
+ mCoreLayoutParams.x = mDisplayHeight - sfpsLocationY - sfpsAffordanceHeight;
+ mCoreLayoutParams.y = mDisplayWidth - SFPS_AFFORDANCE_WIDTH;
+ mCoreLayoutParams.height = SFPS_AFFORDANCE_WIDTH;
+ mCoreLayoutParams.width = sfpsAffordanceHeight;
+ break;
+ default: // Portrait
+ mCoreLayoutParams.x = mDisplayWidth - SFPS_AFFORDANCE_WIDTH;
+ mCoreLayoutParams.y = sfpsLocationY;
+ mCoreLayoutParams.height = sfpsAffordanceHeight;
+ mCoreLayoutParams.width = SFPS_AFFORDANCE_WIDTH;
+ }
return mCoreLayoutParams;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/SidefpsView.java b/packages/SystemUI/src/com/android/systemui/biometrics/SidefpsView.java
index b9e9b596f54a..4fc59d60ff62 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/SidefpsView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/SidefpsView.java
@@ -16,8 +16,7 @@
package com.android.systemui.biometrics;
-import static com.android.systemui.biometrics.SidefpsController.SFPS_INDICATOR_HEIGHT;
-import static com.android.systemui.biometrics.SidefpsController.SFPS_INDICATOR_WIDTH;
+import static com.android.systemui.biometrics.SidefpsController.SFPS_AFFORDANCE_WIDTH;
import android.annotation.NonNull;
import android.content.Context;
@@ -27,6 +26,7 @@ import android.graphics.Paint;
import android.graphics.RectF;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import android.util.AttributeSet;
+import android.view.Surface;
import android.widget.FrameLayout;
/**
@@ -34,18 +34,22 @@ import android.widget.FrameLayout;
*/
public class SidefpsView extends FrameLayout {
private static final String TAG = "SidefpsView";
+ private static final int POINTER_SIZE_PX = 50;
+ private static final int ROUND_RADIUS = 15;
+
@NonNull private final RectF mSensorRect;
@NonNull private final Paint mSensorRectPaint;
@NonNull private final Paint mPointerText;
- private static final int POINTER_SIZE_PX = 50;
+ @NonNull private final Context mContext;
// Used to obtain the sensor location.
@NonNull private FingerprintSensorPropertiesInternal mSensorProps;
+ @Surface.Rotation private int mOrientation;
public SidefpsView(Context context, AttributeSet attrs) {
super(context, attrs);
super.setWillNotDraw(false);
-
+ mContext = context;
mPointerText = new Paint(0 /* flags */);
mPointerText.setAntiAlias(true);
mPointerText.setColor(Color.WHITE);
@@ -54,7 +58,7 @@ public class SidefpsView extends FrameLayout {
mSensorRect = new RectF();
mSensorRectPaint = new Paint(0 /* flags */);
mSensorRectPaint.setAntiAlias(true);
- mSensorRectPaint.setColor(Color.BLUE);
+ mSensorRectPaint.setColor(Color.BLUE); // TODO: Fix Color
mSensorRectPaint.setStyle(Paint.Style.FILL);
}
@@ -65,11 +69,19 @@ public class SidefpsView extends FrameLayout {
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
- canvas.drawRect(mSensorRect, mSensorRectPaint);
+ canvas.drawRoundRect(mSensorRect, ROUND_RADIUS, ROUND_RADIUS, mSensorRectPaint);
+ int x, y;
+ if (mOrientation == Surface.ROTATION_90 || mOrientation == Surface.ROTATION_270) {
+ x = mSensorProps.sensorRadius + 10;
+ y = SFPS_AFFORDANCE_WIDTH / 2 + 15;
+ } else {
+ x = SFPS_AFFORDANCE_WIDTH / 2 - 10;
+ y = mSensorProps.sensorRadius + 30;
+ }
canvas.drawText(
">",
- SFPS_INDICATOR_WIDTH / 2 - 10, // TODO(b/188690214): retrieve from sensorProps
- SFPS_INDICATOR_HEIGHT / 2 + 30, //TODO(b/188690214): retrieve from sensorProps
+ x,
+ y,
mPointerText
);
}
@@ -77,11 +89,19 @@ public class SidefpsView extends FrameLayout {
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
+ mOrientation = mContext.getDisplay().getRotation();
+ if (mOrientation == Surface.ROTATION_90 || mOrientation == Surface.ROTATION_270) {
+ right = mSensorProps.sensorRadius * 2;
+ bottom = SFPS_AFFORDANCE_WIDTH;
+ } else {
+ right = SFPS_AFFORDANCE_WIDTH;
+ bottom = mSensorProps.sensorRadius * 2;
+ }
mSensorRect.set(
0,
0,
- SFPS_INDICATOR_WIDTH, //TODO(b/188690214): retrieve from sensorProps
- SFPS_INDICATOR_HEIGHT); //TODO(b/188690214): retrieve from sensorProps
+ right,
+ bottom);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
index 5c360a649af0..3726ae132b64 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
@@ -123,6 +123,11 @@ public class UdfpsController implements DozeReceiver {
private int mActivePointerId = -1;
// The timestamp of the most recent touch log.
private long mTouchLogTime;
+ // Sensor has a good capture for this touch. Do not need to illuminate for this particular
+ // touch event anymore. In other words, do not illuminate until user lifts and touches the
+ // sensor area again.
+ // TODO: We should probably try to make touch/illumination things more of a FSM
+ private boolean mGoodCaptureReceived;
@Nullable private UdfpsView mView;
// The current request from FingerprintService. Null if no current request.
@@ -225,48 +230,69 @@ public class UdfpsController implements DozeReceiver {
@Override
public void showUdfpsOverlay(int sensorId, int reason,
@NonNull IUdfpsOverlayControllerCallback callback) {
- final UdfpsEnrollHelper enrollHelper;
- if (reason == IUdfpsOverlayController.REASON_ENROLL_FIND_SENSOR
- || reason == IUdfpsOverlayController.REASON_ENROLL_ENROLLING) {
- enrollHelper = new UdfpsEnrollHelper(mContext, reason);
- } else {
- enrollHelper = null;
- }
-
- mServerRequest = new ServerRequest(reason, callback, enrollHelper);
- updateOverlay();
+ mFgExecutor.execute(() -> {
+ final UdfpsEnrollHelper enrollHelper;
+ if (reason == IUdfpsOverlayController.REASON_ENROLL_FIND_SENSOR
+ || reason == IUdfpsOverlayController.REASON_ENROLL_ENROLLING) {
+ enrollHelper = new UdfpsEnrollHelper(mContext, reason);
+ } else {
+ enrollHelper = null;
+ }
+ mServerRequest = new ServerRequest(reason, callback, enrollHelper);
+ updateOverlay();
+ });
}
@Override
public void hideUdfpsOverlay(int sensorId) {
- mServerRequest = null;
- updateOverlay();
+ mFgExecutor.execute(() -> {
+ mServerRequest = null;
+ updateOverlay();
+ });
+ }
+
+ @Override
+ public void onAcquiredGood(int sensorId) {
+ mFgExecutor.execute(() -> {
+ if (mView == null) {
+ Log.e(TAG, "Null view when onAcquiredGood for sensorId: " + sensorId);
+ return;
+ }
+ mGoodCaptureReceived = true;
+ mView.stopIllumination();
+ });
}
@Override
public void onEnrollmentProgress(int sensorId, int remaining) {
- if (mServerRequest == null) {
- Log.e(TAG, "onEnrollProgress received but serverRequest is null");
- return;
- }
- mServerRequest.onEnrollmentProgress(remaining);
+ mFgExecutor.execute(() -> {
+ if (mServerRequest == null) {
+ Log.e(TAG, "onEnrollProgress received but serverRequest is null");
+ return;
+ }
+ mServerRequest.onEnrollmentProgress(remaining);
+ });
}
@Override
public void onEnrollmentHelp(int sensorId) {
- if (mServerRequest == null) {
- Log.e(TAG, "onEnrollmentHelp received but serverRequest is null");
- return;
- }
- mServerRequest.onEnrollmentHelp();
+ mFgExecutor.execute(() -> {
+ if (mServerRequest == null) {
+ Log.e(TAG, "onEnrollmentHelp received but serverRequest is null");
+ return;
+ }
+ mServerRequest.onEnrollmentHelp();
+ });
}
@Override
public void setDebugMessage(int sensorId, String message) {
- if (mView == null) {
- return;
- }
- mView.setDebugMessage(message);
+ mFgExecutor.execute(() -> {
+ if (mView == null) {
+ return;
+ }
+ mView.setDebugMessage(message);
+ });
}
}
@@ -333,7 +359,7 @@ public class UdfpsController implements DozeReceiver {
private boolean onTouch(View view, MotionEvent event, boolean fromUdfpsView) {
UdfpsView udfpsView = (UdfpsView) view;
- final boolean isFingerDown = udfpsView.isIlluminationRequested();
+ final boolean isIlluminationRequested = udfpsView.isIlluminationRequested();
boolean handled = false;
switch (event.getActionMasked()) {
case MotionEvent.ACTION_OUTSIDE:
@@ -388,7 +414,8 @@ public class UdfpsController implements DozeReceiver {
"minor: %.1f, major: %.1f, v: %.1f, exceedsVelocityThreshold: %b",
minor, major, v, exceedsVelocityThreshold);
final long sinceLastLog = SystemClock.elapsedRealtime() - mTouchLogTime;
- if (!isFingerDown && !exceedsVelocityThreshold) {
+ if (!isIlluminationRequested && !mGoodCaptureReceived &&
+ !exceedsVelocityThreshold) {
onFingerDown((int) x, (int) y, minor, major);
Log.v(TAG, "onTouch | finger down: " + touchInfo);
mTouchLogTime = SystemClock.elapsedRealtime();
@@ -423,7 +450,7 @@ public class UdfpsController implements DozeReceiver {
Log.v(TAG, "onTouch | finger move: " + touchInfo);
mTouchLogTime = SystemClock.elapsedRealtime();
}
- } else if (isFingerDown) {
+ } else {
Log.v(TAG, "onTouch | finger outside");
onFingerUp();
}
@@ -438,10 +465,8 @@ public class UdfpsController implements DozeReceiver {
mVelocityTracker.recycle();
mVelocityTracker = null;
}
- if (isFingerDown) {
- Log.v(TAG, "onTouch | finger up");
- onFingerUp();
- }
+ Log.v(TAG, "onTouch | finger up");
+ onFingerUp();
mFalsingManager.isFalseTouch(UDFPS_AUTHENTICATION);
break;
@@ -795,13 +820,16 @@ public class UdfpsController implements DozeReceiver {
// This method can be called from the UI thread.
private void onFingerUp() {
mActivePointerId = -1;
+ mGoodCaptureReceived = false;
mMainHandler.removeCallbacks(mAcquiredVibration);
if (mView == null) {
Log.w(TAG, "Null view in onFingerUp");
return;
}
mFingerprintManager.onPointerUp(mSensorProps.sensorId);
- mView.stopIllumination();
+ if (mView.isIlluminationRequested()) {
+ mView.stopIllumination();
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
index c04201caa182..0fdc4d8e86a7 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
@@ -36,6 +36,7 @@ import com.android.wm.shell.onehanded.OneHanded;
import com.android.wm.shell.pip.Pip;
import com.android.wm.shell.splitscreen.SplitScreen;
import com.android.wm.shell.startingsurface.StartingSurface;
+import com.android.wm.shell.tasksurfacehelper.TaskSurfaceHelper;
import com.android.wm.shell.transition.ShellTransitions;
import java.util.Optional;
@@ -94,6 +95,9 @@ public interface SysUIComponent {
@BindsInstance
Builder setStartingSurface(Optional<StartingSurface> s);
+ @BindsInstance
+ Builder setTaskSurfaceHelper(Optional<TaskSurfaceHelper> t);
+
SysUIComponent build();
}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java
index bbd95b4d0c90..442d351729d7 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java
@@ -33,6 +33,7 @@ import com.android.wm.shell.onehanded.OneHanded;
import com.android.wm.shell.pip.Pip;
import com.android.wm.shell.splitscreen.SplitScreen;
import com.android.wm.shell.startingsurface.StartingSurface;
+import com.android.wm.shell.tasksurfacehelper.TaskSurfaceHelper;
import com.android.wm.shell.transition.ShellTransitions;
import java.util.Optional;
@@ -102,4 +103,7 @@ public interface WMComponent {
@WMSingleton
Optional<StartingSurface> getStartingSurface();
+
+ @WMSingleton
+ Optional<TaskSurfaceHelper> getTaskSurfaceHelper();
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
index 55feea970e84..d698142674ce 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
@@ -315,8 +315,7 @@ public class MediaControlPanel {
appIconView.clearColorFilter();
if (data.getAppIcon() != null && !data.getResumption()) {
appIconView.setImageIcon(data.getAppIcon());
- int color = Utils.getColorAttrDefaultColor(mContext,
- com.android.internal.R.attr.colorAccentTertiary);
+ int color = mContext.getColor(android.R.color.system_accent2_900);
appIconView.setColorFilter(color);
} else {
appIconView.setColorFilter(getGrayscaleFilter());
diff --git a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
index e0c8af6b8977..ce1066ee41c2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
@@ -80,8 +80,22 @@ public class PagedTileLayout extends ViewPager implements QSTileLayout {
@Override
public void setPageMargin(int marginPixels) {
- if (marginPixels != getPageMargin()) {
- super.setPageMargin(marginPixels);
+ // Using page margins creates some rounding issues that interfere with the correct position
+ // in the onPageChangedListener and therefore present bad positions to the PageIndicator.
+ // Instead, we use negative margins in the container and positive padding in the pages,
+ // matching the margin set from QSContainerImpl (note that new pages will always be inflated
+ // with the correct value.
+ // QSContainerImpl resources are set onAttachedView, so this view will always have the right
+ // values when attached.
+ MarginLayoutParams lp = (MarginLayoutParams) getLayoutParams();
+ lp.setMarginStart(-marginPixels);
+ lp.setMarginEnd(-marginPixels);
+ setLayoutParams(lp);
+
+ int nPages = mPages.size();
+ for (int i = 0; i < nPages; i++) {
+ View v = mPages.get(i);
+ v.setPadding(marginPixels, v.getPaddingTop(), marginPixels, v.getPaddingBottom());
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
index cd97f976540d..edfbed04f70d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
@@ -295,7 +295,7 @@ public class QSContainerImpl extends FrameLayout {
qsPanelController.setContentMargins(mContentPadding, mContentPadding);
// Set it as double the side margin (to simulate end margin of current page +
// start margin of next page).
- qsPanelController.setPageMargin(2 * mSideMargins);
+ qsPanelController.setPageMargin(mSideMargins);
} else if (view == mHeader) {
// No content padding for the header.
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
index 86465b6f6b1a..b60ef1d62ef5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
@@ -382,13 +382,15 @@ public class StackScrollAlgorithm {
final boolean isHunGoingToShade = ambientState.isShadeExpanded()
&& view == ambientState.getTrackedHeadsUpRow();
- if (!isHunGoingToShade) {
- if (ambientState.isExpansionChanging() && !ambientState.isOnKeyguard()) {
- viewState.alpha = Interpolators.getNotificationScrimAlpha(
- ambientState.getExpansionFraction(), true /* notification */);
- } else {
- viewState.alpha = 1f - ambientState.getHideAmount();
- }
+ if (isHunGoingToShade) {
+ // Keep 100% opacity for heads up notification going to shade.
+ } else if (ambientState.isOnKeyguard()) {
+ // Adjust alpha for wakeup to lockscreen.
+ viewState.alpha = 1f - ambientState.getHideAmount();
+ } else if (ambientState.isExpansionChanging()) {
+ // Adjust alpha for shade open & close.
+ viewState.alpha = Interpolators.getNotificationScrimAlpha(
+ ambientState.getExpansionFraction(), true /* notification */);
}
if (view.mustStayOnScreen() && viewState.yTranslation >= 0) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
index eb46fe3c6177..a7b802ac4afc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -75,6 +75,7 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.jank.InteractionJankMonitor;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.internal.policy.ScreenDecorationsUtils;
import com.android.internal.util.LatencyTracker;
import com.android.keyguard.KeyguardStatusView;
import com.android.keyguard.KeyguardStatusViewController;
@@ -906,8 +907,7 @@ public class NotificationPanelViewController extends PanelViewController {
R.dimen.pulse_expansion_max_top_overshoot);
mScrimCornerRadius = mResources.getDimensionPixelSize(
R.dimen.notification_scrim_corner_radius);
- mScreenCornerRadius = mResources.getDimensionPixelSize(
- com.android.internal.R.dimen.rounded_corner_radius);
+ mScreenCornerRadius = (int) ScreenDecorationsUtils.getWindowCornerRadius(mResources);
mNotificationScrimPadding = mResources.getDimensionPixelSize(
R.dimen.notification_side_paddings);
mLockscreenNotificationQSPadding = mResources.getDimensionPixelSize(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt
index 7dccf01dcbc6..ef7fac311799 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt
@@ -53,8 +53,8 @@ class OngoingCallController @Inject constructor(
private val logger: OngoingCallLogger
) : CallbackController<OngoingCallListener> {
- /** Null if there's no ongoing call. */
- private var ongoingCallInfo: OngoingCallInfo? = null
+ /** Non-null if there's an active call notification. */
+ private var callNotificationInfo: CallNotificationInfo? = null
/** True if the application managing the call is visible to the user. */
private var isCallAppVisible: Boolean = true
private var chipView: View? = null
@@ -76,19 +76,34 @@ class OngoingCallController @Inject constructor(
}
override fun onEntryUpdated(entry: NotificationEntry) {
- if (isOngoingCallNotification(entry)) {
- ongoingCallInfo = OngoingCallInfo(
- entry.sbn.notification.`when`,
- entry.sbn.notification.contentIntent.intent,
- entry.sbn.uid)
- updateChip()
- } else if (isCallNotification(entry)) {
- removeChip()
+ // We have a new call notification or our existing call notification has been updated.
+ // TODO(b/183229367): This likely won't work if you take a call from one app then
+ // switch to a call from another app.
+ if (callNotificationInfo == null && isCallNotification(entry) ||
+ (entry.sbn.key == callNotificationInfo?.key)) {
+ val newOngoingCallInfo = CallNotificationInfo(
+ entry.sbn.key,
+ entry.sbn.notification.`when`,
+ entry.sbn.notification.contentIntent.intent,
+ entry.sbn.uid,
+ entry.sbn.notification.extras.getInt(
+ Notification.EXTRA_CALL_TYPE, -1) == CALL_TYPE_ONGOING
+ )
+ if (newOngoingCallInfo == callNotificationInfo) {
+ return
+ }
+
+ callNotificationInfo = newOngoingCallInfo
+ if (newOngoingCallInfo.isOngoing) {
+ updateChip()
+ } else {
+ removeChip()
+ }
}
}
override fun onEntryRemoved(entry: NotificationEntry, reason: Int) {
- if (isOngoingCallNotification(entry)) {
+ if (entry.sbn.key == callNotificationInfo?.key) {
removeChip()
}
}
@@ -126,7 +141,7 @@ class OngoingCallController @Inject constructor(
* Returns true if there's an active ongoing call that should be displayed in a status bar chip.
*/
fun hasOngoingCall(): Boolean {
- return ongoingCallInfo != null &&
+ return callNotificationInfo?.isOngoing == true &&
// When the user is in the phone app, don't show the chip.
!isCallAppVisible
}
@@ -146,7 +161,7 @@ class OngoingCallController @Inject constructor(
}
private fun updateChip() {
- val currentOngoingCallInfo = ongoingCallInfo ?: return
+ val currentCallNotificationInfo = callNotificationInfo ?: return
val currentChipView = chipView
val timeView =
@@ -155,7 +170,7 @@ class OngoingCallController @Inject constructor(
currentChipView?.findViewById<View>(R.id.ongoing_call_chip_background)
if (currentChipView != null && timeView != null && backgroundView != null) {
- timeView.base = currentOngoingCallInfo.callStartTime -
+ timeView.base = currentCallNotificationInfo.callStartTime -
System.currentTimeMillis() +
systemClock.elapsedRealtime()
timeView.start()
@@ -163,17 +178,17 @@ class OngoingCallController @Inject constructor(
currentChipView.setOnClickListener {
logger.logChipClicked()
activityStarter.postStartActivityDismissingKeyguard(
- currentOngoingCallInfo.intent, 0,
+ currentCallNotificationInfo.intent, 0,
ActivityLaunchAnimator.Controller.fromView(backgroundView))
}
- setUpUidObserver(currentOngoingCallInfo)
+ setUpUidObserver(currentCallNotificationInfo)
mListeners.forEach { l -> l.onOngoingCallStateChanged(animate = true) }
} else {
- // If we failed to update the chip, don't store the ongoing call info. Then
- // [hasOngoingCall] will return false and we fall back to typical notification handling.
- ongoingCallInfo = null
+ // If we failed to update the chip, don't store the call info. Then [hasOngoingCall]
+ // will return false and we fall back to typical notification handling.
+ callNotificationInfo = null
if (DEBUG) {
Log.w(TAG, "Ongoing call chip view could not be found; " +
@@ -185,14 +200,14 @@ class OngoingCallController @Inject constructor(
/**
* Sets up an [IUidObserver] to monitor the status of the application managing the ongoing call.
*/
- private fun setUpUidObserver(currentOngoingCallInfo: OngoingCallInfo) {
+ private fun setUpUidObserver(currentCallNotificationInfo: CallNotificationInfo) {
isCallAppVisible = isProcessVisibleToUser(
- iActivityManager.getUidProcessState(currentOngoingCallInfo.uid, null))
+ iActivityManager.getUidProcessState(currentCallNotificationInfo.uid, null))
uidObserver = object : IUidObserver.Stub() {
override fun onUidStateChanged(
uid: Int, procState: Int, procStateSeq: Long, capability: Int) {
- if (uid == currentOngoingCallInfo.uid) {
+ if (uid == currentCallNotificationInfo.uid) {
val oldIsCallAppVisible = isCallAppVisible
isCallAppVisible = isProcessVisibleToUser(procState)
if (oldIsCallAppVisible != isCallAppVisible) {
@@ -225,26 +240,23 @@ class OngoingCallController @Inject constructor(
}
private fun removeChip() {
- ongoingCallInfo = null
+ callNotificationInfo = null
mListeners.forEach { l -> l.onOngoingCallStateChanged(animate = true) }
if (uidObserver != null) {
iActivityManager.unregisterUidObserver(uidObserver)
}
}
- private class OngoingCallInfo(
+ private data class CallNotificationInfo(
+ val key: String,
val callStartTime: Long,
val intent: Intent,
- val uid: Int
+ val uid: Int,
+ /** True if the call is currently ongoing (as opposed to incoming, screening, etc.). */
+ val isOngoing: Boolean
)
}
-private fun isOngoingCallNotification(entry: NotificationEntry): Boolean {
- val extras = entry.sbn.notification.extras
- return isCallNotification(entry) &&
- extras.getInt(Notification.EXTRA_CALL_TYPE, -1) == CALL_TYPE_ONGOING
-}
-
private fun isCallNotification(entry: NotificationEntry): Boolean {
return entry.sbn.notification.isStyle(Notification.CallStyle::class.java)
}
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
index 6c306743e4ce..6ef74505a681 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
@@ -73,6 +73,8 @@ import com.android.wm.shell.splitscreen.SplitScreenController;
import com.android.wm.shell.startingsurface.StartingSurface;
import com.android.wm.shell.startingsurface.StartingWindowController;
import com.android.wm.shell.startingsurface.StartingWindowTypeAlgorithm;
+import com.android.wm.shell.tasksurfacehelper.TaskSurfaceHelper;
+import com.android.wm.shell.tasksurfacehelper.TaskSurfaceHelperController;
import com.android.wm.shell.transition.ShellTransitions;
import com.android.wm.shell.transition.Transitions;
@@ -253,6 +255,24 @@ public abstract class WMShellBaseModule {
}
//
+ // Task to Surface communication
+ //
+
+ @WMSingleton
+ @Provides
+ static Optional<TaskSurfaceHelper> provideTaskSurfaceHelper(
+ Optional<TaskSurfaceHelperController> taskSurfaceController) {
+ return taskSurfaceController.map((controller) -> controller.asTaskSurfaceHelper());
+ }
+
+ @WMSingleton
+ @Provides
+ static Optional<TaskSurfaceHelperController> provideTaskSurfaceHelperController(
+ ShellTaskOrganizer taskOrganizer, @ShellMainThread ShellExecutor mainExecutor) {
+ return Optional.ofNullable(new TaskSurfaceHelperController(taskOrganizer, mainExecutor));
+ }
+
+ //
// Pip (optional feature)
//
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
index 46c18480c77b..9322aa9b0ea8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
@@ -275,6 +275,7 @@ public class UdfpsControllerTest extends SysuiTestCase {
mScreenObserver.onScreenTurnedOn();
mFgExecutor.runAllReady();
mUdfpsController.onAodInterrupt(0, 0, 0f, 0f);
+ when(mUdfpsView.isIlluminationRequested()).thenReturn(true);
// WHEN it is cancelled
mUdfpsController.onCancelUdfps();
// THEN the illumination is hidden
@@ -289,6 +290,7 @@ public class UdfpsControllerTest extends SysuiTestCase {
mScreenObserver.onScreenTurnedOn();
mFgExecutor.runAllReady();
mUdfpsController.onAodInterrupt(0, 0, 0f, 0f);
+ when(mUdfpsView.isIlluminationRequested()).thenReturn(true);
// WHEN it times out
mFgExecutor.advanceClockToNext();
mFgExecutor.runAllReady();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerTest.kt
index 3a71ecf42699..ca3cff98b78c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerTest.kt
@@ -55,6 +55,8 @@ import org.mockito.Mockito.mock
import org.mockito.Mockito.never
import org.mockito.Mockito.times
import org.mockito.Mockito.verify
+import org.mockito.Mockito.reset
+
import org.mockito.MockitoAnnotations
private const val CALL_UID = 900
@@ -138,15 +140,51 @@ class OngoingCallControllerTest : SysuiTestCase() {
.onOngoingCallStateChanged(anyBoolean())
}
+ /**
+ * If a call notification is never added before #onEntryRemoved is called, then the listener
+ * should never be notified.
+ */
@Test
- fun onEntryRemoved_ongoingCallNotif_listenerNotified() {
+ fun onEntryRemoved_callNotifNeverAddedBeforehand_listenerNotNotified() {
notifCollectionListener.onEntryRemoved(createOngoingCallNotifEntry(), REASON_USER_STOPPED)
+ verify(mockOngoingCallListener, never()).onOngoingCallStateChanged(anyBoolean())
+ }
+
+ @Test
+ fun onEntryRemoved_callNotifAddedThenRemoved_listenerNotified() {
+ val ongoingCallNotifEntry = createOngoingCallNotifEntry()
+ notifCollectionListener.onEntryAdded(ongoingCallNotifEntry)
+ reset(mockOngoingCallListener)
+
+ notifCollectionListener.onEntryRemoved(ongoingCallNotifEntry, REASON_USER_STOPPED)
+
verify(mockOngoingCallListener).onOngoingCallStateChanged(anyBoolean())
}
+ /** Regression test for b/188491504. */
@Test
- fun onEntryRemoved_notOngoingCallNotif_listenerNotNotified() {
+ fun onEntryRemoved_removedNotifHasSameKeyAsAddedNotif_listenerNotified() {
+ val ongoingCallNotifEntry = createOngoingCallNotifEntry()
+ notifCollectionListener.onEntryAdded(ongoingCallNotifEntry)
+ reset(mockOngoingCallListener)
+
+ // Create another notification based on the ongoing call one, but remove the features that
+ // made it a call notification.
+ val removedEntryBuilder = NotificationEntryBuilder(ongoingCallNotifEntry)
+ removedEntryBuilder.modifyNotification(context).style = null
+
+ notifCollectionListener.onEntryRemoved(removedEntryBuilder.build(), REASON_USER_STOPPED)
+
+ verify(mockOngoingCallListener).onOngoingCallStateChanged(anyBoolean())
+ }
+
+
+ @Test
+ fun onEntryRemoved_notifKeyDoesNotMatchOngoingCallNotif_listenerNotNotified() {
+ notifCollectionListener.onEntryAdded(createOngoingCallNotifEntry())
+ reset(mockOngoingCallListener)
+
notifCollectionListener.onEntryRemoved(createNotCallNotifEntry(), REASON_USER_STOPPED)
verify(mockOngoingCallListener, never()).onOngoingCallStateChanged(anyBoolean())
@@ -158,6 +196,20 @@ class OngoingCallControllerTest : SysuiTestCase() {
}
@Test
+ fun hasOngoingCall_unrelatedNotifSent_returnsFalse() {
+ notifCollectionListener.onEntryUpdated(createNotCallNotifEntry())
+
+ assertThat(controller.hasOngoingCall()).isFalse()
+ }
+
+ @Test
+ fun hasOngoingCall_screeningCallNotifSent_returnsFalse() {
+ notifCollectionListener.onEntryUpdated(createScreeningCallNotifEntry())
+
+ assertThat(controller.hasOngoingCall()).isFalse()
+ }
+
+ @Test
fun hasOngoingCall_ongoingCallNotifSentAndCallAppNotVisible_returnsTrue() {
`when`(mockIActivityManager.getUidProcessState(eq(CALL_UID), nullable(String::class.java)))
.thenReturn(PROC_STATE_INVISIBLE)
@@ -224,6 +276,7 @@ class OngoingCallControllerTest : SysuiTestCase() {
fun setChipView_whenHasOngoingCallIsTrue_listenerNotifiedWithNewView() {
// Start an ongoing call.
notifCollectionListener.onEntryUpdated(createOngoingCallNotifEntry())
+ reset(mockOngoingCallListener)
lateinit var newChipView: View
TestableLooper.get(this).runWithLooper {
@@ -233,10 +286,7 @@ class OngoingCallControllerTest : SysuiTestCase() {
// Change the chip view associated with the controller.
controller.setChipView(newChipView)
- // Verify the listener was notified once for the initial call and again when the new view
- // was set.
- verify(mockOngoingCallListener, times(2))
- .onOngoingCallStateChanged(anyBoolean())
+ verify(mockOngoingCallListener).onOngoingCallStateChanged(anyBoolean())
}
@Test
@@ -245,6 +295,7 @@ class OngoingCallControllerTest : SysuiTestCase() {
`when`(mockIActivityManager.getUidProcessState(eq(CALL_UID), nullable(String::class.java)))
.thenReturn(PROC_STATE_INVISIBLE)
notifCollectionListener.onEntryUpdated(createOngoingCallNotifEntry())
+ reset(mockOngoingCallListener)
val captor = ArgumentCaptor.forClass(IUidObserver.Stub::class.java)
verify(mockIActivityManager).registerUidObserver(
@@ -256,9 +307,7 @@ class OngoingCallControllerTest : SysuiTestCase() {
mainExecutor.advanceClockToLast()
mainExecutor.runAllReady();
- // Once for when the call was started, and another time when the process visibility changes.
- verify(mockOngoingCallListener, times(2))
- .onOngoingCallStateChanged(anyBoolean())
+ verify(mockOngoingCallListener).onOngoingCallStateChanged(anyBoolean())
}
@Test
@@ -267,6 +316,7 @@ class OngoingCallControllerTest : SysuiTestCase() {
`when`(mockIActivityManager.getUidProcessState(eq(CALL_UID), nullable(String::class.java)))
.thenReturn(PROC_STATE_VISIBLE)
notifCollectionListener.onEntryUpdated(createOngoingCallNotifEntry())
+ reset(mockOngoingCallListener)
val captor = ArgumentCaptor.forClass(IUidObserver.Stub::class.java)
verify(mockIActivityManager).registerUidObserver(
@@ -278,9 +328,7 @@ class OngoingCallControllerTest : SysuiTestCase() {
mainExecutor.advanceClockToLast()
mainExecutor.runAllReady();
- // Once for when the call was started, and another time when the process visibility changes.
- verify(mockOngoingCallListener, times(2))
- .onOngoingCallStateChanged(anyBoolean())
+ verify(mockOngoingCallListener).onOngoingCallStateChanged(anyBoolean())
}
@Test
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 8041ec4a9727..9e4290098843 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -811,7 +811,8 @@ public final class ActiveServices {
}
mAm.mAppOpsService.startOperation(AppOpsManager.getToken(mAm.mAppOpsService),
AppOpsManager.OP_START_FOREGROUND, r.appInfo.uid, r.packageName, null,
- true, false, null, false);
+ true, false, null, false, AppOpsManager.ATTRIBUTION_FLAGS_NONE,
+ AppOpsManager.ATTRIBUTION_CHAIN_ID_NONE);
}
final ServiceMap smap = getServiceMapLocked(r.userId);
@@ -1881,7 +1882,8 @@ public final class ActiveServices {
mAm.mAppOpsService.startOperation(
AppOpsManager.getToken(mAm.mAppOpsService),
AppOpsManager.OP_START_FOREGROUND, r.appInfo.uid, r.packageName,
- null, true, false, "", false);
+ null, true, false, "", false, AppOpsManager.ATTRIBUTION_FLAGS_NONE,
+ AppOpsManager.ATTRIBUTION_CHAIN_ID_NONE);
registerAppOpCallbackLocked(r);
mAm.updateForegroundServiceUsageStats(r.name, r.userId, true);
}
@@ -6191,7 +6193,8 @@ public final class ActiveServices {
r.mFgsNotificationDeferred,
r.mFgsNotificationShown,
durationMs,
- r.mStartForegroundCount);
+ r.mStartForegroundCount,
+ ActivityManagerUtils.hashComponentNameForAtom(r.shortInstanceName));
}
boolean canAllowWhileInUsePermissionInFgsLocked(int callingPid, int callingUid,
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 6e500e4ea5ea..294762139f50 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -156,6 +156,7 @@ import android.app.ActivityThread;
import android.app.AnrController;
import android.app.AppGlobals;
import android.app.AppOpsManager;
+import android.app.AppOpsManager.AttributionFlags;
import android.app.AppOpsManagerInternal.CheckOpsDelegate;
import android.app.ApplicationErrorReport;
import android.app.ApplicationExitInfo;
@@ -346,6 +347,7 @@ import com.android.internal.util.FastPrintWriter;
import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.util.MemInfoReader;
import com.android.internal.util.Preconditions;
+import com.android.internal.util.function.DecFunction;
import com.android.internal.util.function.HeptFunction;
import com.android.internal.util.function.HexFunction;
import com.android.internal.util.function.NonaFunction;
@@ -353,6 +355,7 @@ import com.android.internal.util.function.OctFunction;
import com.android.internal.util.function.QuadFunction;
import com.android.internal.util.function.QuintFunction;
import com.android.internal.util.function.TriFunction;
+import com.android.internal.util.function.UndecFunction;
import com.android.server.AlarmManagerInternal;
import com.android.server.DeviceIdleInternal;
import com.android.server.DisplayThread;
@@ -1833,7 +1836,9 @@ public class ActivityManagerService extends IActivityManager.Stub
final int[] cameraOp = {AppOpsManager.OP_CAMERA};
mAppOpsService.startWatchingActive(cameraOp, new IAppOpsActiveCallback.Stub() {
@Override
- public void opActiveChanged(int op, int uid, String packageName, boolean active) {
+ public void opActiveChanged(int op, int uid, String packageName, String attributionTag,
+ boolean active, @AttributionFlags int attributionFlags,
+ int attributionChainId) {
cameraActiveChanged(uid, active);
}
});
@@ -6216,8 +6221,20 @@ public class ActivityManagerService extends IActivityManager.Stub
// signature we just use the first package in the UID. For shared
// UIDs we may blame the wrong app but that is Okay as they are
// in the same security/privacy sandbox.
- final AndroidPackage androidPackage = mPackageManagerInt
- .getPackage(Binder.getCallingUid());
+ final int uid = Binder.getCallingUid();
+ // Here we handle some of the special UIDs (mediaserver, systemserver, etc)
+ final String packageName = AppOpsManager.resolvePackageName(uid,
+ /*packageName*/ null);
+ final AndroidPackage androidPackage;
+ if (packageName != null) {
+ androidPackage = mPackageManagerInt.getPackage(packageName);
+ } else {
+ androidPackage = mPackageManagerInt.getPackage(uid);
+ }
+ if (androidPackage == null) {
+ Log.e(TAG, "Cannot find package for uid: " + uid);
+ return null;
+ }
final AttributionSource attributionSource = new AttributionSource(
Binder.getCallingUid(), androidPackage.getPackageName(), null);
pfd = cph.provider.openFile(attributionSource, uri, "r", null);
@@ -16866,7 +16883,7 @@ public class ActivityManagerService extends IActivityManager.Stub
try {
return superImpl.apply(code, new AttributionSource(shellUid,
"com.android.shell", attributionSource.getAttributionTag(),
- attributionSource.getNext()),
+ attributionSource.getToken(), attributionSource.getNext()),
shouldCollectAsyncNotedOp, message, shouldCollectMessage,
skiProxyOperation);
} finally {
@@ -16882,8 +16899,9 @@ public class ActivityManagerService extends IActivityManager.Stub
@Nullable String packageName, @Nullable String attributionTag,
boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp,
@Nullable String message, boolean shouldCollectMessage,
- @NonNull NonaFunction<IBinder, Integer, Integer, String, String, Boolean,
- Boolean, String, Boolean, SyncNotedAppOp> superImpl) {
+ @AttributionFlags int attributionFlags, int attributionChainId,
+ @NonNull UndecFunction<IBinder, Integer, Integer, String, String, Boolean,
+ Boolean, String, Boolean, Integer, Integer, SyncNotedAppOp> superImpl) {
if (uid == mTargetUid && isTargetOp(code)) {
final int shellUid = UserHandle.getUid(UserHandle.getUserId(uid),
Process.SHELL_UID);
@@ -16891,57 +16909,62 @@ public class ActivityManagerService extends IActivityManager.Stub
try {
return superImpl.apply(token, code, shellUid, "com.android.shell",
attributionTag, startIfModeDefault, shouldCollectAsyncNotedOp, message,
- shouldCollectMessage);
+ shouldCollectMessage, attributionFlags, attributionChainId);
} finally {
Binder.restoreCallingIdentity(identity);
}
}
return superImpl.apply(token, code, uid, packageName, attributionTag,
- startIfModeDefault, shouldCollectAsyncNotedOp, message, shouldCollectMessage);
+ startIfModeDefault, shouldCollectAsyncNotedOp, message, shouldCollectMessage,
+ attributionFlags, attributionChainId);
}
@Override
- public SyncNotedAppOp startProxyOperation(IBinder token, int code,
+ public SyncNotedAppOp startProxyOperation(int code,
@NonNull AttributionSource attributionSource, boolean startIfModeDefault,
boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage,
- boolean skipProsyOperation, @NonNull OctFunction<IBinder, Integer,
- AttributionSource, Boolean, Boolean, String, Boolean, Boolean,
- SyncNotedAppOp> superImpl) {
+ boolean skipProxyOperation, @AttributionFlags int proxyAttributionFlags,
+ @AttributionFlags int proxiedAttributionFlags, int attributionChainId,
+ @NonNull DecFunction<Integer, AttributionSource, Boolean, Boolean, String, Boolean,
+ Boolean, Integer, Integer, Integer, SyncNotedAppOp> superImpl) {
if (attributionSource.getUid() == mTargetUid && isTargetOp(code)) {
final int shellUid = UserHandle.getUid(UserHandle.getUserId(
attributionSource.getUid()), Process.SHELL_UID);
final long identity = Binder.clearCallingIdentity();
try {
- return superImpl.apply(token, code, new AttributionSource(shellUid,
- "com.android.shell", attributionSource.getAttributionTag(),
- attributionSource.getNext()), startIfModeDefault,
- shouldCollectAsyncNotedOp, message, shouldCollectMessage,
- skipProsyOperation);
+ return superImpl.apply(code, new AttributionSource(shellUid,
+ "com.android.shell", attributionSource.getAttributionTag(),
+ attributionSource.getToken(), attributionSource.getNext()),
+ startIfModeDefault, shouldCollectAsyncNotedOp, message,
+ shouldCollectMessage, skipProxyOperation, proxyAttributionFlags,
+ proxiedAttributionFlags, attributionChainId);
} finally {
Binder.restoreCallingIdentity(identity);
}
}
- return superImpl.apply(token, code, attributionSource, startIfModeDefault,
- shouldCollectAsyncNotedOp, message, shouldCollectMessage, skipProsyOperation);
+ return superImpl.apply(code, attributionSource, startIfModeDefault,
+ shouldCollectAsyncNotedOp, message, shouldCollectMessage, skipProxyOperation,
+ proxyAttributionFlags, proxiedAttributionFlags, attributionChainId);
}
@Override
- public void finishProxyOperation(IBinder clientId, int code,
- @NonNull AttributionSource attributionSource,
- @NonNull TriFunction<IBinder, Integer, AttributionSource, Void> superImpl) {
+ public void finishProxyOperation(int code, @NonNull AttributionSource attributionSource,
+ boolean skipProxyOperation, @NonNull TriFunction<Integer, AttributionSource,
+ Boolean, Void> superImpl) {
if (attributionSource.getUid() == mTargetUid && isTargetOp(code)) {
final int shellUid = UserHandle.getUid(UserHandle.getUserId(
attributionSource.getUid()), Process.SHELL_UID);
final long identity = Binder.clearCallingIdentity();
try {
- superImpl.apply(clientId, code, new AttributionSource(shellUid,
+ superImpl.apply(code, new AttributionSource(shellUid,
"com.android.shell", attributionSource.getAttributionTag(),
- attributionSource.getNext()));
+ attributionSource.getToken(), attributionSource.getNext()),
+ skipProxyOperation);
} finally {
Binder.restoreCallingIdentity(identity);
}
}
- superImpl.apply(clientId, code, attributionSource);
+ superImpl.apply(code, attributionSource, skipProxyOperation);
}
private boolean isTargetOp(int code) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerUtils.java b/services/core/java/com/android/server/am/ActivityManagerUtils.java
index dd2414866542..5506ad1b245b 100644
--- a/services/core/java/com/android/server/am/ActivityManagerUtils.java
+++ b/services/core/java/com/android/server/am/ActivityManagerUtils.java
@@ -121,4 +121,12 @@ public class ActivityManagerUtils {
return (((double) hash) / Integer.MAX_VALUE) <= rate;
}
+
+ /**
+ * @param shortInstanceName {@link ServiceRecord#shortInstanceName}.
+ * @return hash of the ServiceRecord's shortInstanceName, combined with ANDROID_ID.
+ */
+ public static int hashComponentNameForAtom(String shortInstanceName) {
+ return getUnsignedHashUnCached(shortInstanceName) ^ getAndroidIdHash();
+ }
}
diff --git a/services/core/java/com/android/server/am/AssistDataRequester.java b/services/core/java/com/android/server/am/AssistDataRequester.java
index 70a54cfdafa5..98ad81d7d9de 100644
--- a/services/core/java/com/android/server/am/AssistDataRequester.java
+++ b/services/core/java/com/android/server/am/AssistDataRequester.java
@@ -16,6 +16,7 @@
package com.android.server.am;
+import static android.app.ActivityManager.ASSIST_CONTEXT_CONTENT;
import static android.app.ActivityManager.ASSIST_CONTEXT_FULL;
import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.app.AppOpsManager.OP_NONE;
@@ -143,45 +144,47 @@ public class AssistDataRequester extends IAssistDataReceiver.Stub {
* Request that autofill data be loaded asynchronously. The resulting data will be provided
* through the {@link AssistDataRequesterCallbacks}.
*
- * See {@link #requestData(List, boolean, boolean, boolean, boolean, boolean, int, String,
- * boolean)}.
+ * See {@link #requestData(List, boolean, boolean, boolean, boolean, boolean, boolean, int,
+ * String, boolean)}.
*/
public void requestAutofillData(List<IBinder> activityTokens, int callingUid,
String callingPackage) {
requestData(activityTokens, true /* requestAutofillData */,
true /* fetchData */, false /* fetchScreenshot */,
- true /* allowFetchData */, false /* allowFetchScreenshot */,
- false /* ignoreTopActivityCheck */, callingUid, callingPackage);
+ true /* fetchStructure */, true /* allowFetchData */,
+ false /* allowFetchScreenshot */, false /* ignoreTopActivityCheck */, callingUid,
+ callingPackage);
}
/**
* Request that assist data be loaded asynchronously. The resulting data will be provided
* through the {@link AssistDataRequesterCallbacks}.
*
- * See {@link #requestData(List, boolean, boolean, boolean, boolean, boolean, int, String,
- * boolean)}.
+ * See {@link #requestData(List, boolean, boolean, boolean, boolean, boolean, boolean, int,
+ * String, boolean)}.
*/
public void requestAssistData(List<IBinder> activityTokens, final boolean fetchData,
final boolean fetchScreenshot, boolean allowFetchData, boolean allowFetchScreenshot,
int callingUid, String callingPackage) {
- requestAssistData(activityTokens, fetchData, fetchScreenshot, allowFetchData,
- allowFetchScreenshot, false /* ignoreTopActivityCheck */, callingUid,
- callingPackage);
+ requestAssistData(activityTokens, fetchData, fetchScreenshot, true /* fetchStructure */,
+ allowFetchData, allowFetchScreenshot, false /* ignoreTopActivityCheck */,
+ callingUid, callingPackage);
}
/**
* Request that assist data be loaded asynchronously. The resulting data will be provided
* through the {@link AssistDataRequesterCallbacks}.
*
- * See {@link #requestData(List, boolean, boolean, boolean, boolean, boolean, int, String,
- * boolean)}.
+ * See {@link #requestData(List, boolean, boolean, boolean, boolean, boolean, boolean, int,
+ * String, boolean)}.
*/
public void requestAssistData(List<IBinder> activityTokens, final boolean fetchData,
- final boolean fetchScreenshot, boolean allowFetchData, boolean allowFetchScreenshot,
- boolean ignoreTopActivityCheck, int callingUid, String callingPackage) {
+ final boolean fetchScreenshot, final boolean fetchStructure, boolean allowFetchData,
+ boolean allowFetchScreenshot, boolean ignoreTopActivityCheck, int callingUid,
+ String callingPackage) {
requestData(activityTokens, false /* requestAutofillData */, fetchData, fetchScreenshot,
- allowFetchData, allowFetchScreenshot, ignoreTopActivityCheck, callingUid,
- callingPackage);
+ fetchStructure, allowFetchData, allowFetchScreenshot, ignoreTopActivityCheck,
+ callingUid, callingPackage);
}
/**
@@ -197,6 +200,8 @@ public class AssistDataRequester extends IAssistDataReceiver.Stub {
* @param fetchScreenshot whether or not to fetch the screenshot, only applies if fetchData is
* true, the caller is allowed to fetch the assist data, and the current activity allows
* assist data to be fetched from it
+ * @param fetchStructure whether or not to fetch the AssistStructure along with the
+ * AssistContent
* @param allowFetchData to be joined with other checks, determines whether or not the requester
* is allowed to fetch the assist data
* @param allowFetchScreenshot to be joined with other checks, determines whether or not the
@@ -205,9 +210,9 @@ public class AssistDataRequester extends IAssistDataReceiver.Stub {
* making the request. Used when passing an activity from Recents.
*/
private void requestData(List<IBinder> activityTokens, final boolean requestAutofillData,
- final boolean fetchData, final boolean fetchScreenshot, boolean allowFetchData,
- boolean allowFetchScreenshot, boolean ignoreTopActivityCheck, int callingUid,
- String callingPackage) {
+ final boolean fetchData, final boolean fetchScreenshot, final boolean fetchStructure,
+ boolean allowFetchData, boolean allowFetchScreenshot, boolean ignoreTopActivityCheck,
+ int callingUid, String callingPackage) {
// TODO(b/34090158): Known issue, if the assist data is not allowed on the current activity,
// then no assist data is requested for any of the other activities
@@ -246,13 +251,18 @@ public class AssistDataRequester extends IAssistDataReceiver.Stub {
Bundle receiverExtras = new Bundle();
receiverExtras.putInt(KEY_RECEIVER_EXTRA_INDEX, i);
receiverExtras.putInt(KEY_RECEIVER_EXTRA_COUNT, numActivities);
- boolean result = requestAutofillData
- ? mActivityTaskManager.requestAutofillData(this,
- receiverExtras, topActivity, 0 /* flags */)
- : mActivityTaskManager.requestAssistContextExtras(
- ASSIST_CONTEXT_FULL, this, receiverExtras, topActivity,
+ boolean result;
+ if (requestAutofillData) {
+ result = mActivityTaskManager.requestAutofillData(this, receiverExtras,
+ topActivity, 0 /* flags */);
+ } else {
+ int requestType = fetchStructure ? ASSIST_CONTEXT_FULL :
+ ASSIST_CONTEXT_CONTENT;
+ result = mActivityTaskManager.requestAssistContextExtras(
+ requestType, this, receiverExtras, topActivity,
/* checkActivityIsTop= */ (i == 0)
&& !ignoreTopActivityCheck, /* newSessionId= */ i == 0);
+ }
if (result) {
mPendingDataCount++;
} else if (i == 0) {
diff --git a/services/core/java/com/android/server/app/GameManagerService.java b/services/core/java/com/android/server/app/GameManagerService.java
index f70b0fb1d207..96db1adcfddb 100644
--- a/services/core/java/com/android/server/app/GameManagerService.java
+++ b/services/core/java/com/android/server/app/GameManagerService.java
@@ -267,7 +267,8 @@ public final class GameManagerService extends IGameManagerService.Stub {
mAllowDownscale = true;
}
} catch (PackageManager.NameNotFoundException e) {
- Slog.e(TAG, "Failed to get package metadata", e);
+ // Not all packages are installed, hence ignore those that are not installed yet.
+ Slog.v(TAG, "Failed to get package metadata");
}
final String configString = DeviceConfig.getProperty(
DeviceConfig.NAMESPACE_GAME_OVERLAY, packageName);
@@ -531,9 +532,8 @@ public final class GameManagerService extends IGameManagerService.Stub {
final ApplicationInfo applicationInfo = mPackageManager
.getApplicationInfoAsUser(packageName, PackageManager.MATCH_ALL, userId);
if (applicationInfo.category != ApplicationInfo.CATEGORY_GAME) {
- Slog.e(TAG, "Ignoring attempt to get the Game Mode for '" + packageName
- + "' which is not categorized as a game: applicationInfo.flags = "
- + applicationInfo.flags + ", category = " + applicationInfo.category);
+ // The game mode for applications that are not identified as game is always
+ // UNSUPPORTED. See {@link PackageManager#setApplicationCategoryHint(String, int)}
return GameManager.GAME_MODE_UNSUPPORTED;
}
} catch (PackageManager.NameNotFoundException e) {
@@ -571,9 +571,8 @@ public final class GameManagerService extends IGameManagerService.Stub {
final ApplicationInfo applicationInfo = mPackageManager
.getApplicationInfoAsUser(packageName, PackageManager.MATCH_ALL, userId);
if (applicationInfo.category != ApplicationInfo.CATEGORY_GAME) {
- Slog.e(TAG, "Ignoring attempt to set the Game Mode for '" + packageName
- + "' which is not categorized as a game: applicationInfo.flags = "
- + applicationInfo.flags + ", category = " + applicationInfo.category);
+ // Ignore attempt to set the game mode for applications that are not identified
+ // as game. See {@link PackageManager#setApplicationCategoryHint(String, int)}
return;
}
} catch (PackageManager.NameNotFoundException e) {
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 541dcdc94a51..fdb3d8ca371c 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -84,6 +84,7 @@ import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
import android.app.AppGlobals;
import android.app.AppOpsManager;
+import android.app.AppOpsManager.AttributionFlags;
import android.app.AppOpsManager.AttributedOpEntry;
import android.app.AppOpsManager.HistoricalOps;
import android.app.AppOpsManager.Mode;
@@ -200,6 +201,7 @@ import java.util.Map;
import java.util.Objects;
import java.util.Scanner;
import java.util.concurrent.ThreadLocalRandom;
+import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
public class AppOpsService extends IAppOpsService.Stub {
@@ -257,11 +259,6 @@ public class AppOpsService extends IAppOpsService.Stub {
private static final int MAX_UNUSED_POOLED_OBJECTS = 3;
private static final int RARELY_USED_PACKAGES_INITIALIZATION_DELAY_MILLIS = 300000;
- //TODO: remove this when development is done.
- private static final int DEBUG_FGS_ALLOW_WHILE_IN_USE = 0;
- private static final int DEBUG_FGS_ENFORCE_TYPE = 1;
-
-
final Context mContext;
final AtomicFile mFile;
private final @Nullable File mNoteOpCallerStacktracesFile;
@@ -414,9 +411,10 @@ public class AppOpsService extends IAppOpsService.Stub {
}
InProgressStartOpEvent acquire(long startTime, long elapsedTime, @NonNull IBinder clientId,
- @NonNull Runnable onDeath, int proxyUid, @Nullable String proxyPackageName,
- @Nullable String proxyAttributionTag, @AppOpsManager.UidState int uidState,
- @OpFlags int flags) throws RemoteException {
+ @Nullable String attributionTag, @NonNull Runnable onDeath, int proxyUid,
+ @Nullable String proxyPackageName, @Nullable String proxyAttributionTag,
+ @AppOpsManager.UidState int uidState, @OpFlags int flags, @AttributionFlags
+ int attributionFlags, int attributionChainId) throws RemoteException {
InProgressStartOpEvent recycled = acquire();
@@ -427,13 +425,14 @@ public class AppOpsService extends IAppOpsService.Stub {
}
if (recycled != null) {
- recycled.reinit(startTime, elapsedTime, clientId, onDeath, uidState, flags,
- proxyInfo, mOpEventProxyInfoPool);
+ recycled.reinit(startTime, elapsedTime, clientId, attributionTag, onDeath,
+ uidState, flags, proxyInfo, attributionFlags, attributionChainId,
+ mOpEventProxyInfoPool);
return recycled;
}
- return new InProgressStartOpEvent(startTime, elapsedTime, clientId, onDeath, uidState,
- proxyInfo, flags);
+ return new InProgressStartOpEvent(startTime, elapsedTime, clientId, attributionTag,
+ onDeath, uidState, proxyInfo, flags, attributionFlags, attributionChainId);
}
}
@@ -685,6 +684,9 @@ public class AppOpsService extends IAppOpsService.Stub {
/** Id of the client that started the event */
private @NonNull IBinder mClientId;
+ /** The attribution tag for this operation */
+ private @Nullable String mAttributionTag;
+
/** To call when client dies */
private @NonNull Runnable mOnDeath;
@@ -700,30 +702,44 @@ public class AppOpsService extends IAppOpsService.Stub {
/** How many times the op was started but not finished yet */
int numUnfinishedStarts;
+ /** The attribution flags related to this event */
+ private @AttributionFlags int mAttributionFlags;
+
+ /** The id of the attribution chain this even is a part of */
+ private int mAttributionChainId;
+
/**
* Create a new {@link InProgressStartOpEvent}.
*
* @param startTime The time {@link #startOperation} was called
* @param startElapsedTime The elapsed time when {@link #startOperation} was called
* @param clientId The client id of the caller of {@link #startOperation}
+ * @param attributionTag The attribution tag for the operation.
* @param onDeath The code to execute on client death
* @param uidState The uidstate of the app {@link #startOperation} was called for
+ * @param attributionFlags the attribution flags for this operation.
+ * @param attributionChainId the unique id of the attribution chain this op is a part of.
* @param proxy The proxy information, if {@link #startProxyOperation} was called
* @param flags The trusted/nontrusted/self flags.
*
* @throws RemoteException If the client is dying
*/
private InProgressStartOpEvent(long startTime, long startElapsedTime,
- @NonNull IBinder clientId, @NonNull Runnable onDeath,
- @AppOpsManager.UidState int uidState, @Nullable OpEventProxyInfo proxy,
- @OpFlags int flags) throws RemoteException {
+ @NonNull IBinder clientId, @Nullable String attributionTag,
+ @NonNull Runnable onDeath, @AppOpsManager.UidState int uidState,
+ @Nullable OpEventProxyInfo proxy, @OpFlags int flags,
+ @AttributionFlags int attributionFlags, int attributionChainId)
+ throws RemoteException {
mStartTime = startTime;
mStartElapsedTime = startElapsedTime;
mClientId = clientId;
+ mAttributionTag = attributionTag;
mOnDeath = onDeath;
mUidState = uidState;
mProxy = proxy;
mFlags = flags;
+ mAttributionFlags = attributionFlags;
+ mAttributionChainId = attributionChainId;
clientId.linkToDeath(this, 0);
}
@@ -744,21 +760,27 @@ public class AppOpsService extends IAppOpsService.Stub {
* @param startTime The time {@link #startOperation} was called
* @param startElapsedTime The elapsed time when {@link #startOperation} was called
* @param clientId The client id of the caller of {@link #startOperation}
+ * @param attributionTag The attribution tag for this operation.
* @param onDeath The code to execute on client death
* @param uidState The uidstate of the app {@link #startOperation} was called for
* @param flags The flags relating to the proxy
* @param proxy The proxy information, if {@link #startProxyOperation} was called
+ * @param attributionFlags the attribution flags for this operation.
+ * @param attributionChainId the unique id of the attribution chain this op is a part of.
* @param proxyPool The pool to release previous {@link OpEventProxyInfo} to
*
* @throws RemoteException If the client is dying
*/
public void reinit(long startTime, long startElapsedTime, @NonNull IBinder clientId,
- @NonNull Runnable onDeath, @AppOpsManager.UidState int uidState, @OpFlags int flags,
- @Nullable OpEventProxyInfo proxy, @NonNull Pools.Pool<OpEventProxyInfo> proxyPool
+ @Nullable String attributionTag, @NonNull Runnable onDeath,
+ @AppOpsManager.UidState int uidState, @OpFlags int flags,
+ @Nullable OpEventProxyInfo proxy, @AttributionFlags int attributionFlags,
+ int attributionChainId, @NonNull Pools.Pool<OpEventProxyInfo> proxyPool
) throws RemoteException {
mStartTime = startTime;
mStartElapsedTime = startElapsedTime;
mClientId = clientId;
+ mAttributionTag = attributionTag;
mOnDeath = onDeath;
mUidState = uidState;
mFlags = flags;
@@ -767,6 +789,8 @@ public class AppOpsService extends IAppOpsService.Stub {
proxyPool.release(mProxy);
}
mProxy = proxy;
+ mAttributionFlags = attributionFlags;
+ mAttributionChainId = attributionChainId;
clientId.linkToDeath(this, 0);
}
@@ -791,7 +815,7 @@ public class AppOpsService extends IAppOpsService.Stub {
return mUidState;
}
- /** @return proxy info for the access */
+ /** @return proxy tag for the access */
public @Nullable OpEventProxyInfo getProxy() {
return mProxy;
}
@@ -800,6 +824,16 @@ public class AppOpsService extends IAppOpsService.Stub {
public @OpFlags int getFlags() {
return mFlags;
}
+
+ /** @return attributoin flags used for the access */
+ public @AttributionFlags int getAttributionFlags() {
+ return mAttributionFlags;
+ }
+
+ /** @return attributoin chiang id for the access */
+ public int getAttributionChainId() {
+ return mAttributionChainId;
+ }
}
private final class AttributedOp {
@@ -943,32 +977,38 @@ public class AppOpsService extends IAppOpsService.Stub {
* @param proxyAttributionTag The attribution tag of the proxy app
* @param uidState UID state of the app startOp is called for
* @param flags The proxy flags
+ * @param attributionFlags The attribution flags associated with this operation.
+ * @param attributionChainId The if of the attribution chain this operations is a part of.
*/
public void started(@NonNull IBinder clientId, int proxyUid,
@Nullable String proxyPackageName, @Nullable String proxyAttributionTag,
- @AppOpsManager.UidState int uidState, @OpFlags int flags) throws RemoteException {
- started(clientId, proxyUid, proxyPackageName, proxyAttributionTag, uidState, flags,
- true);
+ @AppOpsManager.UidState int uidState, @OpFlags int flags, @AttributionFlags
+ int attributionFlags, int attributionChainId) throws RemoteException {
+ started(clientId, proxyUid, proxyPackageName, proxyAttributionTag,
+ uidState, flags,/*triggerCallbackIfNeeded*/ true, attributionFlags,
+ attributionChainId);
}
private void started(@NonNull IBinder clientId, int proxyUid,
@Nullable String proxyPackageName, @Nullable String proxyAttributionTag,
@AppOpsManager.UidState int uidState, @OpFlags int flags,
- boolean triggerCallbackIfNeeded) throws RemoteException {
- startedOrPaused(clientId, proxyUid, proxyPackageName, proxyAttributionTag,
- uidState, flags, triggerCallbackIfNeeded, true);
+ boolean triggerCallbackIfNeeded, @AttributionFlags int attributionFlags,
+ int attributionChainId) throws RemoteException {
+ startedOrPaused(clientId, proxyUid, proxyPackageName,
+ proxyAttributionTag, uidState, flags, triggerCallbackIfNeeded,
+ /*triggerCallbackIfNeeded*/ true, attributionFlags, attributionChainId);
}
private void startedOrPaused(@NonNull IBinder clientId, int proxyUid,
@Nullable String proxyPackageName, @Nullable String proxyAttributionTag,
@AppOpsManager.UidState int uidState, @OpFlags int flags,
- boolean triggerCallbackIfNeeded, boolean isStarted) throws RemoteException {
+ boolean triggerCallbackIfNeeded, boolean isStarted, @AttributionFlags
+ int attributionFlags, int attributionChainId) throws RemoteException {
if (triggerCallbackIfNeeded && !parent.isRunning() && isStarted) {
- scheduleOpActiveChangedIfNeededLocked(parent.op, parent.uid,
- parent.packageName, true);
+ scheduleOpActiveChangedIfNeededLocked(parent.op, parent.uid, parent.packageName,
+ tag, true, attributionFlags, attributionChainId);
}
-
if (isStarted && mInProgressEvents == null) {
mInProgressEvents = new ArrayMap<>(1);
} else if (mPausedInProgressEvents == null) {
@@ -981,9 +1021,10 @@ public class AppOpsService extends IAppOpsService.Stub {
InProgressStartOpEvent event = events.get(clientId);
if (event == null) {
event = mInProgressStartOpEventPool.acquire(startTime,
- SystemClock.elapsedRealtime(), clientId,
+ SystemClock.elapsedRealtime(), clientId, tag,
PooledLambda.obtainRunnable(AppOpsService::onClientDeath, this, clientId),
- proxyUid, proxyPackageName, proxyAttributionTag, uidState, flags);
+ proxyUid, proxyPackageName, proxyAttributionTag, uidState, flags,
+ attributionFlags, attributionChainId);
events.put(clientId, event);
} else {
if (uidState != event.mUidState) {
@@ -994,10 +1035,10 @@ public class AppOpsService extends IAppOpsService.Stub {
event.numUnfinishedStarts++;
if (isStarted) {
+ // TODO: Consider storing the attribution chain flags and id
mHistoricalRegistry.incrementOpAccessedCount(parent.op, parent.uid,
parent.packageName, tag, uidState, flags, startTime);
}
-
}
/**
@@ -1063,7 +1104,8 @@ public class AppOpsService extends IAppOpsService.Stub {
// TODO ntmyren: Also callback for single attribution tag activity changes
if (triggerCallbackIfNeeded && !parent.isRunning()) {
scheduleOpActiveChangedIfNeededLocked(parent.op, parent.uid,
- parent.packageName, false);
+ parent.packageName, tag, false, event.getAttributionFlags(),
+ event.getAttributionChainId());
}
}
}
@@ -1103,9 +1145,10 @@ public class AppOpsService extends IAppOpsService.Stub {
*/
public void createPaused(@NonNull IBinder clientId, int proxyUid,
@Nullable String proxyPackageName, @Nullable String proxyAttributionTag,
- @AppOpsManager.UidState int uidState, @OpFlags int flags) throws RemoteException {
+ @AppOpsManager.UidState int uidState, @OpFlags int flags, @AttributionFlags
+ int attributionFlags, int attributionChainId) throws RemoteException {
startedOrPaused(clientId, proxyUid, proxyPackageName, proxyAttributionTag,
- uidState, flags, true, false);
+ uidState, flags, true, false, attributionFlags, attributionChainId);
}
/**
@@ -1124,9 +1167,11 @@ public class AppOpsService extends IAppOpsService.Stub {
InProgressStartOpEvent event = mInProgressEvents.valueAt(i);
mPausedInProgressEvents.put(event.mClientId, event);
finishOrPause(event.mClientId, true, true);
+
+ scheduleOpActiveChangedIfNeededLocked(parent.op, parent.uid,
+ parent.packageName, tag, false,
+ event.getAttributionFlags(), event.getAttributionChainId());
}
- scheduleOpActiveChangedIfNeededLocked(parent.op, parent.uid,
- parent.packageName, false);
mInProgressEvents = null;
}
@@ -1153,10 +1198,10 @@ public class AppOpsService extends IAppOpsService.Stub {
event.mStartTime = startTime;
mHistoricalRegistry.incrementOpAccessedCount(parent.op, parent.uid,
parent.packageName, tag, event.mUidState, event.mFlags, startTime);
- }
- if (shouldSendActive) {
- scheduleOpActiveChangedIfNeededLocked(parent.op, parent.uid,
- parent.packageName, true);
+ if (shouldSendActive) {
+ scheduleOpActiveChangedIfNeededLocked(parent.op, parent.uid, parent.packageName,
+ tag, true, event.getAttributionFlags(), event.getAttributionChainId());
+ }
}
mPausedInProgressEvents = null;
}
@@ -1210,10 +1255,12 @@ public class AppOpsService extends IAppOpsService.Stub {
// previously removed unfinished start counts back
if (proxy != null) {
started(event.getClientId(), proxy.getUid(), proxy.getPackageName(),
- proxy.getAttributionTag(), newState, event.getFlags(), false);
+ proxy.getAttributionTag(), newState, event.getFlags(), false,
+ event.getAttributionFlags(), event.getAttributionChainId());
} else {
started(event.getClientId(), Process.INVALID_UID, null, null, newState,
- OP_FLAG_SELF, false);
+ OP_FLAG_SELF, false, event.getAttributionFlags(),
+ event.getAttributionChainId());
}
InProgressStartOpEvent newEvent = mInProgressEvents.get(binders.get(i));
@@ -3321,9 +3368,10 @@ public class AppOpsService extends IAppOpsService.Stub {
scheduleOpNotedIfNeededLocked(code, uid, packageName, attributionTag, flags,
AppOpsManager.MODE_IGNORED);
if (DEBUG) Slog.d(TAG, "noteOperation: no op for code " + code + " uid " + uid
- + " package " + packageName);
+ + " package " + packageName + "flags: " +
+ AppOpsManager.flagsToString(flags));
return new SyncNotedAppOp(AppOpsManager.MODE_ERRORED, code, attributionTag,
- packageName);
+ packageName + " flags: " + AppOpsManager.flagsToString(flags));
}
final Op op = getOpLocked(ops, code, uid, true);
final AttributedOp attributedOp = op.getOrCreateAttribution(op, attributionTag);
@@ -3349,7 +3397,7 @@ public class AppOpsService extends IAppOpsService.Stub {
if (uidMode != AppOpsManager.MODE_ALLOWED) {
if (DEBUG) Slog.d(TAG, "noteOperation: uid reject #" + uidMode + " for code "
+ switchCode + " (" + code + ") uid " + uid + " package "
- + packageName);
+ + packageName + " flags: " + AppOpsManager.flagsToString(flags));
attributedOp.rejected(uidState.state, flags);
scheduleOpNotedIfNeededLocked(code, uid, packageName, attributionTag, flags,
uidMode);
@@ -3362,7 +3410,7 @@ public class AppOpsService extends IAppOpsService.Stub {
if (mode != AppOpsManager.MODE_ALLOWED) {
if (DEBUG) Slog.d(TAG, "noteOperation: reject #" + mode + " for code "
+ switchCode + " (" + code + ") uid " + uid + " package "
- + packageName);
+ + packageName + " flags: " + AppOpsManager.flagsToString(flags));
attributedOp.rejected(uidState.state, flags);
scheduleOpNotedIfNeededLocked(code, uid, packageName, attributionTag, flags,
mode);
@@ -3373,7 +3421,8 @@ public class AppOpsService extends IAppOpsService.Stub {
Slog.d(TAG,
"noteOperation: allowing code " + code + " uid " + uid + " package "
+ packageName + (attributionTag == null ? ""
- : "." + attributionTag));
+ : "." + attributionTag) + " flags: "
+ + AppOpsManager.flagsToString(flags));
}
scheduleOpNotedIfNeededLocked(code, uid, packageName, attributionTag, flags,
AppOpsManager.MODE_ALLOWED);
@@ -3674,16 +3723,18 @@ public class AppOpsService extends IAppOpsService.Stub {
public SyncNotedAppOp startOperation(IBinder token, int code, int uid,
@Nullable String packageName, @Nullable String attributionTag,
boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp,
- String message, boolean shouldCollectMessage) {
+ String message, boolean shouldCollectMessage, @AttributionFlags int attributionFlags,
+ int attributionChainId) {
return mCheckOpsDelegateDispatcher.startOperation(token, code, uid, packageName,
attributionTag, startIfModeDefault, shouldCollectAsyncNotedOp, message,
- shouldCollectMessage);
+ shouldCollectMessage, attributionFlags, attributionChainId);
}
private SyncNotedAppOp startOperationImpl(@NonNull IBinder clientId, int code, int uid,
@Nullable String packageName, @Nullable String attributionTag,
boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp, @NonNull String message,
- boolean shouldCollectMessage) {
+ boolean shouldCollectMessage, @AttributionFlags int attributionFlags,
+ int attributionChainId) {
verifyIncomingUid(uid);
verifyIncomingOp(code);
verifyIncomingPackage(packageName, UserHandle.getUserId(uid));
@@ -3707,29 +3758,36 @@ public class AppOpsService extends IAppOpsService.Stub {
}
return startOperationUnchecked(clientId, code, uid, packageName, attributionTag,
Process.INVALID_UID, null, null, OP_FLAG_SELF, startIfModeDefault,
- shouldCollectAsyncNotedOp, message, shouldCollectMessage, false);
+ shouldCollectAsyncNotedOp, message, shouldCollectMessage, attributionFlags,
+ attributionChainId, /*dryRun*/ false);
}
@Override
- public SyncNotedAppOp startProxyOperation(IBinder clientId, int code,
+ public SyncNotedAppOp startProxyOperation(int code,
@NonNull AttributionSource attributionSource, boolean startIfModeDefault,
boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage,
- boolean skipProxyOperation) {
- return mCheckOpsDelegateDispatcher.startProxyOperation(clientId, code, attributionSource,
+ boolean skipProxyOperation, @AttributionFlags int proxyAttributionFlags,
+ @AttributionFlags int proxiedAttributionFlags, int attributionChainId) {
+ return mCheckOpsDelegateDispatcher.startProxyOperation(code, attributionSource,
startIfModeDefault, shouldCollectAsyncNotedOp, message, shouldCollectMessage,
- skipProxyOperation);
+ skipProxyOperation, proxyAttributionFlags, proxiedAttributionFlags,
+ attributionChainId);
}
- private SyncNotedAppOp startProxyOperationImpl(IBinder clientId, int code,
+ private SyncNotedAppOp startProxyOperationImpl(int code,
@NonNull AttributionSource attributionSource,
boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp, String message,
- boolean shouldCollectMessage, boolean skipProxyOperation) {
+ boolean shouldCollectMessage, boolean skipProxyOperation, @AttributionFlags
+ int proxyAttributionFlags, @AttributionFlags int proxiedAttributionFlags,
+ int attributionChainId) {
final int proxyUid = attributionSource.getUid();
final String proxyPackageName = attributionSource.getPackageName();
final String proxyAttributionTag = attributionSource.getAttributionTag();
+ final IBinder proxyToken = attributionSource.getToken();
final int proxiedUid = attributionSource.getNextUid();
final String proxiedPackageName = attributionSource.getNextPackageName();
final String proxiedAttributionTag = attributionSource.getNextAttributionTag();
+ final IBinder proxiedToken = attributionSource.getNextToken();
verifyIncomingProxyUid(attributionSource);
verifyIncomingOp(code);
@@ -3762,10 +3820,11 @@ public class AppOpsService extends IAppOpsService.Stub {
if (!skipProxyOperation) {
// Test if the proxied operation will succeed before starting the proxy operation
- final SyncNotedAppOp testProxiedOp = startOperationUnchecked(clientId, code, proxiedUid,
- resolvedProxiedPackageName, proxiedAttributionTag, proxyUid,
+ final SyncNotedAppOp testProxiedOp = startOperationUnchecked(proxiedToken, code,
+ proxiedUid, resolvedProxiedPackageName, proxiedAttributionTag, proxyUid,
resolvedProxyPackageName, proxyAttributionTag, proxiedFlags, startIfModeDefault,
- shouldCollectAsyncNotedOp, message, shouldCollectMessage, true);
+ shouldCollectAsyncNotedOp, message, shouldCollectMessage,
+ proxiedAttributionFlags, attributionChainId, /*dryRun*/ true);
if (!shouldStartForMode(testProxiedOp.getOpMode(), startIfModeDefault)) {
return testProxiedOp;
}
@@ -3773,19 +3832,21 @@ public class AppOpsService extends IAppOpsService.Stub {
final int proxyFlags = isProxyTrusted ? AppOpsManager.OP_FLAG_TRUSTED_PROXY
: AppOpsManager.OP_FLAG_UNTRUSTED_PROXY;
- final SyncNotedAppOp proxyAppOp = startOperationUnchecked(clientId, code, proxyUid,
+ final SyncNotedAppOp proxyAppOp = startOperationUnchecked(proxyToken, code, proxyUid,
resolvedProxyPackageName, proxyAttributionTag, Process.INVALID_UID, null, null,
proxyFlags, startIfModeDefault, !isProxyTrusted, "proxy " + message,
- shouldCollectMessage, false);
+ shouldCollectMessage, proxyAttributionFlags, attributionChainId,
+ /*dryRun*/ false);
if (!shouldStartForMode(proxyAppOp.getOpMode(), startIfModeDefault)) {
return proxyAppOp;
}
}
- return startOperationUnchecked(clientId, code, proxiedUid, resolvedProxiedPackageName,
+ return startOperationUnchecked(proxiedToken, code, proxiedUid, resolvedProxiedPackageName,
proxiedAttributionTag, proxyUid, resolvedProxyPackageName, proxyAttributionTag,
proxiedFlags, startIfModeDefault, shouldCollectAsyncNotedOp, message,
- shouldCollectMessage, false);
+ shouldCollectMessage, proxiedAttributionFlags, attributionChainId,
+ /*dryRun*/ false);
}
private boolean shouldStartForMode(int mode, boolean startIfModeDefault) {
@@ -3796,7 +3857,8 @@ public class AppOpsService extends IAppOpsService.Stub {
@NonNull String packageName, @Nullable String attributionTag, int proxyUid,
String proxyPackageName, @Nullable String proxyAttributionTag, @OpFlags int flags,
boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp, @Nullable String message,
- boolean shouldCollectMessage, boolean dryRun) {
+ boolean shouldCollectMessage, @AttributionFlags int attributionFlags,
+ int attributionChainId, boolean dryRun) {
RestrictionBypass bypass;
try {
bypass = verifyAndGetBypass(uid, packageName, attributionTag, proxyPackageName);
@@ -3818,7 +3880,8 @@ public class AppOpsService extends IAppOpsService.Stub {
flags, AppOpsManager.MODE_IGNORED);
}
if (DEBUG) Slog.d(TAG, "startOperation: no op for code " + code + " uid " + uid
- + " package " + packageName);
+ + " package " + packageName + " flags: "
+ + AppOpsManager.flagsToString(flags));
return new SyncNotedAppOp(AppOpsManager.MODE_ERRORED, code, attributionTag,
packageName);
}
@@ -3835,7 +3898,7 @@ public class AppOpsService extends IAppOpsService.Stub {
if (DEBUG) {
Slog.d(TAG, "startOperation: uid reject #" + uidMode + " for code "
+ switchCode + " (" + code + ") uid " + uid + " package "
- + packageName);
+ + packageName + " flags: " + AppOpsManager.flagsToString(flags));
}
if (!dryRun) {
attributedOp.rejected(uidState.state, flags);
@@ -3852,7 +3915,7 @@ public class AppOpsService extends IAppOpsService.Stub {
&& (!startIfModeDefault || mode != MODE_DEFAULT)) {
if (DEBUG) Slog.d(TAG, "startOperation: reject #" + mode + " for code "
+ switchCode + " (" + code + ") uid " + uid + " package "
- + packageName);
+ + packageName + " flags: " + AppOpsManager.flagsToString(flags));
if (!dryRun) {
attributedOp.rejected(uidState.state, flags);
scheduleOpStartedIfNeededLocked(code, uid, packageName, attributionTag,
@@ -3862,15 +3925,18 @@ public class AppOpsService extends IAppOpsService.Stub {
}
}
if (DEBUG) Slog.d(TAG, "startOperation: allowing code " + code + " uid " + uid
- + " package " + packageName + " restricted: " + isRestricted);
+ + " package " + packageName + " restricted: " + isRestricted
+ + " flags: " + AppOpsManager.flagsToString(flags));
if (!dryRun) {
try {
if (isRestricted) {
attributedOp.createPaused(clientId, proxyUid, proxyPackageName,
- proxyAttributionTag, uidState.state, flags);
+ proxyAttributionTag, uidState.state, flags, attributionFlags,
+ attributionChainId);
} else {
attributedOp.started(clientId, proxyUid, proxyPackageName,
- proxyAttributionTag, uidState.state, flags);
+ proxyAttributionTag, uidState.state, flags, attributionFlags,
+ attributionChainId);
}
} catch (RemoteException e) {
throw new RuntimeException(e);
@@ -3905,21 +3971,26 @@ public class AppOpsService extends IAppOpsService.Stub {
}
@Override
- public void finishProxyOperation(IBinder clientId, int code,
- @NonNull AttributionSource attributionSource) {
- mCheckOpsDelegateDispatcher.finishProxyOperation(clientId, code, attributionSource);
+ public void finishProxyOperation(int code, @NonNull AttributionSource attributionSource,
+ boolean skipProxyOperation) {
+ mCheckOpsDelegateDispatcher.finishProxyOperation(code, attributionSource,
+ skipProxyOperation);
}
- private Void finishProxyOperationImpl(IBinder clientId, int code,
- @NonNull AttributionSource attributionSource) {
+ private Void finishProxyOperationImpl(int code, @NonNull AttributionSource attributionSource,
+ boolean skipProxyOperation) {
final int proxyUid = attributionSource.getUid();
final String proxyPackageName = attributionSource.getPackageName();
final String proxyAttributionTag = attributionSource.getAttributionTag();
+ final IBinder proxyToken = attributionSource.getToken();
final int proxiedUid = attributionSource.getNextUid();
final String proxiedPackageName = attributionSource.getNextPackageName();
final String proxiedAttributionTag = attributionSource.getNextAttributionTag();
+ final IBinder proxiedToken = attributionSource.getNextToken();
- verifyIncomingUid(proxyUid);
+ skipProxyOperation = resolveSkipProxyOperation(skipProxyOperation, attributionSource);
+
+ verifyIncomingProxyUid(attributionSource);
verifyIncomingOp(code);
verifyIncomingPackage(proxyPackageName, UserHandle.getUserId(proxyUid));
verifyIncomingPackage(proxiedPackageName, UserHandle.getUserId(proxiedUid));
@@ -3930,8 +4001,10 @@ public class AppOpsService extends IAppOpsService.Stub {
return null;
}
- finishOperationUnchecked(clientId, code, proxyUid, resolvedProxyPackageName,
- proxyAttributionTag);
+ if (!skipProxyOperation) {
+ finishOperationUnchecked(proxyToken, code, proxyUid, resolvedProxyPackageName,
+ proxyAttributionTag);
+ }
String resolvedProxiedPackageName = AppOpsManager.resolvePackageName(proxiedUid,
proxiedPackageName);
@@ -3939,7 +4012,7 @@ public class AppOpsService extends IAppOpsService.Stub {
return null;
}
- finishOperationUnchecked(clientId, code, proxiedUid, resolvedProxiedPackageName,
+ finishOperationUnchecked(proxiedToken, code, proxiedUid, resolvedProxiedPackageName,
proxiedAttributionTag);
return null;
@@ -3981,8 +4054,9 @@ public class AppOpsService extends IAppOpsService.Stub {
}
}
- private void scheduleOpActiveChangedIfNeededLocked(int code, int uid, String packageName,
- boolean active) {
+ private void scheduleOpActiveChangedIfNeededLocked(int code, int uid, @NonNull
+ String packageName, @Nullable String attributionTag, boolean active, @AttributionFlags
+ int attributionFlags, int attributionChainId) {
ArraySet<ActiveCallback> dispatchedCallbacks = null;
final int callbackListCount = mActiveWatchers.size();
for (int i = 0; i < callbackListCount; i++) {
@@ -4003,11 +4077,13 @@ public class AppOpsService extends IAppOpsService.Stub {
}
mHandler.sendMessage(PooledLambda.obtainMessage(
AppOpsService::notifyOpActiveChanged,
- this, dispatchedCallbacks, code, uid, packageName, active));
+ this, dispatchedCallbacks, code, uid, packageName, attributionTag, active,
+ attributionFlags, attributionChainId));
}
private void notifyOpActiveChanged(ArraySet<ActiveCallback> callbacks,
- int code, int uid, String packageName, boolean active) {
+ int code, int uid, @NonNull String packageName, @Nullable String attributionTag,
+ boolean active, @AttributionFlags int attributionFlags, int attributionChainId) {
// There are features watching for mode changes such as window manager
// and location manager which are in our process. The callbacks in these
// features may require permissions our remote caller does not have.
@@ -4017,7 +4093,8 @@ public class AppOpsService extends IAppOpsService.Stub {
for (int i = 0; i < callbackCount; i++) {
final ActiveCallback callback = callbacks.valueAt(i);
try {
- callback.mCallback.opActiveChanged(code, uid, packageName, active);
+ callback.mCallback.opActiveChanged(code, uid, packageName, attributionTag,
+ active, attributionFlags, attributionChainId);
} catch (RemoteException e) {
/* do nothing */
}
@@ -5023,6 +5100,8 @@ public class AppOpsService extends IAppOpsService.Stub {
}
static class Shell extends ShellCommand {
+ static final AtomicInteger sAttributionChainIds = new AtomicInteger(0);
+
final IAppOpsService mInterface;
final AppOpsService mInternal;
@@ -5491,7 +5570,9 @@ public class AppOpsService extends IAppOpsService.Stub {
if (shell.packageName != null) {
shell.mInterface.startOperation(shell.mToken, shell.op, shell.packageUid,
shell.packageName, shell.attributionTag, true, true,
- "appops start shell command", true);
+ "appops start shell command", true,
+ AppOpsManager.ATTRIBUTION_FLAG_ACCESSOR,
+ shell.sAttributionChainIds.incrementAndGet());
} else {
return -1;
}
@@ -6421,7 +6502,9 @@ public class AppOpsService extends IAppOpsService.Stub {
@NonNull String proxiedPackageName) {
Objects.requireNonNull(proxyPackageName);
Objects.requireNonNull(proxiedPackageName);
- Binder.withCleanCallingIdentity(() -> {
+ final long callingUid = Binder.getCallingUid();
+ final long identity = Binder.clearCallingIdentity();
+ try {
final List<AppOpsManager.PackageOps> packageOps = getOpsForPackage(proxiedUid,
proxiedPackageName, new int[] {op});
if (packageOps == null || packageOps.isEmpty()) {
@@ -6436,13 +6519,13 @@ public class AppOpsService extends IAppOpsService.Stub {
return false;
}
final OpEventProxyInfo proxyInfo = opEntry.getLastProxyInfo(
- AppOpsManager.OP_FLAG_TRUSTED_PROXY
- | AppOpsManager.OP_FLAG_UNTRUSTED_PROXY);
- return proxyInfo != null && Binder.getCallingUid() == proxyInfo.getUid()
+ OP_FLAG_TRUSTED_PROXIED | AppOpsManager.OP_FLAG_UNTRUSTED_PROXIED);
+ return proxyInfo != null && callingUid == proxyInfo.getUid()
&& proxyPackageName.equals(proxyInfo.getPackageName())
&& Objects.equals(proxyAttributionTag, proxyInfo.getAttributionTag());
- });
- return false;
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
}
@Override
@@ -7275,89 +7358,101 @@ public class AppOpsService extends IAppOpsService.Stub {
public SyncNotedAppOp startOperation(IBinder token, int code, int uid,
@Nullable String packageName, @NonNull String attributionTag,
boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp,
- @Nullable String message, boolean shouldCollectMessage) {
+ @Nullable String message, boolean shouldCollectMessage,
+ @AttributionFlags int attributionFlags, int attributionChainId) {
if (mPolicy != null) {
if (mCheckOpsDelegate != null) {
return mPolicy.startOperation(token, code, uid, packageName,
attributionTag, startIfModeDefault, shouldCollectAsyncNotedOp, message,
- shouldCollectMessage, this::startDelegateOperationImpl);
+ shouldCollectMessage, attributionFlags, attributionChainId,
+ this::startDelegateOperationImpl);
} else {
return mPolicy.startOperation(token, code, uid, packageName, attributionTag,
startIfModeDefault, shouldCollectAsyncNotedOp, message,
- shouldCollectMessage, AppOpsService.this::startOperationImpl);
+ shouldCollectMessage, attributionFlags, attributionChainId,
+ AppOpsService.this::startOperationImpl);
}
} else if (mCheckOpsDelegate != null) {
return startDelegateOperationImpl(token, code, uid, packageName, attributionTag,
startIfModeDefault, shouldCollectAsyncNotedOp, message,
- shouldCollectMessage);
+ shouldCollectMessage, attributionFlags, attributionChainId);
}
return startOperationImpl(token, code, uid, packageName, attributionTag,
- startIfModeDefault, shouldCollectAsyncNotedOp, message, shouldCollectMessage);
+ startIfModeDefault, shouldCollectAsyncNotedOp, message, shouldCollectMessage,
+ attributionFlags, attributionChainId);
}
private SyncNotedAppOp startDelegateOperationImpl(IBinder token, int code, int uid,
@Nullable String packageName, @Nullable String attributionTag,
boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp, String message,
- boolean shouldCollectMessage) {
+ boolean shouldCollectMessage, @AttributionFlags int attributionFlags,
+ int attributionChainId) {
return mCheckOpsDelegate.startOperation(token, code, uid, packageName, attributionTag,
startIfModeDefault, shouldCollectAsyncNotedOp, message, shouldCollectMessage,
- AppOpsService.this::startOperationImpl);
+ attributionFlags, attributionChainId, AppOpsService.this::startOperationImpl);
}
- public SyncNotedAppOp startProxyOperation(IBinder clientId, int code,
+ public SyncNotedAppOp startProxyOperation(int code,
@NonNull AttributionSource attributionSource, boolean startIfModeDefault,
boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage,
- boolean skipProxyOperation) {
+ boolean skipProxyOperation, @AttributionFlags int proxyAttributionFlags,
+ @AttributionFlags int proxiedAttributionFlags, int attributionChainId) {
if (mPolicy != null) {
if (mCheckOpsDelegate != null) {
- return mPolicy.startProxyOperation(clientId, code, attributionSource,
+ return mPolicy.startProxyOperation(code, attributionSource,
startIfModeDefault, shouldCollectAsyncNotedOp, message,
- shouldCollectMessage, skipProxyOperation,
+ shouldCollectMessage, skipProxyOperation, proxyAttributionFlags,
+ proxiedAttributionFlags, attributionChainId,
this::startDelegateProxyOperationImpl);
} else {
- return mPolicy.startProxyOperation(clientId, code, attributionSource,
+ return mPolicy.startProxyOperation(code, attributionSource,
startIfModeDefault, shouldCollectAsyncNotedOp, message,
- shouldCollectMessage, skipProxyOperation,
+ shouldCollectMessage, skipProxyOperation, proxyAttributionFlags,
+ proxiedAttributionFlags, attributionChainId,
AppOpsService.this::startProxyOperationImpl);
}
} else if (mCheckOpsDelegate != null) {
- return startDelegateProxyOperationImpl(clientId, code,
- attributionSource, startIfModeDefault, shouldCollectAsyncNotedOp, message,
- shouldCollectMessage, skipProxyOperation);
+ return startDelegateProxyOperationImpl(code, attributionSource,
+ startIfModeDefault, shouldCollectAsyncNotedOp, message,
+ shouldCollectMessage, skipProxyOperation, proxyAttributionFlags,
+ proxiedAttributionFlags, attributionChainId);
}
- return startProxyOperationImpl(clientId, code, attributionSource, startIfModeDefault,
- shouldCollectAsyncNotedOp, message, shouldCollectMessage, skipProxyOperation);
+ return startProxyOperationImpl(code, attributionSource, startIfModeDefault,
+ shouldCollectAsyncNotedOp, message, shouldCollectMessage, skipProxyOperation,
+ proxyAttributionFlags, proxiedAttributionFlags, attributionChainId);
}
-
- private SyncNotedAppOp startDelegateProxyOperationImpl(IBinder token, int code,
+ private SyncNotedAppOp startDelegateProxyOperationImpl(int code,
@NonNull AttributionSource attributionSource, boolean startIfModeDefault,
boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage,
- boolean skipProxyOperation) {
- return mCheckOpsDelegate.startProxyOperation(token, code, attributionSource,
+ boolean skipProxyOperation, @AttributionFlags int proxyAttributionFlags,
+ @AttributionFlags int proxiedAttributionFlsgs, int attributionChainId) {
+ return mCheckOpsDelegate.startProxyOperation(code, attributionSource,
startIfModeDefault, shouldCollectAsyncNotedOp, message, shouldCollectMessage,
- skipProxyOperation, AppOpsService.this::startProxyOperationImpl);
+ skipProxyOperation, proxyAttributionFlags, proxiedAttributionFlsgs,
+ attributionChainId, AppOpsService.this::startProxyOperationImpl);
}
- public void finishProxyOperation(IBinder clientId, int code,
- @NonNull AttributionSource attributionSource) {
+ public void finishProxyOperation(int code,
+ @NonNull AttributionSource attributionSource, boolean skipProxyOperation) {
if (mPolicy != null) {
if (mCheckOpsDelegate != null) {
- mPolicy.finishProxyOperation(clientId, code, attributionSource,
- this::finishDelegateProxyOperationImpl);
+ mPolicy.finishProxyOperation(code, attributionSource,
+ skipProxyOperation, this::finishDelegateProxyOperationImpl);
} else {
- mPolicy.finishProxyOperation(clientId, code, attributionSource,
- AppOpsService.this::finishProxyOperationImpl);
+ mPolicy.finishProxyOperation(code, attributionSource,
+ skipProxyOperation, AppOpsService.this::finishProxyOperationImpl);
}
} else if (mCheckOpsDelegate != null) {
- finishDelegateProxyOperationImpl(clientId, code, attributionSource);
+ finishDelegateProxyOperationImpl(code, attributionSource, skipProxyOperation);
+ } else {
+ finishProxyOperationImpl(code, attributionSource, skipProxyOperation);
}
- finishProxyOperationImpl(clientId, code, attributionSource);
}
- private Void finishDelegateProxyOperationImpl(IBinder clientId, int code,
- @NonNull AttributionSource attributionSource) {
- mCheckOpsDelegate.finishProxyOperation(clientId, code, attributionSource,
+ private Void finishDelegateProxyOperationImpl(int code,
+ @NonNull AttributionSource attributionSource, boolean skipProxyOperation) {
+ mCheckOpsDelegate.finishProxyOperation(code, attributionSource, skipProxyOperation,
AppOpsService.this::finishProxyOperationImpl);
return null;
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/UdfpsHelper.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/UdfpsHelper.java
index f0e45978c365..879c8a0317d7 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/UdfpsHelper.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/UdfpsHelper.java
@@ -113,6 +113,19 @@ public class UdfpsHelper {
}
}
+ public static void onAcquiredGood(int sensorId,
+ @Nullable IUdfpsOverlayController udfpsOverlayController) {
+ if (udfpsOverlayController == null) {
+ return;
+ }
+
+ try {
+ udfpsOverlayController.onAcquiredGood(sensorId);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Remote exception when sending onAcquiredGood", e);
+ }
+ }
+
public static void onEnrollmentProgress(int sensorId, int remaining,
@Nullable IUdfpsOverlayController udfpsOverlayController) {
if (udfpsOverlayController == null) {
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
index 45842677609c..a5326b352264 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
@@ -22,6 +22,7 @@ import android.app.TaskStackListener;
import android.content.Context;
import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.biometrics.BiometricFingerprintConstants;
+import android.hardware.biometrics.BiometricFingerprintConstants.FingerprintAcquired;
import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.common.ICancellationSignal;
import android.hardware.biometrics.fingerprint.ISession;
@@ -81,6 +82,17 @@ class FingerprintAuthenticationClient extends AuthenticationClient<ISession> imp
}
@Override
+ public void onAcquired(@FingerprintAcquired int acquiredInfo, int vendorCode) {
+ // For UDFPS, notify SysUI that the illumination can be turned off.
+ // See AcquiredInfo#GOOD and AcquiredInfo#RETRYING_CAPTURE
+ if (acquiredInfo == BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_GOOD) {
+ UdfpsHelper.onAcquiredGood(getSensorId(), mUdfpsOverlayController);
+ }
+
+ super.onAcquired(acquiredInfo, vendorCode);
+ }
+
+ @Override
public void onError(int errorCode, int vendorCode) {
super.onError(errorCode, vendorCode);
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java
index ed886fe166e0..125cfd2e134d 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java
@@ -21,6 +21,7 @@ import android.annotation.Nullable;
import android.content.Context;
import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.biometrics.BiometricFingerprintConstants;
+import android.hardware.biometrics.BiometricFingerprintConstants.FingerprintAcquired;
import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.common.ICancellationSignal;
import android.hardware.biometrics.fingerprint.ISession;
@@ -85,14 +86,19 @@ class FingerprintEnrollClient extends EnrollClient<ISession> implements Udfps {
}
}
-
@Override
- public void onAcquired(int acquiredInfo, int vendorCode) {
- super.onAcquired(acquiredInfo, vendorCode);
+ public void onAcquired(@FingerprintAcquired int acquiredInfo, int vendorCode) {
+ // For UDFPS, notify SysUI that the illumination can be turned off.
+ // See AcquiredInfo#GOOD and AcquiredInfo#RETRYING_CAPTURE
+ if (acquiredInfo == BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_GOOD) {
+ UdfpsHelper.onAcquiredGood(getSensorId(), mUdfpsOverlayController);
+ }
if (UdfpsHelper.isValidAcquisitionMessage(getContext(), acquiredInfo, vendorCode)) {
UdfpsHelper.onEnrollmentHelp(getSensorId(), mUdfpsOverlayController);
}
+
+ super.onAcquired(acquiredInfo, vendorCode);
}
@Override
diff --git a/services/core/java/com/android/server/location/injector/SystemEmergencyHelper.java b/services/core/java/com/android/server/location/injector/SystemEmergencyHelper.java
index a34d7226136a..70a222fb09c5 100644
--- a/services/core/java/com/android/server/location/injector/SystemEmergencyHelper.java
+++ b/services/core/java/com/android/server/location/injector/SystemEmergencyHelper.java
@@ -35,17 +35,17 @@ public class SystemEmergencyHelper extends EmergencyHelper {
private final Context mContext;
- private TelephonyManager mTelephonyManager;
+ TelephonyManager mTelephonyManager;
- private boolean mIsInEmergencyCall;
- private long mEmergencyCallEndRealtimeMs = Long.MIN_VALUE;
+ boolean mIsInEmergencyCall;
+ long mEmergencyCallEndRealtimeMs = Long.MIN_VALUE;
public SystemEmergencyHelper(Context context) {
mContext = context;
}
/** Called when system is ready. */
- public void onSystemReady() {
+ public synchronized void onSystemReady() {
if (mTelephonyManager != null) {
return;
}
@@ -64,14 +64,20 @@ public class SystemEmergencyHelper extends EmergencyHelper {
return;
}
- mIsInEmergencyCall = mTelephonyManager.isEmergencyNumber(
- intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER));
+ synchronized (SystemEmergencyHelper.this) {
+ mIsInEmergencyCall = mTelephonyManager.isEmergencyNumber(
+ intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER));
+ }
}
}, new IntentFilter(Intent.ACTION_NEW_OUTGOING_CALL));
}
@Override
- public boolean isInEmergency(long extensionTimeMs) {
+ public synchronized boolean isInEmergency(long extensionTimeMs) {
+ if (mTelephonyManager == null) {
+ return false;
+ }
+
boolean isInExtensionTime = mEmergencyCallEndRealtimeMs != Long.MIN_VALUE
&& (SystemClock.elapsedRealtime() - mEmergencyCallEndRealtimeMs) < extensionTimeMs;
@@ -84,12 +90,16 @@ public class SystemEmergencyHelper extends EmergencyHelper {
private class EmergencyCallTelephonyCallback extends TelephonyCallback implements
TelephonyCallback.CallStateListener{
+ EmergencyCallTelephonyCallback() {}
+
@Override
public void onCallStateChanged(int state) {
if (state == TelephonyManager.CALL_STATE_IDLE) {
- if (mIsInEmergencyCall) {
- mEmergencyCallEndRealtimeMs = SystemClock.elapsedRealtime();
- mIsInEmergencyCall = false;
+ synchronized (SystemEmergencyHelper.this) {
+ if (mIsInEmergencyCall) {
+ mEmergencyCallEndRealtimeMs = SystemClock.elapsedRealtime();
+ mIsInEmergencyCall = false;
+ }
}
}
}
diff --git a/services/core/java/com/android/server/location/provider/LocationProviderManager.java b/services/core/java/com/android/server/location/provider/LocationProviderManager.java
index 6d7f79250715..4f8b87b51294 100644
--- a/services/core/java/com/android/server/location/provider/LocationProviderManager.java
+++ b/services/core/java/com/android/server/location/provider/LocationProviderManager.java
@@ -1527,16 +1527,16 @@ public class LocationProviderManager extends
throw new IllegalArgumentException(mName + " provider is not a test provider");
}
+ String locationProvider = location.getProvider();
+ if (!TextUtils.isEmpty(locationProvider) && !mName.equals(locationProvider)) {
+ // The location has an explicit provider that is different from the mock
+ // provider name. The caller may be trying to fool us via b/33091107.
+ EventLog.writeEvent(0x534e4554, "33091107", Binder.getCallingUid(),
+ mName + "!=" + locationProvider);
+ }
+
final long identity = Binder.clearCallingIdentity();
try {
- String locationProvider = location.getProvider();
- if (!TextUtils.isEmpty(locationProvider) && !mName.equals(locationProvider)) {
- // The location has an explicit provider that is different from the mock
- // provider name. The caller may be trying to fool us via b/33091107.
- EventLog.writeEvent(0x534e4554, "33091107", Binder.getCallingUid(),
- mName + "!=" + locationProvider);
- }
-
mProvider.setMockProviderLocation(location);
} finally {
Binder.restoreCallingIdentity(identity);
diff --git a/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java b/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
index c1209d466d20..62db886b90e9 100644
--- a/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
+++ b/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
@@ -154,7 +154,7 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub {
// must have the required permission and the users must be in the same profile group
// in order to launch any of its own activities.
if (callerUserId != userId) {
- final int permissionFlag = PermissionChecker.checkPermissionForPreflight(
+ final int permissionFlag = PermissionChecker.checkPermissionForPreflight(
mContext,
INTERACT_ACROSS_PROFILES,
callingPid,
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 2f8ba6da89a3..6a399bdbb010 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -341,6 +341,7 @@ import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.ResolverActivity;
+import com.android.internal.content.F2fsUtils;
import com.android.internal.content.NativeLibraryHelper;
import com.android.internal.content.PackageHelper;
import com.android.internal.content.om.OverlayConfig;
@@ -896,6 +897,20 @@ public class PackageManagerService extends IPackageManager.Stub
* Only non-null during an OTA, and even then it is nulled again once systemReady().
*/
private @Nullable ArraySet<String> mExistingPackages = null;
+
+ /**
+ * List of code paths that need to be released when the system becomes ready.
+ * <p>
+ * NOTE: We have to delay releasing cblocks for no other reason than we cannot
+ * retrieve the setting {@link Secure#RELEASE_COMPRESS_BLOCKS_ON_INSTALL}. When
+ * we no longer need to read that setting, cblock release can occur in the
+ * constructor.
+ *
+ * @see Secure#RELEASE_COMPRESS_BLOCKS_ON_INSTALL
+ * @see #systemReady()
+ */
+ private @Nullable List<File> mReleaseOnSystemReady;
+
/**
* Whether or not system app permissions should be promoted from install to runtime.
*/
@@ -1413,8 +1428,8 @@ public class PackageManagerService extends IPackageManager.Stub
mStaticLibsByDeclaringPackage = new WatchedArrayMap<>();
private final SnapshotCache<WatchedArrayMap<String, WatchedLongSparseArray<SharedLibraryInfo>>>
mStaticLibsByDeclaringPackageSnapshot =
- new SnapshotCache.Auto<>(mSharedLibraries, mSharedLibraries,
- "PackageManagerService.mSharedLibraries");
+ new SnapshotCache.Auto<>(mStaticLibsByDeclaringPackage, mStaticLibsByDeclaringPackage,
+ "PackageManagerService.mStaticLibsByDeclaringPackage");
// Mapping from instrumentation class names to info about them.
@Watched
@@ -7907,6 +7922,21 @@ public class PackageManagerService extends IPackageManager.Stub
IoUtils.closeQuietly(handle);
}
}
+ if (ret == PackageManager.INSTALL_SUCCEEDED) {
+ // NOTE: During boot, we have to delay releasing cblocks for no other reason than
+ // we cannot retrieve the setting {@link Secure#RELEASE_COMPRESS_BLOCKS_ON_INSTALL}.
+ // When we no longer need to read that setting, cblock release can occur always
+ // occur here directly
+ if (!mSystemReady) {
+ if (mReleaseOnSystemReady == null) {
+ mReleaseOnSystemReady = new ArrayList<>();
+ }
+ mReleaseOnSystemReady.add(dstCodePath);
+ } else {
+ final ContentResolver resolver = mContext.getContentResolver();
+ F2fsUtils.releaseCompressedBlocks(resolver, dstCodePath);
+ }
+ }
if (ret != PackageManager.INSTALL_SUCCEEDED) {
if (!dstCodePath.exists()) {
return null;
@@ -13224,9 +13254,8 @@ public class PackageManagerService extends IPackageManager.Stub
if (!sharedLibraryInfo.isStatic()) {
continue;
}
- final PackageSetting staticLibPkgSetting = getPackageSetting(
- toStaticSharedLibraryPackageName(sharedLibraryInfo.getName(),
- sharedLibraryInfo.getLongVersion()));
+ final PackageSetting staticLibPkgSetting =
+ getPackageSetting(sharedLibraryInfo.getPackageName());
if (staticLibPkgSetting == null) {
Slog.wtf(TAG, "Shared lib without setting: " + sharedLibraryInfo);
continue;
@@ -17778,6 +17807,10 @@ public class PackageManagerService extends IPackageManager.Stub
if (mRet == PackageManager.INSTALL_SUCCEEDED) {
mRet = args.copyApk();
}
+ if (mRet == PackageManager.INSTALL_SUCCEEDED) {
+ F2fsUtils.releaseCompressedBlocks(
+ mContext.getContentResolver(), new File(args.getCodePath()));
+ }
if (mParentInstallParams != null) {
mParentInstallParams.tryProcessInstallRequest(args, mRet);
} else {
@@ -17785,7 +17818,6 @@ public class PackageManagerService extends IPackageManager.Stub
processInstallRequestsAsync(
res.returnCode == PackageManager.INSTALL_SUCCEEDED,
Collections.singletonList(new InstallRequest(args, res)));
-
}
}
}
@@ -22726,7 +22758,8 @@ public class PackageManagerService extends IPackageManager.Stub
*/
public int getPreferredActivitiesInternal(List<WatchedIntentFilter> outFilters,
List<ComponentName> outActivities, String packageName) {
- if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+ final int callingUid = Binder.getCallingUid();
+ if (getInstantAppPackageName(callingUid) != null) {
return 0;
}
int num = 0;
@@ -22738,9 +22771,13 @@ public class PackageManagerService extends IPackageManager.Stub
final Iterator<PreferredActivity> it = pir.filterIterator();
while (it.hasNext()) {
final PreferredActivity pa = it.next();
+ final String prefPackageName = pa.mPref.mComponent.getPackageName();
if (packageName == null
- || (pa.mPref.mComponent.getPackageName().equals(packageName)
- && pa.mPref.mAlways)) {
+ || (prefPackageName.equals(packageName) && pa.mPref.mAlways)) {
+ if (shouldFilterApplicationLocked(
+ mSettings.getPackageLPr(prefPackageName), callingUid, userId)) {
+ continue;
+ }
if (outFilters != null) {
outFilters.add(new WatchedIntentFilter(pa.getIntentFilter()));
}
@@ -24120,8 +24157,15 @@ public class PackageManagerService extends IPackageManager.Stub
public void systemReady() {
enforceSystemOrRoot("Only the system can claim the system is ready");
- mSystemReady = true;
final ContentResolver resolver = mContext.getContentResolver();
+ if (mReleaseOnSystemReady != null) {
+ for (int i = mReleaseOnSystemReady.size() - 1; i >= 0; --i) {
+ final File dstCodePath = mReleaseOnSystemReady.get(i);
+ F2fsUtils.releaseCompressedBlocks(resolver, dstCodePath);
+ }
+ mReleaseOnSystemReady = null;
+ }
+ mSystemReady = true;
ContentObserver co = new ContentObserver(mHandler) {
@Override
public void onChange(boolean selfChange) {
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index 1bfa72f64d8e..b0f8ee1925c5 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -20,6 +20,7 @@ import static android.Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY;
import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
import static android.app.AppOpsManager.MODE_ALLOWED;
+import static android.app.AppOpsManager.MODE_ERRORED;
import static android.app.AppOpsManager.MODE_IGNORED;
import static android.content.pm.ApplicationInfo.AUTO_REVOKE_DISALLOWED;
import static android.content.pm.ApplicationInfo.AUTO_REVOKE_DISCOURAGED;
@@ -65,6 +66,7 @@ import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.AppOpsManager;
+import android.app.AppOpsManager.AttributionFlags;
import android.app.IActivityManager;
import android.app.admin.DevicePolicyManagerInternal;
import android.compat.annotation.ChangeId;
@@ -108,6 +110,7 @@ import android.os.storage.StorageManager;
import android.permission.IOnPermissionsChangeListener;
import android.permission.IPermissionChecker;
import android.permission.IPermissionManager;
+import android.permission.PermissionCheckerManager;
import android.permission.PermissionControllerManager;
import android.permission.PermissionManager;
import android.permission.PermissionManagerInternal;
@@ -171,6 +174,7 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.BiFunction;
/**
@@ -3320,8 +3324,8 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
@Override
- public @NonNull AttributionSource registerAttributionSource(@NonNull AttributionSource source) {
- return mAttributionSourceRegistry.registerAttributionSource(source);
+ public void registerAttributionSource(@NonNull AttributionSource source) {
+ mAttributionSourceRegistry.registerAttributionSource(source);
}
@Override
@@ -5295,8 +5299,8 @@ public class PermissionManagerService extends IPermissionManager.Stub {
* @param permissionName the name of the permission to be checked
* @param userId the user ID
* @param superImpl the original implementation that can be delegated to
- * @return {@link android.content.pm.PackageManager.PERMISSION_GRANTED} if the package has
- * the permission, or {@link android.content.pm.PackageManager.PERMISSION_DENITED} otherwise
+ * @return {@link android.content.pm.PackageManager#PERMISSION_GRANTED} if the package has
+ * the permission, or {@link android.content.pm.PackageManager#PERMISSION_DENIED} otherwise
*
* @see android.content.pm.PackageManager#checkPermission(String, String)
*/
@@ -5310,8 +5314,8 @@ public class PermissionManagerService extends IPermissionManager.Stub {
* @param uid the UID to be checked
* @param permissionName the name of the permission to be checked
* @param superImpl the original implementation that can be delegated to
- * @return {@link android.content.pm.PackageManager.PERMISSION_GRANTED} if the package has
- * the permission, or {@link android.content.pm.PackageManager.PERMISSION_DENITED} otherwise
+ * @return {@link android.content.pm.PackageManager#PERMISSION_GRANTED} if the package has
+ * the permission, or {@link android.content.pm.PackageManager#PERMISSION_DENIED} otherwise
*/
int checkUidPermission(int uid, @NonNull String permissionName,
BiFunction<Integer, String, Integer> superImpl);
@@ -5395,8 +5399,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
private final WeakHashMap<IBinder, AttributionSource> mAttributions = new WeakHashMap<>();
- public @NonNull AttributionSource registerAttributionSource(
- @NonNull AttributionSource source) {
+ public void registerAttributionSource(@NonNull AttributionSource source) {
// Here we keep track of attribution sources that were created by an app
// from an attribution chain that called into the app and the apps's
// own attribution source. An app can register an attribution chain up
@@ -5443,10 +5446,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
synchronized (mLock) {
- final IBinder token = new Binder();
- final AttributionSource result = source.withToken(token);
- mAttributions.put(token, result);
- return result;
+ mAttributions.put(source.getToken(), source);
}
}
@@ -5472,6 +5472,8 @@ public class PermissionManagerService extends IPermissionManager.Stub {
private static final ConcurrentHashMap<String, PermissionInfo> sPlatformPermissions
= new ConcurrentHashMap<>();
+ private static final AtomicInteger sAttributionChainIds = new AtomicInteger(0);
+
private final @NonNull Context mContext;
private final @NonNull AppOpsManager mAppOpsManager;
@@ -5481,53 +5483,108 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
@Override
- @PermissionChecker.PermissionResult
+ @PermissionCheckerManager.PermissionResult
public int checkPermission(@NonNull String permission,
@NonNull AttributionSourceState attributionSourceState, @Nullable String message,
- boolean forDataDelivery, boolean startDataDelivery, boolean fromDatasource) {
+ boolean forDataDelivery, boolean startDataDelivery, boolean fromDatasource,
+ int attributedOp) {
Objects.requireNonNull(permission);
Objects.requireNonNull(attributionSourceState);
final AttributionSource attributionSource = new AttributionSource(
attributionSourceState);
final int result = checkPermission(mContext, permission, attributionSource, message,
- forDataDelivery, startDataDelivery, fromDatasource);
+ forDataDelivery, startDataDelivery, fromDatasource, attributedOp);
// Finish any started op if some step in the attribution chain failed.
if (startDataDelivery && result != PermissionChecker.PERMISSION_GRANTED) {
- finishDataDelivery(AppOpsManager.permissionToOp(permission),
- attributionSource.asState());
+ if (attributedOp == AppOpsManager.OP_NONE) {
+ finishDataDelivery(AppOpsManager.permissionToOpCode(permission),
+ attributionSource.asState(), fromDatasource);
+ } else {
+ finishDataDelivery(attributedOp, attributionSource.asState(), fromDatasource);
+ }
}
return result;
}
@Override
- public void finishDataDelivery(@NonNull String op,
- @NonNull AttributionSourceState attributionSourceState) {
- if (op == null || attributionSourceState.packageName == null) {
+ public void finishDataDelivery(int op,
+ @NonNull AttributionSourceState attributionSourceState, boolean fromDatasource) {
+ Objects.requireNonNull(attributionSourceState);
+
+ if (op == AppOpsManager.OP_NONE) {
return;
}
- mAppOpsManager.finishProxyOp(op, new AttributionSource(attributionSourceState));
- if (attributionSourceState.next != null) {
- finishDataDelivery(op, attributionSourceState.next[0]);
+
+ AttributionSource current = new AttributionSource(attributionSourceState);
+ AttributionSource next = null;
+
+ while (true) {
+ final boolean skipCurrentFinish = (fromDatasource || next != null);
+
+ next = current.getNext();
+
+ // If the call is from a datasource we need to vet only the chain before it. This
+ // way we can avoid the datasource creating an attribution context for every call.
+ if (!(fromDatasource && current.asState() == attributionSourceState)
+ && next != null && !current.isTrusted(mContext)) {
+ return;
+ }
+
+ // The access is for oneself if this is the single receiver of data
+ // after the data source or if this is the single attribution source
+ // in the chain if not from a datasource.
+ final boolean singleReceiverFromDatasource = (fromDatasource
+ && current.asState() == attributionSourceState && next != null
+ && next.getNext() == null);
+ final boolean selfAccess = singleReceiverFromDatasource || next == null;
+
+ final AttributionSource accessorSource = (!singleReceiverFromDatasource)
+ ? current : next;
+
+ if (selfAccess) {
+ final String resolvedPackageName = resolvePackageName(mContext, accessorSource);
+ if (resolvedPackageName == null) {
+ return;
+ }
+ mAppOpsManager.finishOp(accessorSource.getToken(), op,
+ accessorSource.getUid(), resolvedPackageName,
+ accessorSource.getAttributionTag());
+ } else {
+ final AttributionSource resolvedAttributionSource =
+ resolveAttributionSource(mContext, accessorSource);
+ if (resolvedAttributionSource.getPackageName() == null) {
+ return;
+ }
+ mAppOpsManager.finishProxyOp(AppOpsManager.opToPublicName(op),
+ resolvedAttributionSource, skipCurrentFinish);
+ }
+
+ if (next == null || next.getNext() == null) {
+ return;
+ }
+
+ current = next;
}
}
@Override
- @PermissionChecker.PermissionResult
+ @PermissionCheckerManager.PermissionResult
public int checkOp(int op, AttributionSourceState attributionSource,
String message, boolean forDataDelivery, boolean startDataDelivery) {
int result = checkOp(mContext, op, new AttributionSource(attributionSource), message,
forDataDelivery, startDataDelivery);
if (result != PermissionChecker.PERMISSION_GRANTED && startDataDelivery) {
// Finish any started op if some step in the attribution chain failed.
- finishDataDelivery(AppOpsManager.opToName(op), attributionSource);
+ finishDataDelivery(op, attributionSource, /*fromDatasource*/ false);
}
return result;
}
- @PermissionChecker.PermissionResult
+ @PermissionCheckerManager.PermissionResult
private static int checkPermission(@NonNull Context context, @NonNull String permission,
@NonNull AttributionSource attributionSource, @Nullable String message,
- boolean forDataDelivery, boolean startDataDelivery, boolean fromDatasource) {
+ boolean forDataDelivery, boolean startDataDelivery, boolean fromDatasource,
+ int attributedOp) {
PermissionInfo permissionInfo = sPlatformPermissions.get(permission);
if (permissionInfo == null) {
@@ -5549,7 +5606,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
if (permissionInfo.isRuntime()) {
return checkRuntimePermission(context, permission, attributionSource, message,
- forDataDelivery, startDataDelivery, fromDatasource);
+ forDataDelivery, startDataDelivery, fromDatasource, attributedOp);
}
if (!fromDatasource && !checkPermission(context, permission, attributionSource.getUid(),
@@ -5558,15 +5615,14 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
if (attributionSource.getNext() != null) {
- return checkPermission(context, permission,
- attributionSource.getNext(), message, forDataDelivery,
- startDataDelivery, /*fromDatasource*/ false);
+ return checkPermission(context, permission, attributionSource.getNext(), message,
+ forDataDelivery, startDataDelivery, /*fromDatasource*/ false, attributedOp);
}
return PermissionChecker.PERMISSION_GRANTED;
}
- @PermissionChecker.PermissionResult
+ @PermissionCheckerManager.PermissionResult
private static int checkAppOpPermission(@NonNull Context context,
@NonNull String permission, @NonNull AttributionSource attributionSource,
@Nullable String message, boolean forDataDelivery, boolean fromDatasource) {
@@ -5586,7 +5642,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
// If the call is from a datasource we need to vet only the chain before it. This
// way we can avoid the datasource creating an attribution context for every call.
- if (!(fromDatasource && current == attributionSource)
+ if (!(fromDatasource && current.equals(attributionSource))
&& next != null && !current.isTrusted(context)) {
return PermissionChecker.PERMISSION_HARD_DENIED;
}
@@ -5595,12 +5651,15 @@ public class PermissionManagerService extends IPermissionManager.Stub {
// after the data source or if this is the single attribution source
// in the chain if not from a datasource.
final boolean singleReceiverFromDatasource = (fromDatasource
- && current == attributionSource && next != null && next.getNext() == null);
+ && current.equals(attributionSource) && next != null
+ && next.getNext() == null);
final boolean selfAccess = singleReceiverFromDatasource || next == null;
final int opMode = performOpTransaction(context, op, current, message,
forDataDelivery, /*startDataDelivery*/ false, skipCurrentChecks,
- selfAccess, singleReceiverFromDatasource);
+ selfAccess, singleReceiverFromDatasource, AppOpsManager.OP_NONE,
+ AppOpsManager.ATTRIBUTION_FLAGS_NONE, AppOpsManager.ATTRIBUTION_FLAGS_NONE,
+ AppOpsManager.ATTRIBUTION_CHAIN_ID_NONE);
switch (opMode) {
case AppOpsManager.MODE_IGNORED:
@@ -5631,9 +5690,12 @@ public class PermissionManagerService extends IPermissionManager.Stub {
private static int checkRuntimePermission(@NonNull Context context,
@NonNull String permission, @NonNull AttributionSource attributionSource,
@Nullable String message, boolean forDataDelivery, boolean startDataDelivery,
- boolean fromDatasource) {
+ boolean fromDatasource, int attributedOp) {
// Now let's check the identity chain...
final int op = AppOpsManager.permissionToOpCode(permission);
+ final int attributionChainId = (startDataDelivery)
+ ? sAttributionChainIds.incrementAndGet()
+ : AppOpsManager.ATTRIBUTION_CHAIN_ID_NONE;
AttributionSource current = attributionSource;
AttributionSource next = null;
@@ -5644,7 +5706,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
// If the call is from a datasource we need to vet only the chain before it. This
// way we can avoid the datasource creating an attribution context for every call.
- if (!(fromDatasource && current == attributionSource)
+ if (!(fromDatasource && current.equals(attributionSource))
&& next != null && !current.isTrusted(context)) {
return PermissionChecker.PERMISSION_HARD_DENIED;
}
@@ -5678,12 +5740,21 @@ public class PermissionManagerService extends IPermissionManager.Stub {
// after the data source or if this is the single attribution source
// in the chain if not from a datasource.
final boolean singleReceiverFromDatasource = (fromDatasource
- && current == attributionSource && next != null && next.getNext() == null);
+ && current.equals(attributionSource)
+ && next != null && next.getNext() == null);
final boolean selfAccess = singleReceiverFromDatasource || next == null;
+ final int proxyAttributionFlags = (!skipCurrentChecks)
+ ? resolveProxyAttributionFlags(attributionSource, current, fromDatasource,
+ startDataDelivery, selfAccess)
+ : AppOpsManager.ATTRIBUTION_FLAGS_NONE;
+ final int proxiedAttributionFlags = resolveProxiedAttributionFlags(
+ attributionSource, next, fromDatasource, startDataDelivery, selfAccess);
+
final int opMode = performOpTransaction(context, op, current, message,
forDataDelivery, startDataDelivery, skipCurrentChecks, selfAccess,
- singleReceiverFromDatasource);
+ singleReceiverFromDatasource, attributedOp, proxyAttributionFlags,
+ proxiedAttributionFlags, attributionChainId);
switch (opMode) {
case AppOpsManager.MODE_ERRORED: {
@@ -5714,6 +5785,50 @@ public class PermissionManagerService extends IPermissionManager.Stub {
return permissionGranted;
}
+ private static @AttributionFlags int resolveProxyAttributionFlags(
+ @NonNull AttributionSource attributionChain,
+ @NonNull AttributionSource current, boolean fromDatasource,
+ boolean startDataDelivery, boolean selfAccess) {
+ return resolveAttributionFlags(attributionChain, current, fromDatasource,
+ startDataDelivery, selfAccess, /*flagsForProxy*/ true);
+ }
+
+ private static @AttributionFlags int resolveProxiedAttributionFlags(
+ @NonNull AttributionSource attributionChain,
+ @NonNull AttributionSource current, boolean fromDatasource,
+ boolean startDataDelivery, boolean selfAccess) {
+ return resolveAttributionFlags(attributionChain, current, fromDatasource,
+ startDataDelivery, selfAccess, /*flagsForProxy*/ false);
+ }
+
+ private static @AttributionFlags int resolveAttributionFlags(
+ @NonNull AttributionSource attributionChain,
+ @NonNull AttributionSource current, boolean fromDatasource,
+ boolean startDataDelivery, boolean selfAccess, boolean flagsForProxy) {
+ if (current == null || !startDataDelivery) {
+ return AppOpsManager.ATTRIBUTION_FLAGS_NONE;
+ }
+ if (flagsForProxy) {
+ if (selfAccess) {
+ return AppOpsManager.ATTRIBUTION_FLAG_ACCESSOR;
+ } else if (!fromDatasource && current.equals(attributionChain)) {
+ return AppOpsManager.ATTRIBUTION_FLAG_ACCESSOR;
+ }
+ } else {
+ if (selfAccess) {
+ return AppOpsManager.ATTRIBUTION_FLAG_RECEIVER;
+ } else if (fromDatasource && current.equals(attributionChain.getNext())) {
+ return AppOpsManager.ATTRIBUTION_FLAG_ACCESSOR;
+ } else if (current.getNext() == null) {
+ return AppOpsManager.ATTRIBUTION_FLAG_RECEIVER;
+ }
+ }
+ if (fromDatasource && current.equals(attributionChain)) {
+ return AppOpsManager.ATTRIBUTION_FLAGS_NONE;
+ }
+ return AppOpsManager.ATTRIBUTION_FLAG_INTERMEDIARY;
+ }
+
private static int checkOp(@NonNull Context context, @NonNull int op,
@NonNull AttributionSource attributionSource, @Nullable String message,
boolean forDataDelivery, boolean startDataDelivery) {
@@ -5721,6 +5836,10 @@ public class PermissionManagerService extends IPermissionManager.Stub {
return PermissionChecker.PERMISSION_HARD_DENIED;
}
+ final int attributionChainId = (startDataDelivery)
+ ? sAttributionChainIds.incrementAndGet()
+ : AppOpsManager.ATTRIBUTION_CHAIN_ID_NONE;
+
AttributionSource current = attributionSource;
AttributionSource next = null;
@@ -5737,9 +5856,18 @@ public class PermissionManagerService extends IPermissionManager.Stub {
// The access is for oneself if this is the single attribution source in the chain.
final boolean selfAccess = (next == null);
+ final int proxyAttributionFlags = (!skipCurrentChecks)
+ ? resolveProxyAttributionFlags(attributionSource, current,
+ /*fromDatasource*/ false, startDataDelivery, selfAccess)
+ : AppOpsManager.ATTRIBUTION_FLAGS_NONE;
+ final int proxiedAttributionFlags = resolveProxiedAttributionFlags(
+ attributionSource, next, /*fromDatasource*/ false, startDataDelivery,
+ selfAccess);
+
final int opMode = performOpTransaction(context, op, current, message,
forDataDelivery, startDataDelivery, skipCurrentChecks, selfAccess,
- /*fromDatasource*/ false);
+ /*fromDatasource*/ false, AppOpsManager.OP_NONE, proxyAttributionFlags,
+ proxiedAttributionFlags, attributionChainId);
switch (opMode) {
case AppOpsManager.MODE_ERRORED: {
@@ -5758,10 +5886,13 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
}
+ @SuppressWarnings("ConstantConditions")
private static int performOpTransaction(@NonNull Context context, int op,
@NonNull AttributionSource attributionSource, @Nullable String message,
boolean forDataDelivery, boolean startDataDelivery, boolean skipProxyOperation,
- boolean selfAccess, boolean singleReceiverFromDatasource) {
+ boolean selfAccess, boolean singleReceiverFromDatasource, int attributedOp,
+ @AttributionFlags int proxyAttributionFlags,
+ @AttributionFlags int proxiedAttributionFlags, int attributionChainId) {
// We cannot perform app ops transactions without a package name. In all relevant
// places we pass the package name but just in case there is a bug somewhere we
// do a best effort to resolve the package from the UID (pick first without a loss
@@ -5793,36 +5924,75 @@ public class PermissionManagerService extends IPermissionManager.Stub {
if (resolvedAttributionSource.getPackageName() == null) {
return AppOpsManager.MODE_ERRORED;
}
+ // If the datasource is not in a trusted platform component then in would not
+ // have UPDATE_APP_OPS_STATS and the call below would fail. The problem is that
+ // an app is exposing runtime permission protected data but cannot blame others
+ // in a trusted way which would not properly show in permission usage UIs.
+ // As a fallback we note a proxy op that blames the app and the datasource.
+ int startedOp = op;
+ int checkedOpResult = MODE_ALLOWED;
+ int startedOpResult;
+
+ // If the datasource wants to attribute to another app op we need to
+ // make sure the op for the permission and the attributed ops allow
+ // the operation. We return the less permissive of the two and check
+ // the permission op while start the attributed op.
+ if (attributedOp != AppOpsManager.OP_NONE && attributedOp != op) {
+ checkedOpResult = appOpsManager.checkOpNoThrow(op,
+ resolvedAttributionSource.getUid(), resolvedAttributionSource
+ .getPackageName());
+ if (checkedOpResult == MODE_ERRORED) {
+ return checkedOpResult;
+ }
+ startedOp = attributedOp;
+ }
if (selfAccess) {
- // If the datasource is not in a trusted platform component then in would not
- // have UPDATE_APP_OPS_STATS and the call below would fail. The problem is that
- // an app is exposing runtime permission protected data but cannot blame others
- // in a trusted way which would not properly show in permission usage UIs.
- // As a fallback we note a proxy op that blames the app and the datasource.
try {
- return appOpsManager.startOpNoThrow(op, resolvedAttributionSource.getUid(),
+ startedOpResult = appOpsManager.startOpNoThrow(
+ resolvedAttributionSource.getToken(), startedOp,
+ resolvedAttributionSource.getUid(),
resolvedAttributionSource.getPackageName(),
/*startIfModeDefault*/ false,
resolvedAttributionSource.getAttributionTag(),
- message);
+ message, proxyAttributionFlags, attributionChainId);
} catch (SecurityException e) {
Slog.w(LOG_TAG, "Datasource " + attributionSource + " protecting data with"
+ " platform defined runtime permission "
+ AppOpsManager.opToPermission(op) + " while not having "
+ Manifest.permission.UPDATE_APP_OPS_STATS);
- return appOpsManager.startProxyOpNoThrow(op, attributionSource, message,
- skipProxyOperation);
+ startedOpResult = appOpsManager.startProxyOpNoThrow(attributedOp,
+ attributionSource, message, skipProxyOperation,
+ proxyAttributionFlags, proxiedAttributionFlags, attributionChainId);
}
} else {
- return appOpsManager.startProxyOpNoThrow(op, resolvedAttributionSource, message,
- skipProxyOperation);
+ startedOpResult = appOpsManager.startProxyOpNoThrow(startedOp,
+ resolvedAttributionSource, message, skipProxyOperation,
+ proxyAttributionFlags, proxiedAttributionFlags, attributionChainId);
}
+ return Math.max(checkedOpResult, startedOpResult);
} else {
final AttributionSource resolvedAttributionSource = resolveAttributionSource(
context, accessorSource);
if (resolvedAttributionSource.getPackageName() == null) {
return AppOpsManager.MODE_ERRORED;
}
+ int notedOp = op;
+ int checkedOpResult = MODE_ALLOWED;
+ int notedOpResult;
+
+ // If the datasource wants to attribute to another app op we need to
+ // make sure the op for the permission and the attributed ops allow
+ // the operation. We return the less permissive of the two and check
+ // the permission op while start the attributed op.
+ if (attributedOp != AppOpsManager.OP_NONE && attributedOp != op) {
+ checkedOpResult = appOpsManager.checkOpNoThrow(op,
+ resolvedAttributionSource.getUid(), resolvedAttributionSource
+ .getPackageName());
+ if (checkedOpResult == MODE_ERRORED) {
+ return checkedOpResult;
+ }
+ notedOp = attributedOp;
+ }
if (selfAccess) {
// If the datasource is not in a trusted platform component then in would not
// have UPDATE_APP_OPS_STATS and the call below would fail. The problem is that
@@ -5830,7 +6000,8 @@ public class PermissionManagerService extends IPermissionManager.Stub {
// in a trusted way which would not properly show in permission usage UIs.
// As a fallback we note a proxy op that blames the app and the datasource.
try {
- return appOpsManager.noteOpNoThrow(op, resolvedAttributionSource.getUid(),
+ notedOpResult = appOpsManager.noteOpNoThrow(notedOp,
+ resolvedAttributionSource.getUid(),
resolvedAttributionSource.getPackageName(),
resolvedAttributionSource.getAttributionTag(),
message);
@@ -5839,13 +6010,14 @@ public class PermissionManagerService extends IPermissionManager.Stub {
+ " platform defined runtime permission "
+ AppOpsManager.opToPermission(op) + " while not having "
+ Manifest.permission.UPDATE_APP_OPS_STATS);
- return appOpsManager.noteProxyOpNoThrow(op, attributionSource, message,
- skipProxyOperation);
+ notedOpResult = appOpsManager.noteProxyOpNoThrow(notedOp, attributionSource,
+ message, skipProxyOperation);
}
} else {
- return appOpsManager.noteProxyOpNoThrow(op, resolvedAttributionSource, message,
- skipProxyOperation);
+ notedOpResult = appOpsManager.noteProxyOpNoThrow(notedOp,
+ resolvedAttributionSource, message, skipProxyOperation);
}
+ return Math.max(checkedOpResult, notedOpResult);
}
}
diff --git a/services/core/java/com/android/server/policy/AppOpsPolicy.java b/services/core/java/com/android/server/policy/AppOpsPolicy.java
index 2cfbf26cf996..607bc569ad64 100644
--- a/services/core/java/com/android/server/policy/AppOpsPolicy.java
+++ b/services/core/java/com/android/server/policy/AppOpsPolicy.java
@@ -19,6 +19,7 @@ package com.android.server.policy;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.AppOpsManager;
+import android.app.AppOpsManager.AttributionFlags;
import android.app.AppOpsManagerInternal;
import android.app.SyncNotedAppOp;
import android.app.role.RoleManager;
@@ -39,6 +40,7 @@ import android.util.ArraySet;
import android.util.Log;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.function.DecFunction;
import com.android.internal.util.function.HeptFunction;
import com.android.internal.util.function.HexFunction;
import com.android.internal.util.function.NonaFunction;
@@ -46,6 +48,7 @@ import com.android.internal.util.function.OctFunction;
import com.android.internal.util.function.QuadFunction;
import com.android.internal.util.function.QuintFunction;
import com.android.internal.util.function.TriFunction;
+import com.android.internal.util.function.UndecFunction;
import com.android.server.LocalServices;
import java.util.List;
@@ -179,32 +182,37 @@ public final class AppOpsPolicy implements AppOpsManagerInternal.CheckOpsDelegat
public SyncNotedAppOp startOperation(IBinder token, int code, int uid,
@Nullable String packageName, @Nullable String attributionTag,
boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp, String message,
- boolean shouldCollectMessage, @NonNull NonaFunction<IBinder, Integer, Integer, String,
- String, Boolean, Boolean, String, Boolean, SyncNotedAppOp> superImpl) {
+ boolean shouldCollectMessage, @AttributionFlags int attributionFlags,
+ int attributionChainId, @NonNull UndecFunction<IBinder, Integer, Integer, String,
+ String, Boolean, Boolean, String, Boolean, Integer, Integer,
+ SyncNotedAppOp> superImpl) {
return superImpl.apply(token, resolveDatasourceOp(code, uid, packageName, attributionTag),
uid, packageName, attributionTag, startIfModeDefault, shouldCollectAsyncNotedOp,
- message, shouldCollectMessage);
+ message, shouldCollectMessage, attributionFlags, attributionChainId);
}
@Override
- public SyncNotedAppOp startProxyOperation(IBinder token, int code,
+ public SyncNotedAppOp startProxyOperation(int code,
@NonNull AttributionSource attributionSource, boolean startIfModeDefault,
boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage,
- boolean skipProxyOperation, @NonNull OctFunction<IBinder, Integer, AttributionSource,
- Boolean, Boolean, String, Boolean, Boolean, SyncNotedAppOp> superImpl) {
- return superImpl.apply(token, resolveDatasourceOp(code, attributionSource.getUid(),
+ boolean skipProxyOperation, @AttributionFlags int proxyAttributionFlags,
+ @AttributionFlags int proxiedAttributionFlags, int attributionChainId,
+ @NonNull DecFunction<Integer, AttributionSource, Boolean, Boolean, String, Boolean,
+ Boolean, Integer, Integer, Integer, SyncNotedAppOp> superImpl) {
+ return superImpl.apply(resolveDatasourceOp(code, attributionSource.getUid(),
attributionSource.getPackageName(), attributionSource.getAttributionTag()),
attributionSource, startIfModeDefault, shouldCollectAsyncNotedOp, message,
- shouldCollectMessage, skipProxyOperation);
+ shouldCollectMessage, skipProxyOperation, proxyAttributionFlags,
+ proxiedAttributionFlags, attributionChainId);
}
@Override
- public void finishProxyOperation(IBinder clientId, int code,
- @NonNull AttributionSource attributionSource,
- @NonNull TriFunction<IBinder, Integer, AttributionSource, Void> superImpl) {
- superImpl.apply(clientId, resolveDatasourceOp(code, attributionSource.getUid(),
+ public void finishProxyOperation(int code, @NonNull AttributionSource attributionSource,
+ boolean skipProxyOperation, @NonNull TriFunction<Integer, AttributionSource,
+ Boolean, Void> superImpl) {
+ superImpl.apply(resolveDatasourceOp(code, attributionSource.getUid(),
attributionSource.getPackageName(), attributionSource.getAttributionTag()),
- attributionSource);
+ attributionSource, skipProxyOperation);
}
private int resolveDatasourceOp(int code, int uid, @NonNull String packageName,
diff --git a/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java b/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java
index 753b42b24556..0f37450c24c9 100644
--- a/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java
+++ b/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java
@@ -25,6 +25,8 @@ import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
import android.graphics.drawable.Icon;
import android.net.Uri;
import android.os.Binder;
@@ -59,6 +61,7 @@ import android.view.textclassifier.TextLinks;
import android.view.textclassifier.TextSelection;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.content.PackageMonitor;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.FunctionalUtils;
import com.android.internal.util.FunctionalUtils.ThrowingConsumer;
@@ -110,6 +113,7 @@ public final class TextClassificationManagerService extends ITextClassifierServi
try {
publishBinderService(Context.TEXT_CLASSIFICATION_SERVICE, mManagerService);
mManagerService.startListenSettings();
+ mManagerService.startTrackingPackageChanges();
} catch (Throwable t) {
// Starting this service is not critical to the running of this device and should
// therefore not crash the device. If it fails, log the error and continue.
@@ -119,11 +123,14 @@ public final class TextClassificationManagerService extends ITextClassifierServi
@Override
public void onUserStarting(@NonNull TargetUser user) {
+ updatePackageStateForUser(user.getUserIdentifier());
processAnyPendingWork(user.getUserIdentifier());
}
@Override
public void onUserUnlocking(@NonNull TargetUser user) {
+ // refresh if we failed earlier due to locked encrypted user
+ updatePackageStateForUser(user.getUserIdentifier());
// Rebind if we failed earlier due to locked encrypted user
processAnyPendingWork(user.getUserIdentifier());
}
@@ -134,6 +141,14 @@ public final class TextClassificationManagerService extends ITextClassifierServi
}
}
+ private void updatePackageStateForUser(int userId) {
+ synchronized (mManagerService.mLock) {
+ // Update the cached disable status, the TextClassfier may not be direct boot aware,
+ // we should update the disable status after user unlock
+ mManagerService.getUserStateLocked(userId).updatePackageStateLocked();
+ }
+ }
+
@Override
public void onUserStopping(@NonNull TargetUser user) {
int userId = user.getUserIdentifier();
@@ -160,6 +175,8 @@ public final class TextClassificationManagerService extends ITextClassifierServi
private final String mDefaultTextClassifierPackage;
@Nullable
private final String mSystemTextClassifierPackage;
+ // TODO: consider using device config to control it.
+ private boolean DEBUG = false;
private TextClassificationManagerService(Context context) {
mContext = Objects.requireNonNull(context);
@@ -176,6 +193,46 @@ public final class TextClassificationManagerService extends ITextClassifierServi
mSettingsListener.registerObserver();
}
+ void startTrackingPackageChanges() {
+ final PackageMonitor monitor = new PackageMonitor() {
+
+ @Override
+ public void onPackageAdded(String packageName, int uid) {
+ notifyPackageInstallStatusChange(packageName, /* installed*/ true);
+ }
+
+ @Override
+ public void onPackageRemoved(String packageName, int uid) {
+ notifyPackageInstallStatusChange(packageName, /* installed= */ false);
+ }
+
+ @Override
+ public void onPackageModified(String packageName) {
+ final int userId = getChangingUserId();
+ synchronized (mLock) {
+ final UserState userState = getUserStateLocked(userId);
+ final ServiceState serviceState = userState.getServiceStateLocked(packageName);
+ if (serviceState != null) {
+ serviceState.onPackageModifiedLocked();
+ }
+ }
+ }
+
+ private void notifyPackageInstallStatusChange(String packageName, boolean installed) {
+ final int userId = getChangingUserId();
+ synchronized (mLock) {
+ final UserState userState = getUserStateLocked(userId);
+ final ServiceState serviceState = userState.getServiceStateLocked(packageName);
+ if (serviceState != null) {
+ serviceState.onPackageInstallStatusChangeLocked(installed);
+ }
+ }
+ }
+ };
+
+ monitor.register(mContext, null, UserHandle.ALL, true);
+ }
+
@Override
public void onConnectedStateChanged(@ConnectionState int connected) {
}
@@ -452,6 +509,14 @@ public final class TextClassificationManagerService extends ITextClassifierServi
if (serviceState == null) {
Slog.d(LOG_TAG, "No configured system TextClassifierService");
callback.onFailure();
+ } else if (!serviceState.isInstalledLocked() || !serviceState.isEnabledLocked()) {
+ if (DEBUG) {
+ Slog.d(LOG_TAG,
+ serviceState.mPackageName + " is not available in user " + userId
+ + ". Installed: " + serviceState.isInstalledLocked()
+ + ", enabled:" + serviceState.isEnabledLocked());
+ }
+ callback.onFailure();
} else if (attemptToBind && !serviceState.bindLocked()) {
Slog.d(LOG_TAG, "Unable to bind TextClassifierService at " + methodName);
callback.onFailure();
@@ -761,6 +826,24 @@ public final class TextClassificationManagerService extends ITextClassifierServi
return serviceStates;
}
+ @GuardedBy("mLock")
+ @Nullable
+ private ServiceState getServiceStateLocked(String packageName) {
+ for (ServiceState serviceState : getAllServiceStatesLocked()) {
+ if (serviceState.mPackageName.equals(packageName)) {
+ return serviceState;
+ }
+ }
+ return null;
+ }
+
+ @GuardedBy("mLock")
+ private void updatePackageStateLocked() {
+ for (ServiceState serviceState : getAllServiceStatesLocked()) {
+ serviceState.updatePackageStateLocked();
+ }
+ }
+
void dump(IndentingPrintWriter pw) {
synchronized (mLock) {
pw.increaseIndent();
@@ -814,6 +897,10 @@ public final class TextClassificationManagerService extends ITextClassifierServi
ComponentName mBoundComponentName = null;
@GuardedBy("mLock")
int mBoundServiceUid = Process.INVALID_UID;
+ @GuardedBy("mLock")
+ boolean mInstalled;
+ @GuardedBy("mLock")
+ boolean mEnabled;
private ServiceState(
@UserIdInt int userId, @NonNull String packageName, boolean isTrusted) {
@@ -822,6 +909,8 @@ public final class TextClassificationManagerService extends ITextClassifierServi
mConnection = new TextClassifierServiceConnection(mUserId);
mIsTrusted = isTrusted;
mBindServiceFlags = createBindServiceFlags(packageName);
+ mInstalled = isPackageInstalledForUser();
+ mEnabled = isServiceEnabledForUser();
}
@Context.BindServiceFlags
@@ -833,6 +922,54 @@ public final class TextClassificationManagerService extends ITextClassifierServi
return flags;
}
+ private boolean isPackageInstalledForUser() {
+ try {
+ PackageManager packageManager = mContext.getPackageManager();
+ return packageManager.getPackageInfoAsUser(mPackageName, 0, mUserId) != null;
+ } catch (PackageManager.NameNotFoundException e) {
+ return false;
+ }
+ }
+
+ private boolean isServiceEnabledForUser() {
+ PackageManager packageManager = mContext.getPackageManager();
+ Intent intent = new Intent(TextClassifierService.SERVICE_INTERFACE);
+ intent.setPackage(mPackageName);
+ ResolveInfo resolveInfo = packageManager.resolveServiceAsUser(intent,
+ PackageManager.GET_SERVICES, mUserId);
+ ServiceInfo serviceInfo = resolveInfo == null ? null : resolveInfo.serviceInfo;
+ return serviceInfo != null;
+ }
+
+ @GuardedBy("mLock")
+ @NonNull
+ private void onPackageInstallStatusChangeLocked(boolean installed) {
+ mInstalled = installed;
+ }
+
+ @GuardedBy("mLock")
+ @NonNull
+ private void onPackageModifiedLocked() {
+ mEnabled = isServiceEnabledForUser();
+ }
+
+ @GuardedBy("mLock")
+ @NonNull
+ private void updatePackageStateLocked() {
+ mInstalled = isPackageInstalledForUser();
+ mEnabled = isServiceEnabledForUser();
+ }
+
+ @GuardedBy("mLock")
+ boolean isInstalledLocked() {
+ return mInstalled;
+ }
+
+ @GuardedBy("mLock")
+ boolean isEnabledLocked() {
+ return mEnabled;
+ }
+
@GuardedBy("mLock")
boolean isBoundLocked() {
return mService != null;
@@ -923,6 +1060,8 @@ public final class TextClassificationManagerService extends ITextClassifierServi
pw.printPair("userId", mUserId);
synchronized (mLock) {
pw.printPair("packageName", mPackageName);
+ pw.printPair("installed", mInstalled);
+ pw.printPair("enabled", mEnabled);
pw.printPair("boundComponentName", mBoundComponentName);
pw.printPair("isTrusted", mIsTrusted);
pw.printPair("bindServiceFlags", mBindServiceFlags);
diff --git a/services/core/java/com/android/server/vibrator/ClippingAmplitudeAndFrequencyAdapter.java b/services/core/java/com/android/server/vibrator/ClippingAmplitudeAndFrequencyAdapter.java
new file mode 100644
index 000000000000..0690d3be3db1
--- /dev/null
+++ b/services/core/java/com/android/server/vibrator/ClippingAmplitudeAndFrequencyAdapter.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.vibrator;
+
+import android.os.VibratorInfo;
+import android.os.vibrator.RampSegment;
+import android.os.vibrator.StepSegment;
+import android.os.vibrator.VibrationEffectSegment;
+import android.util.MathUtils;
+
+import java.util.List;
+
+/**
+ * Adapter that clips frequency values to {@link VibratorInfo#getFrequencyRange()} and
+ * amplitude values to respective {@link VibratorInfo#getMaxAmplitude}.
+ *
+ * <p>Devices with no frequency control will collapse all frequencies to zero and leave
+ * amplitudes unchanged.
+ *
+ * <p>The frequency value returned in segments will be absolute, converted with
+ * {@link VibratorInfo#getAbsoluteFrequency(float)}.
+ */
+final class ClippingAmplitudeAndFrequencyAdapter
+ implements VibrationEffectAdapters.SegmentsAdapter<VibratorInfo> {
+
+ @Override
+ public int apply(List<VibrationEffectSegment> segments, int repeatIndex, VibratorInfo info) {
+ int segmentCount = segments.size();
+ for (int i = 0; i < segmentCount; i++) {
+ VibrationEffectSegment segment = segments.get(i);
+ if (segment instanceof StepSegment) {
+ segments.set(i, apply((StepSegment) segment, info));
+ } else if (segment instanceof RampSegment) {
+ segments.set(i, apply((RampSegment) segment, info));
+ }
+ }
+ return repeatIndex;
+ }
+
+ private StepSegment apply(StepSegment segment, VibratorInfo info) {
+ float clampedFrequency = clampFrequency(info, segment.getFrequency());
+ return new StepSegment(
+ clampAmplitude(info, clampedFrequency, segment.getAmplitude()),
+ info.getAbsoluteFrequency(clampedFrequency),
+ (int) segment.getDuration());
+ }
+
+ private RampSegment apply(RampSegment segment, VibratorInfo info) {
+ float clampedStartFrequency = clampFrequency(info, segment.getStartFrequency());
+ float clampedEndFrequency = clampFrequency(info, segment.getEndFrequency());
+ return new RampSegment(
+ clampAmplitude(info, clampedStartFrequency, segment.getStartAmplitude()),
+ clampAmplitude(info, clampedEndFrequency, segment.getEndAmplitude()),
+ info.getAbsoluteFrequency(clampedStartFrequency),
+ info.getAbsoluteFrequency(clampedEndFrequency),
+ (int) segment.getDuration());
+ }
+
+ private float clampFrequency(VibratorInfo info, float frequency) {
+ return info.getFrequencyRange().clamp(frequency);
+ }
+
+ private float clampAmplitude(VibratorInfo info, float frequency, float amplitude) {
+ return MathUtils.min(amplitude, info.getMaxAmplitude(frequency));
+ }
+}
diff --git a/services/core/java/com/android/server/vibrator/DeviceVibrationEffectAdapter.java b/services/core/java/com/android/server/vibrator/DeviceVibrationEffectAdapter.java
index 7f2b07b6f367..b695150d9ba3 100644
--- a/services/core/java/com/android/server/vibrator/DeviceVibrationEffectAdapter.java
+++ b/services/core/java/com/android/server/vibrator/DeviceVibrationEffectAdapter.java
@@ -16,159 +16,33 @@
package com.android.server.vibrator;
-import android.hardware.vibrator.IVibrator;
import android.os.VibrationEffect;
import android.os.VibratorInfo;
-import android.os.vibrator.RampSegment;
-import android.os.vibrator.StepSegment;
-import android.os.vibrator.VibrationEffectSegment;
-import android.util.MathUtils;
-import android.util.Range;
-import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
/** Adapts a {@link VibrationEffect} to a specific device, taking into account its capabilities. */
-final class DeviceVibrationEffectAdapter implements VibrationEffectModifier<VibratorInfo> {
+final class DeviceVibrationEffectAdapter
+ implements VibrationEffectAdapters.EffectAdapter<VibratorInfo> {
- /** Adapts a sequence of {@link VibrationEffectSegment} to device's capabilities. */
- interface SegmentsAdapter {
+ /** Duration of each step created to simulate a ramp segment. */
+ private static final int RAMP_STEP_DURATION_MILLIS = 5;
- /**
- * Modifies the given segments list by adding/removing segments to it based on the
- * device capabilities specified by given {@link VibratorInfo}.
- *
- * @param segments List of {@link VibrationEffectSegment} to be adapter to the device.
- * @param repeatIndex Repeat index on the current segment list.
- * @param info The device vibrator info that the segments must be adapted to.
- * @return The new repeat index on the modifies list.
- */
- int apply(List<VibrationEffectSegment> segments, int repeatIndex, VibratorInfo info);
- }
-
- private final SegmentsAdapter mAmplitudeFrequencyAdapter;
- private final SegmentsAdapter mStepToRampAdapter;
+ private final List<VibrationEffectAdapters.SegmentsAdapter<VibratorInfo>> mSegmentAdapters;
DeviceVibrationEffectAdapter() {
- this(new ClippingAmplitudeFrequencyAdapter());
- }
-
- DeviceVibrationEffectAdapter(SegmentsAdapter amplitudeFrequencyAdapter) {
- mAmplitudeFrequencyAdapter = amplitudeFrequencyAdapter;
- mStepToRampAdapter = new StepToRampAdapter();
+ mSegmentAdapters = Arrays.asList(
+ // TODO(b/167947076): add filter that removes unsupported primitives
+ // TODO(b/167947076): add filter that replaces unsupported prebaked with fallback
+ new RampToStepAdapter(RAMP_STEP_DURATION_MILLIS),
+ new StepToRampAdapter(),
+ new ClippingAmplitudeAndFrequencyAdapter()
+ );
}
@Override
public VibrationEffect apply(VibrationEffect effect, VibratorInfo info) {
- if (!(effect instanceof VibrationEffect.Composed)) {
- return effect;
- }
-
- VibrationEffect.Composed composed = (VibrationEffect.Composed) effect;
- List<VibrationEffectSegment> newSegments = new ArrayList<>(composed.getSegments());
- int newRepeatIndex = composed.getRepeatIndex();
-
- // Maps steps that should be handled by PWLE to ramps.
- // This should be done before frequency is converted from relative to absolute values.
- newRepeatIndex = mStepToRampAdapter.apply(newSegments, newRepeatIndex, info);
-
- // Adapt amplitude and frequency values to device supported ones, converting frequency
- // to absolute values in Hertz.
- newRepeatIndex = mAmplitudeFrequencyAdapter.apply(newSegments, newRepeatIndex, info);
-
- // TODO(b/167947076): add ramp to step adapter
- // TODO(b/167947076): add filter that removes unsupported primitives
- // TODO(b/167947076): add filter that replaces unsupported prebaked with fallback
-
- return new VibrationEffect.Composed(newSegments, newRepeatIndex);
- }
-
- /**
- * Adapter that converts step segments that should be handled as PWLEs to ramp segments.
- *
- * <p>This leves the list unchanged if the device do not have compose PWLE capability.
- */
- private static final class StepToRampAdapter implements SegmentsAdapter {
- @Override
- public int apply(List<VibrationEffectSegment> segments, int repeatIndex,
- VibratorInfo info) {
- if (!info.hasCapability(IVibrator.CAP_COMPOSE_PWLE_EFFECTS)) {
- // The vibrator do not have PWLE capability, so keep the segments unchanged.
- return repeatIndex;
- }
- int segmentCount = segments.size();
- // Convert steps that require frequency control to ramps.
- for (int i = 0; i < segmentCount; i++) {
- VibrationEffectSegment segment = segments.get(i);
- if ((segment instanceof StepSegment)
- && ((StepSegment) segment).getFrequency() != 0) {
- segments.set(i, apply((StepSegment) segment));
- }
- }
- // Convert steps that are next to ramps to also become ramps, so they can be composed
- // together in the same PWLE waveform.
- for (int i = 1; i < segmentCount; i++) {
- if (segments.get(i) instanceof RampSegment) {
- for (int j = i - 1; j >= 0 && (segments.get(j) instanceof StepSegment); j--) {
- segments.set(j, apply((StepSegment) segments.get(j)));
- }
- }
- }
- return repeatIndex;
- }
-
- private RampSegment apply(StepSegment segment) {
- return new RampSegment(segment.getAmplitude(), segment.getAmplitude(),
- segment.getFrequency(), segment.getFrequency(), (int) segment.getDuration());
- }
- }
-
- /**
- * Adapter that clips frequency values to {@link VibratorInfo#getFrequencyRange()} and
- * amplitude values to respective {@link VibratorInfo#getMaxAmplitude}.
- *
- * <p>Devices with no frequency control will collapse all frequencies to zero and leave
- * amplitudes unchanged.
- *
- * <p>The frequency value returned in segments will be absolute, conveted with
- * {@link VibratorInfo#getAbsoluteFrequency(float)}.
- */
- private static final class ClippingAmplitudeFrequencyAdapter implements SegmentsAdapter {
- @Override
- public int apply(List<VibrationEffectSegment> segments, int repeatIndex,
- VibratorInfo info) {
- int segmentCount = segments.size();
- for (int i = 0; i < segmentCount; i++) {
- VibrationEffectSegment segment = segments.get(i);
- if (segment instanceof StepSegment) {
- segments.set(i, apply((StepSegment) segment, info));
- } else if (segment instanceof RampSegment) {
- segments.set(i, apply((RampSegment) segment, info));
- }
- }
- return repeatIndex;
- }
-
- private StepSegment apply(StepSegment segment, VibratorInfo info) {
- float clampedFrequency = info.getFrequencyRange().clamp(segment.getFrequency());
- return new StepSegment(
- MathUtils.min(segment.getAmplitude(), info.getMaxAmplitude(clampedFrequency)),
- info.getAbsoluteFrequency(clampedFrequency),
- (int) segment.getDuration());
- }
-
- private RampSegment apply(RampSegment segment, VibratorInfo info) {
- Range<Float> frequencyRange = info.getFrequencyRange();
- float clampedStartFrequency = frequencyRange.clamp(segment.getStartFrequency());
- float clampedEndFrequency = frequencyRange.clamp(segment.getEndFrequency());
- return new RampSegment(
- MathUtils.min(segment.getStartAmplitude(),
- info.getMaxAmplitude(clampedStartFrequency)),
- MathUtils.min(segment.getEndAmplitude(),
- info.getMaxAmplitude(clampedEndFrequency)),
- info.getAbsoluteFrequency(clampedStartFrequency),
- info.getAbsoluteFrequency(clampedEndFrequency),
- (int) segment.getDuration());
- }
+ return VibrationEffectAdapters.apply(effect, mSegmentAdapters, info);
}
}
diff --git a/services/core/java/com/android/server/vibrator/RampToStepAdapter.java b/services/core/java/com/android/server/vibrator/RampToStepAdapter.java
new file mode 100644
index 000000000000..1e05bdbdf082
--- /dev/null
+++ b/services/core/java/com/android/server/vibrator/RampToStepAdapter.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.vibrator;
+
+import android.hardware.vibrator.IVibrator;
+import android.os.VibratorInfo;
+import android.os.vibrator.RampSegment;
+import android.os.vibrator.StepSegment;
+import android.os.vibrator.VibrationEffectSegment;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Adapter that converts ramp segments that to a sequence of fixed step segments.
+ *
+ * <p>This leaves the list unchanged if the device have compose PWLE capability.
+ */
+final class RampToStepAdapter implements VibrationEffectAdapters.SegmentsAdapter<VibratorInfo> {
+
+ private final int mStepDuration;
+
+ RampToStepAdapter(int stepDuration) {
+ mStepDuration = stepDuration;
+ }
+
+ @Override
+ public int apply(List<VibrationEffectSegment> segments, int repeatIndex,
+ VibratorInfo info) {
+ if (info.hasCapability(IVibrator.CAP_COMPOSE_PWLE_EFFECTS)) {
+ // The vibrator have PWLE capability, so keep the segments unchanged.
+ return repeatIndex;
+ }
+ int segmentCount = segments.size();
+ for (int i = 0; i < segmentCount; i++) {
+ VibrationEffectSegment segment = segments.get(i);
+ if (!(segment instanceof RampSegment)) {
+ continue;
+ }
+ List<StepSegment> steps = apply((RampSegment) segment);
+ segments.remove(i);
+ segments.addAll(i, steps);
+ int addedSegments = steps.size() - 1;
+ if (repeatIndex > i) {
+ repeatIndex += addedSegments;
+ }
+ i += addedSegments;
+ segmentCount += addedSegments;
+ }
+ return repeatIndex;
+ }
+
+ private List<StepSegment> apply(RampSegment ramp) {
+ if (Float.compare(ramp.getStartAmplitude(), ramp.getEndAmplitude()) == 0) {
+ // Amplitude is the same, so return a single step to simulate this ramp.
+ return Arrays.asList(
+ new StepSegment(ramp.getStartAmplitude(), ramp.getStartFrequency(),
+ (int) ramp.getDuration()));
+ }
+
+ List<StepSegment> steps = new ArrayList<>();
+ int stepCount = (int) (ramp.getDuration() + mStepDuration - 1) / mStepDuration;
+ for (int i = 0; i < stepCount - 1; i++) {
+ float pos = (float) i / stepCount;
+ steps.add(new StepSegment(
+ interpolate(ramp.getStartAmplitude(), ramp.getEndAmplitude(), pos),
+ interpolate(ramp.getStartFrequency(), ramp.getEndFrequency(), pos),
+ mStepDuration));
+ }
+ int duration = (int) ramp.getDuration() - mStepDuration * (stepCount - 1);
+ steps.add(new StepSegment(ramp.getEndAmplitude(), ramp.getEndFrequency(), duration));
+ return steps;
+ }
+
+ private static float interpolate(float start, float end, float position) {
+ return start + position * (end - start);
+ }
+}
diff --git a/services/core/java/com/android/server/vibrator/StepToRampAdapter.java b/services/core/java/com/android/server/vibrator/StepToRampAdapter.java
new file mode 100644
index 000000000000..f78df9208fbd
--- /dev/null
+++ b/services/core/java/com/android/server/vibrator/StepToRampAdapter.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.vibrator;
+
+import android.hardware.vibrator.IVibrator;
+import android.os.VibratorInfo;
+import android.os.vibrator.RampSegment;
+import android.os.vibrator.StepSegment;
+import android.os.vibrator.VibrationEffectSegment;
+
+import java.util.List;
+
+/**
+ * Adapter that converts step segments that should be handled as PWLEs to ramp segments.
+ *
+ * <p>This leaves the list unchanged if the device do not have compose PWLE capability.
+ */
+final class StepToRampAdapter implements VibrationEffectAdapters.SegmentsAdapter<VibratorInfo> {
+ @Override
+ public int apply(List<VibrationEffectSegment> segments, int repeatIndex,
+ VibratorInfo info) {
+ if (!info.hasCapability(IVibrator.CAP_COMPOSE_PWLE_EFFECTS)) {
+ // The vibrator do not have PWLE capability, so keep the segments unchanged.
+ return repeatIndex;
+ }
+ int segmentCount = segments.size();
+ // Convert steps that require frequency control to ramps.
+ for (int i = 0; i < segmentCount; i++) {
+ VibrationEffectSegment segment = segments.get(i);
+ if ((segment instanceof StepSegment)
+ && ((StepSegment) segment).getFrequency() != 0) {
+ segments.set(i, apply((StepSegment) segment));
+ }
+ }
+ // Convert steps that are next to ramps to also become ramps, so they can be composed
+ // together in the same PWLE waveform.
+ for (int i = 1; i < segmentCount; i++) {
+ if (segments.get(i) instanceof RampSegment) {
+ for (int j = i - 1; j >= 0 && (segments.get(j) instanceof StepSegment); j--) {
+ segments.set(j, apply((StepSegment) segments.get(j)));
+ }
+ }
+ }
+ return repeatIndex;
+ }
+
+ private RampSegment apply(StepSegment segment) {
+ return new RampSegment(segment.getAmplitude(), segment.getAmplitude(),
+ segment.getFrequency(), segment.getFrequency(), (int) segment.getDuration());
+ }
+}
diff --git a/services/core/java/com/android/server/vibrator/VibrationEffectAdapters.java b/services/core/java/com/android/server/vibrator/VibrationEffectAdapters.java
new file mode 100644
index 000000000000..446d9810ff19
--- /dev/null
+++ b/services/core/java/com/android/server/vibrator/VibrationEffectAdapters.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.vibrator;
+
+import android.os.VibrationEffect;
+import android.os.vibrator.VibrationEffectSegment;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Helpers to adapt a {@link VibrationEffect} to generic modifiers (e.g. device capabilities,
+ * user settings, etc).
+ */
+public final class VibrationEffectAdapters {
+
+ /**
+ * Function that applies a generic modifier to a sequence of {@link VibrationEffectSegment}.
+ *
+ * @param <T> The type of modifiers this adapter accepts.
+ */
+ public interface SegmentsAdapter<T> {
+
+ /**
+ * Add and/or remove segments to the given {@link VibrationEffectSegment} list based on the
+ * given modifier.
+ *
+ * <p>This returns the new {@code repeatIndex} to be used together with the updated list to
+ * specify an equivalent {@link VibrationEffect}.
+ *
+ * @param segments List of {@link VibrationEffectSegment} to be modified.
+ * @param repeatIndex Repeat index on the current segment list.
+ * @param modifier The modifier to be applied to the sequence of segments.
+ * @return The new repeat index on the modifies list.
+ */
+ int apply(List<VibrationEffectSegment> segments, int repeatIndex, T modifier);
+ }
+
+ /**
+ * Function that applies a generic modifier to a {@link VibrationEffect}.
+ *
+ * @param <T> The type of modifiers this adapter accepts.
+ */
+ public interface EffectAdapter<T> {
+
+ /** Applies the modifier to given {@link VibrationEffect}, returning the new effect. */
+ VibrationEffect apply(VibrationEffect effect, T modifier);
+ }
+
+ /**
+ * Applies a sequence of {@link SegmentsAdapter} to the segments of a given
+ * {@link VibrationEffect}, in order.
+ *
+ * @param effect The effect to be adapted to given modifier.
+ * @param adapters The sequence of adapters to be applied to given {@link VibrationEffect}.
+ * @param modifier The modifier to be passed to each adapter that describes the conditions the
+ * {@link VibrationEffect} needs to be adapted to (e.g. device capabilities,
+ * user settings, etc).
+ */
+ public static <T> VibrationEffect apply(VibrationEffect effect,
+ List<SegmentsAdapter<T>> adapters, T modifier) {
+ if (!(effect instanceof VibrationEffect.Composed)) {
+ // Segments adapters can only be applied to Composed effects.
+ return effect;
+ }
+
+ VibrationEffect.Composed composed = (VibrationEffect.Composed) effect;
+ List<VibrationEffectSegment> newSegments = new ArrayList<>(composed.getSegments());
+ int newRepeatIndex = composed.getRepeatIndex();
+
+ int adapterCount = adapters.size();
+ for (int i = 0; i < adapterCount; i++) {
+ newRepeatIndex = adapters.get(i).apply(newSegments, newRepeatIndex, modifier);
+ }
+
+ return new VibrationEffect.Composed(newSegments, newRepeatIndex);
+ }
+}
diff --git a/services/core/java/com/android/server/vibrator/VibrationEffectModifier.java b/services/core/java/com/android/server/vibrator/VibrationEffectModifier.java
deleted file mode 100644
index d287c8faa34d..000000000000
--- a/services/core/java/com/android/server/vibrator/VibrationEffectModifier.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.vibrator;
-
-import android.os.VibrationEffect;
-
-/** Function that applies a generic modifier to a {@link VibrationEffect}. */
-interface VibrationEffectModifier<T> {
-
- /** Applies the modifier to given {@link VibrationEffect}. */
- VibrationEffect apply(VibrationEffect effect, T modifier);
-}
diff --git a/services/core/java/com/android/server/vibrator/VibrationThread.java b/services/core/java/com/android/server/vibrator/VibrationThread.java
index b3f1bcd444cc..e3672f4d497c 100644
--- a/services/core/java/com/android/server/vibrator/VibrationThread.java
+++ b/services/core/java/com/android/server/vibrator/VibrationThread.java
@@ -95,7 +95,7 @@ final class VibrationThread extends Thread implements IBinder.DeathRecipient {
private final WorkSource mWorkSource = new WorkSource();
private final PowerManager.WakeLock mWakeLock;
private final IBatteryStats mBatteryStatsService;
- private final VibrationEffectModifier<VibratorInfo> mDeviceEffectAdapter =
+ private final DeviceVibrationEffectAdapter mDeviceEffectAdapter =
new DeviceVibrationEffectAdapter();
private final Vibration mVibration;
private final VibrationCallbacks mCallbacks;
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 3969a5f8d50c..d4df2f258a04 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -7013,7 +7013,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// TODO(b/181207944): Consider removing the if condition and always run
// resolveFixedOrientationConfiguration() since this should be applied for all cases.
if (isFixedOrientationLetterboxAllowed) {
- resolveFixedOrientationConfiguration(newParentConfiguration);
+ resolveFixedOrientationConfiguration(newParentConfiguration, parentWindowingMode);
}
if (mCompatDisplayInsets != null) {
@@ -7160,16 +7160,21 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
* change and the requested orientation is different from the parent.
*
* <p>If letterboxed due to fixed orientation then aspect ratio restrictions are also applied
- * in this methiod.
+ * in this method.
*/
- private void resolveFixedOrientationConfiguration(@NonNull Configuration newParentConfig) {
+ private void resolveFixedOrientationConfiguration(@NonNull Configuration newParentConfig,
+ int windowingMode) {
mLetterboxBoundsForFixedOrientationAndAspectRatio = null;
if (handlesOrientationChangeFromDescendant()) {
// No need to letterbox because of fixed orientation. Display will handle
// fixed-orientation requests.
return;
}
- if (newParentConfig.windowConfiguration.getWindowingMode() == WINDOWING_MODE_PINNED) {
+ if (WindowConfiguration.inMultiWindowMode(windowingMode) && isResizeable()) {
+ // Ignore orientation request for resizable apps in multi window.
+ return;
+ }
+ if (windowingMode == WINDOWING_MODE_PINNED) {
// PiP bounds have higher priority than the requested orientation. Otherwise the
// activity may be squeezed into a small piece.
return;
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 29e55df32509..5e75cebc322d 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -2835,7 +2835,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
List<IBinder> topActivityToken = new ArrayList<>();
topActivityToken.add(tokens.getActivityToken());
requester.requestAssistData(topActivityToken, true /* fetchData */,
- false /* fetchScreenshot */, true /* allowFetchData */,
+ false /* fetchScreenshot */, false /* fetchStructure */, true /* allowFetchData */,
false /* allowFetchScreenshot*/, true /* ignoreFocusCheck */,
Binder.getCallingUid(), callingPackageName);
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index b7ba8f8cf3c9..81992d8934ed 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -5013,28 +5013,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
}
/**
- * Re-parent the DisplayContent's top surface, {@link #mSurfaceControl} to the specified
- * SurfaceControl.
- *
- * @param win The window which owns the SurfaceControl. This indicates the z-order of the
- * windows of this display against the windows on the parent display.
- * @param sc The new SurfaceControl, where the DisplayContent's surfaces will be re-parented to.
- */
- void reparentDisplayContent(WindowState win, SurfaceControl sc) {
- if (mParentWindow != null) {
- mParentWindow.removeEmbeddedDisplayContent(this);
- }
- mParentWindow = win;
- mParentWindow.addEmbeddedDisplayContent(this);
- mParentSurfaceControl = sc;
- if (mPortalWindowHandle == null) {
- mPortalWindowHandle = createPortalWindowHandle(sc.toString());
- }
- getPendingTransaction().setInputWindowInfo(sc, mPortalWindowHandle)
- .reparent(mSurfaceControl, sc);
- }
-
- /**
* Get the window which owns the surface that this DisplayContent is re-parented to.
*
* @return the parent window.
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 70f2d64e89aa..977df93412f8 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -1453,8 +1453,7 @@ public class DisplayPolicy {
}
void onDisplayInfoChanged(DisplayInfo info) {
- mSystemGestures.screenWidth = info.logicalWidth;
- mSystemGestures.screenHeight = info.logicalHeight;
+ mSystemGestures.onDisplayInfoChanged(info);
}
private void layoutStatusBar(DisplayFrames displayFrames, Rect contentFrame) {
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index c6cd5606770e..e28201245d9b 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -609,11 +609,6 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient {
}
@Override
- public void reparentDisplayContent(IWindow window, SurfaceControl sc, int displayId) {
- mService.reparentDisplayContent(window, sc, displayId);
- }
-
- @Override
public void updateDisplayContentLocation(IWindow window, int x, int y, int displayId) {
mService.updateDisplayContentLocation(window, x, y, displayId);
}
diff --git a/services/core/java/com/android/server/wm/SystemGesturesPointerEventListener.java b/services/core/java/com/android/server/wm/SystemGesturesPointerEventListener.java
index f3859b41b6fd..513b1b715a27 100644
--- a/services/core/java/com/android/server/wm/SystemGesturesPointerEventListener.java
+++ b/services/core/java/com/android/server/wm/SystemGesturesPointerEventListener.java
@@ -17,6 +17,7 @@
package com.android.server.wm;
import android.content.Context;
+import android.content.res.Resources;
import android.graphics.Rect;
import android.graphics.Region;
import android.hardware.display.DisplayManagerGlobal;
@@ -65,6 +66,7 @@ class SystemGesturesPointerEventListener implements PointerEventListener {
int screenHeight;
int screenWidth;
+ private DisplayInfo mTmpDisplayInfo = new DisplayInfo();
private int mDownPointers;
private boolean mSwipeFireable;
private boolean mDebugFireable;
@@ -75,23 +77,31 @@ class SystemGesturesPointerEventListener implements PointerEventListener {
mContext = checkNull("context", context);
mHandler = handler;
mCallbacks = checkNull("callbacks", callbacks);
+ onConfigurationChanged();
+ }
+ void onDisplayInfoChanged(DisplayInfo info) {
+ screenWidth = info.logicalWidth;
+ screenHeight = info.logicalHeight;
onConfigurationChanged();
}
void onConfigurationChanged() {
- mSwipeStartThreshold = mContext.getResources()
- .getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
-
+ final Resources r = mContext.getResources();
final Display display = DisplayManagerGlobal.getInstance()
.getRealDisplay(Display.DEFAULT_DISPLAY);
+ display.getDisplayInfo(mTmpDisplayInfo);
+ mSwipeStartThreshold = mTmpDisplayInfo.logicalWidth > mTmpDisplayInfo.logicalHeight
+ ? r.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height_landscape)
+ : r.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height_portrait);
+
final DisplayCutout displayCutout = display.getCutout();
if (displayCutout != null) {
final Rect bounds = displayCutout.getBoundingRectTop();
if (!bounds.isEmpty()) {
// Expand swipe start threshold such that we can catch touches that just start below
// the notch area
- mDisplayCutoutTouchableRegionSize = mContext.getResources().getDimensionPixelSize(
+ mDisplayCutoutTouchableRegionSize = r.getDimensionPixelSize(
com.android.internal.R.dimen.display_cutout_touchable_region_size);
mSwipeStartThreshold += mDisplayCutoutTouchableRegionSize;
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 7df5744cdf15..1042a0b13e1c 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2329,6 +2329,17 @@ public class WindowManagerService extends IWindowManager.Stub
}
result |= RELAYOUT_RES_SURFACE_CHANGED;
if (!win.mWillReplaceWindow) {
+ // When FLAG_SHOW_WALLPAPER flag is removed from a window, we usually set a flag
+ // in DC#pendingLayoutChanges and update the wallpaper target later.
+ // However it's possible that FLAG_SHOW_WALLPAPER flag is removed from a window
+ // when the window is about to exit, so we update the wallpaper target
+ // immediately here. Otherwise this window will be stuck in exiting and its
+ // surface remains on the screen.
+ // TODO(b/189856716): Allow destroying surface even if it belongs to the
+ // keyguard target.
+ if (wallpaperMayMove) {
+ displayContent.mWallpaperController.adjustWallpaperWindows();
+ }
focusMayChange = tryStartExitingAnimation(win, winAnimator, focusMayChange);
}
}
@@ -6960,32 +6971,6 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
- /** @see Session#reparentDisplayContent(IWindow, SurfaceControl, int) */
- void reparentDisplayContent(IWindow client, SurfaceControl sc, int displayId) {
- checkCallerOwnsDisplay(displayId);
-
- synchronized (mGlobalLock) {
- int uid = Binder.getCallingUid();
- final long token = Binder.clearCallingIdentity();
- try {
- final WindowState win = windowForClientLocked(null, client, false);
- if (win == null) {
- ProtoLog.w(WM_ERROR, "Bad requesting window %s", client);
- return;
- }
- getDisplayContentOrCreate(displayId, null).reparentDisplayContent(win, sc);
- // Notifies AccessibilityController to re-compute the window observer of
- // this embedded display
- if (mAccessibilityController != null) {
- mAccessibilityController.handleWindowObserverOfEmbeddedDisplay(
- displayId, win, uid);
- }
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
- }
-
/** @see Session#updateDisplayContentLocation(IWindow, int, int, int) */
void updateDisplayContentLocation(IWindow client, int x, int y, int displayId) {
checkCallerOwnsDisplay(displayId);
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 5f4798650184..20a992d244c5 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -1500,7 +1500,9 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
}
boolean didFrameInsetsChange = setReportResizeHints();
- boolean configChanged = !isLastConfigReportedToClient();
+ // The latest configuration will be returned by the out parameter of relayout, so it is
+ // unnecessary to report resize if this window is running relayout.
+ final boolean configChanged = !mInRelayout && !isLastConfigReportedToClient();
if (DEBUG_CONFIGURATION && configChanged) {
Slog.v(TAG_WM, "Win " + this + " config changed: " + getConfiguration());
}
diff --git a/services/tests/mockingservicestests/Android.bp b/services/tests/mockingservicestests/Android.bp
index 64b9a63991b4..24e11af23798 100644
--- a/services/tests/mockingservicestests/Android.bp
+++ b/services/tests/mockingservicestests/Android.bp
@@ -31,7 +31,10 @@ android_test {
name: "FrameworksMockingServicesTests",
defaults: ["FrameworkMockingServicesTests-jni-defaults"],
- srcs: ["src/**/*.java", "src/**/*.kt"],
+ srcs: [
+ "src/**/*.java",
+ "src/**/*.kt",
+ ],
static_libs: [
"services.core",
@@ -41,6 +44,7 @@ android_test {
"service-jobscheduler",
"service-permission.impl",
"service-blobstore",
+ "service-appsearch",
"androidx.test.runner",
"androidx.test.ext.truth",
"mockito-target-extended-minus-junit4",
diff --git a/services/tests/mockingservicestests/src/com/android/server/appsearch/AppSearchConfigTest.java b/services/tests/mockingservicestests/src/com/android/server/appsearch/AppSearchConfigTest.java
new file mode 100644
index 000000000000..c4860287c567
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/appsearch/AppSearchConfigTest.java
@@ -0,0 +1,286 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.appsearch;
+
+import static com.android.internal.util.ConcurrentUtils.DIRECT_EXECUTOR;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.provider.DeviceConfig;
+
+import com.android.server.testables.TestableDeviceConfig;
+
+import org.junit.Assert;
+import org.junit.Rule;
+import org.junit.Test;
+
+/**
+ * Tests for {@link AppSearchConfig}.
+ *
+ * <p>Build/Install/Run: atest FrameworksMockingServicesTests:AppSearchConfigTest
+ */
+public class AppSearchConfigTest {
+ @Rule
+ public final TestableDeviceConfig.TestableDeviceConfigRule
+ mDeviceConfigRule = new TestableDeviceConfig.TestableDeviceConfigRule();
+
+ @Test
+ public void testDefaultValues_allCachedValue() {
+ AppSearchConfig appSearchConfig = AppSearchConfig.create(DIRECT_EXECUTOR);
+
+ assertThat(appSearchConfig.getCachedMinTimeIntervalBetweenSamplesMillis()).isEqualTo(
+ AppSearchConfig.DEFAULT_MIN_TIME_INTERVAL_BETWEEN_SAMPLES_MILLIS);
+ assertThat(appSearchConfig.getCachedSamplingIntervalDefault()).isEqualTo(
+ AppSearchConfig.DEFAULT_SAMPLING_INTERVAL);
+ assertThat(appSearchConfig.getCachedSamplingIntervalForBatchCallStats()).isEqualTo(
+ AppSearchConfig.DEFAULT_SAMPLING_INTERVAL);
+ assertThat(appSearchConfig.getCachedSamplingIntervalForPutDocumentStats()).isEqualTo(
+ AppSearchConfig.DEFAULT_SAMPLING_INTERVAL);
+ }
+
+ @Test
+ public void testCustomizedValue_minTimeIntervalBetweenSamplesMillis() {
+ final long minTimeIntervalBetweenSamplesMillis = -1;
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ AppSearchConfig.KEY_MIN_TIME_INTERVAL_BETWEEN_SAMPLES_MILLIS,
+ Long.toString(minTimeIntervalBetweenSamplesMillis),
+ false);
+
+ AppSearchConfig appSearchConfig = AppSearchConfig.create(DIRECT_EXECUTOR);
+
+ assertThat(appSearchConfig.getCachedMinTimeIntervalBetweenSamplesMillis()).isEqualTo(
+ minTimeIntervalBetweenSamplesMillis);
+ }
+
+ @Test
+ public void testCustomizedValueOverride_minTimeIntervalBetweenSamplesMillis() {
+ long minTimeIntervalBetweenSamplesMillis = -1;
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ AppSearchConfig.KEY_MIN_TIME_INTERVAL_BETWEEN_SAMPLES_MILLIS,
+ Long.toString(minTimeIntervalBetweenSamplesMillis),
+ false);
+ AppSearchConfig appSearchConfig = AppSearchConfig.create(DIRECT_EXECUTOR);
+
+ minTimeIntervalBetweenSamplesMillis = -2;
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ AppSearchConfig.KEY_MIN_TIME_INTERVAL_BETWEEN_SAMPLES_MILLIS,
+ Long.toString(minTimeIntervalBetweenSamplesMillis),
+ false);
+
+ assertThat(appSearchConfig.getCachedMinTimeIntervalBetweenSamplesMillis()).isEqualTo(
+ minTimeIntervalBetweenSamplesMillis);
+ }
+
+ @Test
+ public void testCustomizedValue_allSamplingIntervals() {
+ final int samplingIntervalDefault = -1;
+ final int samplingIntervalPutDocumentStats = -2;
+ final int samplingIntervalBatchCallStats = -3;
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ AppSearchConfig.KEY_SAMPLING_INTERVAL_DEFAULT,
+ Integer.toString(samplingIntervalDefault),
+ false);
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_PUT_DOCUMENT_STATS,
+ Integer.toString(samplingIntervalPutDocumentStats),
+ false);
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_BATCH_CALL_STATS,
+ Integer.toString(samplingIntervalBatchCallStats),
+ false);
+
+ AppSearchConfig appSearchConfig = AppSearchConfig.create(DIRECT_EXECUTOR);
+
+ assertThat(appSearchConfig.getCachedSamplingIntervalDefault()).isEqualTo(
+ samplingIntervalDefault);
+ assertThat(appSearchConfig.getCachedSamplingIntervalForPutDocumentStats()).isEqualTo(
+ samplingIntervalPutDocumentStats);
+ assertThat(appSearchConfig.getCachedSamplingIntervalForBatchCallStats()).isEqualTo(
+ samplingIntervalBatchCallStats);
+ }
+
+ @Test
+ public void testCustomizedValueOverride_allSamplingIntervals() {
+ int samplingIntervalDefault = -1;
+ int samplingIntervalPutDocumentStats = -2;
+ int samplingIntervalBatchCallStats = -3;
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ AppSearchConfig.KEY_SAMPLING_INTERVAL_DEFAULT,
+ Integer.toString(samplingIntervalDefault),
+ false);
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_PUT_DOCUMENT_STATS,
+ Integer.toString(samplingIntervalPutDocumentStats),
+ false);
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_BATCH_CALL_STATS,
+ Integer.toString(samplingIntervalBatchCallStats),
+ false);
+ AppSearchConfig appSearchConfig = AppSearchConfig.create(DIRECT_EXECUTOR);
+
+ // Overrides
+ samplingIntervalDefault = -4;
+ samplingIntervalPutDocumentStats = -5;
+ samplingIntervalBatchCallStats = -6;
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ AppSearchConfig.KEY_SAMPLING_INTERVAL_DEFAULT,
+ Integer.toString(samplingIntervalDefault),
+ false);
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_PUT_DOCUMENT_STATS,
+ Integer.toString(samplingIntervalPutDocumentStats),
+ false);
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_BATCH_CALL_STATS,
+ Integer.toString(samplingIntervalBatchCallStats),
+ false);
+
+ assertThat(appSearchConfig.getCachedSamplingIntervalDefault()).isEqualTo(
+ samplingIntervalDefault);
+ assertThat(appSearchConfig.getCachedSamplingIntervalForPutDocumentStats()).isEqualTo(
+ samplingIntervalPutDocumentStats);
+ assertThat(appSearchConfig.getCachedSamplingIntervalForBatchCallStats()).isEqualTo(
+ samplingIntervalBatchCallStats);
+ }
+
+ /**
+ * Tests if we fall back to {@link AppSearchConfig#DEFAULT_SAMPLING_INTERVAL} if both default
+ * sampling
+ * interval and custom value are not set in DeviceConfig, and there is some other sampling
+ * interval
+ * set.
+ */
+ @Test
+ public void testFallbackToDefaultSamplingValue_useHardCodedDefault() {
+ final int samplingIntervalPutDocumentStats = -1;
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_PUT_DOCUMENT_STATS,
+ Integer.toString(samplingIntervalPutDocumentStats),
+ false);
+
+ AppSearchConfig appSearchConfig = AppSearchConfig.create(DIRECT_EXECUTOR);
+
+ assertThat(appSearchConfig.getCachedSamplingIntervalForPutDocumentStats()).isEqualTo(
+ samplingIntervalPutDocumentStats);
+ assertThat(appSearchConfig.getCachedSamplingIntervalForBatchCallStats()).isEqualTo(
+ AppSearchConfig.DEFAULT_SAMPLING_INTERVAL);
+ }
+
+ // Tests if we fall back to configured default sampling interval if custom value is not set in
+ // DeviceConfig.
+ @Test
+ public void testFallbackDefaultSamplingValue_useConfiguredDefault() {
+ final int samplingIntervalPutDocumentStats = -1;
+ final int samplingIntervalDefault = -2;
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_PUT_DOCUMENT_STATS,
+ Integer.toString(samplingIntervalPutDocumentStats),
+ false);
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ AppSearchConfig.KEY_SAMPLING_INTERVAL_DEFAULT,
+ Integer.toString(samplingIntervalDefault),
+ false);
+
+ AppSearchConfig appSearchConfig = AppSearchConfig.create(DIRECT_EXECUTOR);
+
+ assertThat(appSearchConfig.getCachedSamplingIntervalForPutDocumentStats()).isEqualTo(
+ samplingIntervalPutDocumentStats);
+ assertThat(appSearchConfig.getCachedSamplingIntervalForBatchCallStats()).isEqualTo(
+ samplingIntervalDefault);
+ }
+
+ // Tests that cached values should reflect latest values in DeviceConfig.
+ @Test
+ public void testFallbackDefaultSamplingValue_defaultValueChanged() {
+ int samplingIntervalPutDocumentStats = -1;
+ int samplingIntervalDefault = -2;
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_PUT_DOCUMENT_STATS,
+ Integer.toString(samplingIntervalPutDocumentStats),
+ false);
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ AppSearchConfig.KEY_SAMPLING_INTERVAL_DEFAULT,
+ Integer.toString(samplingIntervalDefault),
+ false);
+
+ AppSearchConfig appSearchConfig = AppSearchConfig.create(DIRECT_EXECUTOR);
+
+ // Sampling values changed.
+ samplingIntervalPutDocumentStats = -3;
+ samplingIntervalDefault = -4;
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_PUT_DOCUMENT_STATS,
+ Integer.toString(samplingIntervalPutDocumentStats),
+ false);
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ AppSearchConfig.KEY_SAMPLING_INTERVAL_DEFAULT,
+ Integer.toString(samplingIntervalDefault),
+ false);
+
+ assertThat(appSearchConfig.getCachedSamplingIntervalForPutDocumentStats()).isEqualTo(
+ samplingIntervalPutDocumentStats);
+ assertThat(appSearchConfig.getCachedSamplingIntervalForBatchCallStats()).isEqualTo(
+ samplingIntervalDefault);
+ }
+
+ // Tests default sampling interval won't affect custom sampling intervals if they are set.
+ @Test
+ public void testShouldNotFallBack_ifValueConfigured() {
+ int samplingIntervalDefault = -1;
+ int samplingIntervalBatchCallStats = -2;
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ AppSearchConfig.KEY_SAMPLING_INTERVAL_DEFAULT,
+ Integer.toString(samplingIntervalDefault),
+ false);
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_BATCH_CALL_STATS,
+ Integer.toString(samplingIntervalBatchCallStats),
+ false);
+
+ AppSearchConfig appSearchConfig = AppSearchConfig.create(DIRECT_EXECUTOR);
+
+ // Default sampling interval changed.
+ samplingIntervalDefault = -3;
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ AppSearchConfig.KEY_SAMPLING_INTERVAL_DEFAULT,
+ Integer.toString(samplingIntervalDefault),
+ false);
+
+ assertThat(appSearchConfig.getCachedSamplingIntervalForBatchCallStats()).isEqualTo(
+ samplingIntervalBatchCallStats);
+ }
+
+ @Test
+ public void testNotUsable_afterClose() {
+ AppSearchConfig appSearchConfig = AppSearchConfig.create(DIRECT_EXECUTOR);
+
+ appSearchConfig.close();
+
+ Assert.assertThrows("Trying to use a closed AppSearchConfig instance.",
+ IllegalStateException.class,
+ () -> appSearchConfig.getCachedMinTimeIntervalBetweenSamplesMillis());
+ Assert.assertThrows("Trying to use a closed AppSearchConfig instance.",
+ IllegalStateException.class,
+ () -> appSearchConfig.getCachedSamplingIntervalDefault());
+ Assert.assertThrows("Trying to use a closed AppSearchConfig instance.",
+ IllegalStateException.class,
+ () -> appSearchConfig.getCachedSamplingIntervalForBatchCallStats());
+ Assert.assertThrows("Trying to use a closed AppSearchConfig instance.",
+ IllegalStateException.class,
+ () -> appSearchConfig.getCachedSamplingIntervalForPutDocumentStats());
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/appop/AppOpsActiveWatcherTest.java b/services/tests/servicestests/src/com/android/server/appop/AppOpsActiveWatcherTest.java
index 98bc0673f79c..a2aaccc679dc 100644
--- a/services/tests/servicestests/src/com/android/server/appop/AppOpsActiveWatcherTest.java
+++ b/services/tests/servicestests/src/com/android/server/appop/AppOpsActiveWatcherTest.java
@@ -20,6 +20,8 @@ import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.reset;
@@ -66,7 +68,8 @@ public class AppOpsActiveWatcherTest {
// Verify that we got called for the op being active
verify(listener, timeout(NOTIFICATION_TIMEOUT_MILLIS)
.times(1)).onOpActiveChanged(eq(AppOpsManager.OPSTR_CAMERA),
- eq(Process.myUid()), eq(getContext().getPackageName()), eq(true));
+ eq(Process.myUid()), eq(getContext().getPackageName()),
+ isNull(), eq(true), anyInt(), anyInt());
// This should be the only callback we got
verifyNoMoreInteractions(listener);
@@ -84,7 +87,8 @@ public class AppOpsActiveWatcherTest {
// Verify that we got called for the op being active
verify(listener, timeout(NOTIFICATION_TIMEOUT_MILLIS)
.times(1)).onOpActiveChanged(eq(AppOpsManager.OPSTR_CAMERA),
- eq(Process.myUid()), eq(getContext().getPackageName()), eq(false));
+ eq(Process.myUid()), eq(getContext().getPackageName()), isNull(),
+ eq(false), anyInt(), anyInt());
// Verify that the op is not active
assertThat(appOpsManager.isOperationActive(AppOpsManager.OP_CAMERA,
@@ -121,7 +125,8 @@ public class AppOpsActiveWatcherTest {
// We should get the callback again (and since we reset the listener, we therefore expect 1)
verify(listener, timeout(NOTIFICATION_TIMEOUT_MILLIS)
.times(1)).onOpActiveChanged(eq(AppOpsManager.OPSTR_CAMERA),
- eq(Process.myUid()), eq(getContext().getPackageName()), eq(true));
+ eq(Process.myUid()), eq(getContext().getPackageName()), isNull(),
+ eq(true), anyInt(), anyInt());
// Finish up
appOpsManager.finishOp(AppOpsManager.OP_CAMERA);
diff --git a/services/tests/servicestests/src/com/android/server/appsearch/stats/PlatformLoggerTest.java b/services/tests/servicestests/src/com/android/server/appsearch/stats/PlatformLoggerTest.java
index 747dd1df1869..734f05a8de91 100644
--- a/services/tests/servicestests/src/com/android/server/appsearch/stats/PlatformLoggerTest.java
+++ b/services/tests/servicestests/src/com/android/server/appsearch/stats/PlatformLoggerTest.java
@@ -46,7 +46,7 @@ import java.security.NoSuchAlgorithmException;
public class PlatformLoggerTest {
private static final int TEST_MIN_TIME_INTERVAL_BETWEEN_SAMPLES_MILLIS = 100;
- private static final int TEST_DEFAULT_SAMPLING_RATIO = 10;
+ private static final int TEST_DEFAULT_SAMPLING_INTERVAL = 10;
private static final String TEST_PACKAGE_NAME = "packageName";
private MockPackageManager mMockPackageManager = new MockPackageManager();
private Context mContext;
@@ -72,63 +72,63 @@ public class PlatformLoggerTest {
}
@Test
- public void testCreateExtraStatsLocked_nullSamplingRatioMap_returnsDefaultSamplingRatio() {
+ public void testCreateExtraStatsLocked_nullSamplingIntervalMap_returnsDefault() {
PlatformLogger logger = new PlatformLogger(
ApplicationProvider.getApplicationContext(),
UserHandle.of(UserHandle.USER_NULL),
new PlatformLogger.Config(
TEST_MIN_TIME_INTERVAL_BETWEEN_SAMPLES_MILLIS,
- TEST_DEFAULT_SAMPLING_RATIO,
- /*samplingRatios=*/ new SparseIntArray()));
+ TEST_DEFAULT_SAMPLING_INTERVAL,
+ /*samplingIntervals=*/ new SparseIntArray()));
- // Make sure default sampling ratio is used if samplingMap is not provided.
+ // Make sure default sampling interval is used if samplingMap is not provided.
assertThat(logger.createExtraStatsLocked(TEST_PACKAGE_NAME,
- CallStats.CALL_TYPE_UNKNOWN).mSamplingRatio).isEqualTo(
- TEST_DEFAULT_SAMPLING_RATIO);
+ CallStats.CALL_TYPE_UNKNOWN).mSamplingInterval).isEqualTo(
+ TEST_DEFAULT_SAMPLING_INTERVAL);
assertThat(logger.createExtraStatsLocked(TEST_PACKAGE_NAME,
- CallStats.CALL_TYPE_INITIALIZE).mSamplingRatio).isEqualTo(
- TEST_DEFAULT_SAMPLING_RATIO);
+ CallStats.CALL_TYPE_INITIALIZE).mSamplingInterval).isEqualTo(
+ TEST_DEFAULT_SAMPLING_INTERVAL);
assertThat(logger.createExtraStatsLocked(TEST_PACKAGE_NAME,
- CallStats.CALL_TYPE_SEARCH).mSamplingRatio).isEqualTo(
- TEST_DEFAULT_SAMPLING_RATIO);
+ CallStats.CALL_TYPE_SEARCH).mSamplingInterval).isEqualTo(
+ TEST_DEFAULT_SAMPLING_INTERVAL);
assertThat(logger.createExtraStatsLocked(TEST_PACKAGE_NAME,
- CallStats.CALL_TYPE_FLUSH).mSamplingRatio).isEqualTo(
- TEST_DEFAULT_SAMPLING_RATIO);
+ CallStats.CALL_TYPE_FLUSH).mSamplingInterval).isEqualTo(
+ TEST_DEFAULT_SAMPLING_INTERVAL);
}
@Test
- public void testCreateExtraStatsLocked_with_samplingRatioMap_returnsConfiguredSamplingRatio() {
- int putDocumentSamplingRatio = 1;
- int querySamplingRatio = 2;
- final SparseIntArray samplingRatios = new SparseIntArray();
- samplingRatios.put(CallStats.CALL_TYPE_PUT_DOCUMENT, putDocumentSamplingRatio);
- samplingRatios.put(CallStats.CALL_TYPE_SEARCH, querySamplingRatio);
+ public void testCreateExtraStatsLocked_with_samplingIntervalMap_returnsConfigured() {
+ int putDocumentSamplingInterval = 1;
+ int querySamplingInterval = 2;
+ final SparseIntArray samplingIntervals = new SparseIntArray();
+ samplingIntervals.put(CallStats.CALL_TYPE_PUT_DOCUMENT, putDocumentSamplingInterval);
+ samplingIntervals.put(CallStats.CALL_TYPE_SEARCH, querySamplingInterval);
PlatformLogger logger = new PlatformLogger(
ApplicationProvider.getApplicationContext(),
UserHandle.of(UserHandle.USER_NULL),
new PlatformLogger.Config(
TEST_MIN_TIME_INTERVAL_BETWEEN_SAMPLES_MILLIS,
- TEST_DEFAULT_SAMPLING_RATIO,
- samplingRatios));
+ TEST_DEFAULT_SAMPLING_INTERVAL,
+ samplingIntervals));
- // The default sampling ratio should be used if no sampling ratio is
+ // The default sampling interval should be used if no sampling interval is
// provided for certain call type.
assertThat(logger.createExtraStatsLocked(TEST_PACKAGE_NAME,
- CallStats.CALL_TYPE_INITIALIZE).mSamplingRatio).isEqualTo(
- TEST_DEFAULT_SAMPLING_RATIO);
+ CallStats.CALL_TYPE_INITIALIZE).mSamplingInterval).isEqualTo(
+ TEST_DEFAULT_SAMPLING_INTERVAL);
assertThat(logger.createExtraStatsLocked(TEST_PACKAGE_NAME,
- CallStats.CALL_TYPE_FLUSH).mSamplingRatio).isEqualTo(
- TEST_DEFAULT_SAMPLING_RATIO);
+ CallStats.CALL_TYPE_FLUSH).mSamplingInterval).isEqualTo(
+ TEST_DEFAULT_SAMPLING_INTERVAL);
- // The configured sampling ratio is used if sampling ratio is available
+ // The configured sampling interval is used if sampling interval is available
// for certain call type.
assertThat(logger.createExtraStatsLocked(TEST_PACKAGE_NAME,
- CallStats.CALL_TYPE_PUT_DOCUMENT).mSamplingRatio).isEqualTo(
- putDocumentSamplingRatio);
+ CallStats.CALL_TYPE_PUT_DOCUMENT).mSamplingInterval).isEqualTo(
+ putDocumentSamplingInterval);
assertThat(logger.createExtraStatsLocked(TEST_PACKAGE_NAME,
- CallStats.CALL_TYPE_SEARCH).mSamplingRatio).isEqualTo(
- querySamplingRatio);
+ CallStats.CALL_TYPE_SEARCH).mSamplingInterval).isEqualTo(
+ querySamplingInterval);
}
@Test
@@ -202,16 +202,16 @@ public class PlatformLoggerTest {
}
@Test
- public void testShouldLogForTypeLocked_trueWhenSampleRatioIsOne() {
- final int samplingRatio = 1;
+ public void testShouldLogForTypeLocked_trueWhenSampleIntervalIsOne() {
+ final int samplingInterval = 1;
final String testPackageName = "packageName";
PlatformLogger logger = new PlatformLogger(
ApplicationProvider.getApplicationContext(),
UserHandle.of(UserHandle.USER_NULL),
new PlatformLogger.Config(
TEST_MIN_TIME_INTERVAL_BETWEEN_SAMPLES_MILLIS,
- samplingRatio,
- /*samplingRatios=*/ new SparseIntArray()));
+ samplingInterval,
+ /*samplingIntervals=*/ new SparseIntArray()));
// Sample should always be logged for the first time if sampling is disabled(value is one).
assertThat(logger.shouldLogForTypeLocked(CallStats.CALL_TYPE_PUT_DOCUMENT)).isTrue();
@@ -220,18 +220,18 @@ public class PlatformLoggerTest {
}
@Test
- public void testShouldLogForTypeLocked_falseWhenSampleRatioIsNegative() {
- final int samplingRatio = -1;
+ public void testShouldLogForTypeLocked_falseWhenSampleIntervalIsNegative() {
+ final int samplingInterval = -1;
final String testPackageName = "packageName";
PlatformLogger logger = new PlatformLogger(
ApplicationProvider.getApplicationContext(),
UserHandle.of(UserHandle.USER_NULL),
new PlatformLogger.Config(
TEST_MIN_TIME_INTERVAL_BETWEEN_SAMPLES_MILLIS,
- samplingRatio,
- /*samplingRatios=*/ new SparseIntArray()));
+ samplingInterval,
+ /*samplingIntervals=*/ new SparseIntArray()));
- // Makes sure sample will be excluded due to sampling if sample ratio is negative.
+ // Makes sure sample will be excluded due to sampling if sample interval is negative.
assertThat(logger.shouldLogForTypeLocked(CallStats.CALL_TYPE_PUT_DOCUMENT)).isFalse();
// Skipped count should be 0 since it doesn't pass the sampling.
assertThat(logger.createExtraStatsLocked(testPackageName,
@@ -241,7 +241,7 @@ public class PlatformLoggerTest {
@Test
public void testShouldLogForTypeLocked_falseWhenWithinCoolOffInterval() {
// Next sample won't be excluded due to sampling.
- final int samplingRatio = 1;
+ final int samplingInterval = 1;
// Next sample would guaranteed to be too close.
final int minTimeIntervalBetweenSamplesMillis = Integer.MAX_VALUE;
final String testPackageName = "packageName";
@@ -250,8 +250,8 @@ public class PlatformLoggerTest {
UserHandle.of(UserHandle.USER_NULL),
new PlatformLogger.Config(
minTimeIntervalBetweenSamplesMillis,
- samplingRatio,
- /*samplingRatios=*/ new SparseIntArray()));
+ samplingInterval,
+ /*samplingIntervals=*/ new SparseIntArray()));
logger.setLastPushTimeMillisLocked(SystemClock.elapsedRealtime());
// Makes sure sample will be excluded due to rate limiting if samples are too close.
@@ -263,7 +263,7 @@ public class PlatformLoggerTest {
@Test
public void testShouldLogForTypeLocked_trueWhenOutsideOfCoolOffInterval() {
// Next sample won't be excluded due to sampling.
- final int samplingRatio = 1;
+ final int samplingInterval = 1;
// Next sample would guaranteed to be included.
final int minTimeIntervalBetweenSamplesMillis = 0;
final String testPackageName = "packageName";
@@ -272,8 +272,8 @@ public class PlatformLoggerTest {
UserHandle.of(UserHandle.USER_NULL),
new PlatformLogger.Config(
minTimeIntervalBetweenSamplesMillis,
- samplingRatio,
- /*samplingRatios=*/ new SparseIntArray()));
+ samplingInterval,
+ /*samplingIntervals=*/ new SparseIntArray()));
logger.setLastPushTimeMillisLocked(SystemClock.elapsedRealtime());
// Makes sure sample will be logged if it is not too close to previous sample.
@@ -292,8 +292,8 @@ public class PlatformLoggerTest {
mContext.getUser(),
new PlatformLogger.Config(
TEST_MIN_TIME_INTERVAL_BETWEEN_SAMPLES_MILLIS,
- TEST_DEFAULT_SAMPLING_RATIO,
- /*samplingRatios=*/ new SparseIntArray()));
+ TEST_DEFAULT_SAMPLING_INTERVAL,
+ /*samplingIntervals=*/ new SparseIntArray()));
mMockPackageManager.mockGetPackageUidAsUser(testPackageName, mContext.getUserId(), testUid);
//
diff --git a/services/tests/servicestests/src/com/android/server/pm/CrossProfileAppsServiceImplTest.java b/services/tests/servicestests/src/com/android/server/pm/CrossProfileAppsServiceImplTest.java
index 2162c0b20eac..e811c1f315fe 100644
--- a/services/tests/servicestests/src/com/android/server/pm/CrossProfileAppsServiceImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/CrossProfileAppsServiceImplTest.java
@@ -5,22 +5,29 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+
import static org.testng.Assert.assertThrows;
+import android.Manifest;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
import android.app.AppOpsManager;
import android.app.IApplicationThread;
import android.app.admin.DevicePolicyManagerInternal;
+import android.content.AttributionSourceState;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.PermissionChecker;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.CrossProfileAppsInternal;
@@ -34,6 +41,7 @@ import android.os.Bundle;
import android.os.IBinder;
import android.os.UserHandle;
import android.os.UserManager;
+import android.permission.PermissionCheckerManager;
import android.permission.PermissionManager;
import android.platform.test.annotations.Presubmit;
import android.util.SparseArray;
@@ -411,6 +419,18 @@ public class CrossProfileAppsServiceImplTest {
}
mActivityInfo.exported = false;
+
+ // There's a bug in static mocking if the APK is large - so here is the next best thing...
+ doReturn(Context.PERMISSION_CHECKER_SERVICE).when(mContext)
+ .getSystemServiceName(PermissionCheckerManager.class);
+ PermissionCheckerManager permissionCheckerManager = mock(PermissionCheckerManager.class);
+ doReturn(PermissionChecker.PERMISSION_HARD_DENIED).when(permissionCheckerManager)
+ .checkPermission(eq(Manifest.permission.INTERACT_ACROSS_PROFILES), any(
+ AttributionSourceState.class), anyString(), anyBoolean(), anyBoolean(),
+ anyBoolean(), anyInt());
+ doReturn(permissionCheckerManager).when(mContext).getSystemService(
+ Context.PERMISSION_CHECKER_SERVICE);
+
assertThrows(
SecurityException.class,
() ->
diff --git a/services/tests/servicestests/src/com/android/server/vibrator/DeviceVibrationEffectAdapterTest.java b/services/tests/servicestests/src/com/android/server/vibrator/DeviceVibrationEffectAdapterTest.java
index f65969833521..00b05d4ad10c 100644
--- a/services/tests/servicestests/src/com/android/server/vibrator/DeviceVibrationEffectAdapterTest.java
+++ b/services/tests/servicestests/src/com/android/server/vibrator/DeviceVibrationEffectAdapterTest.java
@@ -77,6 +77,38 @@ public class DeviceVibrationEffectAdapterTest {
}
@Test
+ public void testStepAndRampSegments_withoutPwleCapability_convertsRampsToSteps() {
+ VibrationEffect.Composed effect = new VibrationEffect.Composed(Arrays.asList(
+ new StepSegment(/* amplitude= */ 0, /* frequency= */ 1, /* duration= */ 10),
+ new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ 0, /* duration= */ 100),
+ new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 0.2f,
+ /* startFrequency= */ -4, /* endFrequency= */ 2, /* duration= */ 10),
+ new RampSegment(/* startAmplitude= */ 0.8f, /* endAmplitude= */ 0.2f,
+ /* startFrequency= */ 0, /* endFrequency= */ 0, /* duration= */ 11),
+ new RampSegment(/* startAmplitude= */ 0.65f, /* endAmplitude= */ 0.65f,
+ /* startFrequency= */ 0, /* endFrequency= */ 1, /* duration= */ 200)),
+ /* repeatIndex= */ 3);
+
+ VibrationEffect.Composed expected = new VibrationEffect.Composed(Arrays.asList(
+ new StepSegment(/* amplitude= */ 0, Float.NaN, /* duration= */ 10),
+ new StepSegment(/* amplitude= */ 0.5f, Float.NaN, /* duration= */ 100),
+ // 10ms ramp becomes 2 steps
+ new StepSegment(/* amplitude= */ 1, Float.NaN, /* duration= */ 5),
+ new StepSegment(/* amplitude= */ 0.2f, Float.NaN, /* duration= */ 5),
+ // 11ms ramp becomes 3 steps
+ new StepSegment(/* amplitude= */ 0.8f, Float.NaN, /* duration= */ 5),
+ new StepSegment(/* amplitude= */ 0.6f, Float.NaN, /* duration= */ 5),
+ new StepSegment(/* amplitude= */ 0.2f, Float.NaN, /* duration= */ 1),
+ // 200ms ramp with same amplitude becomes a single step
+ new StepSegment(/* amplitude= */ 0.65f, Float.NaN, /* duration= */ 200)),
+ // Repeat index fixed after intermediate steps added
+ /* repeatIndex= */ 4);
+
+ VibratorInfo info = createVibratorInfo(EMPTY_FREQUENCY_MAPPING);
+ assertEquals(expected, mAdapter.apply(effect, info));
+ }
+
+ @Test
public void testStepAndRampSegments_withPwleCapability_convertsStepsToRamps() {
VibrationEffect.Composed effect = new VibrationEffect.Composed(Arrays.asList(
new StepSegment(/* amplitude= */ 0, /* frequency= */ 1, /* duration= */ 10),
@@ -131,7 +163,7 @@ public class DeviceVibrationEffectAdapterTest {
}
@Test
- public void testStepAndRampSegments_emptyMapping_returnsSameAmplitudesAndFrequencyZero() {
+ public void testStepAndRampSegments_withEmptyFreqMapping_returnsSameAmplitudesAndZeroFreq() {
VibrationEffect.Composed effect = new VibrationEffect.Composed(Arrays.asList(
new StepSegment(/* amplitude= */ 0, /* frequency= */ 1, /* duration= */ 10),
new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ 0, /* duration= */ 100),
@@ -142,8 +174,11 @@ public class DeviceVibrationEffectAdapterTest {
/* repeatIndex= */ 2);
VibrationEffect.Composed expected = new VibrationEffect.Composed(Arrays.asList(
- new StepSegment(/* amplitude= */ 0, /* frequency= */ Float.NaN, /* duration= */ 10),
- new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ Float.NaN,
+ new RampSegment(/* startAmplitude= */ 0, /* endAmplitude= */ 0,
+ /* startFrequency= */ Float.NaN, /* endFrequency= */ Float.NaN,
+ /* duration= */ 10),
+ new RampSegment(/* startAmplitude= */ 0.5f, /* endAmplitude= */ 0.5f,
+ /* startFrequency= */ Float.NaN, /* endFrequency= */ Float.NaN,
/* duration= */ 100),
new RampSegment(/* startAmplitude= */ 0.8f, /* endAmplitude= */ 1,
/* startFrequency= */ Float.NaN, /* endFrequency= */ Float.NaN,
@@ -153,11 +188,13 @@ public class DeviceVibrationEffectAdapterTest {
/* duration= */ 20)),
/* repeatIndex= */ 2);
- assertEquals(expected, mAdapter.apply(effect, createVibratorInfo(EMPTY_FREQUENCY_MAPPING)));
+ VibratorInfo info = createVibratorInfo(EMPTY_FREQUENCY_MAPPING,
+ IVibrator.CAP_COMPOSE_PWLE_EFFECTS);
+ assertEquals(expected, mAdapter.apply(effect, info));
}
@Test
- public void testStepAndRampSegments_nonEmptyMapping_returnsClippedValues() {
+ public void testStepAndRampSegments_withValidFreqMapping_returnsClippedValues() {
VibrationEffect.Composed effect = new VibrationEffect.Composed(Arrays.asList(
new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ 0, /* duration= */ 10),
new StepSegment(/* amplitude= */ 1, /* frequency= */ -1, /* duration= */ 100),
@@ -168,15 +205,21 @@ public class DeviceVibrationEffectAdapterTest {
/* repeatIndex= */ 2);
VibrationEffect.Composed expected = new VibrationEffect.Composed(Arrays.asList(
- new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ 150, /* duration= */ 10),
- new StepSegment(/* amplitude= */ 0.8f, /* frequency= */ 125, /* duration= */ 100),
+ new RampSegment(/* startAmplitude= */ 0.5f, /* endAmplitude= */ 0.5f,
+ /* startFrequency= */ 150, /* endFrequency= */ 150,
+ /* duration= */ 10),
+ new RampSegment(/* startAmplitude= */ 0.8f, /* endAmplitude= */ 0.8f,
+ /* startFrequency= */ 125, /* endFrequency= */ 125,
+ /* duration= */ 100),
new RampSegment(/* startAmplitude= */ 0.1f, /* endAmplitude= */ 0.8f,
/* startFrequency= */ 50, /* endFrequency= */ 200, /* duration= */ 50),
new RampSegment(/* startAmplitude= */ 0.8f, /* endAmplitude= */ 0.1f,
/* startFrequency= */ 200, /* endFrequency= */ 50, /* duration= */ 20)),
/* repeatIndex= */ 2);
- assertEquals(expected, mAdapter.apply(effect, createVibratorInfo(TEST_FREQUENCY_MAPPING)));
+ VibratorInfo info = createVibratorInfo(TEST_FREQUENCY_MAPPING,
+ IVibrator.CAP_COMPOSE_PWLE_EFFECTS);
+ assertEquals(expected, mAdapter.apply(effect, info));
}
private static VibratorInfo createVibratorInfo(VibratorInfo.FrequencyMapping frequencyMapping,
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index aed3f52bd563..821683043804 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -26,6 +26,7 @@ import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_ALWAYS;
import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_DEFAULT;
import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_IF_ALLOWLISTED;
import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_NEVER;
+import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
@@ -546,7 +547,7 @@ public class ActivityRecordTests extends WindowTestsBase {
}
@Test
- public void ignoreRequestedOrientationInSplitWindows() {
+ public void ignoreRequestedOrientationForResizableInSplitWindows() {
final ActivityRecord activity = createActivityWith2LevelTask();
final Task task = activity.getTask();
final Task rootTask = activity.getRootTask();
@@ -578,13 +579,45 @@ public class ActivityRecordTests extends WindowTestsBase {
}
task.setBounds(bounds);
+ final int activityCurOrientation = activity.getConfiguration().orientation;
+
// Requests orientation that's different from its bounds.
- activity.setRequestedOrientation(
- isScreenPortrait ? SCREEN_ORIENTATION_PORTRAIT : SCREEN_ORIENTATION_LANDSCAPE);
+ activity.setRequestedOrientation(activityCurOrientation == ORIENTATION_LANDSCAPE
+ ? SCREEN_ORIENTATION_PORTRAIT : SCREEN_ORIENTATION_LANDSCAPE);
- // Asserts it has orientation derived requested orientation (fixed orientation letterbox).
- assertEquals(isScreenPortrait ? ORIENTATION_PORTRAIT : ORIENTATION_LANDSCAPE,
- activity.getConfiguration().orientation);
+ // Asserts fixed orientation request is ignored, and the orientation is not changed
+ // (fill Task).
+ assertEquals(activityCurOrientation, activity.getConfiguration().orientation);
+ assertFalse(activity.isLetterboxedForFixedOrientationAndAspectRatio());
+ }
+
+ @Test
+ public void respectRequestedOrientationForNonResizableInSplitWindows() {
+ final Task task = new TaskBuilder(mSupervisor)
+ .setCreateParentTask(true).setCreateActivity(true).build();
+ final Task rootTask = task.getRootTask();
+ final ActivityRecord activity = new ActivityBuilder(mAtm)
+ .setParentTask(task)
+ .setOnTop(true)
+ .setResizeMode(RESIZE_MODE_UNRESIZEABLE)
+ .setScreenOrientation(SCREEN_ORIENTATION_PORTRAIT)
+ .build();
+
+ // Task in landscape.
+ rootTask.setWindowingMode(WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
+ task.setBounds(0, 0, 1000, 500);
+ assertEquals(ORIENTATION_LANDSCAPE, task.getConfiguration().orientation);
+
+ // Asserts fixed orientation request is respected, and the orientation is not changed.
+ assertEquals(ORIENTATION_PORTRAIT, activity.getConfiguration().orientation);
+
+ // Clear size compat.
+ activity.clearSizeCompatMode();
+ activity.ensureActivityConfiguration(0 /* globalChanges */, false /* preserveWindow */);
+ activity.mDisplayContent.sendNewConfiguration();
+
+ // Relaunching the app should still respect the orientation request.
+ assertEquals(ORIENTATION_PORTRAIT, activity.getConfiguration().orientation);
assertTrue(activity.isLetterboxedForFixedOrientationAndAspectRatio());
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
index 152a575c847d..178fabcc6a47 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -691,39 +691,6 @@ public class WindowStateTests extends WindowTestsBase {
}
@Test
- public void testGetTransformationMatrix() {
- final int PARENT_WINDOW_OFFSET = 1;
- final int DISPLAY_IN_PARENT_WINDOW_OFFSET = 2;
- final int WINDOW_OFFSET = 3;
- final float OFFSET_SUM =
- PARENT_WINDOW_OFFSET + DISPLAY_IN_PARENT_WINDOW_OFFSET + WINDOW_OFFSET;
-
- final WindowState win0 = createWindow(null, TYPE_APPLICATION, "win0");
-
- final DisplayContent dc = createNewDisplay();
- win0.getFrame().offsetTo(PARENT_WINDOW_OFFSET, 0);
- dc.reparentDisplayContent(win0, win0.getSurfaceControl());
- dc.updateLocation(win0, DISPLAY_IN_PARENT_WINDOW_OFFSET, 0);
-
- final float[] values = new float[9];
- final Matrix matrix = new Matrix();
- final SurfaceControl.Transaction t = spy(StubTransaction.class);
- final WindowState win1 = createWindow(null, TYPE_APPLICATION, dc, "win1");
- win1.mHasSurface = true;
- win1.mSurfaceControl = mock(SurfaceControl.class);
- win1.mAttrs.surfaceInsets.set(1, 2, 3, 4);
- win1.getFrame().offsetTo(WINDOW_OFFSET, 0);
- // Simulate layout
- win1.mRelayoutCalled = true;
- win1.updateSurfacePosition(t);
- win1.getTransformationMatrix(values, matrix);
-
- matrix.getValues(values);
- assertEquals(OFFSET_SUM, values[Matrix.MTRANS_X], 0f);
- assertEquals(0f, values[Matrix.MTRANS_Y], 0f);
- }
-
- @Test
public void testCantReceiveTouchDuringRecentsAnimation() {
final WindowState win0 = createWindow(null, TYPE_APPLICATION, "win0");
diff --git a/tools/aapt/SdkConstants.h b/tools/aapt/SdkConstants.h
index 04fbbe1f1069..955581cf8655 100644
--- a/tools/aapt/SdkConstants.h
+++ b/tools/aapt/SdkConstants.h
@@ -46,6 +46,7 @@ enum {
SDK_P = 28,
SDK_Q = 29,
SDK_R = 30,
+ SDK_S = 31,
};
#endif // H_AAPT_SDK_CONSTANTS
diff --git a/tools/aapt2/SdkConstants.cpp b/tools/aapt2/SdkConstants.cpp
index e8873bf2d81b..96f6512fe7f5 100644
--- a/tools/aapt2/SdkConstants.cpp
+++ b/tools/aapt2/SdkConstants.cpp
@@ -58,7 +58,8 @@ static const std::vector<std::pair<uint16_t, ApiVersion>> sAttrIdMap = {
{0x056d, SDK_O_MR1},
{0x0586, SDK_P},
{0x0606, SDK_Q},
- {0x0617, SDK_R},
+ {0x0616, SDK_R},
+ {0x064b, SDK_S},
};
static bool less_entry_id(const std::pair<uint16_t, ApiVersion>& p, uint16_t entryId) {
diff --git a/tools/aapt2/SdkConstants.h b/tools/aapt2/SdkConstants.h
index aa9aa12d2cee..6bb6ddb13bdb 100644
--- a/tools/aapt2/SdkConstants.h
+++ b/tools/aapt2/SdkConstants.h
@@ -56,6 +56,7 @@ enum : ApiVersion {
SDK_P = 28,
SDK_Q = 29,
SDK_R = 30,
+ SDK_S = 31,
};
ApiVersion FindAttributeSdkLevel(const ResourceId& id);
diff --git a/tools/finalize_res/finalize_res.py b/tools/finalize_res/finalize_res.py
new file mode 100755
index 000000000000..aaf01875024e
--- /dev/null
+++ b/tools/finalize_res/finalize_res.py
@@ -0,0 +1,41 @@
+#!/usr/bin/env python3
+#-*- coding: utf-8 -*-
+
+# Copyright (C) 2021 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.
+
+"""
+Finalize resource values in <staging-public-group> tags
+
+Usage: finalize_res.py core/res/res/values/public.xml public_finalized.xml
+"""
+
+import re, sys, codecs
+
+def finalize_item(raw):
+ global _type, _id
+ _id += 1
+ return '<public type="%s" name="%s" id="%s" />' % (_type, raw.group(1), '0x{0:0{1}x}'.format(_id-1,8))
+
+def finalize_group(raw):
+ global _type, _id
+ _type = raw.group(1)
+ _id = int(raw.group(2), 16)
+ return re.sub(r'<public name="(.+?)" */>', finalize_item, raw.group(3))
+
+with open(sys.argv[1]) as f:
+ raw = f.read()
+ raw = re.sub(r'<staging-public-group type="(.+?)" first-id="(.+?)">(.+?)</staging-public-group>', finalize_group, raw, flags=re.DOTALL)
+ with open(sys.argv[2], "w") as f:
+ f.write(raw)