summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.bp7
-rw-r--r--apct-tests/perftests/core/src/android/os/PackageManagerPerfTest.java111
-rw-r--r--apct-tests/perftests/packagemanager/Android.bp21
-rw-r--r--apct-tests/perftests/packagemanager/AndroidManifest.xml89
-rw-r--r--apct-tests/perftests/packagemanager/AndroidTest.xml88
-rw-r--r--apct-tests/perftests/packagemanager/apps/query-all/Android.bp314
-rw-r--r--apct-tests/perftests/packagemanager/apps/query-all/AndroidManifest.xml81
-rw-r--r--apct-tests/perftests/packagemanager/src/android/os/PackageManagerPerfTest.java189
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java48
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java75
-rw-r--r--apex/permission/testing/Android.bp2
-rw-r--r--apex/sdkextensions/framework/java/android/os/ext/test/Test.java (renamed from packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableViewController.java)48
-rw-r--r--apex/statsd/aidl/Android.bp28
-rw-r--r--apex/statsd/aidl/android/os/IPendingIntentRef.aidl6
-rw-r--r--apex/statsd/aidl/android/os/StatsDimensionsValueParcel.aidl21
-rw-r--r--apex/statsd/framework/java/android/os/StatsDimensionsValue.java41
-rw-r--r--apex/statsd/service/java/com/android/server/stats/StatsCompanion.java5
-rw-r--r--apex/statsd/testing/Android.bp2
-rw-r--r--api/current.txt33
-rw-r--r--api/module-lib-current.txt8
-rwxr-xr-xapi/system-current.txt70
-rw-r--r--api/test-current.txt2
-rw-r--r--cmds/statsd/Android.bp8
-rw-r--r--cmds/statsd/src/HashableDimensionKey.cpp80
-rw-r--r--cmds/statsd/src/HashableDimensionKey.h5
-rw-r--r--cmds/statsd/src/subscriber/SubscriberReporter.cpp57
-rw-r--r--cmds/statsd/src/subscriber/SubscriberReporter.h3
-rw-r--r--cmds/statsd/tests/FieldValue_test.cpp55
-rw-r--r--core/java/android/app/ActivityManager.java5
-rw-r--r--core/java/android/app/ApplicationExitInfo.java38
-rw-r--r--core/java/android/app/INotificationManager.aidl1
-rw-r--r--core/java/android/app/ITaskOrganizerController.aidl3
-rw-r--r--core/java/android/app/NotificationHistory.java20
-rw-r--r--core/java/android/content/ContentResolver.java23
-rw-r--r--core/java/android/content/pm/ILauncherApps.aidl5
-rw-r--r--core/java/android/content/pm/LauncherApps.java56
-rw-r--r--core/java/android/content/pm/PackageManager.java1
-rw-r--r--core/java/android/content/pm/ShortcutServiceInternal.java7
-rw-r--r--core/java/android/hardware/soundtrigger/SoundTriggerModule.java23
-rw-r--r--core/java/android/os/SharedMemory.java15
-rw-r--r--core/java/android/os/Trace.java2
-rw-r--r--core/java/android/os/UserManager.java8
-rw-r--r--core/java/android/os/incremental/IIncrementalService.aidl5
-rw-r--r--core/java/android/os/incremental/IncrementalManager.java41
-rw-r--r--core/java/android/os/incremental/IncrementalStorage.java20
-rw-r--r--core/java/android/service/contentcapture/ContentCaptureService.java6
-rw-r--r--core/java/android/service/quicksettings/TileService.java14
-rw-r--r--core/java/android/telephony/PhoneStateListener.java12
-rw-r--r--core/java/android/view/View.java20
-rw-r--r--core/java/android/view/WindowContainerTransaction.java122
-rw-r--r--core/java/android/view/contentcapture/ContentCaptureSession.java7
-rw-r--r--core/java/android/view/inputmethod/InputMethodManager.java2
-rw-r--r--core/java/android/webkit/WebResourceRequest.java6
-rw-r--r--core/java/android/widget/Toast.java13
-rw-r--r--core/java/com/android/internal/app/ResolverActivity.java1
-rw-r--r--core/java/com/android/internal/content/NativeLibraryHelper.java156
-rw-r--r--core/java/com/android/server/SystemConfig.java6
-rw-r--r--core/jni/Android.bp2
-rw-r--r--core/jni/android/graphics/FontFamily.cpp4
-rw-r--r--core/jni/android/graphics/GraphicsStatsService.cpp195
-rw-r--r--core/jni/android/graphics/fonts/Font.cpp4
-rw-r--r--core/proto/android/app/appexitinfo.proto4
-rw-r--r--core/proto/android/app/settings_enums.proto6
-rw-r--r--core/proto/android/server/jobscheduler.proto8
-rw-r--r--core/proto/android/service/OWNERS1
-rw-r--r--core/proto/android/service/sensor_service.proto4
-rw-r--r--core/res/AndroidManifest.xml2
-rw-r--r--core/res/res/drawable-nodpi/platlogo.xml71
-rw-r--r--core/res/res/drawable-nodpi/stat_sys_adb.xml48
-rw-r--r--core/res/res/drawable/tab_indicator_resolver.xml35
-rw-r--r--core/res/res/layout/tab_indicator_resolver.xml38
-rw-r--r--core/res/res/values-night/colors.xml2
-rw-r--r--core/res/res/values/themes_device_defaults.xml9
-rw-r--r--core/tests/coretests/AndroidManifest.xml6
-rw-r--r--core/tests/coretests/src/android/app/NotificationHistoryTest.java34
-rw-r--r--core/tests/coretests/src/android/content/ContentResolverTest.java9
-rw-r--r--core/tests/coretests/src/android/content/SlowProvider.java65
-rw-r--r--graphics/java/android/graphics/GraphicsStatsService.java (renamed from services/core/java/com/android/server/GraphicsStatsService.java)118
-rw-r--r--libs/hwui/Android.bp3
-rw-r--r--libs/hwui/RenderNode.cpp2
-rw-r--r--libs/hwui/RenderNode.h3
-rw-r--r--libs/hwui/pipeline/skia/ReorderBarrierDrawables.h2
-rw-r--r--libs/hwui/renderthread/RenderThread.cpp3
-rw-r--r--libs/hwui/renderthread/VulkanManager.cpp2
-rw-r--r--libs/hwui/service/GraphicsStatsService.cpp143
-rw-r--r--libs/hwui/service/GraphicsStatsService.h8
-rw-r--r--libs/hwui/tests/unit/FatVectorTests.cpp2
-rw-r--r--libs/hwui/utils/FatVector.h105
-rw-r--r--libs/input/PointerController.cpp33
-rw-r--r--libs/input/tests/PointerController_test.cpp54
-rw-r--r--libs/services/Android.bp1
-rw-r--r--libs/services/include/android/os/StatsDimensionsValue.h70
-rw-r--r--libs/services/src/os/StatsDimensionsValue.cpp126
-rw-r--r--location/java/android/location/GnssRequest.aidl (renamed from core/java/android/os/StatsDimensionsValue.aidl)12
-rw-r--r--location/java/android/location/GnssRequest.java147
-rw-r--r--location/java/android/location/LocationManager.java24
-rw-r--r--media/java/android/media/tv/tuner/frontend/FrontendStatus.java45
-rw-r--r--media/java/android/media/tv/tuner/frontend/ScanCallback.java2
-rw-r--r--packages/Incremental/NativeAdbDataLoader/AndroidManifest.xml2
-rw-r--r--packages/Shell/src/com/android/shell/BugreportProgressService.java122
-rw-r--r--packages/SystemUI/res/drawable-nodpi/android_11_dial.xml63
-rw-r--r--packages/SystemUI/res/drawable-nodpi/icon.xml2
-rw-r--r--packages/SystemUI/res/drawable-nodpi/icon_bg.xml2
-rw-r--r--packages/SystemUI/res/drawable-nodpi/q.xml40
-rw-r--r--packages/SystemUI/res/values/dimens.xml2
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java17
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java103
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java171
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationViewController.java89
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java37
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java161
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableOutlineViewController.java41
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowInflaterTask.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/dagger/ActivatableNotificationViewModule.java37
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/dagger/DismissRunnable.java30
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/dagger/ExpandableNotificationRowComponent.java122
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/dagger/NotificationKey.java30
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/dagger/NotificationRowComponent.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/dagger/NotificationRowScope.java32
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/animation/PhysicsAnimator.kt17
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/external/CustomTileTest.kt6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTest.java6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java81
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java3
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java18
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManagerTest.java10
-rw-r--r--services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java15
-rw-r--r--services/autofill/java/com/android/server/autofill/InlineSuggestionSession.java168
-rw-r--r--services/autofill/java/com/android/server/autofill/Session.java125
-rw-r--r--services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java22
-rw-r--r--services/core/java/com/android/server/TelephonyRegistry.java18
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java27
-rw-r--r--services/core/java/com/android/server/notification/NotificationHistoryDatabase.java48
-rw-r--r--services/core/java/com/android/server/notification/NotificationHistoryManager.java18
-rwxr-xr-xservices/core/java/com/android/server/notification/NotificationManagerService.java22
-rw-r--r--services/core/java/com/android/server/pm/ApexManager.java6
-rw-r--r--services/core/java/com/android/server/pm/AppsFilter.java3
-rw-r--r--services/core/java/com/android/server/pm/LauncherAppsService.java41
-rw-r--r--services/core/java/com/android/server/pm/PackageAbiHelperImpl.java44
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerSession.java9
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java5
-rw-r--r--services/core/java/com/android/server/pm/ShortcutService.java64
-rw-r--r--services/core/java/com/android/server/pm/UserManagerService.java2
-rw-r--r--services/core/java/com/android/server/policy/PermissionPolicyService.java220
-rw-r--r--services/core/java/com/android/server/wm/Task.java12
-rw-r--r--services/core/java/com/android/server/wm/TaskOrganizerController.java100
-rw-r--r--services/core/java/com/android/server/wm/WindowContainer.java4
-rw-r--r--services/core/jni/Android.bp4
-rw-r--r--services/core/jni/com_android_server_GraphicsStatsService.cpp292
-rw-r--r--services/core/jni/onload.cpp4
-rw-r--r--services/incremental/BinderIncrementalService.cpp9
-rw-r--r--services/incremental/BinderIncrementalService.h11
-rw-r--r--services/incremental/IncrementalService.cpp131
-rw-r--r--services/incremental/IncrementalService.h3
-rw-r--r--services/java/com/android/server/SystemServer.java1
-rw-r--r--services/people/java/com/android/server/people/data/ConversationInfo.java20
-rw-r--r--services/people/java/com/android/server/people/data/DataManager.java44
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/am/ApplicationExitInfoTest.java44
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/blob/BlobStoreManagerServiceTest.java14
-rw-r--r--services/tests/servicestests/src/com/android/server/people/data/ConversationInfoTest.java12
-rw-r--r--services/tests/servicestests/src/com/android/server/people/data/ConversationStoreTest.java2
-rw-r--r--services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java93
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java21
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java80
-rw-r--r--services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java34
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/NotificationHistoryDatabaseTest.java47
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/NotificationHistoryManagerTest.java14
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java76
-rw-r--r--telephony/java/android/telephony/euicc/EuiccCardManager.java158
-rw-r--r--tests/RollbackTest/Android.bp9
-rw-r--r--tests/RollbackTest/NetworkStagedRollbackTest.xml25
-rw-r--r--tests/RollbackTest/NetworkStagedRollbackTest/src/com/android/tests/rollback/host/NetworkStagedRollbackTest.java43
-rw-r--r--tests/RollbackTest/RollbackTest.xml4
-rw-r--r--tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/NetworkStagedRollbackTest.java (renamed from packages/SystemUI/src/com/android/systemui/statusbar/notification/row/dagger/AppName.java)16
-rw-r--r--wifi/java/android/net/wifi/SoftApConfiguration.java3
-rw-r--r--wifi/java/android/net/wifi/WifiManager.java18
-rw-r--r--wifi/tests/src/android/net/wifi/SoftApConfigurationTest.java40
185 files changed, 4533 insertions, 2616 deletions
diff --git a/Android.bp b/Android.bp
index 69d654fbddbc..f63e78bedd43 100644
--- a/Android.bp
+++ b/Android.bp
@@ -445,13 +445,6 @@ filegroup {
}
filegroup {
- name: "graphicsstats_proto",
- srcs: [
- "libs/hwui/protos/graphicsstats.proto",
- ],
-}
-
-filegroup {
name: "libvibrator_aidl",
srcs: [
"core/java/android/os/IExternalVibrationController.aidl",
diff --git a/apct-tests/perftests/core/src/android/os/PackageManagerPerfTest.java b/apct-tests/perftests/core/src/android/os/PackageManagerPerfTest.java
deleted file mode 100644
index 236f548cf6dd..000000000000
--- a/apct-tests/perftests/core/src/android/os/PackageManagerPerfTest.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (C) 2017 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.os;
-
-import android.content.ComponentName;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.perftests.utils.BenchmarkState;
-import android.perftests.utils.PerfStatusReporter;
-
-import androidx.test.InstrumentationRegistry;
-import androidx.test.filters.LargeTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@RunWith(AndroidJUnit4.class)
-@LargeTest
-public class PackageManagerPerfTest {
- private static final String PERMISSION_NAME_EXISTS =
- "com.android.perftests.core.TestPermission";
- private static final String PERMISSION_NAME_DOESNT_EXIST =
- "com.android.perftests.core.TestBadPermission";
- private static final ComponentName TEST_ACTIVITY =
- new ComponentName("com.android.perftests.core",
- "android.perftests.utils.PerfTestActivity");
-
- @Rule
- public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
-
- @Test
- public void testCheckPermissionExists() {
- final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
- final PackageManager pm = InstrumentationRegistry.getTargetContext().getPackageManager();
- final String packageName = TEST_ACTIVITY.getPackageName();
-
- while (state.keepRunning()) {
- int ret = pm.checkPermission(PERMISSION_NAME_EXISTS, packageName);
- }
- }
-
- @Test
- public void testCheckPermissionDoesntExist() {
- final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
- final PackageManager pm = InstrumentationRegistry.getTargetContext().getPackageManager();
- final String packageName = TEST_ACTIVITY.getPackageName();
-
- while (state.keepRunning()) {
- int ret = pm.checkPermission(PERMISSION_NAME_DOESNT_EXIST, packageName);
- }
- }
-
- @Test
- public void testQueryIntentActivities() {
- final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
- final PackageManager pm = InstrumentationRegistry.getTargetContext().getPackageManager();
- final Intent intent = new Intent("com.android.perftests.core.PERFTEST");
-
- while (state.keepRunning()) {
- pm.queryIntentActivities(intent, 0);
- }
- }
-
- @Test
- public void testGetPackageInfo() throws Exception {
- final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
- final PackageManager pm = InstrumentationRegistry.getTargetContext().getPackageManager();
- final String packageName = TEST_ACTIVITY.getPackageName();
-
- while (state.keepRunning()) {
- pm.getPackageInfo(packageName, 0);
- }
- }
-
- @Test
- public void testGetApplicationInfo() throws Exception {
- final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
- final PackageManager pm = InstrumentationRegistry.getTargetContext().getPackageManager();
- final String packageName = TEST_ACTIVITY.getPackageName();
-
- while (state.keepRunning()) {
- pm.getApplicationInfo(packageName, 0);
- }
- }
-
- @Test
- public void testGetActivityInfo() throws Exception {
- final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
- final PackageManager pm = InstrumentationRegistry.getTargetContext().getPackageManager();
-
- while (state.keepRunning()) {
- pm.getActivityInfo(TEST_ACTIVITY, 0);
- }
- }
-}
diff --git a/apct-tests/perftests/packagemanager/Android.bp b/apct-tests/perftests/packagemanager/Android.bp
new file mode 100644
index 000000000000..17033e048c7d
--- /dev/null
+++ b/apct-tests/perftests/packagemanager/Android.bp
@@ -0,0 +1,21 @@
+android_test {
+ name: "PackageManagerPerfTests",
+
+ srcs: ["src/**/*.java"],
+
+ static_libs: [
+ "platform-compat-test-rules",
+ "androidx.appcompat_appcompat",
+ "androidx.test.rules",
+ "androidx.test.ext.junit",
+ "androidx.annotation_annotation",
+ "apct-perftests-utils",
+ ],
+
+ libs: ["android.test.base"],
+
+ platform_apis: true,
+
+ test_suites: ["device-tests"],
+
+}
diff --git a/apct-tests/perftests/packagemanager/AndroidManifest.xml b/apct-tests/perftests/packagemanager/AndroidManifest.xml
new file mode 100644
index 000000000000..520f4b55d931
--- /dev/null
+++ b/apct-tests/perftests/packagemanager/AndroidManifest.xml
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.perftests.packagemanager">
+
+ <permission android:name="com.android.perftests.packagemanager.TestPermission" />
+ <uses-permission android:name="com.android.perftests.packagemanager.TestPermission" />
+
+ <queries>
+ <package android:name="com.android.perftests.appenumeration0" />
+ <package android:name="com.android.perftests.appenumeration1" />
+ <package android:name="com.android.perftests.appenumeration2" />
+ <package android:name="com.android.perftests.appenumeration3" />
+ <package android:name="com.android.perftests.appenumeration4" />
+ <package android:name="com.android.perftests.appenumeration5" />
+ <package android:name="com.android.perftests.appenumeration6" />
+ <package android:name="com.android.perftests.appenumeration7" />
+ <package android:name="com.android.perftests.appenumeration8" />
+ <package android:name="com.android.perftests.appenumeration9" />
+ <package android:name="com.android.perftests.appenumeration10" />
+ <package android:name="com.android.perftests.appenumeration11" />
+ <package android:name="com.android.perftests.appenumeration12" />
+ <package android:name="com.android.perftests.appenumeration13" />
+ <package android:name="com.android.perftests.appenumeration14" />
+ <package android:name="com.android.perftests.appenumeration15" />
+ <package android:name="com.android.perftests.appenumeration16" />
+ <package android:name="com.android.perftests.appenumeration17" />
+ <package android:name="com.android.perftests.appenumeration18" />
+ <package android:name="com.android.perftests.appenumeration19" />
+ <package android:name="com.android.perftests.appenumeration20" />
+ <package android:name="com.android.perftests.appenumeration21" />
+ <package android:name="com.android.perftests.appenumeration22" />
+ <package android:name="com.android.perftests.appenumeration23" />
+ <package android:name="com.android.perftests.appenumeration24" />
+ <package android:name="com.android.perftests.appenumeration25" />
+ <package android:name="com.android.perftests.appenumeration26" />
+ <package android:name="com.android.perftests.appenumeration27" />
+ <package android:name="com.android.perftests.appenumeration28" />
+ <package android:name="com.android.perftests.appenumeration29" />
+ <package android:name="com.android.perftests.appenumeration30" />
+ <package android:name="com.android.perftests.appenumeration31" />
+ <package android:name="com.android.perftests.appenumeration32" />
+ <package android:name="com.android.perftests.appenumeration33" />
+ <package android:name="com.android.perftests.appenumeration34" />
+ <package android:name="com.android.perftests.appenumeration35" />
+ <package android:name="com.android.perftests.appenumeration36" />
+ <package android:name="com.android.perftests.appenumeration37" />
+ <package android:name="com.android.perftests.appenumeration38" />
+ <package android:name="com.android.perftests.appenumeration39" />
+ <package android:name="com.android.perftests.appenumeration40" />
+ <package android:name="com.android.perftests.appenumeration41" />
+ <package android:name="com.android.perftests.appenumeration42" />
+ <package android:name="com.android.perftests.appenumeration43" />
+ <package android:name="com.android.perftests.appenumeration44" />
+ <package android:name="com.android.perftests.appenumeration45" />
+ <package android:name="com.android.perftests.appenumeration46" />
+ <package android:name="com.android.perftests.appenumeration47" />
+ <package android:name="com.android.perftests.appenumeration48" />
+ <package android:name="com.android.perftests.appenumeration49" />
+ </queries>
+
+ <application>
+ <uses-library android:name="android.test.runner" />
+ <activity android:name="android.perftests.utils.PerfTestActivity">
+ <intent-filter>
+ <action android:name="com.android.perftests.packagemanager.PERFTEST" />
+ </intent-filter>
+ </activity>
+ </application>
+
+ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.perftests.packagemanager"/>
+
+</manifest>
diff --git a/apct-tests/perftests/packagemanager/AndroidTest.xml b/apct-tests/perftests/packagemanager/AndroidTest.xml
new file mode 100644
index 000000000000..c112d87d83e1
--- /dev/null
+++ b/apct-tests/perftests/packagemanager/AndroidTest.xml
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 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.
+ -->
+<configuration description="Runs PackageManagerPerfTests metric instrumentation.">
+ <option name="test-suite-tag" value="apct" />
+ <option name="test-suite-tag" value="apct-metric-instrumentation" />
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="PackageManagerPerfTests.apk" />
+ </target_preparer>
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="force-queryable" value="false" />
+ <option name="test-file-name" value="QueriesAll0.apk" />
+ <option name="test-file-name" value="QueriesAll1.apk" />
+ <option name="test-file-name" value="QueriesAll2.apk" />
+ <option name="test-file-name" value="QueriesAll3.apk" />
+ <option name="test-file-name" value="QueriesAll4.apk" />
+ <option name="test-file-name" value="QueriesAll5.apk" />
+ <option name="test-file-name" value="QueriesAll6.apk" />
+ <option name="test-file-name" value="QueriesAll7.apk" />
+ <option name="test-file-name" value="QueriesAll8.apk" />
+ <option name="test-file-name" value="QueriesAll9.apk" />
+ <option name="test-file-name" value="QueriesAll10.apk" />
+ <option name="test-file-name" value="QueriesAll11.apk" />
+ <option name="test-file-name" value="QueriesAll12.apk" />
+ <option name="test-file-name" value="QueriesAll13.apk" />
+ <option name="test-file-name" value="QueriesAll14.apk" />
+ <option name="test-file-name" value="QueriesAll15.apk" />
+ <option name="test-file-name" value="QueriesAll16.apk" />
+ <option name="test-file-name" value="QueriesAll17.apk" />
+ <option name="test-file-name" value="QueriesAll18.apk" />
+ <option name="test-file-name" value="QueriesAll19.apk" />
+ <option name="test-file-name" value="QueriesAll20.apk" />
+ <option name="test-file-name" value="QueriesAll21.apk" />
+ <option name="test-file-name" value="QueriesAll22.apk" />
+ <option name="test-file-name" value="QueriesAll23.apk" />
+ <option name="test-file-name" value="QueriesAll24.apk" />
+ <option name="test-file-name" value="QueriesAll25.apk" />
+ <option name="test-file-name" value="QueriesAll26.apk" />
+ <option name="test-file-name" value="QueriesAll27.apk" />
+ <option name="test-file-name" value="QueriesAll28.apk" />
+ <option name="test-file-name" value="QueriesAll29.apk" />
+ <option name="test-file-name" value="QueriesAll30.apk" />
+ <option name="test-file-name" value="QueriesAll31.apk" />
+ <option name="test-file-name" value="QueriesAll32.apk" />
+ <option name="test-file-name" value="QueriesAll33.apk" />
+ <option name="test-file-name" value="QueriesAll34.apk" />
+ <option name="test-file-name" value="QueriesAll35.apk" />
+ <option name="test-file-name" value="QueriesAll36.apk" />
+ <option name="test-file-name" value="QueriesAll37.apk" />
+ <option name="test-file-name" value="QueriesAll38.apk" />
+ <option name="test-file-name" value="QueriesAll39.apk" />
+ <option name="test-file-name" value="QueriesAll40.apk" />
+ <option name="test-file-name" value="QueriesAll41.apk" />
+ <option name="test-file-name" value="QueriesAll42.apk" />
+ <option name="test-file-name" value="QueriesAll43.apk" />
+ <option name="test-file-name" value="QueriesAll44.apk" />
+ <option name="test-file-name" value="QueriesAll45.apk" />
+ <option name="test-file-name" value="QueriesAll46.apk" />
+ <option name="test-file-name" value="QueriesAll47.apk" />
+ <option name="test-file-name" value="QueriesAll48.apk" />
+ <option name="test-file-name" value="QueriesAll49.apk" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="com.android.perftests.packagemanager" />
+ <option name="hidden-api-checks" value="false"/>
+ </test>
+
+ <metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector">
+ <option name="directory-keys" value="/data/local/PackageManagerPerfTests" />
+ <option name="collect-on-run-ended-only" value="true" />
+ </metrics_collector>
+</configuration>
diff --git a/apct-tests/perftests/packagemanager/apps/query-all/Android.bp b/apct-tests/perftests/packagemanager/apps/query-all/Android.bp
new file mode 100644
index 000000000000..3cb1589bc376
--- /dev/null
+++ b/apct-tests/perftests/packagemanager/apps/query-all/Android.bp
@@ -0,0 +1,314 @@
+// Copyright (C) 2020 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.
+
+android_test_helper_app {
+ name: "QueriesAll0",
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.appenumeration0",
+ ]
+}
+android_test_helper_app {
+ name: "QueriesAll1",
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.appenumeration1",
+ ]
+}
+android_test_helper_app {
+ name: "QueriesAll2",
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.appenumeration2",
+ ]
+}
+android_test_helper_app {
+ name: "QueriesAll3",
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.appenumeration3",
+ ]
+}
+android_test_helper_app {
+ name: "QueriesAll4",
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.appenumeration4",
+ ]
+}
+android_test_helper_app {
+ name: "QueriesAll5",
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.appenumeration5",
+ ]
+}
+android_test_helper_app {
+ name: "QueriesAll6",
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.appenumeration6",
+ ]
+}
+android_test_helper_app {
+ name: "QueriesAll7",
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.appenumeration7",
+ ]
+}
+android_test_helper_app {
+ name: "QueriesAll8",
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.appenumeration8",
+ ]
+}
+android_test_helper_app {
+ name: "QueriesAll9",
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.appenumeration9",
+ ]
+}
+android_test_helper_app {
+ name: "QueriesAll10",
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.appenumeration10",
+ ]
+}
+android_test_helper_app {
+ name: "QueriesAll11",
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.appenumeration11",
+ ]
+}
+android_test_helper_app {
+ name: "QueriesAll12",
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.appenumeration12",
+ ]
+}
+android_test_helper_app {
+ name: "QueriesAll13",
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.appenumeration13",
+ ]
+}
+android_test_helper_app {
+ name: "QueriesAll14",
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.appenumeration14",
+ ]
+}
+android_test_helper_app {
+ name: "QueriesAll15",
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.appenumeration15",
+ ]
+}
+android_test_helper_app {
+ name: "QueriesAll16",
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.appenumeration16",
+ ]
+}
+android_test_helper_app {
+ name: "QueriesAll17",
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.appenumeration17",
+ ]
+}
+android_test_helper_app {
+ name: "QueriesAll18",
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.appenumeration18",
+ ]
+}
+android_test_helper_app {
+ name: "QueriesAll19",
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.appenumeration19",
+ ]
+}
+android_test_helper_app {
+ name: "QueriesAll20",
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.appenumeration20",
+ ]
+}
+android_test_helper_app {
+ name: "QueriesAll21",
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.appenumeration21",
+ ]
+}
+android_test_helper_app {
+ name: "QueriesAll22",
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.appenumeration22",
+ ]
+}
+android_test_helper_app {
+ name: "QueriesAll23",
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.appenumeration23",
+ ]
+}
+android_test_helper_app {
+ name: "QueriesAll24",
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.appenumeration24",
+ ]
+}
+android_test_helper_app {
+ name: "QueriesAll25",
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.appenumeration25",
+ ]
+}
+android_test_helper_app {
+ name: "QueriesAll26",
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.appenumeration26",
+ ]
+}
+android_test_helper_app {
+ name: "QueriesAll27",
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.appenumeration27",
+ ]
+}
+android_test_helper_app {
+ name: "QueriesAll28",
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.appenumeration28",
+ ]
+}
+android_test_helper_app {
+ name: "QueriesAll29",
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.appenumeration29",
+ ]
+}
+android_test_helper_app {
+ name: "QueriesAll30",
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.appenumeration30",
+ ]
+}
+android_test_helper_app {
+ name: "QueriesAll31",
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.appenumeration31",
+ ]
+}
+android_test_helper_app {
+ name: "QueriesAll32",
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.appenumeration32",
+ ]
+}
+android_test_helper_app {
+ name: "QueriesAll33",
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.appenumeration33",
+ ]
+}
+android_test_helper_app {
+ name: "QueriesAll34",
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.appenumeration34",
+ ]
+}
+android_test_helper_app {
+ name: "QueriesAll35",
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.appenumeration35",
+ ]
+}
+android_test_helper_app {
+ name: "QueriesAll36",
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.appenumeration36",
+ ]
+}
+android_test_helper_app {
+ name: "QueriesAll37",
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.appenumeration37",
+ ]
+}
+android_test_helper_app {
+ name: "QueriesAll38",
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.appenumeration38",
+ ]
+}
+android_test_helper_app {
+ name: "QueriesAll39",
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.appenumeration39",
+ ]
+}
+android_test_helper_app {
+ name: "QueriesAll40",
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.appenumeration40",
+ ]
+}
+android_test_helper_app {
+ name: "QueriesAll41",
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.appenumeration41",
+ ]
+}
+android_test_helper_app {
+ name: "QueriesAll42",
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.appenumeration42",
+ ]
+}
+android_test_helper_app {
+ name: "QueriesAll43",
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.appenumeration43",
+ ]
+}
+android_test_helper_app {
+ name: "QueriesAll44",
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.appenumeration44",
+ ]
+}
+android_test_helper_app {
+ name: "QueriesAll45",
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.appenumeration45",
+ ]
+}
+android_test_helper_app {
+ name: "QueriesAll46",
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.appenumeration46",
+ ]
+}
+android_test_helper_app {
+ name: "QueriesAll47",
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.appenumeration47",
+ ]
+}
+android_test_helper_app {
+ name: "QueriesAll48",
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.appenumeration48",
+ ]
+}
+android_test_helper_app {
+ name: "QueriesAll49",
+ aaptflags: [
+ "--rename-manifest-package com.android.perftests.appenumeration49",
+ ]
+}
diff --git a/apct-tests/perftests/packagemanager/apps/query-all/AndroidManifest.xml b/apct-tests/perftests/packagemanager/apps/query-all/AndroidManifest.xml
new file mode 100644
index 000000000000..e2cfa0430a32
--- /dev/null
+++ b/apct-tests/perftests/packagemanager/apps/query-all/AndroidManifest.xml
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 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.
+ -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.perftests.appenumeration">
+
+ <application android:hasCode="false" >
+ <activity android:name="android.perftests.utils.PerfTestActivity">
+ <intent-filter>
+ <action android:name="com.android.perftests.packagemanager.PERFTEST" />
+ </intent-filter>
+ </activity>
+ </application>
+
+ <queries>
+ <package android:name="com.android.perftests.appenumeration0" />
+ <package android:name="com.android.perftests.appenumeration1" />
+ <package android:name="com.android.perftests.appenumeration2" />
+ <package android:name="com.android.perftests.appenumeration3" />
+ <package android:name="com.android.perftests.appenumeration4" />
+ <package android:name="com.android.perftests.appenumeration5" />
+ <package android:name="com.android.perftests.appenumeration6" />
+ <package android:name="com.android.perftests.appenumeration7" />
+ <package android:name="com.android.perftests.appenumeration8" />
+ <package android:name="com.android.perftests.appenumeration9" />
+ <package android:name="com.android.perftests.appenumeration10" />
+ <package android:name="com.android.perftests.appenumeration11" />
+ <package android:name="com.android.perftests.appenumeration12" />
+ <package android:name="com.android.perftests.appenumeration13" />
+ <package android:name="com.android.perftests.appenumeration14" />
+ <package android:name="com.android.perftests.appenumeration15" />
+ <package android:name="com.android.perftests.appenumeration16" />
+ <package android:name="com.android.perftests.appenumeration17" />
+ <package android:name="com.android.perftests.appenumeration18" />
+ <package android:name="com.android.perftests.appenumeration19" />
+ <package android:name="com.android.perftests.appenumeration20" />
+ <package android:name="com.android.perftests.appenumeration21" />
+ <package android:name="com.android.perftests.appenumeration22" />
+ <package android:name="com.android.perftests.appenumeration23" />
+ <package android:name="com.android.perftests.appenumeration24" />
+ <package android:name="com.android.perftests.appenumeration25" />
+ <package android:name="com.android.perftests.appenumeration26" />
+ <package android:name="com.android.perftests.appenumeration27" />
+ <package android:name="com.android.perftests.appenumeration28" />
+ <package android:name="com.android.perftests.appenumeration29" />
+ <package android:name="com.android.perftests.appenumeration30" />
+ <package android:name="com.android.perftests.appenumeration31" />
+ <package android:name="com.android.perftests.appenumeration32" />
+ <package android:name="com.android.perftests.appenumeration33" />
+ <package android:name="com.android.perftests.appenumeration34" />
+ <package android:name="com.android.perftests.appenumeration35" />
+ <package android:name="com.android.perftests.appenumeration36" />
+ <package android:name="com.android.perftests.appenumeration37" />
+ <package android:name="com.android.perftests.appenumeration38" />
+ <package android:name="com.android.perftests.appenumeration39" />
+ <package android:name="com.android.perftests.appenumeration40" />
+ <package android:name="com.android.perftests.appenumeration41" />
+ <package android:name="com.android.perftests.appenumeration42" />
+ <package android:name="com.android.perftests.appenumeration43" />
+ <package android:name="com.android.perftests.appenumeration44" />
+ <package android:name="com.android.perftests.appenumeration45" />
+ <package android:name="com.android.perftests.appenumeration46" />
+ <package android:name="com.android.perftests.appenumeration47" />
+ <package android:name="com.android.perftests.appenumeration48" />
+ <package android:name="com.android.perftests.appenumeration49" />
+ </queries>
+
+</manifest> \ No newline at end of file
diff --git a/apct-tests/perftests/packagemanager/src/android/os/PackageManagerPerfTest.java b/apct-tests/perftests/packagemanager/src/android/os/PackageManagerPerfTest.java
new file mode 100644
index 000000000000..d7428cf0ab8a
--- /dev/null
+++ b/apct-tests/perftests/packagemanager/src/android/os/PackageManagerPerfTest.java
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 2020 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.os;
+
+import static libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges;
+import static libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;
+
+import android.compat.testing.PlatformCompatChangeRule;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.LargeTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@LargeTest
+public class PackageManagerPerfTest {
+ private static final String PERMISSION_NAME_EXISTS =
+ "com.android.perftests.packagemanager.TestPermission";
+ private static final String PERMISSION_NAME_DOESNT_EXIST =
+ "com.android.perftests.packagemanager.TestBadPermission";
+ private static final String OTHER_PACKAGE_NAME = "com.android.perftests.appenumeration0";
+ private static final ComponentName TEST_ACTIVITY =
+ new ComponentName(OTHER_PACKAGE_NAME,
+ "android.perftests.utils.PerfTestActivity");
+
+ @Rule
+ public final PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+ @Rule
+ public final PlatformCompatChangeRule mPlatformCompatChangeRule =
+ new PlatformCompatChangeRule();
+
+ public PackageManagerPerfTest() throws PackageManager.NameNotFoundException {
+ final Context context = InstrumentationRegistry.getInstrumentation().getContext();
+ }
+
+ @Test
+ @DisableCompatChanges(PackageManager.FILTER_APPLICATION_QUERY)
+ public void testCheckPermissionExists() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ final PackageManager pm =
+ InstrumentationRegistry.getInstrumentation().getTargetContext().getPackageManager();
+ final String packageName = TEST_ACTIVITY.getPackageName();
+
+ while (state.keepRunning()) {
+ int ret = pm.checkPermission(PERMISSION_NAME_EXISTS, packageName);
+ }
+ }
+
+ @Test
+ @EnableCompatChanges(PackageManager.FILTER_APPLICATION_QUERY)
+ public void testCheckPermissionExistsWithFiltering() {
+ testCheckPermissionExists();
+ }
+
+ @Test
+ @DisableCompatChanges(PackageManager.FILTER_APPLICATION_QUERY)
+ public void testCheckPermissionDoesntExist() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ final PackageManager pm =
+ InstrumentationRegistry.getInstrumentation().getTargetContext().getPackageManager();
+ final String packageName = TEST_ACTIVITY.getPackageName();
+
+ while (state.keepRunning()) {
+ int ret = pm.checkPermission(PERMISSION_NAME_DOESNT_EXIST, packageName);
+ }
+ }
+
+ @Test
+ @EnableCompatChanges(PackageManager.FILTER_APPLICATION_QUERY)
+ public void testCheckPermissionDoesntExistWithFiltering() {
+ testCheckPermissionDoesntExist();
+ }
+
+ @Test
+ @DisableCompatChanges(PackageManager.FILTER_APPLICATION_QUERY)
+ public void testQueryIntentActivities() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ final PackageManager pm =
+ InstrumentationRegistry.getInstrumentation().getTargetContext().getPackageManager();
+ final Intent intent = new Intent("com.android.perftests.core.PERFTEST");
+
+ while (state.keepRunning()) {
+ pm.queryIntentActivities(intent, 0);
+ }
+ }
+
+ @Test
+ @EnableCompatChanges(PackageManager.FILTER_APPLICATION_QUERY)
+ public void testQueryIntentActivitiesWithFiltering() {
+ testQueryIntentActivities();
+ }
+
+ @Test
+ @DisableCompatChanges(PackageManager.FILTER_APPLICATION_QUERY)
+ public void testGetPackageInfo() throws Exception {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ final PackageManager pm =
+ InstrumentationRegistry.getInstrumentation().getTargetContext().getPackageManager();
+
+ while (state.keepRunning()) {
+ pm.getPackageInfo(OTHER_PACKAGE_NAME, 0);
+ }
+ }
+
+ @Test
+ @EnableCompatChanges(PackageManager.FILTER_APPLICATION_QUERY)
+ public void testGetPackageInfoWithFiltering() throws Exception {
+ testGetPackageInfo();
+ }
+
+ @Test
+ @DisableCompatChanges(PackageManager.FILTER_APPLICATION_QUERY)
+ public void testGetApplicationInfo() throws Exception {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ final PackageManager pm =
+ InstrumentationRegistry.getInstrumentation().getTargetContext().getPackageManager();
+
+ while (state.keepRunning()) {
+ pm.getApplicationInfo(OTHER_PACKAGE_NAME, 0);
+ }
+ }
+
+ @Test
+ @EnableCompatChanges(PackageManager.FILTER_APPLICATION_QUERY)
+ public void testGetApplicationInfoWithFiltering() throws Exception {
+ testGetApplicationInfo();
+ }
+
+ @Test
+ @DisableCompatChanges(PackageManager.FILTER_APPLICATION_QUERY)
+ public void testGetActivityInfo() throws Exception {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ final PackageManager pm =
+ InstrumentationRegistry.getInstrumentation().getTargetContext().getPackageManager();
+
+ while (state.keepRunning()) {
+ pm.getActivityInfo(TEST_ACTIVITY, 0);
+ }
+ }
+
+ @Test
+ @EnableCompatChanges(PackageManager.FILTER_APPLICATION_QUERY)
+ public void testGetActivityInfoWithFiltering() throws Exception {
+ testGetActivityInfo();
+ }
+
+ @Test
+ @DisableCompatChanges(PackageManager.FILTER_APPLICATION_QUERY)
+ public void testGetInstalledPackages() throws Exception {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ final PackageManager pm =
+ InstrumentationRegistry.getInstrumentation().getTargetContext().getPackageManager();
+
+ while (state.keepRunning()) {
+ pm.getInstalledPackages(0);
+ }
+ }
+
+ @Test
+ @EnableCompatChanges(PackageManager.FILTER_APPLICATION_QUERY)
+ public void testGetInstalledPackagesWithFiltering() throws Exception {
+ testGetInstalledPackages();
+ }
+}
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
index 69f4748548a7..939164edd13e 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
@@ -494,9 +494,10 @@ public class JobSchedulerService extends com.android.server.SystemService
private static final String DEPRECATED_KEY_BG_LOW_JOB_COUNT = "bg_low_job_count";
private static final String DEPRECATED_KEY_BG_CRITICAL_JOB_COUNT = "bg_critical_job_count";
- private static final String KEY_MAX_STANDARD_RESCHEDULE_COUNT
+ private static final String DEPRECATED_KEY_MAX_STANDARD_RESCHEDULE_COUNT
= "max_standard_reschedule_count";
- private static final String KEY_MAX_WORK_RESCHEDULE_COUNT = "max_work_reschedule_count";
+ private static final String DEPRECATED_KEY_MAX_WORK_RESCHEDULE_COUNT =
+ "max_work_reschedule_count";
private static final String KEY_MIN_LINEAR_BACKOFF_TIME = "min_linear_backoff_time";
private static final String KEY_MIN_EXP_BACKOFF_TIME = "min_exp_backoff_time";
private static final String DEPRECATED_KEY_STANDBY_HEARTBEAT_TIME =
@@ -525,8 +526,6 @@ public class JobSchedulerService extends com.android.server.SystemService
private static final long DEFAULT_MAX_NON_ACTIVE_JOB_BATCH_DELAY_MS = 31 * MINUTE_IN_MILLIS;
private static final float DEFAULT_HEAVY_USE_FACTOR = .9f;
private static final float DEFAULT_MODERATE_USE_FACTOR = .5f;
- private static final int DEFAULT_MAX_STANDARD_RESCHEDULE_COUNT = Integer.MAX_VALUE;
- private static final int DEFAULT_MAX_WORK_RESCHEDULE_COUNT = Integer.MAX_VALUE;
private static final long DEFAULT_MIN_LINEAR_BACKOFF_TIME = JobInfo.MIN_BACKOFF_MILLIS;
private static final long DEFAULT_MIN_EXP_BACKOFF_TIME = JobInfo.MIN_BACKOFF_MILLIS;
private static final float DEFAULT_CONN_CONGESTION_DELAY_FRAC = 0.5f;
@@ -640,16 +639,6 @@ public class JobSchedulerService extends com.android.server.SystemService
"screen_off_job_concurrency_increase_delay_ms", 30_000);
/**
- * The maximum number of times we allow a job to have itself rescheduled before
- * giving up on it, for standard jobs.
- */
- int MAX_STANDARD_RESCHEDULE_COUNT = DEFAULT_MAX_STANDARD_RESCHEDULE_COUNT;
- /**
- * The maximum number of times we allow a job to have itself rescheduled before
- * giving up on it, for jobs that are executing work.
- */
- int MAX_WORK_RESCHEDULE_COUNT = DEFAULT_MAX_WORK_RESCHEDULE_COUNT;
- /**
* The minimum backoff time to allow for linear backoff.
*/
long MIN_LINEAR_BACKOFF_TIME = DEFAULT_MIN_LINEAR_BACKOFF_TIME;
@@ -735,10 +724,6 @@ public class JobSchedulerService extends com.android.server.SystemService
SCREEN_OFF_JOB_CONCURRENCY_INCREASE_DELAY_MS.parse(mParser);
- MAX_STANDARD_RESCHEDULE_COUNT = mParser.getInt(KEY_MAX_STANDARD_RESCHEDULE_COUNT,
- DEFAULT_MAX_STANDARD_RESCHEDULE_COUNT);
- MAX_WORK_RESCHEDULE_COUNT = mParser.getInt(KEY_MAX_WORK_RESCHEDULE_COUNT,
- DEFAULT_MAX_WORK_RESCHEDULE_COUNT);
MIN_LINEAR_BACKOFF_TIME = mParser.getDurationMillis(KEY_MIN_LINEAR_BACKOFF_TIME,
DEFAULT_MIN_LINEAR_BACKOFF_TIME);
MIN_EXP_BACKOFF_TIME = mParser.getDurationMillis(KEY_MIN_EXP_BACKOFF_TIME,
@@ -790,8 +775,6 @@ public class JobSchedulerService extends com.android.server.SystemService
SCREEN_OFF_JOB_CONCURRENCY_INCREASE_DELAY_MS.dump(pw, "");
- pw.printPair(KEY_MAX_STANDARD_RESCHEDULE_COUNT, MAX_STANDARD_RESCHEDULE_COUNT).println();
- pw.printPair(KEY_MAX_WORK_RESCHEDULE_COUNT, MAX_WORK_RESCHEDULE_COUNT).println();
pw.printPair(KEY_MIN_LINEAR_BACKOFF_TIME, MIN_LINEAR_BACKOFF_TIME).println();
pw.printPair(KEY_MIN_EXP_BACKOFF_TIME, MIN_EXP_BACKOFF_TIME).println();
pw.printPair(KEY_CONN_CONGESTION_DELAY_FRAC, CONN_CONGESTION_DELAY_FRAC).println();
@@ -827,8 +810,6 @@ public class JobSchedulerService extends com.android.server.SystemService
SCREEN_OFF_JOB_CONCURRENCY_INCREASE_DELAY_MS.dumpProto(proto,
ConstantsProto.SCREEN_OFF_JOB_CONCURRENCY_INCREASE_DELAY_MS);
- proto.write(ConstantsProto.MAX_STANDARD_RESCHEDULE_COUNT, MAX_STANDARD_RESCHEDULE_COUNT);
- proto.write(ConstantsProto.MAX_WORK_RESCHEDULE_COUNT, MAX_WORK_RESCHEDULE_COUNT);
proto.write(ConstantsProto.MIN_LINEAR_BACKOFF_TIME_MS, MIN_LINEAR_BACKOFF_TIME);
proto.write(ConstantsProto.MIN_EXP_BACKOFF_TIME_MS, MIN_EXP_BACKOFF_TIME);
proto.write(ConstantsProto.CONN_CONGESTION_DELAY_FRAC, CONN_CONGESTION_DELAY_FRAC);
@@ -1390,18 +1371,8 @@ public class JobSchedulerService extends com.android.server.SystemService
// Effective standby bucket can change after this in some situations so use
// the real bucket so that the job is tracked by the controllers.
if (js.getStandbyBucket() == RESTRICTED_INDEX) {
- js.addDynamicConstraint(JobStatus.CONSTRAINT_BATTERY_NOT_LOW);
- js.addDynamicConstraint(JobStatus.CONSTRAINT_CHARGING);
- js.addDynamicConstraint(JobStatus.CONSTRAINT_CONNECTIVITY);
- js.addDynamicConstraint(JobStatus.CONSTRAINT_IDLE);
-
mRestrictiveControllers.get(j).startTrackingRestrictedJobLocked(js);
} else {
- js.removeDynamicConstraint(JobStatus.CONSTRAINT_BATTERY_NOT_LOW);
- js.removeDynamicConstraint(JobStatus.CONSTRAINT_CHARGING);
- js.removeDynamicConstraint(JobStatus.CONSTRAINT_CONNECTIVITY);
- js.removeDynamicConstraint(JobStatus.CONSTRAINT_IDLE);
-
mRestrictiveControllers.get(j).stopTrackingRestrictedJobLocked(js);
}
}
@@ -1738,19 +1709,6 @@ public class JobSchedulerService extends com.android.server.SystemService
final int backoffAttempts = failureToReschedule.getNumFailures() + 1;
long delayMillis;
- if (failureToReschedule.hasWorkLocked()) {
- if (backoffAttempts > mConstants.MAX_WORK_RESCHEDULE_COUNT) {
- Slog.w(TAG, "Not rescheduling " + failureToReschedule + ": attempt #"
- + backoffAttempts + " > work limit "
- + mConstants.MAX_STANDARD_RESCHEDULE_COUNT);
- return null;
- }
- } else if (backoffAttempts > mConstants.MAX_STANDARD_RESCHEDULE_COUNT) {
- Slog.w(TAG, "Not rescheduling " + failureToReschedule + ": attempt #"
- + backoffAttempts + " > std limit " + mConstants.MAX_STANDARD_RESCHEDULE_COUNT);
- return null;
- }
-
switch (job.getBackoffPolicy()) {
case JobInfo.BACKOFF_POLICY_LINEAR: {
long backoff = initialBackoffMillis;
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
index f706260edec2..1e89158ca4bb 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
@@ -17,6 +17,8 @@
package com.android.server.job.controllers;
import static com.android.server.job.JobSchedulerService.ACTIVE_INDEX;
+import static com.android.server.job.JobSchedulerService.NEVER_INDEX;
+import static com.android.server.job.JobSchedulerService.RESTRICTED_INDEX;
import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
import android.app.AppGlobals;
@@ -63,26 +65,36 @@ import java.util.function.Predicate;
* @hide
*/
public final class JobStatus {
- static final String TAG = "JobSchedulerService";
+ private static final String TAG = "JobScheduler.JobStatus";
static final boolean DEBUG = JobSchedulerService.DEBUG;
public static final long NO_LATEST_RUNTIME = Long.MAX_VALUE;
public static final long NO_EARLIEST_RUNTIME = 0L;
- public static final int CONSTRAINT_CHARGING = JobInfo.CONSTRAINT_FLAG_CHARGING; // 1 < 0
- public static final int CONSTRAINT_IDLE = JobInfo.CONSTRAINT_FLAG_DEVICE_IDLE; // 1 << 2
- public static final int CONSTRAINT_BATTERY_NOT_LOW =
- JobInfo.CONSTRAINT_FLAG_BATTERY_NOT_LOW; // 1 << 1
+ static final int CONSTRAINT_CHARGING = JobInfo.CONSTRAINT_FLAG_CHARGING; // 1 < 0
+ static final int CONSTRAINT_IDLE = JobInfo.CONSTRAINT_FLAG_DEVICE_IDLE; // 1 << 2
+ static final int CONSTRAINT_BATTERY_NOT_LOW = JobInfo.CONSTRAINT_FLAG_BATTERY_NOT_LOW; // 1 << 1
static final int CONSTRAINT_STORAGE_NOT_LOW = JobInfo.CONSTRAINT_FLAG_STORAGE_NOT_LOW; // 1 << 3
static final int CONSTRAINT_TIMING_DELAY = 1<<31;
static final int CONSTRAINT_DEADLINE = 1<<30;
- public static final int CONSTRAINT_CONNECTIVITY = 1 << 28;
+ static final int CONSTRAINT_CONNECTIVITY = 1 << 28;
static final int CONSTRAINT_CONTENT_TRIGGER = 1<<26;
static final int CONSTRAINT_DEVICE_NOT_DOZING = 1 << 25; // Implicit constraint
static final int CONSTRAINT_WITHIN_QUOTA = 1 << 24; // Implicit constraint
static final int CONSTRAINT_BACKGROUND_NOT_RESTRICTED = 1 << 22; // Implicit constraint
/**
+ * The additional set of dynamic constraints that must be met if the job's effective bucket is
+ * {@link JobSchedulerService#RESTRICTED_INDEX}. Connectivity can be ignored if the job doesn't
+ * need network.
+ */
+ private static final int DYNAMIC_RESTRICTED_CONSTRAINTS =
+ CONSTRAINT_BATTERY_NOT_LOW
+ | CONSTRAINT_CHARGING
+ | CONSTRAINT_CONNECTIVITY
+ | CONSTRAINT_IDLE;
+
+ /**
* The constraints that we want to log to statsd.
*
* Constraints that can be inferred from other atoms have been excluded to avoid logging too
@@ -419,7 +431,11 @@ public final class JobStatus {
this.requiredConstraints = requiredConstraints;
mRequiredConstraintsOfInterest = requiredConstraints & CONSTRAINTS_OF_INTEREST;
mReadyNotDozing = (job.getFlags() & JobInfo.FLAG_WILL_BE_FOREGROUND) != 0;
- mReadyDynamicSatisfied = true;
+ if (standbyBucket == RESTRICTED_INDEX) {
+ addDynamicConstraints(DYNAMIC_RESTRICTED_CONSTRAINTS);
+ } else {
+ mReadyDynamicSatisfied = true;
+ }
mLastSuccessfulRunTime = lastSuccessfulRunTime;
mLastFailedRunTime = lastFailedRunTime;
@@ -727,6 +743,14 @@ public final class JobStatus {
}
public void setStandbyBucket(int newBucket) {
+ if (newBucket == RESTRICTED_INDEX) {
+ // Adding to the bucket.
+ addDynamicConstraints(DYNAMIC_RESTRICTED_CONSTRAINTS);
+ } else if (standbyBucket == RESTRICTED_INDEX) {
+ // Removing from the RESTRICTED bucket.
+ removeDynamicConstraints(DYNAMIC_RESTRICTED_CONSTRAINTS);
+ }
+
standbyBucket = newBucket;
}
@@ -1054,6 +1078,11 @@ public final class JobStatus {
if (old == state) {
return false;
}
+ if (DEBUG) {
+ Slog.v(TAG,
+ "Constraint " + constraint + " is " + (!state ? "NOT " : "") + "satisfied for "
+ + toShortString());
+ }
satisfiedConstraints = (satisfiedConstraints&~constraint) | (state ? constraint : 0);
mSatisfiedConstraintsOfInterest = satisfiedConstraints & CONSTRAINTS_OF_INTEREST;
mReadyDynamicSatisfied =
@@ -1086,38 +1115,40 @@ public final class JobStatus {
}
/**
- * Indicates that this job cannot run without the specified constraint. This is evaluated
+ * Indicates that this job cannot run without the specified constraints. This is evaluated
* separately from the job's explicitly requested constraints and MUST be satisfied before
* the job can run if the app doesn't have quota.
- *
*/
- public void addDynamicConstraint(int constraint) {
- if (constraint == CONSTRAINT_WITHIN_QUOTA) {
+ private void addDynamicConstraints(int constraints) {
+ if ((constraints & CONSTRAINT_WITHIN_QUOTA) != 0) {
+ // Quota should never be used as a dynamic constraint.
Slog.wtf(TAG, "Tried to set quota as a dynamic constraint");
- return;
+ constraints &= ~CONSTRAINT_WITHIN_QUOTA;
}
// Connectivity and content trigger are special since they're only valid to add if the
// job has requested network or specific content URIs. Adding these constraints to jobs
// that don't need them doesn't make sense.
- if ((constraint == CONSTRAINT_CONNECTIVITY && !hasConnectivityConstraint())
- || (constraint == CONSTRAINT_CONTENT_TRIGGER && !hasContentTriggerConstraint())) {
- return;
+ if (!hasConnectivityConstraint()) {
+ constraints &= ~CONSTRAINT_CONNECTIVITY;
+ }
+ if (!hasContentTriggerConstraint()) {
+ constraints &= ~CONSTRAINT_CONTENT_TRIGGER;
}
- mDynamicConstraints |= constraint;
+ mDynamicConstraints |= constraints;
mReadyDynamicSatisfied =
mDynamicConstraints == (satisfiedConstraints & mDynamicConstraints);
}
/**
- * Removes a dynamic constraint from a job, meaning that the requirement is not required for
+ * Removes dynamic constraints from a job, meaning that the requirements are not required for
* the job to run (if the job itself hasn't requested the constraint. This is separate from
* the job's explicitly requested constraints and does not remove those requested constraints.
*
*/
- public void removeDynamicConstraint(int constraint) {
- mDynamicConstraints &= ~constraint;
+ private void removeDynamicConstraints(int constraints) {
+ mDynamicConstraints &= ~constraints;
mReadyDynamicSatisfied =
mDynamicConstraints == (satisfiedConstraints & mDynamicConstraints);
}
@@ -1193,7 +1224,11 @@ public final class JobStatus {
private boolean isReady(int satisfiedConstraints) {
// Quota and dynamic constraints trump all other constraints.
- if (!mReadyWithinQuota && !mReadyDynamicSatisfied) {
+ // NEVER jobs are not supposed to run at all. Since we're using quota to allow parole
+ // sessions (exempt from dynamic restrictions), we need the additional check to ensure
+ // that NEVER jobs don't run.
+ // TODO: cleanup quota and standby bucket management so we don't need the additional checks
+ if ((!mReadyWithinQuota && !mReadyDynamicSatisfied) || standbyBucket == NEVER_INDEX) {
return false;
}
// Deadline constraint trumps other constraints besides quota and dynamic (except for
diff --git a/apex/permission/testing/Android.bp b/apex/permission/testing/Android.bp
index f8978dcd83ee..63bf0a08e956 100644
--- a/apex/permission/testing/Android.bp
+++ b/apex/permission/testing/Android.bp
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-apex {
+apex_test {
name: "test_com.android.permission",
visibility: [
"//system/apex/tests",
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableViewController.java b/apex/sdkextensions/framework/java/android/os/ext/test/Test.java
index e14ca8c4e590..1715f498be1e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableViewController.java
+++ b/apex/sdkextensions/framework/java/android/os/ext/test/Test.java
@@ -14,24 +14,40 @@
* limitations under the License.
*/
-package com.android.systemui.statusbar.notification.row;
+package android.os.ext.test;
-import javax.inject.Inject;
+import android.annotation.SystemApi;
/**
- * Controller for {@link ExpandableView}.
+ * This class exists temporarily to verify SDK updates are working properly.
+ * @deprecated Do not use.
*/
-public class ExpandableViewController {
- private final ExpandableView mView;
-
- @Inject
- public ExpandableViewController(ExpandableView view) {
- mView = view;
- }
-
- /**
- * Initialize the controller.
- */
- public void init() {
- }
+@Deprecated
+public class Test {
+
+ public Test() { }
+
+ /** @hide */
+ public void testA() {}
+
+ /** @hide */
+ public void testB() {}
+
+ /** @hide */
+ public void testC() {}
+
+ /** @hide */
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ public void testD() {}
+
+ public void testE() {}
+
+ /** @hide */
+ @SystemApi
+ public void testF() {}
+
+ /** @hide */
+ @SystemApi
+ public void testG() {}
+
}
diff --git a/apex/statsd/aidl/Android.bp b/apex/statsd/aidl/Android.bp
index 6d639fddd043..db5f439cd40e 100644
--- a/apex/statsd/aidl/Android.bp
+++ b/apex/statsd/aidl/Android.bp
@@ -13,35 +13,31 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//
-
-// TODO(b/145815909): move StatsDimensionsValue.aidl here
filegroup {
- name: "statsd_aidl",
+ name: "statsd_java_aidl",
+ srcs: ["**/*.aidl"],
+}
+
+aidl_interface {
+ name: "statsd-aidl",
srcs: [
"android/os/IPendingIntentRef.aidl",
"android/os/IPullAtomCallback.aidl",
"android/os/IPullAtomResultReceiver.aidl",
"android/os/IStatsCompanionService.aidl",
"android/os/IStatsd.aidl",
+ "android/os/StatsDimensionsValueParcel.aidl",
"android/util/StatsEventParcel.aidl",
],
-}
-
-filegroup {
- name: "statsd_java_aidl",
- srcs: ["**/*.aidl"],
-}
-
-// This library is currently unused
-aidl_interface {
- name: "stats-event-parcel-aidl",
- srcs: ["android/util/StatsEventParcel.aidl"],
backend: {
java: {
- sdk_version: "28",
+ enabled: false, // the platform uses statsd_java_aidl
},
cpp: {
- enabled: false,
+ enabled: true,
+ },
+ ndk: {
+ enabled: true,
}
}
}
diff --git a/apex/statsd/aidl/android/os/IPendingIntentRef.aidl b/apex/statsd/aidl/android/os/IPendingIntentRef.aidl
index 6b9e467a7e15..000a69992a49 100644
--- a/apex/statsd/aidl/android/os/IPendingIntentRef.aidl
+++ b/apex/statsd/aidl/android/os/IPendingIntentRef.aidl
@@ -16,7 +16,7 @@
package android.os;
-import android.os.StatsDimensionsValue;
+import android.os.StatsDimensionsValueParcel;
/**
* Binder interface to hold a PendingIntent for StatsCompanionService.
@@ -42,5 +42,5 @@ interface IPendingIntentRef {
*/
oneway void sendSubscriberBroadcast(long configUid, long configId, long subscriptionId,
long subscriptionRuleId, in String[] cookies,
- in StatsDimensionsValue dimensionsValue);
-} \ No newline at end of file
+ in StatsDimensionsValueParcel dimensionsValueParcel);
+}
diff --git a/apex/statsd/aidl/android/os/StatsDimensionsValueParcel.aidl b/apex/statsd/aidl/android/os/StatsDimensionsValueParcel.aidl
new file mode 100644
index 000000000000..a8685e34dd52
--- /dev/null
+++ b/apex/statsd/aidl/android/os/StatsDimensionsValueParcel.aidl
@@ -0,0 +1,21 @@
+package android.os;
+
+/**
+ * @hide
+ */
+parcelable StatsDimensionsValueParcel {
+ /**
+ * Field equals:
+ * - atomTag for top level StatsDimensionsValueParcel
+ * - position in dimension for all other levels
+ */
+ int field;
+ int valueType;
+
+ String stringValue;
+ int intValue;
+ long longValue;
+ boolean boolValue;
+ float floatValue;
+ StatsDimensionsValueParcel[] tupleValue;
+}
diff --git a/apex/statsd/framework/java/android/os/StatsDimensionsValue.java b/apex/statsd/framework/java/android/os/StatsDimensionsValue.java
index 886130fc5f14..71d43599fc82 100644
--- a/apex/statsd/framework/java/android/os/StatsDimensionsValue.java
+++ b/apex/statsd/framework/java/android/os/StatsDimensionsValue.java
@@ -96,6 +96,47 @@ public final class StatsDimensionsValue implements Parcelable {
}
/**
+ * Creates a {@code StatsDimensionsValue} from a StatsDimensionsValueParcel
+ * TODO(b/149103391): Make StatsDimensionsValue a wrapper on top of
+ * StatsDimensionsValueParcel.
+ *
+ * @hide
+ */
+ public StatsDimensionsValue(StatsDimensionsValueParcel parcel) {
+ mField = parcel.field;
+ mValueType = parcel.valueType;
+ switch (mValueType) {
+ case STRING_VALUE_TYPE:
+ mValue = parcel.stringValue;
+ break;
+ case INT_VALUE_TYPE:
+ mValue = parcel.intValue;
+ break;
+ case LONG_VALUE_TYPE:
+ mValue = parcel.longValue;
+ break;
+ case BOOLEAN_VALUE_TYPE:
+ mValue = parcel.boolValue;
+ break;
+ case FLOAT_VALUE_TYPE:
+ mValue = parcel.floatValue;
+ break;
+ case TUPLE_VALUE_TYPE:
+ StatsDimensionsValue[] values = new StatsDimensionsValue[parcel.tupleValue.length];
+ for (int i = 0; i < parcel.tupleValue.length; i++) {
+ values[i] = new StatsDimensionsValue(parcel.tupleValue[i]);
+ }
+ mValue = values;
+ break;
+ default:
+ Slog.w(TAG, "StatsDimensionsValueParcel contains bad valueType: " + mValueType);
+ mValue = null;
+ break;
+ }
+ }
+
+
+ /**
* Return the field, i.e. the tag of a statsd atom.
*
* @return the field
diff --git a/apex/statsd/service/java/com/android/server/stats/StatsCompanion.java b/apex/statsd/service/java/com/android/server/stats/StatsCompanion.java
index 4495dc9de71e..7cc6760f307b 100644
--- a/apex/statsd/service/java/com/android/server/stats/StatsCompanion.java
+++ b/apex/statsd/service/java/com/android/server/stats/StatsCompanion.java
@@ -24,6 +24,7 @@ import android.os.Binder;
import android.os.IPendingIntentRef;
import android.os.Process;
import android.os.StatsDimensionsValue;
+import android.os.StatsDimensionsValueParcel;
import android.util.Slog;
import com.android.server.SystemService;
@@ -145,8 +146,10 @@ public class StatsCompanion {
@Override
public void sendSubscriberBroadcast(long configUid, long configId, long subscriptionId,
- long subscriptionRuleId, String[] cookies, StatsDimensionsValue dimensionsValue) {
+ long subscriptionRuleId, String[] cookies,
+ StatsDimensionsValueParcel dimensionsValueParcel) {
enforceStatsdCallingUid();
+ StatsDimensionsValue dimensionsValue = new StatsDimensionsValue(dimensionsValueParcel);
Intent intent =
new Intent()
.putExtra(StatsManager.EXTRA_STATS_CONFIG_UID, configUid)
diff --git a/apex/statsd/testing/Android.bp b/apex/statsd/testing/Android.bp
index 22e73015ba39..a9cd0ccb53e8 100644
--- a/apex/statsd/testing/Android.bp
+++ b/apex/statsd/testing/Android.bp
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-apex {
+apex_test {
name: "test_com.android.os.statsd",
visibility: [
"//system/apex/tests",
diff --git a/api/current.txt b/api/current.txt
index 294384055252..977dcde6a072 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -4015,7 +4015,7 @@ package android.app {
method public android.util.Size getAppTaskThumbnailSize();
method public java.util.List<android.app.ActivityManager.AppTask> getAppTasks();
method public android.content.pm.ConfigurationInfo getDeviceConfigurationInfo();
- method @Nullable public java.util.List<android.app.ApplicationExitInfo> getHistoricalProcessExitReasons(@Nullable String, @IntRange(from=0) int, @IntRange(from=0) int);
+ method @NonNull public java.util.List<android.app.ApplicationExitInfo> getHistoricalProcessExitReasons(@Nullable String, @IntRange(from=0) int, @IntRange(from=0) int);
method public int getLargeMemoryClass();
method public int getLauncherLargeIconDensity();
method public int getLauncherLargeIconSize();
@@ -4555,12 +4555,13 @@ package android.app {
method public int getPackageUid();
method public int getPid();
method @NonNull public String getProcessName();
- method public int getPss();
+ method public long getPss();
method public int getRealUid();
method public int getReason();
- method public int getRss();
+ method public long getRss();
method public int getStatus();
method public long getTimestamp();
+ method @NonNull public android.os.UserHandle getUserHandle();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.app.ApplicationExitInfo> CREATOR;
field public static final int REASON_ANR = 6; // 0x6
@@ -30779,7 +30780,6 @@ package android.net.sip {
method public void close();
method public void continueCall(int) throws android.net.sip.SipException;
method public void endCall() throws android.net.sip.SipException;
- method @Nullable public android.net.rtp.AudioGroup getAudioGroup();
method public android.net.sip.SipProfile getLocalProfile();
method public android.net.sip.SipProfile getPeerProfile();
method public int getState();
@@ -30790,7 +30790,6 @@ package android.net.sip {
method public void makeCall(android.net.sip.SipProfile, android.net.sip.SipSession, int) throws android.net.sip.SipException;
method public void sendDtmf(int);
method public void sendDtmf(int, android.os.Message);
- method public void setAudioGroup(@NonNull android.net.rtp.AudioGroup);
method public void setListener(android.net.sip.SipAudioCall.Listener);
method public void setListener(android.net.sip.SipAudioCall.Listener, boolean);
method public void setSpeakerMode(boolean);
@@ -30839,7 +30838,6 @@ package android.net.sip {
method public void close(String) throws android.net.sip.SipException;
method public android.net.sip.SipSession createSipSession(android.net.sip.SipProfile, android.net.sip.SipSession.Listener) throws android.net.sip.SipException;
method public static String getCallId(android.content.Intent);
- method @NonNull public java.util.List<android.net.sip.SipProfile> getListOfProfiles() throws android.net.sip.SipException;
method public static String getOfferSessionDescription(android.content.Intent);
method public android.net.sip.SipSession getSessionFor(android.content.Intent) throws android.net.sip.SipException;
method public static boolean isApiSupported(android.content.Context);
@@ -30857,11 +30855,6 @@ package android.net.sip {
method public void setRegistrationListener(String, android.net.sip.SipRegistrationListener) throws android.net.sip.SipException;
method public android.net.sip.SipAudioCall takeAudioCall(android.content.Intent, android.net.sip.SipAudioCall.Listener) throws android.net.sip.SipException;
method public void unregister(android.net.sip.SipProfile, android.net.sip.SipRegistrationListener) throws android.net.sip.SipException;
- field public static final String ACTION_SIP_CALL_OPTION_CHANGED = "android.net.sip.action.SIP_CALL_OPTION_CHANGED";
- field public static final String ACTION_SIP_INCOMING_CALL = "android.net.sip.action.SIP_INCOMING_CALL";
- field public static final String ACTION_SIP_REMOVE_PROFILE = "android.net.sip.action.SIP_REMOVE_PROFILE";
- field public static final String ACTION_SIP_SERVICE_UP = "android.net.sip.action.SIP_SERVICE_UP";
- field public static final String ACTION_START_SIP = "android.net.sip.action.START_SIP";
field public static final String EXTRA_CALL_ID = "android:sipCallID";
field public static final String EXTRA_OFFER_SD = "android:sipOfferSD";
field public static final int INCOMING_CALL_RESULT_CODE = 101; // 0x65
@@ -30871,7 +30864,6 @@ package android.net.sip {
method public int describeContents();
method public String getAuthUserName();
method public boolean getAutoRegistration();
- method public int getCallingUid();
method public String getDisplayName();
method public String getPassword();
method public int getPort();
@@ -37046,6 +37038,15 @@ package android.os {
}
+package android.os.ext.test {
+
+ @Deprecated public class Test {
+ ctor @Deprecated public Test();
+ method @Deprecated public void testE();
+ }
+
+}
+
package android.os.health {
public class HealthStats {
@@ -43995,7 +43996,7 @@ package android.service.quicksettings {
field public static final String ACTION_QS_TILE = "android.service.quicksettings.action.QS_TILE";
field public static final String ACTION_QS_TILE_PREFERENCES = "android.service.quicksettings.action.QS_TILE_PREFERENCES";
field public static final String META_DATA_ACTIVE_TILE = "android.service.quicksettings.ACTIVE_TILE";
- field public static final String META_DATA_BOOLEAN_TILE = "android.service.quicksettings.BOOLEAN_TILE";
+ field public static final String META_DATA_TOGGLEABLE_TILE = "android.service.quicksettings.TOGGLEABLE_TILE";
}
}
@@ -47312,7 +47313,7 @@ package android.telephony {
method public void onSignalStrengthsChanged(android.telephony.SignalStrength);
method public void onUserMobileDataStateChanged(boolean);
field public static final int LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE = 4194304; // 0x400000
- field @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public static final int LISTEN_BARRING_INFO = -2147483648; // 0x80000000
+ field @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public static final int LISTEN_BARRING_INFO = -2147483648; // 0x80000000
field @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public static final int LISTEN_CALL_DISCONNECT_CAUSES = 33554432; // 0x2000000
field public static final int LISTEN_CALL_FORWARDING_INDICATOR = 8; // 0x8
field public static final int LISTEN_CALL_STATE = 32; // 0x20
@@ -47325,7 +47326,7 @@ package android.telephony {
field public static final int LISTEN_MESSAGE_WAITING_INDICATOR = 4; // 0x4
field public static final int LISTEN_NONE = 0; // 0x0
field @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public static final int LISTEN_PRECISE_DATA_CONNECTION_STATE = 4096; // 0x1000
- field @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public static final int LISTEN_REGISTRATION_FAILURE = 1073741824; // 0x40000000
+ field @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public static final int LISTEN_REGISTRATION_FAILURE = 1073741824; // 0x40000000
field public static final int LISTEN_SERVICE_STATE = 1; // 0x1
field @Deprecated public static final int LISTEN_SIGNAL_STRENGTH = 2; // 0x2
field public static final int LISTEN_SIGNAL_STRENGTHS = 256; // 0x100
@@ -60889,7 +60890,7 @@ package android.widget {
method public int getGravity();
method public float getHorizontalMargin();
method public float getVerticalMargin();
- method @Deprecated public android.view.View getView();
+ method @Deprecated @Nullable public android.view.View getView();
method public int getXOffset();
method public int getYOffset();
method public static android.widget.Toast makeText(android.content.Context, CharSequence, int);
diff --git a/api/module-lib-current.txt b/api/module-lib-current.txt
index 8100b07c31e3..59aa145ce1e9 100644
--- a/api/module-lib-current.txt
+++ b/api/module-lib-current.txt
@@ -120,6 +120,14 @@ package android.net {
}
+package android.os.ext.test {
+
+ @Deprecated public class Test {
+ method @Deprecated public void testD();
+ }
+
+}
+
package android.util {
public final class Log {
diff --git a/api/system-current.txt b/api/system-current.txt
index df7198aa2028..24936d5784f8 100755
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -585,10 +585,6 @@ package android.app {
field @NonNull public static final android.os.Parcelable.Creator<android.app.AppOpsManager.PackageOps> CREATOR;
}
- public final class ApplicationExitInfo implements android.os.Parcelable {
- method @NonNull public android.os.UserHandle getUserHandle();
- }
-
public class BroadcastOptions {
method public static android.app.BroadcastOptions makeBasic();
method @RequiresPermission("android.permission.START_ACTIVITIES_FROM_BACKGROUND") public void setBackgroundActivityStartsAllowed(boolean);
@@ -3866,6 +3862,20 @@ package android.location {
method @NonNull public android.location.GnssReflectingPlane.Builder setLongitudeDegrees(@FloatRange(from=-180.0F, to=180.0f) double);
}
+ public final class GnssRequest implements android.os.Parcelable {
+ method public int describeContents();
+ method public boolean isFullTracking();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssRequest> CREATOR;
+ }
+
+ public static final class GnssRequest.Builder {
+ ctor public GnssRequest.Builder();
+ ctor public GnssRequest.Builder(@NonNull android.location.GnssRequest);
+ method @NonNull public android.location.GnssRequest build();
+ method @NonNull public android.location.GnssRequest.Builder setFullTracking(boolean);
+ }
+
public final class GnssSingleSatCorrection implements android.os.Parcelable {
method public int describeContents();
method @FloatRange(from=0.0f, fromInclusive=false) public float getCarrierFrequencyHz();
@@ -4139,6 +4149,7 @@ package android.location {
method public boolean isProviderEnabledForUser(@NonNull String, @NonNull android.os.UserHandle);
method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public boolean isProviderPackage(@NonNull String);
method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public boolean registerGnssBatchedLocationCallback(long, boolean, @NonNull android.location.BatchedLocationCallback, @Nullable android.os.Handler);
+ method @RequiresPermission(allOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.LOCATION_HARDWARE}) public boolean registerGnssMeasurementsCallback(@NonNull android.location.GnssRequest, @NonNull java.util.concurrent.Executor, @NonNull android.location.GnssMeasurementsEvent.Callback);
method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@Nullable android.location.LocationRequest, @NonNull android.location.LocationListener, @Nullable android.os.Looper);
method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@Nullable android.location.LocationRequest, @NonNull java.util.concurrent.Executor, @NonNull android.location.LocationListener);
method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@Nullable android.location.LocationRequest, @NonNull android.app.PendingIntent);
@@ -5746,7 +5757,6 @@ package android.media.tv.tuner.frontend {
method public int getFreqOffset();
method public int getHierarchy();
method @NonNull public boolean[] getLayerErrors();
- method public int getLberCn();
method public int getLnbVoltage();
method public int getMer();
method public int getModulation();
@@ -5758,37 +5768,32 @@ package android.media.tv.tuner.frontend {
method public int getSnr();
method public int getSpectralInversion();
method public int getSymbolRate();
- method public int getVberCn();
- method public int getXerCn();
method public boolean isDemodLocked();
method public boolean isEwbs();
method public boolean isLnaOn();
method public boolean isRfLock();
field public static final int FRONTEND_STATUS_TYPE_AGC = 14; // 0xe
- field public static final int FRONTEND_STATUS_TYPE_ATSC3_PLP_INFO = 24; // 0x18
+ field public static final int FRONTEND_STATUS_TYPE_ATSC3_PLP_INFO = 21; // 0x15
field public static final int FRONTEND_STATUS_TYPE_BER = 2; // 0x2
field public static final int FRONTEND_STATUS_TYPE_DEMOD_LOCK = 0; // 0x0
field public static final int FRONTEND_STATUS_TYPE_EWBS = 13; // 0xd
field public static final int FRONTEND_STATUS_TYPE_FEC = 8; // 0x8
- field public static final int FRONTEND_STATUS_TYPE_FREQ_OFFSET = 21; // 0x15
- field public static final int FRONTEND_STATUS_TYPE_HIERARCHY = 22; // 0x16
+ field public static final int FRONTEND_STATUS_TYPE_FREQ_OFFSET = 18; // 0x12
+ field public static final int FRONTEND_STATUS_TYPE_HIERARCHY = 19; // 0x13
field public static final int FRONTEND_STATUS_TYPE_LAYER_ERROR = 16; // 0x10
- field public static final int FRONTEND_STATUS_TYPE_LBER_CN = 18; // 0x12
field public static final int FRONTEND_STATUS_TYPE_LNA = 15; // 0xf
field public static final int FRONTEND_STATUS_TYPE_LNB_VOLTAGE = 11; // 0xb
- field public static final int FRONTEND_STATUS_TYPE_MER = 20; // 0x14
+ field public static final int FRONTEND_STATUS_TYPE_MER = 17; // 0x11
field public static final int FRONTEND_STATUS_TYPE_MODULATION = 9; // 0x9
field public static final int FRONTEND_STATUS_TYPE_PER = 3; // 0x3
field public static final int FRONTEND_STATUS_TYPE_PLP_ID = 12; // 0xc
field public static final int FRONTEND_STATUS_TYPE_PRE_BER = 4; // 0x4
- field public static final int FRONTEND_STATUS_TYPE_RF_LOCK = 23; // 0x17
+ field public static final int FRONTEND_STATUS_TYPE_RF_LOCK = 20; // 0x14
field public static final int FRONTEND_STATUS_TYPE_SIGNAL_QUALITY = 5; // 0x5
field public static final int FRONTEND_STATUS_TYPE_SIGNAL_STRENGTH = 6; // 0x6
field public static final int FRONTEND_STATUS_TYPE_SNR = 1; // 0x1
field public static final int FRONTEND_STATUS_TYPE_SPECTRAL = 10; // 0xa
field public static final int FRONTEND_STATUS_TYPE_SYMBOL_RATE = 7; // 0x7
- field public static final int FRONTEND_STATUS_TYPE_VBER_CN = 17; // 0x11
- field public static final int FRONTEND_STATUS_TYPE_XER_CN = 19; // 0x13
}
public static class FrontendStatus.Atsc3PlpInfo {
@@ -7210,6 +7215,28 @@ package android.net.netstats.provider {
}
+package android.net.sip {
+
+ public class SipAudioCall {
+ method @Nullable public android.net.rtp.AudioGroup getAudioGroup();
+ method public void setAudioGroup(@NonNull android.net.rtp.AudioGroup);
+ }
+
+ public class SipManager {
+ method @NonNull public java.util.List<android.net.sip.SipProfile> getProfiles() throws android.net.sip.SipException;
+ field public static final String ACTION_SIP_CALL_OPTION_CHANGED = "android.net.sip.action.SIP_CALL_OPTION_CHANGED";
+ field public static final String ACTION_SIP_INCOMING_CALL = "android.net.sip.action.SIP_INCOMING_CALL";
+ field public static final String ACTION_SIP_REMOVE_PROFILE = "android.net.sip.action.SIP_REMOVE_PROFILE";
+ field public static final String ACTION_SIP_SERVICE_UP = "android.net.sip.action.SIP_SERVICE_UP";
+ field public static final String ACTION_START_SIP = "android.net.sip.action.START_SIP";
+ }
+
+ public class SipProfile implements java.lang.Cloneable android.os.Parcelable java.io.Serializable {
+ method public int getCallingUid();
+ }
+
+}
+
package android.net.util {
public final class SocketUtils {
@@ -9146,6 +9173,15 @@ package android.os.ext {
}
+package android.os.ext.test {
+
+ @Deprecated public class Test {
+ method @Deprecated public void testF();
+ method @Deprecated public void testG();
+ }
+
+}
+
package android.os.image {
public class DynamicSystemClient {
@@ -14131,6 +14167,10 @@ package android.view.contentcapture {
method public boolean isContentCaptureFeatureEnabled();
}
+ public abstract class ContentCaptureSession implements java.lang.AutoCloseable {
+ field public static final int NO_SESSION_ID = 0; // 0x0
+ }
+
public final class ViewNode extends android.app.assist.AssistStructure.ViewNode {
method @Nullable public android.view.autofill.AutofillId getParentAutofillId();
}
diff --git a/api/test-current.txt b/api/test-current.txt
index e1f83822609d..e352cb65156e 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -923,6 +923,7 @@ package android.content.pm {
field public static final int FLAG_PERMISSION_USER_SET = 1; // 0x1
field public static final int MATCH_FACTORY_ONLY = 2097152; // 0x200000
field public static final int MATCH_KNOWN_PACKAGES = 4202496; // 0x402000
+ field public static final int MODULE_APEX_NAME = 1; // 0x1
field public static final String SYSTEM_SHARED_LIBRARY_SERVICES = "android.ext.services";
field public static final String SYSTEM_SHARED_LIBRARY_SHARED = "android.ext.shared";
}
@@ -2539,6 +2540,7 @@ package android.os {
}
public class UserManager {
+ method @RequiresPermission(anyOf={"android.permission.MANAGE_USERS", "android.permission.CREATE_USERS"}) public boolean hasBaseUserRestriction(@NonNull String, @NonNull android.os.UserHandle);
method public static boolean isSplitSystemUser();
field public static final String ACTION_USER_RESTRICTIONS_CHANGED = "android.os.action.USER_RESTRICTIONS_CHANGED";
}
diff --git a/cmds/statsd/Android.bp b/cmds/statsd/Android.bp
index 7e069a6b4372..956fd29205cb 100644
--- a/cmds/statsd/Android.bp
+++ b/cmds/statsd/Android.bp
@@ -44,12 +44,8 @@ cc_library_host_shared {
cc_defaults {
name: "statsd_defaults",
- aidl: {
- include_dirs: ["frameworks/base/core/java"],
- },
srcs: [
- ":statsd_aidl",
"src/active_config_list.proto",
"src/anomaly/AlarmMonitor.cpp",
"src/anomaly/AlarmTracker.cpp",
@@ -124,14 +120,14 @@ cc_defaults {
"libstatslog",
"libstatsmetadata",
"libsysutils",
+ "libutils",
],
shared_libs: [
"libbinder",
"libincident",
"liblog",
- "libservices",
"libstatssocket",
- "libutils",
+ "statsd-aidl-cpp",
],
}
diff --git a/cmds/statsd/src/HashableDimensionKey.cpp b/cmds/statsd/src/HashableDimensionKey.cpp
index 5b75b97a0764..6b9d0e4fdac0 100644
--- a/cmds/statsd/src/HashableDimensionKey.cpp
+++ b/cmds/statsd/src/HashableDimensionKey.cpp
@@ -26,6 +26,86 @@ namespace statsd {
using std::string;
using std::vector;
+// These constants must be kept in sync with those in StatsDimensionsValue.java
+const static int STATS_DIMENSIONS_VALUE_STRING_TYPE = 2;
+const static int STATS_DIMENSIONS_VALUE_INT_TYPE = 3;
+const static int STATS_DIMENSIONS_VALUE_LONG_TYPE = 4;
+// const static int STATS_DIMENSIONS_VALUE_BOOL_TYPE = 5; (commented out because
+// unused -- statsd does not correctly support bool types)
+const static int STATS_DIMENSIONS_VALUE_FLOAT_TYPE = 6;
+const static int STATS_DIMENSIONS_VALUE_TUPLE_TYPE = 7;
+
+/**
+ * Recursive helper function that populates a parent StatsDimensionsValueParcel
+ * with children StatsDimensionsValueParcels.
+ *
+ * \param dims vector of FieldValues stored by HashableDimensionKey
+ * \param index positions in dims vector to start reading children from
+ * \param depth level of parent parcel in the full StatsDimensionsValueParcel
+ * tree
+ */
+static void populateStatsDimensionsValueParcelChildren(StatsDimensionsValueParcel &parentParcel,
+ const vector<FieldValue>& dims, size_t& index,
+ int depth, int prefix) {
+ while (index < dims.size()) {
+ const FieldValue& dim = dims[index];
+ int fieldDepth = dim.mField.getDepth();
+ int fieldPrefix = dim.mField.getPrefix(depth);
+ StatsDimensionsValueParcel childParcel;
+ childParcel.field = dim.mField.getPosAtDepth(depth);
+ if (depth > 2) {
+ ALOGE("Depth > 2 not supported by StatsDimensionsValueParcel.");
+ return;
+ }
+ if (depth == fieldDepth && prefix == fieldPrefix) {
+ switch (dim.mValue.getType()) {
+ case INT:
+ childParcel.valueType = STATS_DIMENSIONS_VALUE_INT_TYPE;
+ childParcel.intValue = dim.mValue.int_value;
+ break;
+ case LONG:
+ childParcel.valueType = STATS_DIMENSIONS_VALUE_LONG_TYPE;
+ childParcel.longValue = dim.mValue.long_value;
+ break;
+ case FLOAT:
+ childParcel.valueType = STATS_DIMENSIONS_VALUE_FLOAT_TYPE;
+ childParcel.floatValue = dim.mValue.float_value;
+ break;
+ case STRING:
+ childParcel.valueType = STATS_DIMENSIONS_VALUE_STRING_TYPE;
+ childParcel.stringValue = String16(dim.mValue.str_value.c_str());
+ break;
+ default:
+ ALOGE("Encountered FieldValue with unsupported value type.");
+ break;
+ }
+ index++;
+ parentParcel.tupleValue.push_back(childParcel);
+ } else if (fieldDepth > depth && fieldPrefix == prefix) {
+ childParcel.valueType = STATS_DIMENSIONS_VALUE_TUPLE_TYPE;
+ populateStatsDimensionsValueParcelChildren(childParcel, dims, index, depth + 1,
+ dim.mField.getPrefix(depth + 1));
+ parentParcel.tupleValue.push_back(childParcel);
+ } else {
+ return;
+ }
+ }
+}
+
+StatsDimensionsValueParcel HashableDimensionKey::toStatsDimensionsValueParcel() const {
+ StatsDimensionsValueParcel parcel;
+ if (mValues.size() == 0) {
+ return parcel;
+ }
+
+ parcel.field = mValues[0].mField.getTag();
+ parcel.valueType = STATS_DIMENSIONS_VALUE_TUPLE_TYPE;
+
+ size_t index = 0;
+ populateStatsDimensionsValueParcelChildren(parcel, mValues, index, /*depth=*/0, /*prefix=*/0);
+ return parcel;
+}
+
android::hash_t hashDimension(const HashableDimensionKey& value) {
android::hash_t hash = 0;
for (const auto& fieldValue : value.getValues()) {
diff --git a/cmds/statsd/src/HashableDimensionKey.h b/cmds/statsd/src/HashableDimensionKey.h
index 654e1358f2a1..4adcf967555e 100644
--- a/cmds/statsd/src/HashableDimensionKey.h
+++ b/cmds/statsd/src/HashableDimensionKey.h
@@ -16,10 +16,11 @@
#pragma once
+#include <android/os/StatsDimensionsValueParcel.h>
#include <utils/JenkinsHash.h>
#include <vector>
-#include "FieldValue.h"
#include "android-base/stringprintf.h"
+#include "FieldValue.h"
#include "logd/LogEvent.h"
namespace android {
@@ -69,6 +70,8 @@ public:
return nullptr;
}
+ StatsDimensionsValueParcel toStatsDimensionsValueParcel() const;
+
std::string toString() const;
bool operator!=(const HashableDimensionKey& that) const;
diff --git a/cmds/statsd/src/subscriber/SubscriberReporter.cpp b/cmds/statsd/src/subscriber/SubscriberReporter.cpp
index 160b57e27c6c..8fd6b46d0716 100644
--- a/cmds/statsd/src/subscriber/SubscriberReporter.cpp
+++ b/cmds/statsd/src/subscriber/SubscriberReporter.cpp
@@ -121,7 +121,7 @@ void SubscriberReporter::sendBroadcastLocked(const sp<IPendingIntentRef>& pir,
subscription.id(),
subscription.rule_id(),
cookies,
- getStatsDimensionsValue(dimKey.getDimensionKeyInWhat()));
+ dimKey.getDimensionKeyInWhat().toStatsDimensionsValueParcel());
}
sp<IPendingIntentRef> SubscriberReporter::getBroadcastSubscriber(const ConfigKey& configKey,
@@ -138,61 +138,6 @@ sp<IPendingIntentRef> SubscriberReporter::getBroadcastSubscriber(const ConfigKey
return pirMapIt->second;
}
-void getStatsDimensionsValueHelper(const vector<FieldValue>& dims, size_t* index, int depth,
- int prefix, vector<StatsDimensionsValue>* output) {
- size_t count = dims.size();
- while (*index < count) {
- const auto& dim = dims[*index];
- const int valueDepth = dim.mField.getDepth();
- const int valuePrefix = dim.mField.getPrefix(depth);
- if (valueDepth > 2) {
- ALOGE("Depth > 2 not supported");
- return;
- }
- if (depth == valueDepth && valuePrefix == prefix) {
- switch (dim.mValue.getType()) {
- case INT:
- output->push_back(StatsDimensionsValue(dim.mField.getPosAtDepth(depth),
- dim.mValue.int_value));
- break;
- case LONG:
- output->push_back(StatsDimensionsValue(dim.mField.getPosAtDepth(depth),
- dim.mValue.long_value));
- break;
- case FLOAT:
- output->push_back(StatsDimensionsValue(dim.mField.getPosAtDepth(depth),
- dim.mValue.float_value));
- break;
- case STRING:
- output->push_back(StatsDimensionsValue(dim.mField.getPosAtDepth(depth),
- String16(dim.mValue.str_value.c_str())));
- break;
- default:
- break;
- }
- (*index)++;
- } else if (valueDepth > depth && valuePrefix == prefix) {
- vector<StatsDimensionsValue> childOutput;
- getStatsDimensionsValueHelper(dims, index, depth + 1, dim.mField.getPrefix(depth + 1),
- &childOutput);
- output->push_back(StatsDimensionsValue(dim.mField.getPosAtDepth(depth), childOutput));
- } else {
- return;
- }
- }
-}
-
-StatsDimensionsValue SubscriberReporter::getStatsDimensionsValue(const HashableDimensionKey& dim) {
- if (dim.getValues().size() == 0) {
- return StatsDimensionsValue();
- }
-
- vector<StatsDimensionsValue> fields;
- size_t index = 0;
- getStatsDimensionsValueHelper(dim.getValues(), &index, 0, 0, &fields);
- return StatsDimensionsValue(dim.getValues()[0].mField.getTag(), fields);
-}
-
} // namespace statsd
} // namespace os
} // namespace android
diff --git a/cmds/statsd/src/subscriber/SubscriberReporter.h b/cmds/statsd/src/subscriber/SubscriberReporter.h
index 087a1b84b91f..42599f508313 100644
--- a/cmds/statsd/src/subscriber/SubscriberReporter.h
+++ b/cmds/statsd/src/subscriber/SubscriberReporter.h
@@ -22,7 +22,6 @@
#include "config/ConfigKey.h"
#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h" // subscription
-#include "android/os/StatsDimensionsValue.h"
#include "HashableDimensionKey.h"
#include <mutex>
@@ -70,8 +69,6 @@ public:
sp<IPendingIntentRef> getBroadcastSubscriber(const ConfigKey& configKey, int64_t subscriberId);
- static StatsDimensionsValue getStatsDimensionsValue(const HashableDimensionKey& dim);
-
private:
SubscriberReporter() {};
diff --git a/cmds/statsd/tests/FieldValue_test.cpp b/cmds/statsd/tests/FieldValue_test.cpp
index f4a59ed14d10..9e69d977f351 100644
--- a/cmds/statsd/tests/FieldValue_test.cpp
+++ b/cmds/statsd/tests/FieldValue_test.cpp
@@ -290,33 +290,34 @@ TEST(AtomMatcherTest, TestWriteDimensionPath) {
}
}
-TEST(AtomMatcherTest, TestSubscriberDimensionWrite) {
- HashableDimensionKey dim;
-
- int pos1[] = {1, 1, 1};
- int pos2[] = {1, 1, 2};
- int pos3[] = {1, 1, 3};
- int pos4[] = {2, 0, 0};
-
- Field field1(10, pos1, 2);
- Field field2(10, pos2, 2);
- Field field3(10, pos3, 2);
- Field field4(10, pos4, 0);
-
- Value value1((int32_t)10025);
- Value value2("tag");
- Value value3((int32_t)987654);
- Value value4((int32_t)99999);
-
- dim.addValue(FieldValue(field1, value1));
- dim.addValue(FieldValue(field2, value2));
- dim.addValue(FieldValue(field3, value3));
- dim.addValue(FieldValue(field4, value4));
-
- SubscriberReporter::getStatsDimensionsValue(dim);
- // TODO(b/110562792): can't test anything here because StatsDimensionsValue class doesn't
- // have any read api.
-}
+//TODO(b/149050405) Update this test for StatsDimensionValueParcel
+//TEST(AtomMatcherTest, TestSubscriberDimensionWrite) {
+// HashableDimensionKey dim;
+//
+// int pos1[] = {1, 1, 1};
+// int pos2[] = {1, 1, 2};
+// int pos3[] = {1, 1, 3};
+// int pos4[] = {2, 0, 0};
+//
+// Field field1(10, pos1, 2);
+// Field field2(10, pos2, 2);
+// Field field3(10, pos3, 2);
+// Field field4(10, pos4, 0);
+//
+// Value value1((int32_t)10025);
+// Value value2("tag");
+// Value value3((int32_t)987654);
+// Value value4((int32_t)99999);
+//
+// dim.addValue(FieldValue(field1, value1));
+// dim.addValue(FieldValue(field2, value2));
+// dim.addValue(FieldValue(field3, value3));
+// dim.addValue(FieldValue(field4, value4));
+//
+// SubscriberReporter::getStatsDimensionsValue(dim);
+// // TODO(b/110562792): can't test anything here because StatsDimensionsValue class doesn't
+// // have any read api.
+//}
TEST(AtomMatcherTest, TestWriteDimensionToProto) {
HashableDimensionKey dim;
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index db9aa18dbd5a..7ee44053d4d5 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -94,6 +94,7 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
import java.util.List;
import java.util.Locale;
@@ -3555,13 +3556,13 @@ public class ActivityManager {
* @return a list of {@link ApplicationExitInfo} records matching the criteria, sorted in
* the order from most recent to least recent.
*/
- @Nullable
+ @NonNull
public List<ApplicationExitInfo> getHistoricalProcessExitReasons(@Nullable String packageName,
@IntRange(from = 0) int pid, @IntRange(from = 0) int maxNum) {
try {
ParceledListSlice<ApplicationExitInfo> r = getService().getHistoricalProcessExitReasons(
packageName, pid, maxNum, mContext.getUserId());
- return r == null ? null : r.getList();
+ return r == null ? Collections.emptyList() : r.getList();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/app/ApplicationExitInfo.java b/core/java/android/app/ApplicationExitInfo.java
index 4bf5f07e86be..c55453e94960 100644
--- a/core/java/android/app/ApplicationExitInfo.java
+++ b/core/java/android/app/ApplicationExitInfo.java
@@ -19,7 +19,6 @@ package android.app;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.SystemApi;
import android.app.ActivityManager.RunningAppProcessInfo.Importance;
import android.icu.text.SimpleDateFormat;
import android.os.Parcel;
@@ -245,12 +244,12 @@ public final class ApplicationExitInfo implements Parcelable {
/**
* @see {@link #getPss}
*/
- private int mPss;
+ private long mPss;
/**
* @see {@link #getRss}
*/
- private int mRss;
+ private long mRss;
/**
* @see {@link #getTimestamp}
@@ -385,7 +384,7 @@ public final class ApplicationExitInfo implements Parcelable {
* it's NOT the exact memory information prior to its death; and it'll be zero
* if the process died before system had a chance to take the sample. </p>
*/
- public int getPss() {
+ public long getPss() {
return mPss;
}
@@ -396,12 +395,13 @@ public final class ApplicationExitInfo implements Parcelable {
* it's NOT the exact memory information prior to its death; and it'll be zero
* if the process died before system had a chance to take the sample. </p>
*/
- public int getRss() {
+ public long getRss() {
return mRss;
}
/**
- * The timestamp of the process's death, in milliseconds since the epoch.
+ * The timestamp of the process's death, in milliseconds since the epoch,
+ * as returned by {@link System#currentTimeMillis System.currentTimeMillis()}.
*/
public long getTimestamp() {
return mTimestamp;
@@ -409,6 +409,9 @@ public final class ApplicationExitInfo implements Parcelable {
/**
* The human readable description of the process's death, given by the system; could be null.
+ *
+ * <p class="note">Note: only intended to be human-readable and the system provides no
+ * guarantees that the format is stable across devices or Android releases.</p>
*/
public @Nullable String getDescription() {
return mDescription;
@@ -416,10 +419,7 @@ public final class ApplicationExitInfo implements Parcelable {
/**
* Return the user id of the record on a multi-user system.
- *
- * @hide
*/
- @SystemApi
public @NonNull UserHandle getUserHandle() {
return UserHandle.of(UserHandle.getUserId(mRealUid));
}
@@ -546,7 +546,7 @@ public final class ApplicationExitInfo implements Parcelable {
*
* @hide
*/
- public void setPss(final int pss) {
+ public void setPss(final long pss) {
mPss = pss;
}
@@ -555,7 +555,7 @@ public final class ApplicationExitInfo implements Parcelable {
*
* @hide
*/
- public void setRss(final int rss) {
+ public void setRss(final long rss) {
mRss = rss;
}
@@ -630,8 +630,8 @@ public final class ApplicationExitInfo implements Parcelable {
dest.writeInt(mSubReason);
dest.writeInt(mStatus);
dest.writeInt(mImportance);
- dest.writeInt(mPss);
- dest.writeInt(mRss);
+ dest.writeLong(mPss);
+ dest.writeLong(mRss);
dest.writeLong(mTimestamp);
dest.writeString(mDescription);
}
@@ -669,8 +669,8 @@ public final class ApplicationExitInfo implements Parcelable {
mSubReason = in.readInt();
mStatus = in.readInt();
mImportance = in.readInt();
- mPss = in.readInt();
- mRss = in.readInt();
+ mPss = in.readLong();
+ mRss = in.readLong();
mTimestamp = in.readLong();
mDescription = in.readString();
}
@@ -848,10 +848,10 @@ public final class ApplicationExitInfo implements Parcelable {
mImportance = proto.readInt(ApplicationExitInfoProto.IMPORTANCE);
break;
case (int) ApplicationExitInfoProto.PSS:
- mPss = proto.readInt(ApplicationExitInfoProto.PSS);
+ mPss = proto.readLong(ApplicationExitInfoProto.PSS);
break;
case (int) ApplicationExitInfoProto.RSS:
- mRss = proto.readInt(ApplicationExitInfoProto.RSS);
+ mRss = proto.readLong(ApplicationExitInfoProto.RSS);
break;
case (int) ApplicationExitInfoProto.TIMESTAMP:
mTimestamp = proto.readLong(ApplicationExitInfoProto.TIMESTAMP);
@@ -891,8 +891,8 @@ public final class ApplicationExitInfo implements Parcelable {
result = 31 * result + mSubReason;
result = 31 * result + mImportance;
result = 31 * result + mStatus;
- result = 31 * result + mPss;
- result = 31 * result + mRss;
+ result = 31 * result + (int) mPss;
+ result = 31 * result + (int) mRss;
result = 31 * result + Long.hashCode(mTimestamp);
result = 31 * result + Objects.hashCode(mProcessName);
result = 31 * result + Objects.hashCode(mDescription);
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index 16c0910f1273..19397ed3ebaa 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -113,6 +113,7 @@ interface INotificationManager
int getAppsBypassingDndCount(int uid);
ParceledListSlice getNotificationChannelsBypassingDnd(String pkg, int userId);
boolean isPackagePaused(String pkg);
+ void deleteNotificationHistoryItem(String pkg, int uid, long postedTime);
void silenceNotificationSound();
diff --git a/core/java/android/app/ITaskOrganizerController.aidl b/core/java/android/app/ITaskOrganizerController.aidl
index bfc42ef8848d..5d5956e4dca4 100644
--- a/core/java/android/app/ITaskOrganizerController.aidl
+++ b/core/java/android/app/ITaskOrganizerController.aidl
@@ -51,6 +51,9 @@ interface ITaskOrganizerController {
/** Deletes a persistent root task in WM */
boolean deleteRootTask(IWindowContainer task);
+ /** Gets direct child tasks (ordered from top-to-bottom) */
+ List<ActivityManager.RunningTaskInfo> getChildTasks(in IWindowContainer parent);
+
/** Get the root task which contains the current ime target */
IWindowContainer getImeTarget(int display);
diff --git a/core/java/android/app/NotificationHistory.java b/core/java/android/app/NotificationHistory.java
index 909a476f3c94..f26e62874347 100644
--- a/core/java/android/app/NotificationHistory.java
+++ b/core/java/android/app/NotificationHistory.java
@@ -346,6 +346,26 @@ public final class NotificationHistory implements Parcelable {
}
/**
+ * Removes an individual historical notification and regenerates the string pool
+ */
+ public boolean removeNotificationFromWrite(String packageName, long postedTime) {
+ boolean removed = false;
+ for (int i = mNotificationsToWrite.size() - 1; i >= 0; i--) {
+ HistoricalNotification hn = mNotificationsToWrite.get(i);
+ if (packageName.equals(hn.getPackage())
+ && postedTime == hn.getPostedTimeMs()) {
+ removed = true;
+ mNotificationsToWrite.remove(i);
+ }
+ }
+ if (removed) {
+ poolStringsFromNotifications();
+ }
+
+ return removed;
+ }
+
+ /**
* Gets pooled strings in order to write them to disk
*/
public @NonNull String[] getPooledStringsToWrite() {
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index f32a4ab43357..0e0161ff4e9f 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -700,6 +700,27 @@ public abstract class ContentResolver implements ContentInterface {
/** @hide */
public static final String REMOTE_CALLBACK_RESULT = "result";
+ /**
+ * How long we wait for an attached process to publish its content providers
+ * before we decide it must be hung.
+ * @hide
+ */
+ public static final int CONTENT_PROVIDER_PUBLISH_TIMEOUT_MILLIS = 10 * 1000;
+
+ /**
+ * How long we wait for an provider to be published. Should be longer than
+ * {@link #CONTENT_PROVIDER_PUBLISH_TIMEOUT_MILLIS}.
+ * @hide
+ */
+ public static final int CONTENT_PROVIDER_WAIT_TIMEOUT_MILLIS =
+ CONTENT_PROVIDER_PUBLISH_TIMEOUT_MILLIS + 10 * 1000;
+
+ // Should be >= {@link #CONTENT_PROVIDER_WAIT_TIMEOUT_MILLIS}, because that's how
+ // long ActivityManagerService is giving a content provider to get published if a new process
+ // needs to be started for that.
+ private static final int GET_TYPE_TIMEOUT_MILLIS =
+ CONTENT_PROVIDER_WAIT_TIMEOUT_MILLIS + 5 * 1000;
+
public ContentResolver(@Nullable Context context) {
this(context, null);
}
@@ -849,8 +870,6 @@ public abstract class ContentResolver implements ContentInterface {
}
}
- private static final int GET_TYPE_TIMEOUT_MILLIS = 3000;
-
private static class GetTypeResultListener implements RemoteCallback.OnResultListener {
@GuardedBy("this")
public boolean done;
diff --git a/core/java/android/content/pm/ILauncherApps.aidl b/core/java/android/content/pm/ILauncherApps.aidl
index 04923590b413..38a9ac4a0d05 100644
--- a/core/java/android/content/pm/ILauncherApps.aidl
+++ b/core/java/android/content/pm/ILauncherApps.aidl
@@ -98,4 +98,9 @@ interface ILauncherApps {
in ComponentName componentName, int flags, in IShortcutChangeCallback callback,
int callbackId);
void unregisterShortcutChangeCallback(String callingPackage, int callbackId);
+
+ void cacheShortcuts(String callingPackage, String packageName, in List<String> shortcutIds,
+ in UserHandle user);
+ void uncacheShortcuts(String callingPackage, String packageName, in List<String> shortcutIds,
+ in UserHandle user);
}
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index 73c9e4d843b7..d2532783f47c 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -20,6 +20,7 @@ import android.annotation.CallbackExecutor;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
@@ -1089,6 +1090,61 @@ public class LauncherApps {
}
/**
+ * Mark shortcuts as cached for a package.
+ *
+ * <p>Only dynamic long lived shortcuts can be cached. None dynamic or non long lived shortcuts
+ * in the list will be ignored.
+ *
+ * <p>Unlike pinned shortcuts, where different callers can have different sets of pinned
+ * shortcuts, cached state is per shortcut only, and even if multiple callers cache the same
+ * shortcut, it can be uncached by any valid caller.
+ *
+ * @param packageName The target package name.
+ * @param shortcutIds The IDs of the shortcut to be cached.
+ * @param user The UserHandle of the profile.
+ * @throws IllegalStateException when the user is locked, or when the {@code user} user
+ * is locked or not running.
+ *
+ * @see ShortcutManager
+ *
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.ACCESS_SHORTCUTS)
+ public void cacheShortcuts(@NonNull String packageName, @NonNull List<String> shortcutIds,
+ @NonNull UserHandle user) {
+ logErrorForInvalidProfileAccess(user);
+ try {
+ mService.cacheShortcuts(mContext.getPackageName(), packageName, shortcutIds, user);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Remove cached flag from shortcuts for a package.
+ *
+ * @param packageName The target package name.
+ * @param shortcutIds The IDs of the shortcut to be uncached.
+ * @param user The UserHandle of the profile.
+ * @throws IllegalStateException when the user is locked, or when the {@code user} user
+ * is locked or not running.
+ *
+ * @see ShortcutManager
+ *
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.ACCESS_SHORTCUTS)
+ public void uncacheShortcuts(@NonNull String packageName, @NonNull List<String> shortcutIds,
+ @NonNull UserHandle user) {
+ logErrorForInvalidProfileAccess(user);
+ try {
+ mService.uncacheShortcuts(mContext.getPackageName(), packageName, shortcutIds, user);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* @hide kept for testing.
*/
@Deprecated
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 9f7f4821a11e..e8668f1368fb 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -597,6 +597,7 @@ public abstract class PackageManager {
* @hide
*/
@SystemApi
+ @TestApi
public static final int MODULE_APEX_NAME = 0x00000001;
/** @hide */
diff --git a/core/java/android/content/pm/ShortcutServiceInternal.java b/core/java/android/content/pm/ShortcutServiceInternal.java
index a11a1dd5a68b..a69905eb3de4 100644
--- a/core/java/android/content/pm/ShortcutServiceInternal.java
+++ b/core/java/android/content/pm/ShortcutServiceInternal.java
@@ -85,4 +85,11 @@ public abstract class ShortcutServiceInternal {
public abstract boolean isForegroundDefaultLauncher(@NonNull String callingPackage,
int callingUid);
+
+ public abstract void cacheShortcuts(int launcherUserId,
+ @NonNull String callingPackage, @NonNull String packageName,
+ @NonNull List<String> shortcutIds, int userId);
+ public abstract void uncacheShortcuts(int launcherUserId,
+ @NonNull String callingPackage, @NonNull String packageName,
+ @NonNull List<String> shortcutIds, int userId);
}
diff --git a/core/java/android/hardware/soundtrigger/SoundTriggerModule.java b/core/java/android/hardware/soundtrigger/SoundTriggerModule.java
index 9bd39925f83f..c1df5b6d2e7e 100644
--- a/core/java/android/hardware/soundtrigger/SoundTriggerModule.java
+++ b/core/java/android/hardware/soundtrigger/SoundTriggerModule.java
@@ -221,10 +221,8 @@ public class SoundTriggerModule {
/**
* Set a model specific {@link ModelParams} with the given value. This
* parameter will keep its value for the duration the model is loaded regardless of starting
- * and
- * stopping recognition. Once the model is unloaded, the value will be lost.
- * {@link SoundTriggerModule#queryParameter(int, int)} should be checked first before calling
- * this method.
+ * and stopping recognition. Once the model is unloaded, the value will be lost.
+ * {@link #queryParameter} should be checked first before calling this method.
*
* @param soundModelHandle handle of model to apply parameter
* @param modelParam {@link ModelParams}
@@ -251,22 +249,14 @@ public class SoundTriggerModule {
* for the duration the model is loaded regardless of starting and stopping recognition.
* Once the model is unloaded, the value will be lost. If the value is not set, a default
* value is returned. See {@link ModelParams} for parameter default values.
- * {@link SoundTriggerModule#queryParameter(int, int)} should be checked first before
+ * {@link #queryParameter} should be checked first before
* calling this method. Otherwise, an exception can be thrown.
*
* @param soundModelHandle handle of model to get parameter
* @param modelParam {@link ModelParams}
* @return value of parameter
- * @throws UnsupportedOperationException if hal or model do not support this API.
- * {@link SoundTriggerModule#queryParameter(int, int)}
- * should
- * be checked first.
- * @throws IllegalArgumentException if invalid model handle or parameter is passed.
- * {@link SoundTriggerModule#queryParameter(int, int)}
- * should be checked first.
*/
- public synchronized int getParameter(int soundModelHandle, @ModelParams int modelParam)
- throws UnsupportedOperationException, IllegalArgumentException {
+ public synchronized int getParameter(int soundModelHandle, @ModelParams int modelParam) {
try {
return mService.getModelParameter(soundModelHandle,
ConversionUtil.api2aidlModelParameter(modelParam));
@@ -276,9 +266,8 @@ public class SoundTriggerModule {
}
/**
- * Determine if parameter control is supported for the given model handle.
- * This method should be checked prior to calling {@link SoundTriggerModule#setParameter} or
- * {@link SoundTriggerModule#getParameter}.
+ * Query the parameter support and range for a given {@link ModelParams}.
+ * This method should be check prior to calling {@link #setParameter} or {@link #getParameter}.
*
* @param soundModelHandle handle of model to get parameter
* @param modelParam {@link ModelParams}
diff --git a/core/java/android/os/SharedMemory.java b/core/java/android/os/SharedMemory.java
index 26d9c7d687eb..75123528a6b8 100644
--- a/core/java/android/os/SharedMemory.java
+++ b/core/java/android/os/SharedMemory.java
@@ -27,6 +27,7 @@ import dalvik.system.VMRuntime;
import java.io.Closeable;
import java.io.FileDescriptor;
+import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.DirectByteBuffer;
import java.nio.NioUtils;
@@ -272,6 +273,20 @@ public final class SharedMemory implements Parcelable, Closeable {
dest.writeFileDescriptor(mFileDescriptor);
}
+ /**
+ * Returns a dup'd ParcelFileDescriptor from the SharedMemory FileDescriptor.
+ * This obeys standard POSIX semantics, where the
+ * new file descriptor shared state such as file position with the
+ * original file descriptor.
+ * TODO: propose this method as a public or system API for next release to achieve parity with
+ * NDK ASharedMemory_dupFromJava.
+ *
+ * @hide
+ */
+ public ParcelFileDescriptor getFdDup() throws IOException {
+ return ParcelFileDescriptor.dup(mFileDescriptor);
+ }
+
public static final @android.annotation.NonNull Parcelable.Creator<SharedMemory> CREATOR =
new Parcelable.Creator<SharedMemory>() {
@Override
diff --git a/core/java/android/os/Trace.java b/core/java/android/os/Trace.java
index 25584f156084..3508b7031dd3 100644
--- a/core/java/android/os/Trace.java
+++ b/core/java/android/os/Trace.java
@@ -101,6 +101,8 @@ public final class Trace {
public static final long TRACE_TAG_NNAPI = 1L << 25;
/** @hide */
public static final long TRACE_TAG_RRO = 1L << 26;
+ /** @hide */
+ public static final long TRACE_TAG_APEX_MANAGER = 1L << 18;
private static final long TRACE_TAG_NOT_READY = 1L << 63;
private static final int MAX_SECTION_NAME_LEN = 127;
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 6ed1d2c345f8..b202053b5d65 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -2325,10 +2325,12 @@ public class UserManager {
* @param restrictionKey the string key representing the restriction
* @param userHandle the UserHandle of the user for whom to retrieve the restrictions.
*/
+ @TestApi
@UnsupportedAppUsage
- @RequiresPermission(Manifest.permission.MANAGE_USERS)
- public boolean hasBaseUserRestriction(@UserRestrictionKey String restrictionKey,
- UserHandle userHandle) {
+ @RequiresPermission(anyOf = {Manifest.permission.MANAGE_USERS,
+ Manifest.permission.CREATE_USERS})
+ public boolean hasBaseUserRestriction(@UserRestrictionKey @NonNull String restrictionKey,
+ @NonNull UserHandle userHandle) {
try {
return mService.hasBaseUserRestriction(restrictionKey, userHandle.getIdentifier());
} catch (RemoteException re) {
diff --git a/core/java/android/os/incremental/IIncrementalService.aidl b/core/java/android/os/incremental/IIncrementalService.aidl
index 21434a2aecba..9d98b3b7819b 100644
--- a/core/java/android/os/incremental/IIncrementalService.aidl
+++ b/core/java/android/os/incremental/IIncrementalService.aidl
@@ -103,4 +103,9 @@ interface IIncrementalService {
* Deletes a storage given its ID. Deletes its bind mounts and unmount it. Stop its data loader.
*/
void deleteStorage(int storageId);
+
+ /**
+ * Setting up native library directories and extract native libs onto a storage.
+ */
+ boolean configureNativeBinaries(int storageId, in @utf8InCpp String apkFullPath, in @utf8InCpp String libDirRelativePath, in @utf8InCpp String abi);
}
diff --git a/core/java/android/os/incremental/IncrementalManager.java b/core/java/android/os/incremental/IncrementalManager.java
index 0024ac7a6b2e..ba38268949b5 100644
--- a/core/java/android/os/incremental/IncrementalManager.java
+++ b/core/java/android/os/incremental/IncrementalManager.java
@@ -229,16 +229,41 @@ public final class IncrementalManager {
if (linkedApkStorage == null) {
throw new IOException("Failed to create linked storage at dir: " + afterCodePathParent);
}
- linkedApkStorage.makeDirectory(afterCodePathName);
- File[] files = beforeCodeFile.listFiles();
- for (int i = 0; i < files.length; i++) {
- if (files[i].isFile()) {
- String fileName = files[i].getName();
- apkStorage.makeLink(
- fileName, linkedApkStorage, afterCodePathName + "/" + fileName);
+ linkFiles(apkStorage, beforeCodeFile, "", linkedApkStorage, afterCodePathName);
+ apkStorage.unBind(beforeCodePath);
+ }
+
+ /**
+ * Recursively set up directories and link all the files from source storage to target storage.
+ *
+ * @param sourceStorage The storage that has all the files and directories underneath.
+ * @param sourceAbsolutePath The absolute path of the directory that holds all files and dirs.
+ * @param sourceRelativePath The relative path on the source directory, e.g., "" or "lib".
+ * @param targetStorage The target storage that will have the same files and directories.
+ * @param targetRelativePath The relative path to the directory on the target storage that
+ * should have all the files and dirs underneath,
+ * e.g., "packageName-random".
+ * @throws IOException When makeDirectory or makeLink fails on the Incremental File System.
+ */
+ private void linkFiles(IncrementalStorage sourceStorage, File sourceAbsolutePath,
+ String sourceRelativePath, IncrementalStorage targetStorage,
+ String targetRelativePath) throws IOException {
+ targetStorage.makeDirectory(targetRelativePath);
+ final File[] entryList = sourceAbsolutePath.listFiles();
+ for (int i = 0; i < entryList.length; i++) {
+ final File entry = entryList[i];
+ final String entryName = entryList[i].getName();
+ final String sourceEntryRelativePath =
+ sourceRelativePath.isEmpty() ? entryName : sourceRelativePath + "/" + entryName;
+ final String targetEntryRelativePath = targetRelativePath + "/" + entryName;
+ if (entry.isFile()) {
+ sourceStorage.makeLink(
+ sourceEntryRelativePath, targetStorage, targetEntryRelativePath);
+ } else if (entry.isDirectory()) {
+ linkFiles(sourceStorage, entry, sourceEntryRelativePath, targetStorage,
+ targetEntryRelativePath);
}
}
- apkStorage.unBind(beforeCodePath);
}
/**
diff --git a/core/java/android/os/incremental/IncrementalStorage.java b/core/java/android/os/incremental/IncrementalStorage.java
index c4b843b6ce33..5df44ff49059 100644
--- a/core/java/android/os/incremental/IncrementalStorage.java
+++ b/core/java/android/os/incremental/IncrementalStorage.java
@@ -416,4 +416,24 @@ public final class IncrementalStorage {
return false;
}
}
+
+ /**
+ * Configure all the lib files inside Incremental Service, e.g., create lib dirs, create new lib
+ * files, extract original lib file data from zip and then write data to the lib files on the
+ * Incremental File System.
+ *
+ * @param apkFullPath Source APK to extract native libs from.
+ * @param libDirRelativePath Target dir to put lib files, e.g., "lib" or "lib/arm".
+ * @param abi Target ABI of the native lib files. Only extract native libs of this ABI.
+ * @return Success of not.
+ */
+ public boolean configureNativeBinaries(String apkFullPath, String libDirRelativePath,
+ String abi) {
+ try {
+ return mService.configureNativeBinaries(mId, apkFullPath, libDirRelativePath, abi);
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ return false;
+ }
+ }
}
diff --git a/core/java/android/service/contentcapture/ContentCaptureService.java b/core/java/android/service/contentcapture/ContentCaptureService.java
index 707426a22889..0edd01330fdd 100644
--- a/core/java/android/service/contentcapture/ContentCaptureService.java
+++ b/core/java/android/service/contentcapture/ContentCaptureService.java
@@ -345,9 +345,11 @@ public abstract class ContentCaptureService extends Service {
}
/**
- * Notifies the service of {@link SnapshotData snapshot data} associated with a session.
+ * Notifies the service of {@link SnapshotData snapshot data} associated with an activity.
*
- * @param sessionId the session's Id
+ * @param sessionId the session's Id. This may also be
+ * {@link ContentCaptureSession#NO_SESSION_ID} if no content capture session
+ * exists for the activity being snapshotted
* @param snapshotData the data
*/
public void onActivitySnapshot(@NonNull ContentCaptureSessionId sessionId,
diff --git a/core/java/android/service/quicksettings/TileService.java b/core/java/android/service/quicksettings/TileService.java
index d0675ed4b99a..b4b5819c7d5f 100644
--- a/core/java/android/service/quicksettings/TileService.java
+++ b/core/java/android/service/quicksettings/TileService.java
@@ -126,22 +126,22 @@ public class TileService extends Service {
= "android.service.quicksettings.ACTIVE_TILE";
/**
- * Meta-data for a tile to support {@code BooleanState}.
+ * Meta-data for a tile to mark is toggleable.
* <p>
- * BooleanState is for tiles that should support switch tile behavior in accessibility. This is
+ * Toggleable tiles support switch tile behavior in accessibility. This is
* the behavior of most of the framework tiles.
*
- * To make a TileService support BooleanState, set this meta-data to true on the TileService's
- * manifest declaration.
+ * To indicate that a TileService is toggleable, set this meta-data to true on the
+ * TileService's manifest declaration.
* <pre class="prettyprint">
* {@literal
- * <meta-data android:name="android.service.quicksettings.BOOLEAN_TILE"
+ * <meta-data android:name="android.service.quicksettings.TOGGLEABLE_TILE"
* android:value="true" />
* }
* </pre>
*/
- public static final String META_DATA_BOOLEAN_TILE =
- "android.service.quicksettings.BOOLEAN_TILE";
+ public static final String META_DATA_TOGGLEABLE_TILE =
+ "android.service.quicksettings.TOGGLEABLE_TILE";
/**
* Used to notify SysUI that Listening has be requested.
diff --git a/core/java/android/telephony/PhoneStateListener.java b/core/java/android/telephony/PhoneStateListener.java
index 531ade04fe02..e65bd9f20ec4 100644
--- a/core/java/android/telephony/PhoneStateListener.java
+++ b/core/java/android/telephony/PhoneStateListener.java
@@ -412,23 +412,23 @@ public class PhoneStateListener {
* domain. This indication does not necessarily indicate a change of service state, which should
* be tracked via {@link #LISTEN_SERVICE_STATE}.
*
- * <p>Requires permission {@link android.Manifest.permission#READ_PHONE_STATE} or the calling
- * app has carrier privileges (see {@link TelephonyManager#hasCarrierPrivileges}).
+ * <p>Requires permission {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE} or
+ * the calling app has carrier privileges (see {@link TelephonyManager#hasCarrierPrivileges}).
*
* @see #onRegistrationFailed()
*/
- @RequiresPermission(Manifest.permission.READ_PHONE_STATE)
+ @RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE)
public static final int LISTEN_REGISTRATION_FAILURE = 0x40000000;
/**
* Listen for Barring Information for the current registered / camped cell.
*
- * <p>Requires permission {@link android.Manifest.permission#READ_PHONE_STATE} or the calling
- * app has carrier privileges (see {@link TelephonyManager#hasCarrierPrivileges}).
+ * <p>Requires permission {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE} or
+ * the calling app has carrier privileges (see {@link TelephonyManager#hasCarrierPrivileges}).
*
* @see #onBarringInfoChanged()
*/
- @RequiresPermission(Manifest.permission.READ_PHONE_STATE)
+ @RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE)
public static final int LISTEN_BARRING_INFO = 0x80000000;
/*
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index a407bd8f001e..a6f8fad817e1 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -12729,12 +12729,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
return findViewInsideOutShouldExist(root, mNextFocusForwardId);
case FOCUS_BACKWARD: {
if (mID == View.NO_ID) return null;
- return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
- @Override
- public boolean test(View t) {
- return t.findViewById(t.mNextFocusForwardId) == View.this;
- }
- });
+ final View rootView = root;
+ final View startView = this;
+ // Since we have forward links but no backward links, we need to find the view that
+ // forward links to this view. We can't just find the view with the specified ID
+ // because view IDs need not be unique throughout the tree.
+ return root.findViewByPredicateInsideOut(startView,
+ t -> findViewInsideOutShouldExist(rootView, t, t.mNextFocusForwardId)
+ == startView);
}
}
return null;
@@ -12764,11 +12766,15 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
private View findViewInsideOutShouldExist(View root, int id) {
+ return findViewInsideOutShouldExist(root, this, id);
+ }
+
+ private View findViewInsideOutShouldExist(View root, View start, int id) {
if (mMatchIdPredicate == null) {
mMatchIdPredicate = new MatchIdPredicate();
}
mMatchIdPredicate.mId = id;
- View result = root.findViewByPredicateInsideOut(this, mMatchIdPredicate);
+ View result = root.findViewByPredicateInsideOut(start, mMatchIdPredicate);
if (result == null) {
Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id);
}
diff --git a/core/java/android/view/WindowContainerTransaction.java b/core/java/android/view/WindowContainerTransaction.java
index 33f21f211a1a..cf34b0bad78d 100644
--- a/core/java/android/view/WindowContainerTransaction.java
+++ b/core/java/android/view/WindowContainerTransaction.java
@@ -16,6 +16,8 @@
package android.view;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.app.WindowConfiguration;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
@@ -25,6 +27,8 @@ import android.os.Parcel;
import android.os.Parcelable;
import android.util.ArrayMap;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Map;
/**
@@ -36,10 +40,14 @@ import java.util.Map;
public class WindowContainerTransaction implements Parcelable {
private final ArrayMap<IBinder, Change> mChanges = new ArrayMap<>();
+ // Flat list because re-order operations are order-dependent
+ private final ArrayList<HierarchyOp> mHierarchyOps = new ArrayList<>();
+
public WindowContainerTransaction() {}
protected WindowContainerTransaction(Parcel in) {
in.readMap(mChanges, null /* loader */);
+ in.readList(mHierarchyOps, null /* loader */);
}
private Change getOrCreateChange(IBinder token) {
@@ -97,10 +105,39 @@ public class WindowContainerTransaction implements Parcelable {
return this;
}
+ /**
+ * Reparents a container into another one. The effect of a {@code null} parent can vary. For
+ * example, reparenting a stack to {@code null} will reparent it to its display.
+ *
+ * @param onTop When {@code true}, the child goes to the top of parent; otherwise it goes to
+ * the bottom.
+ */
+ public WindowContainerTransaction reparent(@NonNull IWindowContainer child,
+ @Nullable IWindowContainer parent, boolean onTop) {
+ mHierarchyOps.add(new HierarchyOp(child.asBinder(),
+ parent == null ? null : parent.asBinder(), onTop));
+ return this;
+ }
+
+ /**
+ * Reorders a container within its parent.
+ *
+ * @param onTop When {@code true}, the child goes to the top of parent; otherwise it goes to
+ * the bottom.
+ */
+ public WindowContainerTransaction reorder(@NonNull IWindowContainer child, boolean onTop) {
+ mHierarchyOps.add(new HierarchyOp(child.asBinder(), onTop));
+ return this;
+ }
+
public Map<IBinder, Change> getChanges() {
return mChanges;
}
+ public List<HierarchyOp> getHierarchyOps() {
+ return mHierarchyOps;
+ }
+
@Override
public String toString() {
return "WindowContainerTransaction { changes = " + mChanges + " }";
@@ -109,6 +146,7 @@ public class WindowContainerTransaction implements Parcelable {
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeMap(mChanges);
+ dest.writeList(mHierarchyOps);
}
@Override
@@ -249,4 +287,88 @@ public class WindowContainerTransaction implements Parcelable {
}
};
}
+
+ /**
+ * Holds information about a reparent/reorder operation in the hierarchy. This is separate from
+ * Changes because they must be executed in the same order that they are added.
+ */
+ public static class HierarchyOp implements Parcelable {
+ private final IBinder mContainer;
+
+ // If this is same as mContainer, then only change position, don't reparent.
+ private final IBinder mReparent;
+
+ // Moves/reparents to top of parent when {@code true}, otherwise moves/reparents to bottom.
+ private final boolean mToTop;
+
+ public HierarchyOp(@NonNull IBinder container, @Nullable IBinder reparent, boolean toTop) {
+ mContainer = container;
+ mReparent = reparent;
+ mToTop = toTop;
+ }
+
+ public HierarchyOp(@NonNull IBinder container, boolean toTop) {
+ mContainer = container;
+ mReparent = container;
+ mToTop = toTop;
+ }
+
+ protected HierarchyOp(Parcel in) {
+ mContainer = in.readStrongBinder();
+ mReparent = in.readStrongBinder();
+ mToTop = in.readBoolean();
+ }
+
+ public boolean isReparent() {
+ return mContainer != mReparent;
+ }
+
+ @Nullable
+ public IBinder getNewParent() {
+ return mReparent;
+ }
+
+ @NonNull
+ public IBinder getContainer() {
+ return mContainer;
+ }
+
+ public boolean getToTop() {
+ return mToTop;
+ }
+
+ @Override
+ public String toString() {
+ if (isReparent()) {
+ return "{reparent: " + mContainer + " to " + (mToTop ? "top of " : "bottom of ")
+ + mReparent + "}";
+ } else {
+ return "{reorder: " + mContainer + " to " + (mToTop ? "top" : "bottom") + "}";
+ }
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeStrongBinder(mContainer);
+ dest.writeStrongBinder(mReparent);
+ dest.writeBoolean(mToTop);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ public static final Creator<HierarchyOp> CREATOR = new Creator<HierarchyOp>() {
+ @Override
+ public HierarchyOp createFromParcel(Parcel in) {
+ return new HierarchyOp(in);
+ }
+
+ @Override
+ public HierarchyOp[] newArray(int size) {
+ return new HierarchyOp[size];
+ }
+ };
+ }
}
diff --git a/core/java/android/view/contentcapture/ContentCaptureSession.java b/core/java/android/view/contentcapture/ContentCaptureSession.java
index 232d96ba7f43..2134dab7986b 100644
--- a/core/java/android/view/contentcapture/ContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/ContentCaptureSession.java
@@ -22,6 +22,7 @@ import android.annotation.CallSuper;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SystemApi;
import android.util.DebugUtils;
import android.util.Log;
import android.view.View;
@@ -50,7 +51,11 @@ public abstract class ContentCaptureSession implements AutoCloseable {
private static final Random sIdGenerator = new Random();
- /** @hide */
+ /**
+ * ID used to indicate that a session does not exist
+ * @hide
+ */
+ @SystemApi
public static final int NO_SESSION_ID = 0;
/**
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index f0c16aadf12f..dbab81b129a9 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -664,8 +664,6 @@ public final class InputMethodManager {
*/
@Override
public void setCurrentRootView(ViewRootImpl rootView) {
- // If the mCurRootView is losing window focus, release the strong reference to it
- // so as not to prevent it from being garbage-collected.
if (mWindowFocusGainFuture != null) {
mWindowFocusGainFuture.cancel(false /* mayInterruptIfRunning */);
mWindowFocusGainFuture = null;
diff --git a/core/java/android/webkit/WebResourceRequest.java b/core/java/android/webkit/WebResourceRequest.java
index 964b6f8e259d..0b307e63ca45 100644
--- a/core/java/android/webkit/WebResourceRequest.java
+++ b/core/java/android/webkit/WebResourceRequest.java
@@ -32,10 +32,10 @@ public interface WebResourceRequest {
Uri getUrl();
/**
- * Gets whether the request was made for the main frame.
+ * Gets whether the request was made in order to fetch the main frame's document.
*
- * @return whether the request was made for the main frame. Will be {@code false} for iframes,
- * for example.
+ * @return whether the request was made for the main frame document. Will be
+ * {@code false} for subresources or iframes, for example.
*/
boolean isForMainFrame();
diff --git a/core/java/android/widget/Toast.java b/core/java/android/widget/Toast.java
index a2c70b9afbee..8c52d1fadc52 100644
--- a/core/java/android/widget/Toast.java
+++ b/core/java/android/widget/Toast.java
@@ -263,9 +263,14 @@ public class Toast {
/**
* Return the view.
*
- * <p><strong>Warning:</strong> Starting from Android {@link Build.VERSION_CODES#R}, for apps
- * targeting API level {@link Build.VERSION_CODES#R} or higher that haven't called {@link
- * #setView(View)} with a non-{@code null} view, this method will return {@code null}.
+ * <p>Toasts constructed with {@link #Toast(Context)} that haven't called {@link #setView(View)}
+ * with a non-{@code null} view will return {@code null} here.
+ *
+ * <p>Starting from Android {@link Build.VERSION_CODES#R}, in apps targeting API level {@link
+ * Build.VERSION_CODES#R} or higher, toasts constructed with {@link #makeText(Context,
+ * CharSequence, int)} or its variants will also return {@code null} here unless they had called
+ * {@link #setView(View)} with a non-{@code null} view. If you want to be notified when the
+ * toast is shown or hidden, use {@link #addCallback(Callback)}.
*
* @see #setView
* @deprecated Custom toast views are deprecated. Apps can create a standard text toast with the
@@ -276,7 +281,7 @@ public class Toast {
* will not have custom toast views displayed.
*/
@Deprecated
- public View getView() {
+ @Nullable public View getView() {
return mNextView;
}
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index bbb751359bab..a934de328989 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -1487,7 +1487,6 @@ public class ResolverActivity extends Activity implements
for (int i = 0; i < tabWidget.getChildCount(); i++) {
TextView title = tabWidget.getChildAt(i).findViewById(android.R.id.title);
title.setTextColor(getColor(R.color.resolver_tabs_inactive_color));
- title.setAllCaps(false);
}
}
diff --git a/core/java/com/android/internal/content/NativeLibraryHelper.java b/core/java/com/android/internal/content/NativeLibraryHelper.java
index 22fe31eeda38..0ccc45e000e6 100644
--- a/core/java/com/android/internal/content/NativeLibraryHelper.java
+++ b/core/java/com/android/internal/content/NativeLibraryHelper.java
@@ -25,6 +25,7 @@ import static android.system.OsConstants.S_IRWXU;
import static android.system.OsConstants.S_IXGRP;
import static android.system.OsConstants.S_IXOTH;
+import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageParser;
@@ -32,7 +33,12 @@ import android.content.pm.PackageParser.PackageLite;
import android.content.pm.PackageParser.PackageParserException;
import android.content.pm.parsing.AndroidPackage;
import android.os.Build;
+import android.os.IBinder;
import android.os.SELinux;
+import android.os.ServiceManager;
+import android.os.incremental.IIncrementalService;
+import android.os.incremental.IncrementalManager;
+import android.os.incremental.IncrementalStorage;
import android.system.ErrnoException;
import android.system.Os;
import android.util.Slog;
@@ -44,6 +50,7 @@ import java.io.Closeable;
import java.io.File;
import java.io.FileDescriptor;
import java.io.IOException;
+import java.nio.file.Path;
import java.util.List;
/**
@@ -73,6 +80,7 @@ public class NativeLibraryHelper {
private final CloseGuard mGuard = CloseGuard.get();
private volatile boolean mClosed;
+ final String[] apkPaths;
final long[] apkHandles;
final boolean multiArch;
final boolean extractNativeLibs;
@@ -103,9 +111,11 @@ public class NativeLibraryHelper {
private static Handle create(List<String> codePaths, boolean multiArch,
boolean extractNativeLibs, boolean debuggable) throws IOException {
final int size = codePaths.size();
+ final String[] apkPaths = new String[size];
final long[] apkHandles = new long[size];
for (int i = 0; i < size; i++) {
final String path = codePaths.get(i);
+ apkPaths[i] = path;
apkHandles[i] = nativeOpenApk(path);
if (apkHandles[i] == 0) {
// Unwind everything we've opened so far
@@ -116,7 +126,7 @@ public class NativeLibraryHelper {
}
}
- return new Handle(apkHandles, multiArch, extractNativeLibs, debuggable);
+ return new Handle(apkPaths, apkHandles, multiArch, extractNativeLibs, debuggable);
}
public static Handle createFd(PackageLite lite, FileDescriptor fd) throws IOException {
@@ -127,11 +137,13 @@ public class NativeLibraryHelper {
throw new IOException("Unable to open APK " + path + " from fd " + fd);
}
- return new Handle(apkHandles, lite.multiArch, lite.extractNativeLibs, lite.debuggable);
+ return new Handle(new String[]{path}, apkHandles, lite.multiArch,
+ lite.extractNativeLibs, lite.debuggable);
}
- Handle(long[] apkHandles, boolean multiArch, boolean extractNativeLibs,
- boolean debuggable) {
+ Handle(String[] apkPaths, long[] apkHandles, boolean multiArch,
+ boolean extractNativeLibs, boolean debuggable) {
+ this.apkPaths = apkPaths;
this.apkHandles = apkHandles;
this.multiArch = multiArch;
this.extractNativeLibs = extractNativeLibs;
@@ -313,40 +325,58 @@ public class NativeLibraryHelper {
}
public static int copyNativeBinariesForSupportedAbi(Handle handle, File libraryRoot,
- String[] abiList, boolean useIsaSubdir) throws IOException {
- createNativeLibrarySubdir(libraryRoot);
-
+ String[] abiList, boolean useIsaSubdir, boolean isIncremental) throws IOException {
/*
* If this is an internal application or our nativeLibraryPath points to
* the app-lib directory, unpack the libraries if necessary.
*/
int abi = findSupportedAbi(handle, abiList);
- if (abi >= 0) {
- /*
- * If we have a matching instruction set, construct a subdir under the native
- * library root that corresponds to this instruction set.
- */
- final String instructionSet = VMRuntime.getInstructionSet(abiList[abi]);
- final File subDir;
- if (useIsaSubdir) {
- final File isaSubdir = new File(libraryRoot, instructionSet);
- createNativeLibrarySubdir(isaSubdir);
- subDir = isaSubdir;
- } else {
- subDir = libraryRoot;
- }
+ if (abi < 0) {
+ return abi;
+ }
- int copyRet = copyNativeBinaries(handle, subDir, abiList[abi]);
- if (copyRet != PackageManager.INSTALL_SUCCEEDED) {
- return copyRet;
+ /*
+ * If we have a matching instruction set, construct a subdir under the native
+ * library root that corresponds to this instruction set.
+ */
+ final String supportedAbi = abiList[abi];
+ final String instructionSet = VMRuntime.getInstructionSet(supportedAbi);
+ final File subDir;
+ if (useIsaSubdir) {
+ subDir = new File(libraryRoot, instructionSet);
+ } else {
+ subDir = libraryRoot;
+ }
+
+ if (isIncremental) {
+ int res =
+ incrementalConfigureNativeBinariesForSupportedAbi(handle, subDir, supportedAbi);
+ if (res != PackageManager.INSTALL_SUCCEEDED) {
+ // TODO(b/133435829): the caller of this function expects that we return the index
+ // to the supported ABI. However, any non-negative integer can be a valid index.
+ // We should fix this function and make sure it doesn't accidentally return an error
+ // code that can also be a valid index.
+ return res;
}
+ return abi;
+ }
+
+ // For non-incremental, use regular extraction and copy
+ createNativeLibrarySubdir(libraryRoot);
+ if (subDir != libraryRoot) {
+ createNativeLibrarySubdir(subDir);
+ }
+
+ int copyRet = copyNativeBinaries(handle, subDir, supportedAbi);
+ if (copyRet != PackageManager.INSTALL_SUCCEEDED) {
+ return copyRet;
}
return abi;
}
public static int copyNativeBinariesWithOverride(Handle handle, File libraryRoot,
- String abiOverride) {
+ String abiOverride, boolean isIncremental) {
try {
if (handle.multiArch) {
// Warn if we've set an abiOverride for multi-lib packages..
@@ -359,7 +389,8 @@ public class NativeLibraryHelper {
int copyRet = PackageManager.NO_NATIVE_LIBRARIES;
if (Build.SUPPORTED_32_BIT_ABIS.length > 0) {
copyRet = copyNativeBinariesForSupportedAbi(handle, libraryRoot,
- Build.SUPPORTED_32_BIT_ABIS, true /* use isa specific subdirs */);
+ Build.SUPPORTED_32_BIT_ABIS, true /* use isa specific subdirs */,
+ isIncremental);
if (copyRet < 0 && copyRet != PackageManager.NO_NATIVE_LIBRARIES &&
copyRet != PackageManager.INSTALL_FAILED_NO_MATCHING_ABIS) {
Slog.w(TAG, "Failure copying 32 bit native libraries; copyRet=" +copyRet);
@@ -369,7 +400,8 @@ public class NativeLibraryHelper {
if (Build.SUPPORTED_64_BIT_ABIS.length > 0) {
copyRet = copyNativeBinariesForSupportedAbi(handle, libraryRoot,
- Build.SUPPORTED_64_BIT_ABIS, true /* use isa specific subdirs */);
+ Build.SUPPORTED_64_BIT_ABIS, true /* use isa specific subdirs */,
+ isIncremental);
if (copyRet < 0 && copyRet != PackageManager.NO_NATIVE_LIBRARIES &&
copyRet != PackageManager.INSTALL_FAILED_NO_MATCHING_ABIS) {
Slog.w(TAG, "Failure copying 64 bit native libraries; copyRet=" +copyRet);
@@ -392,7 +424,7 @@ public class NativeLibraryHelper {
}
int copyRet = copyNativeBinariesForSupportedAbi(handle, libraryRoot, abiList,
- true /* use isa specific subdirs */);
+ true /* use isa specific subdirs */, isIncremental);
if (copyRet < 0 && copyRet != PackageManager.NO_NATIVE_LIBRARIES) {
Slog.w(TAG, "Failure copying native libraries [errorCode=" + copyRet + "]");
return copyRet;
@@ -449,29 +481,61 @@ public class NativeLibraryHelper {
* Service will create native library directories and set up native library binary files in the
* same structure as they are in non-incremental installations.
*
- * @param pkg The package to be installed, including all the APK files.
- * @param handle The pointer to an zip archive.
- * @param libraryRoot The root directory of the native library files, e.g., lib/
- * @param abiList The list of ABIs that are supported by the current device.
- * @param useIsaSubdir Whether or not to set up a sub dir for the ISA.
- * @return ABI code if installation succeeds or error code if installation fails.
+ * @param handle The Handle object that contains all apk paths.
+ * @param libSubDir The target directory to put the native library files, e.g., lib/ or lib/arm
+ * @param abi The abi that is supported by the current device.
+ * @return Integer code if installation succeeds or fails.
*/
- public static int configureNativeBinariesForSupportedAbi(AndroidPackage pkg, Handle handle,
- File libraryRoot, String[] abiList, boolean useIsaSubdir) {
- int abi = findSupportedAbi(handle, abiList);
- if (abi < 0) {
- Slog.e(TAG, "Failed to find find matching ABI.");
- return abi;
+ private static int incrementalConfigureNativeBinariesForSupportedAbi(Handle handle,
+ File libSubDir, String abi) {
+ final String[] apkPaths = handle.apkPaths;
+ if (apkPaths == null || apkPaths.length == 0) {
+ Slog.e(TAG, "No apks to extract native libraries from.");
+ return PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
}
- // Currently only support installations that have pre-configured native library files
- // TODO(b/136132412): implement this after incfs supports file mapping
- if (!libraryRoot.exists()) {
- Slog.e(TAG, "Incremental installation currently does not configure native libs");
- return INSTALL_FAILED_NO_MATCHING_ABIS;
+ final IBinder incrementalService = ServiceManager.getService(Context.INCREMENTAL_SERVICE);
+ if (incrementalService == null) {
+ //TODO(b/133435829): add incremental specific error codes
+ return PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
+ }
+ final IncrementalManager incrementalManager = new IncrementalManager(
+ IIncrementalService.Stub.asInterface(incrementalService));
+ final File apkParent = new File(apkPaths[0]).getParentFile();
+ IncrementalStorage incrementalStorage =
+ incrementalManager.openStorage(apkParent.getAbsolutePath());
+ if (incrementalStorage == null) {
+ Slog.e(TAG, "Failed to find incremental storage");
+ return PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
}
- return abi;
+ String libRelativeDir = getRelativePath(apkParent, libSubDir);
+ if (libRelativeDir == null) {
+ return PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
+ }
+
+ for (int i = 0; i < apkPaths.length; i++) {
+ if (!incrementalStorage.configureNativeBinaries(apkPaths[i], libRelativeDir, abi)) {
+ return PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
+ }
+ }
+ return PackageManager.INSTALL_SUCCEEDED;
+ }
+
+ private static String getRelativePath(File base, File target) {
+ try {
+ final Path basePath = base.toPath();
+ final Path targetPath = target.toPath();
+ final Path relativePath = basePath.relativize(targetPath);
+ if (relativePath.toString().isEmpty()) {
+ return "";
+ }
+ return relativePath.toString();
+ } catch (IllegalArgumentException ex) {
+ Slog.e(TAG, "Failed to find relative path between: " + base.getAbsolutePath()
+ + " and: " + target.getAbsolutePath());
+ return null;
+ }
}
// We don't care about the other return values for now.
diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java
index 26d2f19b13b6..2fcc1de776fb 100644
--- a/core/java/com/android/server/SystemConfig.java
+++ b/core/java/com/android/server/SystemConfig.java
@@ -903,7 +903,6 @@ public class SystemConfig {
} break;
case "component-override": {
readComponentOverrides(parser, permFile);
- XmlUtils.skipCurrentTag(parser);
} break;
case "backup-transport-whitelisted-service": {
if (allowFeatures) {
@@ -1403,8 +1402,7 @@ public class SystemConfig {
final int depth = parser.getDepth();
while (XmlUtils.nextElementWithin(parser, depth)) {
- String name = parser.getName();
- if ("component".equals(name)) {
+ if ("component".equals(parser.getName())) {
String clsname = parser.getAttributeValue(null, "class");
String enabled = parser.getAttributeValue(null, "enabled");
if (clsname == null) {
@@ -1432,8 +1430,6 @@ public class SystemConfig {
}
componentEnabledStates.put(clsname, !"false".equals(enabled));
- } else {
- XmlUtils.skipCurrentTag(parser);
}
}
}
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index 3d0926d61789..76e7e191d293 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -182,6 +182,7 @@ cc_library_shared {
"android_hardware_UsbRequest.cpp",
"android_hardware_location_ActivityRecognitionHardware.cpp",
"android_util_FileObserver.cpp",
+ "android/graphics/GraphicsStatsService.cpp",
"android/graphics/SurfaceTexture.cpp",
"android/opengl/poly_clip.cpp", // TODO: .arm
"android/opengl/util.cpp",
@@ -273,6 +274,7 @@ cc_library_shared {
"libstats_jni",
"libstatslog",
"server_configurable_flags",
+ "libstatspull",
],
export_shared_lib_headers: [
// AndroidRuntime.h depends on nativehelper/jni.h
diff --git a/core/jni/android/graphics/FontFamily.cpp b/core/jni/android/graphics/FontFamily.cpp
index 8fc6afa0f386..2a56fd6d6d17 100644
--- a/core/jni/android/graphics/FontFamily.cpp
+++ b/core/jni/android/graphics/FontFamily.cpp
@@ -34,9 +34,9 @@
#include <hwui/MinikinSkia.h>
#include <hwui/Typeface.h>
-#include <utils/FatVector.h>
#include <minikin/FontFamily.h>
#include <minikin/LocaleList.h>
+#include <ui/FatVector.h>
#include <memory>
@@ -109,7 +109,7 @@ static jlong FontFamily_getFamilyReleaseFunc(CRITICAL_JNI_PARAMS) {
static bool addSkTypeface(NativeFamilyBuilder* builder, sk_sp<SkData>&& data, int ttcIndex,
jint weight, jint italic) {
- uirenderer::FatVector<SkFontArguments::Axis, 2> skiaAxes;
+ FatVector<SkFontArguments::Axis, 2> skiaAxes;
for (const auto& axis : builder->axes) {
skiaAxes.emplace_back(SkFontArguments::Axis{axis.axisTag, axis.value});
}
diff --git a/core/jni/android/graphics/GraphicsStatsService.cpp b/core/jni/android/graphics/GraphicsStatsService.cpp
new file mode 100644
index 000000000000..ef0aacc4d9ec
--- /dev/null
+++ b/core/jni/android/graphics/GraphicsStatsService.cpp
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2017 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 "GraphicsStatsService"
+
+#include <JankTracker.h>
+#include <jni.h>
+#include <log/log.h>
+#include <nativehelper/JNIHelp.h>
+#include <nativehelper/ScopedPrimitiveArray.h>
+#include <nativehelper/ScopedUtfChars.h>
+#include <service/GraphicsStatsService.h>
+#include <stats_event.h>
+#include <stats_pull_atom_callback.h>
+#include <statslog.h>
+#include "core_jni_helpers.h"
+
+namespace android {
+
+using namespace android::uirenderer;
+
+static jint getAshmemSize(JNIEnv*, jobject) {
+ return sizeof(ProfileData);
+}
+
+static jlong createDump(JNIEnv*, jobject, jint fd, jboolean isProto) {
+ GraphicsStatsService::Dump* dump =
+ GraphicsStatsService::createDump(fd,
+ isProto ? GraphicsStatsService::DumpType::Protobuf
+ : GraphicsStatsService::DumpType::Text);
+ return reinterpret_cast<jlong>(dump);
+}
+
+static void addToDump(JNIEnv* env, jobject, jlong dumpPtr, jstring jpath, jstring jpackage,
+ jlong versionCode, jlong startTime, jlong endTime, jbyteArray jdata) {
+ std::string path;
+ const ProfileData* data = nullptr;
+ LOG_ALWAYS_FATAL_IF(jdata == nullptr && jpath == nullptr, "Path and data can't both be null");
+ ScopedByteArrayRO buffer{env};
+ if (jdata != nullptr) {
+ buffer.reset(jdata);
+ LOG_ALWAYS_FATAL_IF(buffer.size() != sizeof(ProfileData),
+ "Buffer size %zu doesn't match expected %zu!", buffer.size(),
+ sizeof(ProfileData));
+ data = reinterpret_cast<const ProfileData*>(buffer.get());
+ }
+ if (jpath != nullptr) {
+ ScopedUtfChars pathChars(env, jpath);
+ LOG_ALWAYS_FATAL_IF(pathChars.size() <= 0 || !pathChars.c_str(),
+ "Failed to get path chars");
+ path.assign(pathChars.c_str(), pathChars.size());
+ }
+ ScopedUtfChars packageChars(env, jpackage);
+ LOG_ALWAYS_FATAL_IF(packageChars.size() <= 0 || !packageChars.c_str(),
+ "Failed to get path chars");
+ GraphicsStatsService::Dump* dump = reinterpret_cast<GraphicsStatsService::Dump*>(dumpPtr);
+ LOG_ALWAYS_FATAL_IF(!dump, "null passed for dump pointer");
+
+ const std::string package(packageChars.c_str(), packageChars.size());
+ GraphicsStatsService::addToDump(dump, path, package, versionCode, startTime, endTime, data);
+}
+
+static void addFileToDump(JNIEnv* env, jobject, jlong dumpPtr, jstring jpath) {
+ ScopedUtfChars pathChars(env, jpath);
+ LOG_ALWAYS_FATAL_IF(pathChars.size() <= 0 || !pathChars.c_str(), "Failed to get path chars");
+ const std::string path(pathChars.c_str(), pathChars.size());
+ GraphicsStatsService::Dump* dump = reinterpret_cast<GraphicsStatsService::Dump*>(dumpPtr);
+ GraphicsStatsService::addToDump(dump, path);
+}
+
+static void finishDump(JNIEnv*, jobject, jlong dumpPtr) {
+ GraphicsStatsService::Dump* dump = reinterpret_cast<GraphicsStatsService::Dump*>(dumpPtr);
+ GraphicsStatsService::finishDump(dump);
+}
+
+static void finishDumpInMemory(JNIEnv* env, jobject, jlong dumpPtr, jlong pulledData,
+ jboolean lastFullDay) {
+ GraphicsStatsService::Dump* dump = reinterpret_cast<GraphicsStatsService::Dump*>(dumpPtr);
+ AStatsEventList* data = reinterpret_cast<AStatsEventList*>(pulledData);
+ GraphicsStatsService::finishDumpInMemory(dump, data, lastFullDay == JNI_TRUE);
+}
+
+static void saveBuffer(JNIEnv* env, jobject clazz, jstring jpath, jstring jpackage,
+ jlong versionCode, jlong startTime, jlong endTime, jbyteArray jdata) {
+ ScopedByteArrayRO buffer(env, jdata);
+ LOG_ALWAYS_FATAL_IF(buffer.size() != sizeof(ProfileData),
+ "Buffer size %zu doesn't match expected %zu!", buffer.size(),
+ sizeof(ProfileData));
+ ScopedUtfChars pathChars(env, jpath);
+ LOG_ALWAYS_FATAL_IF(pathChars.size() <= 0 || !pathChars.c_str(), "Failed to get path chars");
+ ScopedUtfChars packageChars(env, jpackage);
+ LOG_ALWAYS_FATAL_IF(packageChars.size() <= 0 || !packageChars.c_str(),
+ "Failed to get path chars");
+
+ const std::string path(pathChars.c_str(), pathChars.size());
+ const std::string package(packageChars.c_str(), packageChars.size());
+ const ProfileData* data = reinterpret_cast<const ProfileData*>(buffer.get());
+ GraphicsStatsService::saveBuffer(path, package, versionCode, startTime, endTime, data);
+}
+
+static jobject gGraphicsStatsServiceObject = nullptr;
+static jmethodID gGraphicsStatsService_pullGraphicsStatsMethodID;
+
+static JNIEnv* getJNIEnv() {
+ JavaVM* vm = AndroidRuntime::getJavaVM();
+ JNIEnv* env = nullptr;
+ if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
+ if (vm->AttachCurrentThreadAsDaemon(&env, nullptr) != JNI_OK) {
+ LOG_ALWAYS_FATAL("Failed to AttachCurrentThread!");
+ }
+ }
+ return env;
+}
+
+// graphicsStatsPullCallback is invoked by statsd service to pull GRAPHICS_STATS atom.
+static AStatsManager_PullAtomCallbackReturn graphicsStatsPullCallback(int32_t atom_tag,
+ AStatsEventList* data,
+ void* cookie) {
+ JNIEnv* env = getJNIEnv();
+ if (!env) {
+ return false;
+ }
+ if (gGraphicsStatsServiceObject == nullptr) {
+ ALOGE("Failed to get graphicsstats service");
+ return AStatsManager_PULL_SKIP;
+ }
+
+ for (bool lastFullDay : {true, false}) {
+ env->CallVoidMethod(gGraphicsStatsServiceObject,
+ gGraphicsStatsService_pullGraphicsStatsMethodID,
+ (jboolean)(lastFullDay ? JNI_TRUE : JNI_FALSE),
+ reinterpret_cast<jlong>(data));
+ if (env->ExceptionCheck()) {
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ ALOGE("Failed to invoke graphicsstats service");
+ return AStatsManager_PULL_SKIP;
+ }
+ }
+ return AStatsManager_PULL_SUCCESS;
+}
+
+// Register a puller for GRAPHICS_STATS atom with the statsd service.
+static void nativeInit(JNIEnv* env, jobject javaObject) {
+ gGraphicsStatsServiceObject = env->NewGlobalRef(javaObject);
+ AStatsManager_PullAtomMetadata* metadata = AStatsManager_PullAtomMetadata_obtain();
+ AStatsManager_PullAtomMetadata_setCoolDownNs(metadata, 10 * 1000000); // 10 milliseconds
+ AStatsManager_PullAtomMetadata_setTimeoutNs(metadata, 2 * NS_PER_SEC); // 2 seconds
+
+ AStatsManager_registerPullAtomCallback(android::util::GRAPHICS_STATS,
+ &graphicsStatsPullCallback, metadata, nullptr);
+
+ AStatsManager_PullAtomMetadata_release(metadata);
+}
+
+static void nativeDestructor(JNIEnv* env, jobject javaObject) {
+ AStatsManager_unregisterPullAtomCallback(android::util::GRAPHICS_STATS);
+ env->DeleteGlobalRef(gGraphicsStatsServiceObject);
+ gGraphicsStatsServiceObject = nullptr;
+}
+
+static const JNINativeMethod sMethods[] =
+ {{"nGetAshmemSize", "()I", (void*)getAshmemSize},
+ {"nCreateDump", "(IZ)J", (void*)createDump},
+ {"nAddToDump", "(JLjava/lang/String;Ljava/lang/String;JJJ[B)V", (void*)addToDump},
+ {"nAddToDump", "(JLjava/lang/String;)V", (void*)addFileToDump},
+ {"nFinishDump", "(J)V", (void*)finishDump},
+ {"nFinishDumpInMemory", "(JJZ)V", (void*)finishDumpInMemory},
+ {"nSaveBuffer", "(Ljava/lang/String;Ljava/lang/String;JJJ[B)V", (void*)saveBuffer},
+ {"nativeInit", "()V", (void*)nativeInit},
+ {"nativeDestructor", "()V", (void*)nativeDestructor}};
+
+int register_android_graphics_GraphicsStatsService(JNIEnv* env) {
+ jclass graphicsStatsService_class =
+ FindClassOrDie(env, "android/graphics/GraphicsStatsService");
+ gGraphicsStatsService_pullGraphicsStatsMethodID =
+ GetMethodIDOrDie(env, graphicsStatsService_class, "pullGraphicsStats", "(ZJ)V");
+ return jniRegisterNativeMethods(env, "android/graphics/GraphicsStatsService", sMethods,
+ NELEM(sMethods));
+}
+
+} // namespace android
diff --git a/core/jni/android/graphics/fonts/Font.cpp b/core/jni/android/graphics/fonts/Font.cpp
index bb0654d255c0..8d84e870d205 100644
--- a/core/jni/android/graphics/fonts/Font.cpp
+++ b/core/jni/android/graphics/fonts/Font.cpp
@@ -33,8 +33,8 @@
#include <hwui/MinikinSkia.h>
#include <hwui/Typeface.h>
-#include <utils/FatVector.h>
#include <minikin/FontFamily.h>
+#include <ui/FatVector.h>
#include <memory>
@@ -157,7 +157,7 @@ static jlong Font_Builder_build(JNIEnv* env, jobject clazz, jlong builderPtr, jo
sk_sp<SkData> data(SkData::MakeWithProc(fontPtr, fontSize,
release_global_ref, reinterpret_cast<void*>(fontRef)));
- uirenderer::FatVector<SkFontArguments::Axis, 2> skiaAxes;
+ FatVector<SkFontArguments::Axis, 2> skiaAxes;
for (const auto& axis : builder->axes) {
skiaAxes.emplace_back(SkFontArguments::Axis{axis.axisTag, axis.value});
}
diff --git a/core/proto/android/app/appexitinfo.proto b/core/proto/android/app/appexitinfo.proto
index e23f150fab25..6a4922000805 100644
--- a/core/proto/android/app/appexitinfo.proto
+++ b/core/proto/android/app/appexitinfo.proto
@@ -178,8 +178,8 @@ message ApplicationExitInfoProto {
}
optional Importance importance = 10;
- optional int32 pss = 11;
- optional int32 rss = 12;
+ optional int64 pss = 11;
+ optional int64 rss = 12;
optional int64 timestamp = 13;
optional string description = 14;
}
diff --git a/core/proto/android/app/settings_enums.proto b/core/proto/android/app/settings_enums.proto
index c14d99c5d3fb..cc257973b860 100644
--- a/core/proto/android/app/settings_enums.proto
+++ b/core/proto/android/app/settings_enums.proto
@@ -708,6 +708,12 @@ enum Action {
// ACTION: Deny "Access all files" for an app
APP_SPECIAL_PERMISSION_MANAGE_EXT_STRG_DENY = 1731;
+
+ // ACTION: Battery feature usage
+ ACTION_BATTERY_OPTION_FEATURE_USAGE = 1732;
+
+ // ACTION: Battery feature runtime event
+ ACTION_BATTERY_OPTION_RUNTIME_EVENT = 1733;
}
/**
diff --git a/core/proto/android/server/jobscheduler.proto b/core/proto/android/server/jobscheduler.proto
index 303d62dbb30a..546c5a092a50 100644
--- a/core/proto/android/server/jobscheduler.proto
+++ b/core/proto/android/server/jobscheduler.proto
@@ -219,12 +219,8 @@ message ConstantsProto {
// The maximum number of background jobs we allow when the system is in a
// critical memory state.
optional int32 bg_critical_job_count = 14;
- // The maximum number of times we allow a job to have itself rescheduled
- // before giving up on it, for standard jobs.
- optional int32 max_standard_reschedule_count = 15;
- // The maximum number of times we allow a job to have itself rescheduled
- // before giving up on it, for jobs that are executing work.
- optional int32 max_work_reschedule_count = 16;
+ reserved 15; // max_standard_reschedule_count
+ reserved 16; // max_work_reschedule_count
// The minimum backoff time to allow for linear backoff.
optional int64 min_linear_backoff_time_ms = 17;
// The minimum backoff time to allow for exponential backoff.
diff --git a/core/proto/android/service/OWNERS b/core/proto/android/service/OWNERS
new file mode 100644
index 000000000000..70cb50f75362
--- /dev/null
+++ b/core/proto/android/service/OWNERS
@@ -0,0 +1 @@
+per-file sensor_service.proto = arthuri@google.com, bduddie@google.com, stange@google.com
diff --git a/core/proto/android/service/sensor_service.proto b/core/proto/android/service/sensor_service.proto
index 8598f86a7f28..48f6670b59fe 100644
--- a/core/proto/android/service/sensor_service.proto
+++ b/core/proto/android/service/sensor_service.proto
@@ -39,7 +39,7 @@ message SensorServiceProto {
OP_MODE_RESTRICTED = 2;
OP_MODE_DATA_INJECTION = 3;
}
-
+ optional sint32 init_status = 16;
optional int64 current_time_ms = 1;
optional SensorDeviceProto sensor_device = 2;
optional SensorListProto sensors = 3;
@@ -56,6 +56,8 @@ message SensorServiceProto {
repeated SensorEventConnectionProto active_connections = 13;
repeated SensorDirectConnectionProto direct_connections = 14;
repeated SensorRegistrationInfoProto previous_registrations = 15;
+
+ // Next tag: 17
}
// Proto dump of android::SensorDevice
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 6d63a532ae14..ff696715e94d 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1535,7 +1535,7 @@
@hide
-->
<permission android:name="android.permission.ACCESS_CONTEXT_HUB"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature|privileged" />
<uses-permission android:name="android.permission.ACCESS_CONTEXT_HUB"/>
<!-- @SystemApi Allows an application to create mock location providers for testing.
diff --git a/core/res/res/drawable-nodpi/platlogo.xml b/core/res/res/drawable-nodpi/platlogo.xml
index 46e8f64753ac..b01eb3944b50 100644
--- a/core/res/res/drawable-nodpi/platlogo.xml
+++ b/core/res/res/drawable-nodpi/platlogo.xml
@@ -1,31 +1,50 @@
-<!--
-Copyright (C) 2020 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.
--->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="240dp"
- android:height="240dp"
- android:viewportWidth="24"
- android:viewportHeight="24">
+ android:width="512dp"
+ android:height="512dp"
+ android:viewportWidth="512"
+ android:viewportHeight="512">
<path
- android:fillColor="#000"
- android:pathData="M16 4c-2.2 0-4 1.8-4 4v4H4V8c0-2.2 1.8-4 4-4h8z"/>
+ android:fillColor="#F86734"
+ android:pathData="M416.23 236.62h-10.67c-1.46 0-2.65-1.19-2.65-2.65v-9.85c0-1.47 1.19-2.65 2.65-2.65h23.37c1.47 0 2.66 1.19 2.66 2.65v66.9c0 1.46-1.2 2.65-2.66 2.65H418.9c-1.47 0-2.66-1.19-2.66-2.65v-54.4z"/>
<path
- android:fillColor="#000"
- android:pathData="M8 20c2.2 0 4-1.8 4-4v-4H4v8h4z"/>
+ android:fillColor="#F86734"
+ android:pathData="M455.51 236.62h-10.67c-1.47 0-2.65-1.19-2.65-2.65v-9.85c0-1.47 1.18-2.65 2.65-2.65h23.37c1.47 0 2.66 1.19 2.66 2.65v66.9c0 1.46-1.2 2.65-2.66 2.65h-10.05c-1.46 0-2.65-1.19-2.65-2.65v-54.4z"/>
<path
- android:fillColor="#80000000"
- android:pathData="M16 12c2.2 0 4-1.8 4-4V4h-8v8h4z"/>
+ android:fillColor="#D6F0FF"
+ android:pathData="M364.12 400.25a4.34 4.34 0 1 0 0 8.68a4.34 4.34 0 1 0 0-8.68z"/>
+ <path
+ android:fillColor="#D6F0FF"
+ android:pathData="M275.46 433.53a4.84 4.84 0 1 0 0 9.68a4.84 4.84 0 1 0 0-9.68z"/>
+ <path
+ android:fillColor="#D6F0FF"
+ android:pathData="M184.52 418.83a5.36 5.36 0 1 0 0 10.72a5.36 5.36 0 1 0 0-10.72z"/>
+ <path
+ android:fillColor="#D6F0FF"
+ android:pathData="M110.42 359.19a5.89 5.89 0 1 0 0 11.78a5.89 5.89 0 1 0 0-11.78z"/>
+ <path
+ android:fillColor="#D6F0FF"
+ android:pathData="M75.94 270.17a6.43 6.43 0 1 0 0 12.86a6.43 6.43 0 1 0 0-12.86z"/>
+ <path
+ android:fillColor="#D6F0FF"
+ android:pathData="M89.48 178.57a6.98 6.98 0 1 0 0 13.96a6.98 6.98 0 1 0 0-13.96z"/>
+ <path
+ android:fillColor="#D6F0FF"
+ android:pathData="M147.97 103.54a7.54 7.54 0 1 0 0 15.08a7.54 7.54 0 1 0 0-15.08z"/>
+ <path
+ android:fillColor="#D6F0FF"
+ android:pathData="M236.63 66.7a8.1 8.1 0 1 0 0 16.2a8.1 8.1 0 1 0 0-16.2z"/>
+ <path
+ android:fillColor="#D6F0FF"
+ android:pathData="M327.09 78.3a8.66 8.66 0 1 0 0 17.32a8.66 8.66 0 1 0 0-17.32z"/>
+ <path
+ android:fillColor="#D6F0FF"
+ android:pathData="M401.05 136.97a9.22 9.22 0 1 0 0 18.44a9.22 9.22 0 1 0 0-18.44z"/>
+ <group>
+ <path
+ android:fillColor="#3DDB85"
+ android:pathData="M255.45 129.46a128.11 128.11 0 1 0 0 256.22a128.11 128.11 0 1 0 0-256.22z"/>
+ <path
+ android:fillColor="#FFF"
+ android:pathData="M339.23 236.09a21.48 21.48 0 1 0 0 42.96a21.48 21.48 0 1 0 0-42.96z"/>
+ </group>
</vector>
-
diff --git a/core/res/res/drawable-nodpi/stat_sys_adb.xml b/core/res/res/drawable-nodpi/stat_sys_adb.xml
index 0e9aab2ab59d..700781b1d0b1 100644
--- a/core/res/res/drawable-nodpi/stat_sys_adb.xml
+++ b/core/res/res/drawable-nodpi/stat_sys_adb.xml
@@ -1,17 +1,17 @@
-<!--
-Copyright (C) 2020 The Android Open Source Project
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2020 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
+ 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
+ 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.
+ 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.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
@@ -19,12 +19,22 @@ Copyright (C) 2020 The Android Open Source Project
android:viewportWidth="24"
android:viewportHeight="24">
<path
- android:fillColor="#000"
- android:pathData="M16 4c-2.2 0-4 1.8-4 4v4H4V8c0-2.2 1.8-4 4-4h8z"/>
- <path
- android:fillColor="#000"
- android:pathData="M8 20c2.2 0 4-1.8 4-4v-4H4v8h4z"/>
- <path
- android:fillColor="#80000000"
- android:pathData="M16 12c2.2 0 4-1.8 4-4V4h-8v8h4z"/>
+ android:fillColor="#FFFFFF"
+ android:pathData="
+M 12,1
+A 11 11 0 0 0 1,12
+A 11 11 0 1 0 12,1
+Z
+
+M 12.5,8
+a 3,3 0 0 1 6,0
+a 3,3 0 0 1 -6,0
+Z
+
+M 5.5,8
+a 3,3 0 0 1 6,0
+l 0,8
+a 3,3 0 0 1 -6,0
+Z
+"/>
</vector>
diff --git a/core/res/res/drawable/tab_indicator_resolver.xml b/core/res/res/drawable/tab_indicator_resolver.xml
new file mode 100644
index 000000000000..ff16d81a6383
--- /dev/null
+++ b/core/res/res/drawable/tab_indicator_resolver.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 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.
+-->
+
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
+ android:paddingMode="nest">
+ <item>
+ <ripple android:color="@color/tab_highlight_material">
+ <item android:id="@id/mask">
+ <color android:color="@color/white" />
+ </item>
+ </ripple>
+ </item>
+ <item android:gravity="bottom">
+ <shape android:shape="rectangle"
+ android:tint="@color/resolver_tabs_active_color">
+ <size android:height="2dp" />
+ <solid android:color="@color/tab_indicator_material" />
+ </shape>
+ </item>
+ <item android:bottom="2dp"
+ android:drawable="@color/transparent" />
+</layer-list>
diff --git a/core/res/res/layout/tab_indicator_resolver.xml b/core/res/res/layout/tab_indicator_resolver.xml
new file mode 100644
index 000000000000..2038da656ee3
--- /dev/null
+++ b/core/res/res/layout/tab_indicator_resolver.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 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.
+ -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_height="?android:attr/actionBarSize"
+ android:orientation="horizontal"
+ style="@android:style/Widget.Material.Resolver.Tab">
+
+ <ImageView
+ android:id="@android:id/icon"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:visibility="gone" />
+
+ <TextView
+ android:id="@android:id/title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:textAllCaps="false"
+ style="@android:style/Widget.Material.TabText" />
+
+</LinearLayout>
diff --git a/core/res/res/values-night/colors.xml b/core/res/res/values-night/colors.xml
index c5e72f012a21..33caeb65c2f8 100644
--- a/core/res/res/values-night/colors.xml
+++ b/core/res/res/values-night/colors.xml
@@ -32,4 +32,6 @@
<color name="chooser_row_divider">@color/list_divider_color_dark</color>
<color name="chooser_gradient_background">@color/loading_gradient_background_color_dark</color>
<color name="chooser_gradient_highlight">@color/loading_gradient_highlight_color_dark</color>
+
+ <color name="resolver_tabs_active_color">#FF8AB4F8</color>
</resources>
diff --git a/core/res/res/values/themes_device_defaults.xml b/core/res/res/values/themes_device_defaults.xml
index cef21db1e0f8..81ec27841aa7 100644
--- a/core/res/res/values/themes_device_defaults.xml
+++ b/core/res/res/values/themes_device_defaults.xml
@@ -1679,6 +1679,15 @@ easier.
<item name="listPreferredItemPaddingStart">?attr/dialogPreferredPadding</item>
<item name="listPreferredItemPaddingEnd">?attr/dialogPreferredPadding</item>
<item name="navigationBarColor">@android:color/transparent</item>
+ <item name="tabWidgetStyle">@style/Widget.DeviceDefault.Resolver.TabWidget</item>
+ </style>
+
+ <style name="Widget.DeviceDefault.Resolver.TabWidget" parent="Widget.DeviceDefault.TabWidget">
+ <item name="tabLayout">@layout/tab_indicator_resolver</item>
+ </style>
+
+ <style name="Widget.Material.Resolver.Tab" parent="Widget.Material.Tab">
+ <item name="background">@drawable/tab_indicator_resolver</item>
</style>
<style name="Theme.DeviceDefault.Resolver" parent="Theme.DeviceDefault.ResolverCommon">
diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml
index 59335a595334..718ca46a4f18 100644
--- a/core/tests/coretests/AndroidManifest.xml
+++ b/core/tests/coretests/AndroidManifest.xml
@@ -1330,6 +1330,12 @@
android:process=":FakeProvider">
</provider>
+ <provider
+ android:name="android.content.SlowProvider"
+ android:authorities="android.content.SlowProvider"
+ android:process=":SlowProvider">
+ </provider>
+
<!-- Application components used for os tests -->
<service android:name="android.os.MessengerService"
diff --git a/core/tests/coretests/src/android/app/NotificationHistoryTest.java b/core/tests/coretests/src/android/app/NotificationHistoryTest.java
index 0a21875fd77d..d1608d055604 100644
--- a/core/tests/coretests/src/android/app/NotificationHistoryTest.java
+++ b/core/tests/coretests/src/android/app/NotificationHistoryTest.java
@@ -234,6 +234,40 @@ public class NotificationHistoryTest {
}
@Test
+ public void testRemoveNotificationFromWrite() {
+ NotificationHistory history = new NotificationHistory();
+
+ List<HistoricalNotification> postRemoveExpectedEntries = new ArrayList<>();
+ List<String> postRemoveExpectedStrings = new ArrayList<>();
+ for (int i = 1; i <= 10; i++) {
+ HistoricalNotification n = getHistoricalNotification("pkg", i);
+
+ if (987654323 != n.getPostedTimeMs()) {
+ postRemoveExpectedStrings.add(n.getPackage());
+ postRemoveExpectedStrings.add(n.getChannelName());
+ postRemoveExpectedStrings.add(n.getChannelId());
+ postRemoveExpectedEntries.add(n);
+ }
+
+ history.addNotificationToWrite(n);
+ }
+
+ history.poolStringsFromNotifications();
+
+ assertThat(history.getNotificationsToWrite().size()).isEqualTo(10);
+ // 1 package name and 10 unique channel names and ids
+ assertThat(history.getPooledStringsToWrite().length).isEqualTo(21);
+
+ history.removeNotificationFromWrite("pkg", 987654323);
+
+
+ // 1 package names and 9 * 2 unique channel names and ids
+ assertThat(history.getPooledStringsToWrite().length).isEqualTo(19);
+ assertThat(history.getNotificationsToWrite())
+ .containsExactlyElementsIn(postRemoveExpectedEntries);
+ }
+
+ @Test
public void testParceling() {
NotificationHistory history = new NotificationHistory();
diff --git a/core/tests/coretests/src/android/content/ContentResolverTest.java b/core/tests/coretests/src/android/content/ContentResolverTest.java
index 9dcce1e51e0b..6dc7392945d8 100644
--- a/core/tests/coretests/src/android/content/ContentResolverTest.java
+++ b/core/tests/coretests/src/android/content/ContentResolverTest.java
@@ -209,4 +209,13 @@ public class ContentResolverTest {
String type = mResolver.getType(Uri.parse("content://android.content.FakeProviderRemote"));
assertEquals("fake/remote", type);
}
+
+
+ @Test
+ public void testGetType_slowProvider() {
+ // This provider is running in a different process and is intentionally slow to start.
+ // We are trying to confirm that it does not cause an ANR
+ String type = mResolver.getType(Uri.parse("content://android.content.SlowProvider"));
+ assertEquals("slow", type);
+ }
}
diff --git a/core/tests/coretests/src/android/content/SlowProvider.java b/core/tests/coretests/src/android/content/SlowProvider.java
new file mode 100644
index 000000000000..aba32e836e80
--- /dev/null
+++ b/core/tests/coretests/src/android/content/SlowProvider.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2020 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.content;
+
+import android.database.Cursor;
+import android.net.Uri;
+
+/**
+ * A dummy content provider for tests. This provider runs in a different process from the test and
+ * is intentionally slow.
+ */
+public class SlowProvider extends ContentProvider {
+
+ private static final int ON_CREATE_LATENCY_MILLIS = 3000;
+
+ @Override
+ public boolean onCreate() {
+ try {
+ Thread.sleep(ON_CREATE_LATENCY_MILLIS);
+ } catch (InterruptedException e) {
+ // Ignore
+ }
+ return true;
+ }
+
+ @Override
+ public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+ String sortOrder) {
+ return null;
+ }
+
+ @Override
+ public String getType(Uri uri) {
+ return "slow";
+ }
+
+ @Override
+ public Uri insert(Uri uri, ContentValues values) {
+ return null;
+ }
+
+ @Override
+ public int delete(Uri uri, String selection, String[] selectionArgs) {
+ return 0;
+ }
+
+ @Override
+ public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+ return 0;
+ }
+}
diff --git a/services/core/java/com/android/server/GraphicsStatsService.java b/graphics/java/android/graphics/GraphicsStatsService.java
index 5179fa7a6eb5..8dfd6ee92a9a 100644
--- a/services/core/java/com/android/server/GraphicsStatsService.java
+++ b/graphics/java/android/graphics/GraphicsStatsService.java
@@ -14,8 +14,9 @@
* limitations under the License.
*/
-package com.android.server;
+package android.graphics;
+import android.annotation.SystemApi;
import android.app.AlarmManager;
import android.app.AppOpsManager;
import android.content.Context;
@@ -26,13 +27,14 @@ import android.os.Environment;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
-import android.os.MemoryFile;
import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.RemoteException;
+import android.os.SharedMemory;
import android.os.Trace;
import android.os.UserHandle;
+import android.system.ErrnoException;
import android.util.Log;
import android.view.IGraphicsStats;
import android.view.IGraphicsStatsCallback;
@@ -45,6 +47,7 @@ import java.io.FileDescriptor;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
+import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
@@ -84,8 +87,8 @@ public class GraphicsStatsService extends IGraphicsStats.Stub {
// This isn't static because we need this to happen after registerNativeMethods, however
// the class is loaded (and thus static ctor happens) before that occurs.
- private final int ASHMEM_SIZE = nGetAshmemSize();
- private final byte[] ZERO_DATA = new byte[ASHMEM_SIZE];
+ private final int mAshmemSize = nGetAshmemSize();
+ private final byte[] mZeroData = new byte[mAshmemSize];
private final Context mContext;
private final AppOpsManager mAppOps;
@@ -97,6 +100,7 @@ public class GraphicsStatsService extends IGraphicsStats.Stub {
private Handler mWriteOutHandler;
private boolean mRotateIsScheduled = false;
+ @SystemApi
public GraphicsStatsService(Context context) {
mContext = context;
mAppOps = context.getSystemService(AppOpsManager.class);
@@ -108,7 +112,8 @@ public class GraphicsStatsService extends IGraphicsStats.Stub {
throw new IllegalStateException("Graphics stats directory does not exist: "
+ mGraphicsStatsDir.getAbsolutePath());
}
- HandlerThread bgthread = new HandlerThread("GraphicsStats-disk", Process.THREAD_PRIORITY_BACKGROUND);
+ HandlerThread bgthread = new HandlerThread("GraphicsStats-disk",
+ Process.THREAD_PRIORITY_BACKGROUND);
bgthread.start();
mWriteOutHandler = new Handler(bgthread.getLooper(), new Handler.Callback() {
@@ -159,7 +164,7 @@ public class GraphicsStatsService extends IGraphicsStats.Stub {
active.mCallback.onRotateGraphicsStatsBuffer();
} catch (RemoteException e) {
Log.w(TAG, String.format("Failed to notify '%s' (pid=%d) to rotate buffers",
- active.mInfo.packageName, active.mPid), e);
+ active.mInfo.mPackageName, active.mPid), e);
}
}
// Give a few seconds for everyone to rotate before doing the cleanup
@@ -167,8 +172,8 @@ public class GraphicsStatsService extends IGraphicsStats.Stub {
}
@Override
- public ParcelFileDescriptor requestBufferForProcess(String packageName, IGraphicsStatsCallback token)
- throws RemoteException {
+ public ParcelFileDescriptor requestBufferForProcess(String packageName,
+ IGraphicsStatsCallback token) throws RemoteException {
int uid = Binder.getCallingUid();
int pid = Binder.getCallingPid();
ParcelFileDescriptor pfd = null;
@@ -196,7 +201,7 @@ public class GraphicsStatsService extends IGraphicsStats.Stub {
// current day.
// This method is invoked from native code only.
@SuppressWarnings({"UnusedDeclaration"})
- private long pullGraphicsStats(boolean lastFullDay) throws RemoteException {
+ private void pullGraphicsStats(boolean lastFullDay, long pulledData) throws RemoteException {
int uid = Binder.getCallingUid();
// DUMP and PACKAGE_USAGE_STATS permissions are required to invoke this method.
@@ -213,13 +218,13 @@ public class GraphicsStatsService extends IGraphicsStats.Stub {
long callingIdentity = Binder.clearCallingIdentity();
try {
- return pullGraphicsStatsImpl(lastFullDay);
+ pullGraphicsStatsImpl(lastFullDay, pulledData);
} finally {
Binder.restoreCallingIdentity(callingIdentity);
}
}
- private long pullGraphicsStatsImpl(boolean lastFullDay) {
+ private void pullGraphicsStatsImpl(boolean lastFullDay, long pulledData) {
long targetDay;
if (lastFullDay) {
// Get stats from yesterday. Stats stay constant, because the day is over.
@@ -235,7 +240,7 @@ public class GraphicsStatsService extends IGraphicsStats.Stub {
buffers = new ArrayList<>(mActive.size());
for (int i = 0; i < mActive.size(); i++) {
ActiveBuffer buffer = mActive.get(i);
- if (buffer.mInfo.startTime == targetDay) {
+ if (buffer.mInfo.mStartTime == targetDay) {
try {
buffers.add(new HistoricalBuffer(buffer));
} catch (IOException ex) {
@@ -267,18 +272,7 @@ public class GraphicsStatsService extends IGraphicsStats.Stub {
}
}
} finally {
- return nFinishDumpInMemory(dump);
- }
- }
-
- private ParcelFileDescriptor getPfd(MemoryFile file) {
- try {
- if (!file.getFileDescriptor().valid()) {
- throw new IllegalStateException("Invalid file descriptor");
- }
- return ParcelFileDescriptor.dup(file.getFileDescriptor());
- } catch (IOException ex) {
- throw new IllegalStateException("Failed to get PFD from memory file", ex);
+ nFinishDumpInMemory(dump, pulledData, lastFullDay);
}
}
@@ -286,7 +280,7 @@ public class GraphicsStatsService extends IGraphicsStats.Stub {
int uid, int pid, String packageName, long versionCode) throws RemoteException {
ActiveBuffer buffer = fetchActiveBuffersLocked(token, uid, pid, packageName, versionCode);
scheduleRotateLocked();
- return getPfd(buffer.mProcessBuffer);
+ return buffer.getPfd();
}
private Calendar normalizeDate(long timestamp) {
@@ -301,13 +295,15 @@ public class GraphicsStatsService extends IGraphicsStats.Stub {
private File pathForApp(BufferInfo info) {
String subPath = String.format("%d/%s/%d/total",
- normalizeDate(info.startTime).getTimeInMillis(), info.packageName, info.versionCode);
+ normalizeDate(info.mStartTime).getTimeInMillis(), info.mPackageName,
+ info.mVersionCode);
return new File(mGraphicsStatsDir, subPath);
}
private void saveBuffer(HistoricalBuffer buffer) {
if (Trace.isTagEnabled(Trace.TRACE_TAG_SYSTEM_SERVER)) {
- Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "saving graphicsstats for " + buffer.mInfo.packageName);
+ Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER,
+ "saving graphicsstats for " + buffer.mInfo.mPackageName);
}
synchronized (mFileAccessLock) {
File path = pathForApp(buffer.mInfo);
@@ -317,8 +313,9 @@ public class GraphicsStatsService extends IGraphicsStats.Stub {
Log.w(TAG, "Unable to create path: '" + parent.getAbsolutePath() + "'");
return;
}
- nSaveBuffer(path.getAbsolutePath(), buffer.mInfo.packageName, buffer.mInfo.versionCode,
- buffer.mInfo.startTime, buffer.mInfo.endTime, buffer.mData);
+ nSaveBuffer(path.getAbsolutePath(), buffer.mInfo.mPackageName,
+ buffer.mInfo.mVersionCode, buffer.mInfo.mStartTime, buffer.mInfo.mEndTime,
+ buffer.mData);
}
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
}
@@ -365,7 +362,7 @@ public class GraphicsStatsService extends IGraphicsStats.Stub {
HistoricalBuffer data = new HistoricalBuffer(buffer);
Message.obtain(mWriteOutHandler, SAVE_BUFFER, data).sendToTarget();
} catch (IOException e) {
- Log.w(TAG, "Failed to copy graphicsstats from " + buffer.mInfo.packageName, e);
+ Log.w(TAG, "Failed to copy graphicsstats from " + buffer.mInfo.mPackageName, e);
}
buffer.closeAllBuffers();
}
@@ -386,7 +383,7 @@ public class GraphicsStatsService extends IGraphicsStats.Stub {
if (buffer.mPid == pid
&& buffer.mUid == uid) {
// If the buffer is too old we remove it and return a new one
- if (buffer.mInfo.startTime < today) {
+ if (buffer.mInfo.mStartTime < today) {
buffer.binderDied();
break;
} else {
@@ -410,8 +407,8 @@ public class GraphicsStatsService extends IGraphicsStats.Stub {
HistoricalBuffer buffer = buffers.get(i);
File path = pathForApp(buffer.mInfo);
skipFiles.add(path);
- nAddToDump(dump, path.getAbsolutePath(), buffer.mInfo.packageName,
- buffer.mInfo.versionCode, buffer.mInfo.startTime, buffer.mInfo.endTime,
+ nAddToDump(dump, path.getAbsolutePath(), buffer.mInfo.mPackageName,
+ buffer.mInfo.mVersionCode, buffer.mInfo.mStartTime, buffer.mInfo.mEndTime,
buffer.mData);
}
return skipFiles;
@@ -478,20 +475,20 @@ public class GraphicsStatsService extends IGraphicsStats.Stub {
long versionCode, long startTime, long endTime, byte[] data);
private static native void nAddToDump(long dump, String path);
private static native void nFinishDump(long dump);
- private static native long nFinishDumpInMemory(long dump);
+ private static native void nFinishDumpInMemory(long dump, long pulledData, boolean lastFullDay);
private static native void nSaveBuffer(String path, String packageName, long versionCode,
long startTime, long endTime, byte[] data);
private final class BufferInfo {
- final String packageName;
- final long versionCode;
- long startTime;
- long endTime;
+ final String mPackageName;
+ final long mVersionCode;
+ long mStartTime;
+ long mEndTime;
BufferInfo(String packageName, long versionCode, long startTime) {
- this.packageName = packageName;
- this.versionCode = versionCode;
- this.startTime = startTime;
+ this.mPackageName = packageName;
+ this.mVersionCode = versionCode;
+ this.mStartTime = startTime;
}
}
@@ -501,7 +498,8 @@ public class GraphicsStatsService extends IGraphicsStats.Stub {
final int mPid;
final IGraphicsStatsCallback mCallback;
final IBinder mToken;
- MemoryFile mProcessBuffer;
+ SharedMemory mProcessBuffer;
+ ByteBuffer mMapping;
ActiveBuffer(IGraphicsStatsCallback token, int uid, int pid, String packageName,
long versionCode)
@@ -512,8 +510,14 @@ public class GraphicsStatsService extends IGraphicsStats.Stub {
mCallback = token;
mToken = mCallback.asBinder();
mToken.linkToDeath(this, 0);
- mProcessBuffer = new MemoryFile("GFXStats-" + pid, ASHMEM_SIZE);
- mProcessBuffer.writeBytes(ZERO_DATA, 0, 0, ASHMEM_SIZE);
+ try {
+ mProcessBuffer = SharedMemory.create("GFXStats-" + pid, mAshmemSize);
+ mMapping = mProcessBuffer.mapReadWrite();
+ } catch (ErrnoException ex) {
+ ex.rethrowAsIOException();
+ }
+ mMapping.position(0);
+ mMapping.put(mZeroData, 0, mAshmemSize);
}
@Override
@@ -523,20 +527,40 @@ public class GraphicsStatsService extends IGraphicsStats.Stub {
}
void closeAllBuffers() {
+ if (mMapping != null) {
+ SharedMemory.unmap(mMapping);
+ mMapping = null;
+ }
if (mProcessBuffer != null) {
mProcessBuffer.close();
mProcessBuffer = null;
}
}
+
+ ParcelFileDescriptor getPfd() {
+ try {
+ return mProcessBuffer.getFdDup();
+ } catch (IOException ex) {
+ throw new IllegalStateException("Failed to get PFD from memory file", ex);
+ }
+ }
+
+ void readBytes(byte[] buffer, int count) throws IOException {
+ if (mMapping == null) {
+ throw new IOException("SharedMemory has been deactivated");
+ }
+ mMapping.position(0);
+ mMapping.get(buffer, 0, count);
+ }
}
private final class HistoricalBuffer {
final BufferInfo mInfo;
- final byte[] mData = new byte[ASHMEM_SIZE];
+ final byte[] mData = new byte[mAshmemSize];
HistoricalBuffer(ActiveBuffer active) throws IOException {
mInfo = active.mInfo;
- mInfo.endTime = System.currentTimeMillis();
- active.mProcessBuffer.readBytes(mData, 0, 0, ASHMEM_SIZE);
+ mInfo.mEndTime = System.currentTimeMillis();
+ active.readBytes(mData, mAshmemSize);
}
}
}
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index 51270f5bcebd..301d1afc6c13 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -92,9 +92,12 @@ cc_defaults {
"libandroidfw",
"libcrypto",
"libsync",
+ "libstatspull",
+ "libstatssocket",
],
static_libs: [
"libEGL_blobCache",
+ "libprotoutil",
],
},
host: {
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index 6761435a8171..31e45558139d 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -27,7 +27,6 @@
#include "DamageAccumulator.h"
#include "pipeline/skia/SkiaDisplayList.h"
#endif
-#include "utils/FatVector.h"
#include "utils/MathUtils.h"
#include "utils/StringUtils.h"
#include "utils/TraceUtils.h"
@@ -37,6 +36,7 @@
#include <atomic>
#include <sstream>
#include <string>
+#include <ui/FatVector.h>
namespace android {
namespace uirenderer {
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index d55e5b0ce836..c0ec2174bb35 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -27,6 +27,8 @@
#include <androidfw/ResourceTypes.h>
+#include <ui/FatVector.h>
+
#include "AnimatorManager.h"
#include "CanvasTransform.h"
#include "Debug.h"
@@ -35,7 +37,6 @@
#include "RenderProperties.h"
#include "pipeline/skia/SkiaDisplayList.h"
#include "pipeline/skia/SkiaLayer.h"
-#include "utils/FatVector.h"
#include <vector>
diff --git a/libs/hwui/pipeline/skia/ReorderBarrierDrawables.h b/libs/hwui/pipeline/skia/ReorderBarrierDrawables.h
index cfc0f9b258da..d669f84c5ee2 100644
--- a/libs/hwui/pipeline/skia/ReorderBarrierDrawables.h
+++ b/libs/hwui/pipeline/skia/ReorderBarrierDrawables.h
@@ -21,7 +21,7 @@
#include <SkCanvas.h>
#include <SkDrawable.h>
-#include <utils/FatVector.h>
+#include <ui/FatVector.h>
namespace android {
namespace uirenderer {
diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp
index cae3e3b5188c..206b58f62ea7 100644
--- a/libs/hwui/renderthread/RenderThread.cpp
+++ b/libs/hwui/renderthread/RenderThread.cpp
@@ -27,7 +27,6 @@
#include "pipeline/skia/SkiaOpenGLPipeline.h"
#include "pipeline/skia/SkiaVulkanPipeline.h"
#include "renderstate/RenderState.h"
-#include "utils/FatVector.h"
#include "utils/TimeUtils.h"
#include "utils/TraceUtils.h"
@@ -40,6 +39,8 @@
#include <utils/Mutex.h>
#include <thread>
+#include <ui/FatVector.h>
+
namespace android {
namespace uirenderer {
namespace renderthread {
diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp
index a5355fc3499d..ba70afc8b8d2 100644
--- a/libs/hwui/renderthread/VulkanManager.cpp
+++ b/libs/hwui/renderthread/VulkanManager.cpp
@@ -23,13 +23,13 @@
#include <GrContext.h>
#include <GrTypes.h>
#include <android/sync.h>
+#include <ui/FatVector.h>
#include <vk/GrVkExtensions.h>
#include <vk/GrVkTypes.h>
#include "Properties.h"
#include "RenderThread.h"
#include "renderstate/RenderState.h"
-#include "utils/FatVector.h"
#include "utils/TraceUtils.h"
namespace android {
diff --git a/libs/hwui/service/GraphicsStatsService.cpp b/libs/hwui/service/GraphicsStatsService.cpp
index c4186174b637..644d5fbd5bf9 100644
--- a/libs/hwui/service/GraphicsStatsService.cpp
+++ b/libs/hwui/service/GraphicsStatsService.cpp
@@ -26,9 +26,9 @@
#include <sys/types.h>
#include <unistd.h>
-#include <algorithm>
-#include <map>
-#include <vector>
+#include <android/util/ProtoOutputStream.h>
+#include <stats_event.h>
+#include <statslog.h>
#include "JankTracker.h"
#include "protos/graphicsstats.pb.h"
@@ -61,7 +61,7 @@ public:
}
}
bool valid() { return mFd != -1; }
- operator int() { return mFd; } // NOLINT(google-explicit-constructor)
+ operator int() { return mFd; } // NOLINT(google-explicit-constructor)
private:
int mFd;
@@ -485,79 +485,82 @@ void GraphicsStatsService::finishDump(Dump* dump) {
delete dump;
}
-class MemOutputStreamLite : public io::ZeroCopyOutputStream {
-public:
- explicit MemOutputStreamLite() : mCopyAdapter(), mImpl(&mCopyAdapter) {}
- virtual ~MemOutputStreamLite() {}
-
- virtual bool Next(void** data, int* size) override { return mImpl.Next(data, size); }
-
- virtual void BackUp(int count) override { mImpl.BackUp(count); }
-
- virtual int64 ByteCount() const override { return mImpl.ByteCount(); }
-
- bool Flush() { return mImpl.Flush(); }
-
- void copyData(const DumpMemoryFn& reader, void* param1, void* param2) {
- int bufferOffset = 0;
- int totalSize = mCopyAdapter.mBuffersSize - mCopyAdapter.mCurrentBufferUnusedSize;
- int totalDataLeft = totalSize;
- for (auto& it : mCopyAdapter.mBuffers) {
- int bufferSize = std::min(totalDataLeft, (int)it.size()); // last buffer is not full
- reader(it.data(), bufferOffset, bufferSize, totalSize, param1, param2);
- bufferOffset += bufferSize;
- totalDataLeft -= bufferSize;
- }
- }
-
-private:
- struct MemAdapter : public io::CopyingOutputStream {
- // Data is stored in an array of buffers.
- // JNI SetByteArrayRegion assembles data in one continuous Java byte[] buffer.
- std::vector<std::vector<unsigned char>> mBuffers;
- int mBuffersSize = 0; // total bytes allocated in mBuffers
- int mCurrentBufferUnusedSize = 0; // unused bytes in the last buffer mBuffers.back()
- unsigned char* mCurrentBuffer = nullptr; // pointer to next free byte in mBuffers.back()
+using namespace google::protobuf;
- explicit MemAdapter() {}
- virtual ~MemAdapter() {}
+// Field ids taken from FrameTimingHistogram message in atoms.proto
+#define TIME_MILLIS_BUCKETS_FIELD_NUMBER 1
+#define FRAME_COUNTS_FIELD_NUMBER 2
+
+static void writeCpuHistogram(AStatsEvent* event,
+ const uirenderer::protos::GraphicsStatsProto& stat) {
+ util::ProtoOutputStream proto;
+ for (int bucketIndex = 0; bucketIndex < stat.histogram_size(); bucketIndex++) {
+ auto& bucket = stat.histogram(bucketIndex);
+ proto.write(android::util::FIELD_TYPE_INT32 | android::util::FIELD_COUNT_REPEATED |
+ TIME_MILLIS_BUCKETS_FIELD_NUMBER /* field id */,
+ (int)bucket.render_millis());
+ }
+ for (int bucketIndex = 0; bucketIndex < stat.histogram_size(); bucketIndex++) {
+ auto& bucket = stat.histogram(bucketIndex);
+ proto.write(android::util::FIELD_TYPE_INT64 | android::util::FIELD_COUNT_REPEATED |
+ FRAME_COUNTS_FIELD_NUMBER /* field id */,
+ (long long)bucket.frame_count());
+ }
+ std::vector<uint8_t> outVector;
+ proto.serializeToVector(&outVector);
+ AStatsEvent_writeByteArray(event, outVector.data(), outVector.size());
+}
- virtual bool Write(const void* buffer, int size) override {
- while (size > 0) {
- if (0 == mCurrentBufferUnusedSize) {
- mCurrentBufferUnusedSize =
- std::max(size, mBuffersSize ? 2 * mBuffersSize : 10000);
- mBuffers.emplace_back();
- mBuffers.back().resize(mCurrentBufferUnusedSize);
- mCurrentBuffer = mBuffers.back().data();
- mBuffersSize += mCurrentBufferUnusedSize;
- }
- int dataMoved = std::min(mCurrentBufferUnusedSize, size);
- memcpy(mCurrentBuffer, buffer, dataMoved);
- mCurrentBufferUnusedSize -= dataMoved;
- mCurrentBuffer += dataMoved;
- buffer = reinterpret_cast<const unsigned char*>(buffer) + dataMoved;
- size -= dataMoved;
- }
- return true;
- }
- };
+static void writeGpuHistogram(AStatsEvent* event,
+ const uirenderer::protos::GraphicsStatsProto& stat) {
+ util::ProtoOutputStream proto;
+ for (int bucketIndex = 0; bucketIndex < stat.gpu_histogram_size(); bucketIndex++) {
+ auto& bucket = stat.gpu_histogram(bucketIndex);
+ proto.write(android::util::FIELD_TYPE_INT32 | android::util::FIELD_COUNT_REPEATED |
+ TIME_MILLIS_BUCKETS_FIELD_NUMBER /* field id */,
+ (int)bucket.render_millis());
+ }
+ for (int bucketIndex = 0; bucketIndex < stat.gpu_histogram_size(); bucketIndex++) {
+ auto& bucket = stat.gpu_histogram(bucketIndex);
+ proto.write(android::util::FIELD_TYPE_INT64 | android::util::FIELD_COUNT_REPEATED |
+ FRAME_COUNTS_FIELD_NUMBER /* field id */,
+ (long long)bucket.frame_count());
+ }
+ std::vector<uint8_t> outVector;
+ proto.serializeToVector(&outVector);
+ AStatsEvent_writeByteArray(event, outVector.data(), outVector.size());
+}
- MemOutputStreamLite::MemAdapter mCopyAdapter;
- io::CopyingOutputStreamAdaptor mImpl;
-};
-void GraphicsStatsService::finishDumpInMemory(Dump* dump, const DumpMemoryFn& reader, void* param1,
- void* param2) {
- MemOutputStreamLite stream;
+void GraphicsStatsService::finishDumpInMemory(Dump* dump, AStatsEventList* data,
+ bool lastFullDay) {
dump->updateProto();
- bool success = dump->proto().SerializeToZeroCopyStream(&stream) && stream.Flush();
- delete dump;
- if (!success) {
- return;
+ auto& serviceDump = dump->proto();
+ for (int stat_index = 0; stat_index < serviceDump.stats_size(); stat_index++) {
+ auto& stat = serviceDump.stats(stat_index);
+ AStatsEvent* event = AStatsEventList_addStatsEvent(data);
+ AStatsEvent_setAtomId(event, android::util::GRAPHICS_STATS);
+ AStatsEvent_writeString(event, stat.package_name().c_str());
+ AStatsEvent_writeInt64(event, (int64_t)stat.version_code());
+ AStatsEvent_writeInt64(event, (int64_t)stat.stats_start());
+ AStatsEvent_writeInt64(event, (int64_t)stat.stats_end());
+ AStatsEvent_writeInt32(event, (int32_t)stat.pipeline());
+ AStatsEvent_writeInt32(event, (int32_t)stat.summary().total_frames());
+ AStatsEvent_writeInt32(event, (int32_t)stat.summary().missed_vsync_count());
+ AStatsEvent_writeInt32(event, (int32_t)stat.summary().high_input_latency_count());
+ AStatsEvent_writeInt32(event, (int32_t)stat.summary().slow_ui_thread_count());
+ AStatsEvent_writeInt32(event, (int32_t)stat.summary().slow_bitmap_upload_count());
+ AStatsEvent_writeInt32(event, (int32_t)stat.summary().slow_draw_count());
+ AStatsEvent_writeInt32(event, (int32_t)stat.summary().missed_deadline_count());
+ writeCpuHistogram(event, stat);
+ writeGpuHistogram(event, stat);
+ // TODO: fill in UI mainline module version, when the feature is available.
+ AStatsEvent_writeInt64(event, (int64_t)0);
+ AStatsEvent_writeBool(event, !lastFullDay);
+ AStatsEvent_build(event);
}
- stream.copyData(reader, param1, param2);
}
+
} /* namespace uirenderer */
} /* namespace android */
diff --git a/libs/hwui/service/GraphicsStatsService.h b/libs/hwui/service/GraphicsStatsService.h
index 4bed96330a52..59e21d039c9d 100644
--- a/libs/hwui/service/GraphicsStatsService.h
+++ b/libs/hwui/service/GraphicsStatsService.h
@@ -20,6 +20,7 @@
#include "JankTracker.h"
#include "utils/Macros.h"
+#include <stats_pull_atom_callback.h>
namespace android {
namespace uirenderer {
@@ -27,9 +28,6 @@ namespace protos {
class GraphicsStatsProto;
}
-typedef void (*DumpMemoryFn)(void* buffer, int bufferOffset, int bufferSize, int totalSize,
- void* param1, void* param2);
-
/*
* The exported entry points used by GraphicsStatsService.java in f/b/services/core
*
@@ -56,8 +54,8 @@ public:
int64_t startTime, int64_t endTime, const ProfileData* data);
ANDROID_API static void addToDump(Dump* dump, const std::string& path);
ANDROID_API static void finishDump(Dump* dump);
- ANDROID_API static void finishDumpInMemory(Dump* dump, const DumpMemoryFn& reader, void* param1,
- void* param2);
+ ANDROID_API static void finishDumpInMemory(Dump* dump, AStatsEventList* data,
+ bool lastFullDay);
// Visible for testing
static bool parseFromFile(const std::string& path, protos::GraphicsStatsProto* output);
diff --git a/libs/hwui/tests/unit/FatVectorTests.cpp b/libs/hwui/tests/unit/FatVectorTests.cpp
index 8523e6c9e973..6585a6249b44 100644
--- a/libs/hwui/tests/unit/FatVectorTests.cpp
+++ b/libs/hwui/tests/unit/FatVectorTests.cpp
@@ -15,7 +15,7 @@
*/
#include <gtest/gtest.h>
-#include <utils/FatVector.h>
+#include <ui/FatVector.h>
#include <tests/common/TestUtils.h>
diff --git a/libs/hwui/utils/FatVector.h b/libs/hwui/utils/FatVector.h
deleted file mode 100644
index 8cc4d1010ab6..000000000000
--- a/libs/hwui/utils/FatVector.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright 2015, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef ANDROID_FAT_VECTOR_H
-#define ANDROID_FAT_VECTOR_H
-
-#include "utils/Macros.h"
-
-#include <stddef.h>
-#include <stdlib.h>
-#include <utils/Log.h>
-#include <type_traits>
-
-#include <vector>
-
-namespace android {
-namespace uirenderer {
-
-template <typename T, size_t SIZE>
-class InlineStdAllocator {
-public:
- struct Allocation {
- PREVENT_COPY_AND_ASSIGN(Allocation);
-
- public:
- Allocation(){};
- // char array instead of T array, so memory is uninitialized, with no destructors run
- char array[sizeof(T) * SIZE];
- bool inUse = false;
- };
-
- typedef T value_type; // needed to implement std::allocator
- typedef T* pointer; // needed to implement std::allocator
-
- explicit InlineStdAllocator(Allocation& allocation) : mAllocation(allocation) {}
- InlineStdAllocator(const InlineStdAllocator& other) : mAllocation(other.mAllocation) {}
- ~InlineStdAllocator() {}
-
- T* allocate(size_t num, const void* = 0) {
- if (!mAllocation.inUse && num <= SIZE) {
- mAllocation.inUse = true;
- return (T*)mAllocation.array;
- } else {
- return (T*)malloc(num * sizeof(T));
- }
- }
-
- void deallocate(pointer p, size_t num) {
- if (p == (T*)mAllocation.array) {
- mAllocation.inUse = false;
- } else {
- // 'free' instead of delete here - destruction handled separately
- free(p);
- }
- }
- Allocation& mAllocation;
-};
-
-/**
- * std::vector with SIZE elements preallocated into an internal buffer.
- *
- * Useful for avoiding the cost of malloc in cases where only SIZE or
- * fewer elements are needed in the common case.
- */
-template <typename T, size_t SIZE>
-class FatVector : public std::vector<T, InlineStdAllocator<T, SIZE>> {
-public:
- FatVector()
- : std::vector<T, InlineStdAllocator<T, SIZE>>(
- InlineStdAllocator<T, SIZE>(mAllocation)) {
- this->reserve(SIZE);
- }
-
- explicit FatVector(size_t capacity) : FatVector() { this->resize(capacity); }
-
-private:
- typename InlineStdAllocator<T, SIZE>::Allocation mAllocation;
-};
-
-} // namespace uirenderer
-} // namespace android
-
-#endif // ANDROID_FAT_VECTOR_H
diff --git a/libs/input/PointerController.cpp b/libs/input/PointerController.cpp
index e4348f2a9b21..3b494e9129db 100644
--- a/libs/input/PointerController.cpp
+++ b/libs/input/PointerController.cpp
@@ -251,19 +251,24 @@ void PointerController::unfade(Transition transition) {
void PointerController::setPresentation(Presentation presentation) {
AutoMutex _l(mLock);
- if (presentation == PRESENTATION_POINTER && mLocked.additionalMouseResources.empty()) {
- mPolicy->loadAdditionalMouseResources(&mLocked.additionalMouseResources,
- &mLocked.animationResources, mLocked.viewport.displayId);
+ if (mLocked.presentation == presentation) {
+ return;
}
- if (mLocked.presentation != presentation) {
- mLocked.presentation = presentation;
- mLocked.presentationChanged = true;
+ mLocked.presentation = presentation;
+ mLocked.presentationChanged = true;
- if (presentation != PRESENTATION_SPOT) {
- fadeOutAndReleaseAllSpotsLocked();
- }
+ if (!mLocked.viewport.isValid()) {
+ return;
+ }
+ if (presentation == PRESENTATION_POINTER) {
+ if (mLocked.additionalMouseResources.empty()) {
+ mPolicy->loadAdditionalMouseResources(&mLocked.additionalMouseResources,
+ &mLocked.animationResources,
+ mLocked.viewport.displayId);
+ }
+ fadeOutAndReleaseAllSpotsLocked();
updatePointerLocked();
}
}
@@ -285,6 +290,9 @@ void PointerController::setSpots(const PointerCoords* spotCoords,
#endif
AutoMutex _l(mLock);
+ if (!mLocked.viewport.isValid()) {
+ return;
+ }
std::vector<Spot*> newSpots;
std::map<int32_t, std::vector<Spot*>>::const_iterator iter =
@@ -331,6 +339,9 @@ void PointerController::clearSpots() {
#endif
AutoMutex _l(mLock);
+ if (!mLocked.viewport.isValid()) {
+ return;
+ }
fadeOutAndReleaseAllSpotsLocked();
}
@@ -752,6 +763,10 @@ void PointerController::fadeOutAndReleaseAllSpotsLocked() {
}
void PointerController::loadResourcesLocked() REQUIRES(mLock) {
+ if (!mLocked.viewport.isValid()) {
+ return;
+ }
+
mPolicy->loadPointerResources(&mResources, mLocked.viewport.displayId);
mPolicy->loadPointerIcon(&mLocked.pointerIcon, mLocked.viewport.displayId);
diff --git a/libs/input/tests/PointerController_test.cpp b/libs/input/tests/PointerController_test.cpp
index b36406d6a703..a15742671dc7 100644
--- a/libs/input/tests/PointerController_test.cpp
+++ b/libs/input/tests/PointerController_test.cpp
@@ -39,8 +39,8 @@ enum TestCursorType {
using ::testing::AllOf;
using ::testing::Field;
-using ::testing::NiceMock;
using ::testing::Mock;
+using ::testing::NiceMock;
using ::testing::Return;
using ::testing::Test;
@@ -57,12 +57,20 @@ public:
virtual int32_t getDefaultPointerIconId() override;
virtual int32_t getCustomPointerIconId() override;
+ bool allResourcesAreLoaded();
+ bool noResourcesAreLoaded();
+
private:
void loadPointerIconForType(SpriteIcon* icon, int32_t cursorType);
+
+ bool pointerIconLoaded{false};
+ bool pointerResourcesLoaded{false};
+ bool additionalMouseResourcesLoaded{false};
};
void MockPointerControllerPolicyInterface::loadPointerIcon(SpriteIcon* icon, int32_t) {
loadPointerIconForType(icon, CURSOR_TYPE_DEFAULT);
+ pointerIconLoaded = true;
}
void MockPointerControllerPolicyInterface::loadPointerResources(PointerResources* outResources,
@@ -70,6 +78,7 @@ void MockPointerControllerPolicyInterface::loadPointerResources(PointerResources
loadPointerIconForType(&outResources->spotHover, CURSOR_TYPE_HOVER);
loadPointerIconForType(&outResources->spotTouch, CURSOR_TYPE_TOUCH);
loadPointerIconForType(&outResources->spotAnchor, CURSOR_TYPE_ANCHOR);
+ pointerResourcesLoaded = true;
}
void MockPointerControllerPolicyInterface::loadAdditionalMouseResources(
@@ -91,6 +100,8 @@ void MockPointerControllerPolicyInterface::loadAdditionalMouseResources(
anim.durationPerFrame = 10;
(*outResources)[cursorType] = icon;
(*outAnimationResources)[cursorType] = anim;
+
+ additionalMouseResourcesLoaded = true;
}
int32_t MockPointerControllerPolicyInterface::getDefaultPointerIconId() {
@@ -101,18 +112,27 @@ int32_t MockPointerControllerPolicyInterface::getCustomPointerIconId() {
return CURSOR_TYPE_CUSTOM;
}
+bool MockPointerControllerPolicyInterface::allResourcesAreLoaded() {
+ return pointerIconLoaded && pointerResourcesLoaded && additionalMouseResourcesLoaded;
+}
+
+bool MockPointerControllerPolicyInterface::noResourcesAreLoaded() {
+ return !(pointerIconLoaded || pointerResourcesLoaded || additionalMouseResourcesLoaded);
+}
+
void MockPointerControllerPolicyInterface::loadPointerIconForType(SpriteIcon* icon, int32_t type) {
icon->style = type;
std::pair<float, float> hotSpot = getHotSpotCoordinatesForType(type);
icon->hotSpotX = hotSpot.first;
icon->hotSpotY = hotSpot.second;
}
-
class PointerControllerTest : public Test {
protected:
PointerControllerTest();
~PointerControllerTest();
+ void ensureDisplayViewportIsSet();
+
sp<MockSprite> mPointerSprite;
sp<MockPointerControllerPolicyInterface> mPolicy;
sp<MockSpriteController> mSpriteController;
@@ -141,7 +161,14 @@ PointerControllerTest::PointerControllerTest() : mPointerSprite(new NiceMock<Moc
.WillOnce(Return(mPointerSprite));
mPointerController = new PointerController(mPolicy, mLooper, mSpriteController);
+}
+
+PointerControllerTest::~PointerControllerTest() {
+ mRunning.store(false, std::memory_order_relaxed);
+ mThread.join();
+}
+void PointerControllerTest::ensureDisplayViewportIsSet() {
DisplayViewport viewport;
viewport.displayId = ADISPLAY_ID_DEFAULT;
viewport.logicalRight = 1600;
@@ -151,11 +178,9 @@ PointerControllerTest::PointerControllerTest() : mPointerSprite(new NiceMock<Moc
viewport.deviceWidth = 400;
viewport.deviceHeight = 300;
mPointerController->setDisplayViewport(viewport);
-}
-PointerControllerTest::~PointerControllerTest() {
- mRunning.store(false, std::memory_order_relaxed);
- mThread.join();
+ // The first call to setDisplayViewport should trigger the loading of the necessary resources.
+ EXPECT_TRUE(mPolicy->allResourcesAreLoaded());
}
void PointerControllerTest::loopThread() {
@@ -167,6 +192,7 @@ void PointerControllerTest::loopThread() {
}
TEST_F(PointerControllerTest, useDefaultCursorTypeByDefault) {
+ ensureDisplayViewportIsSet();
mPointerController->unfade(PointerController::TRANSITION_IMMEDIATE);
std::pair<float, float> hotspot = getHotSpotCoordinatesForType(CURSOR_TYPE_DEFAULT);
@@ -181,6 +207,7 @@ TEST_F(PointerControllerTest, useDefaultCursorTypeByDefault) {
}
TEST_F(PointerControllerTest, updatePointerIcon) {
+ ensureDisplayViewportIsSet();
mPointerController->unfade(PointerController::TRANSITION_IMMEDIATE);
int32_t type = CURSOR_TYPE_ADDITIONAL;
@@ -196,6 +223,7 @@ TEST_F(PointerControllerTest, updatePointerIcon) {
}
TEST_F(PointerControllerTest, setCustomPointerIcon) {
+ ensureDisplayViewportIsSet();
mPointerController->unfade(PointerController::TRANSITION_IMMEDIATE);
int32_t style = CURSOR_TYPE_CUSTOM;
@@ -217,4 +245,18 @@ TEST_F(PointerControllerTest, setCustomPointerIcon) {
mPointerController->setCustomPointerIcon(icon);
}
+TEST_F(PointerControllerTest, doesNotGetResourcesBeforeSettingViewport) {
+ mPointerController->setPresentation(PointerController::PRESENTATION_POINTER);
+ mPointerController->setSpots(nullptr, nullptr, BitSet32(), -1);
+ mPointerController->clearSpots();
+ mPointerController->setPosition(1.0f, 1.0f);
+ mPointerController->move(1.0f, 1.0f);
+ mPointerController->unfade(PointerController::TRANSITION_IMMEDIATE);
+ mPointerController->fade(PointerController::TRANSITION_IMMEDIATE);
+
+ EXPECT_TRUE(mPolicy->noResourcesAreLoaded());
+
+ ensureDisplayViewportIsSet();
+}
+
} // namespace android
diff --git a/libs/services/Android.bp b/libs/services/Android.bp
index 9b047ca22d19..1e621079b532 100644
--- a/libs/services/Android.bp
+++ b/libs/services/Android.bp
@@ -20,7 +20,6 @@ cc_library_shared {
":IDropBoxManagerService.aidl",
"src/content/ComponentName.cpp",
"src/os/DropBoxManager.cpp",
- "src/os/StatsDimensionsValue.cpp",
],
shared_libs: [
diff --git a/libs/services/include/android/os/StatsDimensionsValue.h b/libs/services/include/android/os/StatsDimensionsValue.h
deleted file mode 100644
index cc0b05644f2c..000000000000
--- a/libs/services/include/android/os/StatsDimensionsValue.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * 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.
- */
-#ifndef STATS_DIMENSIONS_VALUE_H
-#define STATS_DIMENSIONS_VALUE_H
-
-#include <binder/Parcel.h>
-#include <binder/Parcelable.h>
-#include <binder/Status.h>
-#include <utils/String16.h>
-#include <vector>
-
-namespace android {
-namespace os {
-
-// Represents a parcelable object. Used to send data from statsd to StatsCompanionService.java.
-class StatsDimensionsValue : public android::Parcelable {
-public:
- StatsDimensionsValue();
-
- StatsDimensionsValue(int32_t field, String16 value);
- StatsDimensionsValue(int32_t field, int32_t value);
- StatsDimensionsValue(int32_t field, int64_t value);
- StatsDimensionsValue(int32_t field, bool value);
- StatsDimensionsValue(int32_t field, float value);
- StatsDimensionsValue(int32_t field, std::vector<StatsDimensionsValue> value);
-
- virtual ~StatsDimensionsValue();
-
- virtual android::status_t writeToParcel(android::Parcel* out) const override;
- virtual android::status_t readFromParcel(const android::Parcel* in) override;
-
-private:
- // Keep constants in sync with android/os/StatsDimensionsValue.java
- // and stats_log.proto's DimensionValue.
- static const int kStrValueType = 2;
- static const int kIntValueType = 3;
- static const int kLongValueType = 4;
- static const int kBoolValueType = 5;
- static const int kFloatValueType = 6;
- static const int kTupleValueType = 7;
-
- int32_t mField;
- int32_t mValueType;
-
- // This isn't very clever, but it isn't used for long-term storage, so it'll do.
- String16 mStrValue;
- int32_t mIntValue;
- int64_t mLongValue;
- bool mBoolValue;
- float mFloatValue;
- std::vector<StatsDimensionsValue> mTupleValue;
-};
-
-} // namespace os
-} // namespace android
-
-#endif // STATS_DIMENSIONS_VALUE_H
diff --git a/libs/services/src/os/StatsDimensionsValue.cpp b/libs/services/src/os/StatsDimensionsValue.cpp
deleted file mode 100644
index 0052e0baa905..000000000000
--- a/libs/services/src/os/StatsDimensionsValue.cpp
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * 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.
- */
-
-#define LOG_TAG "StatsDimensionsValue"
-
-#include "android/os/StatsDimensionsValue.h"
-
-#include <cutils/log.h>
-
-using android::Parcel;
-using android::Parcelable;
-using android::status_t;
-using std::vector;
-
-namespace android {
-namespace os {
-
-StatsDimensionsValue::StatsDimensionsValue() {};
-
-StatsDimensionsValue::StatsDimensionsValue(int32_t field, String16 value) :
- mField(field),
- mValueType(kStrValueType),
- mStrValue(value) {
-}
-StatsDimensionsValue::StatsDimensionsValue(int32_t field, int32_t value) :
- mField(field),
- mValueType(kIntValueType),
- mIntValue(value) {
-}
-StatsDimensionsValue::StatsDimensionsValue(int32_t field, int64_t value) :
- mField(field),
- mValueType(kLongValueType),
- mLongValue(value) {
-}
-StatsDimensionsValue::StatsDimensionsValue(int32_t field, bool value) :
- mField(field),
- mValueType(kBoolValueType),
- mBoolValue(value) {
-}
-StatsDimensionsValue::StatsDimensionsValue(int32_t field, float value) :
- mField(field),
- mValueType(kFloatValueType),
- mFloatValue(value) {
-}
-StatsDimensionsValue::StatsDimensionsValue(int32_t field, vector<StatsDimensionsValue> value) :
- mField(field),
- mValueType(kTupleValueType),
- mTupleValue(value) {
-}
-
-StatsDimensionsValue::~StatsDimensionsValue() {}
-
-status_t
-StatsDimensionsValue::writeToParcel(Parcel* out) const {
- status_t err ;
-
- err = out->writeInt32(mField);
- if (err != NO_ERROR) {
- return err;
- }
- err = out->writeInt32(mValueType);
- if (err != NO_ERROR) {
- return err;
- }
- switch (mValueType) {
- case kStrValueType:
- err = out->writeString16(mStrValue);
- break;
- case kIntValueType:
- err = out->writeInt32(mIntValue);
- break;
- case kLongValueType:
- err = out->writeInt64(mLongValue);
- break;
- case kBoolValueType:
- err = out->writeBool(mBoolValue);
- break;
- case kFloatValueType:
- err = out->writeFloat(mFloatValue);
- break;
- case kTupleValueType:
- {
- int sz = mTupleValue.size();
- err = out->writeInt32(sz);
- if (err != NO_ERROR) {
- return err;
- }
- for (int i = 0; i < sz; ++i) {
- err = mTupleValue[i].writeToParcel(out);
- if (err != NO_ERROR) {
- return err;
- }
- }
- }
- break;
- default:
- err = UNKNOWN_ERROR;
- break;
- }
- return err;
-}
-
-status_t
-StatsDimensionsValue::readFromParcel(const Parcel* in)
-{
- // Implement me if desired. We don't currently use this.
- ALOGE("Cannot do c++ StatsDimensionsValue.readFromParcel(); it is not implemented.");
- (void)in; // To prevent compile error of unused parameter 'in'
- return UNKNOWN_ERROR;
-}
-
-} // namespace os
-} // namespace android
diff --git a/core/java/android/os/StatsDimensionsValue.aidl b/location/java/android/location/GnssRequest.aidl
index 81a14a4b67d9..581abcce6651 100644
--- a/core/java/android/os/StatsDimensionsValue.aidl
+++ b/location/java/android/location/GnssRequest.aidl
@@ -1,5 +1,5 @@
-/**
- * Copyright (c) 2018, The Android Open Source Project
+/*
+ * Copyright (C) 2020, 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.
@@ -14,7 +14,9 @@
* limitations under the License.
*/
-package android.os;
+package android.location;
-/** @hide */
-parcelable StatsDimensionsValue cpp_header "android/os/StatsDimensionsValue.h"; \ No newline at end of file
+/**
+ * @hide
+ */
+parcelable GnssRequest;
diff --git a/location/java/android/location/GnssRequest.java b/location/java/android/location/GnssRequest.java
new file mode 100644
index 000000000000..2afb265f638c
--- /dev/null
+++ b/location/java/android/location/GnssRequest.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2020 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.location;
+
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * This class contains extra parameters to pass to a GNSS provider implementation.
+ * @hide
+ */
+@SystemApi
+public final class GnssRequest implements Parcelable {
+ private final boolean mFullTracking;
+
+ /**
+ * Creates a {@link GnssRequest} with a full list of parameters.
+ */
+ private GnssRequest(boolean fullTracking) {
+ mFullTracking = fullTracking;
+ }
+
+ /**
+ * Represents whether to enable full GNSS tracking.
+ *
+ * <p>If true, GNSS chipset switches off duty cycling. In such a mode, no clock
+ * discontinuities are expected, and when supported, carrier phase should be continuous in
+ * good signal conditions. All non-blacklisted, healthy constellations, satellites and
+ * frequency bands that the chipset supports must be reported in this mode. The GNSS chipset
+ * is allowed to consume more power in this mode. If false, GNSS chipset optimizes power via
+ * duty cycling, constellations and frequency limits, etc.
+ */
+ public boolean isFullTracking() {
+ return mFullTracking;
+ }
+
+ @NonNull
+ public static final Creator<GnssRequest> CREATOR =
+ new Creator<GnssRequest>() {
+ @Override
+ @NonNull
+ public GnssRequest createFromParcel(@NonNull Parcel parcel) {
+ return new GnssRequest(parcel.readBoolean());
+ }
+
+ @Override
+ public GnssRequest[] newArray(int i) {
+ return new GnssRequest[i];
+ }
+ };
+
+ @NonNull
+ @Override
+ public String toString() {
+ StringBuilder s = new StringBuilder();
+ s.append("GnssRequest[");
+ s.append("FullTracking=").append(mFullTracking);
+ s.append(']');
+ return s.toString();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+ if (obj == null) return false;
+ if (!(obj instanceof GnssRequest)) return false;
+
+ GnssRequest other = (GnssRequest) obj;
+ if (mFullTracking != other.mFullTracking) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return mFullTracking ? 1 : 0;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel parcel, int flags) {
+ parcel.writeBoolean(mFullTracking);
+ }
+
+ /** Builder for {@link GnssRequest} */
+ public static final class Builder {
+ private boolean mFullTracking;
+
+ /**
+ * Constructs a {@link Builder} instance.
+ */
+ public Builder() {
+ }
+
+ /**
+ * Constructs a {@link Builder} instance by copying a {@link GnssRequest}.
+ */
+ public Builder(@NonNull GnssRequest request) {
+ mFullTracking = request.isFullTracking();
+ }
+
+ /**
+ * Set the value of whether to enable full GNSS tracking, which is false by default.
+ *
+ * <p>If true, GNSS chipset switches off duty cycling. In such a mode, no clock
+ * discontinuities are expected, and when supported, carrier phase should be continuous in
+ * good signal conditions. All non-blacklisted, healthy constellations, satellites and
+ * frequency bands that the chipset supports must be reported in this mode. The GNSS chipset
+ * is allowed to consume more power in this mode. If false, GNSS chipset optimizes power via
+ * duty cycling, constellations and frequency limits, etc.
+ *
+ * <p>Full tracking requests always override non-full tracking requests. If any full
+ * tracking request occurs, all listeners on the device will receive full tracking GNSS
+ * measurements.
+ */
+ @NonNull public Builder setFullTracking(boolean value) {
+ mFullTracking = value;
+ return this;
+ }
+
+ /** Builds a {@link GnssRequest} instance as specified by this builder. */
+ @NonNull
+ public GnssRequest build() {
+ return new GnssRequest(mFullTracking);
+ }
+ }
+}
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 1c10edb11293..7e6486cc933e 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -2196,6 +2196,30 @@ public class LocationManager {
}
/**
+ * Registers a GNSS Measurement callback.
+ *
+ * @param request extra parameters to pass to GNSS measurement provider. For example, if {@link
+ * GnssRequest#isFullTrackingEnabled()} is true, GNSS chipset switches off duty
+ * cycling.
+ * @param executor the executor that the callback runs on.
+ * @param callback a {@link GnssMeasurementsEvent.Callback} object to register.
+ * @return {@code true} if the callback was added successfully, {@code false} otherwise.
+ * @throws IllegalArgumentException if request is null
+ * @throws IllegalArgumentException if executor is null
+ * @throws IllegalArgumentException if callback is null
+ * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(allOf = {ACCESS_FINE_LOCATION, LOCATION_HARDWARE})
+ public boolean registerGnssMeasurementsCallback(
+ @NonNull GnssRequest request,
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull GnssMeasurementsEvent.Callback callback) {
+ throw new RuntimeException();
+ }
+
+ /**
* Injects GNSS measurement corrections into the GNSS chipset.
*
* @param measurementCorrections a {@link GnssMeasurementCorrections} object with the GNSS
diff --git a/media/java/android/media/tv/tuner/frontend/FrontendStatus.java b/media/java/android/media/tv/tuner/frontend/FrontendStatus.java
index c1b17d3615bb..63de03344219 100644
--- a/media/java/android/media/tv/tuner/frontend/FrontendStatus.java
+++ b/media/java/android/media/tv/tuner/frontend/FrontendStatus.java
@@ -41,8 +41,7 @@ public class FrontendStatus {
FRONTEND_STATUS_TYPE_MODULATION, FRONTEND_STATUS_TYPE_SPECTRAL,
FRONTEND_STATUS_TYPE_LNB_VOLTAGE, FRONTEND_STATUS_TYPE_PLP_ID,
FRONTEND_STATUS_TYPE_EWBS, FRONTEND_STATUS_TYPE_AGC, FRONTEND_STATUS_TYPE_LNA,
- FRONTEND_STATUS_TYPE_LAYER_ERROR, FRONTEND_STATUS_TYPE_VBER_CN,
- FRONTEND_STATUS_TYPE_LBER_CN, FRONTEND_STATUS_TYPE_XER_CN, FRONTEND_STATUS_TYPE_MER,
+ FRONTEND_STATUS_TYPE_LAYER_ERROR, FRONTEND_STATUS_TYPE_MER,
FRONTEND_STATUS_TYPE_FREQ_OFFSET, FRONTEND_STATUS_TYPE_HIERARCHY,
FRONTEND_STATUS_TYPE_RF_LOCK, FRONTEND_STATUS_TYPE_ATSC3_PLP_INFO})
@Retention(RetentionPolicy.SOURCE)
@@ -125,18 +124,6 @@ public class FrontendStatus {
public static final int FRONTEND_STATUS_TYPE_LAYER_ERROR =
Constants.FrontendStatusType.LAYER_ERROR;
/**
- * CN value by VBER.
- */
- public static final int FRONTEND_STATUS_TYPE_VBER_CN = Constants.FrontendStatusType.VBER_CN;
- /**
- * CN value by LBER.
- */
- public static final int FRONTEND_STATUS_TYPE_LBER_CN = Constants.FrontendStatusType.LBER_CN;
- /**
- * CN value by XER.
- */
- public static final int FRONTEND_STATUS_TYPE_XER_CN = Constants.FrontendStatusType.XER_CN;
- /**
* Modulation Error Ratio.
*/
public static final int FRONTEND_STATUS_TYPE_MER = Constants.FrontendStatusType.MER;
@@ -223,9 +210,6 @@ public class FrontendStatus {
private Integer mAgc;
private Boolean mIsLnaOn;
private boolean[] mIsLayerErrors;
- private Integer mVberCn;
- private Integer mLberCn;
- private Integer mXerCn;
private Integer mMer;
private Integer mFreqOffset;
private Integer mHierarchy;
@@ -403,33 +387,6 @@ public class FrontendStatus {
return mIsLayerErrors;
}
/**
- * Gets CN value by VBER in thousandths of a deciBel (0.001dB).
- */
- public int getVberCn() {
- if (mVberCn == null) {
- throw new IllegalStateException();
- }
- return mVberCn;
- }
- /**
- * Gets CN value by LBER in thousandths of a deciBel (0.001dB).
- */
- public int getLberCn() {
- if (mLberCn == null) {
- throw new IllegalStateException();
- }
- return mLberCn;
- }
- /**
- * Gets CN value by XER in thousandths of a deciBel (0.001dB).
- */
- public int getXerCn() {
- if (mXerCn == null) {
- throw new IllegalStateException();
- }
- return mXerCn;
- }
- /**
* Gets Modulation Error Ratio in thousandths of a deciBel (0.001dB).
*/
public int getMer() {
diff --git a/media/java/android/media/tv/tuner/frontend/ScanCallback.java b/media/java/android/media/tv/tuner/frontend/ScanCallback.java
index f90144bc97ef..8105c74cfb62 100644
--- a/media/java/android/media/tv/tuner/frontend/ScanCallback.java
+++ b/media/java/android/media/tv/tuner/frontend/ScanCallback.java
@@ -67,7 +67,7 @@ public interface ScanCallback {
/** Frontend hierarchy. */
void onHierarchy(@DvbtFrontendSettings.Hierarchy int hierarchy);
- /** Frontend hierarchy. */
+ /** Frontend signal type. */
void onSignalType(@AnalogFrontendSettings.SignalType int signalType);
}
diff --git a/packages/Incremental/NativeAdbDataLoader/AndroidManifest.xml b/packages/Incremental/NativeAdbDataLoader/AndroidManifest.xml
index a06dc546f85c..c4d8f35cec71 100644
--- a/packages/Incremental/NativeAdbDataLoader/AndroidManifest.xml
+++ b/packages/Incremental/NativeAdbDataLoader/AndroidManifest.xml
@@ -29,7 +29,7 @@
<service android:enabled="true"
android:name="com.android.incremental.nativeadb.NativeAdbDataLoaderService"
android:label="@string/app_name"
- android:exported="true">
+ android:exported="false">
<intent-filter>
<action android:name="android.intent.action.LOAD_DATA" />
</intent-filter>
diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java
index 48d405a4b91f..18145939c384 100644
--- a/packages/Shell/src/com/android/shell/BugreportProgressService.java
+++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java
@@ -97,6 +97,7 @@ import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
+import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
@@ -193,9 +194,7 @@ public class BugreportProgressService extends Service {
* <p>
* Must be a path supported by its FileProvider.
*/
- // TODO: use the same variable for both dir
- private static final String SCREENSHOT_DIR = "bugreports";
- private static final String BUGREPORT_DIR = "/bugreports";
+ private static final String BUGREPORT_DIR = "bugreports";
private static final String NOTIFICATION_CHANNEL_ID = "bugreports";
@@ -230,7 +229,7 @@ public class BugreportProgressService extends Service {
private final BugreportInfoDialog mInfoDialog = new BugreportInfoDialog();
- private File mScreenshotsDir;
+ private File mBugreportsDir;
private BugreportManager mBugreportManager;
@@ -263,11 +262,12 @@ public class BugreportProgressService extends Service {
mScreenshotHandler = new ScreenshotHandler("BugreportProgressServiceScreenshotThread");
startSelfIntent = new Intent(this, this.getClass());
- mScreenshotsDir = new File(getFilesDir(), SCREENSHOT_DIR);
- if (!mScreenshotsDir.exists()) {
- Log.i(TAG, "Creating directory " + mScreenshotsDir + " to store temporary screenshots");
- if (!mScreenshotsDir.mkdir()) {
- Log.w(TAG, "Could not create directory " + mScreenshotsDir);
+ mBugreportsDir = new File(getFilesDir(), BUGREPORT_DIR);
+ if (!mBugreportsDir.exists()) {
+ Log.i(TAG, "Creating directory " + mBugreportsDir
+ + " to store bugreports and screenshots");
+ if (!mBugreportsDir.mkdir()) {
+ Log.w(TAG, "Could not create directory " + mBugreportsDir);
}
}
final Configuration conf = mContext.getResources().getConfiguration();
@@ -372,7 +372,7 @@ public class BugreportProgressService extends Service {
@Override
public void onFinished() {
mInfo.renameBugreportFile();
- mInfo.renameScreenshots(mScreenshotsDir);
+ mInfo.renameScreenshots();
synchronized (mLock) {
sendBugreportFinishedBroadcastLocked();
}
@@ -406,7 +406,7 @@ public class BugreportProgressService extends Service {
mInfo.bugreportFile);
} else {
trackInfoWithIdLocked();
- cleanupOldFiles(MIN_KEEP_COUNT, MIN_KEEP_AGE);
+ cleanupOldFiles(MIN_KEEP_COUNT, MIN_KEEP_AGE, mBugreportsDir);
final Intent intent = new Intent(INTENT_BUGREPORT_FINISHED);
intent.putExtra(EXTRA_BUGREPORT, bugreportFilePath);
intent.putExtra(EXTRA_SCREENSHOT, getScreenshotForIntent(mInfo));
@@ -418,7 +418,8 @@ public class BugreportProgressService extends Service {
private static void sendRemoteBugreportFinishedBroadcast(Context context,
String bugreportFileName, File bugreportFile) {
- cleanupOldFiles(REMOTE_BUGREPORT_FILES_AMOUNT, REMOTE_MIN_KEEP_AGE);
+ cleanupOldFiles(REMOTE_BUGREPORT_FILES_AMOUNT, REMOTE_MIN_KEEP_AGE,
+ bugreportFile.getParentFile());
final Intent intent = new Intent(DevicePolicyManager.ACTION_REMOTE_BUGREPORT_DISPATCH);
final Uri bugreportUri = getUri(context, bugreportFile);
final String bugreportHash = generateFileHash(bugreportFileName);
@@ -468,12 +469,12 @@ public class BugreportProgressService extends Service {
return fileHash;
}
- static void cleanupOldFiles(final int minCount, final long minAge) {
+ static void cleanupOldFiles(final int minCount, final long minAge, File bugreportsDir) {
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
try {
- FileUtils.deleteOlderFiles(new File(BUGREPORT_DIR), minCount, minAge);
+ FileUtils.deleteOlderFiles(bugreportsDir, minCount, minAge);
} catch (RuntimeException e) {
Log.e(TAG, "RuntimeException deleting old files", e);
}
@@ -604,18 +605,25 @@ public class BugreportProgressService extends Service {
String name = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date());
BugreportInfo info = new BugreportInfo(mContext, baseName, name,
- shareTitle, shareDescription, bugreportType);
+ shareTitle, shareDescription, bugreportType, mBugreportsDir);
+ ParcelFileDescriptor bugreportFd;
+ ParcelFileDescriptor screenshotFd;
- ParcelFileDescriptor bugreportFd = info.createBugreportFd();
- if (bugreportFd == null) {
- Log.e(TAG, "Bugreport parcel file descriptor is null.");
- return;
- }
- ParcelFileDescriptor screenshotFd = info.createScreenshotFd();
- if (screenshotFd == null) {
- Log.e(TAG, "Screenshot parcel file descriptor is null. Deleting bugreport file");
- FileUtils.closeQuietly(bugreportFd);
- info.bugreportFile.delete();
+ try {
+ bugreportFd = info.createAndGetBugreportFd();
+ if (bugreportFd == null) {
+ Log.e(TAG, "Bugreport parcel file descriptor is null.");
+ return;
+ }
+ screenshotFd = info.createAndGetDefaultScreenshotFd();
+ if (screenshotFd == null) {
+ Log.e(TAG, "Screenshot parcel file descriptor is null. Deleting bugreport file");
+ FileUtils.closeQuietly(bugreportFd);
+ info.bugreportFile.delete();
+ return;
+ }
+ } catch (IOException e) {
+ Log.e(TAG, "Error in generating bugreport files: ", e);
return;
}
mBugreportManager = (BugreportManager) mContext.getSystemService(
@@ -639,21 +647,24 @@ public class BugreportProgressService extends Service {
}
}
- private static ParcelFileDescriptor createReadWriteFile(File file) {
+ private static ParcelFileDescriptor getFd(File file) {
try {
- file.createNewFile();
- file.setReadable(true, true);
- file.setWritable(true, true);
-
- ParcelFileDescriptor fd = ParcelFileDescriptor.open(file,
+ return ParcelFileDescriptor.open(file,
ParcelFileDescriptor.MODE_WRITE_ONLY | ParcelFileDescriptor.MODE_APPEND);
- return fd;
- } catch (IOException e) {
+ } catch (FileNotFoundException e) {
Log.i(TAG, "Error in generating bugreports: ", e);
}
return null;
}
+ private static void createReadWriteFile(File file) throws IOException {
+ if (!file.exists()) {
+ file.createNewFile();
+ file.setReadable(true, true);
+ file.setWritable(true, true);
+ }
+ }
+
/**
* Updates the system notification for a given bugreport.
*/
@@ -874,7 +885,7 @@ public class BugreportProgressService extends Service {
return;
}
final String screenshotPath =
- new File(mScreenshotsDir, info.getPathNextScreenshot()).getAbsolutePath();
+ new File(mBugreportsDir, info.getPathNextScreenshot()).getAbsolutePath();
Message.obtain(mScreenshotHandler, MSG_SCREENSHOT_REQUEST, id, UNUSED_ARG2, screenshotPath)
.sendToTarget();
@@ -921,7 +932,7 @@ public class BugreportProgressService extends Service {
info.addScreenshot(screenshotFile);
if (info.finished) {
Log.d(TAG, "Screenshot finished after bugreport; updating share notification");
- info.renameScreenshots(mScreenshotsDir);
+ info.renameScreenshots();
sendBugreportNotification(info, mTakingScreenshot);
}
msg = mContext.getString(R.string.bugreport_screenshot_taken);
@@ -1030,11 +1041,10 @@ public class BugreportProgressService extends Service {
/**
* Build {@link Intent} that can be used to share the given bugreport.
*/
- private static Intent buildSendIntent(Context context, BugreportInfo info,
- File screenshotsDir) {
+ private static Intent buildSendIntent(Context context, BugreportInfo info) {
// Rename files (if required) before sharing
info.renameBugreportFile();
- info.renameScreenshots(screenshotsDir);
+ info.renameScreenshots();
// Files are kept on private storage, so turn into Uris that we can
// grant temporary permissions for.
final Uri bugreportUri;
@@ -1120,7 +1130,7 @@ public class BugreportProgressService extends Service {
addDetailsToZipFile(info);
- final Intent sendIntent = buildSendIntent(mContext, info, mScreenshotsDir);
+ final Intent sendIntent = buildSendIntent(mContext, info);
if (sendIntent == null) {
Log.w(TAG, "Stopping progres on ID " + id + " because share intent could not be built");
synchronized (mLock) {
@@ -1813,24 +1823,37 @@ public class BugreportProgressService extends Service {
*/
BugreportInfo(Context context, String baseName, String name,
@Nullable String shareTitle, @Nullable String shareDescription,
- @BugreportParams.BugreportMode int type) {
+ @BugreportParams.BugreportMode int type, File bugreportsDir) {
this.context = context;
this.name = this.initialName = name;
this.shareTitle = shareTitle == null ? "" : shareTitle;
this.shareDescription = shareDescription == null ? "" : shareDescription;
this.type = type;
this.baseName = baseName;
+ createBugreportFile(bugreportsDir);
+ createScreenshotFile(bugreportsDir);
}
- ParcelFileDescriptor createBugreportFd() {
- bugreportFile = new File(BUGREPORT_DIR, getFileName(this, ".zip"));
- return createReadWriteFile(bugreportFile);
+ void createBugreportFile(File bugreportsDir) {
+ bugreportFile = new File(bugreportsDir, getFileName(this, ".zip"));
}
- ParcelFileDescriptor createScreenshotFd() {
- File screenshotFile = new File(BUGREPORT_DIR, getScreenshotName("default"));
+ void createScreenshotFile(File bugreportsDir) {
+ File screenshotFile = new File(bugreportsDir, getScreenshotName("default"));
addScreenshot(screenshotFile);
- return createReadWriteFile(screenshotFile);
+ }
+
+ ParcelFileDescriptor createAndGetBugreportFd() throws IOException {
+ createReadWriteFile(bugreportFile);
+ return getFd(bugreportFile);
+ }
+
+ ParcelFileDescriptor createAndGetDefaultScreenshotFd() throws IOException {
+ if (screenshotFiles.isEmpty()) {
+ return null;
+ }
+ createReadWriteFile(screenshotFiles.get(0));
+ return getFd(screenshotFiles.get(0));
}
/**
@@ -1859,7 +1882,7 @@ public class BugreportProgressService extends Service {
* Rename all screenshots files so that they contain the new {@code name} instead of the
* {@code initialName} if user has changed it.
*/
- void renameScreenshots(File screenshotDir) {
+ void renameScreenshots() {
if (TextUtils.isEmpty(name)) {
return;
}
@@ -1869,7 +1892,7 @@ public class BugreportProgressService extends Service {
final String newName = oldName.replaceFirst(initialName, name);
final File newFile;
if (!newName.equals(oldName)) {
- final File renamedFile = new File(screenshotDir, newName);
+ final File renamedFile = new File(oldFile.getParentFile(), newName);
Log.d(TAG, "Renaming screenshot file " + oldFile + " to " + renamedFile);
newFile = oldFile.renameTo(renamedFile) ? renamedFile : oldFile;
} else {
@@ -1889,7 +1912,8 @@ public class BugreportProgressService extends Service {
* Rename bugreport file to include the name given by user via UI
*/
void renameBugreportFile() {
- File newBugreportFile = new File(BUGREPORT_DIR, getFileName(this, ".zip"));
+ File newBugreportFile = new File(bugreportFile.getParentFile(),
+ getFileName(this, ".zip"));
if (!newBugreportFile.getPath().equals(bugreportFile.getPath())) {
if (bugreportFile.renameTo(newBugreportFile)) {
bugreportFile = newBugreportFile;
diff --git a/packages/SystemUI/res/drawable-nodpi/android_11_dial.xml b/packages/SystemUI/res/drawable-nodpi/android_11_dial.xml
new file mode 100644
index 000000000000..73fd37f1bdd6
--- /dev/null
+++ b/packages/SystemUI/res/drawable-nodpi/android_11_dial.xml
@@ -0,0 +1,63 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:aapt="http://schemas.android.com/aapt"
+ android:width="108dp"
+ android:height="108dp"
+ android:viewportWidth="108"
+ android:viewportHeight="108">
+ <path
+ android:pathData="M77.773,51.064h-1.583c-0.217,0 -0.393,-0.176 -0.393,-0.393v-1.46c0,-0.217 0.176,-0.393 0.393,-0.393h3.466c0.217,0 0.393,0.176 0.393,0.393v9.921c0,0.217 -0.176,0.393 -0.393,0.393h-1.49c-0.217,0 -0.393,-0.176 -0.393,-0.393V51.064z"
+ android:fillColor="#F86734"/>
+ <path
+ android:pathData="M83.598,51.064h-1.583c-0.217,0 -0.393,-0.176 -0.393,-0.393v-1.46c0,-0.217 0.176,-0.393 0.393,-0.393h3.466c0.217,0 0.393,0.176 0.393,0.393v9.921c0,0.217 -0.176,0.393 -0.393,0.393h-1.49c-0.217,0 -0.393,-0.176 -0.393,-0.393V51.064z"
+ android:fillColor="#F86734"/>
+ <path
+ android:pathData="M70.044,75.974m-0.644,0a0.644,0.644 0,1 1,1.288 0a0.644,0.644 0,1 1,-1.288 0"
+ android:fillColor="#d7effe"/>
+ <path
+ android:pathData="M56.896,80.985m-0.718,0a0.718,0.718 0,1 1,1.436 0a0.718,0.718 0,1 1,-1.436 0"
+ android:fillColor="#d7effe"/>
+ <path
+ android:pathData="M43.408,78.881m-0.795,0a0.795,0.795 0,1 1,1.59 0a0.795,0.795 0,1 1,-1.59 0"
+ android:fillColor="#d7effe"/>
+ <path
+ android:pathData="M32.419,70.115m-0.874,0a0.874,0.874 0,1 1,1.748 0a0.874,0.874 0,1 1,-1.748 0"
+ android:fillColor="#d7effe"/>
+ <path
+ android:pathData="M27.306,56.992m-0.954,0a0.954,0.954 0,1 1,1.908 0a0.954,0.954 0,1 1,-1.908 0"
+ android:fillColor="#d7effe"/>
+ <path
+ android:pathData="M29.313,43.489m-1.036,0a1.036,1.036 0,1 1,2.072 0a1.036,1.036 0,1 1,-2.072 0"
+ android:fillColor="#d7effe"/>
+ <path
+ android:pathData="M37.988,32.445m-1.118,0a1.118,1.118 0,1 1,2.236 0a1.118,1.118 0,1 1,-2.236 0"
+ android:fillColor="#d7effe"/>
+ <path
+ android:pathData="M51.137,27.064m-1.201,0a1.201,1.201 0,1 1,2.402 0a1.201,1.201 0,1 1,-2.402 0"
+ android:fillColor="#d7effe"/>
+ <path
+ android:pathData="M64.553,28.868m-1.284,0a1.284,1.284 0,1 1,2.568 0a1.284,1.284 0,1 1,-2.568 0"
+ android:fillColor="#d7effe"/>
+ <path
+ android:pathData="M75.522,37.652m-1.368,0a1.368,1.368 0,1 1,2.736 0a1.368,1.368 0,1 1,-2.736 0"
+ android:fillColor="#d7effe"/>
+ <path
+ android:pathData="M87.942,115.052l-47.557,-47.557l26.869,-26.87l47.557,47.558z">
+ <aapt:attr name="android:fillColor">
+ <gradient
+ android:startY="56.087"
+ android:startX="55.8464"
+ android:endY="100.0297"
+ android:endX="99.7891"
+ android:type="linear">
+ <item android:offset="0" android:color="#3F000000"/>
+ <item android:offset="1" android:color="#00000000"/>
+ </gradient>
+ </aapt:attr>
+ </path>
+ <path
+ android:pathData="M53.928,54.17m-18.999,0a18.999,18.999 0,1 1,37.998 0a18.999,18.999 0,1 1,-37.998 0"
+ android:fillColor="#3ddc84"/>
+ <path
+ android:pathData="M66.353,54.17m-3.185,0a3.185,3.185 0,1 1,6.37 0a3.185,3.185 0,1 1,-6.37 0"
+ android:fillColor="#FFFFFF"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable-nodpi/icon.xml b/packages/SystemUI/res/drawable-nodpi/icon.xml
index 7a68c032d8be..7f8d4fa8833f 100644
--- a/packages/SystemUI/res/drawable-nodpi/icon.xml
+++ b/packages/SystemUI/res/drawable-nodpi/icon.xml
@@ -15,5 +15,5 @@ Copyright (C) 2018 The Android Open Source Project
-->
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/icon_bg"/>
- <foreground android:drawable="@drawable/q"/>
+ <foreground android:drawable="@drawable/android_11_dial"/>
</adaptive-icon>
diff --git a/packages/SystemUI/res/drawable-nodpi/icon_bg.xml b/packages/SystemUI/res/drawable-nodpi/icon_bg.xml
index 2a54dfad8191..31b2a7f9a333 100644
--- a/packages/SystemUI/res/drawable-nodpi/icon_bg.xml
+++ b/packages/SystemUI/res/drawable-nodpi/icon_bg.xml
@@ -14,5 +14,5 @@ Copyright (C) 2018 The Android Open Source Project
limitations under the License.
-->
<color xmlns:android="http://schemas.android.com/apk/res/android"
- android:color="#77C360" />
+ android:color="#073042" />
diff --git a/packages/SystemUI/res/drawable-nodpi/q.xml b/packages/SystemUI/res/drawable-nodpi/q.xml
deleted file mode 100644
index 0f42d2e20040..000000000000
--- a/packages/SystemUI/res/drawable-nodpi/q.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<!--
-Copyright (C) 2019 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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="108dp"
- android:height="108dp"
- android:viewportWidth="108.0"
- android:viewportHeight="108.0">
- <group
- android:name="scale"
- android:pivotX="54" android:pivotY="54"
- android:scaleX="0.9"
- android:scaleY="0.9">
- <group
- android:name="nudge"
- android:translateX="24"
- android:translateY="23.5">
- <path
- android:name="tail"
- android:fillColor="#FFFFFF"
- android:pathData="M21.749674,34.122784l-9.431964,9.529709l-6.31771,-6.2529106l15.736504,-15.899582l64.765724,65.16436l-6.3046494,6.266083z"/>
- <path
- android:name="counter"
- android:fillColor="#FFFFFF"
- android:pathData="M30,9.32352941 C41.6954418,9.32352941 51.1764706,18.8045582 51.1764706,30.5 C51.1764706,42.1954418 41.6954418,51.6764706 30,51.6764706 C18.3045582,51.6764706 8.82352941,42.1954418 8.82352941,30.5 C8.82352941,18.8045582 18.3045582,9.32352941 30,9.32352941 L30,9.32352941 Z M30,0.5 C13.4314575,0.5 -5.53805368e-15,13.9314575 -7.10542736e-15,30.5 C-1.02401747e-14,47.0685425 13.4314575,60.5 30,60.5 C46.5685425,60.5 60,47.0685425 60,30.5 C59.9805514,13.9395201 46.5604799,0.519448617 30,0.5 Z"/>
- </group>
- </group>
-</vector>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index c4fa4e5d4ef3..7a3395c229a0 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -1090,7 +1090,7 @@
<!-- Blur radius on status bar window and power menu -->
<dimen name="min_window_blur_radius">1px</dimen>
- <dimen name="max_window_blur_radius">250px</dimen>
+ <dimen name="max_window_blur_radius">150px</dimen>
<!-- How much into a DisplayCutout's bounds we can go, on each side -->
<dimen name="display_cutout_margin_consumption">0px</dimen>
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
index f61f585cfe7c..f48210cf90c4 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
@@ -42,7 +42,6 @@ import android.util.Log;
import android.util.TypedValue;
import android.view.View;
import android.view.animation.Animation;
-import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
@@ -251,9 +250,9 @@ public class KeyguardSliceView extends LinearLayout implements View.OnClickListe
SliceItem item = rc.getSliceItem();
final Uri itemTag = item.getSlice().getUri();
// Try to reuse the view if already exists in the layout
- KeyguardSliceButton button = mRow.findViewWithTag(itemTag);
+ KeyguardSliceTextView button = mRow.findViewWithTag(itemTag);
if (button == null) {
- button = new KeyguardSliceButton(mContext);
+ button = new KeyguardSliceTextView(mContext);
button.setTextColor(blendedColor);
button.setTag(itemTag);
final int viewIndex = i - (mHasHeader ? 1 : 0);
@@ -316,8 +315,8 @@ public class KeyguardSliceView extends LinearLayout implements View.OnClickListe
int childCount = mRow.getChildCount();
for (int i = 0; i < childCount; i++) {
View v = mRow.getChildAt(i);
- if (v instanceof Button) {
- ((Button) v).setTextColor(blendedColor);
+ if (v instanceof TextView) {
+ ((TextView) v).setTextColor(blendedColor);
}
}
}
@@ -500,8 +499,8 @@ public class KeyguardSliceView extends LinearLayout implements View.OnClickListe
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
- if (child instanceof KeyguardSliceButton) {
- ((KeyguardSliceButton) child).setMaxWidth(width / childCount);
+ if (child instanceof KeyguardSliceTextView) {
+ ((KeyguardSliceTextView) child).setMaxWidth(width / childCount);
}
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
@@ -527,13 +526,13 @@ public class KeyguardSliceView extends LinearLayout implements View.OnClickListe
* Representation of an item that appears under the clock on main keyguard message.
*/
@VisibleForTesting
- static class KeyguardSliceButton extends Button implements
+ static class KeyguardSliceTextView extends TextView implements
ConfigurationController.ConfigurationListener {
@StyleRes
private static int sStyleId = R.style.TextAppearance_Keyguard_Secondary;
- public KeyguardSliceButton(Context context) {
+ KeyguardSliceTextView(Context context) {
super(context, null /* attrs */, 0 /* styleAttr */, sStyleId);
onDensityOrFontScaleChanged();
setEllipsize(TruncateAt.END);
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java
index 0ec739fecaa7..53a23b89f943 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java
@@ -30,7 +30,6 @@ import android.view.IWindowManager;
import android.view.LayoutInflater;
import com.android.internal.logging.MetricsLogger;
-import com.android.internal.util.NotificationMessagingUtil;
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.ViewMediatorCallback;
import com.android.systemui.dagger.qualifiers.Background;
@@ -192,12 +191,6 @@ public class DependencyProvider {
return new AlwaysOnDisplayPolicy(context);
}
- /***/
- @Provides
- public NotificationMessagingUtil provideNotificationMessagingUtil(Context context) {
- return new NotificationMessagingUtil(context);
- }
-
/** */
@Provides
public ViewMediatorCallback providesViewMediatorCallback(KeyguardViewMediator viewMediator) {
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
index f068d9c10e86..7b541991088c 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
@@ -40,7 +40,6 @@ import com.android.systemui.statusbar.notification.collection.inflation.Notifica
import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl;
import com.android.systemui.statusbar.notification.dagger.NotificationsModule;
import com.android.systemui.statusbar.notification.people.PeopleHubModule;
-import com.android.systemui.statusbar.notification.row.dagger.ExpandableNotificationRowComponent;
import com.android.systemui.statusbar.notification.row.dagger.NotificationRowComponent;
import com.android.systemui.statusbar.phone.KeyguardLiftController;
import com.android.systemui.statusbar.phone.StatusBar;
@@ -69,9 +68,7 @@ import dagger.Provides;
NotificationsModule.class,
PeopleHubModule.class,
},
- subcomponents = {StatusBarComponent.class,
- NotificationRowComponent.class,
- ExpandableNotificationRowComponent.class})
+ subcomponents = {StatusBarComponent.class, NotificationRowComponent.class})
public abstract class SystemUIModule {
@Binds
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 14eec59211bd..9da99c453022 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -151,7 +151,7 @@ public class KeyguardViewMediator extends SystemUI {
private static final int KEYGUARD_DISPLAY_TIMEOUT_DELAY_DEFAULT = 30000;
private static final long KEYGUARD_DONE_PENDING_TIMEOUT_MS = 3000;
- private static final boolean DEBUG = KeyguardConstants.DEBUG;
+ private static final boolean DEBUG = true;
private static final boolean DEBUG_SIM_STATES = KeyguardConstants.DEBUG_SIM_STATES;
private final static String TAG = "KeyguardViewMediator";
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
index 411980b399bd..ae6162219afa 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
@@ -83,7 +83,7 @@ public class CustomTile extends QSTileImpl<State> implements TileChangeListener
mTile = new Tile();
updateDefaultTileAndIcon();
mServiceManager = host.getTileServices().getTileWrapper(this);
- if (mServiceManager.isBooleanTile()) {
+ if (mServiceManager.isToggleableTile()) {
// Replace states with BooleanState
resetStates();
}
@@ -252,7 +252,7 @@ public class CustomTile extends QSTileImpl<State> implements TileChangeListener
@Override
public State newTileState() {
- if (mServiceManager != null && mServiceManager.isBooleanTile()) {
+ if (mServiceManager != null && mServiceManager.isToggleableTile()) {
return new BooleanState();
}
return new State();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
index ad79cadcc12d..17b0251837e7 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
@@ -141,16 +141,16 @@ public class TileLifecycleManager extends BroadcastReceiver implements
/**
* Determines whether the associated TileService is a Boolean Tile.
*
- * @return true if {@link TileService#META_DATA_BOOLEAN_TILE} is set to {@code true} for this
+ * @return true if {@link TileService#META_DATA_TOGGLEABLE_TILE} is set to {@code true} for this
* tile
- * @see TileService#META_DATA_BOOLEAN_TILE
+ * @see TileService#META_DATA_TOGGLEABLE_TILE
*/
- public boolean isBooleanTile() {
+ public boolean isToggleableTile() {
try {
ServiceInfo info = mPackageManagerAdapter.getServiceInfo(mIntent.getComponent(),
PackageManager.MATCH_UNINSTALLED_PACKAGES | PackageManager.GET_META_DATA);
return info.metaData != null
- && info.metaData.getBoolean(TileService.META_DATA_BOOLEAN_TILE, false);
+ && info.metaData.getBoolean(TileService.META_DATA_TOGGLEABLE_TILE, false);
} catch (PackageManager.NameNotFoundException e) {
return false;
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
index 1902d655abc3..cfa8fb6373a1 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
@@ -124,8 +124,8 @@ public class TileServiceManager {
return mStateManager.isActiveTile();
}
- public boolean isBooleanTile() {
- return mStateManager.isBooleanTile();
+ public boolean isToggleableTile() {
+ return mStateManager.isToggleableTile();
}
public void setShowingDialog(boolean dialog) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
index 006d40ddbac5..41c1b7b5fae8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
@@ -69,7 +69,6 @@ import com.android.systemui.statusbar.notification.collection.listbuilder.plugga
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifDismissInterceptor;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRowController;
import com.android.systemui.statusbar.notification.row.NotificationGuts;
import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag;
import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager;
@@ -154,7 +153,6 @@ public final class NotificationEntry extends ListEntry {
private NotificationEntry parent; // our parent (if we're in a group)
private ExpandableNotificationRow row; // the outer expanded view
- private ExpandableNotificationRowController mRowController;
private int mCachedContrastColor = COLOR_INVALID;
private int mCachedContrastColorIsFor = COLOR_INVALID;
@@ -426,14 +424,6 @@ public final class NotificationEntry extends ListEntry {
this.row = row;
}
- public ExpandableNotificationRowController getRowController() {
- return mRowController;
- }
-
- public void setRowController(ExpandableNotificationRowController controller) {
- mRowController = controller;
- }
-
@Nullable
public List<NotificationEntry> getChildren() {
if (row == null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java
index e8a62e48e75e..ecf62db4680b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar.notification.collection.inflation;
import static com.android.systemui.Dependency.ALLOW_NOTIFICATION_LONG_PRESS_NAME;
+import static com.android.systemui.statusbar.NotificationRemoteInputManager.ENABLE_REMOTE_INPUT;
import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_HEADS_UP;
import android.annotation.Nullable;
@@ -39,19 +40,19 @@ import com.android.systemui.statusbar.notification.InflationException;
import com.android.systemui.statusbar.notification.NotificationClicker;
import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRowController;
import com.android.systemui.statusbar.notification.row.NotifBindPipeline;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder;
import com.android.systemui.statusbar.notification.row.RowContentBindParams;
import com.android.systemui.statusbar.notification.row.RowContentBindStage;
import com.android.systemui.statusbar.notification.row.RowInflaterTask;
-import com.android.systemui.statusbar.notification.row.dagger.ExpandableNotificationRowComponent;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.StatusBar;
+import com.android.systemui.statusbar.policy.HeadsUpManager;
import java.util.Objects;
@@ -66,28 +67,35 @@ public class NotificationRowBinderImpl implements NotificationRowBinder {
private static final String TAG = "NotificationViewManager";
+ private final NotificationGroupManager mGroupManager;
+ private final NotificationGutsManager mGutsManager;
private final NotificationInterruptionStateProvider mNotificationInterruptionStateProvider;
private final Context mContext;
private final NotifBindPipeline mNotifBindPipeline;
private final RowContentBindStage mRowContentBindStage;
private final NotificationMessagingUtil mMessagingUtil;
+ private final ExpandableNotificationRow.ExpansionLogger mExpansionLogger =
+ this::logNotificationExpansion;
private final NotificationRemoteInputManager mNotificationRemoteInputManager;
private final NotificationLockscreenUserManager mNotificationLockscreenUserManager;
+ private final boolean mAllowLongPress;
+ private final KeyguardBypassController mKeyguardBypassController;
+ private final StatusBarStateController mStatusBarStateController;
private NotificationPresenter mPresenter;
private NotificationListContainer mListContainer;
+ private HeadsUpManager mHeadsUpManager;
private NotificationRowContentBinder.InflationCallback mInflationCallback;
+ private ExpandableNotificationRow.OnAppOpsClickListener mOnAppOpsClickListener;
private BindRowCallback mBindRowCallback;
private NotificationClicker mNotificationClicker;
private final Provider<RowInflaterTask> mRowInflaterTaskProvider;
- private final ExpandableNotificationRowComponent.Builder
- mExpandableNotificationRowComponentBuilder;
+ private final NotificationLogger mNotificationLogger;
@Inject
public NotificationRowBinderImpl(
Context context,
- NotificationMessagingUtil notificationMessagingUtil,
NotificationRemoteInputManager notificationRemoteInputManager,
NotificationLockscreenUserManager notificationLockscreenUserManager,
NotifBindPipeline notifBindPipeline,
@@ -99,16 +107,21 @@ public class NotificationRowBinderImpl implements NotificationRowBinder {
NotificationGutsManager notificationGutsManager,
NotificationInterruptionStateProvider notificationInterruptionStateProvider,
Provider<RowInflaterTask> rowInflaterTaskProvider,
- ExpandableNotificationRowComponent.Builder expandableNotificationRowComponentBuilder) {
+ NotificationLogger logger) {
mContext = context;
mNotifBindPipeline = notifBindPipeline;
mRowContentBindStage = rowContentBindStage;
- mMessagingUtil = notificationMessagingUtil;
+ mMessagingUtil = new NotificationMessagingUtil(context);
mNotificationRemoteInputManager = notificationRemoteInputManager;
mNotificationLockscreenUserManager = notificationLockscreenUserManager;
+ mAllowLongPress = allowLongPress;
+ mKeyguardBypassController = keyguardBypassController;
+ mStatusBarStateController = statusBarStateController;
+ mGroupManager = notificationGroupManager;
+ mGutsManager = notificationGutsManager;
mNotificationInterruptionStateProvider = notificationInterruptionStateProvider;
mRowInflaterTaskProvider = rowInflaterTaskProvider;
- mExpandableNotificationRowComponentBuilder = expandableNotificationRowComponentBuilder;
+ mNotificationLogger = logger;
}
/**
@@ -116,10 +129,13 @@ public class NotificationRowBinderImpl implements NotificationRowBinder {
*/
public void setUpWithPresenter(NotificationPresenter presenter,
NotificationListContainer listContainer,
+ HeadsUpManager headsUpManager,
BindRowCallback bindRowCallback) {
mPresenter = presenter;
mListContainer = listContainer;
+ mHeadsUpManager = headsUpManager;
mBindRowCallback = bindRowCallback;
+ mOnAppOpsClickListener = mGutsManager::openGuts;
}
public void setInflationCallback(NotificationRowContentBinder.InflationCallback callback) {
@@ -134,7 +150,9 @@ public class NotificationRowBinderImpl implements NotificationRowBinder {
* Inflates the views for the given entry (possibly asynchronously).
*/
@Override
- public void inflateViews(NotificationEntry entry, Runnable onDismissRunnable)
+ public void inflateViews(
+ NotificationEntry entry,
+ Runnable onDismissRunnable)
throws InflationException {
ViewGroup parent = mListContainer.getViewParentForNotification(entry);
PackageManager pmUser = StatusBar.getPackageManagerForUser(mContext,
@@ -145,26 +163,12 @@ public class NotificationRowBinderImpl implements NotificationRowBinder {
entry.updateIcons(mContext, sbn);
entry.reset();
updateNotification(entry, pmUser, sbn, entry.getRow());
- entry.getRowController().setOnDismissRunnable(onDismissRunnable);
+ entry.getRow().setOnDismissRunnable(onDismissRunnable);
} else {
entry.createIcons(mContext, sbn);
mRowInflaterTaskProvider.get().inflate(mContext, parent, entry,
row -> {
- // Setup the controller for the view.
- ExpandableNotificationRowComponent component =
- mExpandableNotificationRowComponentBuilder
- .expandableNotificationRow(row)
- .notificationEntry(entry)
- .onDismissRunnable(onDismissRunnable)
- .inflationCallback(mInflationCallback)
- .rowContentBindStage(mRowContentBindStage)
- .onExpandClickListener(mPresenter)
- .build();
- ExpandableNotificationRowController rowController =
- component.getExpandableNotificationRowController();
- rowController.init();
- entry.setRowController(rowController);
- bindRow(entry, pmUser, sbn, row);
+ bindRow(entry, pmUser, sbn, row, onDismissRunnable);
updateNotification(entry, pmUser, sbn, row);
});
}
@@ -172,12 +176,55 @@ public class NotificationRowBinderImpl implements NotificationRowBinder {
//TODO: This method associates a row with an entry, but eventually needs to not do that
private void bindRow(NotificationEntry entry, PackageManager pmUser,
- StatusBarNotification sbn, ExpandableNotificationRow row) {
+ StatusBarNotification sbn, ExpandableNotificationRow row,
+ Runnable onDismissRunnable) {
+ // Get the app name.
+ // Note that Notification.Builder#bindHeaderAppName has similar logic
+ // but since this field is used in the guts, it must be accurate.
+ // Therefore we will only show the application label, or, failing that, the
+ // package name. No substitutions.
+ final String pkg = sbn.getPackageName();
+ String appname = pkg;
+ try {
+ final ApplicationInfo info = pmUser.getApplicationInfo(pkg,
+ PackageManager.MATCH_UNINSTALLED_PACKAGES
+ | PackageManager.MATCH_DISABLED_COMPONENTS);
+ if (info != null) {
+ appname = String.valueOf(pmUser.getApplicationLabel(info));
+ }
+ } catch (PackageManager.NameNotFoundException e) {
+ // Do nothing
+ }
+
+ row.initialize(
+ appname,
+ sbn.getKey(),
+ mExpansionLogger,
+ mKeyguardBypassController,
+ mGroupManager,
+ mHeadsUpManager,
+ mRowContentBindStage,
+ mPresenter);
+
+ // TODO: Either move these into ExpandableNotificationRow#initialize or out of row entirely
+ row.setStatusBarStateController(mStatusBarStateController);
+ row.setAppOpsOnClickListener(mOnAppOpsClickListener);
+ if (mAllowLongPress) {
+ row.setLongPressListener(mGutsManager::openGuts);
+ }
mListContainer.bindRow(row);
mNotificationRemoteInputManager.bindRow(row);
+
+ row.setOnDismissRunnable(onDismissRunnable);
+ row.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
+ if (ENABLE_REMOTE_INPUT) {
+ row.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
+ }
+
entry.setRow(row);
row.setEntry(entry);
mNotifBindPipeline.manageRow(entry, row);
+
mBindRowCallback.onBindRow(entry, pmUser, sbn, row);
}
@@ -260,6 +307,10 @@ public class NotificationRowBinderImpl implements NotificationRowBinder {
Objects.requireNonNull(mNotificationClicker).register(row, sbn);
}
+ private void logNotificationExpansion(String key, boolean userAction, boolean expanded) {
+ mNotificationLogger.onExpansionChanged(key, userAction, expanded);
+ }
+
/** Callback for when a row is bound to an entry. */
public interface BindRowCallback {
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt
index 3e0bcbb796bf..254b64ffcd90 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt
@@ -90,6 +90,7 @@ class NotificationsControllerImpl @Inject constructor(
notificationRowBinder.setUpWithPresenter(
presenter,
listContainer,
+ headsUpManager,
bindRowCallback)
if (featureFlags.isNewNotifPipelineEnabled) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
index a6ef81d4612c..50a20374fee5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
@@ -29,17 +29,20 @@ import android.util.MathUtils;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewAnimationUtils;
+import android.view.accessibility.AccessibilityManager;
import android.view.animation.Interpolator;
import android.view.animation.PathInterpolator;
-import com.android.systemui.Gefingerpoken;
+import com.android.systemui.Dependency;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
+import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.notification.FakeShadowView;
import com.android.systemui.statusbar.notification.NotificationUtils;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
+import com.android.systemui.statusbar.phone.DoubleTapHelper;
/**
* Base class for both {@link ExpandableNotificationRow} and {@link NotificationShelf}
@@ -91,12 +94,14 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
private static final Interpolator ACTIVATE_INVERSE_ALPHA_INTERPOLATOR
= new PathInterpolator(0, 0, 0.5f, 1);
private int mTintedRippleColor;
- private int mNormalRippleColor;
- private Gefingerpoken mTouchHandler;
+ protected int mNormalRippleColor;
+ private final AccessibilityManager mAccessibilityManager;
+ private final DoubleTapHelper mDoubleTapHelper;
private boolean mDimmed;
- int mBgTint = NO_COLOR;
+ protected int mBgTint = NO_COLOR;
+ private float mBgAlpha = 1f;
/**
* Flag to indicate that the notification has been touched once and the second touch will
@@ -111,7 +116,7 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
private Interpolator mCurrentAppearInterpolator;
private Interpolator mCurrentAlphaInterpolator;
- NotificationBackgroundView mBackgroundNormal;
+ protected NotificationBackgroundView mBackgroundNormal;
private NotificationBackgroundView mBackgroundDimmed;
private ObjectAnimator mBackgroundAnimator;
private RectF mAppearAnimationRect = new RectF();
@@ -125,6 +130,7 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
private boolean mLastInSection;
private boolean mFirstInSection;
private boolean mIsBelowSpeedBump;
+ private final FalsingManager mFalsingManager;
private float mNormalBackgroundVisibilityAmount;
private float mDimmedBackgroundFadeInAmount = -1;
@@ -148,24 +154,38 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
*/
private boolean mNeedsDimming;
private int mDimmedAlpha;
+ private boolean mBlockNextTouch;
private boolean mIsHeadsUpAnimation;
private int mHeadsUpAddStartLocation;
private float mHeadsUpLocation;
private boolean mIsAppearing;
private boolean mDismissed;
private boolean mRefocusOnDismiss;
- private OnDimmedListener mOnDimmedListener;
public ActivatableNotificationView(Context context, AttributeSet attrs) {
super(context, attrs);
mSlowOutFastInInterpolator = new PathInterpolator(0.8f, 0.0f, 0.6f, 1.0f);
mSlowOutLinearInInterpolator = new PathInterpolator(0.8f, 0.0f, 1.0f, 1.0f);
+ mFalsingManager = Dependency.get(FalsingManager.class); // TODO: inject into a controller.
setClipChildren(false);
setClipToPadding(false);
updateColors();
+ mAccessibilityManager = AccessibilityManager.getInstance(mContext);
+
+ mDoubleTapHelper = new DoubleTapHelper(this, (active) -> {
+ if (active) {
+ makeActive();
+ } else {
+ makeInactive(true /* animate */);
+ }
+ }, super::performClick, this::handleSlideBack, mFalsingManager::onNotificationDoubleTap);
initDimens();
}
+ public FalsingManager getFalsingManager() {
+ return mFalsingManager;
+ }
+
private void updateColors() {
mNormalColor = mContext.getColor(R.color.notification_material_background_color);
mTintedRippleColor = mContext.getColor(
@@ -216,15 +236,32 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
mBackgroundDimmed.setCustomBackground(R.drawable.notification_material_bg_dim);
}
+ private final Runnable mTapTimeoutRunnable = new Runnable() {
+ @Override
+ public void run() {
+ makeInactive(true /* animate */);
+ }
+ };
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
- if (mTouchHandler != null && mTouchHandler.onInterceptTouchEvent(ev)) {
- return true;
+ if (mNeedsDimming && ev.getActionMasked() == MotionEvent.ACTION_DOWN
+ && disallowSingleClick(ev) && !isTouchExplorationEnabled()) {
+ if (!mActivated) {
+ return true;
+ } else if (!mDoubleTapHelper.isWithinDoubleTapSlop(ev)) {
+ mBlockNextTouch = true;
+ makeInactive(true /* animate */);
+ return true;
+ }
}
return super.onInterceptTouchEvent(ev);
}
+ private boolean isTouchExplorationEnabled() {
+ return mAccessibilityManager.isTouchExplorationEnabled();
+ }
+
protected boolean disallowSingleClick(MotionEvent ev) {
return false;
}
@@ -233,6 +270,25 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
return false;
}
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ boolean result;
+ if (mBlockNextTouch) {
+ mBlockNextTouch = false;
+ return false;
+ }
+ if (mNeedsDimming && !isTouchExplorationEnabled() && isInteractive()) {
+ boolean wasActivated = mActivated;
+ result = handleTouchEventDimmed(event);
+ if (wasActivated && result && event.getAction() == MotionEvent.ACTION_UP) {
+ removeCallbacks(mTapTimeoutRunnable);
+ }
+ } else {
+ result = super.onTouchEvent(event);
+ }
+ return result;
+ }
+
/**
* @return whether this view is interactive and can be double tapped
*/
@@ -257,11 +313,28 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
}
}
- void setRippleAllowed(boolean allowed) {
+ public void setRippleAllowed(boolean allowed) {
mBackgroundNormal.setPressedAllowed(allowed);
}
- void makeActive() {
+ private boolean handleTouchEventDimmed(MotionEvent event) {
+ if (mNeedsDimming && !mDimmed) {
+ // We're actually dimmed, but our content isn't dimmable, let's ensure we have a ripple
+ super.onTouchEvent(event);
+ }
+ return mDoubleTapHelper.onTouchEvent(event, getActualHeight());
+ }
+
+ @Override
+ public boolean performClick() {
+ if (!mNeedsDimming || isTouchExplorationEnabled()) {
+ return super.performClick();
+ }
+ return false;
+ }
+
+ private void makeActive() {
+ mFalsingManager.onNotificationActive();
startActivateAnimation(false /* reverse */);
mActivated = true;
if (mOnActivatedListener != null) {
@@ -315,12 +388,15 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
mBackgroundNormal.animate()
.alpha(reverse ? 0f : 1f)
.setInterpolator(alphaInterpolator)
- .setUpdateListener(animation -> {
- float animatedFraction = animation.getAnimatedFraction();
- if (reverse) {
- animatedFraction = 1.0f - animatedFraction;
+ .setUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ float animatedFraction = animation.getAnimatedFraction();
+ if (reverse) {
+ animatedFraction = 1.0f - animatedFraction;
+ }
+ setNormalBackgroundVisibilityAmount(animatedFraction);
}
- setNormalBackgroundVisibilityAmount(animatedFraction);
})
.setDuration(ACTIVATE_ANIMATION_LENGTH);
}
@@ -342,13 +418,11 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
if (mOnActivatedListener != null) {
mOnActivatedListener.onActivationReset(this);
}
+ removeCallbacks(mTapTimeoutRunnable);
}
public void setDimmed(boolean dimmed, boolean fade) {
mNeedsDimming = dimmed;
- if (mOnDimmedListener != null) {
- mOnDimmedListener.onSetDimmed(dimmed);
- }
dimmed &= isDimmable();
if (mDimmed != dimmed) {
mDimmed = dimmed;
@@ -365,17 +439,13 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
return true;
}
- public boolean isDimmed() {
- return mDimmed;
- }
-
private void updateOutlineAlpha() {
float alpha = NotificationStackScrollLayout.BACKGROUND_ALPHA_DIMMED;
alpha = (alpha + (1.0f - alpha) * mNormalBackgroundVisibilityAmount);
setOutlineAlpha(alpha);
}
- private void setNormalBackgroundVisibilityAmount(float normalBackgroundVisibilityAmount) {
+ public void setNormalBackgroundVisibilityAmount(float normalBackgroundVisibilityAmount) {
mNormalBackgroundVisibilityAmount = normalBackgroundVisibilityAmount;
updateOutlineAlpha();
}
@@ -403,14 +473,14 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
/**
* Sets the tint color of the background
*/
- protected void setTintColor(int color) {
+ public void setTintColor(int color) {
setTintColor(color, false);
}
/**
* Sets the tint color of the background
*/
- void setTintColor(int color, boolean animated) {
+ public void setTintColor(int color, boolean animated) {
if (color != mBgTint) {
mBgTint = color;
updateBackgroundTint(animated);
@@ -492,10 +562,13 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
mStartTint = mCurrentBackgroundTint;
mTargetTint = color;
mBackgroundColorAnimator = ValueAnimator.ofFloat(0.0f, 1.0f);
- mBackgroundColorAnimator.addUpdateListener(animation -> {
- int newColor = NotificationUtils.interpolateColors(mStartTint, mTargetTint,
- animation.getAnimatedFraction());
- setBackgroundTintColor(newColor);
+ mBackgroundColorAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ int newColor = NotificationUtils.interpolateColors(mStartTint, mTargetTint,
+ animation.getAnimatedFraction());
+ setBackgroundTintColor(newColor);
+ }
});
mBackgroundColorAnimator.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
mBackgroundColorAnimator.setInterpolator(Interpolators.LINEAR);
@@ -570,11 +643,11 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
}
protected void updateBackgroundAlpha(float transformationAmount) {
- float bgAlpha = isChildInGroup() && mDimmed ? transformationAmount : 1f;
+ mBgAlpha = isChildInGroup() && mDimmed ? transformationAmount : 1f;
if (mDimmedBackgroundFadeInAmount != -1) {
- bgAlpha *= mDimmedBackgroundFadeInAmount;
+ mBgAlpha *= mDimmedBackgroundFadeInAmount;
}
- mBackgroundDimmed.setAlpha(bgAlpha);
+ mBackgroundDimmed.setAlpha(mBgAlpha);
}
protected void resetBackgroundAlpha() {
@@ -598,6 +671,7 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
mBackgroundDimmed.setVisibility(View.INVISIBLE);
mBackgroundNormal.setVisibility(View.VISIBLE);
mBackgroundNormal.setAlpha(1f);
+ removeCallbacks(mTapTimeoutRunnable);
// make in inactive to avoid it sticking around active
makeInactive(false /* animate */);
}
@@ -709,11 +783,14 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
mAppearAnimator.setInterpolator(Interpolators.LINEAR);
mAppearAnimator.setDuration(
(long) (duration * Math.abs(mAppearAnimationFraction - targetValue)));
- mAppearAnimator.addUpdateListener(animation -> {
- mAppearAnimationFraction = (float) animation.getAnimatedValue();
- updateAppearAnimationAlpha();
- updateAppearRect();
- invalidate();
+ mAppearAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ mAppearAnimationFraction = (float) animation.getAnimatedValue();
+ updateAppearAnimationAlpha();
+ updateAppearRect();
+ invalidate();
+ }
});
if (animationListener != null) {
mAppearAnimator.addListener(animationListener);
@@ -844,7 +921,7 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
getCurrentBackgroundRadiusBottom());
}
- private void applyBackgroundRoundness(float topRadius, float bottomRadius) {
+ protected void applyBackgroundRoundness(float topRadius, float bottomRadius) {
mBackgroundDimmed.setRoundness(topRadius, bottomRadius);
mBackgroundNormal.setRoundness(topRadius, bottomRadius);
}
@@ -886,7 +963,7 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
}
}
- private int getRippleColor() {
+ protected int getRippleColor() {
if (mBgTint != 0) {
return mTintedRippleColor;
} else {
@@ -933,6 +1010,10 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
mOnActivatedListener = onActivatedListener;
}
+ public boolean hasSameBgColor(ActivatableNotificationView otherView) {
+ return calculateBgColor() == otherView.calculateBgColor();
+ }
+
@Override
public void setFakeShadowIntensity(float shadowIntensity, float outlineAlpha, int shadowYEnd,
int outlineTranslation) {
@@ -990,20 +1071,8 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
return mRefocusOnDismiss || isAccessibilityFocused();
}
- void setTouchHandler(Gefingerpoken touchHandler) {
- mTouchHandler = touchHandler;
- }
-
- void setOnDimmedListener(OnDimmedListener onDimmedListener) {
- mOnDimmedListener = onDimmedListener;
- }
-
public interface OnActivatedListener {
void onActivated(ActivatableNotificationView view);
void onActivationReset(ActivatableNotificationView view);
}
-
- interface OnDimmedListener {
- void onSetDimmed(boolean dimmed);
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationViewController.java
index a6a1a4a3a56b..18993ffec357 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationViewController.java
@@ -16,13 +16,9 @@
package com.android.systemui.statusbar.notification.row;
-import android.view.MotionEvent;
-import android.view.View;
import android.view.accessibility.AccessibilityManager;
-import com.android.systemui.Gefingerpoken;
import com.android.systemui.plugins.FalsingManager;
-import com.android.systemui.statusbar.phone.DoubleTapHelper;
import javax.inject.Inject;
@@ -31,106 +27,21 @@ import javax.inject.Inject;
*/
public class ActivatableNotificationViewController {
private final ActivatableNotificationView mView;
- private final ExpandableOutlineViewController mExpandableOutlineViewController;
private final AccessibilityManager mAccessibilityManager;
private final FalsingManager mFalsingManager;
- private DoubleTapHelper mDoubleTapHelper;
- private boolean mNeedsDimming;
-
- private TouchHandler mTouchHandler = new TouchHandler();
@Inject
public ActivatableNotificationViewController(ActivatableNotificationView view,
- ExpandableOutlineViewController expandableOutlineViewController,
AccessibilityManager accessibilityManager, FalsingManager falsingManager) {
mView = view;
- mExpandableOutlineViewController = expandableOutlineViewController;
mAccessibilityManager = accessibilityManager;
mFalsingManager = falsingManager;
-
- mView.setOnActivatedListener(new ActivatableNotificationView.OnActivatedListener() {
- @Override
- public void onActivated(ActivatableNotificationView view) {
- mFalsingManager.onNotificationActive();
- }
-
- @Override
- public void onActivationReset(ActivatableNotificationView view) {
- }
- });
}
/**
* Initialize the controller, setting up handlers and other behavior.
*/
public void init() {
- mExpandableOutlineViewController.init();
- mDoubleTapHelper = new DoubleTapHelper(mView, (active) -> {
- if (active) {
- mView.makeActive();
- mFalsingManager.onNotificationActive();
- } else {
- mView.makeInactive(true /* animate */);
- }
- }, mView::performClick, mView::handleSlideBack, mFalsingManager::onNotificationDoubleTap);
- mView.setOnTouchListener(mTouchHandler);
- mView.setTouchHandler(mTouchHandler);
- mView.setOnDimmedListener(dimmed -> {
- mNeedsDimming = dimmed;
- if (dimmed && !mAccessibilityManager.isTouchExplorationEnabled()) {
- mView.setOnClickListener(null);
- } else {
- mView.setOnClickListener((v) -> mView.performClick());
- }
- });
- }
-
- class TouchHandler implements Gefingerpoken, View.OnTouchListener {
- private boolean mBlockNextTouch;
-
- @Override
- public boolean onTouch(View v, MotionEvent ev) {
- boolean result;
- if (mBlockNextTouch) {
- mBlockNextTouch = false;
- return true;
- }
- if (mNeedsDimming && !mAccessibilityManager.isTouchExplorationEnabled()
- && mView.isInteractive()) {
- if (mNeedsDimming && !mView.isDimmed()) {
- // We're actually dimmed, but our content isn't dimmable,
- // let's ensure we have a ripple
- return false;
- }
- result = mDoubleTapHelper.onTouchEvent(ev, mView.getActualHeight());
- } else {
- return false;
- }
- return result;
- }
-
- @Override
- public boolean onInterceptTouchEvent(MotionEvent ev) {
- if (mNeedsDimming && ev.getActionMasked() == MotionEvent.ACTION_DOWN
- && mView.disallowSingleClick(ev)
- && !mAccessibilityManager.isTouchExplorationEnabled()) {
- if (!mView.isActivated()) {
- return true;
- } else if (!mDoubleTapHelper.isWithinDoubleTapSlop(ev)) {
- mBlockNextTouch = true;
- mView.makeInactive(true /* animate */);
- return true;
- }
- }
- return false;
- }
- /**
- * Use {@link #onTouch(View, MotionEvent) instead}.
- */
- @Override
- public boolean onTouchEvent(MotionEvent ev) {
- return false;
- }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index 551731824570..c34bba782ad5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -42,6 +42,7 @@ import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
+import android.os.SystemClock;
import android.service.notification.StatusBarNotification;
import android.util.ArraySet;
import android.util.AttributeSet;
@@ -71,11 +72,11 @@ import com.android.internal.widget.CachingIconView;
import com.android.systemui.Dependency;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
-import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.PluginListener;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.MenuItem;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.RemoteInputController;
import com.android.systemui.statusbar.StatusBarIconView;
@@ -198,7 +199,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
private NotificationGuts mGuts;
private NotificationEntry mEntry;
private String mAppName;
- private FalsingManager mFalsingManager;
/**
* Whether or not the notification is using the heads up view and should peek from the top.
@@ -1087,6 +1087,20 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
}
@Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ mEntry.setInitializationTime(SystemClock.elapsedRealtime());
+ Dependency.get(PluginManager.class).addPluginListener(this,
+ NotificationMenuRowPlugin.class, false /* Allow multiple */);
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+ Dependency.get(PluginManager.class).removePluginListener(this);
+ }
+
+ @Override
public void onPluginConnected(NotificationMenuRowPlugin plugin, Context pluginContext) {
boolean existed = mMenuRow != null && mMenuRow.getMenuView() != null;
if (existed) {
@@ -1425,7 +1439,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
return mIsBlockingHelperShowing && mNotificationTranslationFinished;
}
- void setOnDismissRunnable(Runnable onDismissRunnable) {
+ public void setOnDismissRunnable(Runnable onDismissRunnable) {
mOnDismissRunnable = onDismissRunnable;
}
@@ -1583,6 +1597,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
mMenuRow = new NotificationMenuRow(mContext);
mImageResolver = new NotificationInlineImageResolver(context,
new NotificationInlineImageCache());
+ mMediaManager = Dependency.get(NotificationMediaManager.class);
initDimens();
}
@@ -1597,11 +1612,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
NotificationGroupManager groupManager,
HeadsUpManager headsUpManager,
RowContentBindStage rowContentBindStage,
- OnExpandClickListener onExpandClickListener,
- NotificationMediaManager notificationMediaManager,
- OnAppOpsClickListener onAppOpsClickListener,
- FalsingManager falsingManager,
- StatusBarStateController statusBarStateController) {
+ OnExpandClickListener onExpandClickListener) {
mAppName = appName;
if (mMenuRow != null && mMenuRow.getMenuView() != null) {
mMenuRow.setAppName(mAppName);
@@ -1614,9 +1625,9 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
mHeadsUpManager = headsUpManager;
mRowContentBindStage = rowContentBindStage;
mOnExpandClickListener = onExpandClickListener;
- mMediaManager = notificationMediaManager;
- setAppOpsOnClickListener(onAppOpsClickListener);
- mFalsingManager = falsingManager;
+ }
+
+ public void setStatusBarStateController(StatusBarStateController statusBarStateController) {
mStatusbarStateController = statusBarStateController;
}
@@ -1708,7 +1719,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
return mOnAppOpsClickListener;
}
- void setAppOpsOnClickListener(ExpandableNotificationRow.OnAppOpsClickListener l) {
+ public void setAppOpsOnClickListener(ExpandableNotificationRow.OnAppOpsClickListener l) {
mOnAppOpsClickListener = v -> {
createMenu();
NotificationMenuRowPlugin provider = getProvider();
@@ -2177,7 +2188,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
* @param allowChildExpansion whether a call to this method allows expanding children
*/
public void setUserExpanded(boolean userExpanded, boolean allowChildExpansion) {
- mFalsingManager.setNotificationExpanded();
+ getFalsingManager().setNotificationExpanded();
if (mIsSummaryWithChildren && !shouldShowPublic() && allowChildExpansion
&& !mChildrenContainer.showingAsLowPriority()) {
final boolean wasExpanded = mGroupManager.isGroupExpanded(mEntry.getSbn());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java
deleted file mode 100644
index 39fab439ad07..000000000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.notification.row;
-
-import static com.android.systemui.Dependency.ALLOW_NOTIFICATION_LONG_PRESS_NAME;
-import static com.android.systemui.statusbar.NotificationRemoteInputManager.ENABLE_REMOTE_INPUT;
-
-import android.view.View;
-import android.view.ViewGroup;
-
-import com.android.systemui.plugins.FalsingManager;
-import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
-import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.shared.plugins.PluginManager;
-import com.android.systemui.statusbar.NotificationMediaManager;
-import com.android.systemui.statusbar.notification.logging.NotificationLogger;
-import com.android.systemui.statusbar.notification.row.dagger.AppName;
-import com.android.systemui.statusbar.notification.row.dagger.DismissRunnable;
-import com.android.systemui.statusbar.notification.row.dagger.NotificationKey;
-import com.android.systemui.statusbar.notification.row.dagger.NotificationRowScope;
-import com.android.systemui.statusbar.phone.KeyguardBypassController;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
-import com.android.systemui.statusbar.policy.HeadsUpManager;
-import com.android.systemui.util.time.SystemClock;
-
-import javax.inject.Inject;
-import javax.inject.Named;
-
-/**
- * Controller for {@link ExpandableNotificationRow}.
- */
-@NotificationRowScope
-public class ExpandableNotificationRowController {
- private final ExpandableNotificationRow mView;
- private final ActivatableNotificationViewController mActivatableNotificationViewController;
- private final NotificationMediaManager mMediaManager;
- private final PluginManager mPluginManager;
- private final SystemClock mClock;
- private final String mAppName;
- private final String mNotificationKey;
- private final KeyguardBypassController mKeyguardBypassController;
- private final NotificationGroupManager mNotificationGroupManager;
- private final RowContentBindStage mRowContentBindStage;
- private final NotificationLogger mNotificationLogger;
- private final HeadsUpManager mHeadsUpManager;
- private final ExpandableNotificationRow.OnExpandClickListener mOnExpandClickListener;
- private final StatusBarStateController mStatusBarStateController;
- private final NotificationRowContentBinder.InflationCallback mInflationCallback;
-
- private final ExpandableNotificationRow.ExpansionLogger mExpansionLogger =
- this::logNotificationExpansion;
- private final ExpandableNotificationRow.OnAppOpsClickListener mOnAppOpsClickListener;
- private final NotificationGutsManager mNotificationGutsManager;
- private Runnable mOnDismissRunnable;
- private final FalsingManager mFalsingManager;
- private final boolean mAllowLongPress;
-
- @Inject
- public ExpandableNotificationRowController(ExpandableNotificationRow view,
- ActivatableNotificationViewController activatableNotificationViewController,
- NotificationMediaManager mediaManager, PluginManager pluginManager,
- SystemClock clock, @AppName String appName, @NotificationKey String notificationKey,
- KeyguardBypassController keyguardBypassController,
- NotificationGroupManager notificationGroupManager,
- RowContentBindStage rowContentBindStage,
- NotificationLogger notificationLogger, HeadsUpManager headsUpManager,
- ExpandableNotificationRow.OnExpandClickListener onExpandClickListener,
- StatusBarStateController statusBarStateController,
- NotificationRowContentBinder.InflationCallback inflationCallback,
- NotificationGutsManager notificationGutsManager,
- @Named(ALLOW_NOTIFICATION_LONG_PRESS_NAME) boolean allowLongPress,
- @DismissRunnable Runnable onDismissRunnable, FalsingManager falsingManager) {
- mView = view;
- mActivatableNotificationViewController = activatableNotificationViewController;
- mMediaManager = mediaManager;
- mPluginManager = pluginManager;
- mClock = clock;
- mAppName = appName;
- mNotificationKey = notificationKey;
- mKeyguardBypassController = keyguardBypassController;
- mNotificationGroupManager = notificationGroupManager;
- mRowContentBindStage = rowContentBindStage;
- mNotificationLogger = notificationLogger;
- mHeadsUpManager = headsUpManager;
- mOnExpandClickListener = onExpandClickListener;
- mStatusBarStateController = statusBarStateController;
- mInflationCallback = inflationCallback;
- mNotificationGutsManager = notificationGutsManager;
- mOnDismissRunnable = onDismissRunnable;
- mOnAppOpsClickListener = mNotificationGutsManager::openGuts;
- mAllowLongPress = allowLongPress;
- mFalsingManager = falsingManager;
- }
-
- /**
- * Initialize the controller.
- */
- public void init() {
- mActivatableNotificationViewController.init();
- mView.initialize(
- mAppName,
- mNotificationKey,
- mExpansionLogger,
- mKeyguardBypassController,
- mNotificationGroupManager,
- mHeadsUpManager,
- mRowContentBindStage,
- mOnExpandClickListener,
- mMediaManager,
- mOnAppOpsClickListener,
- mFalsingManager,
- mStatusBarStateController
- );
- mView.setOnDismissRunnable(mOnDismissRunnable);
- mView.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
- if (mAllowLongPress) {
- mView.setLongPressListener(mNotificationGutsManager::openGuts);
- }
- if (ENABLE_REMOTE_INPUT) {
- mView.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
- }
-
- mView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
- @Override
- public void onViewAttachedToWindow(View v) {
- mView.getEntry().setInitializationTime(mClock.elapsedRealtime());
- mPluginManager.addPluginListener(mView,
- NotificationMenuRowPlugin.class, false /* Allow multiple */);
- }
-
- @Override
- public void onViewDetachedFromWindow(View v) {
- mPluginManager.removePluginListener(mView);
- }
- });
- }
-
- private void logNotificationExpansion(String key, boolean userAction, boolean expanded) {
- mNotificationLogger.onExpansionChanged(key, userAction, expanded);
- }
-
- /** */
- public void setOnDismissRunnable(Runnable onDismissRunnable) {
- mOnDismissRunnable = onDismissRunnable;
- mView.setOnDismissRunnable(onDismissRunnable);
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableOutlineViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableOutlineViewController.java
deleted file mode 100644
index 75c9d1e6f2fc..000000000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableOutlineViewController.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.notification.row;
-
-import javax.inject.Inject;
-
-/**
- * Controller for {@link ExpandableOutlineView}.
- */
-public class ExpandableOutlineViewController {
- private final ExpandableOutlineView mView;
- private final ExpandableViewController mExpandableViewController;
-
- @Inject
- public ExpandableOutlineViewController(ExpandableOutlineView view,
- ExpandableViewController expandableViewController) {
- mView = view;
- mExpandableViewController = expandableViewController;
- }
-
- /**
- * Initialize the controller.
- */
- public void init() {
- mExpandableViewController.init();
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowInflaterTask.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowInflaterTask.java
index 6feffe654630..c173b4dbaebe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowInflaterTask.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowInflaterTask.java
@@ -26,6 +26,7 @@ import androidx.asynclayoutinflater.view.AsyncLayoutInflater;
import com.android.systemui.R;
import com.android.systemui.statusbar.InflationTask;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.row.dagger.NotificationRowComponent;
import javax.inject.Inject;
@@ -36,6 +37,7 @@ public class RowInflaterTask implements InflationTask, AsyncLayoutInflater.OnInf
private static final String TAG = "RowInflaterTask";
private static final boolean TRACE_ORIGIN = true;
+ private final NotificationRowComponent.Builder mNotificationRowComponentBuilder;
private RowInflationFinishedListener mListener;
private NotificationEntry mEntry;
@@ -43,7 +45,10 @@ public class RowInflaterTask implements InflationTask, AsyncLayoutInflater.OnInf
private Throwable mInflateOrigin;
@Inject
- public RowInflaterTask() {
+ public RowInflaterTask(
+ NotificationRowComponent.Builder notificationRowComponentBuilder) {
+ super();
+ mNotificationRowComponentBuilder = notificationRowComponentBuilder;
}
/**
@@ -70,6 +75,12 @@ public class RowInflaterTask implements InflationTask, AsyncLayoutInflater.OnInf
public void onInflateFinished(View view, int resid, ViewGroup parent) {
if (!mCancelled) {
try {
+ // Setup the controller for the view.
+ NotificationRowComponent component = mNotificationRowComponentBuilder
+ .activatableNotificationView((ActivatableNotificationView) view)
+ .build();
+ component.getActivatableNotificationViewController().init();
+
mEntry.onInflationTaskFinished();
mListener.onInflationFinished((ExpandableNotificationRow) view);
} catch (Throwable t) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/dagger/ActivatableNotificationViewModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/dagger/ActivatableNotificationViewModule.java
deleted file mode 100644
index a3dfa608c709..000000000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/dagger/ActivatableNotificationViewModule.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.notification.row.dagger;
-
-import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
-import com.android.systemui.statusbar.notification.row.ExpandableOutlineView;
-import com.android.systemui.statusbar.notification.row.ExpandableView;
-
-import dagger.Binds;
-import dagger.Module;
-
-/**
- * Module for NotificationRowComponent.
- */
-@Module
-public interface ActivatableNotificationViewModule {
- /** ExpandableView is provided as an instance of ActivatableNotificationView. */
- @Binds
- ExpandableView bindExpandableView(ActivatableNotificationView view);
- /** ExpandableOutlineView is provided as an instance of ActivatableNotificationView. */
- @Binds
- ExpandableOutlineView bindExpandableOutlineView(ActivatableNotificationView view);
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/dagger/DismissRunnable.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/dagger/DismissRunnable.java
deleted file mode 100644
index 433114224289..000000000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/dagger/DismissRunnable.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.notification.row.dagger;
-
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.Retention;
-
-import javax.inject.Qualifier;
-
-@Qualifier
-@Documented
-@Retention(RUNTIME)
-public @interface DismissRunnable {
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/dagger/ExpandableNotificationRowComponent.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/dagger/ExpandableNotificationRowComponent.java
deleted file mode 100644
index 6d6d3e446f53..000000000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/dagger/ExpandableNotificationRowComponent.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.notification.row.dagger;
-
-import android.content.Context;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.service.notification.StatusBarNotification;
-
-import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRowController;
-import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder;
-import com.android.systemui.statusbar.notification.row.RowContentBindStage;
-import com.android.systemui.statusbar.phone.StatusBar;
-
-import dagger.Binds;
-import dagger.BindsInstance;
-import dagger.Module;
-import dagger.Provides;
-import dagger.Subcomponent;
-
-/**
- * Dagger Component for a {@link ExpandableNotificationRow}.
- */
-@Subcomponent(modules = {ExpandableNotificationRowComponent.ExpandableNotificationRowModule.class,
- ActivatableNotificationViewModule.class})
-@NotificationRowScope
-public interface ExpandableNotificationRowComponent {
-
- /**
- * Builder for {@link NotificationRowComponent}.
- */
- @Subcomponent.Builder
- interface Builder {
- // TODO: NotificationEntry contains a reference to ExpandableNotificationRow, so it
- // should be possible to pull one from the other, but they aren't connected at the time
- // this component is constructed.
- @BindsInstance
- Builder expandableNotificationRow(ExpandableNotificationRow view);
- @BindsInstance
- Builder notificationEntry(NotificationEntry entry);
- @BindsInstance
- Builder onDismissRunnable(@DismissRunnable Runnable runnable);
- @BindsInstance
- Builder rowContentBindStage(RowContentBindStage rowContentBindStage);
- @BindsInstance
- Builder inflationCallback(NotificationRowContentBinder.InflationCallback inflationCallback);
- @BindsInstance
- Builder onExpandClickListener(ExpandableNotificationRow.OnExpandClickListener presenter);
- ExpandableNotificationRowComponent build();
- }
-
- /**
- * Creates a ExpandableNotificationRowController.
- */
- @NotificationRowScope
- ExpandableNotificationRowController getExpandableNotificationRowController();
-
- /**
- * Dagger Module that extracts interesting properties from an ExpandableNotificationRow.
- */
- @Module
- abstract class ExpandableNotificationRowModule {
-
- /** ExpandableNotificationRow is provided as an instance of ActivatableNotificationView. */
- @Binds
- abstract ActivatableNotificationView bindExpandableView(ExpandableNotificationRow view);
-
- @Provides
- static StatusBarNotification provideStatusBarNotification(
- NotificationEntry notificationEntry) {
- return notificationEntry.getSbn();
- }
-
- @Provides
- @NotificationKey
- static String provideNotificationKey(StatusBarNotification statusBarNotification) {
- return statusBarNotification.getKey();
- }
-
- @Provides
- @AppName
- static String provideAppName(Context context, StatusBarNotification statusBarNotification) {
- // Get the app name.
- // Note that Notification.Builder#bindHeaderAppName has similar logic
- // but since this field is used in the guts, it must be accurate.
- // Therefore we will only show the application label, or, failing that, the
- // package name. No substitutions.
- PackageManager pmUser = StatusBar.getPackageManagerForUser(
- context, statusBarNotification.getUser().getIdentifier());
- final String pkg = statusBarNotification.getPackageName();
- try {
- final ApplicationInfo info = pmUser.getApplicationInfo(pkg,
- PackageManager.MATCH_UNINSTALLED_PACKAGES
- | PackageManager.MATCH_DISABLED_COMPONENTS);
- if (info != null) {
- return String.valueOf(pmUser.getApplicationLabel(info));
- }
- } catch (PackageManager.NameNotFoundException e) {
- // Do nothing
- }
-
- return pkg;
- }
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/dagger/NotificationKey.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/dagger/NotificationKey.java
deleted file mode 100644
index b1fff383cd5d..000000000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/dagger/NotificationKey.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.notification.row.dagger;
-
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.Retention;
-
-import javax.inject.Qualifier;
-
-@Qualifier
-@Documented
-@Retention(RUNTIME)
-public @interface NotificationKey {
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/dagger/NotificationRowComponent.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/dagger/NotificationRowComponent.java
index 1f535c5e3f56..f16ea7ae23e9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/dagger/NotificationRowComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/dagger/NotificationRowComponent.java
@@ -16,17 +16,24 @@
package com.android.systemui.statusbar.notification.row.dagger;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
import com.android.systemui.statusbar.notification.row.ActivatableNotificationViewController;
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+
+import javax.inject.Scope;
+
import dagger.BindsInstance;
import dagger.Subcomponent;
/**
* Dagger subcomponent for Notification related views.
*/
-@Subcomponent(modules = {ActivatableNotificationViewModule.class})
-@NotificationRowScope
+@Subcomponent(modules = {})
+@NotificationRowComponent.NotificationRowScope
public interface NotificationRowComponent {
/**
* Builder for {@link NotificationRowComponent}.
@@ -39,6 +46,14 @@ public interface NotificationRowComponent {
}
/**
+ * Scope annotation for singleton items within the StatusBarComponent.
+ */
+ @Documented
+ @Retention(RUNTIME)
+ @Scope
+ @interface NotificationRowScope {}
+
+ /**
* Creates a ActivatableNotificationViewController.
*/
@NotificationRowScope
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/dagger/NotificationRowScope.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/dagger/NotificationRowScope.java
deleted file mode 100644
index 4555b839a3f2..000000000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/dagger/NotificationRowScope.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.notification.row.dagger;
-
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.Retention;
-
-import javax.inject.Scope;
-
-/**
- * Scope annotation for singleton items within the StatusBarComponent.
- */
-@Documented
-@Retention(RUNTIME)
-@Scope
-public @interface NotificationRowScope {}
diff --git a/packages/SystemUI/src/com/android/systemui/util/animation/PhysicsAnimator.kt b/packages/SystemUI/src/com/android/systemui/util/animation/PhysicsAnimator.kt
index cfd77be9303d..f4157f21e158 100644
--- a/packages/SystemUI/src/com/android/systemui/util/animation/PhysicsAnimator.kt
+++ b/packages/SystemUI/src/com/android/systemui/util/animation/PhysicsAnimator.kt
@@ -901,6 +901,23 @@ class PhysicsAnimator<T> private constructor (val target: T) {
verboseLogging = debug
}
+ /**
+ * Estimates the end value of a fling that starts at the given value using the provided
+ * start velocity and fling configuration.
+ *
+ * This is only an estimate. Fling animations use a timing-based physics simulation that is
+ * non-deterministic, so this exact value may not be reached.
+ */
+ @JvmStatic
+ fun estimateFlingEndValue(
+ startValue: Float,
+ startVelocity: Float,
+ flingConfig: FlingConfig
+ ): Float {
+ val distance = startVelocity / (flingConfig.friction * FLING_FRICTION_SCALAR_MULTIPLIER)
+ return Math.min(flingConfig.max, Math.max(flingConfig.min, startValue + distance))
+ }
+
@JvmStatic
fun getReadablePropertyName(property: FloatPropertyCompat<*>): String {
return when (property) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/CustomTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/external/CustomTileTest.kt
index 4becd522ebd6..9fe2569177d7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/CustomTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/CustomTileTest.kt
@@ -88,8 +88,8 @@ class CustomTileTest : SysuiTestCase() {
}
@Test
- fun testBooleanTileHasBooleanState() {
- `when`(mTileServiceManager.isBooleanTile).thenReturn(true)
+ fun testToggleableTileHasBooleanState() {
+ `when`(mTileServiceManager.isToggleableTile).thenReturn(true)
customTile = CustomTile.create(mTileHost, TILE_SPEC)
assertTrue(customTile.state is QSTile.BooleanState)
@@ -104,7 +104,7 @@ class CustomTileTest : SysuiTestCase() {
@Test
fun testValueUpdatedInBooleanTile() {
- `when`(mTileServiceManager.isBooleanTile).thenReturn(true)
+ `when`(mTileServiceManager.isToggleableTile).thenReturn(true)
customTile = CustomTile.create(mTileHost, TILE_SPEC)
customTile.qsTile.icon = mock(Icon::class.java)
`when`(customTile.qsTile.icon.loadDrawable(any(Context::class.java)))
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTest.java
index 9e5e582bf5e7..42fd288d94ee 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTest.java
@@ -105,7 +105,7 @@ public class TileLifecycleManagerTest extends SysuiTestCase {
defaultServiceInfo = new ServiceInfo();
defaultServiceInfo.metaData = new Bundle();
defaultServiceInfo.metaData.putBoolean(TileService.META_DATA_ACTIVE_TILE, true);
- defaultServiceInfo.metaData.putBoolean(TileService.META_DATA_BOOLEAN_TILE, true);
+ defaultServiceInfo.metaData.putBoolean(TileService.META_DATA_TOGGLEABLE_TILE, true);
}
when(mMockPackageManagerAdapter.getServiceInfo(any(), anyInt(), anyInt()))
.thenReturn(defaultServiceInfo);
@@ -244,7 +244,7 @@ public class TileLifecycleManagerTest extends SysuiTestCase {
}
@Test
- public void testBooleanTile() throws Exception {
- assertTrue(mStateManager.isBooleanTile());
+ public void testToggleableTile() throws Exception {
+ assertTrue(mStateManager.isToggleableTile());
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
index 5a0a495e1f85..07f6936ece07 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
@@ -58,13 +58,10 @@ import androidx.annotation.NonNull;
import androidx.test.filters.SmallTest;
import com.android.internal.statusbar.NotificationVisibility;
-import com.android.internal.util.NotificationMessagingUtil;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.statusbar.FeatureFlags;
import com.android.systemui.statusbar.NotificationLifetimeExtender;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
@@ -86,13 +83,12 @@ import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
import com.android.systemui.statusbar.notification.row.ActivatableNotificationViewController;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRowController;
import com.android.systemui.statusbar.notification.row.NotifBindPipeline;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
import com.android.systemui.statusbar.notification.row.RowContentBindParams;
import com.android.systemui.statusbar.notification.row.RowContentBindStage;
import com.android.systemui.statusbar.notification.row.RowInflaterTask;
-import com.android.systemui.statusbar.notification.row.dagger.ExpandableNotificationRowComponent;
+import com.android.systemui.statusbar.notification.row.dagger.NotificationRowComponent;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
@@ -100,7 +96,6 @@ import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.util.Assert;
import com.android.systemui.util.leak.LeakDetector;
-import com.android.systemui.util.time.FakeSystemClock;
import org.junit.After;
import org.junit.Before;
@@ -111,7 +106,6 @@ import org.mockito.ArgumentCaptor;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import org.mockito.stubbing.Answer;
import java.util.ArrayList;
import java.util.Arrays;
@@ -147,13 +141,8 @@ public class NotificationEntryManagerTest extends SysuiTestCase {
@Mock private NotificationEntryManagerLogger mLogger;
@Mock private FeatureFlags mFeatureFlags;
@Mock private LeakDetector mLeakDetector;
- @Mock private NotificationMediaManager mNotificationMediaManager;
- @Mock private ExpandableNotificationRowComponent.Builder
- mExpandableNotificationRowComponentBuilder;
- @Mock private ExpandableNotificationRowComponent mExpandableNotificationRowComponent;
- @Mock private FalsingManager mFalsingManager;
- @Mock private KeyguardBypassController mKeyguardBypassController;
- @Mock private StatusBarStateController mStatusBarStateController;
+ @Mock private ActivatableNotificationViewController mActivatableNotificationViewController;
+ @Mock private NotificationRowComponent.Builder mNotificationRowComponentBuilder;
private int mId;
private NotificationEntry mEntry;
@@ -202,6 +191,7 @@ public class NotificationEntryManagerTest extends SysuiTestCase {
public void setUp() {
MockitoAnnotations.initMocks(this);
mDependency.injectMockDependency(SmartReplyController.class);
+ mDependency.injectMockDependency(NotificationMediaManager.class);
mCountDownLatch = new CountDownLatch(1);
@@ -217,23 +207,28 @@ public class NotificationEntryManagerTest extends SysuiTestCase {
mEntry.expandedIcon = mock(StatusBarIconView.class);
+ when(mNotificationRowComponentBuilder.activatableNotificationView(any()))
+ .thenReturn(mNotificationRowComponentBuilder);
+ when(mNotificationRowComponentBuilder.build()).thenReturn(
+ () -> mActivatableNotificationViewController);
+
RowContentBindStage bindStage = mock(RowContentBindStage.class);
when(bindStage.getStageParams(any())).thenReturn(new RowContentBindParams());
+
NotificationRowBinderImpl notificationRowBinder =
new NotificationRowBinderImpl(mContext,
- new NotificationMessagingUtil(mContext),
mRemoteInputManager,
mLockscreenUserManager,
mock(NotifBindPipeline.class),
bindStage,
true, /* allowLongPress */
- mKeyguardBypassController,
- mStatusBarStateController,
+ mock(KeyguardBypassController.class),
+ mock(StatusBarStateController.class),
mGroupManager,
mGutsManager,
mNotificationInterruptionStateProvider,
- RowInflaterTask::new,
- mExpandableNotificationRowComponentBuilder);
+ () -> new RowInflaterTask(mNotificationRowComponentBuilder),
+ mock(NotificationLogger.class));
when(mFeatureFlags.isNewNotifPipelineEnabled()).thenReturn(false);
when(mFeatureFlags.isNewNotifPipelineRenderingEnabled()).thenReturn(false);
@@ -241,7 +236,7 @@ public class NotificationEntryManagerTest extends SysuiTestCase {
mLogger,
mGroupManager,
new NotificationRankingManager(
- () -> mNotificationMediaManager,
+ () -> mock(NotificationMediaManager.class),
mGroupManager,
mHeadsUpManager,
mock(NotificationFilter.class),
@@ -260,55 +255,13 @@ public class NotificationEntryManagerTest extends SysuiTestCase {
mEntryManager.addNotificationEntryListener(mEntryListener);
mEntryManager.addNotificationRemoveInterceptor(mRemoveInterceptor);
- notificationRowBinder.setUpWithPresenter(mPresenter, mListContainer, mBindCallback);
+ notificationRowBinder.setUpWithPresenter(
+ mPresenter, mListContainer, mHeadsUpManager, mBindCallback);
notificationRowBinder.setInflationCallback(mEntryManager);
notificationRowBinder.setNotificationClicker(mock(NotificationClicker.class));
setUserSentiment(
mEntry.getKey(), Ranking.USER_SENTIMENT_NEUTRAL);
-
- ArgumentCaptor<ExpandableNotificationRow> viewCaptor =
- ArgumentCaptor.forClass(ExpandableNotificationRow.class);
- when(mExpandableNotificationRowComponentBuilder
- .expandableNotificationRow(viewCaptor.capture()))
- .thenReturn(mExpandableNotificationRowComponentBuilder);
- when(mExpandableNotificationRowComponentBuilder
- .notificationEntry(any()))
- .thenReturn(mExpandableNotificationRowComponentBuilder);
- when(mExpandableNotificationRowComponentBuilder
- .onDismissRunnable(any()))
- .thenReturn(mExpandableNotificationRowComponentBuilder);
- when(mExpandableNotificationRowComponentBuilder
- .inflationCallback(any()))
- .thenReturn(mExpandableNotificationRowComponentBuilder);
- when(mExpandableNotificationRowComponentBuilder
- .onExpandClickListener(any()))
- .thenReturn(mExpandableNotificationRowComponentBuilder);
-
- when(mExpandableNotificationRowComponentBuilder.build())
- .thenReturn(mExpandableNotificationRowComponent);
- when(mExpandableNotificationRowComponent.getExpandableNotificationRowController())
- .thenAnswer((Answer<ExpandableNotificationRowController>) invocation ->
- new ExpandableNotificationRowController(
- viewCaptor.getValue(),
- mock(ActivatableNotificationViewController.class),
- mNotificationMediaManager,
- mock(PluginManager.class),
- new FakeSystemClock(),
- "FOOBAR", "FOOBAR",
- mKeyguardBypassController,
- mGroupManager,
- bindStage,
- mock(NotificationLogger.class),
- mHeadsUpManager,
- mPresenter,
- mStatusBarStateController,
- mEntryManager,
- mGutsManager,
- true,
- null,
- mFalsingManager
- ));
}
@After
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
index a8918103c4a2..d8cf6ed9a47b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
@@ -194,8 +194,9 @@ public class ExpandableNotificationRowTest extends SysuiTestCase {
@Test
public void testClickSound() throws Exception {
assertTrue("Should play sounds by default.", mGroupRow.isSoundEffectsEnabled());
- StatusBarStateController mock = mNotificationTestHelper.getStatusBarStateController();
+ StatusBarStateController mock = mock(StatusBarStateController.class);
when(mock.isDozing()).thenReturn(true);
+ mGroupRow.setStatusBarStateController(mock);
mGroupRow.setSecureStateProvider(()-> false);
assertFalse("Shouldn't play sounds when dark and trusted.",
mGroupRow.isSoundEffectsEnabled());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
index 35b55087873b..9b2e0c375e87 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
@@ -45,7 +45,6 @@ import com.android.internal.statusbar.IStatusBarService;
import com.android.systemui.TestableDependency;
import com.android.systemui.bubbles.BubbleController;
import com.android.systemui.bubbles.BubblesTestActivity;
-import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
@@ -92,7 +91,6 @@ public class NotificationTestHelper {
private final NotifBindPipeline mBindPipeline;
private final NotificationEntryListener mBindPipelineEntryListener;
private final RowContentBindStage mBindStage;
- private StatusBarStateController mStatusBarStateController;
public NotificationTestHelper(Context context, TestableDependency dependency) {
mContext = context;
@@ -100,9 +98,9 @@ public class NotificationTestHelper {
dependency.injectMockDependency(BubbleController.class);
dependency.injectMockDependency(NotificationShadeWindowController.class);
dependency.injectMockDependency(SmartReplyController.class);
- mStatusBarStateController = mock(StatusBarStateController.class);
- mGroupManager = new NotificationGroupManager(mStatusBarStateController);
- mHeadsUpManager = new HeadsUpManagerPhone(mContext, mStatusBarStateController,
+ StatusBarStateController stateController = mock(StatusBarStateController.class);
+ mGroupManager = new NotificationGroupManager(stateController);
+ mHeadsUpManager = new HeadsUpManagerPhone(mContext, stateController,
mock(KeyguardBypassController.class));
mHeadsUpManager.setUp(null, mGroupManager, null, null);
mGroupManager.setHeadsUpManager(mHeadsUpManager);
@@ -323,10 +321,6 @@ public class NotificationTestHelper {
return notificationBuilder.build();
}
- public StatusBarStateController getStatusBarStateController() {
- return mStatusBarStateController;
- }
-
private ExpandableNotificationRow generateRow(
Notification notification,
String pkg,
@@ -388,11 +382,7 @@ public class NotificationTestHelper {
mGroupManager,
mHeadsUpManager,
mBindStage,
- mock(OnExpandClickListener.class),
- mock(NotificationMediaManager.class),
- mock(ExpandableNotificationRow.OnAppOpsClickListener.class),
- mock(FalsingManager.class),
- mStatusBarStateController);
+ mock(OnExpandClickListener.class));
row.setAboveShelfChangedListener(aboveShelf -> { });
mBindStage.getStageParams(entry).requireContentViews(extraInflationFlags);
inflateAndWait(entry, mBindStage);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManagerTest.java
index 2d1bc7890aed..e84f14a6a2c1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManagerTest.java
@@ -30,6 +30,7 @@ import android.testing.TestableLooper.RunWithLooper;
import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
@@ -58,6 +59,8 @@ public class NotificationRoundnessManagerTest extends SysuiTestCase {
private ExpandableNotificationRow mFirst;
private ExpandableNotificationRow mSecond;
@Mock
+ private StatusBarStateController mStatusBarStateController;
+ @Mock
private KeyguardBypassController mBypassController;
@Before
@@ -147,12 +150,13 @@ public class NotificationRoundnessManagerTest extends SysuiTestCase {
createSection(mFirst, mSecond),
createSection(null, null)
});
- NotificationTestHelper testHelper = new NotificationTestHelper(getContext(), mDependency);
- ExpandableNotificationRow row = testHelper.createRow();
+ ExpandableNotificationRow row = new NotificationTestHelper(getContext(), mDependency)
+ .createRow();
NotificationEntry entry = mock(NotificationEntry.class);
when(entry.getRow()).thenReturn(row);
- when(testHelper.getStatusBarStateController().isDozing()).thenReturn(true);
+ when(mStatusBarStateController.isDozing()).thenReturn(true);
+ row.setStatusBarStateController(mStatusBarStateController);
row.setHeadsUp(true);
mRoundnessManager.onHeadsUpStateChanged(entry, true);
Assert.assertEquals(1f, row.getCurrentBottomRoundness(), 0.0f);
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
index 1cb9313d9bf9..4474f608f955 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
@@ -82,6 +82,7 @@ import com.android.server.LocalServices;
import com.android.server.autofill.AutofillManagerService.AutofillCompatState;
import com.android.server.autofill.RemoteAugmentedAutofillService.RemoteAugmentedAutofillServiceCallbacks;
import com.android.server.autofill.ui.AutoFillUI;
+import com.android.server.contentcapture.ContentCaptureManagerInternal;
import com.android.server.infra.AbstractPerUserSystemService;
import com.android.server.inputmethod.InputMethodManagerInternal;
@@ -180,6 +181,8 @@ final class AutofillManagerServiceImpl
private final InputMethodManagerInternal mInputMethodManagerInternal;
+ private final ContentCaptureManagerInternal mContentCaptureManagerInternal;
+
AutofillManagerServiceImpl(AutofillManagerService master, Object lock,
LocalLog uiLatencyHistory, LocalLog wtfHistory, int userId, AutoFillUI ui,
AutofillCompatState autofillCompatState,
@@ -192,10 +195,22 @@ final class AutofillManagerServiceImpl
mFieldClassificationStrategy = new FieldClassificationStrategy(getContext(), userId);
mAutofillCompatState = autofillCompatState;
mInputMethodManagerInternal = LocalServices.getService(InputMethodManagerInternal.class);
+ mContentCaptureManagerInternal = LocalServices.getService(
+ ContentCaptureManagerInternal.class);
updateLocked(disabled);
}
+ boolean sendActivityAssistDataToContentCapture(@NonNull IBinder activityToken,
+ @NonNull Bundle data) {
+ if (mContentCaptureManagerInternal != null) {
+ mContentCaptureManagerInternal.sendActivityAssistData(getUserId(), activityToken, data);
+ return true;
+ }
+
+ return false;
+ }
+
@GuardedBy("mLock")
void onBackKeyPressed() {
final RemoteAugmentedAutofillService remoteService =
diff --git a/services/autofill/java/com/android/server/autofill/InlineSuggestionSession.java b/services/autofill/java/com/android/server/autofill/InlineSuggestionSession.java
new file mode 100644
index 000000000000..1fc48d235add
--- /dev/null
+++ b/services/autofill/java/com/android/server/autofill/InlineSuggestionSession.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2020 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.autofill;
+
+import static com.android.server.autofill.Helper.sDebug;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.ComponentName;
+import android.os.RemoteException;
+import android.util.Log;
+import android.view.autofill.AutofillId;
+import android.view.inputmethod.InlineSuggestionsRequest;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.view.IInlineSuggestionsRequestCallback;
+import com.android.internal.view.IInlineSuggestionsResponseCallback;
+import com.android.server.inputmethod.InputMethodManagerInternal;
+
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+/**
+ * Maintains an inline suggestion autofill session.
+ *
+ * <p> This class is thread safe.
+ */
+final class InlineSuggestionSession {
+
+ private static final String TAG = "InlineSuggestionSession";
+ private static final int INLINE_REQUEST_TIMEOUT_MS = 1000;
+
+ @NonNull
+ private final InputMethodManagerInternal mInputMethodManagerInternal;
+ private final int mUserId;
+ @NonNull
+ private final ComponentName mComponentName;
+ @NonNull
+ private final Object mLock;
+
+ @GuardedBy("mLock")
+ @Nullable
+ private CompletableFuture<ImeResponse> mPendingImeResponse;
+
+ InlineSuggestionSession(InputMethodManagerInternal inputMethodManagerInternal,
+ int userId, ComponentName componentName) {
+ mInputMethodManagerInternal = inputMethodManagerInternal;
+ mUserId = userId;
+ mComponentName = componentName;
+ mLock = new Object();
+ }
+
+ public void createRequest(@NonNull AutofillId currentViewId) {
+ synchronized (mLock) {
+ cancelCurrentRequest();
+ mPendingImeResponse = new CompletableFuture<>();
+ mInputMethodManagerInternal.onCreateInlineSuggestionsRequest(
+ mUserId, mComponentName, currentViewId,
+ new InlineSuggestionsRequestCallbackImpl(mPendingImeResponse));
+ }
+ }
+
+ @Nullable
+ public ImeResponse waitAndGetImeResponse() {
+ CompletableFuture<ImeResponse> pendingImeResponse = getPendingImeResponse();
+ if (pendingImeResponse == null || pendingImeResponse.isCancelled()) {
+ return null;
+ }
+ try {
+ return pendingImeResponse.get(INLINE_REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS);
+ } catch (TimeoutException e) {
+ Log.w(TAG, "Exception getting inline suggestions request in time: " + e);
+ } catch (CancellationException e) {
+ Log.w(TAG, "Inline suggestions request cancelled");
+ } catch (InterruptedException | ExecutionException e) {
+ throw new RuntimeException(e);
+ }
+ return null;
+ }
+
+ private void cancelCurrentRequest() {
+ CompletableFuture<ImeResponse> pendingImeResponse = getPendingImeResponse();
+ if (pendingImeResponse != null) {
+ pendingImeResponse.cancel(true);
+ }
+ }
+
+ @Nullable
+ @GuardedBy("mLock")
+ private CompletableFuture<ImeResponse> getPendingImeResponse() {
+ synchronized (mLock) {
+ return mPendingImeResponse;
+ }
+ }
+
+ private static final class InlineSuggestionsRequestCallbackImpl
+ extends IInlineSuggestionsRequestCallback.Stub {
+
+ private final CompletableFuture<ImeResponse> mResponse;
+
+ private InlineSuggestionsRequestCallbackImpl(CompletableFuture<ImeResponse> response) {
+ mResponse = response;
+ }
+
+ @Override
+ public void onInlineSuggestionsUnsupported() throws RemoteException {
+ if (sDebug) {
+ Log.d(TAG, "onInlineSuggestionsUnsupported() called.");
+ }
+ mResponse.cancel(true);
+ }
+
+ @Override
+ public void onInlineSuggestionsRequest(InlineSuggestionsRequest request,
+ IInlineSuggestionsResponseCallback callback) throws RemoteException {
+ if (sDebug) {
+ Log.d(TAG, "onInlineSuggestionsRequest() received: " + request);
+ }
+ if (request != null && callback != null) {
+ mResponse.complete(new ImeResponse(request, callback));
+ } else {
+ mResponse.cancel(true);
+ }
+ }
+ }
+
+ /**
+ * A data class wrapping IME responses for the inline suggestion request.
+ */
+ public static class ImeResponse {
+ @NonNull
+ private final InlineSuggestionsRequest mRequest;
+
+ @NonNull
+ private final IInlineSuggestionsResponseCallback mCallback;
+
+ ImeResponse(@NonNull InlineSuggestionsRequest request,
+ @NonNull IInlineSuggestionsResponseCallback callback) {
+ mRequest = request;
+ mCallback = callback;
+ }
+
+ public InlineSuggestionsRequest getRequest() {
+ return mRequest;
+ }
+
+ public IInlineSuggestionsResponseCallback getCallback() {
+ return mCallback;
+ }
+ }
+}
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 2fc116e504ee..53f85ea7b119 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -100,7 +100,6 @@ import com.android.internal.annotations.GuardedBy;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.util.ArrayUtils;
-import com.android.internal.view.IInlineSuggestionsRequestCallback;
import com.android.internal.view.IInlineSuggestionsResponseCallback;
import com.android.server.autofill.ui.AutoFillUI;
import com.android.server.autofill.ui.InlineSuggestionFactory;
@@ -114,11 +113,6 @@ import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
-import java.util.concurrent.CancellationException;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger;
/**
@@ -159,9 +153,6 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
/** uid the session is for */
public final int uid;
- /** user id the session is for */
- public final int userId;
-
/** ID of the task associated with this session's activity */
public final int taskId;
@@ -310,12 +301,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
@GuardedBy("mLock")
private boolean mForAugmentedAutofillOnly;
- @NonNull
- private final InputMethodManagerInternal mInputMethodManagerInternal;
-
@Nullable
- @GuardedBy("mLock")
- private InlineSuggestionsRequestCallbackImpl mInlineSuggestionsRequestCallback;
+ private final InlineSuggestionSession mInlineSuggestionSession;
/**
* Receiver of assist data from the app's {@link Activity}.
@@ -416,14 +403,16 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
final ArrayList<FillContext> contexts =
mergePreviousSessionLocked(/* forSave= */ false);
- final InlineSuggestionsRequest suggestionsRequest =
- mInlineSuggestionsRequestCallback != null
- ? mInlineSuggestionsRequestCallback.getRequest() : null;
+ final InlineSuggestionSession.ImeResponse imeResponse =
+ mInlineSuggestionSession.waitAndGetImeResponse();
request = new FillRequest(requestId, contexts, mClientState, flags,
- suggestionsRequest);
+ imeResponse != null ? imeResponse.getRequest() : null);
}
+ if (mActivityToken != null) {
+ mService.sendActivityAssistDataToContentCapture(mActivityToken, resultData);
+ }
mRemoteFillService.onFillRequest(request);
}
@@ -616,75 +605,12 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
private void maybeRequestInlineSuggestionsRequestThenFillLocked(@NonNull ViewState viewState,
int newState, int flags) {
if (isInlineSuggestionsEnabled()) {
- mInlineSuggestionsRequestCallback = new InlineSuggestionsRequestCallbackImpl();
- mInputMethodManagerInternal.onCreateInlineSuggestionsRequest(userId,
- mComponentName, mCurrentViewId, mInlineSuggestionsRequestCallback);
+ mInlineSuggestionSession.createRequest(mCurrentViewId);
}
requestNewFillResponseLocked(viewState, newState, flags);
}
- private static final class InlineSuggestionsRequestCallbackImpl
- extends IInlineSuggestionsRequestCallback.Stub {
- private static final int INLINE_REQUEST_TIMEOUT_MS = 1000;
-
- private final CompletableFuture<InlineSuggestionsRequest> mRequest;
- private final CompletableFuture<IInlineSuggestionsResponseCallback> mResponseCallback;
-
- private InlineSuggestionsRequestCallbackImpl() {
- mRequest = new CompletableFuture<>();
- mResponseCallback = new CompletableFuture<>();
- }
-
- @Override
- public void onInlineSuggestionsUnsupported() throws RemoteException {
- if (sDebug) {
- Log.d(TAG, "inline suggestions request unsupported, "
- + "falling back to regular autofill");
- }
- mRequest.cancel(true);
- mResponseCallback.cancel(true);
- }
-
- @Override
- public void onInlineSuggestionsRequest(InlineSuggestionsRequest request,
- IInlineSuggestionsResponseCallback callback) throws RemoteException {
- if (sDebug) {
- Log.d(TAG, "onInlineSuggestionsRequest() received: " + request);
- }
- mRequest.complete(request);
- mResponseCallback.complete(callback);
- }
-
- @Nullable
- private InlineSuggestionsRequest getRequest() {
- try {
- return mRequest.get(INLINE_REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS);
- } catch (TimeoutException e) {
- Log.w(TAG, "Exception getting inline suggestions request in time: " + e);
- } catch (CancellationException e) {
- Log.w(TAG, "Inline suggestions request cancelled");
- } catch (InterruptedException | ExecutionException e) {
- throw new RuntimeException(e);
- }
- return null;
- }
-
- @Nullable
- private IInlineSuggestionsResponseCallback getResponseCallback() {
- try {
- return mResponseCallback.get(INLINE_REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS);
- } catch (TimeoutException e) {
- Log.w(TAG, "Exception getting inline suggestions callback in time: " + e);
- } catch (CancellationException e) {
- Log.w(TAG, "Inline suggestions callback cancelled");
- } catch (InterruptedException | ExecutionException e) {
- throw new RuntimeException(e);
- }
- return null;
- }
- }
-
/**
* Reads a new structure and then request a new fill response from the fill service.
*/
@@ -764,7 +690,6 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
mFlags = flags;
this.taskId = taskId;
this.uid = uid;
- this.userId = userId;
mStartTime = SystemClock.elapsedRealtime();
mService = service;
mLock = lock;
@@ -783,7 +708,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
mForAugmentedAutofillOnly = forAugmentedAutofillOnly;
setClientLocked(client);
- mInputMethodManagerInternal = inputMethodManagerInternal;
+ mInlineSuggestionSession = new InlineSuggestionSession(inputMethodManagerInternal, userId,
+ componentName);
mMetricsLogger.write(newLogMaker(MetricsEvent.AUTOFILL_SESSION_STARTED)
.addTaggedData(MetricsEvent.FIELD_AUTOFILL_FLAGS, flags));
@@ -2676,7 +2602,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
if (response.supportsInlineSuggestions()) {
synchronized (mLock) {
- if (requestShowInlineSuggestions(response, mInlineSuggestionsRequestCallback)) {
+ if (requestShowInlineSuggestionsLocked(response)) {
//TODO(b/137800469): Fix it to log showed only when IME asks for inflation,
// rather than here where framework sends back the response.
mService.logDatasetShown(id, mClientState);
@@ -2719,21 +2645,21 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
/**
* Returns whether we made a request to show inline suggestions.
*/
- private boolean requestShowInlineSuggestions(@NonNull FillResponse response,
- @Nullable InlineSuggestionsRequestCallbackImpl callback) {
+ private boolean requestShowInlineSuggestionsLocked(@NonNull FillResponse response) {
final List<Dataset> datasets = response.getDatasets();
if (datasets == null) {
Log.w(TAG, "response returned null datasets");
return false;
}
- if (callback == null || callback.getRequest() == null
- || callback.getResponseCallback() == null) {
+ final InlineSuggestionSession.ImeResponse imeResponse =
+ mInlineSuggestionSession.waitAndGetImeResponse();
+ if (imeResponse == null) {
Log.w(TAG, "Session input method callback is not set yet");
return false;
}
- final InlineSuggestionsRequest request = callback.getRequest();
+ final InlineSuggestionsRequest request = imeResponse.getRequest();
InlineSuggestionsResponse inlineSuggestionsResponse =
InlineSuggestionFactory.createInlineSuggestionsResponse(request,
response.getRequestId(),
@@ -2744,7 +2670,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
}
});
try {
- callback.getResponseCallback().onInlineSuggestionsResponse(inlineSuggestionsResponse);
+ imeResponse.getCallback().onInlineSuggestionsResponse(inlineSuggestionsResponse);
} catch (RemoteException e) {
Log.w(TAG, "onFillReady() remote error calling onInlineSuggestionsResponse()");
return false;
@@ -3026,12 +2952,21 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
final AutofillId focusedId = AutofillId.withoutSession(mCurrentViewId);
+ // There are 3 cases when augmented autofill should ask IME for a new request:
+ // 1. standard autofill provider is None
+ // 2. standard autofill provider doesn't support inline (and returns null response)
+ // 3. standard autofill provider supports inline, but isn't called because the field
+ // doesn't want autofill
+ if (mForAugmentedAutofillOnly || !isInlineSuggestionsEnabled()) {
+ if (sDebug) Slog.d(TAG, "Create inline request for augmented autofill");
+ mInlineSuggestionSession.createRequest(mCurrentViewId);
+ }
+ InlineSuggestionSession.ImeResponse imeResponse =
+ mInlineSuggestionSession.waitAndGetImeResponse();
final InlineSuggestionsRequest inlineSuggestionsRequest =
- mInlineSuggestionsRequestCallback != null
- ? mInlineSuggestionsRequestCallback.getRequest() : null;
+ imeResponse != null ? imeResponse.getRequest() : null;
final IInlineSuggestionsResponseCallback inlineSuggestionsResponseCallback =
- mInlineSuggestionsRequestCallback != null
- ? mInlineSuggestionsRequestCallback.getResponseCallback() : null;
+ imeResponse != null ? imeResponse.getCallback() : null;
remoteService.onRequestAutofillLocked(id, mClient, taskId, mComponentName, focusedId,
currentValue, inlineSuggestionsRequest, inlineSuggestionsResponseCallback, () -> {
synchronized (mLock) {
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
index 583c5b593b88..32bca35009a8 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
@@ -426,18 +426,26 @@ final class ContentCapturePerUserService
public boolean sendActivityAssistDataLocked(@NonNull IBinder activityToken,
@NonNull Bundle data) {
final int id = getSessionId(activityToken);
+ final Bundle assistData = data.getBundle(ASSIST_KEY_DATA);
+ final AssistStructure assistStructure = data.getParcelable(ASSIST_KEY_STRUCTURE);
+ final AssistContent assistContent = data.getParcelable(ASSIST_KEY_CONTENT);
+ final SnapshotData snapshotData = new SnapshotData(assistData,
+ assistStructure, assistContent);
if (id != NO_SESSION_ID) {
final ContentCaptureServerSession session = mSessions.get(id);
- final Bundle assistData = data.getBundle(ASSIST_KEY_DATA);
- final AssistStructure assistStructure = data.getParcelable(ASSIST_KEY_STRUCTURE);
- final AssistContent assistContent = data.getParcelable(ASSIST_KEY_CONTENT);
- final SnapshotData snapshotData = new SnapshotData(assistData,
- assistStructure, assistContent);
session.sendActivitySnapshotLocked(snapshotData);
return true;
- } else {
- Slog.e(TAG, "Failed to notify activity assist data for activity: " + activityToken);
}
+
+ // We want to send an activity snapshot regardless of whether a content capture session is
+ // present or not since a content capture session is not required for this functionality
+ if (mRemoteService != null) {
+ mRemoteService.onActivitySnapshotRequest(NO_SESSION_ID, snapshotData);
+ Slog.d(TAG, "Notified activity assist data for activity: "
+ + activityToken + " without a session Id");
+ return true;
+ }
+
return false;
}
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index cbf6c274e865..0e5a6bb8bd1c 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -284,16 +284,16 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
static final int ENFORCE_PHONE_STATE_PERMISSION_MASK =
PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR
| PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR
- | PhoneStateListener.LISTEN_EMERGENCY_NUMBER_LIST
- | PhoneStateListener.LISTEN_REGISTRATION_FAILURE
- | PhoneStateListener.LISTEN_BARRING_INFO;
+ | PhoneStateListener.LISTEN_EMERGENCY_NUMBER_LIST;
- static final int PRECISE_PHONE_STATE_PERMISSION_MASK =
+ static final int ENFORCE_PRECISE_PHONE_STATE_PERMISSION_MASK =
PhoneStateListener.LISTEN_PRECISE_CALL_STATE
- | PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE
- | PhoneStateListener.LISTEN_CALL_DISCONNECT_CAUSES
- | PhoneStateListener.LISTEN_CALL_ATTRIBUTES_CHANGED
- | PhoneStateListener.LISTEN_IMS_CALL_DISCONNECT_CAUSES;
+ | PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE
+ | PhoneStateListener.LISTEN_CALL_DISCONNECT_CAUSES
+ | PhoneStateListener.LISTEN_CALL_ATTRIBUTES_CHANGED
+ | PhoneStateListener.LISTEN_IMS_CALL_DISCONNECT_CAUSES
+ | PhoneStateListener.LISTEN_REGISTRATION_FAILURE
+ | PhoneStateListener.LISTEN_BARRING_INFO;
static final int READ_ACTIVE_EMERGENCY_SESSION_PERMISSION_MASK =
PhoneStateListener.LISTEN_OUTGOING_EMERGENCY_CALL
@@ -2535,7 +2535,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
}
}
- if ((events & PRECISE_PHONE_STATE_PERMISSION_MASK) != 0) {
+ if ((events & ENFORCE_PRECISE_PHONE_STATE_PERMISSION_MASK) != 0) {
// check if calling app has either permission READ_PRECISE_PHONE_STATE
// or with carrier privileges
try {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 3ad96ea193bf..6bff76c15edd 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -466,18 +466,9 @@ public class ActivityManagerService extends IActivityManager.Stub
// How long we wait for a launched process to attach to the activity manager
// before we decide it's never going to come up for real.
static final int PROC_START_TIMEOUT = 10*1000;
- // How long we wait for an attached process to publish its content providers
- // before we decide it must be hung.
- static final int CONTENT_PROVIDER_PUBLISH_TIMEOUT = 10*1000;
-
// How long we wait to kill an application zygote, after the last process using
// it has gone away.
static final int KILL_APP_ZYGOTE_DELAY_MS = 5 * 1000;
- /**
- * How long we wait for an provider to be published. Should be longer than
- * {@link #CONTENT_PROVIDER_PUBLISH_TIMEOUT}.
- */
- static final int CONTENT_PROVIDER_WAIT_TIMEOUT = 20 * 1000;
// How long we wait for a launched process to attach to the activity manager
// before we decide it's never going to come up for real, when the process was
@@ -4934,7 +4925,8 @@ public class ActivityManagerService extends IActivityManager.Stub
if (providers != null && checkAppInLaunchingProvidersLocked(app)) {
Message msg = mHandler.obtainMessage(CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG);
msg.obj = app;
- mHandler.sendMessageDelayed(msg, CONTENT_PROVIDER_PUBLISH_TIMEOUT);
+ mHandler.sendMessageDelayed(msg,
+ ContentResolver.CONTENT_PROVIDER_PUBLISH_TIMEOUT_MILLIS);
}
checkTime(startTime, "attachApplicationLocked: before bindApplication");
@@ -7201,7 +7193,8 @@ public class ActivityManagerService extends IActivityManager.Stub
}
// Wait for the provider to be published...
- final long timeout = SystemClock.uptimeMillis() + CONTENT_PROVIDER_WAIT_TIMEOUT;
+ final long timeout =
+ SystemClock.uptimeMillis() + ContentResolver.CONTENT_PROVIDER_WAIT_TIMEOUT_MILLIS;
boolean timedOut = false;
synchronized (cpr) {
while (cpr.provider == null) {
@@ -7238,12 +7231,14 @@ public class ActivityManagerService extends IActivityManager.Stub
}
}
if (timedOut) {
- // Note we do it afer releasing the lock.
+ // Note we do it after releasing the lock.
String callerName = "unknown";
- synchronized (this) {
- final ProcessRecord record = mProcessList.getLRURecordForAppLocked(caller);
- if (record != null) {
- callerName = record.processName;
+ if (caller != null) {
+ synchronized (this) {
+ final ProcessRecord record = mProcessList.getLRURecordForAppLocked(caller);
+ if (record != null) {
+ callerName = record.processName;
+ }
}
}
diff --git a/services/core/java/com/android/server/notification/NotificationHistoryDatabase.java b/services/core/java/com/android/server/notification/NotificationHistoryDatabase.java
index e8cb1632bdc3..061cbd8a1a40 100644
--- a/services/core/java/com/android/server/notification/NotificationHistoryDatabase.java
+++ b/services/core/java/com/android/server/notification/NotificationHistoryDatabase.java
@@ -170,6 +170,11 @@ public class NotificationHistoryDatabase {
mFileWriteHandler.post(rpr);
}
+ public void deleteNotificationHistoryItem(String pkg, long postedTime) {
+ RemoveNotificationRunnable rnr = new RemoveNotificationRunnable(pkg, postedTime);
+ mFileWriteHandler.post(rnr);
+ }
+
public void addNotification(final HistoricalNotification notification) {
synchronized (mLock) {
mBuffer.addNewNotificationToWrite(notification);
@@ -367,6 +372,49 @@ public class NotificationHistoryDatabase {
}
}
+ final class RemoveNotificationRunnable implements Runnable {
+ private String mPkg;
+ private long mPostedTime;
+ private NotificationHistory mNotificationHistory;
+
+ public RemoveNotificationRunnable(String pkg, long postedTime) {
+ mPkg = pkg;
+ mPostedTime = postedTime;
+ }
+
+ @VisibleForTesting
+ void setNotificationHistory(NotificationHistory nh) {
+ mNotificationHistory = nh;
+ }
+
+ @Override
+ public void run() {
+ if (DEBUG) Slog.d(TAG, "RemovePackageRunnable");
+ synchronized (mLock) {
+ // Remove from pending history
+ mBuffer.removeNotificationFromWrite(mPkg, mPostedTime);
+
+ Iterator<AtomicFile> historyFileItr = mHistoryFiles.iterator();
+ while (historyFileItr.hasNext()) {
+ final AtomicFile af = historyFileItr.next();
+ try {
+ NotificationHistory notificationHistory = mNotificationHistory != null
+ ? mNotificationHistory
+ : new NotificationHistory();
+ readLocked(af, notificationHistory,
+ new NotificationHistoryFilter.Builder().build());
+ if(notificationHistory.removeNotificationFromWrite(mPkg, mPostedTime)) {
+ writeLocked(af, notificationHistory);
+ }
+ } catch (Exception e) {
+ Slog.e(TAG, "Cannot clean up file on notification removal "
+ + af.getBaseFile().getName(), e);
+ }
+ }
+ }
+ }
+ }
+
public static final class NotificationHistoryFileAttrProvider implements
NotificationHistoryDatabase.FileAttrProvider {
final static String TAG = "NotifHistoryFileDate";
diff --git a/services/core/java/com/android/server/notification/NotificationHistoryManager.java b/services/core/java/com/android/server/notification/NotificationHistoryManager.java
index 41bc29f7a82e..9aab0fd912e8 100644
--- a/services/core/java/com/android/server/notification/NotificationHistoryManager.java
+++ b/services/core/java/com/android/server/notification/NotificationHistoryManager.java
@@ -130,7 +130,7 @@ public class NotificationHistoryManager {
}
}
- public void onPackageRemoved(int userId, String packageName) {
+ public void onPackageRemoved(@UserIdInt int userId, String packageName) {
synchronized (mLock) {
if (!mUserUnlockedStates.get(userId, false)) {
if (mHistoryEnabled.get(userId, false)) {
@@ -150,6 +150,22 @@ public class NotificationHistoryManager {
}
}
+ public void deleteNotificationHistoryItem(String pkg, int uid, long postedTime) {
+ synchronized (mLock) {
+ int userId = UserHandle.getUserId(uid);
+ final NotificationHistoryDatabase userHistory =
+ getUserHistoryAndInitializeIfNeededLocked(userId);
+ // TODO: it shouldn't be possible to delete a notification entry while the user is
+ // locked but we should handle it
+ if (userHistory == null) {
+ Slog.w(TAG, "Attempted to remove notif for locked/gone/disabled user "
+ + userId);
+ return;
+ }
+ userHistory.deleteNotificationHistoryItem(pkg, postedTime);
+ }
+ }
+
// TODO: wire this up to AMS when power button is long pressed
public void triggerWriteToDisk() {
synchronized (mLock) {
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index f07113591fa5..f8777d618776 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -2780,7 +2780,7 @@ public class NotificationManagerService extends SystemService {
if (!isSystemToast) {
int count = 0;
final int N = mToastQueue.size();
- for (int i=0; i<N; i++) {
+ for (int i = 0; i < N; i++) {
final ToastRecord r = mToastQueue.get(i);
if (r.pkg.equals(pkg)) {
count++;
@@ -2820,7 +2820,7 @@ public class NotificationManagerService extends SystemService {
if (pkg == null || token == null) {
Slog.e(TAG, "Not cancelling notification. pkg=" + pkg + " token=" + token);
- return ;
+ return;
}
synchronized (mToastQueue) {
@@ -2933,14 +2933,14 @@ public class NotificationManagerService extends SystemService {
/**
* Updates the enabled state for notifications for the given package (and uid).
- * Additionally, this method marks the app importance as locked by the user, which means
+ * Additionally, this method marks the app importance as locked by the user, which
+ * means
* that notifications from the app will <b>not</b> be considered for showing a
* blocking helper.
*
- * @param pkg package that owns the notifications to update
- * @param uid uid of the app providing notifications
+ * @param pkg package that owns the notifications to update
+ * @param uid uid of the app providing notifications
* @param enabled whether notifications should be enabled for the app
- *
* @see #setNotificationsEnabledForPackage(String, int, boolean)
*/
@Override
@@ -3031,6 +3031,12 @@ public class NotificationManagerService extends SystemService {
}
@Override
+ public void deleteNotificationHistoryItem(String pkg, int uid, long postedTime) {
+ checkCallerIsSystem();
+ mHistoryManager.deleteNotificationHistoryItem(pkg, uid, postedTime);
+ }
+
+ @Override
public int getPackageImportance(String pkg) {
checkCallerIsSystemOrSameApp(pkg);
return mPreferencesHelper.getImportance(pkg, Binder.getCallingUid());
@@ -9256,7 +9262,7 @@ public class NotificationManagerService extends SystemService {
}
BackgroundThread.getHandler().post(() -> {
- if (hasCompanionDevice(serviceInfo)) {
+ if (serviceInfo.isSystem || hasCompanionDevice(serviceInfo)) {
notifyNotificationChannelChanged(
serviceInfo, pkg, user, channel, modificationType);
}
@@ -9276,7 +9282,7 @@ public class NotificationManagerService extends SystemService {
}
BackgroundThread.getHandler().post(() -> {
- if (hasCompanionDevice(serviceInfo)) {
+ if (serviceInfo.isSystem || hasCompanionDevice(serviceInfo)) {
notifyNotificationChannelGroupChanged(
serviceInfo, pkg, user, group, modificationType);
}
diff --git a/services/core/java/com/android/server/pm/ApexManager.java b/services/core/java/com/android/server/pm/ApexManager.java
index 42bc464e943f..a440c62a5f3c 100644
--- a/services/core/java/com/android/server/pm/ApexManager.java
+++ b/services/core/java/com/android/server/pm/ApexManager.java
@@ -36,6 +36,7 @@ import android.content.pm.parsing.AndroidPackage;
import android.os.Environment;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.Trace;
import android.sysprop.ApexProperties;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -46,6 +47,7 @@ import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.BackgroundThread;
import com.android.internal.util.IndentingPrintWriter;
+import com.android.server.utils.TimingsTraceAndSlog;
import com.google.android.collect.Lists;
@@ -375,8 +377,11 @@ public abstract class ApexManager {
@Override
public List<ActiveApexInfo> getActiveApexInfos() {
+ final TimingsTraceAndSlog t = new TimingsTraceAndSlog(TAG + "Timing",
+ Trace.TRACE_TAG_APEX_MANAGER);
synchronized (mLock) {
if (mActiveApexInfosCache == null) {
+ t.traceBegin("getActiveApexInfos_noCache");
try {
mActiveApexInfosCache = new ArraySet<>();
final ApexInfo[] activePackages = mApexService.getActivePackages();
@@ -387,6 +392,7 @@ public abstract class ApexManager {
} catch (RemoteException e) {
Slog.e(TAG, "Unable to retrieve packages from apexservice", e);
}
+ t.traceEnd();
}
if (mActiveApexInfosCache != null) {
return new ArrayList<>(mActiveApexInfosCache);
diff --git a/services/core/java/com/android/server/pm/AppsFilter.java b/services/core/java/com/android/server/pm/AppsFilter.java
index 3ad120705eb3..8c13b5bf8519 100644
--- a/services/core/java/com/android/server/pm/AppsFilter.java
+++ b/services/core/java/com/android/server/pm/AppsFilter.java
@@ -34,6 +34,7 @@ import android.content.pm.parsing.ComponentParseUtils.ParsedIntentInfo;
import android.content.pm.parsing.ComponentParseUtils.ParsedProvider;
import android.content.pm.parsing.ComponentParseUtils.ParsedService;
import android.net.Uri;
+import android.os.Binder;
import android.os.Process;
import android.os.Trace;
import android.os.UserHandle;
@@ -171,11 +172,13 @@ public class AppsFilter {
@Override
public boolean packageIsEnabled(AndroidPackage pkg) {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "packageIsEnabled");
+ final long token = Binder.clearCallingIdentity();
try {
// TODO(b/135203078): Do not use toAppInfo
return mInjector.getCompatibility().isChangeEnabled(
PackageManager.FILTER_APPLICATION_QUERY, pkg.toAppInfoWithoutState());
} finally {
+ Binder.restoreCallingIdentity(token);
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
}
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index 3e64e9828c3e..0cd1c259dd9e 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -661,6 +661,23 @@ public class LauncherAppsService extends SystemService {
}
}
+ private void ensureStrictAccessShortcutsPermission(@NonNull String callingPackage) {
+ verifyCallingPackage(callingPackage);
+ if (!injectHasAccessShortcutsPermission(injectBinderCallingPid(),
+ injectBinderCallingUid())) {
+ throw new SecurityException("Caller can't access shortcut information");
+ }
+ }
+
+ /**
+ * Returns true if the caller has the "ACCESS_SHORTCUTS" permission.
+ */
+ @VisibleForTesting
+ boolean injectHasAccessShortcutsPermission(int callingPid, int callingUid) {
+ return mContext.checkPermission(android.Manifest.permission.ACCESS_SHORTCUTS,
+ callingPid, callingUid) == PackageManager.PERMISSION_GRANTED;
+ }
+
@Override
public ParceledListSlice getShortcuts(String callingPackage, long changedSince,
String packageName, List shortcutIds, List<LocusId> locusIds,
@@ -710,6 +727,30 @@ public class LauncherAppsService extends SystemService {
}
@Override
+ public void cacheShortcuts(String callingPackage, String packageName, List<String> ids,
+ UserHandle targetUser) {
+ ensureStrictAccessShortcutsPermission(callingPackage);
+ if (!canAccessProfile(targetUser.getIdentifier(), "Cannot cache shortcuts")) {
+ return;
+ }
+
+ mShortcutServiceInternal.cacheShortcuts(getCallingUserId(),
+ callingPackage, packageName, ids, targetUser.getIdentifier());
+ }
+
+ @Override
+ public void uncacheShortcuts(String callingPackage, String packageName, List<String> ids,
+ UserHandle targetUser) {
+ ensureStrictAccessShortcutsPermission(callingPackage);
+ if (!canAccessProfile(targetUser.getIdentifier(), "Cannot uncache shortcuts")) {
+ return;
+ }
+
+ mShortcutServiceInternal.uncacheShortcuts(getCallingUserId(),
+ callingPackage, packageName, ids, targetUser.getIdentifier());
+ }
+
+ @Override
public int getShortcutIconResId(String callingPackage, String packageName, String id,
int targetUserId) {
ensureShortcutPermission(callingPackage);
diff --git a/services/core/java/com/android/server/pm/PackageAbiHelperImpl.java b/services/core/java/com/android/server/pm/PackageAbiHelperImpl.java
index e550bae7484b..482fc4944691 100644
--- a/services/core/java/com/android/server/pm/PackageAbiHelperImpl.java
+++ b/services/core/java/com/android/server/pm/PackageAbiHelperImpl.java
@@ -344,18 +344,10 @@ final class PackageAbiHelperImpl implements PackageAbiHelper {
int abi64 = PackageManager.NO_NATIVE_LIBRARIES;
if (Build.SUPPORTED_32_BIT_ABIS.length > 0) {
if (extractLibs) {
- if (onIncremental) {
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER,
- "incrementalNativeBinaries");
- abi32 = NativeLibraryHelper.configureNativeBinariesForSupportedAbi(pkg,
- handle, nativeLibraryRoot, Build.SUPPORTED_32_BIT_ABIS,
- useIsaSpecificSubdirs);
- } else {
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "copyNativeBinaries");
- abi32 = NativeLibraryHelper.copyNativeBinariesForSupportedAbi(handle,
- nativeLibraryRoot, Build.SUPPORTED_32_BIT_ABIS,
- useIsaSpecificSubdirs);
- }
+ Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "copyNativeBinaries");
+ abi32 = NativeLibraryHelper.copyNativeBinariesForSupportedAbi(handle,
+ nativeLibraryRoot, Build.SUPPORTED_32_BIT_ABIS,
+ useIsaSpecificSubdirs, onIncremental);
} else {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "findSupportedAbi");
abi32 = NativeLibraryHelper.findSupportedAbi(
@@ -375,18 +367,10 @@ final class PackageAbiHelperImpl implements PackageAbiHelper {
if (Build.SUPPORTED_64_BIT_ABIS.length > 0) {
if (extractLibs) {
- if (onIncremental) {
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER,
- "incrementalNativeBinaries");
- abi64 = NativeLibraryHelper.configureNativeBinariesForSupportedAbi(pkg,
- handle, nativeLibraryRoot, Build.SUPPORTED_64_BIT_ABIS,
- useIsaSpecificSubdirs);
- } else {
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "copyNativeBinaries");
- abi64 = NativeLibraryHelper.copyNativeBinariesForSupportedAbi(handle,
- nativeLibraryRoot, Build.SUPPORTED_64_BIT_ABIS,
- useIsaSpecificSubdirs);
- }
+ Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "copyNativeBinaries");
+ abi64 = NativeLibraryHelper.copyNativeBinariesForSupportedAbi(handle,
+ nativeLibraryRoot, Build.SUPPORTED_64_BIT_ABIS,
+ useIsaSpecificSubdirs, onIncremental);
} else {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "findSupportedAbi");
abi64 = NativeLibraryHelper.findSupportedAbi(
@@ -437,15 +421,9 @@ final class PackageAbiHelperImpl implements PackageAbiHelper {
final int copyRet;
if (extractLibs) {
- if (onIncremental) {
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "incrementalNativeBinaries");
- copyRet = NativeLibraryHelper.configureNativeBinariesForSupportedAbi(pkg,
- handle, nativeLibraryRoot, abiList, useIsaSpecificSubdirs);
- } else {
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "copyNativeBinaries");
- copyRet = NativeLibraryHelper.copyNativeBinariesForSupportedAbi(handle,
- nativeLibraryRoot, abiList, useIsaSpecificSubdirs);
- }
+ Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "copyNativeBinaries");
+ copyRet = NativeLibraryHelper.copyNativeBinariesForSupportedAbi(handle,
+ nativeLibraryRoot, abiList, useIsaSpecificSubdirs, onIncremental);
} else {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "findSupportedAbi");
copyRet = NativeLibraryHelper.findSupportedAbi(handle, abiList);
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 0cf8b424b84d..944280d6db88 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -1681,10 +1681,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
mInternalProgress = 0.5f;
computeProgressLocked(true);
- // Unpack native libraries for non-incremental installation
- if (!isIncrementalInstallation()) {
- extractNativeLibraries(stageDir, params.abiOverride, mayInheritNativeLibs());
- }
+ extractNativeLibraries(stageDir, params.abiOverride, mayInheritNativeLibs());
}
// We've reached point of no return; call into PMS to install the stage.
@@ -2260,7 +2257,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
Slog.d(TAG, "Copied " + fromFiles.size() + " files into " + toDir);
}
- private static void extractNativeLibraries(File packageDir, String abiOverride, boolean inherit)
+ private void extractNativeLibraries(File packageDir, String abiOverride, boolean inherit)
throws PackageManagerException {
final File libDir = new File(packageDir, NativeLibraryHelper.LIB_DIR_NAME);
if (!inherit) {
@@ -2272,7 +2269,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
try {
handle = NativeLibraryHelper.Handle.create(packageDir);
final int res = NativeLibraryHelper.copyNativeBinariesWithOverride(handle, libDir,
- abiOverride);
+ abiOverride, isIncrementalInstallation());
if (res != PackageManager.INSTALL_SUCCEEDED) {
throw new PackageManagerException(res,
"Failed to extract native libraries, res=" + res);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 42b24839a36b..88c048cea267 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -3627,7 +3627,7 @@ public class PackageManagerService extends IPackageManager.Stub
try {
handle = NativeLibraryHelper.Handle.create(dstCodePath);
ret = NativeLibraryHelper.copyNativeBinariesWithOverride(handle, libraryRoot,
- null /*abiOverride*/);
+ null /*abiOverride*/, false /*isIncremental*/);
} catch (IOException e) {
logCriticalInfo(Log.ERROR, "Failed to extract native libraries"
+ "; pkg: " + packageName);
@@ -14970,12 +14970,13 @@ public class PackageManagerService extends IPackageManager.Stub
return ret;
}
+ final boolean isIncremental = isIncrementalPath(codeFile.getAbsolutePath());
final File libraryRoot = new File(codeFile, LIB_DIR_NAME);
NativeLibraryHelper.Handle handle = null;
try {
handle = NativeLibraryHelper.Handle.create(codeFile);
ret = NativeLibraryHelper.copyNativeBinariesWithOverride(handle, libraryRoot,
- abiOverride);
+ abiOverride, isIncremental);
} catch (IOException e) {
Slog.e(TAG, "Copying native libraries failed", e);
ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index d16c0748ef0e..377fd16d4e19 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -1704,7 +1704,7 @@ public class ShortcutService extends IShortcutService.Stub {
ShortcutInfo.validateIcon(shortcut.getIcon());
}
- shortcut.replaceFlags(0);
+ shortcut.replaceFlags(shortcut.getFlags() & ShortcutInfo.FLAG_LONG_LIVED);
}
private void fixUpIncomingShortcutInfo(@NonNull ShortcutInfo shortcut, boolean forUpdate) {
@@ -2758,6 +2758,68 @@ public class ShortcutService extends IShortcutService.Stub {
}
@Override
+ public void cacheShortcuts(int launcherUserId,
+ @NonNull String callingPackage, @NonNull String packageName,
+ @NonNull List<String> shortcutIds, int userId) {
+ updateCachedShortcutsInternal(launcherUserId, callingPackage, packageName, shortcutIds,
+ userId, /* doCache= */ true);
+ }
+
+ @Override
+ public void uncacheShortcuts(int launcherUserId,
+ @NonNull String callingPackage, @NonNull String packageName,
+ @NonNull List<String> shortcutIds, int userId) {
+ updateCachedShortcutsInternal(launcherUserId, callingPackage, packageName, shortcutIds,
+ userId, /* doCache= */ false);
+ }
+
+ private void updateCachedShortcutsInternal(int launcherUserId,
+ @NonNull String callingPackage, @NonNull String packageName,
+ @NonNull List<String> shortcutIds, int userId, boolean doCache) {
+ // Calling permission must be checked by LauncherAppsImpl.
+ Preconditions.checkStringNotEmpty(packageName, "packageName");
+ Objects.requireNonNull(shortcutIds, "shortcutIds");
+
+ synchronized (mLock) {
+ throwIfUserLockedL(userId);
+ throwIfUserLockedL(launcherUserId);
+
+ final int idSize = shortcutIds.size();
+ final ShortcutPackage sp = getUserShortcutsLocked(userId)
+ .getPackageShortcutsIfExists(packageName);
+ if (idSize == 0 || sp == null) {
+ return;
+ }
+
+ for (int i = 0; i < idSize; i++) {
+ final String id = Preconditions.checkStringNotEmpty(shortcutIds.get(i));
+ final ShortcutInfo si = sp.findShortcutById(id);
+ if (si == null || doCache == si.isCached()) {
+ continue;
+ }
+
+ if (doCache) {
+ if (si.isDynamic() && si.isLongLived()) {
+ si.addFlags(ShortcutInfo.FLAG_CACHED);
+ } else {
+ Log.w(TAG, "Only dynamic long lived shortcuts can get cached. Ignoring"
+ + "shortcut " + si.getId());
+ }
+ } else {
+ if (si.isDynamic()) {
+ si.clearFlags(ShortcutInfo.FLAG_CACHED);
+ } else {
+ sp.deleteLongLivedWithId(id, /*ignoreInvisible=*/ true);
+ }
+ }
+ }
+ }
+ packageShortcutsChanged(packageName, userId);
+
+ verifyStates();
+ }
+
+ @Override
public Intent[] createShortcutIntents(int launcherUserId,
@NonNull String callingPackage,
@NonNull String packageName, @NonNull String shortcutId, int userId,
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 0cb8f49540be..1c02161c5b96 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -1901,7 +1901,7 @@ public class UserManagerService extends IUserManager.Stub {
@Override
public boolean hasBaseUserRestriction(String restrictionKey, @UserIdInt int userId) {
- checkManageUsersPermission("hasBaseUserRestriction");
+ checkManageOrCreateUsersPermission("hasBaseUserRestriction");
if (!UserRestrictionsUtils.isValidRestriction(restrictionKey)) {
return false;
}
diff --git a/services/core/java/com/android/server/policy/PermissionPolicyService.java b/services/core/java/com/android/server/policy/PermissionPolicyService.java
index 2c7795a6274b..43d45967f67b 100644
--- a/services/core/java/com/android/server/policy/PermissionPolicyService.java
+++ b/services/core/java/com/android/server/policy/PermissionPolicyService.java
@@ -39,9 +39,7 @@ import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.PackageManagerInternal;
import android.content.pm.PackageManagerInternal.PackageListObserver;
import android.content.pm.PermissionInfo;
-import android.content.pm.parsing.AndroidPackage;
import android.os.Build;
-import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
@@ -52,14 +50,15 @@ import android.telecom.TelecomManager;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.LongSparseLongArray;
-import android.util.Pair;
import android.util.Slog;
+import android.util.SparseArray;
import android.util.SparseBooleanArray;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.IAppOpsCallback;
import com.android.internal.app.IAppOpsService;
import com.android.internal.infra.AndroidFuture;
+import com.android.internal.util.ArrayUtils;
import com.android.internal.util.IntPair;
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.FgThread;
@@ -70,6 +69,7 @@ import com.android.server.policy.PermissionPolicyInternal.OnInitializedCallback;
import java.util.ArrayList;
import java.util.List;
+import java.util.Objects;
import java.util.concurrent.ExecutionException;
/**
@@ -100,7 +100,7 @@ public final class PermissionPolicyService extends SystemService {
* scheduled for a package/user.
*/
@GuardedBy("mLock")
- private final ArraySet<Pair<String, Integer>> mIsPackageSyncsScheduled = new ArraySet<>();
+ private final ArraySet<Integer> mIsPackageSyncsScheduled = new ArraySet<>();
public PermissionPolicyService(@NonNull Context context) {
super(context);
@@ -125,10 +125,8 @@ public final class PermissionPolicyService extends SystemService {
@Override
public void onPackageChanged(String packageName, int uid) {
- final int userId = UserHandle.getUserId(uid);
-
- if (isStarted(userId)) {
- synchronizePackagePermissionsAndAppOpsForUser(packageName, userId);
+ if (isStarted(UserHandle.getUserId(uid))) {
+ synchronizePackagePermissionsAndAppOpsForUser(uid);
}
}
@@ -139,12 +137,21 @@ public final class PermissionPolicyService extends SystemService {
});
permManagerInternal.addOnRuntimePermissionStateChangedListener(
- this::synchronizePackagePermissionsAndAppOpsAsyncForUser);
+ (packageName, userId) -> {
+ int uid;
+ try {
+ uid = getContext().getPackageManager().getPackageUidAsUser(packageName, 0,
+ userId);
+ } catch (NameNotFoundException e) {
+ Slog.e(LOG_TAG, "Cannot synchronize changed package " + packageName, e);
+ return;
+ }
+ synchronizeUidPermissionsAndAppOpsAsync(uid);
+ });
mAppOpsCallback = new IAppOpsCallback.Stub() {
public void opChanged(int op, int uid, String packageName) {
- synchronizePackagePermissionsAndAppOpsAsyncForUser(packageName,
- UserHandle.getUserId(uid));
+ synchronizeUidPermissionsAndAppOpsAsync(uid);
}
};
@@ -194,19 +201,17 @@ public final class PermissionPolicyService extends SystemService {
return AppOpsManager.opToSwitch(op);
}
- private void synchronizePackagePermissionsAndAppOpsAsyncForUser(@NonNull String packageName,
- @UserIdInt int changedUserId) {
- if (isStarted(changedUserId)) {
+ private void synchronizeUidPermissionsAndAppOpsAsync(int uid) {
+ if (isStarted(UserHandle.getUserId(uid))) {
synchronized (mLock) {
- if (mIsPackageSyncsScheduled.add(new Pair<>(packageName, changedUserId))) {
+ if (mIsPackageSyncsScheduled.add(uid)) {
FgThread.getHandler().sendMessage(PooledLambda.obtainMessage(
PermissionPolicyService
::synchronizePackagePermissionsAndAppOpsForUser,
- this, packageName, changedUserId));
+ this, uid));
} else {
if (DEBUG) {
- Slog.v(LOG_TAG, "sync for " + packageName + "/" + changedUserId
- + " already scheduled");
+ Slog.v(LOG_TAG, "sync for " + uid + " already scheduled");
}
}
}
@@ -335,39 +340,20 @@ public final class PermissionPolicyService extends SystemService {
/**
* Synchronize a single package.
*/
- private void synchronizePackagePermissionsAndAppOpsForUser(@NonNull String packageName,
- @UserIdInt int userId) {
+ private void synchronizePackagePermissionsAndAppOpsForUser(int uid) {
synchronized (mLock) {
- mIsPackageSyncsScheduled.remove(new Pair<>(packageName, userId));
+ mIsPackageSyncsScheduled.remove(uid);
}
if (DEBUG) {
Slog.v(LOG_TAG,
- "synchronizePackagePermissionsAndAppOpsForUser(" + packageName + ", "
- + userId + ")");
+ "synchronizePackagePermissionsAndAppOpsForUser(" + uid + ")");
}
- final PackageManagerInternal packageManagerInternal = LocalServices.getService(
- PackageManagerInternal.class);
- final PackageInfo pkg = packageManagerInternal.getPackageInfo(packageName, 0,
- Process.SYSTEM_UID, userId);
- if (pkg == null) {
- return;
- }
final PermissionToOpSynchroniser synchroniser = new PermissionToOpSynchroniser(
- getUserContext(getContext(), UserHandle.of(userId)));
- synchroniser.addPackage(pkg.packageName);
- final String[] sharedPkgNames = packageManagerInternal.getSharedUserPackagesForPackage(
- pkg.packageName, userId);
-
- for (String sharedPkgName : sharedPkgNames) {
- final AndroidPackage sharedPkg = packageManagerInternal
- .getPackage(sharedPkgName);
- if (sharedPkg != null) {
- synchroniser.addPackage(sharedPkg.getPackageName());
- }
- }
- synchroniser.syncPackages();
+ getUserContext(getContext(), UserHandle.getUserHandleForUid(uid)));
+ synchroniser.addUid(uid);
+ synchroniser.syncUids();
}
/**
@@ -381,8 +367,8 @@ public final class PermissionPolicyService extends SystemService {
final PermissionToOpSynchroniser synchronizer = new PermissionToOpSynchroniser(
getUserContext(getContext(), UserHandle.of(userId)));
packageManagerInternal.forEachPackage(
- (pkg) -> synchronizer.addPackage(pkg.getPackageName()));
- synchronizer.syncPackages();
+ (pkg) -> synchronizer.addUid(pkg.getUid()));
+ synchronizer.syncUids();
}
/**
@@ -397,37 +383,51 @@ public final class PermissionPolicyService extends SystemService {
private final @NonNull ArrayMap<String, PermissionInfo> mRuntimePermissionInfos;
+ // Cache uid -> packageNames
+ private SparseArray<String[]> mUidToPkg = new SparseArray<>();
+
/**
* All ops that need to be flipped to allow.
*
- * @see #syncPackages
+ * @see #syncUids
*/
- private final @NonNull ArrayList<OpToChange> mOpsToAllow = new ArrayList<>();
+ private final @NonNull ArraySet<OpToChange> mOpsToAllow = new ArraySet<>();
/**
* All ops that need to be flipped to ignore.
*
- * @see #syncPackages
+ * @see #syncUids
*/
- private final @NonNull ArrayList<OpToChange> mOpsToIgnore = new ArrayList<>();
+ private final @NonNull ArraySet<OpToChange> mOpsToIgnore = new ArraySet<>();
/**
* All ops that need to be flipped to ignore if not allowed.
*
* Currently, only used by soft restricted permissions logic.
*
- * @see #syncPackages
+ * @see #syncUids
*/
- private final @NonNull ArrayList<OpToChange> mOpsToIgnoreIfNotAllowed = new ArrayList<>();
+ private final @NonNull ArraySet<OpToChange> mOpsToIgnoreIfNotAllowed = new ArraySet<>();
/**
* All ops that need to be flipped to foreground.
*
* Currently, only used by the foreground/background permissions logic.
*
- * @see #syncPackages
+ * @see #syncUids
*/
- private final @NonNull ArrayList<OpToChange> mOpsToForeground = new ArrayList<>();
+ private final @NonNull ArraySet<OpToChange> mOpsToForeground = new ArraySet<>();
+
+ private @Nullable String[] getPackageNamesForUid(int uid) {
+ String[] pkgs = mUidToPkg.get(uid);
+ if (pkgs != null) {
+ return pkgs;
+ }
+
+ pkgs = mPackageManager.getPackagesForUid(uid);
+ mUidToPkg.put(uid, pkgs);
+ return pkgs;
+ }
PermissionToOpSynchroniser(@NonNull Context context) {
mContext = context;
@@ -449,11 +449,11 @@ public final class PermissionPolicyService extends SystemService {
}
/**
- * Set app ops that were added in {@link #addPackage}.
+ * Set app ops that were added in {@link #addUid}.
*
* <p>This processes ops previously added by {@link #addAppOps(PackageInfo, String)}
*/
- private void syncPackages() {
+ private void syncUids() {
// Remember which ops were already set. This makes sure that we always set the most
// permissive mode if two OpChanges are scheduled. This can e.g. happen if two
// permissions change the same op. See {@link #getSwitchOp}.
@@ -461,42 +461,42 @@ public final class PermissionPolicyService extends SystemService {
final int allowCount = mOpsToAllow.size();
for (int i = 0; i < allowCount; i++) {
- final OpToChange op = mOpsToAllow.get(i);
+ final OpToChange op = mOpsToAllow.valueAt(i);
- setUidModeAllowed(op.code, op.uid, op.packageName);
+ setUidModeAllowed(op.code, op.uid);
alreadySetAppOps.put(IntPair.of(op.uid, op.code), 1);
}
final int foregroundCount = mOpsToForeground.size();
for (int i = 0; i < foregroundCount; i++) {
- final OpToChange op = mOpsToForeground.get(i);
+ final OpToChange op = mOpsToForeground.valueAt(i);
if (alreadySetAppOps.indexOfKey(IntPair.of(op.uid, op.code)) >= 0) {
continue;
}
- setUidModeForeground(op.code, op.uid, op.packageName);
+ setUidModeForeground(op.code, op.uid);
alreadySetAppOps.put(IntPair.of(op.uid, op.code), 1);
}
final int ignoreCount = mOpsToIgnore.size();
for (int i = 0; i < ignoreCount; i++) {
- final OpToChange op = mOpsToIgnore.get(i);
+ final OpToChange op = mOpsToIgnore.valueAt(i);
if (alreadySetAppOps.indexOfKey(IntPair.of(op.uid, op.code)) >= 0) {
continue;
}
- setUidModeIgnored(op.code, op.uid, op.packageName);
+ setUidModeIgnored(op.code, op.uid);
alreadySetAppOps.put(IntPair.of(op.uid, op.code), 1);
}
final int ignoreIfNotAllowedCount = mOpsToIgnoreIfNotAllowed.size();
for (int i = 0; i < ignoreIfNotAllowedCount; i++) {
- final OpToChange op = mOpsToIgnoreIfNotAllowed.get(i);
+ final OpToChange op = mOpsToIgnoreIfNotAllowed.valueAt(i);
if (alreadySetAppOps.indexOfKey(IntPair.of(op.uid, op.code)) >= 0) {
continue;
}
- boolean wasSet = setUidModeIgnoredIfNotAllowed(op.code, op.uid, op.packageName);
+ boolean wasSet = setUidModeIgnoredIfNotAllowed(op.code, op.uid);
if (wasSet) {
alreadySetAppOps.put(IntPair.of(op.uid, op.code), 1);
}
@@ -555,7 +555,7 @@ public final class PermissionPolicyService extends SystemService {
}
int uid = packageInfo.applicationInfo.uid;
- OpToChange opToChange = new OpToChange(uid, packageName, appOpCode);
+ OpToChange opToChange = new OpToChange(uid, appOpCode);
switch (appOpMode) {
case MODE_ALLOWED:
mOpsToAllow.add(opToChange);
@@ -618,8 +618,7 @@ public final class PermissionPolicyService extends SystemService {
}
int uid = packageInfo.applicationInfo.uid;
- String packageName = packageInfo.packageName;
- OpToChange extraOpToChange = new OpToChange(uid, packageName, extraOpCode);
+ OpToChange extraOpToChange = new OpToChange(uid, extraOpCode);
if (policy.mayAllowExtraAppOp()) {
mOpsToAllow.add(extraOpToChange);
} else {
@@ -632,45 +631,56 @@ public final class PermissionPolicyService extends SystemService {
}
/**
- * Add a package for {@link #syncPackages() processing} later.
+ * Add a Uid for {@link #syncUids() processing} later.
*
* <p>Note: Called with the package lock held. Do <u>not</u> call into app-op manager.
*
- * @param pkgName The package to add for later processing.
+ * @param uid The uid to add for later processing.
*/
- void addPackage(@NonNull String pkgName) {
- final PackageInfo pkg;
- try {
- pkg = mPackageManager.getPackageInfo(pkgName, GET_PERMISSIONS);
- } catch (NameNotFoundException e) {
+ void addUid(int uid) {
+ String[] pkgNames = getPackageNamesForUid(uid);
+ if (pkgNames == null) {
return;
}
- if (pkg.requestedPermissions == null) {
- return;
- }
+ for (String pkgName : pkgNames) {
+ final PackageInfo pkg;
+ try {
+ pkg = mPackageManager.getPackageInfo(pkgName, GET_PERMISSIONS);
+ } catch (NameNotFoundException e) {
+ continue;
+ }
+
+ if (pkg.requestedPermissions == null) {
+ continue;
+ }
- for (String permission : pkg.requestedPermissions) {
- addAppOps(pkg, permission);
+ for (String permission : pkg.requestedPermissions) {
+ addAppOps(pkg, permission);
+ }
}
}
- private void setUidModeAllowed(int opCode, int uid, @NonNull String packageName) {
- setUidMode(opCode, uid, MODE_ALLOWED, packageName);
+ private void setUidModeAllowed(int opCode, int uid) {
+ setUidMode(opCode, uid, MODE_ALLOWED);
}
- private void setUidModeForeground(int opCode, int uid, @NonNull String packageName) {
- setUidMode(opCode, uid, MODE_FOREGROUND, packageName);
+ private void setUidModeForeground(int opCode, int uid) {
+ setUidMode(opCode, uid, MODE_FOREGROUND);
}
- private void setUidModeIgnored(int opCode, int uid, @NonNull String packageName) {
- setUidMode(opCode, uid, MODE_IGNORED, packageName);
+ private void setUidModeIgnored(int opCode, int uid) {
+ setUidMode(opCode, uid, MODE_IGNORED);
}
- private boolean setUidModeIgnoredIfNotAllowed(int opCode, int uid,
- @NonNull String packageName) {
+ private boolean setUidModeIgnoredIfNotAllowed(int opCode, int uid) {
+ String[] pkgsOfUid = getPackageNamesForUid(uid);
+ if (ArrayUtils.isEmpty(pkgsOfUid)) {
+ return false;
+ }
+
final int currentMode = mAppOpsManager.unsafeCheckOpRaw(AppOpsManager.opToPublicName(
- opCode), uid, packageName);
+ opCode), uid, pkgsOfUid[0]);
if (currentMode != MODE_ALLOWED) {
if (currentMode != MODE_IGNORED) {
mAppOpsManagerInternal.setUidModeIgnoringCallback(opCode, uid, MODE_IGNORED,
@@ -681,20 +691,24 @@ public final class PermissionPolicyService extends SystemService {
return false;
}
- private void setUidMode(int opCode, int uid, int mode,
- @NonNull String packageName) {
+ private void setUidMode(int opCode, int uid, int mode) {
+ String[] pkgsOfUid = getPackageNamesForUid(uid);
+ if (ArrayUtils.isEmpty(pkgsOfUid)) {
+ return;
+ }
+
final int oldMode = mAppOpsManager.unsafeCheckOpRaw(AppOpsManager.opToPublicName(
- opCode), uid, packageName);
+ opCode), uid, pkgsOfUid[0]);
if (oldMode != mode) {
mAppOpsManagerInternal.setUidModeIgnoringCallback(opCode, uid, mode,
mAppOpsCallback);
final int newMode = mAppOpsManager.unsafeCheckOpRaw(AppOpsManager.opToPublicName(
- opCode), uid, packageName);
+ opCode), uid, pkgsOfUid[0]);
if (newMode != mode) {
// Work around incorrectly-set package mode. It never makes sense for app ops
// related to runtime permissions, but can get in the way and we have to reset
// it.
- mAppOpsManagerInternal.setModeIgnoringCallback(opCode, uid, packageName,
+ mAppOpsManagerInternal.setModeIgnoringCallback(opCode, uid, pkgsOfUid[0],
AppOpsManager.opToDefaultMode(opCode), mAppOpsCallback);
}
}
@@ -702,14 +716,30 @@ public final class PermissionPolicyService extends SystemService {
private class OpToChange {
final int uid;
- final @NonNull String packageName;
final int code;
- OpToChange(int uid, @NonNull String packageName, int code) {
+ OpToChange(int uid, int code) {
this.uid = uid;
- this.packageName = packageName;
this.code = code;
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ OpToChange other = (OpToChange) o;
+ return uid == other.uid && code == other.code;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(uid, code);
+ }
}
}
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 87c91ef6b96c..b1db9d7889dd 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -79,11 +79,6 @@ import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLAS
import static com.android.server.wm.ActivityTaskManagerService.TAG_STACK;
import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER;
import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
-import static com.android.server.wm.TaskProto.DISPLAYED_BOUNDS;
-import static com.android.server.wm.TaskProto.FILLS_PARENT;
-import static com.android.server.wm.TaskProto.SURFACE_HEIGHT;
-import static com.android.server.wm.TaskProto.SURFACE_WIDTH;
-import static com.android.server.wm.TaskProto.WINDOW_CONTAINER;
import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN;
import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
@@ -125,7 +120,6 @@ import android.provider.Settings;
import android.service.voice.IVoiceInteractionSession;
import android.util.DisplayMetrics;
import android.util.Slog;
-import android.util.proto.ProtoOutputStream;
import android.view.DisplayInfo;
import android.view.ITaskOrganizer;
import android.view.RemoteAnimationTarget;
@@ -3195,12 +3189,16 @@ class Task extends WindowContainer<WindowContainer> {
info.lastActiveTime = lastActiveTime;
info.taskDescription = new ActivityManager.TaskDescription(getTaskDescription());
info.supportsSplitScreenMultiWindow = supportsSplitScreenWindowingMode();
- info.resizeMode = mResizeMode;
info.configuration.setTo(getConfiguration());
info.token = mRemoteToken;
// Get's the first non-undefined activity type among this and children. Can't use
// configuration.windowConfiguration because that would only be this level.
info.topActivityType = getActivityType();
+
+ //TODO (AM refactor): Just use local once updateEffectiveIntent is run during all child
+ // order changes.
+ final Task top = getTopMostTask();
+ info.resizeMode = top != null ? top.mResizeMode : mResizeMode;
}
/**
diff --git a/services/core/java/com/android/server/wm/TaskOrganizerController.java b/services/core/java/com/android/server/wm/TaskOrganizerController.java
index 096541f57ba5..0a0530c92a16 100644
--- a/services/core/java/com/android/server/wm/TaskOrganizerController.java
+++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java
@@ -23,6 +23,8 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMAR
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS;
+import static com.android.server.wm.WindowContainer.POSITION_BOTTOM;
+import static com.android.server.wm.WindowContainer.POSITION_TOP;
import android.annotation.Nullable;
import android.app.ActivityManager.RunningTaskInfo;
@@ -47,6 +49,7 @@ import com.android.internal.util.function.pooled.PooledLambda;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
+import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;
@@ -375,6 +378,45 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub
}
}
+ @Override
+ public List<RunningTaskInfo> getChildTasks(IWindowContainer parent) {
+ enforceStackPermission("getChildTasks()");
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ synchronized (mGlobalLock) {
+ if (parent == null) {
+ throw new IllegalArgumentException("Can't get children of null parent");
+ }
+ final WindowContainer container = WindowContainer.fromBinder(parent.asBinder());
+ if (container == null) {
+ Slog.e(TAG, "Can't get children of " + parent + " because it is not valid.");
+ return null;
+ }
+ // For now, only support returning children of persistent root tasks (of which the
+ // only current implementation is TaskTile).
+ if (!(container instanceof TaskTile)) {
+ Slog.w(TAG, "Can only get children of root tasks created via createRootTask");
+ return null;
+ }
+ ArrayList<RunningTaskInfo> out = new ArrayList<>();
+ // Tiles aren't real parents, so we need to go through stacks on the display to
+ // ensure correct ordering.
+ final DisplayContent dc = container.getDisplayContent();
+ for (int i = dc.getStackCount() - 1; i >= 0; --i) {
+ final ActivityStack as = dc.getStackAt(i);
+ if (as.getTile() == container) {
+ final RunningTaskInfo info = new RunningTaskInfo();
+ as.fillTaskInfo(info);
+ out.add(info);
+ }
+ }
+ return out;
+ }
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
private int sanitizeAndApplyChange(WindowContainer container,
WindowContainerTransaction.Change change) {
if (!(container instanceof Task)) {
@@ -405,6 +447,54 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub
return effects;
}
+ private int sanitizeAndApplyHierarchyOp(WindowContainer container,
+ WindowContainerTransaction.HierarchyOp hop) {
+ if (!(container instanceof Task)) {
+ throw new IllegalArgumentException("Invalid container in hierarchy op");
+ }
+ if (hop.isReparent()) {
+ // special case for tiles since they are "virtual" parents
+ if (container instanceof ActivityStack && ((ActivityStack) container).isRootTask()) {
+ ActivityStack as = (ActivityStack) container;
+ TaskTile newParent = hop.getNewParent() == null ? null
+ : (TaskTile) WindowContainer.fromBinder(hop.getNewParent());
+ if (as.getTile() != newParent) {
+ if (as.getTile() != null) {
+ as.getTile().removeChild(as);
+ }
+ if (newParent != null) {
+ if (!as.affectedBySplitScreenResize()) {
+ return 0;
+ }
+ newParent.addChild(as, POSITION_TOP);
+ }
+ }
+ if (hop.getToTop()) {
+ as.getDisplay().positionStackAtTop(as, false /* includingParents */);
+ } else {
+ as.getDisplay().positionStackAtBottom(as);
+ }
+ } else if (container instanceof Task) {
+ throw new RuntimeException("Reparenting leaf Tasks is not supported now.");
+ }
+ } else {
+ // Ugh, of course ActivityStack has its own special reorder logic...
+ if (container instanceof ActivityStack && ((ActivityStack) container).isRootTask()) {
+ ActivityStack as = (ActivityStack) container;
+ if (hop.getToTop()) {
+ as.getDisplay().positionStackAtTop(as, false /* includingParents */);
+ } else {
+ as.getDisplay().positionStackAtBottom(as);
+ }
+ } else {
+ container.getParent().positionChildAt(
+ hop.getToTop() ? POSITION_TOP : POSITION_BOTTOM,
+ container, false /* includingParents */);
+ }
+ }
+ return TRANSACT_EFFECTS_LIFECYCLE;
+ }
+
private void resizePinnedStackIfNeeded(ConfigurationContainer container, int configMask,
int windowMask, Configuration config) {
if ((container instanceof ActivityStack)
@@ -470,8 +560,7 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub
while (entries.hasNext()) {
final Map.Entry<IBinder, WindowContainerTransaction.Change> entry =
entries.next();
- final WindowContainer wc = WindowContainer.RemoteToken.fromBinder(
- entry.getKey()).getContainer();
+ final WindowContainer wc = WindowContainer.fromBinder(entry.getKey());
int containerEffect = applyWindowContainerChange(wc, entry.getValue());
effects |= containerEffect;
@@ -484,6 +573,13 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub
mBLASTSyncEngine.addToSyncSet(syncId, wc);
}
}
+ // Hierarchy changes
+ final List<WindowContainerTransaction.HierarchyOp> hops = t.getHierarchyOps();
+ for (int i = 0, n = hops.size(); i < n; ++i) {
+ final WindowContainerTransaction.HierarchyOp hop = hops.get(i);
+ final WindowContainer wc = WindowContainer.fromBinder(hop.getContainer());
+ effects |= sanitizeAndApplyHierarchyOp(wc, hop);
+ }
if ((effects & TRANSACT_EFFECTS_LIFECYCLE) != 0) {
// Already calls ensureActivityConfig
mService.mRootWindowContainer.ensureActivitiesVisible(
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 9acb660967cb..504aa2dc7b4c 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -2296,6 +2296,10 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
return mRemoteToken;
}
+ static WindowContainer fromBinder(IBinder binder) {
+ return RemoteToken.fromBinder(binder).getContainer();
+ }
+
static class RemoteToken extends IWindowContainer.Stub {
final WeakReference<WindowContainer> mWeakRef;
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index 812bc438246f..49c7e0a3b242 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -13,7 +13,6 @@ cc_library_static {
],
srcs: [
- ":graphicsstats_proto",
":lib_alarmManagerService_native",
"BroadcastRadio/JavaRef.cpp",
"BroadcastRadio/NativeCallbackThread.cpp",
@@ -53,7 +52,6 @@ cc_library_static {
"com_android_server_UsbHostManager.cpp",
"com_android_server_VibratorService.cpp",
"com_android_server_PersistentDataBlockService.cpp",
- "com_android_server_GraphicsStatsService.cpp",
"com_android_server_am_CachedAppOptimizer.cpp",
"com_android_server_am_LowMemDetector.cpp",
"com_android_server_incremental_IncrementalManagerService.cpp",
@@ -107,8 +105,6 @@ cc_defaults {
"libinputflinger",
"libinputflinger_base",
"libinputservice",
- "libprotobuf-cpp-lite",
- "libprotoutil",
"libstatshidl",
"libstatspull",
"libstatssocket",
diff --git a/services/core/jni/com_android_server_GraphicsStatsService.cpp b/services/core/jni/com_android_server_GraphicsStatsService.cpp
deleted file mode 100644
index aa7067ee7509..000000000000
--- a/services/core/jni/com_android_server_GraphicsStatsService.cpp
+++ /dev/null
@@ -1,292 +0,0 @@
-/*
- * Copyright (C) 2017 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 "GraphicsStatsService"
-
-#include <jni.h>
-#include <log/log.h>
-#include <nativehelper/JNIHelp.h>
-#include <nativehelper/ScopedPrimitiveArray.h>
-#include <nativehelper/ScopedUtfChars.h>
-#include <JankTracker.h>
-#include <service/GraphicsStatsService.h>
-#include <stats_pull_atom_callback.h>
-#include <stats_event.h>
-#include <statslog.h>
-#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
-#include <android/util/ProtoOutputStream.h>
-#include "android/graphics/Utils.h"
-#include "core_jni_helpers.h"
-#include "protos/graphicsstats.pb.h"
-#include <cstring>
-#include <memory>
-
-namespace android {
-
-using namespace android::uirenderer;
-
-static jint getAshmemSize(JNIEnv*, jobject) {
- return sizeof(ProfileData);
-}
-
-static jlong createDump(JNIEnv*, jobject, jint fd, jboolean isProto) {
- GraphicsStatsService::Dump* dump = GraphicsStatsService::createDump(fd, isProto
- ? GraphicsStatsService::DumpType::Protobuf : GraphicsStatsService::DumpType::Text);
- return reinterpret_cast<jlong>(dump);
-}
-
-static void addToDump(JNIEnv* env, jobject, jlong dumpPtr, jstring jpath, jstring jpackage,
- jlong versionCode, jlong startTime, jlong endTime, jbyteArray jdata) {
- std::string path;
- const ProfileData* data = nullptr;
- LOG_ALWAYS_FATAL_IF(jdata == nullptr && jpath == nullptr, "Path and data can't both be null");
- ScopedByteArrayRO buffer{env};
- if (jdata != nullptr) {
- buffer.reset(jdata);
- LOG_ALWAYS_FATAL_IF(buffer.size() != sizeof(ProfileData),
- "Buffer size %zu doesn't match expected %zu!", buffer.size(), sizeof(ProfileData));
- data = reinterpret_cast<const ProfileData*>(buffer.get());
- }
- if (jpath != nullptr) {
- ScopedUtfChars pathChars(env, jpath);
- LOG_ALWAYS_FATAL_IF(pathChars.size() <= 0 || !pathChars.c_str(), "Failed to get path chars");
- path.assign(pathChars.c_str(), pathChars.size());
- }
- ScopedUtfChars packageChars(env, jpackage);
- LOG_ALWAYS_FATAL_IF(packageChars.size() <= 0 || !packageChars.c_str(), "Failed to get path chars");
- GraphicsStatsService::Dump* dump = reinterpret_cast<GraphicsStatsService::Dump*>(dumpPtr);
- LOG_ALWAYS_FATAL_IF(!dump, "null passed for dump pointer");
-
- const std::string package(packageChars.c_str(), packageChars.size());
- GraphicsStatsService::addToDump(dump, path, package, versionCode, startTime, endTime, data);
-}
-
-static void addFileToDump(JNIEnv* env, jobject, jlong dumpPtr, jstring jpath) {
- ScopedUtfChars pathChars(env, jpath);
- LOG_ALWAYS_FATAL_IF(pathChars.size() <= 0 || !pathChars.c_str(), "Failed to get path chars");
- const std::string path(pathChars.c_str(), pathChars.size());
- GraphicsStatsService::Dump* dump = reinterpret_cast<GraphicsStatsService::Dump*>(dumpPtr);
- GraphicsStatsService::addToDump(dump, path);
-}
-
-static void finishDump(JNIEnv*, jobject, jlong dumpPtr) {
- GraphicsStatsService::Dump* dump = reinterpret_cast<GraphicsStatsService::Dump*>(dumpPtr);
- GraphicsStatsService::finishDump(dump);
-}
-
-static jlong finishDumpInMemory(JNIEnv* env, jobject, jlong dumpPtr) {
- GraphicsStatsService::Dump* dump = reinterpret_cast<GraphicsStatsService::Dump*>(dumpPtr);
- std::vector<uint8_t>* result = new std::vector<uint8_t>();
- GraphicsStatsService::finishDumpInMemory(dump,
- [](void* buffer, int bufferOffset, int bufferSize, int totalSize, void* param1, void* param2) {
- std::vector<uint8_t>* outBuffer = reinterpret_cast<std::vector<uint8_t>*>(param2);
- if (outBuffer->size() < totalSize) {
- outBuffer->resize(totalSize);
- }
- std::memcpy(outBuffer->data() + bufferOffset, buffer, bufferSize);
- }, env, result);
- return reinterpret_cast<jlong>(result);
-}
-
-static void saveBuffer(JNIEnv* env, jobject clazz, jstring jpath, jstring jpackage,
- jlong versionCode, jlong startTime, jlong endTime, jbyteArray jdata) {
- ScopedByteArrayRO buffer(env, jdata);
- LOG_ALWAYS_FATAL_IF(buffer.size() != sizeof(ProfileData),
- "Buffer size %zu doesn't match expected %zu!", buffer.size(), sizeof(ProfileData));
- ScopedUtfChars pathChars(env, jpath);
- LOG_ALWAYS_FATAL_IF(pathChars.size() <= 0 || !pathChars.c_str(), "Failed to get path chars");
- ScopedUtfChars packageChars(env, jpackage);
- LOG_ALWAYS_FATAL_IF(packageChars.size() <= 0 || !packageChars.c_str(), "Failed to get path chars");
-
- const std::string path(pathChars.c_str(), pathChars.size());
- const std::string package(packageChars.c_str(), packageChars.size());
- const ProfileData* data = reinterpret_cast<const ProfileData*>(buffer.get());
- GraphicsStatsService::saveBuffer(path, package, versionCode, startTime, endTime, data);
-}
-
-static jobject gGraphicsStatsServiceObject = nullptr;
-static jmethodID gGraphicsStatsService_pullGraphicsStatsMethodID;
-
-static JNIEnv* getJNIEnv() {
- JavaVM* vm = AndroidRuntime::getJavaVM();
- JNIEnv* env = nullptr;
- if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
- if (vm->AttachCurrentThreadAsDaemon(&env, nullptr) != JNI_OK) {
- LOG_ALWAYS_FATAL("Failed to AttachCurrentThread!");
- }
- }
- return env;
-}
-
-using namespace google::protobuf;
-
-// Field ids taken from FrameTimingHistogram message in atoms.proto
-#define TIME_MILLIS_BUCKETS_FIELD_NUMBER 1
-#define FRAME_COUNTS_FIELD_NUMBER 2
-
-static void writeCpuHistogram(AStatsEvent* event,
- const uirenderer::protos::GraphicsStatsProto& stat) {
- util::ProtoOutputStream proto;
- for (int bucketIndex = 0; bucketIndex < stat.histogram_size(); bucketIndex++) {
- auto& bucket = stat.histogram(bucketIndex);
- proto.write(android::util::FIELD_TYPE_INT32 | android::util::FIELD_COUNT_REPEATED |
- TIME_MILLIS_BUCKETS_FIELD_NUMBER /* field id */,
- (int)bucket.render_millis());
- }
- for (int bucketIndex = 0; bucketIndex < stat.histogram_size(); bucketIndex++) {
- auto& bucket = stat.histogram(bucketIndex);
- proto.write(android::util::FIELD_TYPE_INT64 | android::util::FIELD_COUNT_REPEATED |
- FRAME_COUNTS_FIELD_NUMBER /* field id */,
- (long long)bucket.frame_count());
- }
- std::vector<uint8_t> outVector;
- proto.serializeToVector(&outVector);
- AStatsEvent_writeByteArray(event, outVector.data(), outVector.size());
-}
-
-static void writeGpuHistogram(AStatsEvent* event,
- const uirenderer::protos::GraphicsStatsProto& stat) {
- util::ProtoOutputStream proto;
- for (int bucketIndex = 0; bucketIndex < stat.gpu_histogram_size(); bucketIndex++) {
- auto& bucket = stat.gpu_histogram(bucketIndex);
- proto.write(android::util::FIELD_TYPE_INT32 | android::util::FIELD_COUNT_REPEATED |
- TIME_MILLIS_BUCKETS_FIELD_NUMBER /* field id */,
- (int)bucket.render_millis());
- }
- for (int bucketIndex = 0; bucketIndex < stat.gpu_histogram_size(); bucketIndex++) {
- auto& bucket = stat.gpu_histogram(bucketIndex);
- proto.write(android::util::FIELD_TYPE_INT64 | android::util::FIELD_COUNT_REPEATED |
- FRAME_COUNTS_FIELD_NUMBER /* field id */,
- (long long)bucket.frame_count());
- }
- std::vector<uint8_t> outVector;
- proto.serializeToVector(&outVector);
- AStatsEvent_writeByteArray(event, outVector.data(), outVector.size());
-}
-
-// graphicsStatsPullCallback is invoked by statsd service to pull GRAPHICS_STATS atom.
-static AStatsManager_PullAtomCallbackReturn graphicsStatsPullCallback(int32_t atom_tag,
- AStatsEventList* data,
- void* cookie) {
- JNIEnv* env = getJNIEnv();
- if (!env) {
- return false;
- }
- if (gGraphicsStatsServiceObject == nullptr) {
- ALOGE("Failed to get graphicsstats service");
- return AStatsManager_PULL_SKIP;
- }
-
- for (bool lastFullDay : {true, false}) {
- jlong jdata = (jlong) env->CallLongMethod(
- gGraphicsStatsServiceObject,
- gGraphicsStatsService_pullGraphicsStatsMethodID,
- (jboolean)(lastFullDay ? JNI_TRUE : JNI_FALSE));
- if (env->ExceptionCheck()) {
- env->ExceptionDescribe();
- env->ExceptionClear();
- ALOGE("Failed to invoke graphicsstats service");
- return AStatsManager_PULL_SKIP;
- }
- if (!jdata) {
- // null means data is not available for that day.
- continue;
- }
- android::uirenderer::protos::GraphicsStatsServiceDumpProto serviceDump;
- std::vector<uint8_t>* buffer = reinterpret_cast<std::vector<uint8_t>*>(jdata);
- std::unique_ptr<std::vector<uint8_t>> bufferRelease(buffer);
- int dataSize = buffer->size();
- if (!dataSize) {
- // Data is not available for that day.
- continue;
- }
- io::ArrayInputStream input{buffer->data(), dataSize};
- bool success = serviceDump.ParseFromZeroCopyStream(&input);
- if (!success) {
- ALOGW("Parse failed on GraphicsStatsPuller error='%s' dataSize='%d'",
- serviceDump.InitializationErrorString().c_str(), dataSize);
- return AStatsManager_PULL_SKIP;
- }
-
- for (int stat_index = 0; stat_index < serviceDump.stats_size(); stat_index++) {
- auto& stat = serviceDump.stats(stat_index);
- AStatsEvent* event = AStatsEventList_addStatsEvent(data);
- AStatsEvent_setAtomId(event, android::util::GRAPHICS_STATS);
- AStatsEvent_writeString(event, stat.package_name().c_str());
- AStatsEvent_writeInt64(event, (int64_t)stat.version_code());
- AStatsEvent_writeInt64(event, (int64_t)stat.stats_start());
- AStatsEvent_writeInt64(event, (int64_t)stat.stats_end());
- AStatsEvent_writeInt32(event, (int32_t)stat.pipeline());
- AStatsEvent_writeInt32(event, (int32_t)stat.summary().total_frames());
- AStatsEvent_writeInt32(event, (int32_t)stat.summary().missed_vsync_count());
- AStatsEvent_writeInt32(event, (int32_t)stat.summary().high_input_latency_count());
- AStatsEvent_writeInt32(event, (int32_t)stat.summary().slow_ui_thread_count());
- AStatsEvent_writeInt32(event, (int32_t)stat.summary().slow_bitmap_upload_count());
- AStatsEvent_writeInt32(event, (int32_t)stat.summary().slow_draw_count());
- AStatsEvent_writeInt32(event, (int32_t)stat.summary().missed_deadline_count());
- writeCpuHistogram(event, stat);
- writeGpuHistogram(event, stat);
- // TODO: fill in UI mainline module version, when the feature is available.
- AStatsEvent_writeInt64(event, (int64_t)0);
- AStatsEvent_writeBool(event, !lastFullDay);
- AStatsEvent_build(event);
- }
- }
- return AStatsManager_PULL_SUCCESS;
-}
-
-// Register a puller for GRAPHICS_STATS atom with the statsd service.
-static void nativeInit(JNIEnv* env, jobject javaObject) {
- gGraphicsStatsServiceObject = env->NewGlobalRef(javaObject);
- AStatsManager_PullAtomMetadata* metadata = AStatsManager_PullAtomMetadata_obtain();
- AStatsManager_PullAtomMetadata_setCoolDownNs(metadata, 10 * 1000000); // 10 milliseconds
- AStatsManager_PullAtomMetadata_setTimeoutNs(metadata, 2 * NS_PER_SEC); // 2 seconds
-
- AStatsManager_registerPullAtomCallback(android::util::GRAPHICS_STATS,
- &graphicsStatsPullCallback, metadata, nullptr);
-
- AStatsManager_PullAtomMetadata_release(metadata);
-}
-
-static void nativeDestructor(JNIEnv* env, jobject javaObject) {
- AStatsManager_unregisterPullAtomCallback(android::util::GRAPHICS_STATS);
- env->DeleteGlobalRef(gGraphicsStatsServiceObject);
- gGraphicsStatsServiceObject = nullptr;
-}
-
-static const JNINativeMethod sMethods[] = {
- { "nGetAshmemSize", "()I", (void*) getAshmemSize },
- { "nCreateDump", "(IZ)J", (void*) createDump },
- { "nAddToDump", "(JLjava/lang/String;Ljava/lang/String;JJJ[B)V", (void*) addToDump },
- { "nAddToDump", "(JLjava/lang/String;)V", (void*) addFileToDump },
- { "nFinishDump", "(J)V", (void*) finishDump },
- { "nFinishDumpInMemory", "(J)J", (void*) finishDumpInMemory },
- { "nSaveBuffer", "(Ljava/lang/String;Ljava/lang/String;JJJ[B)V", (void*) saveBuffer },
- { "nativeInit", "()V", (void*) nativeInit },
- { "nativeDestructor", "()V", (void*)nativeDestructor }
-};
-
-int register_android_server_GraphicsStatsService(JNIEnv* env)
-{
- jclass graphicsStatsService_class = FindClassOrDie(env,
- "com/android/server/GraphicsStatsService");
- gGraphicsStatsService_pullGraphicsStatsMethodID = GetMethodIDOrDie(env,
- graphicsStatsService_class, "pullGraphicsStats", "(Z)J");
- return jniRegisterNativeMethods(env, "com/android/server/GraphicsStatsService",
- sMethods, NELEM(sMethods));
-}
-
-} // namespace android
diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp
index 1202ad33996d..c1864945f921 100644
--- a/services/core/jni/onload.cpp
+++ b/services/core/jni/onload.cpp
@@ -49,7 +49,7 @@ int register_android_server_PersistentDataBlockService(JNIEnv* env);
int register_android_server_Watchdog(JNIEnv* env);
int register_android_server_HardwarePropertiesManagerService(JNIEnv* env);
int register_android_server_SyntheticPasswordManager(JNIEnv* env);
-int register_android_server_GraphicsStatsService(JNIEnv* env);
+int register_android_graphics_GraphicsStatsService(JNIEnv* env);
int register_android_hardware_display_DisplayViewport(JNIEnv* env);
int register_android_server_net_NetworkStatsFactory(JNIEnv* env);
int register_android_server_net_NetworkStatsService(JNIEnv* env);
@@ -102,7 +102,7 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
register_android_server_HardwarePropertiesManagerService(env);
register_android_server_storage_AppFuse(env);
register_android_server_SyntheticPasswordManager(env);
- register_android_server_GraphicsStatsService(env);
+ register_android_graphics_GraphicsStatsService(env);
register_android_hardware_display_DisplayViewport(env);
register_android_server_net_NetworkStatsFactory(env);
register_android_server_net_NetworkStatsService(env);
diff --git a/services/incremental/BinderIncrementalService.cpp b/services/incremental/BinderIncrementalService.cpp
index 0941831f5299..b2c316a25e7f 100644
--- a/services/incremental/BinderIncrementalService.cpp
+++ b/services/incremental/BinderIncrementalService.cpp
@@ -16,6 +16,7 @@
#include "BinderIncrementalService.h"
+#include <android-base/logging.h>
#include <binder/IResultReceiver.h>
#include <binder/PermissionCache.h>
#include <incfs.h>
@@ -24,7 +25,6 @@
#include "jni.h"
#include "nativehelper/JNIHelp.h"
#include "path.h"
-#include <android-base/logging.h>
using namespace std::literals;
using namespace android::incremental;
@@ -277,6 +277,13 @@ binder::Status BinderIncrementalService::startLoading(int32_t storageId, bool* _
return ok();
}
+binder::Status BinderIncrementalService::configureNativeBinaries(
+ int32_t storageId, const std::string& apkFullPath, const std::string& libDirRelativePath,
+ const std::string& abi, bool* _aidl_return) {
+ *_aidl_return = mImpl.configureNativeBinaries(storageId, apkFullPath, libDirRelativePath, abi);
+ return ok();
+}
+
} // namespace android::os::incremental
jlong Incremental_IncrementalService_Start() {
diff --git a/services/incremental/BinderIncrementalService.h b/services/incremental/BinderIncrementalService.h
index 8a099776b54b..51d7de3d9adf 100644
--- a/services/incremental/BinderIncrementalService.h
+++ b/services/incremental/BinderIncrementalService.h
@@ -28,11 +28,11 @@ namespace android::os::incremental {
class BinderIncrementalService : public BnIncrementalService,
public BinderService<BinderIncrementalService> {
public:
- BinderIncrementalService(const sp<IServiceManager> &sm);
+ BinderIncrementalService(const sp<IServiceManager>& sm);
- static BinderIncrementalService *start();
- static const char16_t *getServiceName() { return u"incremental_service"; }
- status_t dump(int fd, const Vector<String16> &args) final;
+ static BinderIncrementalService* start();
+ static const char16_t* getServiceName() { return u"incremental_service"; }
+ status_t dump(int fd, const Vector<String16>& args) final;
void onSystemReady();
void onInvalidStorage(int mountId);
@@ -70,6 +70,9 @@ public:
std::vector<uint8_t>* _aidl_return) final;
binder::Status startLoading(int32_t storageId, bool* _aidl_return) final;
binder::Status deleteStorage(int32_t storageId) final;
+ binder::Status configureNativeBinaries(int32_t storageId, const std::string& apkFullPath,
+ const std::string& libDirRelativePath,
+ const std::string& abi, bool* _aidl_return) final;
private:
android::incremental::IncrementalService mImpl;
diff --git a/services/incremental/IncrementalService.cpp b/services/incremental/IncrementalService.cpp
index dbd97cfa039a..3b513774b615 100644
--- a/services/incremental/IncrementalService.cpp
+++ b/services/incremental/IncrementalService.cpp
@@ -60,6 +60,9 @@ struct Constants {
static constexpr auto storagePrefix = "st"sv;
static constexpr auto mountpointMdPrefix = ".mountpoint."sv;
static constexpr auto infoMdName = ".info"sv;
+ static constexpr auto libDir = "lib"sv;
+ static constexpr auto libSuffix = ".so"sv;
+ static constexpr auto blockSize = 4096;
};
static const Constants& constants() {
@@ -259,16 +262,18 @@ IncrementalService::~IncrementalService() = default;
inline const char* toString(TimePoint t) {
using SystemClock = std::chrono::system_clock;
- time_t time = SystemClock::to_time_t(SystemClock::now() + std::chrono::duration_cast<SystemClock::duration>(t - Clock::now()));
+ time_t time = SystemClock::to_time_t(
+ SystemClock::now() +
+ std::chrono::duration_cast<SystemClock::duration>(t - Clock::now()));
return std::ctime(&time);
}
inline const char* toString(IncrementalService::BindKind kind) {
switch (kind) {
- case IncrementalService::BindKind::Temporary:
- return "Temporary";
- case IncrementalService::BindKind::Permanent:
- return "Permanent";
+ case IncrementalService::BindKind::Temporary:
+ return "Temporary";
+ case IncrementalService::BindKind::Permanent:
+ return "Permanent";
}
}
@@ -1124,6 +1129,122 @@ bool IncrementalService::prepareDataLoader(IncrementalService::IncFsMount& ifs,
return true;
}
+// Extract lib filse from zip, create new files in incfs and write data to them
+bool IncrementalService::configureNativeBinaries(StorageId storage, std::string_view apkFullPath,
+ std::string_view libDirRelativePath,
+ std::string_view abi) {
+ const auto ifs = getIfs(storage);
+ // First prepare target directories if they don't exist yet
+ if (auto res = makeDirs(storage, libDirRelativePath, 0755)) {
+ LOG(ERROR) << "Failed to prepare target lib directory " << libDirRelativePath
+ << " errno: " << res;
+ return false;
+ }
+
+ std::unique_ptr<ZipFileRO> zipFile(ZipFileRO::open(apkFullPath.data()));
+ if (!zipFile) {
+ LOG(ERROR) << "Failed to open zip file at " << apkFullPath;
+ return false;
+ }
+ void* cookie = nullptr;
+ const auto libFilePrefix = path::join(constants().libDir, abi);
+ if (!zipFile.get()->startIteration(&cookie, libFilePrefix.c_str() /* prefix */,
+ constants().libSuffix.data() /* suffix */)) {
+ LOG(ERROR) << "Failed to start zip iteration for " << apkFullPath;
+ return false;
+ }
+ ZipEntryRO entry = nullptr;
+ bool success = true;
+ while ((entry = zipFile.get()->nextEntry(cookie)) != nullptr) {
+ char fileName[PATH_MAX];
+ if (zipFile.get()->getEntryFileName(entry, fileName, sizeof(fileName))) {
+ continue;
+ }
+ const auto libName = path::basename(fileName);
+ const auto targetLibPath = path::join(libDirRelativePath, libName);
+ const auto targetLibPathAbsolute = normalizePathToStorage(ifs, storage, targetLibPath);
+ // If the extract file already exists, skip
+ struct stat st;
+ if (stat(targetLibPathAbsolute.c_str(), &st) == 0) {
+ LOG(INFO) << "Native lib file already exists: " << targetLibPath
+ << "; skipping extraction";
+ continue;
+ }
+
+ uint32_t uncompressedLen;
+ if (!zipFile.get()->getEntryInfo(entry, nullptr, &uncompressedLen, nullptr, nullptr,
+ nullptr, nullptr)) {
+ LOG(ERROR) << "Failed to read native lib entry: " << fileName;
+ success = false;
+ break;
+ }
+
+ // Create new lib file without signature info
+ incfs::NewFileParams libFileParams;
+ libFileParams.size = uncompressedLen;
+ libFileParams.verification.hashAlgorithm = INCFS_HASH_NONE;
+ // Metadata of the new lib file is its relative path
+ IncFsSpan libFileMetadata;
+ libFileMetadata.data = targetLibPath.c_str();
+ libFileMetadata.size = targetLibPath.size();
+ libFileParams.metadata = libFileMetadata;
+ incfs::FileId libFileId = idFromMetadata(targetLibPath);
+ if (auto res = makeFile(storage, targetLibPath, 0777, libFileId, libFileParams)) {
+ LOG(ERROR) << "Failed to make file for: " << targetLibPath << " errno: " << res;
+ success = false;
+ // If one lib file fails to be created, abort others as well
+ break;
+ }
+
+ // Write extracted data to new file
+ std::vector<uint8_t> libData(uncompressedLen);
+ if (!zipFile.get()->uncompressEntry(entry, &libData[0], uncompressedLen)) {
+ LOG(ERROR) << "Failed to extract native lib zip entry: " << fileName;
+ success = false;
+ break;
+ }
+ android::base::unique_fd writeFd(mIncFs->openWrite(ifs->control, libFileId));
+ if (writeFd < 0) {
+ LOG(ERROR) << "Failed to open write fd for: " << targetLibPath << " errno: " << writeFd;
+ success = false;
+ break;
+ }
+ const int numBlocks = uncompressedLen / constants().blockSize + 1;
+ std::vector<IncFsDataBlock> instructions;
+ auto remainingData = std::span(libData);
+ for (int i = 0; i < numBlocks - 1; i++) {
+ auto inst = IncFsDataBlock{
+ .fileFd = writeFd,
+ .pageIndex = static_cast<IncFsBlockIndex>(i),
+ .compression = INCFS_COMPRESSION_KIND_NONE,
+ .kind = INCFS_BLOCK_KIND_DATA,
+ .dataSize = static_cast<uint16_t>(constants().blockSize),
+ .data = reinterpret_cast<const char*>(remainingData.data()),
+ };
+ instructions.push_back(inst);
+ remainingData = remainingData.subspan(constants().blockSize);
+ }
+ // Last block
+ auto inst = IncFsDataBlock{
+ .fileFd = writeFd,
+ .pageIndex = static_cast<IncFsBlockIndex>(numBlocks - 1),
+ .compression = INCFS_COMPRESSION_KIND_NONE,
+ .kind = INCFS_BLOCK_KIND_DATA,
+ .dataSize = static_cast<uint16_t>(remainingData.size()),
+ .data = reinterpret_cast<const char*>(remainingData.data()),
+ };
+ instructions.push_back(inst);
+ size_t res = mIncFs->writeBlocks(instructions);
+ if (res != instructions.size()) {
+ LOG(ERROR) << "Failed to write data into: " << targetLibPath;
+ success = false;
+ }
+ instructions.clear();
+ }
+ zipFile.get()->endIteration(cookie);
+ return success;
+}
+
binder::Status IncrementalService::IncrementalDataLoaderListener::onStatusChanged(MountId mountId,
int newStatus) {
std::unique_lock l(incrementalService.mLock);
diff --git a/services/incremental/IncrementalService.h b/services/incremental/IncrementalService.h
index dec9f64f2084..2444ddecdb80 100644
--- a/services/incremental/IncrementalService.h
+++ b/services/incremental/IncrementalService.h
@@ -126,7 +126,8 @@ public:
std::vector<std::string> listFiles(StorageId storage) const;
bool startLoading(StorageId storage) const;
-
+ bool configureNativeBinaries(StorageId storage, std::string_view apkFullPath,
+ std::string_view libDirRelativePath, std::string_view abi);
class IncrementalDataLoaderListener : public android::content::pm::BnDataLoaderStatusListener {
public:
IncrementalDataLoaderListener(IncrementalService& incrementalService)
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 036335ca9011..eef6c63d29c9 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -41,6 +41,7 @@ import android.content.res.Configuration;
import android.content.res.Resources.Theme;
import android.database.sqlite.SQLiteCompatibilityWalFlags;
import android.database.sqlite.SQLiteGlobal;
+import android.graphics.GraphicsStatsService;
import android.hardware.display.DisplayManagerInternal;
import android.net.ConnectivityModuleConnector;
import android.net.ITetheringConnector;
diff --git a/services/people/java/com/android/server/people/data/ConversationInfo.java b/services/people/java/com/android/server/people/data/ConversationInfo.java
index bb97533b3222..b60ed3e8783f 100644
--- a/services/people/java/com/android/server/people/data/ConversationInfo.java
+++ b/services/people/java/com/android/server/people/data/ConversationInfo.java
@@ -35,7 +35,7 @@ import java.util.Objects;
*/
public class ConversationInfo {
- private static final int FLAG_VIP = 1;
+ private static final int FLAG_IMPORTANT = 1;
private static final int FLAG_NOTIFICATION_SILENCED = 1 << 1;
@@ -50,7 +50,7 @@ public class ConversationInfo {
private static final int FLAG_DEMOTED = 1 << 6;
@IntDef(flag = true, prefix = {"FLAG_"}, value = {
- FLAG_VIP,
+ FLAG_IMPORTANT,
FLAG_NOTIFICATION_SILENCED,
FLAG_BUBBLED,
FLAG_PERSON_IMPORTANT,
@@ -129,9 +129,9 @@ public class ConversationInfo {
return hasShortcutFlags(ShortcutInfo.FLAG_LONG_LIVED);
}
- /** Whether this conversation is marked as VIP by the user. */
- public boolean isVip() {
- return hasConversationFlags(FLAG_VIP);
+ /** Whether this conversation is marked as important by the user. */
+ public boolean isImportant() {
+ return hasConversationFlags(FLAG_IMPORTANT);
}
/** Whether the notifications for this conversation should be silenced. */
@@ -208,8 +208,8 @@ public class ConversationInfo {
sb.append("]");
sb.append(", conversationFlags=0x").append(Integer.toHexString(mConversationFlags));
sb.append(" [");
- if (isVip()) {
- sb.append("Vip");
+ if (isImportant()) {
+ sb.append("Imp");
}
if (isNotificationSilenced()) {
sb.append("Sil");
@@ -221,7 +221,7 @@ public class ConversationInfo {
sb.append("Dem");
}
if (isPersonImportant()) {
- sb.append("Imp");
+ sb.append("PIm");
}
if (isPersonBot()) {
sb.append("Bot");
@@ -318,8 +318,8 @@ public class ConversationInfo {
return this;
}
- Builder setVip(boolean value) {
- return setConversationFlag(FLAG_VIP, value);
+ Builder setImportant(boolean value) {
+ return setConversationFlag(FLAG_IMPORTANT, value);
}
Builder setNotificationSilenced(boolean value) {
diff --git a/services/people/java/com/android/server/people/data/DataManager.java b/services/people/java/com/android/server/people/data/DataManager.java
index 7fdcf42c6364..7a3ed5348d30 100644
--- a/services/people/java/com/android/server/people/data/DataManager.java
+++ b/services/people/java/com/android/server/people/data/DataManager.java
@@ -21,6 +21,8 @@ import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.annotation.WorkerThread;
import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
import android.app.Person;
import android.app.prediction.AppTarget;
import android.app.prediction.AppTargetEvent;
@@ -157,8 +159,8 @@ public class DataManager {
mNotificationListeners.put(userId, notificationListener);
try {
notificationListener.registerAsSystemService(mContext,
- new ComponentName(PLATFORM_PACKAGE_NAME, getClass().getSimpleName()),
- UserHandle.myUserId());
+ new ComponentName(PLATFORM_PACKAGE_NAME, getClass().getCanonicalName()),
+ userId);
} catch (RemoteException e) {
// Should never occur for local calls.
}
@@ -571,6 +573,44 @@ public class DataManager {
long currentTime = System.currentTimeMillis();
eventHistory.addEvent(new Event(currentTime, Event.TYPE_NOTIFICATION_OPENED));
}
+
+ @Override
+ public void onNotificationChannelModified(String pkg, UserHandle user,
+ NotificationChannel channel, int modificationType) {
+ PackageData packageData = getPackage(pkg, user.getIdentifier());
+ String shortcutId = channel.getConversationId();
+ if (packageData == null || shortcutId == null) {
+ return;
+ }
+ ConversationStore conversationStore = packageData.getConversationStore();
+ ConversationInfo conversationInfo = conversationStore.getConversation(shortcutId);
+ if (conversationInfo == null) {
+ return;
+ }
+ ConversationInfo.Builder builder = new ConversationInfo.Builder(conversationInfo);
+ switch (modificationType) {
+ case NOTIFICATION_CHANNEL_OR_GROUP_ADDED:
+ case NOTIFICATION_CHANNEL_OR_GROUP_UPDATED:
+ builder.setNotificationChannelId(channel.getId());
+ builder.setImportant(channel.isImportantConversation());
+ builder.setDemoted(channel.isDemoted());
+ builder.setNotificationSilenced(
+ channel.getImportance() <= NotificationManager.IMPORTANCE_LOW);
+ builder.setBubbled(channel.canBubble());
+ break;
+ case NOTIFICATION_CHANNEL_OR_GROUP_DELETED:
+ // If the notification channel is deleted, revert all the notification settings
+ // to the default value.
+ builder.setNotificationChannelId(null);
+ builder.setImportant(false);
+ builder.setDemoted(false);
+ builder.setNotificationSilenced(false);
+ builder.setBubbled(false);
+ break;
+ }
+ conversationStore.addOrUpdate(builder.build());
+ // TODO: Cache the shortcut when a conversation's notification setting is changed.
+ }
}
/**
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/ApplicationExitInfoTest.java b/services/tests/mockingservicestests/src/com/android/server/am/ApplicationExitInfoTest.java
index 8d2a152dba83..6083ce34a3bd 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/ApplicationExitInfoTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/ApplicationExitInfoTest.java
@@ -174,12 +174,12 @@ public class ApplicationExitInfoTest {
final int app1ConnectiongGroup = 10;
final int app1UidUser2 = 1010123;
final int app1PidUser2 = 12347;
- final int app1Pss1 = 34567;
- final int app1Rss1 = 45678;
- final int app1Pss2 = 34568;
- final int app1Rss2 = 45679;
- final int app1Pss3 = 34569;
- final int app1Rss3 = 45680;
+ final long app1Pss1 = 34567;
+ final long app1Rss1 = 45678;
+ final long app1Pss2 = 34568;
+ final long app1Rss2 = 45679;
+ final long app1Pss3 = 34569;
+ final long app1Rss3 = 45680;
final String app1ProcessName = "com.android.test.stub1:process";
final String app1PackageName = "com.android.test.stub1";
@@ -344,8 +344,8 @@ public class ApplicationExitInfoTest {
// Case 4: Create a process from another package with kill from lmkd
final int app2UidUser2 = 1010234;
final int app2PidUser2 = 12348;
- final int app2Pss1 = 54321;
- final int app2Rss1 = 65432;
+ final long app2Pss1 = 54321;
+ final long app2Rss1 = 65432;
final String app2ProcessName = "com.android.test.stub2:process";
final String app2PackageName = "com.android.test.stub2";
@@ -402,8 +402,8 @@ public class ApplicationExitInfoTest {
final int app3UidUser2 = 1010345;
final int app3PidUser2 = 12349;
final int app3ConnectiongGroup = 4;
- final int app3Pss1 = 54320;
- final int app3Rss1 = 65430;
+ final long app3Pss1 = 54320;
+ final long app3Rss1 = 65430;
final String app3ProcessName = "com.android.test.stub3:process";
final String app3PackageName = "com.android.test.stub3";
final String app3Description = "native crash";
@@ -529,8 +529,8 @@ public class ApplicationExitInfoTest {
final int app3Uid = 10345;
final int app3IsolatedUid = 99001; // it's an isolated process
final int app3Pid = 12350;
- final int app3Pss2 = 23232;
- final int app3Rss2 = 32323;
+ final long app3Pss2 = 23232;
+ final long app3Rss2 = 32323;
final String app3Description2 = "force close";
sleep(1);
@@ -618,8 +618,8 @@ public class ApplicationExitInfoTest {
sleep(1);
final int app1IsolatedUidUser2 = 1099002; // isolated uid
- final int app1Pss4 = 34343;
- final int app1Rss4 = 43434;
+ final long app1Pss4 = 34343;
+ final long app1Rss4 = 43434;
final long now8 = System.currentTimeMillis();
sigNum = OsConstants.SIGKILL;
doReturn(new Pair<Long, Object>(now8, makeSignalStatus(sigNum)))
@@ -673,8 +673,8 @@ public class ApplicationExitInfoTest {
sleep(1);
final int app1Pid2User2 = 56565;
final int app1IsolatedUid2User2 = 1099003; // isolated uid
- final int app1Pss5 = 34344;
- final int app1Rss5 = 43435;
+ final long app1Pss5 = 34344;
+ final long app1Rss5 = 43435;
final long now9 = System.currentTimeMillis();
sigNum = OsConstants.SIGKILL;
doReturn(new Pair<Long, Object>(now9, makeSignalStatus(sigNum)))
@@ -831,7 +831,7 @@ public class ApplicationExitInfoTest {
}
private ProcessRecord makeProcessRecord(int pid, int uid, int packageUid, Integer definingUid,
- int connectionGroup, int procState, int pss, int rss,
+ int connectionGroup, int procState, long pss, long rss,
String processName, String packageName) {
ApplicationInfo ai = new ApplicationInfo();
ai.packageName = packageName;
@@ -847,8 +847,8 @@ public class ApplicationExitInfoTest {
app.connectionGroup = connectionGroup;
app.setProcState = procState;
app.lastMemInfo = spy(new Debug.MemoryInfo());
- doReturn(pss).when(app.lastMemInfo).getTotalPss();
- doReturn(rss).when(app.lastMemInfo).getTotalRss();
+ doReturn((int) pss).when(app.lastMemInfo).getTotalPss();
+ doReturn((int) rss).when(app.lastMemInfo).getTotalRss();
return app;
}
@@ -856,7 +856,7 @@ public class ApplicationExitInfoTest {
Long timestamp, Integer pid, Integer uid, Integer packageUid,
Integer definingUid, String processName, Integer connectionGroup,
Integer reason, Integer subReason, Integer status,
- Integer pss, Integer rss, Integer importance, String description) {
+ Long pss, Long rss, Integer importance, String description) {
assertNotNull(info);
if (timestamp != null) {
@@ -892,10 +892,10 @@ public class ApplicationExitInfoTest {
assertEquals(status.intValue(), info.getStatus());
}
if (pss != null) {
- assertEquals(pss.intValue(), info.getPss());
+ assertEquals(pss.longValue(), info.getPss());
}
if (rss != null) {
- assertEquals(rss.intValue(), info.getRss());
+ assertEquals(rss.longValue(), info.getRss());
}
if (importance != null) {
assertEquals(importance.intValue(), info.getImportance());
diff --git a/services/tests/mockingservicestests/src/com/android/server/blob/BlobStoreManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/blob/BlobStoreManagerServiceTest.java
index 16dde4203e91..1f147403d655 100644
--- a/services/tests/mockingservicestests/src/com/android/server/blob/BlobStoreManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/blob/BlobStoreManagerServiceTest.java
@@ -43,6 +43,7 @@ import com.android.server.blob.BlobStoreManagerService.Injector;
import org.junit.After;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@@ -209,6 +210,7 @@ public class BlobStoreManagerServiceTest {
verify(file3, never()).delete();
}
+ @Ignore
@Test
public void testHandleIdleMaintenance_deleteStaleSessions() throws Exception {
// Setup sessions
@@ -216,8 +218,8 @@ public class BlobStoreManagerServiceTest {
doReturn(System.currentTimeMillis() - SESSION_EXPIRY_TIMEOUT_MILLIS + 1000)
.when(sessionFile1).lastModified();
final long sessionId1 = 342;
- final BlobHandle blobHandle1 = mock(BlobHandle.class);
- doReturn(System.currentTimeMillis() - 1000).when(blobHandle1).getExpiryTimeMillis();
+ final BlobHandle blobHandle1 = BlobHandle.createWithSha256("digest1".getBytes(),
+ "label1", System.currentTimeMillis() - 1000, "tag1");
final BlobStoreSession session1 = createBlobStoreSessionMock(TEST_PKG1, TEST_UID1,
sessionId1, sessionFile1, blobHandle1);
mUserSessions.append(sessionId1, session1);
@@ -226,8 +228,8 @@ public class BlobStoreManagerServiceTest {
doReturn(System.currentTimeMillis() - 20000)
.when(sessionFile2).lastModified();
final long sessionId2 = 4597;
- final BlobHandle blobHandle2 = mock(BlobHandle.class);
- doReturn(System.currentTimeMillis() + 20000).when(blobHandle2).getExpiryTimeMillis();
+ final BlobHandle blobHandle2 = BlobHandle.createWithSha256("digest2".getBytes(),
+ "label2", System.currentTimeMillis() + 20000, "tag2");
final BlobStoreSession session2 = createBlobStoreSessionMock(TEST_PKG2, TEST_UID2,
sessionId2, sessionFile2, blobHandle2);
mUserSessions.append(sessionId2, session2);
@@ -236,8 +238,8 @@ public class BlobStoreManagerServiceTest {
doReturn(System.currentTimeMillis() - SESSION_EXPIRY_TIMEOUT_MILLIS - 2000)
.when(sessionFile3).lastModified();
final long sessionId3 = 9484;
- final BlobHandle blobHandle3 = mock(BlobHandle.class);
- doReturn(System.currentTimeMillis() + 30000).when(blobHandle3).getExpiryTimeMillis();
+ final BlobHandle blobHandle3 = BlobHandle.createWithSha256("digest3".getBytes(),
+ "label3", System.currentTimeMillis() + 30000, "tag3");
final BlobStoreSession session3 = createBlobStoreSessionMock(TEST_PKG3, TEST_UID3,
sessionId3, sessionFile3, blobHandle3);
mUserSessions.append(sessionId3, session3);
diff --git a/services/tests/servicestests/src/com/android/server/people/data/ConversationInfoTest.java b/services/tests/servicestests/src/com/android/server/people/data/ConversationInfoTest.java
index 05a9a80e262c..c0e7927a8d72 100644
--- a/services/tests/servicestests/src/com/android/server/people/data/ConversationInfoTest.java
+++ b/services/tests/servicestests/src/com/android/server/people/data/ConversationInfoTest.java
@@ -47,7 +47,7 @@ public final class ConversationInfoTest {
.setContactPhoneNumber(PHONE_NUMBER)
.setNotificationChannelId(NOTIFICATION_CHANNEL_ID)
.setShortcutFlags(ShortcutInfo.FLAG_LONG_LIVED)
- .setVip(true)
+ .setImportant(true)
.setNotificationSilenced(true)
.setBubbled(true)
.setDemoted(true)
@@ -62,7 +62,7 @@ public final class ConversationInfoTest {
assertEquals(PHONE_NUMBER, conversationInfo.getContactPhoneNumber());
assertEquals(NOTIFICATION_CHANNEL_ID, conversationInfo.getNotificationChannelId());
assertTrue(conversationInfo.isShortcutLongLived());
- assertTrue(conversationInfo.isVip());
+ assertTrue(conversationInfo.isImportant());
assertTrue(conversationInfo.isNotificationSilenced());
assertTrue(conversationInfo.isBubbled());
assertTrue(conversationInfo.isDemoted());
@@ -83,7 +83,7 @@ public final class ConversationInfoTest {
assertNull(conversationInfo.getContactPhoneNumber());
assertNull(conversationInfo.getNotificationChannelId());
assertFalse(conversationInfo.isShortcutLongLived());
- assertFalse(conversationInfo.isVip());
+ assertFalse(conversationInfo.isImportant());
assertFalse(conversationInfo.isNotificationSilenced());
assertFalse(conversationInfo.isBubbled());
assertFalse(conversationInfo.isDemoted());
@@ -101,7 +101,7 @@ public final class ConversationInfoTest {
.setContactPhoneNumber(PHONE_NUMBER)
.setNotificationChannelId(NOTIFICATION_CHANNEL_ID)
.setShortcutFlags(ShortcutInfo.FLAG_LONG_LIVED)
- .setVip(true)
+ .setImportant(true)
.setNotificationSilenced(true)
.setBubbled(true)
.setPersonImportant(true)
@@ -110,7 +110,7 @@ public final class ConversationInfoTest {
.build();
ConversationInfo destination = new ConversationInfo.Builder(source)
- .setVip(false)
+ .setImportant(false)
.setContactStarred(false)
.build();
@@ -120,7 +120,7 @@ public final class ConversationInfoTest {
assertEquals(PHONE_NUMBER, destination.getContactPhoneNumber());
assertEquals(NOTIFICATION_CHANNEL_ID, destination.getNotificationChannelId());
assertTrue(destination.isShortcutLongLived());
- assertFalse(destination.isVip());
+ assertFalse(destination.isImportant());
assertTrue(destination.isNotificationSilenced());
assertTrue(destination.isBubbled());
assertTrue(destination.isPersonImportant());
diff --git a/services/tests/servicestests/src/com/android/server/people/data/ConversationStoreTest.java b/services/tests/servicestests/src/com/android/server/people/data/ConversationStoreTest.java
index bbcb54ef8d3e..331ad5972fc1 100644
--- a/services/tests/servicestests/src/com/android/server/people/data/ConversationStoreTest.java
+++ b/services/tests/servicestests/src/com/android/server/people/data/ConversationStoreTest.java
@@ -167,7 +167,7 @@ public final class ConversationStoreTest {
.setContactPhoneNumber(phoneNumber)
.setNotificationChannelId(notificationChannelId)
.setShortcutFlags(ShortcutInfo.FLAG_LONG_LIVED)
- .setVip(true)
+ .setImportant(true)
.setBubbled(true)
.build();
}
diff --git a/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java b/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java
index ad5c57dd11bc..498d8886eec3 100644
--- a/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java
@@ -16,10 +16,15 @@
package com.android.server.people.data;
+import static android.service.notification.NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED;
+import static android.service.notification.NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_DELETED;
+import static android.service.notification.NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED;
+
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -33,6 +38,8 @@ import static org.mockito.Mockito.when;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
import android.app.Person;
import android.app.prediction.AppTarget;
import android.app.prediction.AppTargetEvent;
@@ -88,6 +95,7 @@ public final class DataManagerTest {
private static final String TEST_SHORTCUT_ID = "sc";
private static final String CONTACT_URI = "content://com.android.contacts/contacts/lookup/123";
private static final String PHONE_NUMBER = "+1234567890";
+ private static final String NOTIFICATION_CHANNEL_ID = "test : sc";
private static final long MILLIS_PER_MINUTE = 1000L * 60L;
@Mock private Context mContext;
@@ -103,6 +111,7 @@ public final class DataManagerTest {
@Mock private StatusBarNotification mStatusBarNotification;
@Mock private Notification mNotification;
+ private NotificationChannel mNotificationChannel;
private DataManager mDataManager;
private int mCallingUserId;
private TestInjector mInjector;
@@ -152,6 +161,10 @@ public final class DataManagerTest {
when(mStatusBarNotification.getUser()).thenReturn(UserHandle.of(USER_ID_PRIMARY));
when(mNotification.getShortcutId()).thenReturn(TEST_SHORTCUT_ID);
+ mNotificationChannel = new NotificationChannel(
+ NOTIFICATION_CHANNEL_ID, "test channel", NotificationManager.IMPORTANCE_DEFAULT);
+ mNotificationChannel.setConversationId("test", TEST_SHORTCUT_ID);
+
mCallingUserId = USER_ID_PRIMARY;
mInjector = new TestInjector();
@@ -284,9 +297,8 @@ public final class DataManagerTest {
}
@Test
- public void testNotificationListener() {
+ public void testNotificationOpened() {
mDataManager.onUserUnlocked(USER_ID_PRIMARY);
- mDataManager.onUserUnlocked(USER_ID_SECONDARY);
ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
buildPerson());
@@ -308,6 +320,83 @@ public final class DataManagerTest {
}
@Test
+ public void testNotificationChannelCreated() {
+ mDataManager.onUserUnlocked(USER_ID_PRIMARY);
+ mDataManager.onUserUnlocked(USER_ID_SECONDARY);
+
+ ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
+ buildPerson());
+ mDataManager.onShortcutAddedOrUpdated(shortcut);
+
+ NotificationListenerService listenerService =
+ mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY);
+ listenerService.onNotificationChannelModified(TEST_PKG_NAME, UserHandle.of(USER_ID_PRIMARY),
+ mNotificationChannel, NOTIFICATION_CHANNEL_OR_GROUP_ADDED);
+
+ ConversationInfo conversationInfo = mDataManager.getPackage(TEST_PKG_NAME, USER_ID_PRIMARY)
+ .getConversationStore()
+ .getConversation(TEST_SHORTCUT_ID);
+ assertEquals(NOTIFICATION_CHANNEL_ID, conversationInfo.getNotificationChannelId());
+ assertFalse(conversationInfo.isImportant());
+ assertFalse(conversationInfo.isNotificationSilenced());
+ assertFalse(conversationInfo.isDemoted());
+ }
+
+ @Test
+ public void testNotificationChannelModified() {
+ mNotificationChannel.setImportantConversation(true);
+
+ mDataManager.onUserUnlocked(USER_ID_PRIMARY);
+ mDataManager.onUserUnlocked(USER_ID_SECONDARY);
+
+ ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
+ buildPerson());
+ mDataManager.onShortcutAddedOrUpdated(shortcut);
+
+ NotificationListenerService listenerService =
+ mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY);
+ listenerService.onNotificationChannelModified(TEST_PKG_NAME, UserHandle.of(USER_ID_PRIMARY),
+ mNotificationChannel, NOTIFICATION_CHANNEL_OR_GROUP_UPDATED);
+
+ ConversationInfo conversationInfo = mDataManager.getPackage(TEST_PKG_NAME, USER_ID_PRIMARY)
+ .getConversationStore()
+ .getConversation(TEST_SHORTCUT_ID);
+ assertEquals(NOTIFICATION_CHANNEL_ID, conversationInfo.getNotificationChannelId());
+ assertTrue(conversationInfo.isImportant());
+ assertFalse(conversationInfo.isNotificationSilenced());
+ assertFalse(conversationInfo.isDemoted());
+ }
+
+ @Test
+ public void testNotificationChannelDeleted() {
+ mDataManager.onUserUnlocked(USER_ID_PRIMARY);
+ mDataManager.onUserUnlocked(USER_ID_SECONDARY);
+
+ ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
+ buildPerson());
+ mDataManager.onShortcutAddedOrUpdated(shortcut);
+
+ NotificationListenerService listenerService =
+ mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY);
+ listenerService.onNotificationChannelModified(TEST_PKG_NAME, UserHandle.of(USER_ID_PRIMARY),
+ mNotificationChannel, NOTIFICATION_CHANNEL_OR_GROUP_ADDED);
+ ConversationInfo conversationInfo = mDataManager.getPackage(TEST_PKG_NAME, USER_ID_PRIMARY)
+ .getConversationStore()
+ .getConversation(TEST_SHORTCUT_ID);
+ assertEquals(NOTIFICATION_CHANNEL_ID, conversationInfo.getNotificationChannelId());
+
+ listenerService.onNotificationChannelModified(TEST_PKG_NAME, UserHandle.of(USER_ID_PRIMARY),
+ mNotificationChannel, NOTIFICATION_CHANNEL_OR_GROUP_DELETED);
+ conversationInfo = mDataManager.getPackage(TEST_PKG_NAME, USER_ID_PRIMARY)
+ .getConversationStore()
+ .getConversation(TEST_SHORTCUT_ID);
+ assertNull(conversationInfo.getNotificationChannelId());
+ assertFalse(conversationInfo.isImportant());
+ assertFalse(conversationInfo.isNotificationSilenced());
+ assertFalse(conversationInfo.isDemoted());
+ }
+
+ @Test
public void testCallLogContentObserver() {
mDataManager.onUserUnlocked(USER_ID_PRIMARY);
mDataManager.onUserUnlocked(USER_ID_SECONDARY);
diff --git a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
index 3d190be8888b..77f842aa503f 100644
--- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
@@ -556,6 +556,11 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
void injectRestoreCallingIdentity(long token) {
mInjectedCallingUid = (int) token;
}
+
+ @Override
+ boolean injectHasAccessShortcutsPermission(int callingPid, int callingUid) {
+ return true;
+ }
}
protected class LauncherAppsTestable extends LauncherApps {
@@ -1617,6 +1622,22 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
}
/**
+ * Make a long lived shortcut with an ID.
+ */
+ protected ShortcutInfo makeLongLivedShortcut(String id) {
+ final ShortcutInfo.Builder b = new ShortcutInfo.Builder(mClientContext, id)
+ .setActivity(new ComponentName(mClientContext.getPackageName(), "main"))
+ .setShortLabel("title-" + id)
+ .setIntent(makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class))
+ .setLongLived(true);
+ final ShortcutInfo s = b.build();
+
+ s.setTimestamp(mInjectedCurrentTimeMillis); // HACK
+
+ return s;
+ }
+
+ /**
* Make an intent.
*/
protected Intent makeIntent(String action, Class<?> clazz, Object... bundleKeysAndValues) {
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
index 63da5fbab122..f03670843f3a 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
@@ -1240,7 +1240,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
assertTrue(mManager.setDynamicShortcuts(list(
- makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
+ makeLongLivedShortcut("s1"), makeLongLivedShortcut("s2"), makeShortcut("s3"))));
});
// Pin 2 and 3
@@ -1250,9 +1250,12 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
});
// Cache 1 and 2
+ runWithCaller(LAUNCHER_1, USER_0, () -> {
+ mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s1", "s2"),
+ HANDLE_USER_0);
+ });
+
setCaller(CALLING_PACKAGE_1);
- getCallerShortcut("s1").setCached();
- getCallerShortcut("s2").setCached();
// Get manifest shortcuts
assertShortcutIds(mManager.getShortcuts(ShortcutManager.FLAG_MATCH_MANIFEST),
@@ -1315,8 +1318,9 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
public void testCachedShortcuts() {
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
- assertTrue(mManager.setDynamicShortcuts(list(makeShortcut("s1"), makeShortcut("s2"),
- makeShortcut("s3"), makeShortcut("s4"))));
+ assertTrue(mManager.setDynamicShortcuts(list(makeShortcut("s1"),
+ makeLongLivedShortcut("s2"), makeLongLivedShortcut("s3"),
+ makeLongLivedShortcut("s4"))));
});
// Pin s2
@@ -1325,11 +1329,13 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
HANDLE_USER_0);
});
- // Cache 2, 3 and 4
+ // Cache some, but non long lived shortcuts will be ignored.
+ runWithCaller(LAUNCHER_1, USER_0, () -> {
+ mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s1", "s2", "s4"),
+ HANDLE_USER_0);
+ });
+
setCaller(CALLING_PACKAGE_1);
- getCallerShortcut("s2").setCached();
- getCallerShortcut("s3").setCached();
- getCallerShortcut("s4").setCached();
// Get dynamic shortcuts
assertShortcutIds(mManager.getShortcuts(ShortcutManager.FLAG_MATCH_DYNAMIC),
@@ -1339,27 +1345,37 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
"s2");
// Get cached shortcuts
assertShortcutIds(mManager.getShortcuts(ShortcutManager.FLAG_MATCH_CACHED),
- "s2", "s3", "s4");
+ "s2", "s4");
// Remove a dynamic cached shortcut
- mManager.removeDynamicShortcuts(list("s3"));
+ mManager.removeDynamicShortcuts(list("s4"));
assertShortcutIds(mManager.getShortcuts(ShortcutManager.FLAG_MATCH_DYNAMIC),
- "s1", "s2", "s4");
+ "s1", "s2", "s3");
assertShortcutIds(mManager.getShortcuts(ShortcutManager.FLAG_MATCH_CACHED),
- "s2", "s3", "s4");
+ "s2", "s4");
- // Remove dynamic cached long lived shortcuts
- mManager.removeLongLivedShortcuts(list("s3", "s4"));
- assertShortcutIds(mManager.getShortcuts(ShortcutManager.FLAG_MATCH_DYNAMIC),
- "s1", "s2");
+ // uncache a non-dynamic shortcut. Should be removed.
+ runWithCaller(LAUNCHER_1, USER_0, () -> {
+ mLauncherApps.uncacheShortcuts(CALLING_PACKAGE_1, list("s4"),
+ HANDLE_USER_0);
+ });
assertShortcutIds(mManager.getShortcuts(ShortcutManager.FLAG_MATCH_CACHED),
"s2");
+ // Cache another shortcut
+ runWithCaller(LAUNCHER_1, USER_0, () -> {
+ mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s3"),
+ HANDLE_USER_0);
+ });
+ assertShortcutIds(mManager.getShortcuts(ShortcutManager.FLAG_MATCH_CACHED),
+ "s2", "s3");
+
// Remove a dynamic cached pinned long lived shortcut
mManager.removeLongLivedShortcuts(list("s2"));
assertShortcutIds(mManager.getShortcuts(ShortcutManager.FLAG_MATCH_DYNAMIC),
- "s1");
- assertShortcutIds(mManager.getShortcuts(ShortcutManager.FLAG_MATCH_CACHED));
+ "s1", "s3");
+ assertShortcutIds(mManager.getShortcuts(ShortcutManager.FLAG_MATCH_CACHED),
+ "s3");
assertShortcutIds(mManager.getShortcuts(ShortcutManager.FLAG_MATCH_PINNED),
"s2");
}
@@ -1371,7 +1387,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
// Set up shortcuts.
setCaller(CALLING_PACKAGE_1);
- final ShortcutInfo s1_1 = makeShortcut("s1");
+ final ShortcutInfo s1_1 = makeLongLivedShortcut("s1");
final ShortcutInfo s1_2 = makeShortcutWithLocusId("s2", makeLocusId("l1"));
assertTrue(mManager.setDynamicShortcuts(list(s1_1, s1_2)));
@@ -1395,6 +1411,8 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
setCaller(CALLING_PACKAGE_3);
final ShortcutInfo s3_2 = makeShortcutWithLocusId("s3", makeLocusId("l2"));
+ s3_2.setLongLived();
+
assertTrue(mManager.setDynamicShortcuts(list(s3_2)));
getCallerShortcut("s3").setTimestamp(START_TIME + 5000);
@@ -1535,26 +1553,20 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
// TODO More tests: pinned but dynamic.
- // Cache some shortcuts
- setCaller(CALLING_PACKAGE_1);
- getCallerShortcut("s1").setCached();
-
- setCaller(CALLING_PACKAGE_2);
- getCallerShortcut("s4").setCached();
-
- setCaller(CALLING_PACKAGE_3);
- getCallerShortcut("s3").setCached();
-
setCaller(LAUNCHER_1);
+ // Cache some shortcuts. Only long lived shortcuts can get cached.
+ mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s1"), getCallingUser());
+ mLauncherApps.cacheShortcuts(CALLING_PACKAGE_3, list("s3"), getCallingUser());
+
// Cached ones only
assertShortcutIds(assertAllNotKeyFieldsOnly(
mLauncherApps.getShortcuts(buildQuery(
- /* time =*/ 0, CALLING_PACKAGE_2,
+ /* time =*/ 0, CALLING_PACKAGE_3,
/* activity =*/ null,
ShortcutQuery.FLAG_MATCH_CACHED),
getCallingUser())),
- "s4");
+ "s3");
// All packages.
assertShortcutIds(assertAllNotKeyFieldsOnly(
@@ -1563,7 +1575,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
/* activity =*/ null,
ShortcutQuery.FLAG_MATCH_CACHED),
getCallingUser())),
- "s1", "s4", "s3");
+ "s1", "s3");
assertExpectException(
IllegalArgumentException.class, "package name must also be set", () -> {
@@ -1581,7 +1593,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
/* activity =*/ null,
ShortcutQuery.FLAG_MATCH_CACHED),
getCallingUser())),
- "s1", "s4", "s3");
+ "s1", "s3");
}
public void testGetShortcuts_shortcutKinds() throws Exception {
diff --git a/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java b/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java
index fde0ddffa365..4d0481be20b3 100644
--- a/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java
+++ b/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java
@@ -144,6 +144,40 @@ public class SystemConfigTest {
assertEquals("Incorrect blacklist", expectedBlack, actualBlack);
}
+ @Test
+ public void testComponentOverride() throws Exception {
+ final String contents =
+ "<permissions>"
+ + " <component-override package=\"com.android.package1\">\n"
+ + " <component class=\"com.android.package1.Full\" enabled=\"true\"/>"
+ + " <component class=\".Relative\" enabled=\"false\" />\n"
+ + " </component-override>"
+ + " <component-override package=\"com.android.package2\" >\n"
+ + " <component class=\"com.android.package3.Relative2\" enabled=\"yes\" />\n"
+ + " </component-override>\n"
+ + "</permissions>";
+
+ final File folder = createTempSubfolder("folder");
+ createTempFile(folder, "component-override.xml", contents);
+
+ mSysConfig.readPermissions(folder, /* No permission needed anyway */ 0);
+
+ final ArrayMap<String, Boolean> packageOneExpected = new ArrayMap<>();
+ packageOneExpected.put("com.android.package1.Full", true);
+ packageOneExpected.put("com.android.package1.Relative", false);
+
+ final ArrayMap<String, Boolean> packageTwoExpected = new ArrayMap<>();
+ packageTwoExpected.put("com.android.package3.Relative2", true);
+
+ final Map<String, Boolean> packageOne = mSysConfig.getComponentsEnabledStates(
+ "com.android.package1");
+ assertEquals(packageOneExpected, packageOne);
+
+ final Map<String, Boolean> packageTwo = mSysConfig.getComponentsEnabledStates(
+ "com.android.package2");
+ assertEquals(packageTwoExpected, packageTwo);
+ }
+
/**
* Creates folderName/fileName in the mTemporaryFolder and fills it with the contents.
* @param folderName subdirectory of mTemporaryFolder to put the file, creating if needed
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationHistoryDatabaseTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationHistoryDatabaseTest.java
index 5b5ad877081c..cbb760a7a871 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationHistoryDatabaseTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationHistoryDatabaseTest.java
@@ -44,6 +44,7 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.mockito.internal.matchers.Not;
import java.io.File;
import java.util.ArrayList;
@@ -239,6 +240,52 @@ public class NotificationHistoryDatabaseTest extends UiServiceTestCase {
verify(af2, never()).openRead();
}
+ @Test
+ public void testRemoveNotificationRunnable() throws Exception {
+ NotificationHistory nh = mock(NotificationHistory.class);
+ NotificationHistoryDatabase.RemoveNotificationRunnable rnr =
+ mDataBase.new RemoveNotificationRunnable("pkg", 123);
+ rnr.setNotificationHistory(nh);
+
+ AtomicFile af = mock(AtomicFile.class);
+ when(af.getBaseFile()).thenReturn(new File(mRootDir, "af"));
+ mDataBase.mHistoryFiles.addLast(af);
+
+ when(nh.removeNotificationFromWrite("pkg", 123)).thenReturn(true);
+
+ mDataBase.mBuffer = mock(NotificationHistory.class);
+
+ rnr.run();
+
+ verify(mDataBase.mBuffer).removeNotificationFromWrite("pkg", 123);
+ verify(af).openRead();
+ verify(nh).removeNotificationFromWrite("pkg", 123);
+ verify(af).startWrite();
+ }
+
+ @Test
+ public void testRemoveNotificationRunnable_noChanges() throws Exception {
+ NotificationHistory nh = mock(NotificationHistory.class);
+ NotificationHistoryDatabase.RemoveNotificationRunnable rnr =
+ mDataBase.new RemoveNotificationRunnable("pkg", 123);
+ rnr.setNotificationHistory(nh);
+
+ AtomicFile af = mock(AtomicFile.class);
+ when(af.getBaseFile()).thenReturn(new File(mRootDir, "af"));
+ mDataBase.mHistoryFiles.addLast(af);
+
+ when(nh.removeNotificationFromWrite("pkg", 123)).thenReturn(false);
+
+ mDataBase.mBuffer = mock(NotificationHistory.class);
+
+ rnr.run();
+
+ verify(mDataBase.mBuffer).removeNotificationFromWrite("pkg", 123);
+ verify(af).openRead();
+ verify(nh).removeNotificationFromWrite("pkg", 123);
+ verify(af, never()).startWrite();
+ }
+
private class TestFileAttrProvider implements NotificationHistoryDatabase.FileAttrProvider {
public Map<File, Long> creationDates = new HashMap<>();
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationHistoryManagerTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationHistoryManagerTest.java
index b5eb1bf31848..2c548be185c9 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationHistoryManagerTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationHistoryManagerTest.java
@@ -289,6 +289,20 @@ public class NotificationHistoryManagerTest extends UiServiceTestCase {
}
@Test
+ public void testDeleteNotificationHistoryItem_userUnlocked() {
+ String pkg = "pkg";
+ long time = 235;
+ NotificationHistoryDatabase userHistory = mock(NotificationHistoryDatabase.class);
+
+ mHistoryManager.onUserUnlocked(USER_SYSTEM);
+ mHistoryManager.replaceNotificationHistoryDatabase(USER_SYSTEM, userHistory);
+
+ mHistoryManager.deleteNotificationHistoryItem(pkg, 1, time);
+
+ verify(userHistory, times(1)).deleteNotificationHistoryItem(pkg, time);
+ }
+
+ @Test
public void testTriggerWriteToDisk() {
NotificationHistoryDatabase userHistorySystem = mock(NotificationHistoryDatabase.class);
NotificationHistoryDatabase userHistoryAll = mock(NotificationHistoryDatabase.class);
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java
index 7172a1b14244..f7aa3cc9e52c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java
@@ -29,10 +29,10 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -45,8 +45,10 @@ import android.app.ActivityManager.StackInfo;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.Binder;
+import android.os.IBinder;
import android.os.RemoteException;
import android.platform.test.annotations.Presubmit;
+import android.util.ArrayMap;
import android.view.Display;
import android.view.ITaskOrganizer;
import android.view.IWindowContainer;
@@ -357,6 +359,78 @@ public class TaskOrganizerTests extends WindowTestsBase {
assertEquals(ACTIVITY_TYPE_UNDEFINED, lastReportedTiles.get(0).topActivityType);
}
+ @Test
+ public void testHierarchyTransaction() {
+ final ArrayMap<IBinder, RunningTaskInfo> lastReportedTiles = new ArrayMap<>();
+ ITaskOrganizer listener = new ITaskOrganizer.Stub() {
+ @Override
+ public void taskAppeared(RunningTaskInfo taskInfo) { }
+
+ @Override
+ public void taskVanished(IWindowContainer container) { }
+
+ @Override
+ public void transactionReady(int id, SurfaceControl.Transaction t) { }
+
+ @Override
+ public void onTaskInfoChanged(RunningTaskInfo info) {
+ lastReportedTiles.put(info.token.asBinder(), info);
+ }
+ };
+ mWm.mAtmService.mTaskOrganizerController.registerTaskOrganizer(
+ listener, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
+ RunningTaskInfo info1 = mWm.mAtmService.mTaskOrganizerController.createRootTask(
+ mDisplayContent.mDisplayId, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
+ RunningTaskInfo info2 = mWm.mAtmService.mTaskOrganizerController.createRootTask(
+ mDisplayContent.mDisplayId, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
+
+ final ActivityStack stack = createTaskStackOnDisplay(
+ WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD, mDisplayContent);
+ final ActivityStack stack2 = createTaskStackOnDisplay(
+ WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_HOME, mDisplayContent);
+
+ lastReportedTiles.clear();
+ WindowContainerTransaction wct = new WindowContainerTransaction();
+ wct.reparent(stack.mRemoteToken, info1.token, true /* onTop */);
+ wct.reparent(stack2.mRemoteToken, info2.token, true /* onTop */);
+ mWm.mAtmService.mTaskOrganizerController.applyContainerTransaction(wct,
+ null /* organizer */);
+ assertFalse(lastReportedTiles.isEmpty());
+ assertEquals(ACTIVITY_TYPE_STANDARD,
+ lastReportedTiles.get(info1.token.asBinder()).topActivityType);
+ assertEquals(ACTIVITY_TYPE_HOME,
+ lastReportedTiles.get(info2.token.asBinder()).topActivityType);
+
+ lastReportedTiles.clear();
+ wct = new WindowContainerTransaction();
+ wct.reparent(stack2.mRemoteToken, info1.token, false /* onTop */);
+ mWm.mAtmService.mTaskOrganizerController.applyContainerTransaction(wct,
+ null /* organizer */);
+ assertFalse(lastReportedTiles.isEmpty());
+ // Standard should still be on top of tile 1, so no change there
+ assertFalse(lastReportedTiles.containsKey(info1.token.asBinder()));
+ // But tile 2 has no children, so should become undefined
+ assertEquals(ACTIVITY_TYPE_UNDEFINED,
+ lastReportedTiles.get(info2.token.asBinder()).topActivityType);
+
+ // Check the getChildren call
+ List<RunningTaskInfo> children =
+ mWm.mAtmService.mTaskOrganizerController.getChildTasks(info1.token);
+ assertEquals(2, children.size());
+ children = mWm.mAtmService.mTaskOrganizerController.getChildTasks(info2.token);
+ assertEquals(0, children.size());
+
+ lastReportedTiles.clear();
+ wct = new WindowContainerTransaction();
+ wct.reorder(stack2.mRemoteToken, true /* onTop */);
+ mWm.mAtmService.mTaskOrganizerController.applyContainerTransaction(wct,
+ null /* organizer */);
+ // Home should now be on top. No change occurs in second tile, so not reported
+ assertEquals(1, lastReportedTiles.size());
+ assertEquals(ACTIVITY_TYPE_HOME,
+ lastReportedTiles.get(info1.token.asBinder()).topActivityType);
+ }
+
private List<TaskTile> getTaskTiles(DisplayContent dc) {
ArrayList<TaskTile> out = new ArrayList<>();
for (int i = dc.getStackCount() - 1; i >= 0; --i) {
diff --git a/telephony/java/android/telephony/euicc/EuiccCardManager.java b/telephony/java/android/telephony/euicc/EuiccCardManager.java
index e16fffa69f8a..e1aec0a593b4 100644
--- a/telephony/java/android/telephony/euicc/EuiccCardManager.java
+++ b/telephony/java/android/telephony/euicc/EuiccCardManager.java
@@ -20,6 +20,7 @@ import android.annotation.IntDef;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.content.Context;
+import android.os.Binder;
import android.os.RemoteException;
import android.service.euicc.EuiccProfileInfo;
import android.telephony.TelephonyFrameworkInitializer;
@@ -168,7 +169,12 @@ public class EuiccCardManager {
new IGetAllProfilesCallback.Stub() {
@Override
public void onComplete(int resultCode, EuiccProfileInfo[] profiles) {
- executor.execute(() -> callback.onComplete(resultCode, profiles));
+ final long token = Binder.clearCallingIdentity();
+ try {
+ executor.execute(() -> callback.onComplete(resultCode, profiles));
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
});
} catch (RemoteException e) {
@@ -192,7 +198,12 @@ public class EuiccCardManager {
new IGetProfileCallback.Stub() {
@Override
public void onComplete(int resultCode, EuiccProfileInfo profile) {
- executor.execute(() -> callback.onComplete(resultCode, profile));
+ final long token = Binder.clearCallingIdentity();
+ try {
+ executor.execute(() -> callback.onComplete(resultCode, profile));
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
});
} catch (RemoteException e) {
@@ -217,7 +228,12 @@ public class EuiccCardManager {
refresh, new IDisableProfileCallback.Stub() {
@Override
public void onComplete(int resultCode) {
- executor.execute(() -> callback.onComplete(resultCode, null));
+ final long token = Binder.clearCallingIdentity();
+ try {
+ executor.execute(() -> callback.onComplete(resultCode, null));
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
});
} catch (RemoteException e) {
@@ -243,7 +259,12 @@ public class EuiccCardManager {
refresh, new ISwitchToProfileCallback.Stub() {
@Override
public void onComplete(int resultCode, EuiccProfileInfo profile) {
- executor.execute(() -> callback.onComplete(resultCode, profile));
+ final long token = Binder.clearCallingIdentity();
+ try {
+ executor.execute(() -> callback.onComplete(resultCode, profile));
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
});
} catch (RemoteException e) {
@@ -268,7 +289,12 @@ public class EuiccCardManager {
nickname, new ISetNicknameCallback.Stub() {
@Override
public void onComplete(int resultCode) {
- executor.execute(() -> callback.onComplete(resultCode, null));
+ final long token = Binder.clearCallingIdentity();
+ try {
+ executor.execute(() -> callback.onComplete(resultCode, null));
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
});
} catch (RemoteException e) {
@@ -292,7 +318,12 @@ public class EuiccCardManager {
new IDeleteProfileCallback.Stub() {
@Override
public void onComplete(int resultCode) {
- executor.execute(() -> callback.onComplete(resultCode, null));
+ final long token = Binder.clearCallingIdentity();
+ try {
+ executor.execute(() -> callback.onComplete(resultCode, null));
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
});
} catch (RemoteException e) {
@@ -317,7 +348,12 @@ public class EuiccCardManager {
new IResetMemoryCallback.Stub() {
@Override
public void onComplete(int resultCode) {
- executor.execute(() -> callback.onComplete(resultCode, null));
+ final long token = Binder.clearCallingIdentity();
+ try {
+ executor.execute(() -> callback.onComplete(resultCode, null));
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
});
} catch (RemoteException e) {
@@ -340,7 +376,12 @@ public class EuiccCardManager {
new IGetDefaultSmdpAddressCallback.Stub() {
@Override
public void onComplete(int resultCode, String address) {
- executor.execute(() -> callback.onComplete(resultCode, address));
+ final long token = Binder.clearCallingIdentity();
+ try {
+ executor.execute(() -> callback.onComplete(resultCode, address));
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
});
} catch (RemoteException e) {
@@ -363,7 +404,12 @@ public class EuiccCardManager {
new IGetSmdsAddressCallback.Stub() {
@Override
public void onComplete(int resultCode, String address) {
- executor.execute(() -> callback.onComplete(resultCode, address));
+ final long token = Binder.clearCallingIdentity();
+ try {
+ executor.execute(() -> callback.onComplete(resultCode, address));
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
});
} catch (RemoteException e) {
@@ -388,7 +434,12 @@ public class EuiccCardManager {
new ISetDefaultSmdpAddressCallback.Stub() {
@Override
public void onComplete(int resultCode) {
- executor.execute(() -> callback.onComplete(resultCode, null));
+ final long token = Binder.clearCallingIdentity();
+ try {
+ executor.execute(() -> callback.onComplete(resultCode, null));
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
});
} catch (RemoteException e) {
@@ -411,7 +462,12 @@ public class EuiccCardManager {
new IGetRulesAuthTableCallback.Stub() {
@Override
public void onComplete(int resultCode, EuiccRulesAuthTable rat) {
- executor.execute(() -> callback.onComplete(resultCode, rat));
+ final long token = Binder.clearCallingIdentity();
+ try {
+ executor.execute(() -> callback.onComplete(resultCode, rat));
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
});
} catch (RemoteException e) {
@@ -434,7 +490,12 @@ public class EuiccCardManager {
new IGetEuiccChallengeCallback.Stub() {
@Override
public void onComplete(int resultCode, byte[] challenge) {
- executor.execute(() -> callback.onComplete(resultCode, challenge));
+ final long token = Binder.clearCallingIdentity();
+ try {
+ executor.execute(() -> callback.onComplete(resultCode, challenge));
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
});
} catch (RemoteException e) {
@@ -457,7 +518,12 @@ public class EuiccCardManager {
new IGetEuiccInfo1Callback.Stub() {
@Override
public void onComplete(int resultCode, byte[] info) {
- executor.execute(() -> callback.onComplete(resultCode, info));
+ final long token = Binder.clearCallingIdentity();
+ try {
+ executor.execute(() -> callback.onComplete(resultCode, info));
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
});
} catch (RemoteException e) {
@@ -480,7 +546,12 @@ public class EuiccCardManager {
new IGetEuiccInfo2Callback.Stub() {
@Override
public void onComplete(int resultCode, byte[] info) {
- executor.execute(() -> callback.onComplete(resultCode, info));
+ final long token = Binder.clearCallingIdentity();
+ try {
+ executor.execute(() -> callback.onComplete(resultCode, info));
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
});
} catch (RemoteException e) {
@@ -522,7 +593,12 @@ public class EuiccCardManager {
new IAuthenticateServerCallback.Stub() {
@Override
public void onComplete(int resultCode, byte[] response) {
- executor.execute(() -> callback.onComplete(resultCode, response));
+ final long token = Binder.clearCallingIdentity();
+ try {
+ executor.execute(() -> callback.onComplete(resultCode, response));
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
});
} catch (RemoteException e) {
@@ -561,7 +637,12 @@ public class EuiccCardManager {
new IPrepareDownloadCallback.Stub() {
@Override
public void onComplete(int resultCode, byte[] response) {
- executor.execute(() -> callback.onComplete(resultCode, response));
+ final long token = Binder.clearCallingIdentity();
+ try {
+ executor.execute(() -> callback.onComplete(resultCode, response));
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
});
} catch (RemoteException e) {
@@ -589,7 +670,12 @@ public class EuiccCardManager {
new ILoadBoundProfilePackageCallback.Stub() {
@Override
public void onComplete(int resultCode, byte[] response) {
- executor.execute(() -> callback.onComplete(resultCode, response));
+ final long token = Binder.clearCallingIdentity();
+ try {
+ executor.execute(() -> callback.onComplete(resultCode, response));
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
});
} catch (RemoteException e) {
@@ -619,7 +705,12 @@ public class EuiccCardManager {
new ICancelSessionCallback.Stub() {
@Override
public void onComplete(int resultCode, byte[] response) {
- executor.execute(() -> callback.onComplete(resultCode, response));
+ final long token = Binder.clearCallingIdentity();
+ try {
+ executor.execute(() -> callback.onComplete(resultCode, response));
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
});
} catch (RemoteException e) {
@@ -643,7 +734,13 @@ public class EuiccCardManager {
new IListNotificationsCallback.Stub() {
@Override
public void onComplete(int resultCode, EuiccNotification[] notifications) {
- executor.execute(() -> callback.onComplete(resultCode, notifications));
+ final long token = Binder.clearCallingIdentity();
+ try {
+ executor.execute(() -> callback.onComplete(
+ resultCode, notifications));
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
});
} catch (RemoteException e) {
@@ -667,7 +764,13 @@ public class EuiccCardManager {
events, new IRetrieveNotificationListCallback.Stub() {
@Override
public void onComplete(int resultCode, EuiccNotification[] notifications) {
- executor.execute(() -> callback.onComplete(resultCode, notifications));
+ final long token = Binder.clearCallingIdentity();
+ try {
+ executor.execute(() -> callback.onComplete(
+ resultCode, notifications));
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
});
} catch (RemoteException e) {
@@ -691,7 +794,13 @@ public class EuiccCardManager {
seqNumber, new IRetrieveNotificationCallback.Stub() {
@Override
public void onComplete(int resultCode, EuiccNotification notification) {
- executor.execute(() -> callback.onComplete(resultCode, notification));
+ final long token = Binder.clearCallingIdentity();
+ try {
+ executor.execute(() -> callback.onComplete(
+ resultCode, notification));
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
});
} catch (RemoteException e) {
@@ -718,7 +827,12 @@ public class EuiccCardManager {
new IRemoveNotificationFromListCallback.Stub() {
@Override
public void onComplete(int resultCode) {
- executor.execute(() -> callback.onComplete(resultCode, null));
+ final long token = Binder.clearCallingIdentity();
+ try {
+ executor.execute(() -> callback.onComplete(resultCode, null));
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
});
} catch (RemoteException e) {
diff --git a/tests/RollbackTest/Android.bp b/tests/RollbackTest/Android.bp
index 98e7b4e1b430..89005da27709 100644
--- a/tests/RollbackTest/Android.bp
+++ b/tests/RollbackTest/Android.bp
@@ -36,6 +36,15 @@ java_test_host {
}
java_test_host {
+ name: "NetworkStagedRollbackTest",
+ srcs: ["NetworkStagedRollbackTest/src/**/*.java"],
+ libs: ["tradefed"],
+ static_libs: ["testng"],
+ test_suites: ["general-tests"],
+ test_config: "NetworkStagedRollbackTest.xml",
+}
+
+java_test_host {
name: "MultiUserRollbackTest",
srcs: ["MultiUserRollbackTest/src/**/*.java"],
libs: ["tradefed"],
diff --git a/tests/RollbackTest/NetworkStagedRollbackTest.xml b/tests/RollbackTest/NetworkStagedRollbackTest.xml
new file mode 100644
index 000000000000..a465a4fe578b
--- /dev/null
+++ b/tests/RollbackTest/NetworkStagedRollbackTest.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 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.
+-->
+<configuration description="Runs the network staged rollback tests">
+ <option name="test-suite-tag" value="NetworkStagedRollbackTest" />
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="RollbackTest.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.HostTest" >
+ <option name="class" value="com.android.tests.rollback.host.NetworkStagedRollbackTest" />
+ </test>
+</configuration>
diff --git a/tests/RollbackTest/NetworkStagedRollbackTest/src/com/android/tests/rollback/host/NetworkStagedRollbackTest.java b/tests/RollbackTest/NetworkStagedRollbackTest/src/com/android/tests/rollback/host/NetworkStagedRollbackTest.java
new file mode 100644
index 000000000000..2c2e8282ff51
--- /dev/null
+++ b/tests/RollbackTest/NetworkStagedRollbackTest/src/com/android/tests/rollback/host/NetworkStagedRollbackTest.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2020 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.tests.rollback.host;
+
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Runs the network rollback tests.
+ */
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class NetworkStagedRollbackTest extends BaseHostJUnit4Test {
+ /**
+ * Tests failed network health check triggers watchdog staged rollbacks.
+ */
+ @Test
+ public void testNetworkFailedRollback() throws Exception {
+ }
+
+ /**
+ * Tests passed network health check does not trigger watchdog staged rollbacks.
+ */
+ @Test
+ public void testNetworkPassedDoesNotRollback() throws Exception {
+ }
+}
diff --git a/tests/RollbackTest/RollbackTest.xml b/tests/RollbackTest/RollbackTest.xml
index a14b01c57b1b..f2c0f86c3ce1 100644
--- a/tests/RollbackTest/RollbackTest.xml
+++ b/tests/RollbackTest/RollbackTest.xml
@@ -22,9 +22,9 @@
<option name="package" value="com.android.tests.rollback" />
<option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
- <!-- Exclude the StagedRollbackTest and MultiUserRollbackTest tests, which need to be
- specially driven from the StagedRollbackTest and MultiUserRollbackTest host test -->
+ <!-- Exclude the device tests which need to be specially driven from the host tests -->
<option name="exclude-filter" value="com.android.tests.rollback.StagedRollbackTest" />
+ <option name="exclude-filter" value="com.android.tests.rollback.NetworkStagedRollbackTest" />
<option name="exclude-filter" value="com.android.tests.rollback.MultiUserRollbackTest" />
</test>
</configuration>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/dagger/AppName.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/NetworkStagedRollbackTest.java
index 1dbca0cd5527..04004d6abb5a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/dagger/AppName.java
+++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/NetworkStagedRollbackTest.java
@@ -14,17 +14,11 @@
* limitations under the License.
*/
-package com.android.systemui.statusbar.notification.row.dagger;
+package com.android.tests.rollback;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
-import java.lang.annotation.Documented;
-import java.lang.annotation.Retention;
-
-import javax.inject.Qualifier;
-
-@Qualifier
-@Documented
-@Retention(RUNTIME)
-public @interface AppName {
+@RunWith(JUnit4.class)
+public class NetworkStagedRollbackTest {
}
diff --git a/wifi/java/android/net/wifi/SoftApConfiguration.java b/wifi/java/android/net/wifi/SoftApConfiguration.java
index c8fd2434e64f..0db3313ae137 100644
--- a/wifi/java/android/net/wifi/SoftApConfiguration.java
+++ b/wifi/java/android/net/wifi/SoftApConfiguration.java
@@ -519,6 +519,9 @@ public final class SoftApConfiguration implements Parcelable {
case BAND_5GHZ:
wifiConfig.apBand = WifiConfiguration.AP_BAND_5GHZ;
break;
+ case BAND_2GHZ | BAND_5GHZ:
+ wifiConfig.apBand = WifiConfiguration.AP_BAND_ANY;
+ break;
case BAND_ANY:
wifiConfig.apBand = WifiConfiguration.AP_BAND_ANY;
break;
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 1682023c3312..5ccc3aa429c6 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -2982,7 +2982,7 @@ public class WifiManager {
}
/**
- * Start Soft AP (hotspot) mode with the specified configuration.
+ * Start Soft AP (hotspot) mode for tethering purposes with the specified configuration.
* Note that starting Soft AP mode may disable station mode operation if the device does not
* support concurrency.
* @param wifiConfig SSID, security and channel details as part of WifiConfiguration, or null to
@@ -3278,7 +3278,7 @@ public class WifiManager {
}
/**
- * Gets the Wi-Fi enabled state.
+ * Gets the tethered Wi-Fi hotspot enabled state.
* @return One of {@link #WIFI_AP_STATE_DISABLED},
* {@link #WIFI_AP_STATE_DISABLING}, {@link #WIFI_AP_STATE_ENABLED},
* {@link #WIFI_AP_STATE_ENABLING}, {@link #WIFI_AP_STATE_FAILED}
@@ -3297,8 +3297,8 @@ public class WifiManager {
}
/**
- * Return whether Wi-Fi AP is enabled or disabled.
- * @return {@code true} if Wi-Fi AP is enabled
+ * Return whether tethered Wi-Fi AP is enabled or disabled.
+ * @return {@code true} if tethered Wi-Fi AP is enabled
* @see #getWifiApState()
*
* @hide
@@ -3310,7 +3310,7 @@ public class WifiManager {
}
/**
- * Gets the Wi-Fi AP Configuration.
+ * Gets the tethered Wi-Fi AP Configuration.
* @return AP details in WifiConfiguration
*
* Note that AP detail may contain configuration which is cannot be represented
@@ -3332,7 +3332,7 @@ public class WifiManager {
}
/**
- * Gets the Wi-Fi AP Configuration.
+ * Gets the Wi-Fi tethered AP Configuration.
* @return AP details in {@link SoftApConfiguration}
*
* @hide
@@ -3349,7 +3349,7 @@ public class WifiManager {
}
/**
- * Sets the Wi-Fi AP Configuration.
+ * Sets the tethered Wi-Fi AP Configuration.
* @return {@code true} if the operation succeeded, {@code false} otherwise
*
* @deprecated This API is deprecated. Use {@link #setSoftApConfiguration(SoftApConfiguration)}
@@ -3368,9 +3368,9 @@ public class WifiManager {
}
/**
- * Sets the Wi-Fi AP Configuration.
+ * Sets the tethered Wi-Fi AP Configuration.
*
- * If the API is called while the soft AP is enabled, the configuration will apply to
+ * If the API is called while the tethered soft AP is enabled, the configuration will apply to
* the current soft AP if the new configuration only includes
* {@link SoftApConfiguration.Builder#setMaxNumberOfClients(int)}
* or {@link SoftApConfiguration.Builder#setShutdownTimeoutMillis(int)}
diff --git a/wifi/tests/src/android/net/wifi/SoftApConfigurationTest.java b/wifi/tests/src/android/net/wifi/SoftApConfigurationTest.java
index 2efdd97543a9..d9584885a045 100644
--- a/wifi/tests/src/android/net/wifi/SoftApConfigurationTest.java
+++ b/wifi/tests/src/android/net/wifi/SoftApConfigurationTest.java
@@ -287,17 +287,43 @@ public class SoftApConfigurationTest {
@Test
public void testToWifiConfigurationWithSupportedParameter() {
- SoftApConfiguration softApConfig = new SoftApConfiguration.Builder()
+ SoftApConfiguration softApConfig_2g = new SoftApConfiguration.Builder()
+ .setPassphrase("secretsecret",
+ SoftApConfiguration.SECURITY_TYPE_WPA2_PSK)
+ .setChannel(11, SoftApConfiguration.BAND_2GHZ)
+ .setHiddenSsid(true)
+ .build();
+ WifiConfiguration wifiConfig_2g = softApConfig_2g.toWifiConfiguration();
+ assertThat(wifiConfig_2g.getAuthType()).isEqualTo(WifiConfiguration.KeyMgmt.WPA2_PSK);
+ assertThat(wifiConfig_2g.preSharedKey).isEqualTo("secretsecret");
+ assertThat(wifiConfig_2g.apBand).isEqualTo(WifiConfiguration.AP_BAND_2GHZ);
+ assertThat(wifiConfig_2g.apChannel).isEqualTo(11);
+ assertThat(wifiConfig_2g.hiddenSSID).isEqualTo(true);
+
+ SoftApConfiguration softApConfig_5g = new SoftApConfiguration.Builder()
.setPassphrase("secretsecret",
SoftApConfiguration.SECURITY_TYPE_WPA2_PSK)
.setChannel(149, SoftApConfiguration.BAND_5GHZ)
.setHiddenSsid(true)
.build();
- WifiConfiguration wifiConfig = softApConfig.toWifiConfiguration();
- assertThat(wifiConfig.getAuthType()).isEqualTo(WifiConfiguration.KeyMgmt.WPA2_PSK);
- assertThat(wifiConfig.preSharedKey).isEqualTo("secretsecret");
- assertThat(wifiConfig.apBand).isEqualTo(WifiConfiguration.AP_BAND_5GHZ);
- assertThat(wifiConfig.apChannel).isEqualTo(149);
- assertThat(wifiConfig.hiddenSSID).isEqualTo(true);
+ WifiConfiguration wifiConfig_5g = softApConfig_5g.toWifiConfiguration();
+ assertThat(wifiConfig_5g.getAuthType()).isEqualTo(WifiConfiguration.KeyMgmt.WPA2_PSK);
+ assertThat(wifiConfig_5g.preSharedKey).isEqualTo("secretsecret");
+ assertThat(wifiConfig_5g.apBand).isEqualTo(WifiConfiguration.AP_BAND_5GHZ);
+ assertThat(wifiConfig_5g.apChannel).isEqualTo(149);
+ assertThat(wifiConfig_5g.hiddenSSID).isEqualTo(true);
+
+ SoftApConfiguration softApConfig_2g5g = new SoftApConfiguration.Builder()
+ .setPassphrase("secretsecret",
+ SoftApConfiguration.SECURITY_TYPE_WPA2_PSK)
+ .setBand(SoftApConfiguration.BAND_2GHZ | SoftApConfiguration.BAND_5GHZ)
+ .setHiddenSsid(true)
+ .build();
+ WifiConfiguration wifiConfig_2g5g = softApConfig_2g5g.toWifiConfiguration();
+ assertThat(wifiConfig_2g5g.getAuthType()).isEqualTo(WifiConfiguration.KeyMgmt.WPA2_PSK);
+ assertThat(wifiConfig_2g5g.preSharedKey).isEqualTo("secretsecret");
+ assertThat(wifiConfig_2g5g.apBand).isEqualTo(WifiConfiguration.AP_BAND_ANY);
+ assertThat(wifiConfig_2g5g.apChannel).isEqualTo(0);
+ assertThat(wifiConfig_2g5g.hiddenSSID).isEqualTo(true);
}
}