Loading core/java/android/app/ActivityTransitionState.java +8 −1 Original line number Diff line number Diff line Loading @@ -145,7 +145,10 @@ class ActivityTransitionState { * that it is preserved through activty destroy and restore. */ private ArrayList<String> getPendingExitNames() { if (mPendingExitNames == null && mEnterTransitionCoordinator != null) { if (mPendingExitNames == null && mEnterTransitionCoordinator != null && !mEnterTransitionCoordinator.isReturning() ) { mPendingExitNames = mEnterTransitionCoordinator.getPendingExitSharedElementNames(); } return mPendingExitNames; Loading Loading @@ -202,6 +205,7 @@ class ActivityTransitionState { restoreExitedViews(); activity.getWindow().getDecorView().setVisibility(View.VISIBLE); } getPendingExitNames(); // Set mPendingExitNames before resetting mEnterTransitionCoordinator mEnterTransitionCoordinator = new EnterTransitionCoordinator(activity, resultReceiver, sharedElementNames, mEnterActivityOptions.isReturning(), mEnterActivityOptions.isCrossTask()); Loading Loading @@ -250,6 +254,7 @@ class ActivityTransitionState { public void onStop(Activity activity) { restoreExitedViews(); if (mEnterTransitionCoordinator != null) { getPendingExitNames(); // Set mPendingExitNames before clearing mEnterTransitionCoordinator.stop(); mEnterTransitionCoordinator = null; } Loading @@ -275,6 +280,7 @@ class ActivityTransitionState { restoreReenteringViews(); } else if (mEnterTransitionCoordinator.isReturning()) { mEnterTransitionCoordinator.runAfterTransitionsComplete(() -> { getPendingExitNames(); // Set mPendingExitNames before clearing mEnterTransitionCoordinator = null; }); } Loading Loading @@ -374,6 +380,7 @@ class ActivityTransitionState { } public void startExitOutTransition(Activity activity, Bundle options) { getPendingExitNames(); // Set mPendingExitNames before clearing mEnterTransitionCoordinator mEnterTransitionCoordinator = null; if (!activity.getWindow().hasFeature(Window.FEATURE_ACTIVITY_TRANSITIONS) || mExitTransitionCoordinators == null) { Loading core/java/android/view/WindowManager.java +7 −1 Original line number Diff line number Diff line Loading @@ -285,11 +285,17 @@ public interface WindowManager extends ViewManager { int TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER = 21; /** * Keyguard is being occluded. * Keyguard is being occluded by non-Dream. * @hide */ int TRANSIT_OLD_KEYGUARD_OCCLUDE = 22; /** * Keyguard is being occluded by Dream. * @hide */ int TRANSIT_OLD_KEYGUARD_OCCLUDE_BY_DREAM = 33; /** * Keyguard is being unoccluded. * @hide Loading packages/SystemUI/checks/src/com/android/internal/systemui/lint/SlowUserQueryDetector.kt 0 → 100644 +103 −0 Original line number Diff line number Diff line /* * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.internal.systemui.lint import com.android.tools.lint.detector.api.Category import com.android.tools.lint.detector.api.Detector import com.android.tools.lint.detector.api.Implementation import com.android.tools.lint.detector.api.Issue import com.android.tools.lint.detector.api.JavaContext import com.android.tools.lint.detector.api.Scope import com.android.tools.lint.detector.api.Severity import com.android.tools.lint.detector.api.SourceCodeScanner import com.intellij.psi.PsiMethod import org.jetbrains.uast.UCallExpression /** * Checks for slow calls to ActivityManager.getCurrentUser() or UserManager.getUserInfo() and * suggests using UserTracker instead. For more info, see: http://go/multi-user-in-systemui-slides. */ @Suppress("UnstableApiUsage") class SlowUserQueryDetector : Detector(), SourceCodeScanner { override fun getApplicableMethodNames(): List<String> { return listOf("getCurrentUser", "getUserInfo") } override fun visitMethodCall(context: JavaContext, node: UCallExpression, method: PsiMethod) { val evaluator = context.evaluator if ( evaluator.isStatic(method) && method.name == "getCurrentUser" && method.containingClass?.qualifiedName == "android.app.ActivityManager" ) { context.report( ISSUE_SLOW_USER_ID_QUERY, method, context.getNameLocation(node), "ActivityManager.getCurrentUser() is slow. " + "Use UserTracker.getUserId() instead." ) } if ( !evaluator.isStatic(method) && method.name == "getUserInfo" && method.containingClass?.qualifiedName == "android.os.UserManager" ) { context.report( ISSUE_SLOW_USER_INFO_QUERY, method, context.getNameLocation(node), "UserManager.getUserInfo() is slow. " + "Use UserTracker.getUserInfo() instead." ) } } companion object { @JvmField val ISSUE_SLOW_USER_ID_QUERY: Issue = Issue.create( id = "SlowUserIdQuery", briefDescription = "User ID queried using ActivityManager instead of UserTracker.", explanation = "ActivityManager.getCurrentUser() makes a binder call and is slow. " + "Instead, inject a UserTracker and call UserTracker.getUserId(). For " + "more info, see: http://go/multi-user-in-systemui-slides", category = Category.PERFORMANCE, priority = 8, severity = Severity.WARNING, implementation = Implementation(SlowUserQueryDetector::class.java, Scope.JAVA_FILE_SCOPE) ) @JvmField val ISSUE_SLOW_USER_INFO_QUERY: Issue = Issue.create( id = "SlowUserInfoQuery", briefDescription = "User info queried using UserManager instead of UserTracker.", explanation = "UserManager.getUserInfo() makes a binder call and is slow. " + "Instead, inject a UserTracker and call UserTracker.getUserInfo(). For " + "more info, see: http://go/multi-user-in-systemui-slides", category = Category.PERFORMANCE, priority = 8, severity = Severity.WARNING, implementation = Implementation(SlowUserQueryDetector::class.java, Scope.JAVA_FILE_SCOPE) ) } } packages/SystemUI/checks/src/com/android/internal/systemui/lint/SystemUIIssueRegistry.kt +2 −0 Original line number Diff line number Diff line Loading @@ -30,6 +30,8 @@ class SystemUIIssueRegistry : IssueRegistry() { get() = listOf( BindServiceViaContextDetector.ISSUE, BroadcastSentViaContextDetector.ISSUE, SlowUserQueryDetector.ISSUE_SLOW_USER_ID_QUERY, SlowUserQueryDetector.ISSUE_SLOW_USER_INFO_QUERY, GetMainLooperViaContextDetector.ISSUE, RegisterReceiverViaContextDetector.ISSUE, SoftwareBitmapDetector.ISSUE, Loading packages/SystemUI/checks/tests/com/android/systemui/lint/SlowUserQueryDetectorTest.kt 0 → 100644 +194 −0 Original line number Diff line number Diff line package com.android.internal.systemui.lint import com.android.tools.lint.checks.infrastructure.LintDetectorTest import com.android.tools.lint.checks.infrastructure.TestFile import com.android.tools.lint.checks.infrastructure.TestFiles import com.android.tools.lint.checks.infrastructure.TestLintTask import com.android.tools.lint.detector.api.Detector import com.android.tools.lint.detector.api.Issue import org.junit.Test class SlowUserQueryDetectorTest : LintDetectorTest() { override fun getDetector(): Detector = SlowUserQueryDetector() override fun lint(): TestLintTask = super.lint().allowMissingSdk(true) override fun getIssues(): List<Issue> = listOf( SlowUserQueryDetector.ISSUE_SLOW_USER_ID_QUERY, SlowUserQueryDetector.ISSUE_SLOW_USER_INFO_QUERY ) @Test fun testGetCurrentUser() { lint() .files( TestFiles.java( """ package test.pkg; import android.app.ActivityManager; public class TestClass1 { public void slewlyGetCurrentUser() { ActivityManager.getCurrentUser(); } } """ ) .indented(), *stubs ) .issues( SlowUserQueryDetector.ISSUE_SLOW_USER_ID_QUERY, SlowUserQueryDetector.ISSUE_SLOW_USER_INFO_QUERY ) .run() .expectWarningCount(1) .expectContains( "ActivityManager.getCurrentUser() is slow. " + "Use UserTracker.getUserId() instead." ) } @Test fun testGetUserInfo() { lint() .files( TestFiles.java( """ package test.pkg; import android.os.UserManager; public class TestClass2 { public void slewlyGetUserInfo(UserManager userManager) { userManager.getUserInfo(); } } """ ) .indented(), *stubs ) .issues( SlowUserQueryDetector.ISSUE_SLOW_USER_ID_QUERY, SlowUserQueryDetector.ISSUE_SLOW_USER_INFO_QUERY ) .run() .expectWarningCount(1) .expectContains( "UserManager.getUserInfo() is slow. " + "Use UserTracker.getUserInfo() instead." ) } @Test fun testUserTrackerGetUserId() { lint() .files( TestFiles.java( """ package test.pkg; import com.android.systemui.settings.UserTracker; public class TestClass3 { public void quicklyGetUserId(UserTracker userTracker) { userTracker.getUserId(); } } """ ) .indented(), *stubs ) .issues( SlowUserQueryDetector.ISSUE_SLOW_USER_ID_QUERY, SlowUserQueryDetector.ISSUE_SLOW_USER_INFO_QUERY ) .run() .expectClean() } @Test fun testUserTrackerGetUserInfo() { lint() .files( TestFiles.java( """ package test.pkg; import com.android.systemui.settings.UserTracker; public class TestClass4 { public void quicklyGetUserId(UserTracker userTracker) { userTracker.getUserInfo(); } } """ ) .indented(), *stubs ) .issues( SlowUserQueryDetector.ISSUE_SLOW_USER_ID_QUERY, SlowUserQueryDetector.ISSUE_SLOW_USER_INFO_QUERY ) .run() .expectClean() } private val activityManagerStub: TestFile = java( """ package android.app; public class ActivityManager { public static int getCurrentUser() {}; } """ ) private val userManagerStub: TestFile = java( """ package android.os; import android.content.pm.UserInfo; import android.annotation.UserIdInt; public class UserManager { public UserInfo getUserInfo(@UserIdInt int userId) {}; } """ ) private val userIdIntStub: TestFile = java( """ package android.annotation; public @interface UserIdInt {} """ ) private val userInfoStub: TestFile = java( """ package android.content.pm; public class UserInfo {} """ ) private val userTrackerStub: TestFile = java( """ package com.android.systemui.settings; import android.content.pm.UserInfo; public interface UserTracker { public int getUserId(); public UserInfo getUserInfo(); } """ ) private val stubs = arrayOf(activityManagerStub, userManagerStub, userIdIntStub, userInfoStub, userTrackerStub) } Loading
core/java/android/app/ActivityTransitionState.java +8 −1 Original line number Diff line number Diff line Loading @@ -145,7 +145,10 @@ class ActivityTransitionState { * that it is preserved through activty destroy and restore. */ private ArrayList<String> getPendingExitNames() { if (mPendingExitNames == null && mEnterTransitionCoordinator != null) { if (mPendingExitNames == null && mEnterTransitionCoordinator != null && !mEnterTransitionCoordinator.isReturning() ) { mPendingExitNames = mEnterTransitionCoordinator.getPendingExitSharedElementNames(); } return mPendingExitNames; Loading Loading @@ -202,6 +205,7 @@ class ActivityTransitionState { restoreExitedViews(); activity.getWindow().getDecorView().setVisibility(View.VISIBLE); } getPendingExitNames(); // Set mPendingExitNames before resetting mEnterTransitionCoordinator mEnterTransitionCoordinator = new EnterTransitionCoordinator(activity, resultReceiver, sharedElementNames, mEnterActivityOptions.isReturning(), mEnterActivityOptions.isCrossTask()); Loading Loading @@ -250,6 +254,7 @@ class ActivityTransitionState { public void onStop(Activity activity) { restoreExitedViews(); if (mEnterTransitionCoordinator != null) { getPendingExitNames(); // Set mPendingExitNames before clearing mEnterTransitionCoordinator.stop(); mEnterTransitionCoordinator = null; } Loading @@ -275,6 +280,7 @@ class ActivityTransitionState { restoreReenteringViews(); } else if (mEnterTransitionCoordinator.isReturning()) { mEnterTransitionCoordinator.runAfterTransitionsComplete(() -> { getPendingExitNames(); // Set mPendingExitNames before clearing mEnterTransitionCoordinator = null; }); } Loading Loading @@ -374,6 +380,7 @@ class ActivityTransitionState { } public void startExitOutTransition(Activity activity, Bundle options) { getPendingExitNames(); // Set mPendingExitNames before clearing mEnterTransitionCoordinator mEnterTransitionCoordinator = null; if (!activity.getWindow().hasFeature(Window.FEATURE_ACTIVITY_TRANSITIONS) || mExitTransitionCoordinators == null) { Loading
core/java/android/view/WindowManager.java +7 −1 Original line number Diff line number Diff line Loading @@ -285,11 +285,17 @@ public interface WindowManager extends ViewManager { int TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER = 21; /** * Keyguard is being occluded. * Keyguard is being occluded by non-Dream. * @hide */ int TRANSIT_OLD_KEYGUARD_OCCLUDE = 22; /** * Keyguard is being occluded by Dream. * @hide */ int TRANSIT_OLD_KEYGUARD_OCCLUDE_BY_DREAM = 33; /** * Keyguard is being unoccluded. * @hide Loading
packages/SystemUI/checks/src/com/android/internal/systemui/lint/SlowUserQueryDetector.kt 0 → 100644 +103 −0 Original line number Diff line number Diff line /* * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.internal.systemui.lint import com.android.tools.lint.detector.api.Category import com.android.tools.lint.detector.api.Detector import com.android.tools.lint.detector.api.Implementation import com.android.tools.lint.detector.api.Issue import com.android.tools.lint.detector.api.JavaContext import com.android.tools.lint.detector.api.Scope import com.android.tools.lint.detector.api.Severity import com.android.tools.lint.detector.api.SourceCodeScanner import com.intellij.psi.PsiMethod import org.jetbrains.uast.UCallExpression /** * Checks for slow calls to ActivityManager.getCurrentUser() or UserManager.getUserInfo() and * suggests using UserTracker instead. For more info, see: http://go/multi-user-in-systemui-slides. */ @Suppress("UnstableApiUsage") class SlowUserQueryDetector : Detector(), SourceCodeScanner { override fun getApplicableMethodNames(): List<String> { return listOf("getCurrentUser", "getUserInfo") } override fun visitMethodCall(context: JavaContext, node: UCallExpression, method: PsiMethod) { val evaluator = context.evaluator if ( evaluator.isStatic(method) && method.name == "getCurrentUser" && method.containingClass?.qualifiedName == "android.app.ActivityManager" ) { context.report( ISSUE_SLOW_USER_ID_QUERY, method, context.getNameLocation(node), "ActivityManager.getCurrentUser() is slow. " + "Use UserTracker.getUserId() instead." ) } if ( !evaluator.isStatic(method) && method.name == "getUserInfo" && method.containingClass?.qualifiedName == "android.os.UserManager" ) { context.report( ISSUE_SLOW_USER_INFO_QUERY, method, context.getNameLocation(node), "UserManager.getUserInfo() is slow. " + "Use UserTracker.getUserInfo() instead." ) } } companion object { @JvmField val ISSUE_SLOW_USER_ID_QUERY: Issue = Issue.create( id = "SlowUserIdQuery", briefDescription = "User ID queried using ActivityManager instead of UserTracker.", explanation = "ActivityManager.getCurrentUser() makes a binder call and is slow. " + "Instead, inject a UserTracker and call UserTracker.getUserId(). For " + "more info, see: http://go/multi-user-in-systemui-slides", category = Category.PERFORMANCE, priority = 8, severity = Severity.WARNING, implementation = Implementation(SlowUserQueryDetector::class.java, Scope.JAVA_FILE_SCOPE) ) @JvmField val ISSUE_SLOW_USER_INFO_QUERY: Issue = Issue.create( id = "SlowUserInfoQuery", briefDescription = "User info queried using UserManager instead of UserTracker.", explanation = "UserManager.getUserInfo() makes a binder call and is slow. " + "Instead, inject a UserTracker and call UserTracker.getUserInfo(). For " + "more info, see: http://go/multi-user-in-systemui-slides", category = Category.PERFORMANCE, priority = 8, severity = Severity.WARNING, implementation = Implementation(SlowUserQueryDetector::class.java, Scope.JAVA_FILE_SCOPE) ) } }
packages/SystemUI/checks/src/com/android/internal/systemui/lint/SystemUIIssueRegistry.kt +2 −0 Original line number Diff line number Diff line Loading @@ -30,6 +30,8 @@ class SystemUIIssueRegistry : IssueRegistry() { get() = listOf( BindServiceViaContextDetector.ISSUE, BroadcastSentViaContextDetector.ISSUE, SlowUserQueryDetector.ISSUE_SLOW_USER_ID_QUERY, SlowUserQueryDetector.ISSUE_SLOW_USER_INFO_QUERY, GetMainLooperViaContextDetector.ISSUE, RegisterReceiverViaContextDetector.ISSUE, SoftwareBitmapDetector.ISSUE, Loading
packages/SystemUI/checks/tests/com/android/systemui/lint/SlowUserQueryDetectorTest.kt 0 → 100644 +194 −0 Original line number Diff line number Diff line package com.android.internal.systemui.lint import com.android.tools.lint.checks.infrastructure.LintDetectorTest import com.android.tools.lint.checks.infrastructure.TestFile import com.android.tools.lint.checks.infrastructure.TestFiles import com.android.tools.lint.checks.infrastructure.TestLintTask import com.android.tools.lint.detector.api.Detector import com.android.tools.lint.detector.api.Issue import org.junit.Test class SlowUserQueryDetectorTest : LintDetectorTest() { override fun getDetector(): Detector = SlowUserQueryDetector() override fun lint(): TestLintTask = super.lint().allowMissingSdk(true) override fun getIssues(): List<Issue> = listOf( SlowUserQueryDetector.ISSUE_SLOW_USER_ID_QUERY, SlowUserQueryDetector.ISSUE_SLOW_USER_INFO_QUERY ) @Test fun testGetCurrentUser() { lint() .files( TestFiles.java( """ package test.pkg; import android.app.ActivityManager; public class TestClass1 { public void slewlyGetCurrentUser() { ActivityManager.getCurrentUser(); } } """ ) .indented(), *stubs ) .issues( SlowUserQueryDetector.ISSUE_SLOW_USER_ID_QUERY, SlowUserQueryDetector.ISSUE_SLOW_USER_INFO_QUERY ) .run() .expectWarningCount(1) .expectContains( "ActivityManager.getCurrentUser() is slow. " + "Use UserTracker.getUserId() instead." ) } @Test fun testGetUserInfo() { lint() .files( TestFiles.java( """ package test.pkg; import android.os.UserManager; public class TestClass2 { public void slewlyGetUserInfo(UserManager userManager) { userManager.getUserInfo(); } } """ ) .indented(), *stubs ) .issues( SlowUserQueryDetector.ISSUE_SLOW_USER_ID_QUERY, SlowUserQueryDetector.ISSUE_SLOW_USER_INFO_QUERY ) .run() .expectWarningCount(1) .expectContains( "UserManager.getUserInfo() is slow. " + "Use UserTracker.getUserInfo() instead." ) } @Test fun testUserTrackerGetUserId() { lint() .files( TestFiles.java( """ package test.pkg; import com.android.systemui.settings.UserTracker; public class TestClass3 { public void quicklyGetUserId(UserTracker userTracker) { userTracker.getUserId(); } } """ ) .indented(), *stubs ) .issues( SlowUserQueryDetector.ISSUE_SLOW_USER_ID_QUERY, SlowUserQueryDetector.ISSUE_SLOW_USER_INFO_QUERY ) .run() .expectClean() } @Test fun testUserTrackerGetUserInfo() { lint() .files( TestFiles.java( """ package test.pkg; import com.android.systemui.settings.UserTracker; public class TestClass4 { public void quicklyGetUserId(UserTracker userTracker) { userTracker.getUserInfo(); } } """ ) .indented(), *stubs ) .issues( SlowUserQueryDetector.ISSUE_SLOW_USER_ID_QUERY, SlowUserQueryDetector.ISSUE_SLOW_USER_INFO_QUERY ) .run() .expectClean() } private val activityManagerStub: TestFile = java( """ package android.app; public class ActivityManager { public static int getCurrentUser() {}; } """ ) private val userManagerStub: TestFile = java( """ package android.os; import android.content.pm.UserInfo; import android.annotation.UserIdInt; public class UserManager { public UserInfo getUserInfo(@UserIdInt int userId) {}; } """ ) private val userIdIntStub: TestFile = java( """ package android.annotation; public @interface UserIdInt {} """ ) private val userInfoStub: TestFile = java( """ package android.content.pm; public class UserInfo {} """ ) private val userTrackerStub: TestFile = java( """ package com.android.systemui.settings; import android.content.pm.UserInfo; public interface UserTracker { public int getUserId(); public UserInfo getUserInfo(); } """ ) private val stubs = arrayOf(activityManagerStub, userManagerStub, userIdIntStub, userInfoStub, userTrackerStub) }