summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.bp2
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java11
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/JobSchedulerShellCommand.java4
-rw-r--r--api/current.txt43
-rw-r--r--api/system-current.txt53
-rw-r--r--core/java/android/app/ActivityOptions.java4
-rw-r--r--core/java/android/app/Notification.java17
-rw-r--r--core/java/android/app/PendingIntent.java7
-rw-r--r--core/java/android/os/BasicShellCommandHandler.java320
-rw-r--r--core/java/android/os/BatteryStatsManager.java16
-rw-r--r--core/java/android/os/Binder.java57
-rw-r--r--core/java/android/os/ShellCommand.java295
-rw-r--r--core/java/android/os/connectivity/CellularBatteryStats.java572
-rw-r--r--core/java/android/util/FeatureFlagUtils.java2
-rw-r--r--core/java/android/view/InputChannel.java5
-rw-r--r--core/java/android/view/TextureView.java66
-rw-r--r--core/java/android/view/View.java15
-rw-r--r--core/java/android/view/WindowlessWindowManager.java5
-rw-r--r--core/java/android/view/inputmethod/InputMethodManager.java77
-rw-r--r--core/java/android/webkit/WebSettings.java7
-rw-r--r--core/java/com/android/internal/os/BaseCommand.java6
-rw-r--r--core/java/com/android/internal/os/BatteryStatsImpl.java20
-rw-r--r--core/java/com/android/internal/statusbar/IStatusBar.aidl19
-rw-r--r--core/java/com/android/internal/statusbar/IStatusBarService.aidl1
-rw-r--r--core/java/com/android/internal/statusbar/RegisterStatusBarResult.java65
-rw-r--r--core/java/com/android/server/SystemConfig.java1
-rw-r--r--core/jni/android_view_InputChannel.cpp14
-rw-r--r--core/proto/android/server/activitymanagerservice.proto4
-rw-r--r--core/res/AndroidManifest.xml5
-rw-r--r--core/res/res/values/config.xml2
-rw-r--r--core/tests/coretests/src/com/android/internal/statusbar/RegisterStatusBarResultTest.java23
-rw-r--r--data/keyboards/Vendor_1532_Product_0900.kl8
-rw-r--r--libs/hwui/renderthread/CanvasContext.cpp3
-rw-r--r--location/java/android/location/LocationRequest.java17
-rw-r--r--media/java/android/media/tv/tuner/Tuner.java121
-rw-r--r--media/java/android/media/tv/tuner/TunerConstants.java72
-rw-r--r--media/jni/android_media_MediaCrypto.cpp18
-rw-r--r--media/jni/android_media_MediaDrm.cpp18
-rw-r--r--media/jni/android_media_tv_Tuner.cpp131
-rw-r--r--media/jni/android_media_tv_Tuner.h36
-rw-r--r--mime/java-res/android.mime.types17
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/CarSystemUIBinder.java217
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationBar.java5
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java8
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarModule.java244
-rw-r--r--packages/SettingsLib/search/processor-src/com/android/settingslib/search/IndexableProcessor.java27
-rw-r--r--packages/SettingsLib/search/src/com/android/settingslib/search/SearchIndexableData.java48
-rw-r--r--packages/SettingsLib/search/src/com/android/settingslib/search/SearchIndexableResources.java11
-rw-r--r--packages/SystemUI/res/values/dimens.xml2
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java19
-rw-r--r--packages/SystemUI/src/com/android/keyguard/CarrierTextController.java12
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java7
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java7
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/CornerHandleView.java25
-rw-r--r--packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/assist/ui/EdgeLight.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/assist/ui/InvocationLightsView.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java30
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java129
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java222
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java691
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java49
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/StatusBarDependenciesModule.java40
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/SuperStatusBarViewFactory.java92
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationData.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinderImpl.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java23
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java26
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java38
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java36
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/PeopleHubView.kt48
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SwipeableView.java50
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationHandle.java25
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java68
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarModule.java230
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java55
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowViewController.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java7
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java10
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java14
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java18
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/WorkLockActivityTest.java11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowControllerTest.java14
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowViewTest.java8
-rw-r--r--packages/Tethering/Android.bp39
-rw-r--r--packages/Tethering/jni/com_android_server_connectivity_tethering_OffloadHardwareInterface.cpp (renamed from services/core/jni/com_android_server_connectivity_tethering_OffloadHardwareInterface.cpp)0
-rw-r--r--packages/Tethering/src/com/android/server/connectivity/tethering/OffloadController.java (renamed from services/core/java/com/android/server/connectivity/tethering/OffloadController.java)20
-rw-r--r--packages/Tethering/src/com/android/server/connectivity/tethering/OffloadHardwareInterface.java (renamed from services/core/java/com/android/server/connectivity/tethering/OffloadHardwareInterface.java)80
-rw-r--r--packages/Tethering/tests/unit/Android.bp2
-rw-r--r--packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/OffloadControllerTest.java (renamed from tests/net/java/com/android/server/connectivity/tethering/OffloadControllerTest.java)14
-rw-r--r--services/core/java/com/android/server/AlarmManagerInternal.java8
-rw-r--r--services/core/java/com/android/server/AlarmManagerService.java31
-rw-r--r--services/core/java/com/android/server/LocationManagerService.java249
-rw-r--r--services/core/java/com/android/server/am/PendingIntentController.java3
-rw-r--r--services/core/java/com/android/server/am/ProcessList.java2
-rw-r--r--services/core/java/com/android/server/attention/AttentionManagerService.java69
-rw-r--r--services/core/java/com/android/server/audio/AudioService.java24
-rw-r--r--services/core/java/com/android/server/input/InputManagerService.java6
-rw-r--r--services/core/java/com/android/server/location/GeofenceManager.java96
-rw-r--r--services/core/java/com/android/server/location/LocationBlacklist.java151
-rw-r--r--services/core/java/com/android/server/location/LocationSettingsStore.java461
-rw-r--r--services/core/java/com/android/server/media/MediaSessionService.java23
-rw-r--r--services/core/java/com/android/server/pm/AppsFilter.java2
-rw-r--r--services/core/java/com/android/server/pm/UserSystemPackageInstaller.java44
-rw-r--r--services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java5
-rw-r--r--services/core/java/com/android/server/statusbar/StatusBarManagerService.java167
-rw-r--r--services/core/java/com/android/server/wallpaper/GLHelper.java148
-rw-r--r--services/core/java/com/android/server/wallpaper/WallpaperManagerService.java114
-rw-r--r--services/core/java/com/android/server/wm/ActivityDisplay.java3
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java135
-rw-r--r--services/core/java/com/android/server/wm/ActivityStack.java271
-rw-r--r--services/core/java/com/android/server/wm/ActivityStackSupervisor.java30
-rw-r--r--services/core/java/com/android/server/wm/ActivityStarter.java7
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerService.java27
-rw-r--r--services/core/java/com/android/server/wm/ConfigurationContainer.java6
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java14
-rw-r--r--services/core/java/com/android/server/wm/DisplayPolicy.java77
-rw-r--r--services/core/java/com/android/server/wm/RecentsAnimation.java6
-rw-r--r--services/core/java/com/android/server/wm/RootActivityContainer.java10
-rw-r--r--services/core/java/com/android/server/wm/RootWindowContainer.java2
-rw-r--r--services/core/java/com/android/server/wm/Task.java231
-rw-r--r--services/core/java/com/android/server/wm/TaskRecord.java517
-rw-r--r--services/core/java/com/android/server/wm/TaskStack.java75
-rw-r--r--services/core/java/com/android/server/wm/WindowContainer.java12
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java5
-rw-r--r--services/core/jni/Android.bp2
-rw-r--r--services/core/jni/com_android_server_input_InputManagerService.cpp4
-rw-r--r--services/java/com/android/server/SystemServer.java2
-rw-r--r--services/net/Android.bp1
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java34
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/am/PendingIntentControllerTest.java130
-rw-r--r--services/tests/servicestests/src/com/android/server/attention/AttentionManagerServiceTest.java52
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java14
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java37
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java8
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java20
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java5
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java3
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java4
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java4
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskPositionerTests.java8
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskPositioningControllerTests.java6
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java31
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskTests.java11
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java15
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java2
-rw-r--r--services/usage/java/com/android/server/usage/UsageStatsProtoV2.java9
-rw-r--r--startop/view_compiler/Android.bp2
-rw-r--r--startop/view_compiler/dex_builder.cc93
-rw-r--r--startop/view_compiler/dex_builder.h29
-rwxr-xr-xtelephony/java/android/telephony/CarrierConfigManager.java8
-rw-r--r--telephony/java/android/telephony/SubscriptionManager.java4
-rw-r--r--telephony/java/android/telephony/SubscriptionPlan.java23
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java27
-rw-r--r--telephony/java/android/telephony/ims/ImsMmTelManager.java25
-rw-r--r--telephony/java/android/telephony/ims/ImsRcsManager.java14
-rw-r--r--telephony/java/android/telephony/ims/RegistrationManager.java38
-rw-r--r--tests/BootImageProfileTest/src/com/android/bootimageprofile/BootImageProfileTest.java7
-rw-r--r--tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassBase.java6
-rw-r--r--tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassChild.java6
-rw-r--r--tests/Codegen/src/com/android/codegentest/ParcelAllTheThingsDataClass.java8
-rw-r--r--tests/Codegen/src/com/android/codegentest/SampleDataClass.java6
-rw-r--r--tests/Codegen/src/com/android/codegentest/SampleWithCustomBuilder.java6
-rw-r--r--tests/Codegen/src/com/android/codegentest/SampleWithNestedDataClasses.java18
-rw-r--r--tests/Codegen/src/com/android/codegentest/StaleDataclassDetectorFalsePositivesTest.java6
-rw-r--r--tools/codegen/src/com/android/codegen/FieldInfo.kt4
-rw-r--r--tools/codegen/src/com/android/codegen/Generators.kt7
-rw-r--r--tools/codegen/src/com/android/codegen/SharedConstants.kt2
-rw-r--r--wifi/java/android/net/wifi/ISoftApCallback.aidl8
-rw-r--r--wifi/java/android/net/wifi/SoftApInfo.aidl20
-rw-r--r--wifi/java/android/net/wifi/SoftApInfo.java211
-rw-r--r--wifi/java/android/net/wifi/WifiManager.java19
-rw-r--r--wifi/tests/src/android/net/wifi/SoftApInfoTest.java71
-rw-r--r--wifi/tests/src/android/net/wifi/WifiManagerTest.java28
193 files changed, 5432 insertions, 3744 deletions
diff --git a/Android.bp b/Android.bp
index 344867715a3f..d04eb17adf15 100644
--- a/Android.bp
+++ b/Android.bp
@@ -962,6 +962,7 @@ metalava_framework_docs_args = "--manifest $(location core/res/AndroidManifest.x
"--hide-package com.android.org.conscrypt --hide-package com.android.server " +
"--error UnhiddenSystemApi " +
"--hide RequiresPermission " +
+ "--hide CallbackInterface " +
"--hide MissingPermission --hide BroadcastBehavior " +
"--hide HiddenSuperclass --hide DeprecationMismatch --hide UnavailableSymbol " +
"--hide SdkConstant --hide HiddenTypeParameter --hide Todo --hide Typo " +
@@ -1637,6 +1638,7 @@ filegroup {
name: "framework-wifistack-shared-srcs",
srcs: [
":framework-annotations",
+ "core/java/android/os/HandlerExecutor.java",
"core/java/android/util/KeyValueListParser.java",
"core/java/android/util/LocalLog.java",
"core/java/android/util/Rational.java",
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 eb22d0907525..593e49490e94 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
@@ -59,9 +59,7 @@ import android.os.Looper;
import android.os.Message;
import android.os.Process;
import android.os.RemoteException;
-import android.os.ResultReceiver;
import android.os.ServiceManager;
-import android.os.ShellCallback;
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManagerInternal;
@@ -2690,12 +2688,13 @@ public class JobSchedulerService extends com.android.server.SystemService
}
@Override
- public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
- String[] args, ShellCallback callback, ResultReceiver resultReceiver) {
- (new JobSchedulerShellCommand(JobSchedulerService.this)).exec(
- this, in, out, err, args, callback, resultReceiver);
+ protected int handleShellCommand(@NonNull FileDescriptor in, @NonNull FileDescriptor out,
+ @NonNull FileDescriptor err, @NonNull String[] args) {
+ return (new JobSchedulerShellCommand(JobSchedulerService.this)).exec(
+ this, in, out, err, args);
}
+
/**
* <b>For internal system user only!</b>
* Returns a list of all currently-executing jobs.
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerShellCommand.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerShellCommand.java
index 01d158ba9452..a5c6c0132fc8 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerShellCommand.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerShellCommand.java
@@ -20,13 +20,13 @@ import android.app.ActivityManager;
import android.app.AppGlobals;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
+import android.os.BasicShellCommandHandler;
import android.os.Binder;
-import android.os.ShellCommand;
import android.os.UserHandle;
import java.io.PrintWriter;
-public final class JobSchedulerShellCommand extends ShellCommand {
+public final class JobSchedulerShellCommand extends BasicShellCommandHandler {
public static final int CMD_ERR_NO_PACKAGE = -1000;
public static final int CMD_ERR_NO_JOB = -1001;
public static final int CMD_ERR_CONSTRAINTS = -1002;
diff --git a/api/current.txt b/api/current.txt
index 55983c86ee4b..e5acc4062377 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -42916,6 +42916,7 @@ package android.system {
field public static final int IP_MULTICAST_TTL;
field public static final int IP_TOS;
field public static final int IP_TTL;
+ field public static final int MAP_ANONYMOUS;
field public static final int MAP_FIXED;
field public static final int MAP_PRIVATE;
field public static final int MAP_SHARED;
@@ -50390,34 +50391,34 @@ package android.view {
}
public class TextureView extends android.view.View {
- ctor public TextureView(android.content.Context);
- ctor public TextureView(android.content.Context, android.util.AttributeSet);
- ctor public TextureView(android.content.Context, android.util.AttributeSet, int);
- ctor public TextureView(android.content.Context, android.util.AttributeSet, int, int);
+ ctor public TextureView(@NonNull android.content.Context);
+ ctor public TextureView(@NonNull android.content.Context, @Nullable android.util.AttributeSet);
+ ctor public TextureView(@NonNull android.content.Context, @Nullable android.util.AttributeSet, int);
+ ctor public TextureView(@NonNull android.content.Context, @Nullable android.util.AttributeSet, int, int);
method public final void draw(android.graphics.Canvas);
- method public android.graphics.Bitmap getBitmap();
- method public android.graphics.Bitmap getBitmap(int, int);
- method public android.graphics.Bitmap getBitmap(android.graphics.Bitmap);
- method public android.graphics.SurfaceTexture getSurfaceTexture();
- method public android.view.TextureView.SurfaceTextureListener getSurfaceTextureListener();
- method public android.graphics.Matrix getTransform(android.graphics.Matrix);
+ method @Nullable public android.graphics.Bitmap getBitmap();
+ method @Nullable public android.graphics.Bitmap getBitmap(int, int);
+ method @NonNull public android.graphics.Bitmap getBitmap(@NonNull android.graphics.Bitmap);
+ method @Nullable public android.graphics.SurfaceTexture getSurfaceTexture();
+ method @Nullable public android.view.TextureView.SurfaceTextureListener getSurfaceTextureListener();
+ method @NonNull public android.graphics.Matrix getTransform(@Nullable android.graphics.Matrix);
method public boolean isAvailable();
- method public android.graphics.Canvas lockCanvas();
- method public android.graphics.Canvas lockCanvas(android.graphics.Rect);
+ method @Nullable public android.graphics.Canvas lockCanvas();
+ method @Nullable public android.graphics.Canvas lockCanvas(@Nullable android.graphics.Rect);
method protected final void onDraw(android.graphics.Canvas);
method public void setBackgroundDrawable(android.graphics.drawable.Drawable);
method public void setOpaque(boolean);
- method public void setSurfaceTexture(android.graphics.SurfaceTexture);
- method public void setSurfaceTextureListener(android.view.TextureView.SurfaceTextureListener);
- method public void setTransform(android.graphics.Matrix);
- method public void unlockCanvasAndPost(android.graphics.Canvas);
+ method public void setSurfaceTexture(@NonNull android.graphics.SurfaceTexture);
+ method public void setSurfaceTextureListener(@Nullable android.view.TextureView.SurfaceTextureListener);
+ method public void setTransform(@Nullable android.graphics.Matrix);
+ method public void unlockCanvasAndPost(@NonNull android.graphics.Canvas);
}
public static interface TextureView.SurfaceTextureListener {
- method public void onSurfaceTextureAvailable(android.graphics.SurfaceTexture, int, int);
- method public boolean onSurfaceTextureDestroyed(android.graphics.SurfaceTexture);
- method public void onSurfaceTextureSizeChanged(android.graphics.SurfaceTexture, int, int);
- method public void onSurfaceTextureUpdated(android.graphics.SurfaceTexture);
+ method public void onSurfaceTextureAvailable(@NonNull android.graphics.SurfaceTexture, int, int);
+ method public boolean onSurfaceTextureDestroyed(@NonNull android.graphics.SurfaceTexture);
+ method public void onSurfaceTextureSizeChanged(@NonNull android.graphics.SurfaceTexture, int, int);
+ method public void onSurfaceTextureUpdated(@NonNull android.graphics.SurfaceTexture);
}
public class TouchDelegate {
@@ -50677,7 +50678,7 @@ package android.view {
method public final int getScrollY();
method @android.view.ViewDebug.ExportedProperty(category="drawing") @ColorInt public int getSolidColor();
method @LayoutRes public int getSourceLayoutResId();
- method @android.view.ViewDebug.ExportedProperty(category="accessibility") @Nullable public final CharSequence getStateDescription();
+ method @android.view.ViewDebug.ExportedProperty(category="accessibility") @Nullable public CharSequence getStateDescription();
method public android.animation.StateListAnimator getStateListAnimator();
method protected int getSuggestedMinimumHeight();
method protected int getSuggestedMinimumWidth();
diff --git a/api/system-current.txt b/api/system-current.txt
index 0b1839374298..9a24181d18f5 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -75,6 +75,7 @@ package android {
field public static final String GET_TOP_ACTIVITY_INFO = "android.permission.GET_TOP_ACTIVITY_INFO";
field public static final String GRANT_PROFILE_OWNER_DEVICE_IDS_ACCESS = "android.permission.GRANT_PROFILE_OWNER_DEVICE_IDS_ACCESS";
field public static final String GRANT_RUNTIME_PERMISSIONS = "android.permission.GRANT_RUNTIME_PERMISSIONS";
+ field public static final String GRANT_RUNTIME_PERMISSIONS_TO_TELEPHONY_DEFAULTS = "android.permission.GRANT_RUNTIME_PERMISSIONS_TO_TELEPHONY_DEFAULTS";
field public static final String HARDWARE_TEST = "android.permission.HARDWARE_TEST";
field public static final String HDMI_CEC = "android.permission.HDMI_CEC";
field public static final String HIDE_NON_SYSTEM_OVERLAY_WINDOWS = "android.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS";
@@ -4754,6 +4755,21 @@ package android.net.wifi {
method @NonNull public android.net.wifi.SoftApConfiguration.Builder setWpa2Passphrase(@Nullable String);
}
+ public final class SoftApInfo implements android.os.Parcelable {
+ method public int describeContents();
+ method public int getBandwidth();
+ method public int getFrequency();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field public static final int CHANNEL_WIDTH_160MHZ = 6; // 0x6
+ field public static final int CHANNEL_WIDTH_20MHZ = 2; // 0x2
+ field public static final int CHANNEL_WIDTH_20MHZ_NOHT = 1; // 0x1
+ field public static final int CHANNEL_WIDTH_40MHZ = 3; // 0x3
+ field public static final int CHANNEL_WIDTH_80MHZ = 4; // 0x4
+ field public static final int CHANNEL_WIDTH_80MHZ_PLUS_MHZ = 5; // 0x5
+ field public static final int CHANNEL_WIDTH_INVALID = 0; // 0x0
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.SoftApInfo> CREATOR;
+ }
+
public final class WifiClient implements android.os.Parcelable {
method public int describeContents();
method @NonNull public android.net.MacAddress getMacAddress();
@@ -5240,6 +5256,7 @@ package android.os {
}
public class BatteryStatsManager {
+ method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public android.os.connectivity.CellularBatteryStats getCellularBatteryStats();
method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public android.os.connectivity.WifiBatteryStats getWifiBatteryStats();
method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void noteFullWifiLockAcquiredFromSource(@NonNull android.os.WorkSource);
method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void noteFullWifiLockReleasedFromSource(@NonNull android.os.WorkSource);
@@ -5747,6 +5764,26 @@ package android.os {
package android.os.connectivity {
+ public final class CellularBatteryStats implements android.os.Parcelable {
+ method public int describeContents();
+ method public long getEnergyConsumedMaMillis();
+ method public long getIdleTimeMillis();
+ method public long getKernelActiveTimeMillis();
+ method public long getLoggingDurationMillis();
+ method public long getMonitoredRailChargeConsumedMaMillis();
+ method public long getNumBytesRx();
+ method public long getNumBytesTx();
+ method public long getNumPacketsRx();
+ method public long getNumPacketsTx();
+ method public long getRxTimeMillis();
+ method public long getSleepTimeMillis();
+ method @NonNull public long[] getTimeInRatMicros();
+ method @NonNull public long[] getTimeInRxSignalStrengthLevelMicros();
+ method @NonNull public long[] getTxTimeMillis();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.os.connectivity.CellularBatteryStats> CREATOR;
+ }
+
public final class WifiBatteryStats implements android.os.Parcelable {
method public int describeContents();
method public long getEnergyConsumedMaMillis();
@@ -8407,7 +8444,6 @@ package android.telephony {
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean enableDataConnectivity();
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean enableModemForSlot(int, boolean);
method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void enableVideoCalling(boolean);
- method @RequiresPermission(android.Manifest.permission.CONNECTIVITY_INTERNAL) public void factoryReset(int);
method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getAidForAppType(int);
method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.List<android.service.carrier.CarrierIdentifier> getAllowedCarriers(int);
method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.ImsiEncryptionInfo getCarrierInfoForImsiEncryption(int);
@@ -8466,6 +8502,7 @@ package android.telephony {
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void requestNumberVerification(@NonNull android.telephony.PhoneNumberRange, long, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.NumberVerificationCallback);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void resetCarrierKeysForImsiEncryption();
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean resetRadioConfig();
+ method @RequiresPermission(android.Manifest.permission.CONNECTIVITY_INTERNAL) public void resetSettings();
method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setAllowedCarriers(int, java.util.List<android.service.carrier.CarrierIdentifier>);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCarrierDataEnabled(boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setCarrierRestrictionRules(@NonNull android.telephony.CarrierRestrictionRules);
@@ -9083,20 +9120,20 @@ package android.telephony.ims {
public class ImsMmTelManager implements android.telephony.ims.RegistrationManager {
method @NonNull public static android.telephony.ims.ImsMmTelManager createForSubscriptionId(int);
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getFeatureState(@NonNull java.util.function.Consumer<java.lang.Integer>, @NonNull java.util.concurrent.Executor) throws android.telephony.ims.ImsException;
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getRegistrationState(@NonNull java.util.function.Consumer<java.lang.Integer>, @NonNull java.util.concurrent.Executor);
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getRegistrationTransportType(@NonNull java.util.function.Consumer<java.lang.Integer>, @NonNull java.util.concurrent.Executor);
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getRegistrationState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getRegistrationTransportType(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getVoWiFiModeSetting();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getVoWiFiRoamingModeSetting();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isAdvancedCallingSettingEnabled();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isAvailable(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int);
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isCapable(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int);
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void isSupported(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int, @NonNull java.util.function.Consumer<java.lang.Boolean>, @NonNull java.util.concurrent.Executor) throws android.telephony.ims.ImsException;
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void isSupported(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>) throws android.telephony.ims.ImsException;
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isTtyOverVolteEnabled();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isVoWiFiRoamingSettingEnabled();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isVoWiFiSettingEnabled();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isVtSettingEnabled();
method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerImsRegistrationCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ImsMmTelManager.RegistrationCallback) throws android.telephony.ims.ImsException;
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerImsRegistrationCallback(@NonNull android.telephony.ims.RegistrationManager.RegistrationCallback, @NonNull java.util.concurrent.Executor) throws android.telephony.ims.ImsException;
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerImsRegistrationCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.RegistrationManager.RegistrationCallback) throws android.telephony.ims.ImsException;
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerMmTelCapabilityCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ImsMmTelManager.CapabilityCallback) throws android.telephony.ims.ImsException;
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setAdvancedCallingSettingEnabled(boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setRttCapabilitySetting(boolean);
@@ -9556,9 +9593,9 @@ package android.telephony.ims {
}
public interface RegistrationManager {
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getRegistrationState(@NonNull java.util.function.Consumer<java.lang.Integer>, @NonNull java.util.concurrent.Executor);
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getRegistrationTransportType(@NonNull java.util.function.Consumer<java.lang.Integer>, @NonNull java.util.concurrent.Executor);
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerImsRegistrationCallback(@NonNull android.telephony.ims.RegistrationManager.RegistrationCallback, @NonNull java.util.concurrent.Executor) throws android.telephony.ims.ImsException;
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getRegistrationState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getRegistrationTransportType(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerImsRegistrationCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.RegistrationManager.RegistrationCallback) throws android.telephony.ims.ImsException;
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterImsRegistrationCallback(@NonNull android.telephony.ims.RegistrationManager.RegistrationCallback);
field public static final int REGISTRATION_STATE_NOT_REGISTERED = 0; // 0x0
field public static final int REGISTRATION_STATE_REGISTERED = 2; // 0x2
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index 67728840ada8..f91453ea0811 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -1301,8 +1301,8 @@ public class ActivityOptions {
/**
* Set's whether the activity launched with this option should be a task overlay. That is the
- * activity will always be the top activity of the task. If {@param canResume} is true, then
- * the task will also not be moved to the front of the stack.
+ * activity will always be the top activity of the task.
+ * @param canResume {@code false} if the task will also not be moved to the front of the stack.
* @hide
*/
@TestApi
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index efb9f6bb88f1..47118a81632e 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -17,7 +17,6 @@
package android.app;
import static android.annotation.Dimension.DP;
-import static android.graphics.drawable.Icon.TYPE_BITMAP;
import static com.android.internal.util.ContrastColorUtil.satisfiesTextContrast;
@@ -8741,26 +8740,20 @@ public class Notification implements Parcelable
* If your app produces multiple bubbles, the image should be unique for each of them.
* </p>
*
- * <p>The shape of a bubble icon is adaptive and can match the device theme.
+ * <p>The shape of a bubble icon is adaptive and will match the device theme.
*
- * If your icon is bitmap-based, you should create it using
- * {@link Icon#createWithAdaptiveBitmap(Bitmap)}, otherwise this method will throw.
- *
- * If your icon is not bitmap-based, you should expect that the icon will be tinted.
+ * Ideally your icon should be constructed via
+ * {@link Icon#createWithAdaptiveBitmap(Bitmap)}, otherwise, the icon will be shrunk
+ * and placed on an adaptive shape.
* </p>
*
- * @throws IllegalArgumentException if icon is null or a non-adaptive bitmap
+ * @throws IllegalArgumentException if icon is null.
*/
@NonNull
public BubbleMetadata.Builder setIcon(@NonNull Icon icon) {
if (icon == null) {
throw new IllegalArgumentException("Bubbles require non-null icon");
}
- if (icon.getType() == TYPE_BITMAP) {
- throw new IllegalArgumentException("When using bitmap based icons, Bubbles "
- + "require TYPE_ADAPTIVE_BITMAP, please use"
- + " Icon#createWithAdaptiveBitmap instead");
- }
mIcon = icon;
return this;
}
diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java
index 3ad88829b812..06b95067c2e8 100644
--- a/core/java/android/app/PendingIntent.java
+++ b/core/java/android/app/PendingIntent.java
@@ -1274,7 +1274,12 @@ public final class PendingIntent implements Parcelable {
return b != null ? new PendingIntent(b, in.getClassCookie(PendingIntent.class)) : null;
}
- /*package*/ PendingIntent(IIntentSender target) {
+ /**
+ * Creates a PendingIntent with the given target.
+ * @param target the backing IIntentSender
+ * @hide
+ */
+ public PendingIntent(IIntentSender target) {
mTarget = target;
}
diff --git a/core/java/android/os/BasicShellCommandHandler.java b/core/java/android/os/BasicShellCommandHandler.java
new file mode 100644
index 000000000000..5bd5d61b6361
--- /dev/null
+++ b/core/java/android/os/BasicShellCommandHandler.java
@@ -0,0 +1,320 @@
+/*
+ * 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.
+ */
+
+package android.os;
+
+import android.util.Log;
+
+import java.io.BufferedInputStream;
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+
+/**
+ * Helper for implementing {@link Binder#onShellCommand Binder.onShellCommand}. This is meant to
+ * be copied into mainline modules, so this class must not use any hidden APIs.
+ *
+ * @hide
+ */
+public abstract class BasicShellCommandHandler {
+ static final String TAG = "ShellCommand";
+ static final boolean DEBUG = false;
+
+ private Binder mTarget;
+ private FileDescriptor mIn;
+ private FileDescriptor mOut;
+ private FileDescriptor mErr;
+ private String[] mArgs;
+
+ private String mCmd;
+ private int mArgPos;
+ private String mCurArgData;
+
+ private FileInputStream mFileIn;
+ private FileOutputStream mFileOut;
+ private FileOutputStream mFileErr;
+
+ private PrintWriter mOutPrintWriter;
+ private PrintWriter mErrPrintWriter;
+ private InputStream mInputStream;
+
+ public void init(Binder target, FileDescriptor in, FileDescriptor out, FileDescriptor err,
+ String[] args, int firstArgPos) {
+ mTarget = target;
+ mIn = in;
+ mOut = out;
+ mErr = err;
+ mArgs = args;
+ mCmd = null;
+ mArgPos = firstArgPos;
+ mCurArgData = null;
+ mFileIn = null;
+ mFileOut = null;
+ mFileErr = null;
+ mOutPrintWriter = null;
+ mErrPrintWriter = null;
+ mInputStream = null;
+ }
+
+ public int exec(Binder target, FileDescriptor in, FileDescriptor out, FileDescriptor err,
+ String[] args) {
+ String cmd;
+ int start;
+ if (args != null && args.length > 0) {
+ cmd = args[0];
+ start = 1;
+ } else {
+ cmd = null;
+ start = 0;
+ }
+ init(target, in, out, err, args, start);
+ mCmd = cmd;
+
+ if (DEBUG) {
+ RuntimeException here = new RuntimeException("here");
+ here.fillInStackTrace();
+ Log.d(TAG, "Starting command " + mCmd + " on " + mTarget, here);
+ Log.d(TAG, "Calling uid=" + Binder.getCallingUid()
+ + " pid=" + Binder.getCallingPid());
+ }
+ int res = -1;
+ try {
+ res = onCommand(mCmd);
+ if (DEBUG) Log.d(TAG, "Executed command " + mCmd + " on " + mTarget);
+ } catch (Throwable e) {
+ // Unlike usual calls, in this case if an exception gets thrown
+ // back to us we want to print it back in to the dump data, since
+ // that is where the caller expects all interesting information to
+ // go.
+ PrintWriter eout = getErrPrintWriter();
+ eout.println();
+ eout.println("Exception occurred while executing: " + e.getMessage());
+ e.printStackTrace(eout);
+ } finally {
+ if (DEBUG) Log.d(TAG, "Flushing output streams on " + mTarget);
+ if (mOutPrintWriter != null) {
+ mOutPrintWriter.flush();
+ }
+ if (mErrPrintWriter != null) {
+ mErrPrintWriter.flush();
+ }
+ if (DEBUG) Log.d(TAG, "Sending command result on " + mTarget);
+ }
+ if (DEBUG) Log.d(TAG, "Finished command " + mCmd + " on " + mTarget);
+ return res;
+ }
+
+ /**
+ * Return the raw FileDescriptor for the output stream.
+ */
+ public FileDescriptor getOutFileDescriptor() {
+ return mOut;
+ }
+
+ /**
+ * Return direct raw access (not buffered) to the command's output data stream.
+ */
+ public OutputStream getRawOutputStream() {
+ if (mFileOut == null) {
+ mFileOut = new FileOutputStream(mOut);
+ }
+ return mFileOut;
+ }
+
+ /**
+ * Return a PrintWriter for formatting output to {@link #getRawOutputStream()}.
+ */
+ public PrintWriter getOutPrintWriter() {
+ if (mOutPrintWriter == null) {
+ mOutPrintWriter = new PrintWriter(getRawOutputStream());
+ }
+ return mOutPrintWriter;
+ }
+
+ /**
+ * Return the raw FileDescriptor for the error stream.
+ */
+ public FileDescriptor getErrFileDescriptor() {
+ return mErr;
+ }
+
+ /**
+ * Return direct raw access (not buffered) to the command's error output data stream.
+ */
+ public OutputStream getRawErrorStream() {
+ if (mFileErr == null) {
+ mFileErr = new FileOutputStream(mErr);
+ }
+ return mFileErr;
+ }
+
+ /**
+ * Return a PrintWriter for formatting output to {@link #getRawErrorStream()}.
+ */
+ public PrintWriter getErrPrintWriter() {
+ if (mErr == null) {
+ return getOutPrintWriter();
+ }
+ if (mErrPrintWriter == null) {
+ mErrPrintWriter = new PrintWriter(getRawErrorStream());
+ }
+ return mErrPrintWriter;
+ }
+
+ /**
+ * Return the raw FileDescriptor for the input stream.
+ */
+ public FileDescriptor getInFileDescriptor() {
+ return mIn;
+ }
+
+ /**
+ * Return direct raw access (not buffered) to the command's input data stream.
+ */
+ public InputStream getRawInputStream() {
+ if (mFileIn == null) {
+ mFileIn = new FileInputStream(mIn);
+ }
+ return mFileIn;
+ }
+
+ /**
+ * Return buffered access to the command's {@link #getRawInputStream()}.
+ */
+ public InputStream getBufferedInputStream() {
+ if (mInputStream == null) {
+ mInputStream = new BufferedInputStream(getRawInputStream());
+ }
+ return mInputStream;
+ }
+
+ /**
+ * Return the next option on the command line -- that is an argument that
+ * starts with '-'. If the next argument is not an option, null is returned.
+ */
+ public String getNextOption() {
+ if (mCurArgData != null) {
+ String prev = mArgs[mArgPos - 1];
+ throw new IllegalArgumentException("No argument expected after \"" + prev + "\"");
+ }
+ if (mArgPos >= mArgs.length) {
+ return null;
+ }
+ String arg = mArgs[mArgPos];
+ if (!arg.startsWith("-")) {
+ return null;
+ }
+ mArgPos++;
+ if (arg.equals("--")) {
+ return null;
+ }
+ if (arg.length() > 1 && arg.charAt(1) != '-') {
+ if (arg.length() > 2) {
+ mCurArgData = arg.substring(2);
+ return arg.substring(0, 2);
+ } else {
+ mCurArgData = null;
+ return arg;
+ }
+ }
+ mCurArgData = null;
+ return arg;
+ }
+
+ /**
+ * Return the next argument on the command line, whatever it is; if there are
+ * no arguments left, return null.
+ */
+ public String getNextArg() {
+ if (mCurArgData != null) {
+ String arg = mCurArgData;
+ mCurArgData = null;
+ return arg;
+ } else if (mArgPos < mArgs.length) {
+ return mArgs[mArgPos++];
+ } else {
+ return null;
+ }
+ }
+
+ public String peekNextArg() {
+ if (mCurArgData != null) {
+ return mCurArgData;
+ } else if (mArgPos < mArgs.length) {
+ return mArgs[mArgPos];
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Return the next argument on the command line, whatever it is; if there are
+ * no arguments left, throws an IllegalArgumentException to report this to the user.
+ */
+ public String getNextArgRequired() {
+ String arg = getNextArg();
+ if (arg == null) {
+ String prev = mArgs[mArgPos - 1];
+ throw new IllegalArgumentException("Argument expected after \"" + prev + "\"");
+ }
+ return arg;
+ }
+
+ public int handleDefaultCommands(String cmd) {
+ if (cmd == null || "help".equals(cmd) || "-h".equals(cmd)) {
+ onHelp();
+ } else {
+ getOutPrintWriter().println("Unknown command: " + cmd);
+ }
+ return -1;
+ }
+
+ public Binder getTarget() {
+ return mTarget;
+ }
+
+ public String[] getAllArgs() {
+ return mArgs;
+ }
+
+ /**
+ * Implement parsing and execution of a command. If it isn't a command you understand,
+ * call {@link #handleDefaultCommands(String)} and return its result as a last resort.
+ * Use {@link #getNextOption()}, {@link #getNextArg()}, and {@link #getNextArgRequired()}
+ * to process additional command line arguments. Command output can be written to
+ * {@link #getOutPrintWriter()} and errors to {@link #getErrPrintWriter()}.
+ *
+ * <p class="caution">Note that no permission checking has been done before entering this
+ * function, so you need to be sure to do your own security verification for any commands you
+ * are executing. The easiest way to do this is to have the ShellCommand contain
+ * only a reference to your service's aidl interface, and do all of your command
+ * implementations on top of that -- that way you can rely entirely on your executing security
+ * code behind that interface.</p>
+ *
+ * @param cmd The first command line argument representing the name of the command to execute.
+ * @return Return the command result; generally 0 or positive indicates success and
+ * negative values indicate error.
+ */
+ public abstract int onCommand(String cmd);
+
+ /**
+ * Implement this to print help text about your command to {@link #getOutPrintWriter()}.
+ */
+ public abstract void onHelp();
+}
diff --git a/core/java/android/os/BatteryStatsManager.java b/core/java/android/os/BatteryStatsManager.java
index 367a868ddef4..e5650aea0522 100644
--- a/core/java/android/os/BatteryStatsManager.java
+++ b/core/java/android/os/BatteryStatsManager.java
@@ -23,6 +23,7 @@ import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.content.Context;
+import android.os.connectivity.CellularBatteryStats;
import android.os.connectivity.WifiBatteryStats;
import com.android.internal.app.IBatteryStats;
@@ -158,6 +159,21 @@ public class BatteryStatsManager {
}
/**
+ * Retrieves all the cellular related battery stats.
+ *
+ * @return Instance of {@link CellularBatteryStats}.
+ */
+ @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS)
+ public @NonNull CellularBatteryStats getCellularBatteryStats() {
+ try {
+ return mBatteryStats.getCellularBatteryStats();
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ return null;
+ }
+ }
+
+ /**
* Retrieves all the wifi related battery stats.
*
* @return Instance of {@link WifiBatteryStats}.
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java
index ef3afabfe878..a856975e2501 100644
--- a/core/java/android/os/Binder.java
+++ b/core/java/android/os/Binder.java
@@ -37,7 +37,9 @@ import libcore.io.IoUtils;
import libcore.util.NativeAllocationRegistry;
import java.io.FileDescriptor;
+import java.io.FileInputStream;
import java.io.FileOutputStream;
+import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Modifier;
@@ -905,11 +907,60 @@ public class Binder implements IBinder {
@Nullable FileDescriptor err,
@NonNull String[] args, @Nullable ShellCallback callback,
@NonNull ResultReceiver resultReceiver) throws RemoteException {
- FileOutputStream fout = new FileOutputStream(err != null ? err : out);
- PrintWriter pw = new FastPrintWriter(fout);
+
+ // First, convert in, out and err to @NonNull, by redirecting any that's null to /dev/null.
+ try {
+ if (in == null) {
+ in = new FileInputStream("/dev/null").getFD();
+ }
+ if (out == null) {
+ out = new FileOutputStream("/dev/null").getFD();
+ }
+ if (err == null) {
+ err = out;
+ }
+ } catch (IOException e) {
+ PrintWriter pw = new FastPrintWriter(new FileOutputStream(err != null ? err : out));
+ pw.println("Failed to open /dev/null: " + e.getMessage());
+ pw.flush();
+ resultReceiver.send(-1, null);
+ return;
+ }
+ // Also make args @NonNull.
+ if (args == null) {
+ args = new String[0];
+ }
+
+ int result = -1;
+ try {
+ result = handleShellCommand(in, out, err, args);
+ } finally {
+ resultReceiver.send(result, null);
+ }
+ }
+
+ /**
+ * System services can implement this method to implement ADB shell commands.
+ *
+ * TODO More Javadoc.
+ * TODO Add a generic way to define subcommands and their permissions.
+ *
+ * @param in standard input.
+ * @param out standard output.
+ * @param err standard error.
+ * @param args arguments passed to the command. Can be empty. The first argument is typically
+ * a subcommand, such as {@code run} for {@code adb shell cmd jobscheduler run}.
+ *
+ * @hide
+ */
+ // @SystemApi TODO Make it a system API.
+ protected int handleShellCommand(@NonNull FileDescriptor in, @NonNull FileDescriptor out,
+ @NonNull FileDescriptor err, @NonNull String[] args) {
+ FileOutputStream ferr = new FileOutputStream(err);
+ PrintWriter pw = new FastPrintWriter(ferr);
pw.println("No shell command implementation.");
pw.flush();
- resultReceiver.send(0, null);
+ return 0;
}
/**
diff --git a/core/java/android/os/ShellCommand.java b/core/java/android/os/ShellCommand.java
index 2fe8726a0915..f3a6869687dc 100644
--- a/core/java/android/os/ShellCommand.java
+++ b/core/java/android/os/ShellCommand.java
@@ -33,105 +33,21 @@ import java.io.PrintWriter;
* Helper for implementing {@link Binder#onShellCommand Binder.onShellCommand}.
* @hide
*/
-public abstract class ShellCommand {
- static final String TAG = "ShellCommand";
- static final boolean DEBUG = false;
-
- private Binder mTarget;
- private FileDescriptor mIn;
- private FileDescriptor mOut;
- private FileDescriptor mErr;
- private String[] mArgs;
+public abstract class ShellCommand extends BasicShellCommandHandler {
private ShellCallback mShellCallback;
private ResultReceiver mResultReceiver;
- private String mCmd;
- private int mArgPos;
- private String mCurArgData;
-
- private FileInputStream mFileIn;
- private FileOutputStream mFileOut;
- private FileOutputStream mFileErr;
-
- private FastPrintWriter mOutPrintWriter;
- private FastPrintWriter mErrPrintWriter;
- private InputStream mInputStream;
-
- public void init(Binder target, FileDescriptor in, FileDescriptor out, FileDescriptor err,
- String[] args, ShellCallback callback, int firstArgPos) {
- mTarget = target;
- mIn = in;
- mOut = out;
- mErr = err;
- mArgs = args;
- mShellCallback = callback;
- mResultReceiver = null;
- mCmd = null;
- mArgPos = firstArgPos;
- mCurArgData = null;
- mFileIn = null;
- mFileOut = null;
- mFileErr = null;
- mOutPrintWriter = null;
- mErrPrintWriter = null;
- mInputStream = null;
- }
-
public int exec(Binder target, FileDescriptor in, FileDescriptor out, FileDescriptor err,
String[] args, ShellCallback callback, ResultReceiver resultReceiver) {
- String cmd;
- int start;
- if (args != null && args.length > 0) {
- cmd = args[0];
- start = 1;
- } else {
- cmd = null;
- start = 0;
- }
- init(target, in, out, err, args, callback, start);
- mCmd = cmd;
+ mShellCallback = callback;
mResultReceiver = resultReceiver;
+ final int result = super.exec(target, in, out, err, args);
- if (DEBUG) {
- RuntimeException here = new RuntimeException("here");
- here.fillInStackTrace();
- Slog.d(TAG, "Starting command " + mCmd + " on " + mTarget, here);
- Slog.d(TAG, "Calling uid=" + Binder.getCallingUid()
- + " pid=" + Binder.getCallingPid() + " ShellCallback=" + getShellCallback());
+ if (mResultReceiver != null) {
+ mResultReceiver.send(result, null);
}
- int res = -1;
- try {
- res = onCommand(mCmd);
- if (DEBUG) Slog.d(TAG, "Executed command " + mCmd + " on " + mTarget);
- } catch (SecurityException e) {
- PrintWriter eout = getErrPrintWriter();
- eout.println("Security exception: " + e.getMessage());
- eout.println();
- e.printStackTrace(eout);
- } catch (Throwable e) {
- // Unlike usual calls, in this case if an exception gets thrown
- // back to us we want to print it back in to the dump data, since
- // that is where the caller expects all interesting information to
- // go.
- PrintWriter eout = getErrPrintWriter();
- eout.println();
- eout.println("Exception occurred while executing:");
- e.printStackTrace(eout);
- } finally {
- if (DEBUG) Slog.d(TAG, "Flushing output streams on " + mTarget);
- if (mOutPrintWriter != null) {
- mOutPrintWriter.flush();
- }
- if (mErrPrintWriter != null) {
- mErrPrintWriter.flush();
- }
- if (DEBUG) Slog.d(TAG, "Sending command result on " + mTarget);
- if (mResultReceiver != null) {
- mResultReceiver.send(res, null);
- }
- }
- if (DEBUG) Slog.d(TAG, "Finished command " + mCmd + " on " + mTarget);
- return res;
+
+ return result;
}
/**
@@ -146,90 +62,6 @@ public abstract class ShellCommand {
}
/**
- * Return the raw FileDescriptor for the output stream.
- */
- public FileDescriptor getOutFileDescriptor() {
- return mOut;
- }
-
- /**
- * Return direct raw access (not buffered) to the command's output data stream.
- */
- public OutputStream getRawOutputStream() {
- if (mFileOut == null) {
- mFileOut = new FileOutputStream(mOut);
- }
- return mFileOut;
- }
-
- /**
- * Return a PrintWriter for formatting output to {@link #getRawOutputStream()}.
- */
- public PrintWriter getOutPrintWriter() {
- if (mOutPrintWriter == null) {
- mOutPrintWriter = new FastPrintWriter(getRawOutputStream());
- }
- return mOutPrintWriter;
- }
-
- /**
- * Return the raw FileDescriptor for the error stream.
- */
- public FileDescriptor getErrFileDescriptor() {
- return mErr;
- }
-
- /**
- * Return direct raw access (not buffered) to the command's error output data stream.
- */
- public OutputStream getRawErrorStream() {
- if (mFileErr == null) {
- mFileErr = new FileOutputStream(mErr);
- }
- return mFileErr;
- }
-
- /**
- * Return a PrintWriter for formatting output to {@link #getRawErrorStream()}.
- */
- public PrintWriter getErrPrintWriter() {
- if (mErr == null) {
- return getOutPrintWriter();
- }
- if (mErrPrintWriter == null) {
- mErrPrintWriter = new FastPrintWriter(getRawErrorStream());
- }
- return mErrPrintWriter;
- }
-
- /**
- * Return the raw FileDescriptor for the input stream.
- */
- public FileDescriptor getInFileDescriptor() {
- return mIn;
- }
-
- /**
- * Return direct raw access (not buffered) to the command's input data stream.
- */
- public InputStream getRawInputStream() {
- if (mFileIn == null) {
- mFileIn = new FileInputStream(mIn);
- }
- return mFileIn;
- }
-
- /**
- * Return buffered access to the command's {@link #getRawInputStream()}.
- */
- public InputStream getBufferedInputStream() {
- if (mInputStream == null) {
- mInputStream = new BufferedInputStream(getRawInputStream());
- }
- return mInputStream;
- }
-
- /**
* Helper for just system services to ask the shell to open an output file.
* @hide
*/
@@ -256,77 +88,19 @@ public abstract class ShellCommand {
return null;
}
- /**
- * Return the next option on the command line -- that is an argument that
- * starts with '-'. If the next argument is not an option, null is returned.
- */
- public String getNextOption() {
- if (mCurArgData != null) {
- String prev = mArgs[mArgPos - 1];
- throw new IllegalArgumentException("No argument expected after \"" + prev + "\"");
- }
- if (mArgPos >= mArgs.length) {
- return null;
- }
- String arg = mArgs[mArgPos];
- if (!arg.startsWith("-")) {
- return null;
- }
- mArgPos++;
- if (arg.equals("--")) {
- return null;
- }
- if (arg.length() > 1 && arg.charAt(1) != '-') {
- if (arg.length() > 2) {
- mCurArgData = arg.substring(2);
- return arg.substring(0, 2);
- } else {
- mCurArgData = null;
- return arg;
- }
- }
- mCurArgData = null;
- return arg;
- }
-
- /**
- * Return the next argument on the command line, whatever it is; if there are
- * no arguments left, return null.
- */
- public String getNextArg() {
- if (mCurArgData != null) {
- String arg = mCurArgData;
- mCurArgData = null;
- return arg;
- } else if (mArgPos < mArgs.length) {
- return mArgs[mArgPos++];
- } else {
- return null;
+ public int handleDefaultCommands(String cmd) {
+ if ("dump".equals(cmd)) {
+ String[] newArgs = new String[getAllArgs().length-1];
+ System.arraycopy(getAllArgs(), 1, newArgs, 0, getAllArgs().length-1);
+ getTarget().doDump(getOutFileDescriptor(), getOutPrintWriter(), newArgs);
+ return 0;
}
+ return super.handleDefaultCommands(cmd);
}
@UnsupportedAppUsage
public String peekNextArg() {
- if (mCurArgData != null) {
- return mCurArgData;
- } else if (mArgPos < mArgs.length) {
- return mArgs[mArgPos];
- } else {
- return null;
- }
- }
-
- /**
- * Return the next argument on the command line, whatever it is; if there are
- * no arguments left, throws an IllegalArgumentException to report this to the user.
- */
- public String getNextArgRequired() {
- String arg = getNextArg();
- if (arg == null) {
- String prev = mArgs[mArgPos - 1];
- throw new IllegalArgumentException("Argument expected after \"" + prev + "\"");
- }
- return arg;
+ return super.peekNextArg();
}
/**
@@ -335,43 +109,4 @@ public abstract class ShellCommand {
public ShellCallback getShellCallback() {
return mShellCallback;
}
-
- public int handleDefaultCommands(String cmd) {
- if ("dump".equals(cmd)) {
- String[] newArgs = new String[mArgs.length-1];
- System.arraycopy(mArgs, 1, newArgs, 0, mArgs.length-1);
- mTarget.doDump(mOut, getOutPrintWriter(), newArgs);
- return 0;
- } else if (cmd == null || "help".equals(cmd) || "-h".equals(cmd)) {
- onHelp();
- } else {
- getOutPrintWriter().println("Unknown command: " + cmd);
- }
- return -1;
- }
-
- /**
- * Implement parsing and execution of a command. If it isn't a command you understand,
- * call {@link #handleDefaultCommands(String)} and return its result as a last resort.
- * Use {@link #getNextOption()}, {@link #getNextArg()}, and {@link #getNextArgRequired()}
- * to process additional command line arguments. Command output can be written to
- * {@link #getOutPrintWriter()} and errors to {@link #getErrPrintWriter()}.
- *
- * <p class="caution">Note that no permission checking has been done before entering this function,
- * so you need to be sure to do your own security verification for any commands you
- * are executing. The easiest way to do this is to have the ShellCommand contain
- * only a reference to your service's aidl interface, and do all of your command
- * implementations on top of that -- that way you can rely entirely on your executing security
- * code behind that interface.</p>
- *
- * @param cmd The first command line argument representing the name of the command to execute.
- * @return Return the command result; generally 0 or positive indicates success and
- * negative values indicate error.
- */
- public abstract int onCommand(String cmd);
-
- /**
- * Implement this to print help text about your command to {@link #getOutPrintWriter()}.
- */
- public abstract void onHelp();
}
diff --git a/core/java/android/os/connectivity/CellularBatteryStats.java b/core/java/android/os/connectivity/CellularBatteryStats.java
index 2e0904048d40..caa406899161 100644
--- a/core/java/android/os/connectivity/CellularBatteryStats.java
+++ b/core/java/android/os/connectivity/CellularBatteryStats.java
@@ -15,241 +15,367 @@
*/
package android.os.connectivity;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
import android.os.BatteryStats;
import android.os.Parcel;
import android.os.Parcelable;
-
+import android.telephony.Annotation.NetworkType;
import android.telephony.ModemActivityInfo;
import android.telephony.SignalStrength;
import java.util.Arrays;
+import java.util.Objects;
/**
* API for Cellular power stats
*
* @hide
*/
+@SystemApi
public final class CellularBatteryStats implements Parcelable {
- private long mLoggingDurationMs;
- private long mKernelActiveTimeMs;
- private long mNumPacketsTx;
- private long mNumBytesTx;
- private long mNumPacketsRx;
- private long mNumBytesRx;
- private long mSleepTimeMs;
- private long mIdleTimeMs;
- private long mRxTimeMs;
- private long mEnergyConsumedMaMs;
- private long[] mTimeInRatMs;
- private long[] mTimeInRxSignalStrengthLevelMs;
- private long[] mTxTimeMs;
- private long mMonitoredRailChargeConsumedMaMs;
-
- public static final @android.annotation.NonNull Parcelable.Creator<CellularBatteryStats> CREATOR = new
- Parcelable.Creator<CellularBatteryStats>() {
- public CellularBatteryStats createFromParcel(Parcel in) {
- return new CellularBatteryStats(in);
- }
-
- public CellularBatteryStats[] newArray(int size) {
- return new CellularBatteryStats[size];
- }
- };
-
- public CellularBatteryStats() {
- initialize();
- }
-
- public void writeToParcel(Parcel out, int flags) {
- out.writeLong(mLoggingDurationMs);
- out.writeLong(mKernelActiveTimeMs);
- out.writeLong(mNumPacketsTx);
- out.writeLong(mNumBytesTx);
- out.writeLong(mNumPacketsRx);
- out.writeLong(mNumBytesRx);
- out.writeLong(mSleepTimeMs);
- out.writeLong(mIdleTimeMs);
- out.writeLong(mRxTimeMs);
- out.writeLong(mEnergyConsumedMaMs);
- out.writeLongArray(mTimeInRatMs);
- out.writeLongArray(mTimeInRxSignalStrengthLevelMs);
- out.writeLongArray(mTxTimeMs);
- out.writeLong(mMonitoredRailChargeConsumedMaMs);
- }
-
- public void readFromParcel(Parcel in) {
- mLoggingDurationMs = in.readLong();
- mKernelActiveTimeMs = in.readLong();
- mNumPacketsTx = in.readLong();
- mNumBytesTx = in.readLong();
- mNumPacketsRx = in.readLong();
- mNumBytesRx = in.readLong();
- mSleepTimeMs = in.readLong();
- mIdleTimeMs = in.readLong();
- mRxTimeMs = in.readLong();
- mEnergyConsumedMaMs = in.readLong();
- in.readLongArray(mTimeInRatMs);
- in.readLongArray(mTimeInRxSignalStrengthLevelMs);
- in.readLongArray(mTxTimeMs);
- mMonitoredRailChargeConsumedMaMs = in.readLong();
- }
-
- public long getLoggingDurationMs() {
- return mLoggingDurationMs;
- }
-
- public long getKernelActiveTimeMs() {
- return mKernelActiveTimeMs;
- }
-
- public long getNumPacketsTx() {
- return mNumPacketsTx;
- }
-
- public long getNumBytesTx() {
- return mNumBytesTx;
- }
-
- public long getNumPacketsRx() {
- return mNumPacketsRx;
- }
-
- public long getNumBytesRx() {
- return mNumBytesRx;
- }
-
- public long getSleepTimeMs() {
- return mSleepTimeMs;
- }
-
- public long getIdleTimeMs() {
- return mIdleTimeMs;
- }
-
- public long getRxTimeMs() {
- return mRxTimeMs;
- }
-
- public long getEnergyConsumedMaMs() {
- return mEnergyConsumedMaMs;
- }
-
- public long[] getTimeInRatMs() {
- return mTimeInRatMs;
- }
-
- public long[] getTimeInRxSignalStrengthLevelMs() {
- return mTimeInRxSignalStrengthLevelMs;
- }
-
- public long[] getTxTimeMs() {
- return mTxTimeMs;
- }
-
- public long getMonitoredRailChargeConsumedMaMs() {
- return mMonitoredRailChargeConsumedMaMs;
- }
-
- public void setLoggingDurationMs(long t) {
- mLoggingDurationMs = t;
- return;
- }
-
- public void setKernelActiveTimeMs(long t) {
- mKernelActiveTimeMs = t;
- return;
- }
-
- public void setNumPacketsTx(long n) {
- mNumPacketsTx = n;
- return;
- }
-
- public void setNumBytesTx(long b) {
- mNumBytesTx = b;
- return;
- }
-
- public void setNumPacketsRx(long n) {
- mNumPacketsRx = n;
- return;
- }
-
- public void setNumBytesRx(long b) {
- mNumBytesRx = b;
- return;
- }
-
- public void setSleepTimeMs(long t) {
- mSleepTimeMs = t;
- return;
- }
-
- public void setIdleTimeMs(long t) {
- mIdleTimeMs = t;
- return;
- }
-
- public void setRxTimeMs(long t) {
- mRxTimeMs = t;
- return;
- }
-
- public void setEnergyConsumedMaMs(long e) {
- mEnergyConsumedMaMs = e;
- return;
- }
-
- public void setTimeInRatMs(long[] t) {
- mTimeInRatMs = Arrays.copyOfRange(t, 0,
- Math.min(t.length, BatteryStats.NUM_DATA_CONNECTION_TYPES));
- return;
- }
-
- public void setTimeInRxSignalStrengthLevelMs(long[] t) {
- mTimeInRxSignalStrengthLevelMs = Arrays.copyOfRange(t, 0,
- Math.min(t.length, SignalStrength.NUM_SIGNAL_STRENGTH_BINS));
- return;
- }
-
- public void setTxTimeMs(long[] t) {
- mTxTimeMs = Arrays.copyOfRange(t, 0, Math.min(t.length, ModemActivityInfo.TX_POWER_LEVELS));
- return;
- }
-
- public void setMonitoredRailChargeConsumedMaMs(long monitoredRailEnergyConsumedMaMs) {
- mMonitoredRailChargeConsumedMaMs = monitoredRailEnergyConsumedMaMs;
- return;
- }
-
- public int describeContents() {
- return 0;
- }
-
- private CellularBatteryStats(Parcel in) {
- initialize();
- readFromParcel(in);
- }
-
- private void initialize() {
- mLoggingDurationMs = 0;
- mKernelActiveTimeMs = 0;
- mNumPacketsTx = 0;
- mNumBytesTx = 0;
- mNumPacketsRx = 0;
- mNumBytesRx = 0;
- mSleepTimeMs = 0;
- mIdleTimeMs = 0;
- mRxTimeMs = 0;
- mEnergyConsumedMaMs = 0;
- mTimeInRatMs = new long[BatteryStats.NUM_DATA_CONNECTION_TYPES];
- Arrays.fill(mTimeInRatMs, 0);
- mTimeInRxSignalStrengthLevelMs = new long[SignalStrength.NUM_SIGNAL_STRENGTH_BINS];
- Arrays.fill(mTimeInRxSignalStrengthLevelMs, 0);
- mTxTimeMs = new long[ModemActivityInfo.TX_POWER_LEVELS];
- Arrays.fill(mTxTimeMs, 0);
- mMonitoredRailChargeConsumedMaMs = 0;
- return;
- }
-} \ No newline at end of file
+ private long mLoggingDurationMs = 0;
+ private long mKernelActiveTimeMs = 0;
+ private long mNumPacketsTx = 0;
+ private long mNumBytesTx = 0;
+ private long mNumPacketsRx = 0;
+ private long mNumBytesRx = 0;
+ private long mSleepTimeMs = 0;
+ private long mIdleTimeMs = 0;
+ private long mRxTimeMs = 0;
+ private long mEnergyConsumedMaMs = 0;
+ private long[] mTimeInRatMs = new long[BatteryStats.NUM_DATA_CONNECTION_TYPES];
+ private long[] mTimeInRxSignalStrengthLevelMs =
+ new long[SignalStrength.NUM_SIGNAL_STRENGTH_BINS];
+ private long[] mTxTimeMs = new long[ModemActivityInfo.TX_POWER_LEVELS];
+ private long mMonitoredRailChargeConsumedMaMs = 0;
+
+ public static final @NonNull Parcelable.Creator<CellularBatteryStats> CREATOR =
+ new Parcelable.Creator<CellularBatteryStats>() {
+ public CellularBatteryStats createFromParcel(Parcel in) {
+ return new CellularBatteryStats(in);
+ }
+
+ public CellularBatteryStats[] newArray(int size) {
+ return new CellularBatteryStats[size];
+ }
+ };
+
+ /** @hide **/
+ public CellularBatteryStats() {}
+
+ @Override
+ public void writeToParcel(@NonNull Parcel out, int flags) {
+ out.writeLong(mLoggingDurationMs);
+ out.writeLong(mKernelActiveTimeMs);
+ out.writeLong(mNumPacketsTx);
+ out.writeLong(mNumBytesTx);
+ out.writeLong(mNumPacketsRx);
+ out.writeLong(mNumBytesRx);
+ out.writeLong(mSleepTimeMs);
+ out.writeLong(mIdleTimeMs);
+ out.writeLong(mRxTimeMs);
+ out.writeLong(mEnergyConsumedMaMs);
+ out.writeLongArray(mTimeInRatMs);
+ out.writeLongArray(mTimeInRxSignalStrengthLevelMs);
+ out.writeLongArray(mTxTimeMs);
+ out.writeLong(mMonitoredRailChargeConsumedMaMs);
+ }
+
+ private void readFromParcel(Parcel in) {
+ mLoggingDurationMs = in.readLong();
+ mKernelActiveTimeMs = in.readLong();
+ mNumPacketsTx = in.readLong();
+ mNumBytesTx = in.readLong();
+ mNumPacketsRx = in.readLong();
+ mNumBytesRx = in.readLong();
+ mSleepTimeMs = in.readLong();
+ mIdleTimeMs = in.readLong();
+ mRxTimeMs = in.readLong();
+ mEnergyConsumedMaMs = in.readLong();
+ in.readLongArray(mTimeInRatMs);
+ in.readLongArray(mTimeInRxSignalStrengthLevelMs);
+ in.readLongArray(mTxTimeMs);
+ mMonitoredRailChargeConsumedMaMs = in.readLong();
+ }
+
+ @Override
+ public boolean equals(@Nullable Object other) {
+ if (!(other instanceof CellularBatteryStats)) return false;
+ if (other == this) return true;
+ CellularBatteryStats otherStats = (CellularBatteryStats) other;
+ return this.mLoggingDurationMs == otherStats.mLoggingDurationMs
+ && this.mKernelActiveTimeMs == otherStats.mKernelActiveTimeMs
+ && this.mNumPacketsTx == otherStats.mNumPacketsTx
+ && this.mNumBytesTx == otherStats.mNumBytesTx
+ && this.mNumPacketsRx == otherStats.mNumPacketsRx
+ && this.mNumBytesRx == otherStats.mNumBytesRx
+ && this.mSleepTimeMs == otherStats.mSleepTimeMs
+ && this.mIdleTimeMs == otherStats.mIdleTimeMs
+ && this.mRxTimeMs == otherStats.mRxTimeMs
+ && this.mEnergyConsumedMaMs == otherStats.mEnergyConsumedMaMs
+ && Arrays.equals(this.mTimeInRatMs, otherStats.mTimeInRatMs)
+ && Arrays.equals(this.mTimeInRxSignalStrengthLevelMs,
+ otherStats.mTimeInRxSignalStrengthLevelMs)
+ && Arrays.equals(this.mTxTimeMs, otherStats.mTxTimeMs)
+ && this.mMonitoredRailChargeConsumedMaMs
+ == otherStats.mMonitoredRailChargeConsumedMaMs;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mLoggingDurationMs, mKernelActiveTimeMs, mNumPacketsTx,
+ mNumBytesTx, mNumPacketsRx, mNumBytesRx, mSleepTimeMs, mIdleTimeMs,
+ mRxTimeMs, mEnergyConsumedMaMs, Arrays.hashCode(mTimeInRatMs),
+ Arrays.hashCode(mTimeInRxSignalStrengthLevelMs), Arrays.hashCode(mTxTimeMs),
+ mMonitoredRailChargeConsumedMaMs);
+ }
+
+ /**
+ * Returns the duration for which these cellular stats were collected.
+ *
+ * @return Duration of stats collection in milliseconds.
+ */
+ public long getLoggingDurationMillis() {
+ return mLoggingDurationMs;
+ }
+
+ /**
+ * Returns the duration for which the kernel was active within
+ * {@link #getLoggingDurationMillis()}.
+ *
+ * @return Duration of kernel active time in milliseconds.
+ */
+ public long getKernelActiveTimeMillis() {
+ return mKernelActiveTimeMs;
+ }
+
+ /**
+ * Returns the number of packets transmitted over cellular within
+ * {@link #getLoggingDurationMillis()}.
+ *
+ * @return Number of packets transmitted.
+ */
+ public long getNumPacketsTx() {
+ return mNumPacketsTx;
+ }
+
+ /**
+ * Returns the number of packets received over cellular within
+ * {@link #getLoggingDurationMillis()}.
+ *
+ * @return Number of packets received.
+ */
+ public long getNumBytesTx() {
+ return mNumBytesTx;
+ }
+
+ /**
+ * Returns the number of bytes transmitted over cellular within
+ * {@link #getLoggingDurationMillis()}.
+ *
+ * @return Number of bytes transmitted.
+ */
+ public long getNumPacketsRx() {
+ return mNumPacketsRx;
+ }
+
+ /**
+ * Returns the number of bytes received over cellular within
+ * {@link #getLoggingDurationMillis()}.
+ *
+ * @return Number of bytes received.
+ */
+ public long getNumBytesRx() {
+ return mNumBytesRx;
+ }
+
+ /**
+ * Returns the duration for which the device was sleeping within
+ * {@link #getLoggingDurationMillis()}.
+ *
+ * @return Duration of sleep time in milliseconds.
+ */
+ public long getSleepTimeMillis() {
+ return mSleepTimeMs;
+ }
+
+ /**
+ * Returns the duration for which the device was idle within
+ * {@link #getLoggingDurationMillis()}.
+ *
+ * @return Duration of idle time in milliseconds.
+ */
+ public long getIdleTimeMillis() {
+ return mIdleTimeMs;
+ }
+
+ /**
+ * Returns the duration for which the device was receiving over cellular within
+ * {@link #getLoggingDurationMillis()}.
+ *
+ * @return Duration of cellular reception time in milliseconds.
+ */
+ public long getRxTimeMillis() {
+ return mRxTimeMs;
+ }
+
+ /**
+ * Returns an estimation of energy consumed by cellular chip within
+ * {@link #getLoggingDurationMillis()}.
+ *
+ * @return Energy consumed in milli-ampere milliseconds (mAmS).
+ */
+ public long getEnergyConsumedMaMillis() {
+ return mEnergyConsumedMaMs;
+ }
+
+ /**
+ * Returns the time in microseconds that the phone has been running with
+ * the given data connection.
+ *
+ * @return Amount of time phone spends in various Radio Access Technologies in microseconds.
+ * The index is {@link NetworkType}.
+ */
+ @NonNull
+ public long[] getTimeInRatMicros() {
+ return mTimeInRatMs;
+ }
+
+ /**
+ * Returns the time in microseconds that the phone has been running with
+ * the given signal strength.
+ *
+ * @return Amount of time phone spends in various cellular rx signal strength levels
+ * in microseconds. The index is signal strength bin.
+ */
+ @NonNull
+ public long[] getTimeInRxSignalStrengthLevelMicros() {
+ return mTimeInRxSignalStrengthLevelMs;
+ }
+
+ /**
+ * Returns the duration for which the device was transmitting over cellular within
+ * {@link #getLoggingDurationMillis()}.
+ *
+ * @return Duration of cellular transmission time in milliseconds.
+ * Tx(transmit) power index below
+ * <ul>
+ * <li> index 0 = tx_power < 0dBm. </li>
+ * <li> index 1 = 0dBm < tx_power < 5dBm. </li>
+ * <li> index 2 = 5dBm < tx_power < 15dBm. </li>
+ * <li> index 3 = 15dBm < tx_power < 20dBm. </li>
+ * <li> index 4 = tx_power > 20dBm. </li>
+ * </ul>
+ */
+ @NonNull
+ public long[] getTxTimeMillis() {
+ return mTxTimeMs;
+ }
+
+ /**
+ * Returns the energy consumed by cellular chip within {@link #getLoggingDurationMillis()}.
+ *
+ * @return Energy consumed in milli-ampere milli-seconds (mAmS).
+ */
+ public long getMonitoredRailChargeConsumedMaMillis() {
+ return mMonitoredRailChargeConsumedMaMs;
+ }
+
+ /** @hide **/
+ public void setLoggingDurationMillis(long t) {
+ mLoggingDurationMs = t;
+ return;
+ }
+
+ /** @hide **/
+ public void setKernelActiveTimeMillis(long t) {
+ mKernelActiveTimeMs = t;
+ return;
+ }
+
+ /** @hide **/
+ public void setNumPacketsTx(long n) {
+ mNumPacketsTx = n;
+ return;
+ }
+
+ /** @hide **/
+ public void setNumBytesTx(long b) {
+ mNumBytesTx = b;
+ return;
+ }
+
+ /** @hide **/
+ public void setNumPacketsRx(long n) {
+ mNumPacketsRx = n;
+ return;
+ }
+
+ /** @hide **/
+ public void setNumBytesRx(long b) {
+ mNumBytesRx = b;
+ return;
+ }
+
+ /** @hide **/
+ public void setSleepTimeMillis(long t) {
+ mSleepTimeMs = t;
+ return;
+ }
+
+ /** @hide **/
+ public void setIdleTimeMillis(long t) {
+ mIdleTimeMs = t;
+ return;
+ }
+
+ /** @hide **/
+ public void setRxTimeMillis(long t) {
+ mRxTimeMs = t;
+ return;
+ }
+
+ /** @hide **/
+ public void setEnergyConsumedMaMillis(long e) {
+ mEnergyConsumedMaMs = e;
+ return;
+ }
+
+ /** @hide **/
+ public void setTimeInRatMicros(@NonNull long[] t) {
+ mTimeInRatMs = Arrays.copyOfRange(t, 0,
+ Math.min(t.length, BatteryStats.NUM_DATA_CONNECTION_TYPES));
+ return;
+ }
+
+ /** @hide **/
+ public void setTimeInRxSignalStrengthLevelMicros(@NonNull long[] t) {
+ mTimeInRxSignalStrengthLevelMs = Arrays.copyOfRange(t, 0,
+ Math.min(t.length, SignalStrength.NUM_SIGNAL_STRENGTH_BINS));
+ return;
+ }
+
+ /** @hide **/
+ public void setTxTimeMillis(@NonNull long[] t) {
+ mTxTimeMs = Arrays.copyOfRange(t, 0, Math.min(t.length, ModemActivityInfo.TX_POWER_LEVELS));
+ return;
+ }
+
+ /** @hide **/
+ public void setMonitoredRailChargeConsumedMaMillis(long monitoredRailEnergyConsumedMaMs) {
+ mMonitoredRailChargeConsumedMaMs = monitoredRailEnergyConsumedMaMs;
+ return;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ private CellularBatteryStats(Parcel in) {
+ readFromParcel(in);
+ }
+}
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index b1fd4e5e699e..af1a51f68d71 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -47,8 +47,6 @@ public class FeatureFlagUtils {
static {
DEFAULT_FLAGS = new HashMap<>();
DEFAULT_FLAGS.put("settings_audio_switcher", "true");
- DEFAULT_FLAGS.put("settings_mobile_network_v2", "true");
- DEFAULT_FLAGS.put("settings_network_and_internet_v2", "true");
DEFAULT_FLAGS.put("settings_systemui_theme", "true");
DEFAULT_FLAGS.put(DYNAMIC_SYSTEM, "false");
DEFAULT_FLAGS.put(SEAMLESS_TRANSFER, "false");
diff --git a/core/java/android/view/InputChannel.java b/core/java/android/view/InputChannel.java
index 831e9ee43546..5d0d5bd79857 100644
--- a/core/java/android/view/InputChannel.java
+++ b/core/java/android/view/InputChannel.java
@@ -61,7 +61,6 @@ public final class InputChannel implements Parcelable {
private native void nativeWriteToParcel(Parcel parcel);
private native void nativeDup(InputChannel target);
private native IBinder nativeGetToken();
- private native void nativeSetToken(IBinder token);
private native String nativeGetName();
@@ -185,8 +184,4 @@ public final class InputChannel implements Parcelable {
public IBinder getToken() {
return nativeGetToken();
}
-
- public void setToken(IBinder token) {
- nativeSetToken(token);
- }
}
diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java
index 0175ba201dd1..5876b03476ce 100644
--- a/core/java/android/view/TextureView.java
+++ b/core/java/android/view/TextureView.java
@@ -16,6 +16,7 @@
package android.view;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UnsupportedAppUsage;
import android.content.Context;
@@ -139,7 +140,7 @@ public class TextureView extends View {
*
* @param context The context to associate this view with.
*/
- public TextureView(Context context) {
+ public TextureView(@NonNull Context context) {
super(context);
}
@@ -149,7 +150,7 @@ public class TextureView extends View {
* @param context The context to associate this view with.
* @param attrs The attributes of the XML tag that is inflating the view.
*/
- public TextureView(Context context, AttributeSet attrs) {
+ public TextureView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
@@ -162,7 +163,7 @@ public class TextureView extends View {
* reference to a style resource that supplies default values for
* the view. Can be 0 to not look for defaults.
*/
- public TextureView(Context context, AttributeSet attrs, int defStyleAttr) {
+ public TextureView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@@ -179,7 +180,8 @@ public class TextureView extends View {
* defStyleAttr is 0 or can not be found in the theme. Can be 0
* to not look for defaults.
*/
- public TextureView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+ public TextureView(@NonNull Context context, @Nullable AttributeSet attrs,
+ int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@@ -484,13 +486,13 @@ public class TextureView extends View {
* situations, make sure this texture view is not marked opaque.</p>
*
* @param transform The transform to apply to the content of
- * this view.
+ * this view. If null the transform will be set to identity.
*
* @see #getTransform(android.graphics.Matrix)
* @see #isOpaque()
* @see #setOpaque(boolean)
*/
- public void setTransform(Matrix transform) {
+ public void setTransform(@Nullable Matrix transform) {
mMatrix.set(transform);
mMatrixChanged = true;
invalidateParentIfNeeded();
@@ -507,7 +509,7 @@ public class TextureView extends View {
*
* @see #setTransform(android.graphics.Matrix)
*/
- public Matrix getTransform(Matrix transform) {
+ public @NonNull Matrix getTransform(@Nullable Matrix transform) {
if (transform == null) {
transform = new Matrix();
}
@@ -544,7 +546,7 @@ public class TextureView extends View {
* @see #getBitmap(android.graphics.Bitmap)
* @see #getBitmap(int, int)
*/
- public Bitmap getBitmap() {
+ public @Nullable Bitmap getBitmap() {
return getBitmap(getWidth(), getHeight());
}
@@ -571,7 +573,7 @@ public class TextureView extends View {
* @see #getBitmap(android.graphics.Bitmap)
* @see #getBitmap()
*/
- public Bitmap getBitmap(int width, int height) {
+ public @Nullable Bitmap getBitmap(int width, int height) {
if (isAvailable() && width > 0 && height > 0) {
return getBitmap(Bitmap.createBitmap(getResources().getDisplayMetrics(),
width, height, Bitmap.Config.ARGB_8888));
@@ -602,7 +604,7 @@ public class TextureView extends View {
* @throws IllegalStateException if the hardware rendering context cannot be
* acquired to capture the bitmap
*/
- public Bitmap getBitmap(Bitmap bitmap) {
+ public @NonNull Bitmap getBitmap(@NonNull Bitmap bitmap) {
if (bitmap != null && isAvailable()) {
applyUpdate();
applyTransformMatrix();
@@ -649,12 +651,13 @@ public class TextureView extends View {
* owned by another producer. For instance, if the TextureView is being used
* to render the camera's preview you cannot invoke this method.</p>
*
- * @return A Canvas used to draw into the surface.
+ * @return A Canvas used to draw into the surface, or null if the surface cannot be locked for
+ * drawing (see {@link #isAvailable()}).
*
* @see #lockCanvas(android.graphics.Rect)
* @see #unlockCanvasAndPost(android.graphics.Canvas)
*/
- public Canvas lockCanvas() {
+ public @Nullable Canvas lockCanvas() {
return lockCanvas(null);
}
@@ -669,15 +672,17 @@ public class TextureView extends View {
* already connected to an image producer (for instance: the camera,
* OpenGL, a media player, etc.)
*
- * @param dirty Area of the surface that will be modified.
+ * @param dirty Area of the surface that will be modified. If null the area of the entire
+ * surface is used.
- * @return A Canvas used to draw into the surface.
+ * @return A Canvas used to draw into the surface, or null if the surface cannot be locked for
+ * drawing (see {@link #isAvailable()}).
*
* @see #lockCanvas()
* @see #unlockCanvasAndPost(android.graphics.Canvas)
* @see #isAvailable()
*/
- public Canvas lockCanvas(Rect dirty) {
+ public @Nullable Canvas lockCanvas(@Nullable Rect dirty) {
if (!isAvailable()) return null;
if (mCanvas == null) {
@@ -705,7 +710,7 @@ public class TextureView extends View {
* @see #lockCanvas()
* @see #lockCanvas(android.graphics.Rect)
*/
- public void unlockCanvasAndPost(Canvas canvas) {
+ public void unlockCanvasAndPost(@NonNull Canvas canvas) {
if (mCanvas != null && canvas == mCanvas) {
canvas.restoreToCount(mSaveCount);
mSaveCount = 0;
@@ -723,7 +728,7 @@ public class TextureView extends View {
*
* @see #isAvailable()
*/
- public SurfaceTexture getSurfaceTexture() {
+ public @Nullable SurfaceTexture getSurfaceTexture() {
return mSurface;
}
@@ -742,7 +747,7 @@ public class TextureView extends View {
* @param surfaceTexture The {@link SurfaceTexture} that the view should use.
* @see SurfaceTexture#detachFromGLContext()
*/
- public void setSurfaceTexture(SurfaceTexture surfaceTexture) {
+ public void setSurfaceTexture(@NonNull SurfaceTexture surfaceTexture) {
if (surfaceTexture == null) {
throw new NullPointerException("surfaceTexture must not be null");
}
@@ -781,7 +786,7 @@ public class TextureView extends View {
* @see #setSurfaceTextureListener(android.view.TextureView.SurfaceTextureListener)
* @see SurfaceTextureListener
*/
- public SurfaceTextureListener getSurfaceTextureListener() {
+ public @Nullable SurfaceTextureListener getSurfaceTextureListener() {
return mListener;
}
@@ -792,25 +797,22 @@ public class TextureView extends View {
* @see #getSurfaceTextureListener()
* @see SurfaceTextureListener
*/
- public void setSurfaceTextureListener(SurfaceTextureListener listener) {
+ public void setSurfaceTextureListener(@Nullable SurfaceTextureListener listener) {
mListener = listener;
}
@UnsupportedAppUsage
private final SurfaceTexture.OnFrameAvailableListener mUpdateListener =
- new SurfaceTexture.OnFrameAvailableListener() {
- @Override
- public void onFrameAvailable(SurfaceTexture surfaceTexture) {
- updateLayer();
- invalidate();
- }
- };
+ surfaceTexture -> {
+ updateLayer();
+ invalidate();
+ };
/**
* This listener can be used to be notified when the surface texture
* associated with this texture view is available.
*/
- public static interface SurfaceTextureListener {
+ public interface SurfaceTextureListener {
/**
* Invoked when a {@link TextureView}'s SurfaceTexture is ready for use.
*
@@ -819,7 +821,7 @@ public class TextureView extends View {
* @param width The width of the surface
* @param height The height of the surface
*/
- public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height);
+ void onSurfaceTextureAvailable(@NonNull SurfaceTexture surface, int width, int height);
/**
* Invoked when the {@link SurfaceTexture}'s buffers size changed.
@@ -829,7 +831,7 @@ public class TextureView extends View {
* @param width The new width of the surface
* @param height The new height of the surface
*/
- public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height);
+ void onSurfaceTextureSizeChanged(@NonNull SurfaceTexture surface, int width, int height);
/**
* Invoked when the specified {@link SurfaceTexture} is about to be destroyed.
@@ -839,7 +841,7 @@ public class TextureView extends View {
*
* @param surface The surface about to be destroyed
*/
- public boolean onSurfaceTextureDestroyed(SurfaceTexture surface);
+ boolean onSurfaceTextureDestroyed(@NonNull SurfaceTexture surface);
/**
* Invoked when the specified {@link SurfaceTexture} is updated through
@@ -847,7 +849,7 @@ public class TextureView extends View {
*
* @param surface The surface just updated
*/
- public void onSurfaceTextureUpdated(SurfaceTexture surface);
+ void onSurfaceTextureUpdated(@NonNull SurfaceTexture surface);
}
@UnsupportedAppUsage
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 1599afb358e0..b90ce876aeb3 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -8727,7 +8727,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
structure.setContextClickable(true);
}
structure.setClassName(getAccessibilityClassName().toString());
- structure.setContentDescription(getContentDescription());
+ structure.setContentDescription(mContentDescription);
}
/**
@@ -9934,8 +9934,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
info.setImportantForAccessibility(isImportantForAccessibility());
info.setPackageName(mContext.getPackageName());
info.setClassName(getAccessibilityClassName());
- info.setStateDescription(getStateDescription());
- info.setContentDescription(getContentDescription());
+ info.setStateDescription(mStateDescription);
+ info.setContentDescription(mContentDescription);
info.setEnabled(isEnabled());
info.setClickable(isClickable());
@@ -10318,7 +10318,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @see #setStateDescription(CharSequence)
*/
@ViewDebug.ExportedProperty(category = "accessibility")
- public final @Nullable CharSequence getStateDescription() {
+ public @Nullable CharSequence getStateDescription() {
return mStateDescription;
}
@@ -13724,7 +13724,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*/
@UnsupportedAppUsage
public CharSequence getIterableTextForAccessibility() {
- return getContentDescription();
+ return mContentDescription;
}
/**
@@ -29514,9 +29514,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
stream.addProperty("text:textAlignment", getTextAlignment());
// accessibility
- CharSequence contentDescription = getContentDescription();
stream.addProperty("accessibility:contentDescription",
- contentDescription == null ? "" : contentDescription.toString());
+ mContentDescription == null ? "" : mContentDescription.toString());
+ stream.addProperty("accessibility:stateDescription",
+ mStateDescription == null ? "" : mStateDescription.toString());
stream.addProperty("accessibility:labelFor", getLabelFor());
stream.addProperty("accessibility:importantForAccessibility", getImportantForAccessibility());
}
diff --git a/core/java/android/view/WindowlessWindowManager.java b/core/java/android/view/WindowlessWindowManager.java
index f4f7d0b33fd1..6c6046f1876f 100644
--- a/core/java/android/view/WindowlessWindowManager.java
+++ b/core/java/android/view/WindowlessWindowManager.java
@@ -93,8 +93,9 @@ class WindowlessWindowManager implements IWindowSession {
DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel,
InsetsState outInsetsState) {
final SurfaceControl.Builder b = new SurfaceControl.Builder(mSurfaceSession)
- .setParent(mRootSurface)
- .setName(attrs.getTitle().toString());
+ .setParent(mRootSurface)
+ .setFormat(attrs.format)
+ .setName(attrs.getTitle().toString());
final SurfaceControl sc = b.build();
synchronized (this) {
mStateForWindow.put(window.asBinder(), new State(sc, attrs));
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 7ee53f26b1f8..e81db16f0743 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -92,7 +92,10 @@ import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
/**
@@ -422,6 +425,13 @@ public final class InputMethodManager {
int mCursorCandEnd;
/**
+ * Initial startInput with {@link StartInputReason.WINDOW_FOCUS_GAIN} is executed
+ * in a background thread. Later, if there is an actual startInput it will wait on
+ * main thread till the background thread completes.
+ */
+ private CompletableFuture<Void> mWindowFocusGainFuture;
+
+ /**
* The instance that has previously been sent to the input method.
*/
private CursorAnchorInfo mCursorAnchorInfo = null;
@@ -1598,6 +1608,18 @@ public final class InputMethodManager {
boolean startInputInner(@StartInputReason int startInputReason,
@Nullable IBinder windowGainingFocus, @StartInputFlags int startInputFlags,
@SoftInputModeFlags int softInputMode, int windowFlags) {
+ if (startInputReason != StartInputReason.WINDOW_FOCUS_GAIN
+ && mWindowFocusGainFuture != null) {
+ try {
+ mWindowFocusGainFuture.get();
+ } catch (ExecutionException | InterruptedException e) {
+ // do nothing
+ } catch (CancellationException e) {
+ // window no longer has focus.
+ return true;
+ }
+ }
+
final View view;
synchronized (mH) {
view = mServedView;
@@ -1947,31 +1969,38 @@ public final class InputMethodManager {
}
}
- if (checkFocusNoStartInput(forceNewFocus)) {
- // We need to restart input on the current focus view. This
- // should be done in conjunction with telling the system service
- // about the window gaining focus, to help make the transition
- // smooth.
- if (startInputInner(StartInputReason.WINDOW_FOCUS_GAIN, rootView.getWindowToken(),
- startInputFlags, softInputMode, windowFlags)) {
- return;
- }
+ final boolean forceNewFocus1 = forceNewFocus;
+ final int startInputFlags1 = startInputFlags;
+ if (mWindowFocusGainFuture != null) {
+ mWindowFocusGainFuture.cancel(false/* mayInterruptIfRunning */);
}
+ mWindowFocusGainFuture = CompletableFuture.runAsync(() -> {
+ if (checkFocusNoStartInput(forceNewFocus1)) {
+ // We need to restart input on the current focus view. This
+ // should be done in conjunction with telling the system service
+ // about the window gaining focus, to help make the transition
+ // smooth.
+ if (startInputInner(StartInputReason.WINDOW_FOCUS_GAIN, rootView.getWindowToken(),
+ startInputFlags1, softInputMode, windowFlags)) {
+ return;
+ }
+ }
- // For some reason we didn't do a startInput + windowFocusGain, so
- // we'll just do a window focus gain and call it a day.
- synchronized (mH) {
- try {
- if (DEBUG) Log.v(TAG, "Reporting focus gain, without startInput");
- mService.startInputOrWindowGainedFocus(
- StartInputReason.WINDOW_FOCUS_GAIN_REPORT_ONLY, mClient,
- rootView.getWindowToken(), startInputFlags, softInputMode, windowFlags,
- null, null, 0 /* missingMethodFlags */,
- rootView.getContext().getApplicationInfo().targetSdkVersion);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
+ // For some reason we didn't do a startInput + windowFocusGain, so
+ // we'll just do a window focus gain and call it a day.
+ synchronized (mH) {
+ try {
+ if (DEBUG) Log.v(TAG, "Reporting focus gain, without startInput");
+ mService.startInputOrWindowGainedFocus(
+ StartInputReason.WINDOW_FOCUS_GAIN_REPORT_ONLY, mClient,
+ rootView.getWindowToken(), startInputFlags1, softInputMode, windowFlags,
+ null, null, 0 /* missingMethodFlags */,
+ rootView.getContext().getApplicationInfo().targetSdkVersion);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
}
- }
+ });
}
/** @hide */
@@ -1986,6 +2015,10 @@ public final class InputMethodManager {
// If the mCurRootView is losing window focus, release the strong reference to it
// so as not to prevent it from being garbage-collected.
mCurRootView = null;
+ if (mWindowFocusGainFuture != null) {
+ mWindowFocusGainFuture.cancel(false /* mayInterruptIfRunning */);
+ mWindowFocusGainFuture = null;
+ }
} else {
if (DEBUG) {
Log.v(TAG, "Ignoring onPreWindowFocus()."
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index 7282008f7e3a..2895621f962a 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -328,6 +328,9 @@ public abstract class WebSettings {
* <p>
* The built-in mechanisms are the only currently supported zoom
* mechanisms, so it is recommended that this setting is always enabled.
+ * However, on-screen zoom controls are deprecated in Android (see
+ * {@link android.widget.ZoomButtonsController}) so it's recommended to
+ * disable {@link #setDisplayZoomControls}.
*
* @param enabled whether the WebView should use its built-in zoom mechanisms
*/
@@ -347,7 +350,9 @@ public abstract class WebSettings {
/**
* Sets whether the WebView should display on-screen zoom controls when
* using the built-in zoom mechanisms. See {@link #setBuiltInZoomControls}.
- * The default is {@code true}.
+ * The default is {@code true}. However, on-screen zoom controls are deprecated
+ * in Android (see {@link android.widget.ZoomButtonsController}) so it's
+ * recommended to set this to {@code false}.
*
* @param enabled whether the WebView should display on-screen zoom controls
*/
diff --git a/core/java/com/android/internal/os/BaseCommand.java b/core/java/com/android/internal/os/BaseCommand.java
index 278f40660ee9..e1b8e6c2d7d1 100644
--- a/core/java/com/android/internal/os/BaseCommand.java
+++ b/core/java/com/android/internal/os/BaseCommand.java
@@ -18,14 +18,14 @@
package com.android.internal.os;
import android.annotation.UnsupportedAppUsage;
-import android.os.ShellCommand;
+import android.os.BasicShellCommandHandler;
import java.io.PrintStream;
public abstract class BaseCommand {
@UnsupportedAppUsage
- final protected ShellCommand mArgs = new ShellCommand() {
+ final protected BasicShellCommandHandler mArgs = new BasicShellCommandHandler() {
@Override public int onCommand(String cmd) {
return 0;
}
@@ -50,7 +50,7 @@ public abstract class BaseCommand {
}
mRawArgs = args;
- mArgs.init(null, null, null, null, args, null, 0);
+ mArgs.init(null, null, null, null, args, 0);
try {
onRun();
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index d6b32b58ce64..f5bfe5cfecaf 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -12618,20 +12618,20 @@ public class BatteryStatsImpl extends BatteryStats {
txTimeMs[i] = counter.getTxTimeCounters()[i].getCountLocked(which);
totalTxTimeMs += txTimeMs[i];
}
- s.setLoggingDurationMs(computeBatteryRealtime(rawRealTime, which) / 1000);
- s.setKernelActiveTimeMs(getMobileRadioActiveTime(rawRealTime, which) / 1000);
+ s.setLoggingDurationMillis(computeBatteryRealtime(rawRealTime, which) / 1000);
+ s.setKernelActiveTimeMillis(getMobileRadioActiveTime(rawRealTime, which) / 1000);
s.setNumPacketsTx(getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which));
s.setNumBytesTx(getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which));
s.setNumPacketsRx(getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which));
s.setNumBytesRx(getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which));
- s.setSleepTimeMs(sleepTimeMs);
- s.setIdleTimeMs(idleTimeMs);
- s.setRxTimeMs(rxTimeMs);
- s.setEnergyConsumedMaMs(energyConsumedMaMs);
- s.setTimeInRatMs(timeInRatMs);
- s.setTimeInRxSignalStrengthLevelMs(timeInRxSignalStrengthLevelMs);
- s.setTxTimeMs(txTimeMs);
- s.setMonitoredRailChargeConsumedMaMs(monitoredRailChargeConsumedMaMs);
+ s.setSleepTimeMillis(sleepTimeMs);
+ s.setIdleTimeMillis(idleTimeMs);
+ s.setRxTimeMillis(rxTimeMs);
+ s.setEnergyConsumedMaMillis(energyConsumedMaMs);
+ s.setTimeInRatMicros(timeInRatMs);
+ s.setTimeInRxSignalStrengthLevelMicros(timeInRxSignalStrengthLevelMs);
+ s.setTxTimeMillis(txTimeMs);
+ s.setMonitoredRailChargeConsumedMaMillis(monitoredRailChargeConsumedMaMs);
return s;
}
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index 317469e58245..73f549a31bac 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -38,25 +38,6 @@ oneway interface IStatusBar
void showWirelessChargingAnimation(int batteryLevel);
- /**
- * Notifies System UI side of a visibility flag change on the specified display.
- *
- * @param displayId the id of the display to notify
- * @param vis the visibility flags except SYSTEM_UI_FLAG_LIGHT_STATUS_BAR which will be reported
- * separately in fullscreenStackVis and dockedStackVis
- * @param fullscreenStackVis the flags which only apply in the region of the fullscreen stack,
- * which is currently only SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
- * @param dockedStackVis the flags that only apply in the region of the docked stack, which is
- * currently only SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
- * @param mask which flags to change
- * @param fullscreenBounds the current bounds of the fullscreen stack, in screen coordinates
- * @param dockedBounds the current bounds of the docked stack, in screen coordinates
- * @param navbarColorManagedByIme {@code true} if navigation bar color is managed by IME.
- */
- void setSystemUiVisibility(int displayId, int vis, int fullscreenStackVis, int dockedStackVis,
- int mask, in Rect fullscreenBounds, in Rect dockedBounds,
- boolean navbarColorManagedByIme);
-
void topAppWindowChanged(int displayId, boolean isFullscreen, boolean isImmersive);
void setImeWindowStatus(int displayId, in IBinder token, int vis, int backDisposition,
boolean showImeSwitcher, boolean isMultiClientImeEnabled);
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index d703b86d6c8d..3f08710bb17f 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -77,7 +77,6 @@ interface IStatusBarService
void onNotificationSmartReplySent(in String key, in int replyIndex, in CharSequence reply,
in int notificationLocation, boolean modifiedBeforeSending);
void onNotificationSettingsViewed(String key);
- void setSystemUiVisibility(int displayId, int vis, int mask, String cause);
void onNotificationBubbleChanged(String key, boolean isBubble);
void grantInlineReplyUriPermission(String key, in Uri uri, in UserHandle user, String packageName);
void clearInlineReplyUriPermissions(String key);
diff --git a/core/java/com/android/internal/statusbar/RegisterStatusBarResult.java b/core/java/com/android/internal/statusbar/RegisterStatusBarResult.java
index 4c3f04b10892..9095f05543da 100644
--- a/core/java/com/android/internal/statusbar/RegisterStatusBarResult.java
+++ b/core/java/com/android/internal/statusbar/RegisterStatusBarResult.java
@@ -16,53 +16,50 @@
package com.android.internal.statusbar;
-import android.graphics.Rect;
+import android.annotation.NonNull;
import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.ArrayMap;
+import com.android.internal.view.AppearanceRegion;
+
/**
* An immutable data object to return a set of values from StatusBarManagerService to its clients.
*/
public final class RegisterStatusBarResult implements Parcelable {
public final ArrayMap<String, StatusBarIcon> mIcons;
- public final int mDisabledFlags1; // switch[0]
- public final int mSystemUiVisibility; // switch[1]
- public final int mImeWindowVis; // switch[3]
- public final int mImeBackDisposition; // switch[4]
- public final boolean mShowImeSwitcher; // switch[5]
- public final int mDisabledFlags2; // switch[6]
- public final int mFullscreenStackSysUiVisibility; // switch[7]
- public final int mDockedStackSysUiVisibility; // switch[8]
+ public final int mDisabledFlags1; // switch[0]
+ public final int mAppearance; // switch[1]
+ public final AppearanceRegion[] mAppearanceRegions; // switch[2]
+ public final int mImeWindowVis; // switch[3]
+ public final int mImeBackDisposition; // switch[4]
+ public final boolean mShowImeSwitcher; // switch[5]
+ public final int mDisabledFlags2; // switch[6]
public final IBinder mImeToken;
- public final Rect mFullscreenStackBounds;
- public final Rect mDockedStackBounds;
public final boolean mNavbarColorManagedByIme;
public final boolean mAppFullscreen;
public final boolean mAppImmersive;
+ public final int[] mTransientBarTypes;
public RegisterStatusBarResult(ArrayMap<String, StatusBarIcon> icons, int disabledFlags1,
- int systemUiVisibility, int imeWindowVis, int imeBackDisposition,
- boolean showImeSwitcher, int disabledFlags2, int fullscreenStackSysUiVisibility,
- int dockedStackSysUiVisibility, IBinder imeToken, Rect fullscreenStackBounds,
- Rect dockedStackBounds, boolean navbarColorManagedByIme, boolean appFullscreen,
- boolean appImmersive) {
+ int appearance, AppearanceRegion[] appearanceRegions, int imeWindowVis,
+ int imeBackDisposition, boolean showImeSwitcher, int disabledFlags2, IBinder imeToken,
+ boolean navbarColorManagedByIme, boolean appFullscreen, boolean appImmersive,
+ @NonNull int[] transientBarTypes) {
mIcons = new ArrayMap<>(icons);
mDisabledFlags1 = disabledFlags1;
- mSystemUiVisibility = systemUiVisibility;
+ mAppearance = appearance;
+ mAppearanceRegions = appearanceRegions;
mImeWindowVis = imeWindowVis;
mImeBackDisposition = imeBackDisposition;
mShowImeSwitcher = showImeSwitcher;
mDisabledFlags2 = disabledFlags2;
- mFullscreenStackSysUiVisibility = fullscreenStackSysUiVisibility;
- mDockedStackSysUiVisibility = dockedStackSysUiVisibility;
mImeToken = imeToken;
- mFullscreenStackBounds = fullscreenStackBounds;
- mDockedStackBounds = dockedStackBounds;
mNavbarColorManagedByIme = navbarColorManagedByIme;
mAppFullscreen = appFullscreen;
mAppImmersive = appImmersive;
+ mTransientBarTypes = transientBarTypes;
}
@Override
@@ -74,19 +71,17 @@ public final class RegisterStatusBarResult implements Parcelable {
public void writeToParcel(Parcel dest, int flags) {
dest.writeTypedArrayMap(mIcons, flags);
dest.writeInt(mDisabledFlags1);
- dest.writeInt(mSystemUiVisibility);
+ dest.writeInt(mAppearance);
+ dest.writeParcelableArray(mAppearanceRegions, 0);
dest.writeInt(mImeWindowVis);
dest.writeInt(mImeBackDisposition);
dest.writeBoolean(mShowImeSwitcher);
dest.writeInt(mDisabledFlags2);
- dest.writeInt(mFullscreenStackSysUiVisibility);
- dest.writeInt(mDockedStackSysUiVisibility);
dest.writeStrongBinder(mImeToken);
- dest.writeTypedObject(mFullscreenStackBounds, flags);
- dest.writeTypedObject(mDockedStackBounds, flags);
dest.writeBoolean(mNavbarColorManagedByIme);
dest.writeBoolean(mAppFullscreen);
dest.writeBoolean(mAppImmersive);
+ dest.writeIntArray(mTransientBarTypes);
}
/**
@@ -99,24 +94,22 @@ public final class RegisterStatusBarResult implements Parcelable {
final ArrayMap<String, StatusBarIcon> icons =
source.createTypedArrayMap(StatusBarIcon.CREATOR);
final int disabledFlags1 = source.readInt();
- final int systemUiVisibility = source.readInt();
+ final int appearance = source.readInt();
+ final AppearanceRegion[] appearanceRegions =
+ source.readParcelableArray(null, AppearanceRegion.class);
final int imeWindowVis = source.readInt();
final int imeBackDisposition = source.readInt();
final boolean showImeSwitcher = source.readBoolean();
final int disabledFlags2 = source.readInt();
- final int fullscreenStackSysUiVisibility = source.readInt();
- final int dockedStackSysUiVisibility = source.readInt();
final IBinder imeToken = source.readStrongBinder();
- final Rect fullscreenStackBounds = source.readTypedObject(Rect.CREATOR);
- final Rect dockedStackBounds = source.readTypedObject(Rect.CREATOR);
final boolean navbarColorManagedByIme = source.readBoolean();
final boolean appFullscreen = source.readBoolean();
final boolean appImmersive = source.readBoolean();
- return new RegisterStatusBarResult(icons, disabledFlags1, systemUiVisibility,
- imeWindowVis, imeBackDisposition, showImeSwitcher, disabledFlags2,
- fullscreenStackSysUiVisibility, dockedStackSysUiVisibility, imeToken,
- fullscreenStackBounds, dockedStackBounds, navbarColorManagedByIme,
- appFullscreen, appImmersive);
+ final int[] transientBarTypes = source.createIntArray();
+ return new RegisterStatusBarResult(icons, disabledFlags1, appearance,
+ appearanceRegions, imeWindowVis, imeBackDisposition, showImeSwitcher,
+ disabledFlags2, imeToken, navbarColorManagedByIme, appFullscreen,
+ appImmersive, transientBarTypes);
}
@Override
diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java
index db91dc5a8bc3..ed7f5de83fd1 100644
--- a/core/java/com/android/server/SystemConfig.java
+++ b/core/java/com/android/server/SystemConfig.java
@@ -540,6 +540,7 @@ public class SystemConfig {
Slog.w(TAG, "Couldn't find or open permissions file " + permFile);
return;
}
+ Slog.i(TAG, "Reading permissions from " + permFile);
final boolean lowRam = ActivityManager.isLowRamDeviceStatic();
diff --git a/core/jni/android_view_InputChannel.cpp b/core/jni/android_view_InputChannel.cpp
index bf1cea8cff2e..891520a34ce1 100644
--- a/core/jni/android_view_InputChannel.cpp
+++ b/core/jni/android_view_InputChannel.cpp
@@ -276,20 +276,12 @@ static jobject android_view_InputChannel_nativeGetToken(JNIEnv* env, jobject obj
NativeInputChannel* nativeInputChannel =
android_view_InputChannel_getNativeInputChannel(env, obj);
if (nativeInputChannel) {
- return javaObjectForIBinder(env, nativeInputChannel->getInputChannel()->getToken());
+ return javaObjectForIBinder(env,
+ nativeInputChannel->getInputChannel()->getConnectionToken());
}
return 0;
}
-static void android_view_InputChannel_nativeSetToken(JNIEnv* env, jobject obj, jobject tokenObj) {
- NativeInputChannel* nativeInputChannel =
- android_view_InputChannel_getNativeInputChannel(env, obj);
- sp<IBinder> token = ibinderForJavaObject(env, tokenObj);
- if (nativeInputChannel != nullptr) {
- nativeInputChannel->getInputChannel()->setToken(token);
- }
-}
-
// ----------------------------------------------------------------------------
static const JNINativeMethod gInputChannelMethods[] = {
@@ -312,8 +304,6 @@ static const JNINativeMethod gInputChannelMethods[] = {
(void*)android_view_InputChannel_nativeDup },
{ "nativeGetToken", "()Landroid/os/IBinder;",
(void*)android_view_InputChannel_nativeGetToken },
- { "nativeSetToken", "(Landroid/os/IBinder;)V",
- (void*)android_view_InputChannel_nativeSetToken }
};
int register_android_view_InputChannel(JNIEnv* env) {
diff --git a/core/proto/android/server/activitymanagerservice.proto b/core/proto/android/server/activitymanagerservice.proto
index 2f87debce978..b9d28e4ce8eb 100644
--- a/core/proto/android/server/activitymanagerservice.proto
+++ b/core/proto/android/server/activitymanagerservice.proto
@@ -100,7 +100,8 @@ message ActivityStackProto {
message TaskRecordProto {
option (.android.msg_privacy).dest = DEST_AUTOMATIC;
- optional .com.android.server.wm.ConfigurationContainerProto configuration_container = 1;
+ // To be removed soon.
+ optional .com.android.server.wm.ConfigurationContainerProto configuration_container = 1 [deprecated=true];
optional int32 id = 2;
repeated ActivityRecordProto activities = 3;
optional int32 stack_id = 4;
@@ -113,6 +114,7 @@ message TaskRecordProto {
optional .android.graphics.RectProto bounds = 11;
optional int32 min_width = 12;
optional int32 min_height = 13;
+ optional .com.android.server.wm.TaskProto task = 14;
}
message ActivityRecordProto {
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index a15e1aea7a82..66e84dc16781 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2006,6 +2006,11 @@
<!-- =========================================== -->
<eat-comment />
+ <!-- @SystemApi Allows granting runtime permissions to telephony related components.
+ @hide Used internally. -->
+ <permission android:name="android.permission.GRANT_RUNTIME_PERMISSIONS_TO_TELEPHONY_DEFAULTS"
+ android:protectionLevel="signature|telephony" />
+
<!-- Allows modification of the telephony state - power on, mmi, etc.
Does not include placing calls.
<p>Not for use by third-party applications. -->
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index eaf93eb9e216..9ca98c570c89 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -3705,7 +3705,7 @@
name is separated by comma.
Example: "com.android.phone,com.android.stk,com.android.providers.telephony"
-->
- <string name="config_telephonyPackages" translatable="false">"com.android.phone,com.android.stk,com.android.providers.telephony,com.android.ons"</string>
+ <string name="config_telephonyPackages" translatable="false">"com.android.phone,com.android.stk,com.android.providers.telephony,com.android.ons,com.android.cellbroadcastservice"</string>
<!-- The package name for the default system wifi app.
This package must be trusted, as it has the permissions to control wifi
diff --git a/core/tests/coretests/src/com/android/internal/statusbar/RegisterStatusBarResultTest.java b/core/tests/coretests/src/com/android/internal/statusbar/RegisterStatusBarResultTest.java
index 0be5009f85f0..9f68ef31c166 100644
--- a/core/tests/coretests/src/com/android/internal/statusbar/RegisterStatusBarResultTest.java
+++ b/core/tests/coretests/src/com/android/internal/statusbar/RegisterStatusBarResultTest.java
@@ -18,7 +18,6 @@ package com.android.internal.statusbar;
import static com.google.common.truth.Truth.assertThat;
-import android.graphics.Rect;
import android.os.Binder;
import android.os.Parcel;
import android.os.UserHandle;
@@ -27,6 +26,8 @@ import android.util.ArrayMap;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
+import com.android.internal.view.AppearanceRegion;
+
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -47,19 +48,17 @@ public class RegisterStatusBarResultTest {
final RegisterStatusBarResult original = new RegisterStatusBarResult(iconMap,
0x2 /* disabledFlags1 */,
- 0x4 /* systemUiVisibility */,
+ 0x4 /* appearance */,
+ new AppearanceRegion[0] /* appearanceRegions */,
0x8 /* imeWindowVis */,
0x10 /* imeBackDisposition */,
false /* showImeSwitcher */,
0x20 /* disabledFlags2 */,
- 0x40 /* fullscreenStackSysUiVisibility */,
- 0x80 /* dockedStackSysUiVisibility */,
new Binder() /* imeToken */,
- new Rect(0x100, 0x200, 0x400, 0x800) /* fullscreenStackBounds */,
- new Rect(0x1000, 0x2000, 0x4000, 0x8000) /* dockedStackBounds */,
true /* navbarColorManagedByIme */,
true /* appFullscreen */,
- true /* appImmersive */);
+ true /* appImmersive */,
+ new int[0] /* transientBarTypes */);
final RegisterStatusBarResult copy = clone(original);
@@ -69,21 +68,17 @@ public class RegisterStatusBarResultTest {
.isEqualTo(original.mIcons.get(dumyIconKey).user);
assertThat(copy.mDisabledFlags1).isEqualTo(original.mDisabledFlags1);
- assertThat(copy.mSystemUiVisibility).isEqualTo(original.mSystemUiVisibility);
+ assertThat(copy.mAppearance).isEqualTo(original.mAppearance);
+ assertThat(copy.mAppearanceRegions).isEqualTo(original.mAppearanceRegions);
assertThat(copy.mImeWindowVis).isEqualTo(original.mImeWindowVis);
assertThat(copy.mImeBackDisposition).isEqualTo(original.mImeBackDisposition);
assertThat(copy.mShowImeSwitcher).isEqualTo(original.mShowImeSwitcher);
assertThat(copy.mDisabledFlags2).isEqualTo(original.mDisabledFlags2);
- assertThat(copy.mFullscreenStackSysUiVisibility)
- .isEqualTo(original.mFullscreenStackSysUiVisibility);
- assertThat(copy.mDockedStackSysUiVisibility)
- .isEqualTo(original.mDockedStackSysUiVisibility);
assertThat(copy.mImeToken).isSameAs(original.mImeToken);
- assertThat(copy.mFullscreenStackBounds).isEqualTo(original.mFullscreenStackBounds);
- assertThat(copy.mDockedStackBounds).isEqualTo(original.mDockedStackBounds);
assertThat(copy.mNavbarColorManagedByIme).isEqualTo(original.mNavbarColorManagedByIme);
assertThat(copy.mAppFullscreen).isEqualTo(original.mAppFullscreen);
assertThat(copy.mAppImmersive).isEqualTo(original.mAppImmersive);
+ assertThat(copy.mTransientBarTypes).isEqualTo(original.mTransientBarTypes);
}
private RegisterStatusBarResult clone(RegisterStatusBarResult original) {
diff --git a/data/keyboards/Vendor_1532_Product_0900.kl b/data/keyboards/Vendor_1532_Product_0900.kl
index c2fc1b4f9365..4c6c4dda02b0 100644
--- a/data/keyboards/Vendor_1532_Product_0900.kl
+++ b/data/keyboards/Vendor_1532_Product_0900.kl
@@ -20,13 +20,19 @@ key 307 BUTTON_X
key 308 BUTTON_Y
key 310 BUTTON_L1
key 311 BUTTON_R1
-key 316 BUTTON_MODE
key 317 BUTTON_THUMBL
key 318 BUTTON_THUMBR
key 158 BACK
key 172 HOME
+# Left arrow to the left of the "power" key
+key 0x13a BUTTON_SELECT
+# Right arrow to the right of the "power" key
+key 0x13b BUTTON_START
+# Power key
+key 0x13c BUTTON_MODE
+
axis 0x00 X
axis 0x01 Y
axis 0x02 Z
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 4ca26c273c95..15e0c8d0a266 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -479,7 +479,8 @@ void CanvasContext::draw() {
if (didDraw) {
swap.damage = windowDirty;
} else {
- swap.damage = SkRect::MakeWH(INT_MAX, INT_MAX);
+ float max = static_cast<float>(INT_MAX);
+ swap.damage = SkRect::MakeWH(max, max);
}
swap.swapCompletedTime = systemTime(SYSTEM_TIME_MONOTONIC);
swap.vsyncTime = mRenderThread.timeLord().latestVsync();
diff --git a/location/java/android/location/LocationRequest.java b/location/java/android/location/LocationRequest.java
index 3abd2c2144e1..ca8f2ac82e94 100644
--- a/location/java/android/location/LocationRequest.java
+++ b/location/java/android/location/LocationRequest.java
@@ -505,6 +505,23 @@ public final class LocationRequest implements Parcelable {
}
/**
+ * Returns the realtime at which this request expires, taking into account both
+ * {@link #setExpireAt(long)} and {@link #setExpireIn(long)} relative to the given realtime.
+ *
+ * @hide
+ */
+ public long getExpirationRealtimeMs(long startRealtimeMs) {
+ long expirationRealtimeMs;
+ // Check for > Long.MAX_VALUE overflow (elapsedRealtime > 0):
+ if (mExpireIn > Long.MAX_VALUE - startRealtimeMs) {
+ expirationRealtimeMs = Long.MAX_VALUE;
+ } else {
+ expirationRealtimeMs = startRealtimeMs + mExpireIn;
+ }
+ return Math.min(expirationRealtimeMs, mExpireAt);
+ }
+
+ /**
* Set the number of location updates.
*
* <p>By default locations are continuously updated until the request is explicitly
diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java
index 2257747c2c8b..4ed8f423d6c9 100644
--- a/media/java/android/media/tv/tuner/Tuner.java
+++ b/media/java/android/media/tv/tuner/Tuner.java
@@ -16,11 +16,11 @@
package android.media.tv.tuner;
-import android.annotation.IntDef;
-import android.hardware.tv.tuner.V1_0.Constants;
+import android.annotation.Nullable;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
import java.util.List;
/**
@@ -32,40 +32,16 @@ public final class Tuner implements AutoCloseable {
private static final String TAG = "MediaTvTuner";
private static final boolean DEBUG = false;
- @Retention(RetentionPolicy.SOURCE)
- @IntDef({FRONTEND_TYPE_UNDEFINED, FRONTEND_TYPE_ANALOG, FRONTEND_TYPE_ATSC, FRONTEND_TYPE_ATSC3,
- FRONTEND_TYPE_DVBC, FRONTEND_TYPE_DVBS, FRONTEND_TYPE_DVBT, FRONTEND_TYPE_ISDBS,
- FRONTEND_TYPE_ISDBS3, FRONTEND_TYPE_ISDBT})
- public @interface FrontendType {}
-
- public static final int FRONTEND_TYPE_UNDEFINED = Constants.FrontendType.UNDEFINED;
- public static final int FRONTEND_TYPE_ANALOG = Constants.FrontendType.ANALOG;
- public static final int FRONTEND_TYPE_ATSC = Constants.FrontendType.ATSC;
- public static final int FRONTEND_TYPE_ATSC3 = Constants.FrontendType.ATSC3;
- public static final int FRONTEND_TYPE_DVBC = Constants.FrontendType.DVBC;
- public static final int FRONTEND_TYPE_DVBS = Constants.FrontendType.DVBS;
- public static final int FRONTEND_TYPE_DVBT = Constants.FrontendType.DVBT;
- public static final int FRONTEND_TYPE_ISDBS = Constants.FrontendType.ISDBS;
- public static final int FRONTEND_TYPE_ISDBS3 = Constants.FrontendType.ISDBS3;
- public static final int FRONTEND_TYPE_ISDBT = Constants.FrontendType.ISDBT;
-
-
- @Retention(RetentionPolicy.SOURCE)
- @IntDef({FRONTEND_EVENT_TYPE_LOCKED, FRONTEND_EVENT_TYPE_NO_SIGNAL,
- FRONTEND_EVENT_TYPE_LOST_LOCK})
- public @interface FrontendEventType {}
-
- public static final int FRONTEND_EVENT_TYPE_LOCKED = Constants.FrontendEventType.LOCKED;
- public static final int FRONTEND_EVENT_TYPE_NO_SIGNAL = Constants.FrontendEventType.NO_SIGNAL;
- public static final int FRONTEND_EVENT_TYPE_LOST_LOCK = Constants.FrontendEventType.LOST_LOCK;
+ private static final int MSG_ON_FRONTEND_EVENT = 1;
static {
System.loadLibrary("media_tv_tuner");
nativeInit();
}
- private FrontendCallback mFrontendCallback;
private List<Integer> mFrontendIds;
+ private Frontend mFrontend;
+ private EventHandler mHandler;
public Tuner() {
nativeSetup();
@@ -96,6 +72,8 @@ public final class Tuner implements AutoCloseable {
*/
private native Frontend nativeOpenFrontendById(int id);
+ private native Filter nativeOpenFilter(int type, int subType, int bufferSize);
+
/**
* Frontend Callback.
@@ -108,11 +86,66 @@ public final class Tuner implements AutoCloseable {
void onEvent(int frontendEventType);
}
- protected static class Frontend {
- int mId;
+ @Nullable
+ private EventHandler createEventHandler() {
+ Looper looper;
+ if ((looper = Looper.myLooper()) != null) {
+ return new EventHandler(looper);
+ } else if ((looper = Looper.getMainLooper()) != null) {
+ return new EventHandler(looper);
+ }
+ return null;
+ }
+
+ private class EventHandler extends Handler {
+ private EventHandler(Looper looper) {
+ super(looper);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_ON_FRONTEND_EVENT:
+ if (mFrontend != null && mFrontend.mCallback != null) {
+ mFrontend.mCallback.onEvent(msg.arg1);
+ }
+ break;
+ default:
+ // fall through
+ }
+ }
+ }
+
+ protected class Frontend {
+ private int mId;
+ private FrontendCallback mCallback;
+
private Frontend(int id) {
mId = id;
}
+
+ public void setCallback(@Nullable FrontendCallback callback, @Nullable Handler handler) {
+ mCallback = callback;
+
+ if (mCallback == null) {
+ return;
+ }
+
+ if (handler == null) {
+ // use default looper if handler is null
+ if (mHandler == null) {
+ mHandler = createEventHandler();
+ }
+ return;
+ }
+
+ Looper looper = handler.getLooper();
+ if (mHandler != null && mHandler.getLooper() == looper) {
+ // the same looper. reuse mHandler
+ return;
+ }
+ mHandler = new EventHandler(looper);
+ }
}
private List<Integer> getFrontendIds() {
@@ -122,11 +155,29 @@ public final class Tuner implements AutoCloseable {
private Frontend openFrontendById(int id) {
if (mFrontendIds == null) {
- getFrontendIds();
+ mFrontendIds = getFrontendIds();
}
if (!mFrontendIds.contains(id)) {
return null;
}
- return nativeOpenFrontendById(id);
+ mFrontend = nativeOpenFrontendById(id);
+ return mFrontend;
+ }
+
+ private void onFrontendEvent(int eventType) {
+ if (mHandler != null) {
+ mHandler.sendMessage(mHandler.obtainMessage(MSG_ON_FRONTEND_EVENT, eventType, 0));
+ }
+ }
+
+ protected class Filter {
+ int mId;
+ private Filter(int id) {
+ mId = id;
+ }
+ }
+
+ private Filter openFilter(int type, int subType, int bufferSize) {
+ return nativeOpenFilter(type, subType, bufferSize);
}
}
diff --git a/media/java/android/media/tv/tuner/TunerConstants.java b/media/java/android/media/tv/tuner/TunerConstants.java
new file mode 100644
index 000000000000..411882ed13bd
--- /dev/null
+++ b/media/java/android/media/tv/tuner/TunerConstants.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 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.
+ */
+
+package android.media.tv.tuner;
+
+import android.annotation.IntDef;
+import android.hardware.tv.tuner.V1_0.Constants;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * @hide
+ */
+final class TunerConstants {
+ public static final int INVALID_TS_PID = Constants.Constant.INVALID_TS_PID;
+ public static final int INVALID_STREAM_ID = Constants.Constant.INVALID_STREAM_ID;
+
+
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({FRONTEND_TYPE_UNDEFINED, FRONTEND_TYPE_ANALOG, FRONTEND_TYPE_ATSC, FRONTEND_TYPE_ATSC3,
+ FRONTEND_TYPE_DVBC, FRONTEND_TYPE_DVBS, FRONTEND_TYPE_DVBT, FRONTEND_TYPE_ISDBS,
+ FRONTEND_TYPE_ISDBS3, FRONTEND_TYPE_ISDBT})
+ public @interface FrontendType {}
+
+ public static final int FRONTEND_TYPE_UNDEFINED = Constants.FrontendType.UNDEFINED;
+ public static final int FRONTEND_TYPE_ANALOG = Constants.FrontendType.ANALOG;
+ public static final int FRONTEND_TYPE_ATSC = Constants.FrontendType.ATSC;
+ public static final int FRONTEND_TYPE_ATSC3 = Constants.FrontendType.ATSC3;
+ public static final int FRONTEND_TYPE_DVBC = Constants.FrontendType.DVBC;
+ public static final int FRONTEND_TYPE_DVBS = Constants.FrontendType.DVBS;
+ public static final int FRONTEND_TYPE_DVBT = Constants.FrontendType.DVBT;
+ public static final int FRONTEND_TYPE_ISDBS = Constants.FrontendType.ISDBS;
+ public static final int FRONTEND_TYPE_ISDBS3 = Constants.FrontendType.ISDBS3;
+ public static final int FRONTEND_TYPE_ISDBT = Constants.FrontendType.ISDBT;
+
+
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({FRONTEND_EVENT_TYPE_LOCKED, FRONTEND_EVENT_TYPE_NO_SIGNAL,
+ FRONTEND_EVENT_TYPE_LOST_LOCK})
+ public @interface FrontendEventType {}
+
+ public static final int FRONTEND_EVENT_TYPE_LOCKED = Constants.FrontendEventType.LOCKED;
+ public static final int FRONTEND_EVENT_TYPE_NO_SIGNAL = Constants.FrontendEventType.NO_SIGNAL;
+ public static final int FRONTEND_EVENT_TYPE_LOST_LOCK = Constants.FrontendEventType.LOST_LOCK;
+
+
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({DATA_FORMAT_TS, DATA_FORMAT_PES, DATA_FORMAT_ES, DATA_FORMAT_SHV_TLV})
+ public @interface DataFormat {}
+
+ public static final int DATA_FORMAT_TS = Constants.DataFormat.TS;
+ public static final int DATA_FORMAT_PES = Constants.DataFormat.PES;
+ public static final int DATA_FORMAT_ES = Constants.DataFormat.ES;
+ public static final int DATA_FORMAT_SHV_TLV = Constants.DataFormat.SHV_TLV;
+
+ private TunerConstants() {
+ }
+}
diff --git a/media/jni/android_media_MediaCrypto.cpp b/media/jni/android_media_MediaCrypto.cpp
index 2d9051f5230d..517672ee6127 100644
--- a/media/jni/android_media_MediaCrypto.cpp
+++ b/media/jni/android_media_MediaCrypto.cpp
@@ -24,11 +24,10 @@
#include "jni.h"
#include <nativehelper/JNIHelp.h>
-#include <binder/IServiceManager.h>
#include <cutils/properties.h>
#include <media/stagefright/foundation/ADebug.h>
+#include <mediadrm/DrmUtils.h>
#include <mediadrm/ICrypto.h>
-#include <mediadrm/IMediaDrmService.h>
namespace android {
@@ -64,20 +63,7 @@ JCrypto::~JCrypto() {
// static
sp<ICrypto> JCrypto::MakeCrypto() {
- sp<IServiceManager> sm = defaultServiceManager();
-
- sp<IBinder> binder = sm->getService(String16("media.drm"));
- sp<IMediaDrmService> service = interface_cast<IMediaDrmService>(binder);
- if (service == NULL) {
- return NULL;
- }
-
- sp<ICrypto> crypto = service->makeCrypto();
- if (crypto == NULL || (crypto->initCheck() != OK && crypto->initCheck() != NO_INIT)) {
- return NULL;
- }
-
- return crypto;
+ return DrmUtils::MakeCrypto();
}
// static
diff --git a/media/jni/android_media_MediaDrm.cpp b/media/jni/android_media_MediaDrm.cpp
index f412161f418a..820fe98cafb6 100644
--- a/media/jni/android_media_MediaDrm.cpp
+++ b/media/jni/android_media_MediaDrm.cpp
@@ -27,14 +27,13 @@
#include "jni.h"
#include <nativehelper/JNIHelp.h>
-#include <binder/IServiceManager.h>
#include <binder/Parcel.h>
#include <binder/PersistableBundle.h>
#include <cutils/properties.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/MediaErrors.h>
+#include <mediadrm/DrmUtils.h>
#include <mediadrm/IDrm.h>
-#include <mediadrm/IMediaDrmService.h>
using ::android::os::PersistableBundle;
@@ -486,20 +485,7 @@ JDrm::~JDrm() {
// static
sp<IDrm> JDrm::MakeDrm() {
- sp<IServiceManager> sm = defaultServiceManager();
-
- sp<IBinder> binder = sm->getService(String16("media.drm"));
- sp<IMediaDrmService> service = interface_cast<IMediaDrmService>(binder);
- if (service == NULL) {
- return NULL;
- }
-
- sp<IDrm> drm = service->makeDrm();
- if (drm == NULL || (drm->initCheck() != OK && drm->initCheck() != NO_INIT)) {
- return NULL;
- }
-
- return drm;
+ return DrmUtils::MakeDrm();
}
// static
diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp
index ba133fc44fb7..f8150972a413 100644
--- a/media/jni/android_media_tv_Tuner.cpp
+++ b/media/jni/android_media_tv_Tuner.cpp
@@ -25,18 +25,59 @@
#pragma GCC diagnostic ignored "-Wunused-function"
+using ::android::hardware::Void;
using ::android::hardware::hidl_vec;
+using ::android::hardware::tv::tuner::V1_0::DemuxFilterMainType;
+using ::android::hardware::tv::tuner::V1_0::DemuxTsFilterType;
using ::android::hardware::tv::tuner::V1_0::ITuner;
using ::android::hardware::tv::tuner::V1_0::Result;
struct fields_t {
jfieldID context;
jmethodID frontendInitID;
+ jmethodID filterInitID;
+ jmethodID onFrontendEventID;
};
static fields_t gFields;
namespace android {
+/////////////// FilterCallback ///////////////////////
+//TODO: implement filter callback
+Return<void> FilterCallback::onFilterEvent(const DemuxFilterEvent& /* filterEvent */) {
+ ALOGD("FilterCallback::onFilterEvent");
+ return Void();
+}
+Return<void> FilterCallback::onFilterStatus(const DemuxFilterStatus /*status*/) {
+ ALOGD("FilterCallback::onFilterStatu");
+ return Void();
+}
+
+/////////////// FrontendCallback ///////////////////////
+
+FrontendCallback::FrontendCallback(jweak tunerObj, FrontendId id) : mObject(tunerObj), mId(id) {}
+
+Return<void> FrontendCallback::onEvent(FrontendEventType frontendEventType) {
+ ALOGD("FrontendCallback::onEvent, type=%d", frontendEventType);
+ JNIEnv *env = AndroidRuntime::getJNIEnv();
+ env->CallVoidMethod(
+ mObject,
+ gFields.onFrontendEventID,
+ (jint)frontendEventType);
+ return Void();
+}
+Return<void> FrontendCallback::onDiseqcMessage(const hidl_vec<uint8_t>& /*diseqcMessage*/) {
+ ALOGD("FrontendCallback::onDiseqcMessage");
+ return Void();
+}
+
+Return<void> FrontendCallback::onScanMessage(
+ FrontendScanMessageType type, const FrontendScanMessage& /*message*/) {
+ ALOGD("FrontendCallback::onScanMessage, type=%d", type);
+ return Void();
+}
+
+/////////////// Tuner ///////////////////////
sp<ITuner> JTuner::mTuner;
@@ -74,11 +115,10 @@ sp<ITuner> JTuner::getTunerService() {
jobject JTuner::getFrontendIds() {
ALOGD("JTuner::getFrontendIds()");
- hidl_vec<FrontendId> feIds;
mTuner->getFrontendIds([&](Result, const hidl_vec<FrontendId>& frontendIds) {
- feIds = frontendIds;
+ mFeIds = frontendIds;
});
- if (feIds.size() == 0) {
+ if (mFeIds.size() == 0) {
ALOGW("Frontend isn't available");
return NULL;
}
@@ -91,21 +131,25 @@ jobject JTuner::getFrontendIds() {
jclass integerClazz = env->FindClass("java/lang/Integer");
jmethodID intInit = env->GetMethodID(integerClazz, "<init>", "(I)V");
- for (int i=0; i < feIds.size(); i++) {
- jobject idObj = env->NewObject(integerClazz, intInit, feIds[i]);
+ for (int i=0; i < mFeIds.size(); i++) {
+ jobject idObj = env->NewObject(integerClazz, intInit, mFeIds[i]);
env->CallBooleanMethod(obj, arrayListAdd, idObj);
}
return obj;
}
jobject JTuner::openFrontendById(int id) {
+ sp<IFrontend> fe;
mTuner->openFrontendById(id, [&](Result, const sp<IFrontend>& frontend) {
- mFe = frontend;
+ fe = frontend;
});
- if (mFe == nullptr) {
+ if (fe == nullptr) {
ALOGE("Failed to open frontend");
return NULL;
}
+ mFe = fe;
+ sp<FrontendCallback> feCb = new FrontendCallback(mObject, id);
+ fe->setCallback(feCb);
jint jId = (jint) id;
JNIEnv *env = AndroidRuntime::getJNIEnv();
@@ -113,9 +157,58 @@ jobject JTuner::openFrontendById(int id) {
return env->NewObject(
env->FindClass("android/media/tv/tuner/Tuner$Frontend"),
gFields.frontendInitID,
+ mObject,
(jint) jId);
}
+bool JTuner::openDemux() {
+ if (mTuner == nullptr) {
+ return false;
+ }
+ if (mDemux != nullptr) {
+ return true;
+ }
+ mTuner->openDemux([&](Result, uint32_t demuxId, const sp<IDemux>& demux) {
+ mDemux = demux;
+ mDemuxId = demuxId;
+ ALOGD("open demux, id = %d", demuxId);
+ });
+ if (mDemux == nullptr) {
+ return false;
+ }
+ return true;
+}
+
+jobject JTuner::openFilter(DemuxFilterType type, int bufferSize) {
+ if (mDemux == NULL) {
+ if (!openDemux()) {
+ return NULL;
+ }
+ }
+
+ sp<IFilter> f;
+ mDemux->openFilter(type, bufferSize, new FilterCallback,
+ [&](Result, const sp<IFilter>& filter) {
+ f = filter;
+ });
+ if (f == NULL) {
+ ALOGD("Failed to open filter, type = %d", type.mainType);
+ return NULL;
+ }
+ int fId;
+ f->getId([&](Result, uint32_t filterId) {
+ fId = filterId;
+ });
+ mFilters[fId] = f;
+
+ JNIEnv *env = AndroidRuntime::getJNIEnv();
+ return env->NewObject(
+ env->FindClass("android/media/tv/tuner/Tuner$Filter"),
+ gFields.filterInitID,
+ mObject,
+ (jint) fId);
+}
+
} // namespace android
////////////////////////////////////////////////////////////////////////////////
@@ -147,8 +240,15 @@ static void android_media_tv_Tuner_native_init(JNIEnv *env) {
gFields.context = env->GetFieldID(clazz, "mNativeContext", "J");
CHECK(gFields.context != NULL);
+ gFields.onFrontendEventID = env->GetMethodID(clazz, "onFrontendEvent", "(I)V");
+
jclass frontendClazz = env->FindClass("android/media/tv/tuner/Tuner$Frontend");
- gFields.frontendInitID = env->GetMethodID(frontendClazz, "<init>", "(I)V");
+ gFields.frontendInitID =
+ env->GetMethodID(frontendClazz, "<init>", "(Landroid/media/tv/tuner/Tuner;I)V");
+
+ jclass filterClazz = env->FindClass("android/media/tv/tuner/Tuner$Filter");
+ gFields.filterInitID =
+ env->GetMethodID(filterClazz, "<init>", "(Landroid/media/tv/tuner/Tuner;I)V");
}
static void android_media_tv_Tuner_native_setup(JNIEnv *env, jobject thiz) {
@@ -166,6 +266,19 @@ static jobject android_media_tv_Tuner_open_frontend_by_id(JNIEnv *env, jobject t
return tuner->openFrontendById(id);
}
+static jobject android_media_tv_Tuner_open_filter(
+ JNIEnv *env, jobject thiz, jint type, jint subType, jint bufferSize) {
+ sp<JTuner> tuner = getTuner(env, thiz);
+ DemuxFilterType filterType {
+ .mainType = static_cast<DemuxFilterMainType>(type),
+ };
+
+ // TODO: other sub types
+ filterType.subType.tsFilterType(static_cast<DemuxTsFilterType>(subType));
+
+ return tuner->openFilter(filterType, bufferSize);
+}
+
static const JNINativeMethod gMethods[] = {
{ "nativeInit", "()V", (void *)android_media_tv_Tuner_native_init },
{ "nativeSetup", "()V", (void *)android_media_tv_Tuner_native_setup },
@@ -173,6 +286,8 @@ static const JNINativeMethod gMethods[] = {
(void *)android_media_tv_Tuner_get_frontend_ids },
{ "nativeOpenFrontendById", "(I)Landroid/media/tv/tuner/Tuner$Frontend;",
(void *)android_media_tv_Tuner_open_frontend_by_id },
+ { "nativeOpenFilter", "(III)Landroid/media/tv/tuner/Tuner$Filter;",
+ (void *)android_media_tv_Tuner_open_filter },
};
static int register_android_media_tv_Tuner(JNIEnv *env) {
diff --git a/media/jni/android_media_tv_Tuner.h b/media/jni/android_media_tv_Tuner.h
index 1425542aa648..7a889c3534da 100644
--- a/media/jni/android_media_tv_Tuner.h
+++ b/media/jni/android_media_tv_Tuner.h
@@ -18,29 +18,65 @@
#define _ANDROID_MEDIA_TV_TUNER_H_
#include <android/hardware/tv/tuner/1.0/ITuner.h>
+#include <unordered_map>
#include <utils/RefBase.h>
#include "jni.h"
+using ::android::hardware::Return;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::tv::tuner::V1_0::DemuxFilterEvent;
+using ::android::hardware::tv::tuner::V1_0::DemuxFilterStatus;
+using ::android::hardware::tv::tuner::V1_0::DemuxFilterType;
+using ::android::hardware::tv::tuner::V1_0::FrontendEventType;
using ::android::hardware::tv::tuner::V1_0::FrontendId;
+using ::android::hardware::tv::tuner::V1_0::FrontendScanMessage;
+using ::android::hardware::tv::tuner::V1_0::FrontendScanMessageType;
+using ::android::hardware::tv::tuner::V1_0::IDemux;
+using ::android::hardware::tv::tuner::V1_0::IFilter;
+using ::android::hardware::tv::tuner::V1_0::IFilterCallback;
using ::android::hardware::tv::tuner::V1_0::IFrontend;
+using ::android::hardware::tv::tuner::V1_0::IFrontendCallback;
using ::android::hardware::tv::tuner::V1_0::ITuner;
namespace android {
+struct FilterCallback : public IFilterCallback {
+ virtual Return<void> onFilterEvent(const DemuxFilterEvent& filterEvent);
+ virtual Return<void> onFilterStatus(const DemuxFilterStatus status);
+};
+
+struct FrontendCallback : public IFrontendCallback {
+ FrontendCallback(jweak tunerObj, FrontendId id);
+
+ virtual Return<void> onEvent(FrontendEventType frontendEventType);
+ virtual Return<void> onDiseqcMessage(const hidl_vec<uint8_t>& diseqcMessage);
+ virtual Return<void> onScanMessage(
+ FrontendScanMessageType type, const FrontendScanMessage& message);
+
+ jweak mObject;
+ FrontendId mId;
+};
+
struct JTuner : public RefBase {
JTuner(JNIEnv *env, jobject thiz);
sp<ITuner> getTunerService();
jobject getFrontendIds();
jobject openFrontendById(int id);
+ jobject openFilter(DemuxFilterType type, int bufferSize);
protected:
+ bool openDemux();
virtual ~JTuner();
private:
jclass mClass;
jweak mObject;
static sp<ITuner> mTuner;
+ hidl_vec<FrontendId> mFeIds;
sp<IFrontend> mFe;
+ sp<IDemux> mDemux;
+ int mDemuxId;
+ std::unordered_map<int, sp<IFilter>> mFilters;
};
} // namespace android
diff --git a/mime/java-res/android.mime.types b/mime/java-res/android.mime.types
index 7a5299ff1b69..ce022a8b0f19 100644
--- a/mime/java-res/android.mime.types
+++ b/mime/java-res/android.mime.types
@@ -48,6 +48,9 @@
?application/epub+zip epub
?application/pkix-cert cer
?application/rss+xml rss
+?application/sdp sdp
+?application/smil+xml smil
+?application/ttml+xml ttml dfxp
?application/vnd.android.ota ota
?application/vnd.apple.mpegurl m3u8
?application/vnd.ms-pki.stl stl
@@ -67,12 +70,13 @@
?application/x-x509-server-cert crt
?application/x-x509-user-cert crt
-?audio/3gpp 3gpp
+?audio/3gpp 3gpp 3ga
?audio/aac-adts aac
+?audio/ac3 ac3 a52
?audio/imelody imy
?audio/midi rtttl xmf
?audio/mobile-xmf mxmf
-?audio/mp4 m4a
+?audio/mp4 m4a m4b m4p f4a f4b f4p
?audio/mpegurl m3u
?audio/sp-midi smf
?audio/x-matroska mka
@@ -101,10 +105,11 @@
?text/xml xml
?text/x-vcard vcf
-?video/3gpp2 3gpp2 3g2
+?video/3gpp2 3gpp2 3gp2 3g2
?video/3gpp 3gpp
?video/avi avi
?video/m4v m4v
+?video/mp4 m4v f4v mp4v mpeg4
?video/mp2p mpeg
?video/mp2t m2ts mts
?video/mp2ts ts
@@ -129,11 +134,11 @@
application/pgp-signature pgp
application/x-x509-ca-cert crt
-audio/aac aac
+audio/aac aac adts adt
audio/basic snd
audio/flac flac
audio/midi rtx
-audio/mpeg mp3 m4a m4r
+audio/mpeg mp3 mp2 mp1 mpa m4a m4r
audio/x-mpegurl m3u m3u8
image/jpeg jpg
image/x-ms-bmp bmp
@@ -141,6 +146,6 @@ text/plain txt
text/x-c++hdr hpp
text/x-c++src cpp
video/3gpp 3gpp
-video/mpeg mpeg
+video/mpeg mpeg mpeg2 mpv2 mp2v m2v m2t mpeg1 mpv1 mp1v m1v
video/quicktime mov
video/x-matroska mkv
diff --git a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIBinder.java b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIBinder.java
index 706727bf050e..d3d9b286ded6 100644
--- a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIBinder.java
+++ b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIBinder.java
@@ -16,100 +16,30 @@
package com.android.systemui;
-import static com.android.systemui.Dependency.ALLOW_NOTIFICATION_LONG_PRESS_NAME;
-
-import android.content.Context;
-import android.os.PowerManager;
-import android.util.DisplayMetrics;
-
-import com.android.internal.logging.MetricsLogger;
-import com.android.keyguard.KeyguardUpdateMonitor;
-import com.android.systemui.appops.AppOpsController;
-import com.android.systemui.assist.AssistManager;
import com.android.systemui.biometrics.AuthController;
-import com.android.systemui.broadcast.BroadcastDispatcher;
-import com.android.systemui.bubbles.BubbleController;
-import com.android.systemui.colorextraction.SysuiColorExtractor;
-import com.android.systemui.doze.DozeLog;
import com.android.systemui.globalactions.GlobalActionsComponent;
import com.android.systemui.keyguard.KeyguardViewMediator;
-import com.android.systemui.keyguard.ScreenLifecycle;
-import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.navigationbar.car.CarNavigationBar;
-import com.android.systemui.navigationbar.car.CarNavigationBarController;
import com.android.systemui.pip.PipUI;
-import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.power.PowerUI;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.RecentsModule;
-import com.android.systemui.shared.plugins.PluginManager;
-import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.FeatureFlags;
-import com.android.systemui.statusbar.NavigationBarController;
-import com.android.systemui.statusbar.NotificationListener;
-import com.android.systemui.statusbar.NotificationLockscreenUserManager;
-import com.android.systemui.statusbar.NotificationMediaManager;
-import com.android.systemui.statusbar.NotificationRemoteInputManager;
-import com.android.systemui.statusbar.NotificationViewHierarchyManager;
-import com.android.systemui.statusbar.PulseExpansionHandler;
-import com.android.systemui.statusbar.SysuiStatusBarStateController;
-import com.android.systemui.statusbar.VibratorHelper;
import com.android.systemui.statusbar.car.CarStatusBar;
-import com.android.systemui.statusbar.notification.BypassHeadsUpNotifier;
-import com.android.systemui.statusbar.notification.DynamicPrivacyController;
+import com.android.systemui.statusbar.car.CarStatusBarModule;
import com.android.systemui.statusbar.notification.InstantAppNotifier;
-import com.android.systemui.statusbar.notification.NewNotifPipeline;
-import com.android.systemui.statusbar.notification.NotificationAlertingManager;
-import com.android.systemui.statusbar.notification.NotificationEntryManager;
-import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
-import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
-import com.android.systemui.statusbar.notification.VisualStabilityManager;
-import com.android.systemui.statusbar.notification.logging.NotifLog;
-import com.android.systemui.statusbar.notification.logging.NotificationLogger;
-import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
-import com.android.systemui.statusbar.phone.AutoHideController;
-import com.android.systemui.statusbar.phone.BiometricUnlockController;
-import com.android.systemui.statusbar.phone.DozeParameters;
-import com.android.systemui.statusbar.phone.DozeScrimController;
-import com.android.systemui.statusbar.phone.DozeServiceHost;
-import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
-import com.android.systemui.statusbar.phone.KeyguardBypassController;
-import com.android.systemui.statusbar.phone.LightBarController;
-import com.android.systemui.statusbar.phone.LockscreenWallpaper;
-import com.android.systemui.statusbar.phone.NotificationGroupAlertTransferHelper;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
-import com.android.systemui.statusbar.phone.ScrimController;
import com.android.systemui.statusbar.phone.StatusBar;
-import com.android.systemui.statusbar.phone.StatusBarIconController;
-import com.android.systemui.statusbar.phone.StatusBarWindowController;
-import com.android.systemui.statusbar.phone.StatusBarWindowViewController;
-import com.android.systemui.statusbar.policy.BatteryController;
-import com.android.systemui.statusbar.policy.ConfigurationController;
-import com.android.systemui.statusbar.policy.DeviceProvisionedController;
-import com.android.systemui.statusbar.policy.KeyguardStateController;
-import com.android.systemui.statusbar.policy.NetworkController;
-import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler;
-import com.android.systemui.statusbar.policy.RemoteInputUriController;
-import com.android.systemui.statusbar.policy.UserSwitcherController;
-import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.statusbar.tv.TvStatusBar;
import com.android.systemui.theme.ThemeOverlayController;
-import com.android.systemui.util.InjectionInflationController;
import com.android.systemui.util.leak.GarbageMonitor;
import com.android.systemui.volume.VolumeUI;
-import javax.inject.Named;
-import javax.inject.Singleton;
-
import dagger.Binds;
-import dagger.Lazy;
import dagger.Module;
-import dagger.Provides;
import dagger.multibindings.ClassKey;
import dagger.multibindings.IntoMap;
/** Binder for car specific {@link SystemUI} modules. */
-@Module(includes = {RecentsModule.class})
+@Module(includes = {RecentsModule.class, CarStatusBarModule.class})
public abstract class CarSystemUIBinder {
/** Inject into AuthController. */
@Binds
@@ -219,147 +149,4 @@ public abstract class CarSystemUIBinder {
@IntoMap
@ClassKey(VolumeUI.class)
public abstract SystemUI bindVolumeUI(VolumeUI sysui);
-
- /**
- * Provides our instance of StatusBar which is considered optional.
- */
- @Provides
- @Singleton
- static CarStatusBar provideStatusBar(
- Context context,
- FeatureFlags featureFlags,
- LightBarController lightBarController,
- AutoHideController autoHideController,
- KeyguardUpdateMonitor keyguardUpdateMonitor,
- StatusBarIconController statusBarIconController,
- DozeLog dozeLog,
- InjectionInflationController injectionInflationController,
- PulseExpansionHandler pulseExpansionHandler,
- NotificationWakeUpCoordinator notificationWakeUpCoordinator,
- KeyguardBypassController keyguardBypassController,
- KeyguardStateController keyguardStateController,
- HeadsUpManagerPhone headsUpManagerPhone,
- DynamicPrivacyController dynamicPrivacyController,
- BypassHeadsUpNotifier bypassHeadsUpNotifier,
- @Named(ALLOW_NOTIFICATION_LONG_PRESS_NAME) boolean allowNotificationLongPress,
- Lazy<NewNotifPipeline> newNotifPipeline,
- FalsingManager falsingManager,
- BroadcastDispatcher broadcastDispatcher,
- RemoteInputQuickSettingsDisabler remoteInputQuickSettingsDisabler,
- NotificationGutsManager notificationGutsManager,
- NotificationLogger notificationLogger,
- NotificationEntryManager notificationEntryManager,
- NotificationInterruptionStateProvider notificationInterruptionStateProvider,
- NotificationViewHierarchyManager notificationViewHierarchyManager,
- ForegroundServiceController foregroundServiceController,
- AppOpsController appOpsController,
- KeyguardViewMediator keyguardViewMediator,
- ZenModeController zenModeController,
- NotificationAlertingManager notificationAlertingManager,
- DisplayMetrics displayMetrics,
- MetricsLogger metricsLogger,
- UiOffloadThread uiOffloadThread,
- NotificationMediaManager notificationMediaManager,
- NotificationLockscreenUserManager lockScreenUserManager,
- NotificationRemoteInputManager remoteInputManager,
- UserSwitcherController userSwitcherController,
- NetworkController networkController,
- BatteryController batteryController,
- SysuiColorExtractor colorExtractor,
- ScreenLifecycle screenLifecycle,
- WakefulnessLifecycle wakefulnessLifecycle,
- SysuiStatusBarStateController statusBarStateController,
- VibratorHelper vibratorHelper,
- BubbleController bubbleController,
- NotificationGroupManager groupManager,
- NotificationGroupAlertTransferHelper groupAlertTransferHelper,
- VisualStabilityManager visualStabilityManager,
- DeviceProvisionedController deviceProvisionedController,
- NavigationBarController navigationBarController,
- AssistManager assistManager,
- NotificationListener notificationListener,
- ConfigurationController configurationController,
- StatusBarWindowController statusBarWindowController,
- StatusBarWindowViewController.Builder statusBarWindowViewControllerBuilder,
- NotifLog notifLog,
- DozeParameters dozeParameters,
- ScrimController scrimController,
- Lazy<LockscreenWallpaper> lockscreenWallpaperLazy,
- Lazy<BiometricUnlockController> biometricUnlockControllerLazy,
- DozeServiceHost dozeServiceHost,
- PowerManager powerManager,
- DozeScrimController dozeScrimController,
- CommandQueue commandQueue,
- PluginManager pluginManager,
- CarNavigationBarController carNavigationBarController,
- RemoteInputUriController remoteInputUriController) {
- return new CarStatusBar(
- context,
- featureFlags,
- lightBarController,
- autoHideController,
- keyguardUpdateMonitor,
- statusBarIconController,
- dozeLog,
- injectionInflationController,
- pulseExpansionHandler,
- notificationWakeUpCoordinator,
- keyguardBypassController,
- keyguardStateController,
- headsUpManagerPhone,
- dynamicPrivacyController,
- bypassHeadsUpNotifier,
- allowNotificationLongPress,
- newNotifPipeline,
- falsingManager,
- broadcastDispatcher,
- remoteInputQuickSettingsDisabler,
- notificationGutsManager,
- notificationLogger,
- notificationEntryManager,
- notificationInterruptionStateProvider,
- notificationViewHierarchyManager,
- foregroundServiceController,
- appOpsController,
- keyguardViewMediator,
- zenModeController,
- notificationAlertingManager,
- displayMetrics,
- metricsLogger,
- uiOffloadThread,
- notificationMediaManager,
- lockScreenUserManager,
- remoteInputManager,
- userSwitcherController,
- networkController,
- batteryController,
- colorExtractor,
- screenLifecycle,
- wakefulnessLifecycle,
- statusBarStateController,
- vibratorHelper,
- bubbleController,
- groupManager,
- groupAlertTransferHelper,
- visualStabilityManager,
- deviceProvisionedController,
- navigationBarController,
- assistManager,
- notificationListener,
- configurationController,
- statusBarWindowController,
- statusBarWindowViewControllerBuilder,
- notifLog,
- dozeParameters,
- scrimController,
- lockscreenWallpaperLazy,
- biometricUnlockControllerLazy,
- dozeServiceHost,
- powerManager,
- dozeScrimController,
- commandQueue,
- pluginManager,
- remoteInputUriController,
- carNavigationBarController);
- }
}
diff --git a/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationBar.java b/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationBar.java
index 98b91ebd8038..af92767efc49 100644
--- a/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationBar.java
+++ b/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationBar.java
@@ -53,13 +53,13 @@ public class CarNavigationBar extends SystemUI implements CommandQueue.Callbacks
private final CarNavigationBarController mCarNavigationBarController;
private final WindowManager mWindowManager;
private final DeviceProvisionedController mDeviceProvisionedController;
+ private final CommandQueue mCommandQueue;
private final Lazy<FacetButtonTaskStackListener> mFacetButtonTaskStackListener;
private final Handler mMainHandler;
private final Lazy<KeyguardStateController> mKeyguardStateController;
private final Lazy<NavigationBarController> mNavigationBarController;
private IStatusBarService mBarService;
- private CommandQueue mCommandQueue;
private ActivityManagerWrapper mActivityManagerWrapper;
// If the nav bar should be hidden when the soft keyboard is visible.
@@ -83,6 +83,7 @@ public class CarNavigationBar extends SystemUI implements CommandQueue.Callbacks
CarNavigationBarController carNavigationBarController,
WindowManager windowManager,
DeviceProvisionedController deviceProvisionedController,
+ CommandQueue commandQueue,
Lazy<FacetButtonTaskStackListener> facetButtonTaskStackListener,
@MainHandler Handler mainHandler,
Lazy<KeyguardStateController> keyguardStateController,
@@ -91,6 +92,7 @@ public class CarNavigationBar extends SystemUI implements CommandQueue.Callbacks
mCarNavigationBarController = carNavigationBarController;
mWindowManager = windowManager;
mDeviceProvisionedController = deviceProvisionedController;
+ mCommandQueue = commandQueue;
mFacetButtonTaskStackListener = facetButtonTaskStackListener;
mMainHandler = mainHandler;
mKeyguardStateController = keyguardStateController;
@@ -109,7 +111,6 @@ public class CarNavigationBar extends SystemUI implements CommandQueue.Callbacks
ServiceManager.getService(Context.STATUS_BAR_SERVICE));
// Connect into the status bar manager service
- mCommandQueue = getComponent(CommandQueue.class);
mCommandQueue.addCallback(this);
RegisterStatusBarResult result = null;
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
index 110b32b57878..fc0b317d04ff 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -92,6 +92,7 @@ import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.NotificationViewHierarchyManager;
import com.android.systemui.statusbar.PulseExpansionHandler;
import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.SuperStatusBarViewFactory;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.VibratorHelper;
import com.android.systemui.statusbar.notification.BypassHeadsUpNotifier;
@@ -131,7 +132,6 @@ import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler;
import com.android.systemui.statusbar.policy.RemoteInputUriController;
import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.statusbar.policy.ZenModeController;
-import com.android.systemui.util.InjectionInflationController;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -244,7 +244,6 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt
KeyguardUpdateMonitor keyguardUpdateMonitor,
StatusBarIconController statusBarIconController,
DozeLog dozeLog,
- InjectionInflationController injectionInflationController,
PulseExpansionHandler pulseExpansionHandler,
NotificationWakeUpCoordinator notificationWakeUpCoordinator,
KeyguardBypassController keyguardBypassController,
@@ -303,6 +302,7 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt
CommandQueue commandQueue,
PluginManager pluginManager,
RemoteInputUriController remoteInputUriController,
+ SuperStatusBarViewFactory superStatusBarViewFactory,
/* Car Settings injected components. */
CarNavigationBarController carNavigationBarController) {
super(
@@ -313,7 +313,6 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt
keyguardUpdateMonitor,
statusBarIconController,
dozeLog,
- injectionInflationController,
pulseExpansionHandler,
notificationWakeUpCoordinator,
keyguardBypassController,
@@ -372,7 +371,8 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt
dozeScrimController,
commandQueue,
pluginManager,
- remoteInputUriController);
+ remoteInputUriController,
+ superStatusBarViewFactory);
mScrimController = scrimController;
mCarNavigationBarController = carNavigationBarController;
}
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarModule.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarModule.java
new file mode 100644
index 000000000000..b19fae891a58
--- /dev/null
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarModule.java
@@ -0,0 +1,244 @@
+/*
+ * 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.
+ */
+
+package com.android.systemui.statusbar.car;
+
+import static com.android.systemui.Dependency.ALLOW_NOTIFICATION_LONG_PRESS_NAME;
+
+import android.content.Context;
+import android.os.PowerManager;
+import android.util.DisplayMetrics;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.systemui.ForegroundServiceController;
+import com.android.systemui.UiOffloadThread;
+import com.android.systemui.appops.AppOpsController;
+import com.android.systemui.assist.AssistManager;
+import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.bubbles.BubbleController;
+import com.android.systemui.colorextraction.SysuiColorExtractor;
+import com.android.systemui.doze.DozeLog;
+import com.android.systemui.keyguard.KeyguardViewMediator;
+import com.android.systemui.keyguard.ScreenLifecycle;
+import com.android.systemui.keyguard.WakefulnessLifecycle;
+import com.android.systemui.navigationbar.car.CarNavigationBarController;
+import com.android.systemui.plugins.FalsingManager;
+import com.android.systemui.shared.plugins.PluginManager;
+import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.FeatureFlags;
+import com.android.systemui.statusbar.NavigationBarController;
+import com.android.systemui.statusbar.NotificationListener;
+import com.android.systemui.statusbar.NotificationLockscreenUserManager;
+import com.android.systemui.statusbar.NotificationMediaManager;
+import com.android.systemui.statusbar.NotificationRemoteInputManager;
+import com.android.systemui.statusbar.NotificationViewHierarchyManager;
+import com.android.systemui.statusbar.PulseExpansionHandler;
+import com.android.systemui.statusbar.StatusBarDependenciesModule;
+import com.android.systemui.statusbar.SuperStatusBarViewFactory;
+import com.android.systemui.statusbar.SysuiStatusBarStateController;
+import com.android.systemui.statusbar.VibratorHelper;
+import com.android.systemui.statusbar.notification.BypassHeadsUpNotifier;
+import com.android.systemui.statusbar.notification.DynamicPrivacyController;
+import com.android.systemui.statusbar.notification.NewNotifPipeline;
+import com.android.systemui.statusbar.notification.NotificationAlertingManager;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
+import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
+import com.android.systemui.statusbar.notification.VisualStabilityManager;
+import com.android.systemui.statusbar.notification.logging.NotifLog;
+import com.android.systemui.statusbar.notification.logging.NotificationLogger;
+import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
+import com.android.systemui.statusbar.phone.AutoHideController;
+import com.android.systemui.statusbar.phone.BiometricUnlockController;
+import com.android.systemui.statusbar.phone.DozeParameters;
+import com.android.systemui.statusbar.phone.DozeScrimController;
+import com.android.systemui.statusbar.phone.DozeServiceHost;
+import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
+import com.android.systemui.statusbar.phone.KeyguardBypassController;
+import com.android.systemui.statusbar.phone.LightBarController;
+import com.android.systemui.statusbar.phone.LockscreenWallpaper;
+import com.android.systemui.statusbar.phone.NotificationGroupAlertTransferHelper;
+import com.android.systemui.statusbar.phone.NotificationGroupManager;
+import com.android.systemui.statusbar.phone.ScrimController;
+import com.android.systemui.statusbar.phone.StatusBarIconController;
+import com.android.systemui.statusbar.phone.StatusBarWindowController;
+import com.android.systemui.statusbar.phone.StatusBarWindowViewController;
+import com.android.systemui.statusbar.policy.BatteryController;
+import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.statusbar.policy.NetworkController;
+import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler;
+import com.android.systemui.statusbar.policy.RemoteInputUriController;
+import com.android.systemui.statusbar.policy.UserSwitcherController;
+import com.android.systemui.statusbar.policy.ZenModeController;
+
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import dagger.Lazy;
+import dagger.Module;
+import dagger.Provides;
+
+/**
+ * Dagger Module providing {@link CarStatusBar}.
+ */
+@Module(includes = {StatusBarDependenciesModule.class})
+public class CarStatusBarModule {
+ /**
+ * Provides our instance of StatusBar which is considered optional.
+ */
+ @Provides
+ @Singleton
+ static CarStatusBar provideStatusBar(
+ Context context,
+ FeatureFlags featureFlags,
+ LightBarController lightBarController,
+ AutoHideController autoHideController,
+ KeyguardUpdateMonitor keyguardUpdateMonitor,
+ StatusBarIconController statusBarIconController,
+ DozeLog dozeLog,
+ PulseExpansionHandler pulseExpansionHandler,
+ NotificationWakeUpCoordinator notificationWakeUpCoordinator,
+ KeyguardBypassController keyguardBypassController,
+ KeyguardStateController keyguardStateController,
+ HeadsUpManagerPhone headsUpManagerPhone,
+ DynamicPrivacyController dynamicPrivacyController,
+ BypassHeadsUpNotifier bypassHeadsUpNotifier,
+ @Named(ALLOW_NOTIFICATION_LONG_PRESS_NAME) boolean allowNotificationLongPress,
+ Lazy<NewNotifPipeline> newNotifPipeline,
+ FalsingManager falsingManager,
+ BroadcastDispatcher broadcastDispatcher,
+ RemoteInputQuickSettingsDisabler remoteInputQuickSettingsDisabler,
+ NotificationGutsManager notificationGutsManager,
+ NotificationLogger notificationLogger,
+ NotificationEntryManager notificationEntryManager,
+ NotificationInterruptionStateProvider notificationInterruptionStateProvider,
+ NotificationViewHierarchyManager notificationViewHierarchyManager,
+ ForegroundServiceController foregroundServiceController,
+ AppOpsController appOpsController,
+ KeyguardViewMediator keyguardViewMediator,
+ ZenModeController zenModeController,
+ NotificationAlertingManager notificationAlertingManager,
+ DisplayMetrics displayMetrics,
+ MetricsLogger metricsLogger,
+ UiOffloadThread uiOffloadThread,
+ NotificationMediaManager notificationMediaManager,
+ NotificationLockscreenUserManager lockScreenUserManager,
+ NotificationRemoteInputManager remoteInputManager,
+ UserSwitcherController userSwitcherController,
+ NetworkController networkController,
+ BatteryController batteryController,
+ SysuiColorExtractor colorExtractor,
+ ScreenLifecycle screenLifecycle,
+ WakefulnessLifecycle wakefulnessLifecycle,
+ SysuiStatusBarStateController statusBarStateController,
+ VibratorHelper vibratorHelper,
+ BubbleController bubbleController,
+ NotificationGroupManager groupManager,
+ NotificationGroupAlertTransferHelper groupAlertTransferHelper,
+ VisualStabilityManager visualStabilityManager,
+ DeviceProvisionedController deviceProvisionedController,
+ NavigationBarController navigationBarController,
+ AssistManager assistManager,
+ NotificationListener notificationListener,
+ ConfigurationController configurationController,
+ StatusBarWindowController statusBarWindowController,
+ StatusBarWindowViewController.Builder statusBarWindowViewControllerBuilder,
+ NotifLog notifLog,
+ DozeParameters dozeParameters,
+ ScrimController scrimController,
+ Lazy<LockscreenWallpaper> lockscreenWallpaperLazy,
+ Lazy<BiometricUnlockController> biometricUnlockControllerLazy,
+ DozeServiceHost dozeServiceHost,
+ PowerManager powerManager,
+ DozeScrimController dozeScrimController,
+ CommandQueue commandQueue,
+ PluginManager pluginManager,
+ RemoteInputUriController remoteInputUriController,
+ SuperStatusBarViewFactory superStatusBarViewFactory,
+ CarNavigationBarController carNavigationBarController) {
+ return new CarStatusBar(
+ context,
+ featureFlags,
+ lightBarController,
+ autoHideController,
+ keyguardUpdateMonitor,
+ statusBarIconController,
+ dozeLog,
+ pulseExpansionHandler,
+ notificationWakeUpCoordinator,
+ keyguardBypassController,
+ keyguardStateController,
+ headsUpManagerPhone,
+ dynamicPrivacyController,
+ bypassHeadsUpNotifier,
+ allowNotificationLongPress,
+ newNotifPipeline,
+ falsingManager,
+ broadcastDispatcher,
+ remoteInputQuickSettingsDisabler,
+ notificationGutsManager,
+ notificationLogger,
+ notificationEntryManager,
+ notificationInterruptionStateProvider,
+ notificationViewHierarchyManager,
+ foregroundServiceController,
+ appOpsController,
+ keyguardViewMediator,
+ zenModeController,
+ notificationAlertingManager,
+ displayMetrics,
+ metricsLogger,
+ uiOffloadThread,
+ notificationMediaManager,
+ lockScreenUserManager,
+ remoteInputManager,
+ userSwitcherController,
+ networkController,
+ batteryController,
+ colorExtractor,
+ screenLifecycle,
+ wakefulnessLifecycle,
+ statusBarStateController,
+ vibratorHelper,
+ bubbleController,
+ groupManager,
+ groupAlertTransferHelper,
+ visualStabilityManager,
+ deviceProvisionedController,
+ navigationBarController,
+ assistManager,
+ notificationListener,
+ configurationController,
+ statusBarWindowController,
+ statusBarWindowViewControllerBuilder,
+ notifLog,
+ dozeParameters,
+ scrimController,
+ lockscreenWallpaperLazy,
+ biometricUnlockControllerLazy,
+ dozeServiceHost,
+ powerManager,
+ dozeScrimController,
+ commandQueue,
+ pluginManager,
+ remoteInputUriController,
+ superStatusBarViewFactory,
+ carNavigationBarController);
+ }
+}
diff --git a/packages/SettingsLib/search/processor-src/com/android/settingslib/search/IndexableProcessor.java b/packages/SettingsLib/search/processor-src/com/android/settingslib/search/IndexableProcessor.java
index 5dc9061a81a0..de45ea536e27 100644
--- a/packages/SettingsLib/search/processor-src/com/android/settingslib/search/IndexableProcessor.java
+++ b/packages/SettingsLib/search/processor-src/com/android/settingslib/search/IndexableProcessor.java
@@ -21,7 +21,6 @@ import com.squareup.javapoet.FieldSpec;
import com.squareup.javapoet.JavaFile;
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.ParameterizedTypeName;
-import com.squareup.javapoet.TypeName;
import com.squareup.javapoet.TypeSpec;
import java.io.IOException;
@@ -73,10 +72,12 @@ public class IndexableProcessor extends AbstractProcessor {
}
mRanOnce = true;
+ final ClassName searchIndexableData = ClassName.get(PACKAGE, "SearchIndexableData");
+
final FieldSpec providers = FieldSpec.builder(
ParameterizedTypeName.get(
ClassName.get(Set.class),
- TypeName.get(Class.class)),
+ searchIndexableData),
"mProviders",
Modifier.PRIVATE, Modifier.FINAL)
.initializer("new $T()", HashSet.class)
@@ -84,7 +85,7 @@ public class IndexableProcessor extends AbstractProcessor {
final MethodSpec addIndex = MethodSpec.methodBuilder("addIndex")
.addModifiers(Modifier.PUBLIC)
- .addParameter(ClassName.get(Class.class), "indexClass")
+ .addParameter(searchIndexableData, "indexClass")
.addCode("$N.add(indexClass);\n", providers)
.build();
@@ -113,19 +114,25 @@ public class IndexableProcessor extends AbstractProcessor {
SearchIndexable searchIndexable = element.getAnnotation(SearchIndexable.class);
int forTarget = searchIndexable.forTarget();
+ MethodSpec.Builder builder = baseConstructorBuilder;
+
if (forTarget == SearchIndexable.ALL) {
- baseConstructorBuilder.addCode("$N($L.class);\n", addIndex, className);
+ builder = baseConstructorBuilder;
} else if ((forTarget & SearchIndexable.MOBILE) != 0) {
- mobileConstructorBuilder.addCode("$N($L.class);\n", addIndex, className);
+ builder = mobileConstructorBuilder;
} else if ((forTarget & SearchIndexable.TV) != 0) {
- tvConstructorBuilder.addCode("$N($L.class);\n", addIndex, className);
+ builder = tvConstructorBuilder;
} else if ((forTarget & SearchIndexable.WEAR) != 0) {
- wearConstructorBuilder.addCode("$N($L.class);\n", addIndex, className);
+ builder = wearConstructorBuilder;
} else if ((forTarget & SearchIndexable.AUTO) != 0) {
- autoConstructorBuilder.addCode("$N($L.class);\n", addIndex, className);
+ builder = autoConstructorBuilder;
} else if ((forTarget & SearchIndexable.ARC) != 0) {
- arcConstructorBuilder.addCode("$N($L.class);\n", addIndex, className);
+ builder = arcConstructorBuilder;
}
+ builder.addCode(
+ "$N(new SearchIndexableData($L.class, $L"
+ + ".SEARCH_INDEX_DATA_PROVIDER));\n",
+ addIndex, className, className);
} else {
throw new IllegalStateException("Null classname from " + element);
}
@@ -137,7 +144,7 @@ public class IndexableProcessor extends AbstractProcessor {
.addModifiers(Modifier.PUBLIC)
.returns(ParameterizedTypeName.get(
ClassName.get(Collection.class),
- TypeName.get(Class.class)))
+ searchIndexableData))
.addCode("return $N;\n", providers)
.build();
diff --git a/packages/SettingsLib/search/src/com/android/settingslib/search/SearchIndexableData.java b/packages/SettingsLib/search/src/com/android/settingslib/search/SearchIndexableData.java
new file mode 100644
index 000000000000..8b8f2688b93f
--- /dev/null
+++ b/packages/SettingsLib/search/src/com/android/settingslib/search/SearchIndexableData.java
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+
+package com.android.settingslib.search;
+
+/**
+ * A Bundle class used in {@link SearchIndexableResources} to provide search Index data.
+ */
+public class SearchIndexableData {
+ private final Class mTargetClass;
+ private final Indexable.SearchIndexProvider mSearchIndexProvider;
+
+ /**
+ * Constructs a SearchIndexableData
+ *
+ * @param targetClass The target opening class of the {@link Indexable.SearchIndexProvider}. It
+ * should be a {@link android.app.Activity} or fragment {@link
+ * androidx.fragment.app.Fragment}.
+ * But fragment is only supported in Android Settings. Other apps should use
+ * {@link android.app.Activity}
+ * @param provider provides searchable data for Android Settings
+ */
+ public SearchIndexableData(Class targetClass, Indexable.SearchIndexProvider provider) {
+ mTargetClass = targetClass;
+ mSearchIndexProvider = provider;
+ }
+
+ public Class getTargetClass() {
+ return mTargetClass;
+ }
+
+ public Indexable.SearchIndexProvider getSearchIndexProvider() {
+ return mSearchIndexProvider;
+ }
+}
diff --git a/packages/SettingsLib/search/src/com/android/settingslib/search/SearchIndexableResources.java b/packages/SettingsLib/search/src/com/android/settingslib/search/SearchIndexableResources.java
index 976647b3e88f..e00ca718ce1c 100644
--- a/packages/SettingsLib/search/src/com/android/settingslib/search/SearchIndexableResources.java
+++ b/packages/SettingsLib/search/src/com/android/settingslib/search/SearchIndexableResources.java
@@ -21,15 +21,12 @@ import java.util.Collection;
public interface SearchIndexableResources {
/**
- * Returns a collection of classes that should be indexed for search.
- *
- * Each class should have the SEARCH_INDEX_DATA_PROVIDER public static member.
+ * Returns a Collection of {@link SearchIndexableData} that should be indexed for search.
*/
- Collection<Class> getProviderValues();
+ Collection<SearchIndexableData> getProviderValues();
/**
- * For testing. Can't use @VisibleForTesting here because this builds as a host binary as well
- * as a device binary.
+ * Add {@link SearchIndexableData} for search in Android Settings.
*/
- void addIndex(Class indexClass);
+ void addIndex(SearchIndexableData indexBundle);
} \ No newline at end of file
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 14371fe4b41b..64b2892efc9a 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -1120,8 +1120,6 @@
<dimen name="bubble_touch_padding">12dp</dimen>
<!-- Size of the circle around the bubbles when they're in the dismiss target. -->
<dimen name="bubble_dismiss_encircle_size">52dp</dimen>
- <!-- How much to inset the icon in the circle -->
- <dimen name="bubble_icon_inset">16dp</dimen>
<!-- Padding around the view displayed when the bubble is expanded -->
<dimen name="bubble_expanded_view_padding">4dp</dimen>
<!-- This should be at least the size of bubble_expanded_view_padding; it is used to include
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java
index 074ef53aa57c..acce41cc942e 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java
@@ -56,7 +56,9 @@ public class TaskStackChangeListeners extends TaskStackListener {
}
public void addListener(IActivityManager am, TaskStackChangeListener listener) {
- mTaskStackListeners.add(listener);
+ synchronized (mTaskStackListeners) {
+ mTaskStackListeners.add(listener);
+ }
if (!mRegistered) {
// Register mTaskStackListener to IActivityManager only once if needed.
try {
@@ -69,8 +71,12 @@ public class TaskStackChangeListeners extends TaskStackListener {
}
public void removeListener(TaskStackChangeListener listener) {
- mTaskStackListeners.remove(listener);
- if (mTaskStackListeners.isEmpty() && mRegistered) {
+ boolean isEmpty;
+ synchronized (mTaskStackListeners) {
+ mTaskStackListeners.remove(listener);
+ isEmpty = mTaskStackListeners.isEmpty();
+ }
+ if (isEmpty && mRegistered) {
// Unregister mTaskStackListener once we have no more listeners
try {
ActivityTaskManager.getService().unregisterTaskStackListener(this);
@@ -83,14 +89,17 @@ public class TaskStackChangeListeners extends TaskStackListener {
@Override
public void onTaskStackChanged() throws RemoteException {
- // Call the task changed callback for the non-ui thread listeners first
+ // Call the task changed callback for the non-ui thread listeners first. Copy to a set of
+ // temp listeners so that we don't lock on mTaskStackListeners while calling all the
+ // callbacks. This call is always on the same binder thread, so we can just synchronize
+ // on the copying of the listener list.
synchronized (mTaskStackListeners) {
- mTmpListeners.clear();
mTmpListeners.addAll(mTaskStackListeners);
}
for (int i = mTmpListeners.size() - 1; i >= 0; i--) {
mTmpListeners.get(i).onTaskStackChangedBackground();
}
+ mTmpListeners.clear();
mHandler.removeMessages(H.ON_TASK_STACK_CHANGED);
mHandler.sendEmptyMessage(H.ON_TASK_STACK_CHANGED);
diff --git a/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java b/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
index 46b4c6b7d44c..21b52c1e5b57 100644
--- a/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
+++ b/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
@@ -169,12 +169,15 @@ public class CarrierTextController {
mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
mSeparator = separator;
mWakefulnessLifecycle = Dependency.get(WakefulnessLifecycle.class);
- mSimSlotsNumber = ((TelephonyManager) context.getSystemService(
- Context.TELEPHONY_SERVICE)).getSupportedModemCount();
+ mSimSlotsNumber = getTelephonyManager().getSupportedModemCount();
mSimErrorState = new boolean[mSimSlotsNumber];
mMainHandler = Dependency.get(Dependency.MAIN_HANDLER);
}
+ private TelephonyManager getTelephonyManager() {
+ return (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
+ }
+
/**
* Checks if there are faulty cards. Adds the text depending on the slot of the card
*
@@ -190,7 +193,7 @@ public class CarrierTextController {
CharSequence carrierTextForSimIOError = getCarrierTextForSimState(
IccCardConstants.State.CARD_IO_ERROR, carrier);
// mSimErrorState has the state of each sim indexed by slotID.
- for (int index = 0; index < mSimErrorState.length; index++) {
+ for (int index = 0; index < getTelephonyManager().getActiveModemCount(); index++) {
if (!mSimErrorState[index]) {
continue;
}
@@ -223,8 +226,7 @@ public class CarrierTextController {
* @param callback Callback to provide text updates
*/
public void setListening(CarrierTextCallback callback) {
- TelephonyManager telephonyManager = ((TelephonyManager) mContext
- .getSystemService(Context.TELEPHONY_SERVICE));
+ TelephonyManager telephonyManager = getTelephonyManager();
if (callback != null) {
mCarrierTextCallback = callback;
// TODO(b/140034799)
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java
index 9c0a71c1f81d..b1502b9a0d63 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java
@@ -104,7 +104,12 @@ public class KeyguardSimPinView extends KeyguardPinBasedInputView {
private void setLockedSimMessage() {
boolean isEsimLocked = KeyguardEsimArea.isEsimLocked(mContext, mSubId);
- int count = TelephonyManager.getDefault().getSimCount();
+ int count = 1;
+ TelephonyManager telephonyManager =
+ (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
+ if (telephonyManager != null) {
+ count = telephonyManager.getActiveModemCount();
+ }
Resources rez = getResources();
String msg;
TypedArray array = mContext.obtainStyledAttributes(new int[] { R.attr.wallpaperTextColor });
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
index fc888e11d3f5..70237a053e1e 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
@@ -164,7 +164,12 @@ public class KeyguardSimPukView extends KeyguardPinBasedInputView {
}
boolean isEsimLocked = KeyguardEsimArea.isEsimLocked(mContext, mSubId);
- int count = TelephonyManager.getDefault().getSimCount();
+ int count = 1;
+ TelephonyManager telephonyManager =
+ (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
+ if (telephonyManager != null) {
+ count = telephonyManager.getActiveModemCount();
+ }
Resources rez = getResources();
String msg;
TypedArray array = mContext.obtainStyledAttributes(new int[] { R.attr.wallpaperTextColor });
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 6685db130d4a..0b0922a7766f 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -2649,8 +2649,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
// that don't return the complete set of values and have different types. In Keyguard we
// need IccCardConstants, but TelephonyManager would only give us
// TelephonyManager.SIM_STATE*, so we retrieve it manually.
- final TelephonyManager tele = TelephonyManager.from(mContext);
- int simState = tele.getSimState(slotId);
+ final TelephonyManager tele =
+ (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
+ int simState = (tele != null) ?
+ tele.getSimState(slotId) : TelephonyManager.SIM_STATE_UNKNOWN;
State state;
try {
state = State.intToState(simState);
diff --git a/packages/SystemUI/src/com/android/systemui/CornerHandleView.java b/packages/SystemUI/src/com/android/systemui/CornerHandleView.java
index a94952c5bc19..8e472f9c98a3 100644
--- a/packages/SystemUI/src/com/android/systemui/CornerHandleView.java
+++ b/packages/SystemUI/src/com/android/systemui/CornerHandleView.java
@@ -47,6 +47,7 @@ public class CornerHandleView extends View {
private int mLightColor;
private int mDarkColor;
private Path mPath;
+ private boolean mRequiresInvalidate;
public CornerHandleView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -67,6 +68,15 @@ public class CornerHandleView extends View {
updatePath();
}
+ @Override
+ public void setAlpha(float alpha) {
+ super.setAlpha(alpha);
+ if (alpha > 0f && mRequiresInvalidate) {
+ mRequiresInvalidate = false;
+ invalidate();
+ }
+ }
+
private void updatePath() {
mPath = new Path();
@@ -104,11 +114,16 @@ public class CornerHandleView extends View {
* appropriately. Intention is to match the home handle color.
*/
public void updateDarkness(float darkIntensity) {
- mPaint.setColor((int) ArgbEvaluator.getInstance().evaluate(darkIntensity,
- mLightColor,
- mDarkColor));
- if (getVisibility() == VISIBLE) {
- invalidate();
+ int color = (int) ArgbEvaluator.getInstance().evaluate(darkIntensity,
+ mLightColor, mDarkColor);
+ if (mPaint.getColor() != color) {
+ mPaint.setColor(color);
+ if (getVisibility() == VISIBLE && getAlpha() > 0) {
+ invalidate();
+ } else {
+ // If we are currently invisible, then invalidate when we are next made visible
+ mRequiresInvalidate = true;
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java
index 9a277e8fa77c..46ae84a95fad 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java
@@ -249,7 +249,7 @@ final class AssistHandleReminderExpBehavior implements BehaviorController {
public void onModeDeactivated() {
mAssistHandleCallbacks = null;
if (mContext != null) {
- mContext.unregisterReceiver(mDefaultHomeBroadcastReceiver);
+ mBroadcastDispatcher.get().unregisterReceiver(mDefaultHomeBroadcastReceiver);
Settings.Secure.putLong(mContext.getContentResolver(), LEARNING_TIME_ELAPSED_KEY, 0);
Settings.Secure.putInt(mContext.getContentResolver(), LEARNING_EVENT_COUNT_KEY, 0);
Settings.Secure.putLong(mContext.getContentResolver(), LEARNED_HINT_LAST_SHOWN_KEY, 0);
diff --git a/packages/SystemUI/src/com/android/systemui/assist/ui/EdgeLight.java b/packages/SystemUI/src/com/android/systemui/assist/ui/EdgeLight.java
index baa3a4a938c1..c641943278d4 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/ui/EdgeLight.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/ui/EdgeLight.java
@@ -67,8 +67,10 @@ public final class EdgeLight {
}
/** Sets the edge light color. */
- public void setColor(@ColorInt int color) {
+ public boolean setColor(@ColorInt int color) {
+ boolean changed = mColor != color;
mColor = color;
+ return changed;
}
/** Returns the edge light length, in units of the total device perimeter. */
diff --git a/packages/SystemUI/src/com/android/systemui/assist/ui/InvocationLightsView.java b/packages/SystemUI/src/com/android/systemui/assist/ui/InvocationLightsView.java
index 570b911cd400..e5121a8ea35c 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/ui/InvocationLightsView.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/ui/InvocationLightsView.java
@@ -259,10 +259,13 @@ public class InvocationLightsView extends View
if (mUseNavBarColor) {
@ColorInt int invocationColor = (int) ArgbEvaluator.getInstance().evaluate(
darkIntensity, mLightColor, mDarkColor);
+ boolean changed = true;
for (EdgeLight light : mAssistInvocationLights) {
- light.setColor(invocationColor);
+ changed &= light.setColor(invocationColor);
+ }
+ if (changed) {
+ invalidate();
}
- invalidate();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java
index f5f1fad71b14..84a592d68627 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java
@@ -298,7 +298,10 @@ public abstract class AuthBiometricView extends LinearLayout {
.getDimension(R.dimen.biometric_dialog_icon_padding);
mIconView.setY(getHeight() - mIconView.getHeight() - iconPadding);
- final int newHeight = mIconView.getHeight() + 2 * (int) iconPadding;
+ // Subtract the vertical padding from the new height since it's only used to create
+ // extra space between the other elements, and not part of the actual icon.
+ final int newHeight = mIconView.getHeight() + 2 * (int) iconPadding
+ - mIconView.getPaddingTop() - mIconView.getPaddingBottom();
mPanelController.updateForContentDimensions(mMediumWidth, newHeight,
0 /* animateDurationMs */);
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
index 516de709c34f..6b0d3c807079 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
@@ -23,7 +23,10 @@ import android.app.ActivityManager;
import android.app.ActivityTaskManager;
import android.app.IActivityTaskManager;
import android.app.TaskStackListener;
+import android.content.BroadcastReceiver;
import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.hardware.biometrics.Authenticator;
@@ -85,6 +88,28 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
}
}
+ @VisibleForTesting
+ final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (mCurrentDialog != null
+ && Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(intent.getAction())) {
+ Log.w(TAG, "ACTION_CLOSE_SYSTEM_DIALOGS received");
+ mCurrentDialog.dismissWithoutCallback(true /* animate */);
+ mCurrentDialog = null;
+
+ try {
+ if (mReceiver != null) {
+ mReceiver.onDialogDismissed(BiometricPrompt.DISMISSED_REASON_USER_CANCEL);
+ mReceiver = null;
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Remote exception", e);
+ }
+ }
+ }
+ };
+
private final Runnable mTaskStackChangedRunnable = () -> {
if (mCurrentDialog != null) {
try {
@@ -204,6 +229,11 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
super(context);
mCommandQueue = commandQueue;
mInjector = injector;
+
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
+
+ context.registerReceiver(mBroadcastReceiver, filter);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java b/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
index 7600b2f3ed7a..f8e45d4c8b63 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
@@ -134,6 +134,10 @@ class Bubble {
return mAppName;
}
+ public Drawable getUserBadgedAppIcon() {
+ return mUserBadgedAppIcon;
+ }
+
boolean isInflated() {
return mInflated;
}
@@ -165,7 +169,6 @@ class Bubble {
mIconView = (BubbleView) inflater.inflate(
R.layout.bubble_view, stackView, false /* attachToRoot */);
mIconView.setBubble(this);
- mIconView.setAppIcon(mUserBadgedAppIcon);
mExpandedView = (BubbleExpandedView) inflater.inflate(
R.layout.bubble_expanded_view, stackView, false /* attachToRoot */);
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
index e5af3897dff2..4a1bbe48efb0 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
@@ -1459,7 +1459,7 @@ public class BubbleStackView extends FrameLayout {
mFlyout.setupFlyoutStartingAsDot(
updateMessage, mStackAnimationController.getStackPosition(), getWidth(),
mStackAnimationController.isStackOnLeftSide(),
- bubble.getIconView().getBadgeColor() /* dotColor */,
+ bubble.getIconView().getDotColor() /* dotColor */,
expandFlyoutAfterDelay /* onLayoutComplete */,
mFlyoutOnHide,
bubble.getIconView().getDotCenter());
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java
index fe4fa90a272d..35657d38df0c 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java
@@ -24,17 +24,16 @@ import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Path;
-import android.graphics.drawable.AdaptiveIconDrawable;
import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
-import android.graphics.drawable.InsetDrawable;
import android.util.AttributeSet;
import android.util.PathParser;
import android.widget.FrameLayout;
import com.android.internal.graphics.ColorUtils;
+import com.android.launcher3.icons.BitmapInfo;
+import com.android.launcher3.icons.ColorExtractor;
import com.android.launcher3.icons.ShadowGenerator;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
@@ -45,17 +44,13 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry;
*/
public class BubbleView extends FrameLayout {
- private static final int DARK_ICON_ALPHA = 180;
- private static final double ICON_MIN_CONTRAST = 4.1;
- private static final int DEFAULT_BACKGROUND_COLOR = Color.LTGRAY;
// Same value as Launcher3 badge code
private static final float WHITE_SCRIM_ALPHA = 0.54f;
private Context mContext;
private BadgedImageView mBadgedImageView;
- private int mBadgeColor;
- private int mIconInset;
- private Drawable mUserBadgedAppIcon;
+ private int mDotColor;
+ private ColorExtractor mColorExtractor;
// mBubbleIconFactory cannot be static because it depends on Context.
private BubbleIconFactory mBubbleIconFactory;
@@ -79,13 +74,13 @@ public class BubbleView extends FrameLayout {
public BubbleView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
mContext = context;
- mIconInset = getResources().getDimensionPixelSize(R.dimen.bubble_icon_inset);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mBadgedImageView = findViewById(R.id.bubble_image);
+ mColorExtractor = new ColorExtractor();
}
@Override
@@ -106,6 +101,13 @@ public class BubbleView extends FrameLayout {
}
/**
+ * @param factory Factory for creating normalized bubble icons.
+ */
+ public void setBubbleIconFactory(BubbleIconFactory factory) {
+ mBubbleIconFactory = factory;
+ }
+
+ /**
* The {@link NotificationEntry} associated with this view, if one exists.
*/
@Nullable
@@ -129,17 +131,6 @@ public class BubbleView extends FrameLayout {
updateViews();
}
- /**
- * @param factory Factory for creating normalized bubble icons.
- */
- public void setBubbleIconFactory(BubbleIconFactory factory) {
- mBubbleIconFactory = factory;
- }
-
- public void setAppIcon(Drawable appIcon) {
- mUserBadgedAppIcon = appIcon;
- }
-
/** Changes the dot's visibility to match the bubble view's state. */
void updateDotVisibility(boolean animate) {
updateDotVisibility(animate, null /* after */);
@@ -154,9 +145,17 @@ public class BubbleView extends FrameLayout {
updateDotVisibility(animate);
}
+ boolean isDotShowing() {
+ return mBubble.showBubbleDot() && !mSuppressDot;
+ }
+
+ int getDotColor() {
+ return mDotColor;
+ }
+
/** Sets the position of the 'new' dot, animating it out and back in if requested. */
void setDotPosition(boolean onLeft, boolean animate) {
- if (animate && onLeft != mBadgedImageView.getDotOnLeft() && shouldShowDot()) {
+ if (animate && onLeft != mBadgedImageView.getDotOnLeft() && isDotShowing()) {
animateDot(false /* showDot */, () -> {
mBadgedImageView.setDotOnLeft(onLeft);
animateDot(true /* showDot */, null);
@@ -180,7 +179,7 @@ public class BubbleView extends FrameLayout {
* after animation if requested.
*/
private void updateDotVisibility(boolean animate, Runnable after) {
- final boolean showDot = shouldShowDot();
+ final boolean showDot = isDotShowing();
if (animate) {
animateDot(showDot, after);
} else {
@@ -218,42 +217,21 @@ public class BubbleView extends FrameLayout {
if (mBubble == null || mBubbleIconFactory == null) {
return;
}
- // Update icon.
- Notification.BubbleMetadata metadata = mBubble.getEntry().getBubbleMetadata();
- Notification n = mBubble.getEntry().getSbn().getNotification();
- Icon ic = metadata.getIcon();
- boolean needsTint = ic.getType() != Icon.TYPE_ADAPTIVE_BITMAP;
-
- Drawable iconDrawable = ic.loadDrawable(mContext);
- if (needsTint) {
- iconDrawable = buildIconWithTint(iconDrawable, n.color);
- }
- Bitmap bubbleIcon = mBubbleIconFactory.createBadgedIconBitmap(iconDrawable,
- null /* user */,
- true /* shrinkNonAdaptiveIcons */).icon;
-
- // Give it a shadow
- Bitmap userBadgedBitmap = mBubbleIconFactory.createIconBitmap(mUserBadgedAppIcon,
- 1f, mBubbleIconFactory.getBadgeSize());
- Canvas c = new Canvas();
- ShadowGenerator shadowGenerator = new ShadowGenerator(mBubbleIconFactory.getBadgeSize());
- c.setBitmap(userBadgedBitmap);
- shadowGenerator.recreateIcon(Bitmap.createBitmap(userBadgedBitmap), c);
- mBubbleIconFactory.badgeWithDrawable(bubbleIcon,
- new BitmapDrawable(mContext.getResources(), userBadgedBitmap));
- mBadgedImageView.setImageBitmap(bubbleIcon);
+ Drawable bubbleDrawable = getBubbleDrawable(mContext);
+ BitmapInfo badgeBitmapInfo = getBadgedBitmap();
+ BitmapInfo bubbleBitmapInfo = getBubbleBitmap(bubbleDrawable, badgeBitmapInfo);
+ mBadgedImageView.setImageBitmap(bubbleBitmapInfo.icon);
// Update badge.
- int badgeColor = determineDominateColor(iconDrawable, n.color);
- mBadgeColor = badgeColor;
- mBadgedImageView.setDotColor(badgeColor);
+ mDotColor = ColorUtils.blendARGB(badgeBitmapInfo.color, Color.WHITE, WHITE_SCRIM_ALPHA);
+ mBadgedImageView.setDotColor(mDotColor);
// Update dot.
Path iconPath = PathParser.createPathFromPathData(
getResources().getString(com.android.internal.R.string.config_icon_mask));
Matrix matrix = new Matrix();
- float scale = mBubbleIconFactory.getNormalizer().getScale(iconDrawable,
+ float scale = mBubbleIconFactory.getNormalizer().getScale(bubbleDrawable,
null /* outBounds */, null /* path */, null /* outMaskShape */);
float radius = BadgedImageView.DEFAULT_PATH_SIZE / 2f;
matrix.setScale(scale /* x scale */, scale /* y scale */, radius /* pivot x */,
@@ -261,41 +239,34 @@ public class BubbleView extends FrameLayout {
iconPath.transform(matrix);
mBadgedImageView.drawDot(iconPath);
- animateDot(shouldShowDot(), null /* after */);
+ animateDot(isDotShowing(), null /* after */);
}
- boolean shouldShowDot() {
- return mBubble.showBubbleDot() && !mSuppressDot;
+ Drawable getBubbleDrawable(Context context) {
+ Notification.BubbleMetadata metadata = getEntry().getBubbleMetadata();
+ Icon ic = metadata.getIcon();
+ return ic.loadDrawable(context);
}
- int getBadgeColor() {
- return mBadgeColor;
- }
+ BitmapInfo getBadgedBitmap() {
+ Bitmap userBadgedBitmap = mBubbleIconFactory.createIconBitmap(
+ mBubble.getUserBadgedAppIcon(), 1f, mBubbleIconFactory.getBadgeSize());
- private AdaptiveIconDrawable buildIconWithTint(Drawable iconDrawable, int backgroundColor) {
- iconDrawable = checkTint(iconDrawable, backgroundColor);
- InsetDrawable foreground = new InsetDrawable(iconDrawable, mIconInset);
- ColorDrawable background = new ColorDrawable(backgroundColor);
- return new AdaptiveIconDrawable(background, foreground);
+ Canvas c = new Canvas();
+ ShadowGenerator shadowGenerator = new ShadowGenerator(mBubbleIconFactory.getBadgeSize());
+ c.setBitmap(userBadgedBitmap);
+ shadowGenerator.recreateIcon(Bitmap.createBitmap(userBadgedBitmap), c);
+ BitmapInfo bitmapInfo = mBubbleIconFactory.createIconBitmap(userBadgedBitmap);
+ return bitmapInfo;
}
- private Drawable checkTint(Drawable iconDrawable, int backgroundColor) {
- backgroundColor = ColorUtils.setAlphaComponent(backgroundColor, 255 /* alpha */);
- if (backgroundColor == Color.TRANSPARENT) {
- // ColorUtils throws exception when background is translucent.
- backgroundColor = DEFAULT_BACKGROUND_COLOR;
- }
- iconDrawable.setTint(Color.WHITE);
- double contrastRatio = ColorUtils.calculateContrast(Color.WHITE, backgroundColor);
- if (contrastRatio < ICON_MIN_CONTRAST) {
- int dark = ColorUtils.setAlphaComponent(Color.BLACK, DARK_ICON_ALPHA);
- iconDrawable.setTint(dark);
- }
- return iconDrawable;
- }
+ BitmapInfo getBubbleBitmap(Drawable bubble, BitmapInfo badge) {
+ BitmapInfo bubbleIconInfo = mBubbleIconFactory.createBadgedIconBitmap(bubble,
+ null /* user */,
+ true /* shrinkNonAdaptiveIcons */);
- private int determineDominateColor(Drawable d, int defaultTint) {
- // XXX: should we pull from the drawable, app icon, notif tint?
- return ColorUtils.blendARGB(defaultTint, Color.WHITE, WHITE_SCRIM_ALPHA);
+ mBubbleIconFactory.badgeWithDrawable(bubbleIconInfo.icon,
+ new BitmapDrawable(mContext.getResources(), badge.icon));
+ return bubbleIconInfo;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java
index 3b0c9aebfe08..9f5493720bef 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java
@@ -16,109 +16,35 @@
package com.android.systemui.dagger;
-import static com.android.systemui.Dependency.ALLOW_NOTIFICATION_LONG_PRESS_NAME;
-
-import android.content.Context;
-import android.os.PowerManager;
-import android.util.DisplayMetrics;
-
-import androidx.annotation.Nullable;
-
-import com.android.internal.logging.MetricsLogger;
-import com.android.keyguard.KeyguardUpdateMonitor;
-import com.android.systemui.ForegroundServiceController;
import com.android.systemui.LatencyTester;
import com.android.systemui.ScreenDecorations;
import com.android.systemui.SizeCompatModeActivityController;
import com.android.systemui.SliceBroadcastRelayHandler;
import com.android.systemui.SystemUI;
-import com.android.systemui.UiOffloadThread;
-import com.android.systemui.appops.AppOpsController;
-import com.android.systemui.assist.AssistManager;
import com.android.systemui.biometrics.AuthController;
-import com.android.systemui.broadcast.BroadcastDispatcher;
-import com.android.systemui.bubbles.BubbleController;
-import com.android.systemui.colorextraction.SysuiColorExtractor;
-import com.android.systemui.doze.DozeLog;
import com.android.systemui.globalactions.GlobalActionsComponent;
import com.android.systemui.keyguard.KeyguardViewMediator;
-import com.android.systemui.keyguard.ScreenLifecycle;
-import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.pip.PipUI;
-import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.power.PowerUI;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.RecentsModule;
-import com.android.systemui.shared.plugins.PluginManager;
-import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.FeatureFlags;
-import com.android.systemui.statusbar.NavigationBarController;
-import com.android.systemui.statusbar.NotificationListener;
-import com.android.systemui.statusbar.NotificationLockscreenUserManager;
-import com.android.systemui.statusbar.NotificationMediaManager;
-import com.android.systemui.statusbar.NotificationRemoteInputManager;
-import com.android.systemui.statusbar.NotificationViewHierarchyManager;
-import com.android.systemui.statusbar.PulseExpansionHandler;
-import com.android.systemui.statusbar.SysuiStatusBarStateController;
-import com.android.systemui.statusbar.VibratorHelper;
-import com.android.systemui.statusbar.notification.BypassHeadsUpNotifier;
-import com.android.systemui.statusbar.notification.DynamicPrivacyController;
import com.android.systemui.statusbar.notification.InstantAppNotifier;
-import com.android.systemui.statusbar.notification.NewNotifPipeline;
-import com.android.systemui.statusbar.notification.NotificationAlertingManager;
-import com.android.systemui.statusbar.notification.NotificationEntryManager;
-import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
-import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
-import com.android.systemui.statusbar.notification.VisualStabilityManager;
-import com.android.systemui.statusbar.notification.logging.NotifLog;
-import com.android.systemui.statusbar.notification.logging.NotificationLogger;
-import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
-import com.android.systemui.statusbar.phone.AutoHideController;
-import com.android.systemui.statusbar.phone.BiometricUnlockController;
-import com.android.systemui.statusbar.phone.DozeParameters;
-import com.android.systemui.statusbar.phone.DozeScrimController;
-import com.android.systemui.statusbar.phone.DozeServiceHost;
-import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
-import com.android.systemui.statusbar.phone.KeyguardBypassController;
-import com.android.systemui.statusbar.phone.KeyguardLiftController;
-import com.android.systemui.statusbar.phone.LightBarController;
-import com.android.systemui.statusbar.phone.LockscreenWallpaper;
-import com.android.systemui.statusbar.phone.NotificationGroupAlertTransferHelper;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
-import com.android.systemui.statusbar.phone.ScrimController;
import com.android.systemui.statusbar.phone.StatusBar;
-import com.android.systemui.statusbar.phone.StatusBarIconController;
-import com.android.systemui.statusbar.phone.StatusBarWindowController;
-import com.android.systemui.statusbar.phone.StatusBarWindowViewController;
-import com.android.systemui.statusbar.policy.BatteryController;
-import com.android.systemui.statusbar.policy.ConfigurationController;
-import com.android.systemui.statusbar.policy.DeviceProvisionedController;
-import com.android.systemui.statusbar.policy.KeyguardStateController;
-import com.android.systemui.statusbar.policy.NetworkController;
-import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler;
-import com.android.systemui.statusbar.policy.RemoteInputUriController;
-import com.android.systemui.statusbar.policy.UserSwitcherController;
-import com.android.systemui.statusbar.policy.ZenModeController;
+import com.android.systemui.statusbar.phone.StatusBarModule;
import com.android.systemui.statusbar.tv.TvStatusBar;
import com.android.systemui.theme.ThemeOverlayController;
-import com.android.systemui.util.InjectionInflationController;
import com.android.systemui.util.leak.GarbageMonitor;
import com.android.systemui.volume.VolumeUI;
-import javax.inject.Named;
-import javax.inject.Singleton;
-
import dagger.Binds;
-import dagger.Lazy;
import dagger.Module;
-import dagger.Provides;
import dagger.multibindings.ClassKey;
import dagger.multibindings.IntoMap;
/**
* SystemUI objects that are injectable should go here.
*/
-@Module(includes = {RecentsModule.class})
+@Module(includes = {RecentsModule.class, StatusBarModule.class})
public abstract class SystemUIBinder {
/** Inject into AuthController. */
@Binds
@@ -216,148 +142,4 @@ public abstract class SystemUIBinder {
@IntoMap
@ClassKey(VolumeUI.class)
public abstract SystemUI bindVolumeUI(VolumeUI sysui);
-
- /**
- * Provides our instance of StatusBar which is considered optional.
- */
- @Provides
- @Singleton
- static StatusBar provideStatusBar(
- Context context,
- FeatureFlags featureFlags,
- LightBarController lightBarController,
- AutoHideController autoHideController,
- KeyguardUpdateMonitor keyguardUpdateMonitor,
- StatusBarIconController statusBarIconController,
- DozeLog dozeLog,
- InjectionInflationController injectionInflationController,
- PulseExpansionHandler pulseExpansionHandler,
- NotificationWakeUpCoordinator notificationWakeUpCoordinator,
- KeyguardBypassController keyguardBypassController,
- KeyguardStateController keyguardStateController,
- HeadsUpManagerPhone headsUpManagerPhone,
- DynamicPrivacyController dynamicPrivacyController,
- BypassHeadsUpNotifier bypassHeadsUpNotifier,
- @Named(ALLOW_NOTIFICATION_LONG_PRESS_NAME) boolean allowNotificationLongPress,
- Lazy<NewNotifPipeline> newNotifPipeline,
- FalsingManager falsingManager,
- BroadcastDispatcher broadcastDispatcher,
- RemoteInputQuickSettingsDisabler remoteInputQuickSettingsDisabler,
- NotificationGutsManager notificationGutsManager,
- NotificationLogger notificationLogger,
- NotificationEntryManager notificationEntryManager,
- NotificationInterruptionStateProvider notificationInterruptionStateProvider,
- NotificationViewHierarchyManager notificationViewHierarchyManager,
- ForegroundServiceController foregroundServiceController,
- AppOpsController appOpsController,
- KeyguardViewMediator keyguardViewMediator,
- ZenModeController zenModeController,
- NotificationAlertingManager notificationAlertingManager,
- DisplayMetrics displayMetrics,
- MetricsLogger metricsLogger,
- UiOffloadThread uiOffloadThread,
- NotificationMediaManager notificationMediaManager,
- NotificationLockscreenUserManager lockScreenUserManager,
- NotificationRemoteInputManager remoteInputManager,
- UserSwitcherController userSwitcherController,
- NetworkController networkController,
- BatteryController batteryController,
- SysuiColorExtractor colorExtractor,
- ScreenLifecycle screenLifecycle,
- WakefulnessLifecycle wakefulnessLifecycle,
- SysuiStatusBarStateController statusBarStateController,
- VibratorHelper vibratorHelper,
- BubbleController bubbleController,
- NotificationGroupManager groupManager,
- NotificationGroupAlertTransferHelper groupAlertTransferHelper,
- VisualStabilityManager visualStabilityManager,
- DeviceProvisionedController deviceProvisionedController,
- NavigationBarController navigationBarController,
- AssistManager assistManager,
- NotificationListener notificationListener,
- ConfigurationController configurationController,
- StatusBarWindowController statusBarWindowController,
- StatusBarWindowViewController.Builder statusBarWindowViewControllerBuilder,
- NotifLog notifLog,
- DozeParameters dozeParameters,
- ScrimController scrimController,
- @Nullable KeyguardLiftController keyguardLiftController,
- Lazy<LockscreenWallpaper> lockscreenWallpaperLazy,
- Lazy<BiometricUnlockController> biometricUnlockControllerLazy,
- DozeServiceHost dozeServiceHost,
- PowerManager powerManager,
- DozeScrimController dozeScrimController,
- CommandQueue commandQueue,
- PluginManager pluginManager,
- RemoteInputUriController remoteInputUriController) {
- return new StatusBar(
- context,
- featureFlags,
- lightBarController,
- autoHideController,
- keyguardUpdateMonitor,
- statusBarIconController,
- dozeLog,
- injectionInflationController,
- pulseExpansionHandler,
- notificationWakeUpCoordinator,
- keyguardBypassController,
- keyguardStateController,
- headsUpManagerPhone,
- dynamicPrivacyController,
- bypassHeadsUpNotifier,
- allowNotificationLongPress,
- newNotifPipeline,
- falsingManager,
- broadcastDispatcher,
- remoteInputQuickSettingsDisabler,
- notificationGutsManager,
- notificationLogger,
- notificationEntryManager,
- notificationInterruptionStateProvider,
- notificationViewHierarchyManager,
- foregroundServiceController,
- appOpsController,
- keyguardViewMediator,
- zenModeController,
- notificationAlertingManager,
- displayMetrics,
- metricsLogger,
- uiOffloadThread,
- notificationMediaManager,
- lockScreenUserManager,
- remoteInputManager,
- userSwitcherController,
- networkController,
- batteryController,
- colorExtractor,
- screenLifecycle,
- wakefulnessLifecycle,
- statusBarStateController,
- vibratorHelper,
- bubbleController,
- groupManager,
- groupAlertTransferHelper,
- visualStabilityManager,
- deviceProvisionedController,
- navigationBarController,
- assistManager,
- notificationListener,
- configurationController,
- statusBarWindowController,
- statusBarWindowViewControllerBuilder,
- notifLog,
- dozeParameters,
- scrimController,
- keyguardLiftController,
- lockscreenWallpaperLazy,
- biometricUnlockControllerLazy,
- dozeServiceHost,
- powerManager,
- dozeScrimController,
- commandQueue,
- pluginManager,
- remoteInputUriController);
- }
-
}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
index 9e7f6c683bbe..b3a5181d1ca5 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
@@ -25,6 +25,7 @@ import com.android.systemui.DumpController;
import com.android.systemui.assist.AssistModule;
import com.android.systemui.model.SysUiState;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.notification.people.PeopleHubModule;
import com.android.systemui.statusbar.phone.KeyguardLiftController;
import com.android.systemui.statusbar.phone.StatusBar;
@@ -71,5 +72,8 @@ public abstract class SystemUIModule {
}
@BindsOptionalOf
+ abstract CommandQueue optionalCommandQueue();
+
+ @BindsOptionalOf
abstract StatusBar optionalStatusBar();
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java b/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java
index 86c532cdb773..ca04633b316a 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java
@@ -117,9 +117,14 @@ public class WorkLockActivity extends Activity {
}
}
+ @VisibleForTesting
+ protected void unregisterBroadcastReceiver() {
+ mBroadcastDispatcher.unregisterReceiver(mLockEventReceiver);
+ }
+
@Override
public void onDestroy() {
- unregisterReceiver(mLockEventReceiver);
+ unregisterBroadcastReceiver();
super.onDestroy();
}
@@ -170,7 +175,12 @@ public class WorkLockActivity extends Activity {
credential.putExtra(EXTRA_FROM_WORK_LOCK_ACTIVITY, true);
}
- startActivityForResult(credential, REQUEST_CODE_CONFIRM_CREDENTIALS);
+ final ActivityOptions launchOptions = ActivityOptions.makeBasic();
+ launchOptions.setLaunchTaskId(getTaskId());
+ launchOptions.setTaskOverlay(true /* taskOverlay */, true /* canResume */);
+
+ startActivityForResult(credential, REQUEST_CODE_CONFIRM_CREDENTIALS,
+ launchOptions.toBundle());
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index 264d644f9057..68a2417f90b8 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -21,9 +21,6 @@ import static android.provider.DeviceConfig.NAMESPACE_SYSTEMUI;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.SCREENSHOT_CORNER_FLOW;
-import static com.android.systemui.screenshot.GlobalScreenshot.EXTRA_ACTION_INTENT;
-import static com.android.systemui.screenshot.GlobalScreenshot.EXTRA_CANCEL_NOTIFICATION;
-import static com.android.systemui.screenshot.GlobalScreenshot.EXTRA_DISALLOW_ENTER_PIP;
import static com.android.systemui.statusbar.phone.StatusBar.SYSTEM_DIALOG_REASON_SCREENSHOT;
import android.animation.Animator;
@@ -101,6 +98,7 @@ import java.io.OutputStream;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
+import java.util.Optional;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
@@ -109,372 +107,381 @@ import java.util.function.Function;
import javax.inject.Inject;
import javax.inject.Singleton;
+import dagger.Lazy;
/**
- * POD used in the AsyncTask which saves an image in the background.
+ * Class for handling device screen shots
*/
-class SaveImageInBackgroundData {
- Context context;
- Bitmap image;
- Uri imageUri;
- Runnable finisher;
- Function<PendingIntent, Void> onEditReady;
- int iconSize;
- int previewWidth;
- int previewheight;
- int errorMsgResId;
-
- void clearImage() {
- image = null;
- imageUri = null;
- iconSize = 0;
- }
- void clearContext() {
- context = null;
- }
-}
-
-/**
- * An AsyncTask that saves an image to the media store in the background.
- */
-class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
- private static final String TAG = "SaveImageInBackgroundTask";
-
- private static final String SCREENSHOT_FILE_NAME_TEMPLATE = "Screenshot_%s.png";
- private static final String SCREENSHOT_SHARE_SUBJECT_TEMPLATE = "Screenshot (%s)";
-
- private final SaveImageInBackgroundData mParams;
- private final NotificationManager mNotificationManager;
- private final Notification.Builder mNotificationBuilder, mPublicNotificationBuilder;
- private final String mImageFileName;
- private final long mImageTime;
- private final BigPictureStyle mNotificationStyle;
- private final int mImageWidth;
- private final int mImageHeight;
-
- SaveImageInBackgroundTask(Context context, SaveImageInBackgroundData data,
- NotificationManager nManager) {
- Resources r = context.getResources();
-
- // Prepare all the output metadata
- mParams = data;
- mImageTime = System.currentTimeMillis();
- String imageDate = new SimpleDateFormat("yyyyMMdd-HHmmss").format(new Date(mImageTime));
- mImageFileName = String.format(SCREENSHOT_FILE_NAME_TEMPLATE, imageDate);
-
- // Create the large notification icon
- mImageWidth = data.image.getWidth();
- mImageHeight = data.image.getHeight();
- int iconSize = data.iconSize;
- int previewWidth = data.previewWidth;
- int previewHeight = data.previewheight;
-
- Paint paint = new Paint();
- ColorMatrix desat = new ColorMatrix();
- desat.setSaturation(0.25f);
- paint.setColorFilter(new ColorMatrixColorFilter(desat));
- Matrix matrix = new Matrix();
- int overlayColor = 0x40FFFFFF;
-
- matrix.setTranslate((previewWidth - mImageWidth) / 2, (previewHeight - mImageHeight) / 2);
- Bitmap picture = generateAdjustedHwBitmap(data.image, previewWidth, previewHeight, matrix,
- paint, overlayColor);
-
- // Note, we can't use the preview for the small icon, since it is non-square
- float scale = (float) iconSize / Math.min(mImageWidth, mImageHeight);
- matrix.setScale(scale, scale);
- matrix.postTranslate((iconSize - (scale * mImageWidth)) / 2,
- (iconSize - (scale * mImageHeight)) / 2);
- Bitmap icon = generateAdjustedHwBitmap(data.image, iconSize, iconSize, matrix, paint,
- overlayColor);
-
- mNotificationManager = nManager;
- final long now = System.currentTimeMillis();
-
- // Setup the notification
- mNotificationStyle = new Notification.BigPictureStyle()
- .bigPicture(picture.createAshmemBitmap());
-
- // The public notification will show similar info but with the actual screenshot omitted
- mPublicNotificationBuilder =
- new Notification.Builder(context, NotificationChannels.SCREENSHOTS_HEADSUP)
- .setContentTitle(r.getString(R.string.screenshot_saving_title))
- .setSmallIcon(R.drawable.stat_notify_image)
- .setCategory(Notification.CATEGORY_PROGRESS)
- .setWhen(now)
- .setShowWhen(true)
- .setColor(r.getColor(
- com.android.internal.R.color.system_notification_accent_color));
- SystemUI.overrideNotificationAppName(context, mPublicNotificationBuilder, true);
-
- mNotificationBuilder = new Notification.Builder(context,
- NotificationChannels.SCREENSHOTS_HEADSUP)
- .setContentTitle(r.getString(R.string.screenshot_saving_title))
- .setSmallIcon(R.drawable.stat_notify_image)
- .setWhen(now)
- .setShowWhen(true)
- .setColor(r.getColor(com.android.internal.R.color.system_notification_accent_color))
- .setStyle(mNotificationStyle)
- .setPublicVersion(mPublicNotificationBuilder.build());
- mNotificationBuilder.setFlag(Notification.FLAG_NO_CLEAR, true);
- SystemUI.overrideNotificationAppName(context, mNotificationBuilder, true);
-
- mNotificationManager.notify(SystemMessage.NOTE_GLOBAL_SCREENSHOT,
- mNotificationBuilder.build());
-
- /**
- * NOTE: The following code prepares the notification builder for updating the notification
- * after the screenshot has been written to disk.
- */
+@Singleton
+public class GlobalScreenshot {
- // On the tablet, the large icon makes the notification appear as if it is clickable (and
- // on small devices, the large icon is not shown) so defer showing the large icon until
- // we compose the final post-save notification below.
- mNotificationBuilder.setLargeIcon(icon.createAshmemBitmap());
- // But we still don't set it for the expanded view, allowing the smallIcon to show here.
- mNotificationStyle.bigLargeIcon((Bitmap) null);
+ /**
+ * POD used in the AsyncTask which saves an image in the background.
+ */
+ private static class SaveImageInBackgroundData {
+ public Context context;
+ public Bitmap image;
+ public Uri imageUri;
+ public Runnable finisher;
+ public Function<PendingIntent, Void> onEditReady;
+ public int iconSize;
+ public int previewWidth;
+ public int previewheight;
+ public int errorMsgResId;
+
+ void clearImage() {
+ image = null;
+ imageUri = null;
+ iconSize = 0;
+ }
+ void clearContext() {
+ context = null;
+ }
}
/**
- * Generates a new hardware bitmap with specified values, copying the content from the passed
- * in bitmap.
+ * An AsyncTask that saves an image to the media store in the background.
*/
- private Bitmap generateAdjustedHwBitmap(Bitmap bitmap, int width, int height, Matrix matrix,
- Paint paint, int color) {
- Picture picture = new Picture();
- Canvas canvas = picture.beginRecording(width, height);
- canvas.drawColor(color);
- canvas.drawBitmap(bitmap, matrix, paint);
- picture.endRecording();
- return Bitmap.createBitmap(picture);
- }
+ private static class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
+ private static final String TAG = "SaveImageInBackgroundTask";
+
+ private static final String SCREENSHOT_FILE_NAME_TEMPLATE = "Screenshot_%s.png";
+ private static final String SCREENSHOT_SHARE_SUBJECT_TEMPLATE = "Screenshot (%s)";
+
+ private final SaveImageInBackgroundData mParams;
+ private final NotificationManager mNotificationManager;
+ private final Notification.Builder mNotificationBuilder, mPublicNotificationBuilder;
+ private final String mImageFileName;
+ private final long mImageTime;
+ private final BigPictureStyle mNotificationStyle;
+ private final int mImageWidth;
+ private final int mImageHeight;
+
+ SaveImageInBackgroundTask(Context context, SaveImageInBackgroundData data,
+ NotificationManager nManager) {
+ Resources r = context.getResources();
+
+ // Prepare all the output metadata
+ mParams = data;
+ mImageTime = System.currentTimeMillis();
+ String imageDate = new SimpleDateFormat("yyyyMMdd-HHmmss").format(new Date(mImageTime));
+ mImageFileName = String.format(SCREENSHOT_FILE_NAME_TEMPLATE, imageDate);
+
+ // Create the large notification icon
+ mImageWidth = data.image.getWidth();
+ mImageHeight = data.image.getHeight();
+ int iconSize = data.iconSize;
+ int previewWidth = data.previewWidth;
+ int previewHeight = data.previewheight;
+
+ Paint paint = new Paint();
+ ColorMatrix desat = new ColorMatrix();
+ desat.setSaturation(0.25f);
+ paint.setColorFilter(new ColorMatrixColorFilter(desat));
+ Matrix matrix = new Matrix();
+ int overlayColor = 0x40FFFFFF;
+
+ matrix.setTranslate((previewWidth - mImageWidth) / 2,
+ (previewHeight - mImageHeight) / 2);
+ Bitmap picture = generateAdjustedHwBitmap(data.image, previewWidth, previewHeight,
+ matrix, paint, overlayColor);
+
+ // Note, we can't use the preview for the small icon, since it is non-square
+ float scale = (float) iconSize / Math.min(mImageWidth, mImageHeight);
+ matrix.setScale(scale, scale);
+ matrix.postTranslate((iconSize - (scale * mImageWidth)) / 2,
+ (iconSize - (scale * mImageHeight)) / 2);
+ Bitmap icon = generateAdjustedHwBitmap(data.image, iconSize, iconSize, matrix, paint,
+ overlayColor);
+
+ mNotificationManager = nManager;
+ final long now = System.currentTimeMillis();
+
+ // Setup the notification
+ mNotificationStyle = new Notification.BigPictureStyle()
+ .bigPicture(picture.createAshmemBitmap());
+
+ // The public notification will show similar info but with the actual screenshot omitted
+ mPublicNotificationBuilder =
+ new Notification.Builder(context, NotificationChannels.SCREENSHOTS_HEADSUP)
+ .setContentTitle(r.getString(R.string.screenshot_saving_title))
+ .setSmallIcon(R.drawable.stat_notify_image)
+ .setCategory(Notification.CATEGORY_PROGRESS)
+ .setWhen(now)
+ .setShowWhen(true)
+ .setColor(r.getColor(
+ com.android.internal.R.color.system_notification_accent_color));
+ SystemUI.overrideNotificationAppName(context, mPublicNotificationBuilder, true);
+
+ mNotificationBuilder = new Notification.Builder(context,
+ NotificationChannels.SCREENSHOTS_HEADSUP)
+ .setContentTitle(r.getString(R.string.screenshot_saving_title))
+ .setSmallIcon(R.drawable.stat_notify_image)
+ .setWhen(now)
+ .setShowWhen(true)
+ .setColor(r.getColor(
+ com.android.internal.R.color.system_notification_accent_color))
+ .setStyle(mNotificationStyle)
+ .setPublicVersion(mPublicNotificationBuilder.build());
+ mNotificationBuilder.setFlag(Notification.FLAG_NO_CLEAR, true);
+ SystemUI.overrideNotificationAppName(context, mNotificationBuilder, true);
+
+ mNotificationManager.notify(SystemMessage.NOTE_GLOBAL_SCREENSHOT,
+ mNotificationBuilder.build());
+
+ /**
+ * NOTE: The following code prepares the notification builder for updating the
+ * notification after the screenshot has been written to disk.
+ */
+
+ // On the tablet, the large icon makes the notification appear as if it is clickable
+ // (and on small devices, the large icon is not shown) so defer showing the large icon
+ // until we compose the final post-save notification below.
+ mNotificationBuilder.setLargeIcon(icon.createAshmemBitmap());
+ // But we still don't set it for the expanded view, allowing the smallIcon to show here.
+ mNotificationStyle.bigLargeIcon((Bitmap) null);
+ }
- @Override
- protected Void doInBackground(Void... paramsUnused) {
- if (isCancelled()) {
- return null;
+ /**
+ * Generates a new hardware bitmap with specified values, copying the content from the
+ * passed in bitmap.
+ */
+ private Bitmap generateAdjustedHwBitmap(Bitmap bitmap, int width, int height, Matrix matrix,
+ Paint paint, int color) {
+ Picture picture = new Picture();
+ Canvas canvas = picture.beginRecording(width, height);
+ canvas.drawColor(color);
+ canvas.drawBitmap(bitmap, matrix, paint);
+ picture.endRecording();
+ return Bitmap.createBitmap(picture);
}
- // By default, AsyncTask sets the worker thread to have background thread priority, so bump
- // it back up so that we save a little quicker.
- Process.setThreadPriority(Process.THREAD_PRIORITY_FOREGROUND);
+ @Override
+ protected Void doInBackground(Void... paramsUnused) {
+ if (isCancelled()) {
+ return null;
+ }
- Context context = mParams.context;
- Bitmap image = mParams.image;
- Resources r = context.getResources();
+ // By default, AsyncTask sets the worker thread to have background thread priority,
+ // so bump it back up so that we save a little quicker.
+ Process.setThreadPriority(Process.THREAD_PRIORITY_FOREGROUND);
+
+ Context context = mParams.context;
+ Bitmap image = mParams.image;
+ Resources r = context.getResources();
- try {
- // Save the screenshot to the MediaStore
- final MediaStore.PendingParams params = new MediaStore.PendingParams(
- MediaStore.Images.Media.EXTERNAL_CONTENT_URI, mImageFileName, "image/png");
- params.setRelativePath(Environment.DIRECTORY_PICTURES + File.separator
- + Environment.DIRECTORY_SCREENSHOTS);
-
- final Uri uri = MediaStore.createPending(context, params);
- final MediaStore.PendingSession session = MediaStore.openPending(context, uri);
try {
- try (OutputStream out = session.openOutputStream()) {
- if (!image.compress(Bitmap.CompressFormat.PNG, 100, out)) {
- throw new IOException("Failed to compress");
+ // Save the screenshot to the MediaStore
+ final MediaStore.PendingParams params = new MediaStore.PendingParams(
+ MediaStore.Images.Media.EXTERNAL_CONTENT_URI, mImageFileName, "image/png");
+ params.setRelativePath(Environment.DIRECTORY_PICTURES + File.separator
+ + Environment.DIRECTORY_SCREENSHOTS);
+
+ final Uri uri = MediaStore.createPending(context, params);
+ final MediaStore.PendingSession session = MediaStore.openPending(context, uri);
+ try {
+ try (OutputStream out = session.openOutputStream()) {
+ if (!image.compress(Bitmap.CompressFormat.PNG, 100, out)) {
+ throw new IOException("Failed to compress");
+ }
}
+ session.publish();
+ } catch (Exception e) {
+ session.abandon();
+ throw e;
+ } finally {
+ IoUtils.closeQuietly(session);
}
- session.publish();
+
+ // Note: Both the share and edit actions are proxied through ActionProxyReceiver in
+ // order to do some common work like dismissing the keyguard and sending
+ // closeSystemWindows
+
+ // Create a share intent, this will always go through the chooser activity first
+ // which should not trigger auto-enter PiP
+ String subjectDate = DateFormat.getDateTimeInstance().format(new Date(mImageTime));
+ String subject = String.format(SCREENSHOT_SHARE_SUBJECT_TEMPLATE, subjectDate);
+ Intent sharingIntent = new Intent(Intent.ACTION_SEND);
+ sharingIntent.setType("image/png");
+ sharingIntent.putExtra(Intent.EXTRA_STREAM, uri);
+ // Include URI in ClipData also, so that grantPermission picks it up.
+ // We don't use setData here because some apps interpret this as "to:".
+ ClipData clipdata = new ClipData(new ClipDescription("content",
+ new String[]{ClipDescription.MIMETYPE_TEXT_PLAIN}),
+ new ClipData.Item(uri));
+ sharingIntent.setClipData(clipdata);
+ sharingIntent.putExtra(Intent.EXTRA_SUBJECT, subject);
+ sharingIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+
+ // Make sure pending intents for the system user are still unique across users
+ // by setting the (otherwise unused) request code to the current user id.
+ int requestCode = context.getUserId();
+
+ PendingIntent chooserAction = PendingIntent.getBroadcast(context, requestCode,
+ new Intent(context, GlobalScreenshot.TargetChosenReceiver.class),
+ PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT);
+ Intent sharingChooserIntent = Intent.createChooser(sharingIntent, null,
+ chooserAction.getIntentSender())
+ .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK)
+ .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+
+ // Create a share action for the notification
+ PendingIntent shareAction = PendingIntent.getBroadcastAsUser(context, requestCode,
+ new Intent(context, GlobalScreenshot.ActionProxyReceiver.class)
+ .putExtra(EXTRA_ACTION_INTENT, sharingChooserIntent)
+ .putExtra(EXTRA_DISALLOW_ENTER_PIP, true)
+ .setAction(Intent.ACTION_SEND),
+ PendingIntent.FLAG_CANCEL_CURRENT, UserHandle.SYSTEM);
+ Notification.Action.Builder shareActionBuilder = new Notification.Action.Builder(
+ R.drawable.ic_screenshot_share,
+ r.getString(com.android.internal.R.string.share), shareAction);
+ mNotificationBuilder.addAction(shareActionBuilder.build());
+
+ // Create an edit intent, if a specific package is provided as the editor, then
+ // launch that directly
+ String editorPackage = context.getString(R.string.config_screenshotEditor);
+ Intent editIntent = new Intent(Intent.ACTION_EDIT);
+ if (!TextUtils.isEmpty(editorPackage)) {
+ editIntent.setComponent(ComponentName.unflattenFromString(editorPackage));
+ }
+ editIntent.setType("image/png");
+ editIntent.setData(uri);
+ editIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ editIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+
+ // Create a edit action
+ PendingIntent editAction = PendingIntent.getBroadcastAsUser(context, requestCode,
+ new Intent(context, GlobalScreenshot.ActionProxyReceiver.class)
+ .putExtra(EXTRA_ACTION_INTENT, editIntent)
+ .putExtra(EXTRA_CANCEL_NOTIFICATION,
+ editIntent.getComponent() != null)
+ .setAction(Intent.ACTION_EDIT),
+ PendingIntent.FLAG_CANCEL_CURRENT, UserHandle.SYSTEM);
+ Notification.Action.Builder editActionBuilder = new Notification.Action.Builder(
+ R.drawable.ic_screenshot_edit,
+ r.getString(com.android.internal.R.string.screenshot_edit), editAction);
+ mNotificationBuilder.addAction(editActionBuilder.build());
+ if (editAction != null && mParams.onEditReady != null) {
+ mParams.onEditReady.apply(editAction);
+ }
+
+ // Create a delete action for the notification
+ PendingIntent deleteAction = PendingIntent.getBroadcast(context, requestCode,
+ new Intent(context, GlobalScreenshot.DeleteScreenshotReceiver.class)
+ .putExtra(GlobalScreenshot.SCREENSHOT_URI_ID, uri.toString()),
+ PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT);
+ Notification.Action.Builder deleteActionBuilder = new Notification.Action.Builder(
+ R.drawable.ic_screenshot_delete,
+ r.getString(com.android.internal.R.string.delete), deleteAction);
+ mNotificationBuilder.addAction(deleteActionBuilder.build());
+
+ mParams.imageUri = uri;
+ mParams.image = null;
+ mParams.errorMsgResId = 0;
} catch (Exception e) {
- session.abandon();
- throw e;
- } finally {
- IoUtils.closeQuietly(session);
+ // IOException/UnsupportedOperationException may be thrown if external storage is
+ // not mounted
+ Slog.e(TAG, "unable to save screenshot", e);
+ mParams.clearImage();
+ mParams.errorMsgResId = R.string.screenshot_failed_to_save_text;
}
- // Note: Both the share and edit actions are proxied through ActionProxyReceiver in
- // order to do some common work like dismissing the keyguard and sending
- // closeSystemWindows
-
- // Create a share intent, this will always go through the chooser activity first which
- // should not trigger auto-enter PiP
- String subjectDate = DateFormat.getDateTimeInstance().format(new Date(mImageTime));
- String subject = String.format(SCREENSHOT_SHARE_SUBJECT_TEMPLATE, subjectDate);
- Intent sharingIntent = new Intent(Intent.ACTION_SEND);
- sharingIntent.setType("image/png");
- sharingIntent.putExtra(Intent.EXTRA_STREAM, uri);
- // Include URI in ClipData also, so that grantPermission picks it up.
- // We don't use setData here because some apps interpret this as "to:".
- ClipData clipdata = new ClipData(new ClipDescription("content",
- new String[]{ClipDescription.MIMETYPE_TEXT_PLAIN}),
- new ClipData.Item(uri));
- sharingIntent.setClipData(clipdata);
- sharingIntent.putExtra(Intent.EXTRA_SUBJECT, subject);
- sharingIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
-
- // Make sure pending intents for the system user are still unique across users
- // by setting the (otherwise unused) request code to the current user id.
- int requestCode = context.getUserId();
-
- PendingIntent chooserAction = PendingIntent.getBroadcast(context, requestCode,
- new Intent(context, GlobalScreenshot.TargetChosenReceiver.class),
- PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT);
- Intent sharingChooserIntent = Intent.createChooser(sharingIntent, null,
- chooserAction.getIntentSender())
- .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK)
- .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
-
- // Create a share action for the notification
- PendingIntent shareAction = PendingIntent.getBroadcastAsUser(context, requestCode,
- new Intent(context, GlobalScreenshot.ActionProxyReceiver.class)
- .putExtra(EXTRA_ACTION_INTENT, sharingChooserIntent)
- .putExtra(EXTRA_DISALLOW_ENTER_PIP, true)
- .setAction(Intent.ACTION_SEND),
- PendingIntent.FLAG_CANCEL_CURRENT, UserHandle.SYSTEM);
- Notification.Action.Builder shareActionBuilder = new Notification.Action.Builder(
- R.drawable.ic_screenshot_share,
- r.getString(com.android.internal.R.string.share), shareAction);
- mNotificationBuilder.addAction(shareActionBuilder.build());
-
- // Create an edit intent, if a specific package is provided as the editor, then launch
- // that directly
- String editorPackage = context.getString(R.string.config_screenshotEditor);
- Intent editIntent = new Intent(Intent.ACTION_EDIT);
- if (!TextUtils.isEmpty(editorPackage)) {
- editIntent.setComponent(ComponentName.unflattenFromString(editorPackage));
- }
- editIntent.setType("image/png");
- editIntent.setData(uri);
- editIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
- editIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
-
- // Create a edit action
- PendingIntent editAction = PendingIntent.getBroadcastAsUser(context, requestCode,
- new Intent(context, GlobalScreenshot.ActionProxyReceiver.class)
- .putExtra(EXTRA_ACTION_INTENT, editIntent)
- .putExtra(EXTRA_CANCEL_NOTIFICATION, editIntent.getComponent() != null)
- .setAction(Intent.ACTION_EDIT),
- PendingIntent.FLAG_CANCEL_CURRENT, UserHandle.SYSTEM);
- Notification.Action.Builder editActionBuilder = new Notification.Action.Builder(
- R.drawable.ic_screenshot_edit,
- r.getString(com.android.internal.R.string.screenshot_edit), editAction);
- mNotificationBuilder.addAction(editActionBuilder.build());
- if (editAction != null && mParams.onEditReady != null) {
- mParams.onEditReady.apply(editAction);
+ // Recycle the bitmap data
+ if (image != null) {
+ image.recycle();
}
- // Create a delete action for the notification
- PendingIntent deleteAction = PendingIntent.getBroadcast(context, requestCode,
- new Intent(context, GlobalScreenshot.DeleteScreenshotReceiver.class)
- .putExtra(GlobalScreenshot.SCREENSHOT_URI_ID, uri.toString()),
- PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT);
- Notification.Action.Builder deleteActionBuilder = new Notification.Action.Builder(
- R.drawable.ic_screenshot_delete,
- r.getString(com.android.internal.R.string.delete), deleteAction);
- mNotificationBuilder.addAction(deleteActionBuilder.build());
-
- mParams.imageUri = uri;
- mParams.image = null;
- mParams.errorMsgResId = 0;
- } catch (Exception e) {
- // IOException/UnsupportedOperationException may be thrown if external storage is not
- // mounted
- Slog.e(TAG, "unable to save screenshot", e);
- mParams.clearImage();
- mParams.errorMsgResId = R.string.screenshot_failed_to_save_text;
+ return null;
}
- // Recycle the bitmap data
- if (image != null) {
- image.recycle();
+ @Override
+ protected void onPostExecute(Void params) {
+ if (mParams.errorMsgResId != 0) {
+ // Show a message that we've failed to save the image to disk
+ GlobalScreenshot.notifyScreenshotError(mParams.context, mNotificationManager,
+ mParams.errorMsgResId);
+ } else {
+ if (mParams.onEditReady != null) {
+ // Cancel the "saving screenshot" notification
+ mNotificationManager.cancel(SystemMessage.NOTE_GLOBAL_SCREENSHOT);
+ } else {
+ // Show the final notification to indicate screenshot saved
+ Context context = mParams.context;
+ Resources r = context.getResources();
+
+ // Create the intent to show the screenshot in gallery
+ Intent launchIntent = new Intent(Intent.ACTION_VIEW);
+ launchIntent.setDataAndType(mParams.imageUri, "image/png");
+ launchIntent.setFlags(
+ Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_GRANT_READ_URI_PERMISSION);
+
+ final long now = System.currentTimeMillis();
+
+ // Update the text and the icon for the existing notification
+ mPublicNotificationBuilder
+ .setContentTitle(r.getString(R.string.screenshot_saved_title))
+ .setContentText(r.getString(R.string.screenshot_saved_text))
+ .setContentIntent(
+ PendingIntent.getActivity(mParams.context, 0, launchIntent, 0))
+ .setWhen(now)
+ .setAutoCancel(true)
+ .setColor(context.getColor(
+ com.android.internal.R.color.system_notification_accent_color));
+ mNotificationBuilder
+ .setContentTitle(r.getString(R.string.screenshot_saved_title))
+ .setContentText(r.getString(R.string.screenshot_saved_text))
+ .setContentIntent(PendingIntent.getActivity(mParams.context, 0,
+ launchIntent, 0))
+ .setWhen(now)
+ .setAutoCancel(true)
+ .setColor(context.getColor(
+ com.android.internal.R.color.system_notification_accent_color))
+ .setPublicVersion(mPublicNotificationBuilder.build())
+ .setFlag(Notification.FLAG_NO_CLEAR, false);
+
+ mNotificationManager.notify(SystemMessage.NOTE_GLOBAL_SCREENSHOT,
+ mNotificationBuilder.build());
+ }
+ }
+ mParams.finisher.run();
+ mParams.clearContext();
}
- return null;
- }
-
- @Override
- protected void onPostExecute(Void params) {
- if (mParams.errorMsgResId != 0) {
- // Show a message that we've failed to save the image to disk
- GlobalScreenshot.notifyScreenshotError(mParams.context, mNotificationManager,
- mParams.errorMsgResId);
- } else {
- if (mParams.onEditReady != null) {
- // Cancel the "saving screenshot" notification
- mNotificationManager.cancel(SystemMessage.NOTE_GLOBAL_SCREENSHOT);
- } else {
- // Show the final notification to indicate screenshot saved
- Context context = mParams.context;
- Resources r = context.getResources();
-
- // Create the intent to show the screenshot in gallery
- Intent launchIntent = new Intent(Intent.ACTION_VIEW);
- launchIntent.setDataAndType(mParams.imageUri, "image/png");
- launchIntent.setFlags(
- Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_GRANT_READ_URI_PERMISSION);
-
- final long now = System.currentTimeMillis();
-
- // Update the text and the icon for the existing notification
- mPublicNotificationBuilder
- .setContentTitle(r.getString(R.string.screenshot_saved_title))
- .setContentText(r.getString(R.string.screenshot_saved_text))
- .setContentIntent(
- PendingIntent.getActivity(mParams.context, 0, launchIntent, 0))
- .setWhen(now)
- .setAutoCancel(true)
- .setColor(context.getColor(
- com.android.internal.R.color.system_notification_accent_color));
- mNotificationBuilder
- .setContentTitle(r.getString(R.string.screenshot_saved_title))
- .setContentText(r.getString(R.string.screenshot_saved_text))
- .setContentIntent(PendingIntent.getActivity(mParams.context, 0, launchIntent, 0))
- .setWhen(now)
- .setAutoCancel(true)
- .setColor(context.getColor(
- com.android.internal.R.color.system_notification_accent_color))
- .setPublicVersion(mPublicNotificationBuilder.build())
- .setFlag(Notification.FLAG_NO_CLEAR, false);
+ @Override
+ protected void onCancelled(Void params) {
+ // If we are cancelled while the task is running in the background, we may get null
+ // params. The finisher is expected to always be called back, so just use the baked-in
+ // params from the ctor in any case.
+ mParams.finisher.run();
+ mParams.clearImage();
+ mParams.clearContext();
- mNotificationManager.notify(SystemMessage.NOTE_GLOBAL_SCREENSHOT,
- mNotificationBuilder.build());
- }
+ // Cancel the posted notification
+ mNotificationManager.cancel(SystemMessage.NOTE_GLOBAL_SCREENSHOT);
}
- mParams.finisher.run();
- mParams.clearContext();
}
- @Override
- protected void onCancelled(Void params) {
- // If we are cancelled while the task is running in the background, we may get null params.
- // The finisher is expected to always be called back, so just use the baked-in params from
- // the ctor in any case.
- mParams.finisher.run();
- mParams.clearImage();
- mParams.clearContext();
-
- // Cancel the posted notification
- mNotificationManager.cancel(SystemMessage.NOTE_GLOBAL_SCREENSHOT);
- }
-}
-
-/**
- * An AsyncTask that deletes an image from the media store in the background.
- */
-class DeleteImageInBackgroundTask extends AsyncTask<Uri, Void, Void> {
- private Context mContext;
+ /**
+ * An AsyncTask that deletes an image from the media store in the background.
+ */
+ private static class DeleteImageInBackgroundTask extends AsyncTask<Uri, Void, Void> {
+ private Context mContext;
- DeleteImageInBackgroundTask(Context context) {
- mContext = context;
- }
+ DeleteImageInBackgroundTask(Context context) {
+ mContext = context;
+ }
- @Override
- protected Void doInBackground(Uri... params) {
- if (params.length != 1) return null;
+ @Override
+ protected Void doInBackground(Uri... params) {
+ if (params.length != 1) return null;
- Uri screenshotUri = params[0];
- ContentResolver resolver = mContext.getContentResolver();
- resolver.delete(screenshotUri, null, null);
- return null;
+ Uri screenshotUri = params[0];
+ ContentResolver resolver = mContext.getContentResolver();
+ resolver.delete(screenshotUri, null, null);
+ return null;
+ }
}
-}
-@Singleton
-public class GlobalScreenshot {
static final String SCREENSHOT_URI_ID = "android:screenshot_uri_id";
static final String EXTRA_ACTION_INTENT = "android:screenshot_action_intent";
static final String EXTRA_CANCEL_NOTIFICATION = "android:screenshot_cancel_notification";
@@ -1041,8 +1048,9 @@ public class GlobalScreenshot {
private final StatusBar mStatusBar;
@Inject
- public ActionProxyReceiver(StatusBar statusBar) {
- mStatusBar = statusBar;
+ public ActionProxyReceiver(Optional<Lazy<StatusBar>> statusBarLazy) {
+ Lazy<StatusBar> statusBar = statusBarLazy.orElse(null);
+ mStatusBar = statusBar != null ? statusBar.get() : null;
}
@Override
@@ -1067,8 +1075,13 @@ public class GlobalScreenshot {
context.startActivityAsUser(actionIntent, opts.toBundle(), UserHandle.CURRENT);
};
- mStatusBar.executeRunnableDismissingKeyguard(startActivityRunnable, null,
- true /* dismissShade */, true /* afterKeyguardGone */, true /* deferred */);
+ if (mStatusBar != null) {
+ mStatusBar.executeRunnableDismissingKeyguard(startActivityRunnable, null,
+ true /* dismissShade */, true /* afterKeyguardGone */,
+ true /* deferred */);
+ } else {
+ startActivityRunnable.run();
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index eb6ea13a6690..621f101cd8af 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -22,8 +22,6 @@ import static android.inputmethodservice.InputMethodService.BACK_DISPOSITION_DEF
import static android.inputmethodservice.InputMethodService.IME_INVISIBLE;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
-import static android.view.InsetsState.TYPE_NAVIGATION_BAR;
-import static android.view.InsetsState.TYPE_TOP_BAR;
import static com.android.systemui.statusbar.phone.StatusBar.ONLY_CORE_APPS;
@@ -34,7 +32,6 @@ import android.app.StatusBarManager.WindowType;
import android.app.StatusBarManager.WindowVisibleState;
import android.content.ComponentName;
import android.content.Context;
-import android.graphics.Rect;
import android.hardware.biometrics.IBiometricServiceReceiverInternal;
import android.hardware.display.DisplayManager;
import android.inputmethodservice.InputMethodService.BackDispositionMode;
@@ -45,13 +42,9 @@ import android.os.Looper;
import android.os.Message;
import android.util.Pair;
import android.util.SparseArray;
-import android.view.InsetsFlags;
import android.view.InsetsState.InternalInsetType;
-import android.view.View;
import android.view.WindowInsetsController.Appearance;
-import androidx.annotation.VisibleForTesting;
-
import com.android.internal.os.SomeArgs;
import com.android.internal.statusbar.IStatusBar;
import com.android.internal.statusbar.StatusBarIcon;
@@ -61,9 +54,6 @@ import com.android.systemui.statusbar.policy.CallbackController;
import java.util.ArrayList;
-import javax.inject.Inject;
-import javax.inject.Singleton;
-
/**
* This class takes the functions from IStatusBar that come in on
* binder pool threads and posts messages to get them onto the main
@@ -71,7 +61,6 @@ import javax.inject.Singleton;
* coalescing these calls so they don't stack up. For the calls
* are coalesced, note that they are all idempotent.
*/
-@Singleton
public class CommandQueue extends IStatusBar.Stub implements CallbackController<Callbacks>,
DisplayManager.DisplayListener {
private static final int INDEX_MASK = 0xffff;
@@ -307,8 +296,6 @@ public class CommandQueue extends IStatusBar.Stub implements CallbackController<
}
}
- @VisibleForTesting
- @Inject
public CommandQueue(Context context) {
context.getSystemService(DisplayManager.class).registerDisplayListener(this, mHandler);
// We always have default display.
@@ -470,42 +457,6 @@ public class CommandQueue extends IStatusBar.Stub implements CallbackController<
}
}
- // TODO(b/118118435): Remove this function after migration
- @Override
- public void setSystemUiVisibility(int displayId, int vis, int fullscreenStackVis,
- int dockedStackVis, int mask, Rect fullscreenStackBounds, Rect dockedStackBounds,
- boolean navbarColorManagedByIme) {
- synchronized (mLock) {
- final boolean hasDockedStack = !dockedStackBounds.isEmpty();
- final boolean transientStatus = (vis & View.STATUS_BAR_TRANSIENT) != 0;
- final boolean transientNavigation = (vis & View.NAVIGATION_BAR_TRANSIENT) != 0;
- if (transientStatus && transientNavigation) {
- showTransient(displayId, new int[]{TYPE_TOP_BAR, TYPE_NAVIGATION_BAR});
- } else if (transientStatus) {
- showTransient(displayId, new int[]{TYPE_TOP_BAR});
- abortTransient(displayId, new int[]{TYPE_NAVIGATION_BAR});
- } else if (transientNavigation) {
- showTransient(displayId, new int[]{TYPE_NAVIGATION_BAR});
- abortTransient(displayId, new int[]{TYPE_TOP_BAR});
- } else {
- abortTransient(displayId, new int[]{TYPE_TOP_BAR, TYPE_NAVIGATION_BAR});
- }
- SomeArgs args = SomeArgs.obtain();
- args.argi1 = displayId;
- args.argi2 = InsetsFlags.getAppearance(vis);
- args.argi3 = navbarColorManagedByIme ? 1 : 0;
- final int fullscreenAppearance = InsetsFlags.getAppearance(fullscreenStackVis);
- final int dockedAppearance = InsetsFlags.getAppearance(dockedStackVis);
- args.arg1 = hasDockedStack
- ? new AppearanceRegion[]{
- new AppearanceRegion(fullscreenAppearance, fullscreenStackBounds),
- new AppearanceRegion(dockedAppearance, dockedStackBounds)}
- : new AppearanceRegion[]{
- new AppearanceRegion(fullscreenAppearance, fullscreenStackBounds)};
- mHandler.obtainMessage(MSG_SYSTEM_BAR_APPEARANCE_CHANGED, args).sendToTarget();
- }
- }
-
@Override
public void topAppWindowChanged(int displayId, boolean isFullscreen, boolean isImmersive) {
synchronized (mLock) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarDependenciesModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarDependenciesModule.java
new file mode 100644
index 000000000000..d1f6ebf3826d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarDependenciesModule.java
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+package com.android.systemui.statusbar;
+
+import android.content.Context;
+
+import javax.inject.Singleton;
+
+import dagger.Module;
+import dagger.Provides;
+
+/**
+ * Dagger Module providing common dependencies of StatusBar.
+ */
+@Module
+public class StatusBarDependenciesModule {
+ /**
+ * Provides our instance of CommandQueue which is considered optional.
+ */
+ @Provides
+ @Singleton
+ public CommandQueue provideCommandQueue(Context context) {
+ return new CommandQueue(context);
+ }
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SuperStatusBarViewFactory.java b/packages/SystemUI/src/com/android/systemui/statusbar/SuperStatusBarViewFactory.java
new file mode 100644
index 000000000000..bc7c22d65a44
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SuperStatusBarViewFactory.java
@@ -0,0 +1,92 @@
+/*
+ * 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.
+ */
+
+package com.android.systemui.statusbar;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.ViewGroup;
+
+import com.android.systemui.R;
+import com.android.systemui.statusbar.phone.StatusBarWindowView;
+import com.android.systemui.util.InjectionInflationController;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ * Creates a single instance of super_status_bar that can be shared across various system ui
+ * objects.
+ */
+@Singleton
+public class SuperStatusBarViewFactory {
+
+ private final Context mContext;
+ private final InjectionInflationController mInjectionInflationController;
+
+ private StatusBarWindowView mStatusBarWindowView;
+ private NotificationShelf mNotificationShelf;
+
+ @Inject
+ public SuperStatusBarViewFactory(Context context,
+ InjectionInflationController injectionInflationController) {
+ mContext = context;
+ mInjectionInflationController = injectionInflationController;
+ }
+
+ /**
+ * Gets the inflated {@link StatusBarWindowView} from {@link R.layout#super_status_bar}. Returns
+ * a cached instance, if it has already been inflated.
+ */
+ public StatusBarWindowView getStatusBarWindowView() {
+ if (mStatusBarWindowView != null) {
+ return mStatusBarWindowView;
+ }
+
+ mStatusBarWindowView = (StatusBarWindowView) mInjectionInflationController.injectable(
+ LayoutInflater.from(mContext)).inflate(R.layout.super_status_bar,
+ /* root= */ null);
+ if (mStatusBarWindowView == null) {
+ throw new IllegalStateException(
+ "R.layout.super_status_bar could not be properly inflated");
+ }
+ return mStatusBarWindowView;
+ }
+
+ /**
+ * Gets the inflated {@link NotificationShelf} from
+ * {@link R.layout#status_bar_notification_shelf}.
+ * Returns a cached instance, if it has already been inflated.
+ *
+ * @param container the expected container to hold the {@link NotificationShelf}. The view
+ * isn't immediately attached, but the layout params of this view is used
+ * during inflation.
+ */
+ public NotificationShelf getNotificationShelf(ViewGroup container) {
+ if (mNotificationShelf != null) {
+ return mNotificationShelf;
+ }
+
+ mNotificationShelf = (NotificationShelf) mInjectionInflationController.injectable(
+ LayoutInflater.from(mContext)).inflate(R.layout.status_bar_notification_shelf,
+ container, /* attachToRoot= */ false);
+ if (mNotificationShelf == null) {
+ throw new IllegalStateException(
+ "R.layout.status_bar_notification_shelf could not be properly inflated");
+ }
+ return mNotificationShelf;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationData.java
index 9981c93431e7..a0229d16d6eb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationData.java
@@ -68,7 +68,6 @@ public class NotificationData {
private final ArrayMap<String, NotificationEntry> mEntries = new ArrayMap<>();
private final ArrayList<NotificationEntry> mSortedAndFiltered = new ArrayList<>();
- private final ArrayList<NotificationEntry> mFilteredForUser = new ArrayList<>();
private final NotificationGroupManager mGroupManager =
Dependency.get(NotificationGroupManager.class);
@@ -166,20 +165,20 @@ public class NotificationData {
}
public ArrayList<NotificationEntry> getNotificationsForCurrentUser() {
- mFilteredForUser.clear();
-
synchronized (mEntries) {
final int len = mEntries.size();
+ ArrayList<NotificationEntry> filteredForUser = new ArrayList<>(len);
+
for (int i = 0; i < len; i++) {
NotificationEntry entry = mEntries.valueAt(i);
final StatusBarNotification sbn = entry.getSbn();
if (!getEnvironment().isNotificationForCurrentProfiles(sbn)) {
continue;
}
- mFilteredForUser.add(entry);
+ filteredForUser.add(entry);
}
+ return filteredForUser;
}
- return mFilteredForUser;
}
public NotificationEntry get(String key) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinderImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinderImpl.java
index 396c5fefd8b7..0ef75165f54f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinderImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinderImpl.java
@@ -142,6 +142,7 @@ public class NotificationRowBinderImpl implements NotificationRowBinder {
entry.updateIcons(mContext, sbn);
entry.reset();
updateNotification(entry, pmUser, sbn, entry.getRow());
+ entry.getRow().setOnDismissRunnable(onDismissRunnable);
} else {
entry.createIcons(mContext, sbn);
new RowInflaterTask().inflate(mContext, parent, entry,
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 a817f54e77ca..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
@@ -159,6 +159,8 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
private int mHeadsUpAddStartLocation;
private float mHeadsUpLocation;
private boolean mIsAppearing;
+ private boolean mDismissed;
+ private boolean mRefocusOnDismiss;
public ActivatableNotificationView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -1048,6 +1050,27 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
return getHeight();
}
+ /** Mark that this view has been dismissed. */
+ public void dismiss(boolean refocusOnDismiss) {
+ mDismissed = true;
+ mRefocusOnDismiss = refocusOnDismiss;
+ }
+
+ /** Mark that this view is no longer dismissed. */
+ public void unDismiss() {
+ mDismissed = false;
+ }
+
+ /** Is this view marked as dismissed? */
+ public boolean isDismissed() {
+ return mDismissed;
+ }
+
+ /** Should a re-focus occur upon dismissing this view? */
+ public boolean shouldRefocusOnDismiss() {
+ return mRefocusOnDismiss || isAccessibilityFocused();
+ }
+
public interface OnActivatedListener {
void onActivated(ActivatableNotificationView view);
void onActivationReset(ActivatableNotificationView view);
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 536db67a8795..f0d07a7ed0bd 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
@@ -95,6 +95,7 @@ import com.android.systemui.statusbar.notification.stack.AnimationProperties;
import com.android.systemui.statusbar.notification.stack.ExpandableViewState;
import com.android.systemui.statusbar.notification.stack.NotificationChildrenContainer;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
+import com.android.systemui.statusbar.notification.stack.SwipeableView;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.StatusBar;
@@ -114,7 +115,7 @@ import java.util.function.Consumer;
* the group summary (which contains 1 or more child notifications).
*/
public class ExpandableNotificationRow extends ActivatableNotificationView
- implements PluginListener<NotificationMenuRowPlugin> {
+ implements PluginListener<NotificationMenuRowPlugin>, SwipeableView {
private static final boolean DEBUG = false;
private static final int DEFAULT_DIVIDER_ALPHA = 0x29;
@@ -288,7 +289,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
}
};
private boolean mForceUnlocked;
- private boolean mDismissed;
private boolean mKeepInParent;
private boolean mRemoved;
private static final Property<ExpandableNotificationRow, Float> TRANSLATE_CONTENT =
@@ -307,7 +307,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
private boolean mHeadsupDisappearRunning;
private View mChildAfterViewWhenDismissed;
private View mGroupParentWhenDismissed;
- private boolean mRefocusOnDismiss;
private float mContentTransformationAmount;
private boolean mIconsVisible = true;
private boolean mAboveShelf;
@@ -1164,6 +1163,11 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
}
}
+ @Override
+ public boolean hasFinishedInitialization() {
+ return getEntry().hasFinishedInitialization();
+ }
+
/**
* Get a handle to a NotificationMenuRowPlugin whose menu view has been added to our hierarchy,
* or null if there is no menu row
@@ -1323,11 +1327,11 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
}
}
- public void setDismissed(boolean fromAccessibility) {
+ @Override
+ public void dismiss(boolean refocusOnDismiss) {
+ super.dismiss(refocusOnDismiss);
setLongPressListener(null);
- mDismissed = true;
mGroupParentWhenDismissed = mNotificationParent;
- mRefocusOnDismiss = fromAccessibility;
mChildAfterViewWhenDismissed = null;
mEntry.icon.setDismissed();
if (isChildInGroup()) {
@@ -1340,10 +1344,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
}
}
- public boolean isDismissed() {
- return mDismissed;
- }
-
public boolean keepInParent() {
return mKeepInParent;
}
@@ -1445,7 +1445,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
groupSummary.getRow().performDismiss(fromAccessibility);
}
}
- setDismissed(fromAccessibility);
+ dismiss(fromAccessibility);
if (mEntry.isClearable()) {
// TODO: beverlyt, log dismissal
// TODO: track dismiss sentiment
@@ -3021,10 +3021,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
return false;
}
- public boolean shouldRefocusOnDismiss() {
- return mRefocusOnDismiss || isAccessibilityFocused();
- }
-
public interface OnExpandClickListener {
void onExpandClicked(NotificationEntry clickedEntry, boolean nowExpanded);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java
index 54d406615ae0..fdd51e9e7790 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java
@@ -23,7 +23,6 @@ import static java.lang.annotation.RetentionPolicy.SOURCE;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.app.PendingIntent;
import android.content.Intent;
import android.provider.Settings;
import android.view.LayoutInflater;
@@ -310,6 +309,8 @@ public class NotificationSectionsManager implements StackScrollAlgorithm.Section
mParent.removeView(mPeopleHubView);
}
} else {
+ mPeopleHubView.unDismiss();
+ mPeopleHubView.resetTranslation();
if (!currentlyVisible) {
if (mPeopleHubView.getTransientContainer() != null) {
mPeopleHubView.getTransientContainer().removeTransientView(mPeopleHubView);
@@ -419,8 +420,9 @@ public class NotificationSectionsManager implements StackScrollAlgorithm.Section
}
}
- private void handlePeopleHubClick(PendingIntent pendingIntent) {
- mActivityStarter.startPendingIntentDismissingKeyguard(pendingIntent, null, mPeopleHubView);
+ void hidePeopleRow() {
+ mPeopleHubVisible = false;
+ updateSectionBoundaries();
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index 6dca7ee9e872..2b9912ce055d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -4920,7 +4920,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
} else {
child.setMinClipTopAmount(0);
}
- previousChildWillBeDismissed = StackScrollAlgorithm.canChildBeDismissed(child);
+ previousChildWillBeDismissed = canChildBeDismissed(child);
}
}
@@ -5523,7 +5523,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
performDismissAllAnimations(viewsToHide, closeShade, () -> {
for (ExpandableNotificationRow rowToRemove : viewsToRemove) {
- if (StackScrollAlgorithm.canChildBeDismissed(rowToRemove)) {
+ if (canChildBeDismissed(rowToRemove)) {
if (selection == ROWS_ALL) {
// TODO: This is a listener method; we shouldn't be calling it. Can we just
// call performRemoveNotification as below?
@@ -5552,7 +5552,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
private boolean includeChildInDismissAll(
ExpandableNotificationRow row,
@SelectedRows int selection) {
- return StackScrollAlgorithm.canChildBeDismissed(row) && matchesSelection(row, selection);
+ return canChildBeDismissed(row) && matchesSelection(row, selection);
}
/**
@@ -6223,7 +6223,10 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
*/
@Override
public void onChildDismissed(View view) {
- ExpandableNotificationRow row = (ExpandableNotificationRow) view;
+ if (!(view instanceof ActivatableNotificationView)) {
+ return;
+ }
+ ActivatableNotificationView row = (ActivatableNotificationView) view;
if (!row.isDismissed()) {
handleChildViewDismissed(view);
}
@@ -6261,6 +6264,12 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
row.performDismissWithBlockingHelper(false /* fromAccessibility */);
}
+ if (view instanceof PeopleHubView) {
+ PeopleHubView row = (PeopleHubView) view;
+ row.dismiss(false);
+ mSectionsManager.hidePeopleRow();
+ }
+
if (!isBlockingHelperShown) {
mSwipedOutViews.add(view);
}
@@ -6349,9 +6358,9 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
return 0;
}
- @Override
+ @Override
public boolean canChildBeDismissed(View v) {
- return StackScrollAlgorithm.canChildBeDismissed(v);
+ return NotificationStackScrollLayout.canChildBeDismissed(v);
}
@Override
@@ -6361,6 +6370,23 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
}
};
+ private static boolean canChildBeDismissed(View v) {
+ if (v instanceof ExpandableNotificationRow) {
+ ExpandableNotificationRow row = (ExpandableNotificationRow) v;
+ if (row.isBlockingHelperShowingAndTranslationFinished()) {
+ return true;
+ }
+ if (row.areGutsExposed() || !row.getEntry().hasFinishedInitialization()) {
+ return false;
+ }
+ return row.canViewBeDismissed();
+ }
+ if (v instanceof PeopleHubView) {
+ return true;
+ }
+ return false;
+ }
+
// ---------------------- DragDownHelper.OnDragDownListener ------------------------------------
@ShadeViewRefactor(RefactorComponent.INPUT)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java
index 0968674d31cc..6d0fcc386281 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java
@@ -31,11 +31,10 @@ import com.android.systemui.SwipeHelper;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.ExpandableView;
-class NotificationSwipeHelper extends SwipeHelper
- implements NotificationSwipeActionHelper {
+class NotificationSwipeHelper extends SwipeHelper implements NotificationSwipeActionHelper {
+
@VisibleForTesting
protected static final long COVER_MENU_DELAY = 4000;
private static final String TAG = "NotificationSwipeHelper";
@@ -58,12 +57,7 @@ class NotificationSwipeHelper extends SwipeHelper
super(swipeDirection, callback, context, falsingManager);
mMenuListener = menuListener;
mCallback = callback;
- mFalsingCheck = new Runnable() {
- @Override
- public void run() {
- resetExposedMenuView(true /* animate */, true /* force */);
- }
- };
+ mFalsingCheck = () -> resetExposedMenuView(true /* animate */, true /* force */);
}
public View getTranslatingParentView() {
@@ -126,14 +120,14 @@ class NotificationSwipeHelper extends SwipeHelper
// Slide back any notifications that might be showing a menu
resetExposedMenuView(true /* animate */, false /* force */);
- if (currView instanceof ExpandableNotificationRow) {
- initializeRow((ExpandableNotificationRow) currView);
+ if (currView instanceof SwipeableView) {
+ initializeRow((SwipeableView) currView);
}
}
@VisibleForTesting
- protected void initializeRow(ExpandableNotificationRow row) {
- if (row.getEntry().hasFinishedInitialization()) {
+ protected void initializeRow(SwipeableView row) {
+ if (row.hasFinishedInitialization()) {
mCurrMenuRow = row.createMenu();
if (mCurrMenuRow != null) {
mCurrMenuRow.setMenuClickListener(mMenuListener);
@@ -304,8 +298,8 @@ class NotificationSwipeHelper extends SwipeHelper
@Override
public Animator getViewTranslationAnimator(View v, float target,
ValueAnimator.AnimatorUpdateListener listener) {
- if (v instanceof ExpandableNotificationRow) {
- return ((ExpandableNotificationRow) v).getTranslateViewAnimator(target, listener);
+ if (v instanceof SwipeableView) {
+ return ((SwipeableView) v).getTranslateViewAnimator(target, listener);
} else {
return superGetViewTranslationAnimator(v, target, listener);
}
@@ -313,15 +307,15 @@ class NotificationSwipeHelper extends SwipeHelper
@Override
public void setTranslation(View v, float translate) {
- if (v instanceof ExpandableNotificationRow) {
- ((ExpandableNotificationRow) v).setTranslation(translate);
+ if (v instanceof SwipeableView) {
+ ((SwipeableView) v).setTranslation(translate);
}
}
@Override
public float getTranslation(View v) {
- if (v instanceof ExpandableNotificationRow) {
- return ((ExpandableNotificationRow) v).getTranslation();
+ if (v instanceof SwipeableView) {
+ return ((SwipeableView) v).getTranslation();
}
else {
return 0f;
@@ -410,8 +404,8 @@ class NotificationSwipeHelper extends SwipeHelper
if (anim != null) {
anim.start();
}
- } else if (prevMenuExposedView instanceof ExpandableNotificationRow) {
- ExpandableNotificationRow row = (ExpandableNotificationRow) prevMenuExposedView;
+ } else if (prevMenuExposedView instanceof SwipeableView) {
+ SwipeableView row = (SwipeableView) prevMenuExposedView;
if (!row.isRemoved()) {
row.resetTranslation();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/PeopleHubView.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/PeopleHubView.kt
index e31ee024fa36..a0796060e9d8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/PeopleHubView.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/PeopleHubView.kt
@@ -16,23 +16,39 @@
package com.android.systemui.statusbar.notification.stack
+import android.animation.Animator
+import android.animation.AnimatorListenerAdapter
+import android.animation.ObjectAnimator
+import android.animation.ValueAnimator
import android.content.Context
import android.util.AttributeSet
+import android.util.FloatProperty
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import com.android.systemui.R
-import com.android.systemui.statusbar.notification.people.PersonViewModel
+import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin
import com.android.systemui.statusbar.notification.people.DataListener
+import com.android.systemui.statusbar.notification.people.PersonViewModel
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView
+private val TRANSLATE_CONTENT = object : FloatProperty<PeopleHubView>("translate") {
+ override fun setValue(view: PeopleHubView, value: Float) {
+ view.translation = value
+ }
+
+ override fun get(view: PeopleHubView) = view.translation
+}
+
class PeopleHubView(context: Context, attrs: AttributeSet) :
- ActivatableNotificationView(context, attrs) {
+ ActivatableNotificationView(context, attrs), SwipeableView {
private lateinit var contents: ViewGroup
private lateinit var personControllers: List<PersonDataListenerImpl>
+ private var translateAnim: ObjectAnimator? = null
+
val personViewAdapters: Sequence<DataListener<PersonViewModel?>>
get() = personControllers.asSequence()
@@ -49,6 +65,34 @@ class PeopleHubView(context: Context, attrs: AttributeSet) :
override fun getContentView(): View = contents
+ override fun hasFinishedInitialization(): Boolean = true
+
+ override fun createMenu(): NotificationMenuRowPlugin? = null
+
+ override fun getTranslateViewAnimator(
+ leftTarget: Float,
+ listener: ValueAnimator.AnimatorUpdateListener?
+ ): Animator =
+ ObjectAnimator
+ .ofFloat(this, TRANSLATE_CONTENT, leftTarget)
+ .apply {
+ listener?.let { addUpdateListener(listener) }
+ addListener(object : AnimatorListenerAdapter() {
+ override fun onAnimationEnd(anim: Animator) {
+ translateAnim = null
+ }
+ })
+ }
+ .also {
+ translateAnim?.cancel()
+ translateAnim = it
+ }
+
+ override fun resetTranslation() {
+ translateAnim?.cancel()
+ translationX = 0f
+ }
+
private inner class PersonDataListenerImpl(val viewGroup: ViewGroup) :
DataListener<PersonViewModel?> {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
index 4b61064f4a54..9646c01c8c41 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
@@ -195,20 +195,6 @@ public class StackScrollAlgorithm {
}
}
- public static boolean canChildBeDismissed(View v) {
- if (!(v instanceof ExpandableNotificationRow)) {
- return false;
- }
- ExpandableNotificationRow row = (ExpandableNotificationRow) v;
- if (row.isBlockingHelperShowingAndTranslationFinished()) {
- return true;
- }
- if (row.areGutsExposed() || !row.getEntry().hasFinishedInitialization()) {
- return false;
- }
- return row.canViewBeDismissed();
- }
-
/**
* Updates the dimmed, activated and hiding sensitive states of the children.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SwipeableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SwipeableView.java
new file mode 100644
index 000000000000..6c6ef61cfdaf
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SwipeableView.java
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+
+package com.android.systemui.statusbar.notification.stack;
+
+import android.animation.Animator;
+import android.animation.ValueAnimator;
+
+import androidx.annotation.Nullable;
+
+import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
+
+/** A View that is swipeable inside of the notification shade. */
+public interface SwipeableView {
+
+ /** Has this view finished initializing? */
+ boolean hasFinishedInitialization();
+
+ /** Optionally creates a menu for this view. */
+ @Nullable NotificationMenuRowPlugin createMenu();
+
+ /** Animator for translating the view, simulating a swipe. */
+ Animator getTranslateViewAnimator(
+ float leftTarget, ValueAnimator.AnimatorUpdateListener listener);
+
+ /** Sets the translation amount for an in-progress swipe. */
+ void setTranslation(float translate);
+
+ /** Gets the current translation amount. */
+ float getTranslation();
+
+ /** Has this view been removed? */
+ boolean isRemoved();
+
+ /** Resets the swipe translation back to zero state. */
+ void resetTranslation();
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java
index fce1dcc998fe..c2731089132c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java
@@ -203,10 +203,16 @@ public class ButtonDispatcher {
mFadeAnimator.addUpdateListener(mAlphaListener);
mFadeAnimator.start();
} else {
- mAlpha = alpha;
- final int N = mViews.size();
- for (int i = 0; i < N; i++) {
- mViews.get(i).setAlpha(alpha);
+ // Discretize the alpha updates to prevent too frequent updates when there is a long
+ // alpha animation
+ int prevAlpha = (int) (getAlpha() * 255);
+ int nextAlpha = (int) (alpha * 255);
+ if (prevAlpha != nextAlpha) {
+ mAlpha = nextAlpha / 255f;
+ final int N = mViews.size();
+ for (int i = 0; i < N; i++) {
+ mViews.get(i).setAlpha(mAlpha);
+ }
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
index 2e776e39b54c..1532c4f977e0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
@@ -247,7 +247,7 @@ public class LightBarController implements BatteryController.BatteryStateChangeC
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println("LightBarController: ");
- pw.print(" mAppearance=0x"); pw.println(ViewDebug.flagsToString(
+ pw.print(" mAppearance="); pw.println(ViewDebug.flagsToString(
InsetsFlags.class, "appearance", mAppearance));
final int numStacks = mAppearanceRegions.length;
for (int i = 0; i < numStacks; i++) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationHandle.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationHandle.java
index 4f7af58094ec..abceb11b36e9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationHandle.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationHandle.java
@@ -31,13 +31,13 @@ import com.android.settingslib.Utils;
import com.android.systemui.R;
public class NavigationHandle extends View implements ButtonInterface {
- private float mDarkIntensity = -1;
private final Paint mPaint = new Paint();
private @ColorInt final int mLightColor;
private @ColorInt final int mDarkColor;
private final int mRadius;
private final int mBottom;
+ private boolean mRequiresInvalidate;
public NavigationHandle(Context context) {
this(context, null);
@@ -60,6 +60,15 @@ public class NavigationHandle extends View implements ButtonInterface {
}
@Override
+ public void setAlpha(float alpha) {
+ super.setAlpha(alpha);
+ if (alpha > 0f && mRequiresInvalidate) {
+ mRequiresInvalidate = false;
+ invalidate();
+ }
+ }
+
+ @Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
@@ -85,11 +94,15 @@ public class NavigationHandle extends View implements ButtonInterface {
@Override
public void setDarkIntensity(float intensity) {
- if (mDarkIntensity != intensity) {
- mPaint.setColor((int) ArgbEvaluator.getInstance().evaluate(intensity, mLightColor,
- mDarkColor));
- mDarkIntensity = intensity;
- invalidate();
+ int color = (int) ArgbEvaluator.getInstance().evaluate(intensity, mLightColor, mDarkColor);
+ if (mPaint.getColor() != color) {
+ mPaint.setColor(color);
+ if (getVisibility() == VISIBLE && getAlpha() > 0) {
+ invalidate();
+ } else {
+ // If we are currently invisible, then invalidate when we are next made visible
+ mRequiresInvalidate = true;
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 4148a73e579c..cff282472074 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -24,7 +24,6 @@ import static android.app.StatusBarManager.WindowType;
import static android.app.StatusBarManager.WindowVisibleState;
import static android.app.StatusBarManager.windowStateToString;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;
-import static android.view.InsetsFlags.getAppearance;
import static android.view.InsetsState.TYPE_TOP_BAR;
import static android.view.InsetsState.containsType;
import static android.view.WindowInsetsController.APPEARANCE_LOW_PROFILE_BARS;
@@ -75,7 +74,6 @@ import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Configuration;
-import android.content.res.Resources;
import android.graphics.Point;
import android.graphics.PointF;
import android.media.AudioAttributes;
@@ -109,7 +107,6 @@ import android.view.Display;
import android.view.IWindowManager;
import android.view.InsetsState.InternalInsetType;
import android.view.KeyEvent;
-import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.RemoteAnimationAdapter;
import android.view.ThreadedRenderer;
@@ -157,7 +154,6 @@ import com.android.systemui.bubbles.BubbleController;
import com.android.systemui.charging.WirelessChargingAnimation;
import com.android.systemui.classifier.FalsingLog;
import com.android.systemui.colorextraction.SysuiColorExtractor;
-import com.android.systemui.dagger.SystemUIBinder;
import com.android.systemui.doze.DozeHost;
import com.android.systemui.doze.DozeLog;
import com.android.systemui.fragments.ExtensionFragmentListener;
@@ -202,6 +198,7 @@ import com.android.systemui.statusbar.NotificationViewHierarchyManager;
import com.android.systemui.statusbar.PulseExpansionHandler;
import com.android.systemui.statusbar.ScrimView;
import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.SuperStatusBarViewFactory;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.VibratorHelper;
import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
@@ -243,7 +240,6 @@ import com.android.systemui.statusbar.policy.UserInfoController;
import com.android.systemui.statusbar.policy.UserInfoControllerImpl;
import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.statusbar.policy.ZenModeController;
-import com.android.systemui.util.InjectionInflationController;
import com.android.systemui.volume.VolumeComponent;
import java.io.FileDescriptor;
@@ -364,8 +360,6 @@ public class StatusBar extends SystemUI implements DemoMode,
@Nullable
private final KeyguardLiftController mKeyguardLiftController;
- private int mNaturalBarHeight = -1;
-
private final Point mCurrentDisplaySize = new Point();
protected StatusBarWindowViewController mStatusBarWindowViewController;
@@ -384,7 +378,6 @@ public class StatusBar extends SystemUI implements DemoMode,
private final FeatureFlags mFeatureFlags;
private final StatusBarIconController mIconController;
private final DozeLog mDozeLog;
- private final InjectionInflationController mInjectionInflater;
private final PulseExpansionHandler mPulseExpansionHandler;
private final NotificationWakeUpCoordinator mWakeUpCoordinator;
private final KeyguardBypassController mKeyguardBypassController;
@@ -403,6 +396,7 @@ public class StatusBar extends SystemUI implements DemoMode,
private final Lazy<BiometricUnlockController> mBiometricUnlockControllerLazy;
private final PluginManager mPluginManager;
private final RemoteInputUriController mRemoteInputUriController;
+ private final SuperStatusBarViewFactory mSuperStatusBarViewFactory;
// expanded notifications
protected NotificationPanelView mNotificationPanel; // the sliding/resizing panel within the notification window
@@ -637,7 +631,7 @@ public class StatusBar extends SystemUI implements DemoMode,
* Public constructor for StatusBar.
*
* StatusBar is considered optional, and therefore can not be marked as @Inject directly.
- * Instead, an @Provide method is included in {@link SystemUIBinder}.
+ * Instead, an @Provide method is included.
*/
public StatusBar(
Context context,
@@ -647,7 +641,6 @@ public class StatusBar extends SystemUI implements DemoMode,
KeyguardUpdateMonitor keyguardUpdateMonitor,
StatusBarIconController statusBarIconController,
DozeLog dozeLog,
- InjectionInflationController injectionInflationController,
PulseExpansionHandler pulseExpansionHandler,
NotificationWakeUpCoordinator notificationWakeUpCoordinator,
KeyguardBypassController keyguardBypassController,
@@ -706,7 +699,8 @@ public class StatusBar extends SystemUI implements DemoMode,
DozeScrimController dozeScrimController,
CommandQueue commandQueue,
PluginManager pluginManager,
- RemoteInputUriController remoteInputUriController) {
+ RemoteInputUriController remoteInputUriController,
+ SuperStatusBarViewFactory superStatusBarViewFactory) {
super(context);
mFeatureFlags = featureFlags;
mLightBarController = lightBarController;
@@ -714,7 +708,6 @@ public class StatusBar extends SystemUI implements DemoMode,
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
mIconController = statusBarIconController;
mDozeLog = dozeLog;
- mInjectionInflater = injectionInflationController;
mPulseExpansionHandler = pulseExpansionHandler;
mWakeUpCoordinator = notificationWakeUpCoordinator;
mKeyguardBypassController = keyguardBypassController;
@@ -774,6 +767,8 @@ public class StatusBar extends SystemUI implements DemoMode,
mCommandQueue = commandQueue;
mPluginManager = pluginManager;
mRemoteInputUriController = remoteInputUriController;
+ mSuperStatusBarViewFactory = superStatusBarViewFactory;
+
mBubbleExpandListener =
(isExpanding, key) -> {
mEntryManager.updateNotifications("onBubbleExpandChanged");
@@ -860,19 +855,11 @@ public class StatusBar extends SystemUI implements DemoMode,
// Set up the initial notification state. This needs to happen before CommandQueue.disable()
setUpPresenter();
- if ((result.mSystemUiVisibility & View.STATUS_BAR_TRANSIENT) != 0) {
+ if (containsType(result.mTransientBarTypes, TYPE_TOP_BAR)) {
showTransientUnchecked();
}
- final int fullscreenAppearance = getAppearance(result.mFullscreenStackSysUiVisibility);
- final int dockedAppearance = getAppearance(result.mDockedStackSysUiVisibility);
- final AppearanceRegion[] appearanceRegions = result.mDockedStackBounds.isEmpty()
- ? new AppearanceRegion[]{
- new AppearanceRegion(fullscreenAppearance, result.mFullscreenStackBounds)}
- : new AppearanceRegion[]{
- new AppearanceRegion(fullscreenAppearance, result.mFullscreenStackBounds),
- new AppearanceRegion(dockedAppearance, result.mDockedStackBounds)};
- onSystemBarAppearanceChanged(mDisplayId, getAppearance(result.mSystemUiVisibility),
- appearanceRegions, result.mNavbarColorManagedByIme);
+ onSystemBarAppearanceChanged(mDisplayId, result.mAppearance, result.mAppearanceRegions,
+ result.mNavbarColorManagedByIme);
mAppFullscreen = result.mAppFullscreen;
mAppImmersive = result.mAppImmersive;
@@ -892,7 +879,7 @@ public class StatusBar extends SystemUI implements DemoMode,
"init: icons=%d disabled=0x%08x lights=0x%08x imeButton=0x%08x",
numIcons,
result.mDisabledFlags1,
- result.mSystemUiVisibility,
+ result.mAppearance,
result.mImeWindowVis));
}
@@ -1368,10 +1355,7 @@ public class StatusBar extends SystemUI implements DemoMode,
}
private void inflateShelf() {
- mNotificationShelf =
- (NotificationShelf) mInjectionInflater.injectable(
- LayoutInflater.from(mContext)).inflate(
- R.layout.status_bar_notification_shelf, mStackScroller, false);
+ mNotificationShelf = mSuperStatusBarViewFactory.getNotificationShelf(mStackScroller);
mNotificationShelf.setOnClickListener(mGoToLockedShadeListener);
}
@@ -1429,10 +1413,8 @@ public class StatusBar extends SystemUI implements DemoMode,
}
protected void inflateStatusBarWindow(Context context) {
- mStatusBarWindow = (StatusBarWindowView) mInjectionInflater.injectable(
- LayoutInflater.from(context)).inflate(R.layout.super_status_bar, null);
+ mStatusBarWindow = mSuperStatusBarViewFactory.getStatusBarWindowView();
mStatusBarWindowViewController = mStatusBarWindowViewControllerBuilder
- .setStatusBarWindowView(mStatusBarWindow)
.setShadeController(this)
.build();
}
@@ -1470,12 +1452,7 @@ public class StatusBar extends SystemUI implements DemoMode,
}
public int getStatusBarHeight() {
- if (mNaturalBarHeight < 0) {
- final Resources res = mContext.getResources();
- mNaturalBarHeight =
- res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
- }
- return mNaturalBarHeight;
+ return mStatusBarWindowController.getStatusBarHeight();
}
protected boolean toggleSplitScreenMode(int metricsDockAction, int metricsUndockAction) {
@@ -2649,7 +2626,7 @@ public class StatusBar extends SystemUI implements DemoMode,
public void createAndAddWindows(@Nullable RegisterStatusBarResult result) {
makeStatusBarView(result);
- mStatusBarWindowController.add(mStatusBarWindow, getStatusBarHeight());
+ mStatusBarWindowController.attach();
}
// called by makeStatusbar and also by PhoneStatusBarView
@@ -2927,7 +2904,7 @@ public class StatusBar extends SystemUI implements DemoMode,
mQSPanel.updateResources();
}
- loadDimens();
+ mStatusBarWindowController.refreshStatusBarHeight();
if (mStatusBarView != null) {
mStatusBarView.updateResources();
@@ -2940,19 +2917,6 @@ public class StatusBar extends SystemUI implements DemoMode,
}
}
- protected void loadDimens() {
- final Resources res = mContext.getResources();
-
- int oldBarHeight = mNaturalBarHeight;
- mNaturalBarHeight = res.getDimensionPixelSize(
- com.android.internal.R.dimen.status_bar_height);
- if (mStatusBarWindowController != null && mNaturalBarHeight != oldBarHeight) {
- mStatusBarWindowController.setBarHeight(mNaturalBarHeight);
- }
-
- if (DEBUG) Log.v(TAG, "defineSlots");
- }
-
// Visibility reporting
protected void handleVisibleToUserChanged(boolean visibleToUser) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarModule.java
new file mode 100644
index 000000000000..67f6a0ca6b72
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarModule.java
@@ -0,0 +1,230 @@
+/*
+ * 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.
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import static com.android.systemui.Dependency.ALLOW_NOTIFICATION_LONG_PRESS_NAME;
+
+import android.content.Context;
+import android.os.PowerManager;
+import android.util.DisplayMetrics;
+
+import androidx.annotation.Nullable;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.systemui.ForegroundServiceController;
+import com.android.systemui.UiOffloadThread;
+import com.android.systemui.appops.AppOpsController;
+import com.android.systemui.assist.AssistManager;
+import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.bubbles.BubbleController;
+import com.android.systemui.colorextraction.SysuiColorExtractor;
+import com.android.systemui.doze.DozeLog;
+import com.android.systemui.keyguard.KeyguardViewMediator;
+import com.android.systemui.keyguard.ScreenLifecycle;
+import com.android.systemui.keyguard.WakefulnessLifecycle;
+import com.android.systemui.plugins.FalsingManager;
+import com.android.systemui.shared.plugins.PluginManager;
+import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.FeatureFlags;
+import com.android.systemui.statusbar.NavigationBarController;
+import com.android.systemui.statusbar.NotificationListener;
+import com.android.systemui.statusbar.NotificationLockscreenUserManager;
+import com.android.systemui.statusbar.NotificationMediaManager;
+import com.android.systemui.statusbar.NotificationRemoteInputManager;
+import com.android.systemui.statusbar.NotificationViewHierarchyManager;
+import com.android.systemui.statusbar.PulseExpansionHandler;
+import com.android.systemui.statusbar.StatusBarDependenciesModule;
+import com.android.systemui.statusbar.SuperStatusBarViewFactory;
+import com.android.systemui.statusbar.SysuiStatusBarStateController;
+import com.android.systemui.statusbar.VibratorHelper;
+import com.android.systemui.statusbar.notification.BypassHeadsUpNotifier;
+import com.android.systemui.statusbar.notification.DynamicPrivacyController;
+import com.android.systemui.statusbar.notification.NewNotifPipeline;
+import com.android.systemui.statusbar.notification.NotificationAlertingManager;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
+import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
+import com.android.systemui.statusbar.notification.VisualStabilityManager;
+import com.android.systemui.statusbar.notification.logging.NotifLog;
+import com.android.systemui.statusbar.notification.logging.NotificationLogger;
+import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
+import com.android.systemui.statusbar.policy.BatteryController;
+import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.statusbar.policy.NetworkController;
+import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler;
+import com.android.systemui.statusbar.policy.RemoteInputUriController;
+import com.android.systemui.statusbar.policy.UserSwitcherController;
+import com.android.systemui.statusbar.policy.ZenModeController;
+
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import dagger.Lazy;
+import dagger.Module;
+import dagger.Provides;
+
+/**
+ * Dagger Module providing {@link StatusBar}.
+ */
+@Module(includes = {StatusBarDependenciesModule.class})
+public class StatusBarModule {
+ /**
+ * Provides our instance of StatusBar which is considered optional.
+ */
+ @Provides
+ @Singleton
+ static StatusBar provideStatusBar(
+ Context context,
+ FeatureFlags featureFlags,
+ LightBarController lightBarController,
+ AutoHideController autoHideController,
+ KeyguardUpdateMonitor keyguardUpdateMonitor,
+ StatusBarIconController statusBarIconController,
+ DozeLog dozeLog,
+ PulseExpansionHandler pulseExpansionHandler,
+ NotificationWakeUpCoordinator notificationWakeUpCoordinator,
+ KeyguardBypassController keyguardBypassController,
+ KeyguardStateController keyguardStateController,
+ HeadsUpManagerPhone headsUpManagerPhone,
+ DynamicPrivacyController dynamicPrivacyController,
+ BypassHeadsUpNotifier bypassHeadsUpNotifier,
+ @Named(ALLOW_NOTIFICATION_LONG_PRESS_NAME) boolean allowNotificationLongPress,
+ Lazy<NewNotifPipeline> newNotifPipeline,
+ FalsingManager falsingManager,
+ BroadcastDispatcher broadcastDispatcher,
+ RemoteInputQuickSettingsDisabler remoteInputQuickSettingsDisabler,
+ NotificationGutsManager notificationGutsManager,
+ NotificationLogger notificationLogger,
+ NotificationEntryManager notificationEntryManager,
+ NotificationInterruptionStateProvider notificationInterruptionStateProvider,
+ NotificationViewHierarchyManager notificationViewHierarchyManager,
+ ForegroundServiceController foregroundServiceController,
+ AppOpsController appOpsController,
+ KeyguardViewMediator keyguardViewMediator,
+ ZenModeController zenModeController,
+ NotificationAlertingManager notificationAlertingManager,
+ DisplayMetrics displayMetrics,
+ MetricsLogger metricsLogger,
+ UiOffloadThread uiOffloadThread,
+ NotificationMediaManager notificationMediaManager,
+ NotificationLockscreenUserManager lockScreenUserManager,
+ NotificationRemoteInputManager remoteInputManager,
+ UserSwitcherController userSwitcherController,
+ NetworkController networkController,
+ BatteryController batteryController,
+ SysuiColorExtractor colorExtractor,
+ ScreenLifecycle screenLifecycle,
+ WakefulnessLifecycle wakefulnessLifecycle,
+ SysuiStatusBarStateController statusBarStateController,
+ VibratorHelper vibratorHelper,
+ BubbleController bubbleController,
+ NotificationGroupManager groupManager,
+ NotificationGroupAlertTransferHelper groupAlertTransferHelper,
+ VisualStabilityManager visualStabilityManager,
+ DeviceProvisionedController deviceProvisionedController,
+ NavigationBarController navigationBarController,
+ AssistManager assistManager,
+ NotificationListener notificationListener,
+ ConfigurationController configurationController,
+ StatusBarWindowController statusBarWindowController,
+ StatusBarWindowViewController.Builder statusBarWindowViewControllerBuilder,
+ NotifLog notifLog,
+ DozeParameters dozeParameters,
+ ScrimController scrimController,
+ @Nullable KeyguardLiftController keyguardLiftController,
+ Lazy<LockscreenWallpaper> lockscreenWallpaperLazy,
+ Lazy<BiometricUnlockController> biometricUnlockControllerLazy,
+ DozeServiceHost dozeServiceHost,
+ PowerManager powerManager,
+ DozeScrimController dozeScrimController,
+ CommandQueue commandQueue,
+ PluginManager pluginManager,
+ RemoteInputUriController remoteInputUriController,
+ SuperStatusBarViewFactory superStatusBarViewFactory) {
+ return new StatusBar(
+ context,
+ featureFlags,
+ lightBarController,
+ autoHideController,
+ keyguardUpdateMonitor,
+ statusBarIconController,
+ dozeLog,
+ pulseExpansionHandler,
+ notificationWakeUpCoordinator,
+ keyguardBypassController,
+ keyguardStateController,
+ headsUpManagerPhone,
+ dynamicPrivacyController,
+ bypassHeadsUpNotifier,
+ allowNotificationLongPress,
+ newNotifPipeline,
+ falsingManager,
+ broadcastDispatcher,
+ remoteInputQuickSettingsDisabler,
+ notificationGutsManager,
+ notificationLogger,
+ notificationEntryManager,
+ notificationInterruptionStateProvider,
+ notificationViewHierarchyManager,
+ foregroundServiceController,
+ appOpsController,
+ keyguardViewMediator,
+ zenModeController,
+ notificationAlertingManager,
+ displayMetrics,
+ metricsLogger,
+ uiOffloadThread,
+ notificationMediaManager,
+ lockScreenUserManager,
+ remoteInputManager,
+ userSwitcherController,
+ networkController,
+ batteryController,
+ colorExtractor,
+ screenLifecycle,
+ wakefulnessLifecycle,
+ statusBarStateController,
+ vibratorHelper,
+ bubbleController,
+ groupManager,
+ groupAlertTransferHelper,
+ visualStabilityManager,
+ deviceProvisionedController,
+ navigationBarController,
+ assistManager,
+ notificationListener,
+ configurationController,
+ statusBarWindowController,
+ statusBarWindowViewControllerBuilder,
+ notifLog,
+ dozeParameters,
+ scrimController,
+ keyguardLiftController,
+ lockscreenWallpaperLazy,
+ biometricUnlockControllerLazy,
+ dozeServiceHost,
+ powerManager,
+ dozeScrimController,
+ commandQueue,
+ pluginManager,
+ remoteInputUriController,
+ superStatusBarViewFactory);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
index ca7a936d58f7..2ecceba2116a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
@@ -41,11 +41,13 @@ import android.view.WindowManager.LayoutParams;
import com.android.systemui.Dumpable;
import com.android.systemui.R;
import com.android.systemui.colorextraction.SysuiColorExtractor;
+import com.android.systemui.dagger.qualifiers.MainResources;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
import com.android.systemui.statusbar.RemoteInputController.Callback;
import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.SuperStatusBarViewFactory;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
@@ -69,6 +71,7 @@ import javax.inject.Singleton;
public class StatusBarWindowController implements Callback, Dumpable, ConfigurationListener {
private static final String TAG = "StatusBarWindowController";
+ private static final boolean DEBUG = false;
private final Context mContext;
private final WindowManager mWindowManager;
@@ -83,7 +86,7 @@ public class StatusBarWindowController implements Callback, Dumpable, Configurat
private LayoutParams mLp;
private boolean mHasTopUi;
private boolean mHasTopUiChanged;
- private int mBarHeight;
+ private int mBarHeight = -1;
private float mScreenBrightnessDoze;
private final State mCurrentState = new State();
private OtherwisedCollapsedListener mListener;
@@ -92,13 +95,17 @@ public class StatusBarWindowController implements Callback, Dumpable, Configurat
mCallbacks = Lists.newArrayList();
private final SysuiColorExtractor mColorExtractor;
+ private final SuperStatusBarViewFactory mSuperStatusBarViewFactory;
+ private final Resources mResources;
@Inject
public StatusBarWindowController(Context context, WindowManager windowManager,
IActivityManager activityManager, DozeParameters dozeParameters,
StatusBarStateController statusBarStateController,
ConfigurationController configurationController,
- KeyguardBypassController keyguardBypassController, SysuiColorExtractor colorExtractor) {
+ KeyguardBypassController keyguardBypassController, SysuiColorExtractor colorExtractor,
+ SuperStatusBarViewFactory superStatusBarViewFactory,
+ @MainResources Resources resources) {
mContext = context;
mWindowManager = windowManager;
mActivityManager = activityManager;
@@ -108,6 +115,15 @@ public class StatusBarWindowController implements Callback, Dumpable, Configurat
mLpChanged = new LayoutParams();
mKeyguardBypassController = keyguardBypassController;
mColorExtractor = colorExtractor;
+ mSuperStatusBarViewFactory = superStatusBarViewFactory;
+ mStatusBarView = mSuperStatusBarViewFactory.getStatusBarWindowView();
+ mResources = resources;
+
+ if (mBarHeight < 0) {
+ mBarHeight = mResources.getDimensionPixelSize(
+ com.android.internal.R.dimen.status_bar_height);
+ }
+
mLockScreenDisplayTimeout = context.getResources()
.getInteger(R.integer.config_lockScreenDisplayTimeout);
((SysuiStatusBarStateController) statusBarStateController)
@@ -149,20 +165,36 @@ public class StatusBarWindowController implements Callback, Dumpable, Configurat
|| res.getBoolean(R.bool.config_enableLockScreenRotation);
}
+ public int getStatusBarHeight() {
+ return mBarHeight;
+ }
+
/**
- * Adds the status bar view to the window manager.
- *
- * @param statusBarView The view to add.
- * @param barHeight The height of the status bar in collapsed state.
+ * Rereads the status_bar_height from configuration and reapplys the current state if the height
+ * is different.
*/
- public void add(ViewGroup statusBarView, int barHeight) {
+ public void refreshStatusBarHeight() {
+ int heightFromConfig = mResources.getDimensionPixelSize(
+ com.android.internal.R.dimen.status_bar_height);
+
+ if (mBarHeight != heightFromConfig) {
+ mBarHeight = heightFromConfig;
+ apply(mCurrentState);
+ }
+ if (DEBUG) Log.v(TAG, "defineSlots");
+ }
+
+ /**
+ * Adds the status bar view to the window manager.
+ */
+ public void attach() {
// Now that the status bar window encompasses the sliding panel and its
// translucent backdrop, the entire thing is made TRANSLUCENT and is
// hardware-accelerated.
mLp = new LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
- barHeight,
+ mBarHeight,
LayoutParams.TYPE_STATUS_BAR,
LayoutParams.FLAG_NOT_FOCUSABLE
| LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
@@ -176,8 +208,6 @@ public class StatusBarWindowController implements Callback, Dumpable, Configurat
mLp.setTitle("StatusBar");
mLp.packageName = mContext.getPackageName();
mLp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
- mStatusBarView = statusBarView;
- mBarHeight = barHeight;
mWindowManager.addView(mStatusBarView, mLp);
mLpChanged.copyFrom(mLp);
onThemeChanged();
@@ -534,11 +564,6 @@ public class StatusBarWindowController implements Callback, Dumpable, Configurat
apply(mCurrentState);
}
- public void setBarHeight(int barHeight) {
- mBarHeight = barHeight;
- apply(mCurrentState);
- }
-
public void setForcePluginOpen(boolean forcePluginOpen) {
mCurrentState.forcePluginOpen = forcePluginOpen;
apply(mCurrentState);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowViewController.java
index b7ada5d35a08..f716443cbfe1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowViewController.java
@@ -43,6 +43,7 @@ import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.DragDownHelper;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.PulseExpansionHandler;
+import com.android.systemui.statusbar.SuperStatusBarViewFactory;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
@@ -492,7 +493,8 @@ public class StatusBarWindowViewController {
private final DozeLog mDozeLog;
private final DozeParameters mDozeParameters;
private final CommandQueue mCommandQueue;
- private StatusBarWindowView mView;
+ private final SuperStatusBarViewFactory mSuperStatusBarViewFactory;
+ private final StatusBarWindowView mView;
@Inject
public Builder(
@@ -510,7 +512,8 @@ public class StatusBarWindowViewController {
StatusBarStateController statusBarStateController,
DozeLog dozeLog,
DozeParameters dozeParameters,
- CommandQueue commandQueue) {
+ CommandQueue commandQueue,
+ SuperStatusBarViewFactory superStatusBarViewFactory) {
mInjectionInflationController = injectionInflationController;
mCoordinator = coordinator;
mPulseExpansionHandler = pulseExpansionHandler;
@@ -526,14 +529,9 @@ public class StatusBarWindowViewController {
mDozeLog = dozeLog;
mDozeParameters = dozeParameters;
mCommandQueue = commandQueue;
- }
+ mSuperStatusBarViewFactory = superStatusBarViewFactory;
- /**
- * Provide {@link StatusBarWindowView} to attach this controller to.
- */
- public Builder setStatusBarWindowView(StatusBarWindowView view) {
- mView = view;
- return this;
+ mView = mSuperStatusBarViewFactory.getStatusBarWindowView();
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
index 5da726749580..bae51b6ebd9e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -48,6 +48,7 @@ import com.android.systemui.statusbar.policy.NetworkControllerImpl.SubscriptionD
import java.io.PrintWriter;
import java.util.BitSet;
+import java.util.concurrent.Executor;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -103,7 +104,7 @@ public class MobileSignalController extends SignalController<
mPhone = phone;
mDefaults = defaults;
mSubscriptionInfo = info;
- mPhoneStateListener = new MobilePhoneStateListener(receiverLooper);
+ mPhoneStateListener = new MobilePhoneStateListener((new Handler(receiverLooper))::post);
mNetworkNameSeparator = getStringIfExists(R.string.status_bar_network_name_separator);
mNetworkNameDefault = getStringIfExists(
com.android.internal.R.string.lockscreen_carrier_default);
@@ -665,8 +666,8 @@ public class MobileSignalController extends SignalController<
}
class MobilePhoneStateListener extends PhoneStateListener {
- public MobilePhoneStateListener(Looper looper) {
- super(looper);
+ public MobilePhoneStateListener(Executor executor) {
+ super(executor);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index e5898eded11e..12d357731560 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -282,7 +282,7 @@ public class NetworkControllerImpl extends BroadcastReceiver
// exclusively for status bar icons.
mConnectivityManager.registerDefaultNetworkCallback(callback, mReceiverHandler);
// Register the listener on our bg looper
- mPhoneStateListener = new PhoneStateListener(bgLooper) {
+ mPhoneStateListener = new PhoneStateListener(mReceiverHandler::post) {
@Override
public void onActiveDataSubscriptionIdChanged(int subId) {
mActiveMobileDataSubscription = subId;
@@ -649,7 +649,7 @@ public class NetworkControllerImpl extends BroadcastReceiver
}
private boolean hasAnySim() {
- int simCount = mPhone.getSimCount();
+ int simCount = mPhone.getActiveModemCount();
for (int i = 0; i < simCount; i++) {
int state = mPhone.getSimState(i);
if (state != TelephonyManager.SIM_STATE_ABSENT
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
index 65bb28ffbe39..949ac4df88ba 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
@@ -22,6 +22,7 @@ import android.text.TextPaint;
import android.text.method.TransformationMethod;
import android.util.AttributeSet;
import android.util.Log;
+import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -238,13 +239,15 @@ public class SmartReplyView extends ViewGroup {
public List<Button> inflateSmartActions(Context packageContext,
@NonNull SmartActions smartActions, SmartReplyController smartReplyController,
NotificationEntry entry, HeadsUpManager headsUpManager, boolean delayOnClickListener) {
+ Context themedPackageContext = new ContextThemeWrapper(packageContext, mContext.getTheme());
List<Button> buttons = new ArrayList<>();
int numSmartActions = smartActions.actions.size();
for (int n = 0; n < numSmartActions; n++) {
Notification.Action action = smartActions.actions.get(n);
if (action.actionIntent != null) {
buttons.add(inflateActionButton(
- this, getContext(), packageContext, n, smartActions, smartReplyController,
+ this, getContext(), themedPackageContext, n, smartActions,
+ smartReplyController,
entry, headsUpManager, delayOnClickListener));
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index 075c6d40ca31..13c0db938ca0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -463,8 +463,11 @@ public class UserSwitcherController implements Dumpable {
}
private void listenForCallState() {
- TelephonyManager.from(mContext).listen(mPhoneStateListener,
- PhoneStateListener.LISTEN_CALL_STATE);
+ final TelephonyManager tele =
+ (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
+ if (tele != null) {
+ tele.listen(mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
+ }
}
private final PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java
index 1dd48634615b..d8eaaa182722 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java
@@ -145,6 +145,7 @@ public class CarrierTextControllerTest extends SysuiTestCase {
mCarrierTextCallbackInfo = new CarrierTextController.CarrierTextCallbackInfo("",
new CharSequence[]{}, false, new int[]{});
when(mTelephonyManager.getSupportedModemCount()).thenReturn(3);
+ when(mTelephonyManager.getActiveModemCount()).thenReturn(3);
mCarrierTextController = new CarrierTextController(mContext, SEPARATOR, true, true);
// This should not start listening on any of the real dependencies but will test that
@@ -216,6 +217,15 @@ public class CarrierTextControllerTest extends SysuiTestCase {
// There's only one subscription in the list
assertEquals(1, captor.getValue().listOfCarriers.length);
assertEquals(TEST_CARRIER, captor.getValue().listOfCarriers[0]);
+
+ // Now it becomes single SIM active mode.
+ reset(mCarrierTextCallback);
+ when(mTelephonyManager.getActiveModemCount()).thenReturn(1);
+ // Update carrier text. It should ignore error state of subId 3 in inactive slotId.
+ mCarrierTextController.updateCarrierText();
+ mTestableLooper.processAllMessages();
+ verify(mCarrierTextCallback).updateCarrierInfo(captor.capture());
+ assertEquals("TEST_CARRIER", captor.getValue().carrierText);
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
index c215a43e0f3e..486fa12e0577 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
@@ -35,6 +35,7 @@ import android.app.ActivityManager;
import android.app.IActivityTaskManager;
import android.content.ComponentName;
import android.content.Context;
+import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.hardware.biometrics.Authenticator;
@@ -403,6 +404,19 @@ public class AuthControllerTest extends SysuiTestCase {
mAuthController.onDeviceCredentialPressed();
}
+ @Test
+ public void testActionCloseSystemDialogs_dismissesDialogIfShowing() throws Exception {
+ showDialog(Authenticator.TYPE_BIOMETRIC, BiometricPrompt.TYPE_FACE);
+ Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
+ mAuthController.mBroadcastReceiver.onReceive(mContext, intent);
+ waitForIdleSync();
+
+ assertNull(mAuthController.mCurrentDialog);
+ assertNull(mAuthController.mReceiver);
+ verify(mDialog1).dismissWithoutCallback(true /* animate */);
+ verify(mReceiver).onDialogDismissed(eq(BiometricPrompt.DISMISSED_REASON_USER_CANCEL));
+ }
+
// Helpers
private void showDialog(int authenticators, int biometricModality) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
index 00681130074b..b1a6bc6d41fd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
@@ -46,18 +46,19 @@ import android.app.Notification;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
+import android.content.res.Resources;
import android.graphics.drawable.Icon;
import android.hardware.face.FaceManager;
import android.service.notification.ZenModeConfig;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.view.WindowManager;
-import android.widget.FrameLayout;
import androidx.test.filters.SmallTest;
import com.android.internal.colorextraction.ColorExtractor;
import com.android.systemui.R;
+import com.android.systemui.SystemUIFactory;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -65,6 +66,7 @@ import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationPresenter;
import com.android.systemui.statusbar.NotificationRemoveInterceptor;
import com.android.systemui.statusbar.NotificationTestHelper;
+import com.android.systemui.statusbar.SuperStatusBarViewFactory;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.notification.NotificationEntryListener;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
@@ -81,6 +83,7 @@ import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.ZenModeController;
+import com.android.systemui.util.InjectionInflationController;
import org.junit.Before;
import org.junit.Test;
@@ -119,7 +122,6 @@ public class BubbleControllerTest extends SysuiTestCase {
@Mock
private KeyguardBypassController mKeyguardBypassController;
- private FrameLayout mStatusBarView;
@Captor
private ArgumentCaptor<NotificationEntryListener> mEntryListenerCaptor;
@Captor
@@ -147,22 +149,28 @@ public class BubbleControllerTest extends SysuiTestCase {
private SysuiColorExtractor mColorExtractor;
@Mock
ColorExtractor.GradientColors mGradientColors;
+ @Mock
+ private Resources mResources;
+ private SuperStatusBarViewFactory mSuperStatusBarViewFactory;
private BubbleData mBubbleData;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
- mStatusBarView = new FrameLayout(mContext);
mDependency.injectTestDependency(NotificationEntryManager.class, mNotificationEntryManager);
mContext.addMockSystemService(FaceManager.class, mFaceManager);
when(mColorExtractor.getNeutralColors()).thenReturn(mGradientColors);
+ mSuperStatusBarViewFactory = new SuperStatusBarViewFactory(mContext,
+ new InjectionInflationController(SystemUIFactory.getInstance().getRootComponent()));
+
// Bubbles get added to status bar window view
mStatusBarWindowController = new StatusBarWindowController(mContext, mWindowManager,
mActivityManager, mDozeParameters, mStatusBarStateController,
- mConfigurationController, mKeyguardBypassController, mColorExtractor);
- mStatusBarWindowController.add(mStatusBarView, 120 /* height */);
+ mConfigurationController, mKeyguardBypassController, mColorExtractor,
+ mSuperStatusBarViewFactory, mResources);
+ mStatusBarWindowController.attach();
// Need notifications for bubbles
mNotificationTestHelper = new NotificationTestHelper(mContext, mDependency);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/WorkLockActivityTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/WorkLockActivityTest.java
index 187c72a065a7..e4c387a26fd5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/WorkLockActivityTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/WorkLockActivityTest.java
@@ -19,7 +19,10 @@ package com.android.systemui.keyguard;
import static android.app.ActivityManager.TaskDescription;
import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.annotation.ColorInt;
@@ -36,7 +39,6 @@ import androidx.test.runner.AndroidJUnit4;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.broadcast.BroadcastDispatcher;
-import com.android.systemui.keyguard.WorkLockActivity;
import org.junit.Before;
import org.junit.Test;
@@ -112,4 +114,11 @@ public class WorkLockActivityTest extends SysuiTestCase {
.putExtra(Intent.EXTRA_USER_ID, USER_ID));
assertEquals(orgColor, mActivity.getPrimaryColor());
}
+
+ @Test
+ public void testUnregisteredFromDispatcher() {
+ mActivity.unregisterBroadcastReceiver();
+ verify(mBroadcastDispatcher).unregisterReceiver(any());
+ verify(mContext, never()).unregisterReceiver(any());
+ }
}
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 5e6c96313d36..d17c573515f5 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
@@ -226,7 +226,7 @@ public class ExpandableNotificationRowTest extends SysuiTestCase {
any(NotificationMenuRowPlugin.MenuItem.class));
reset(listener);
- mGroupRow.setDismissed(true);
+ mGroupRow.dismiss(true);
mGroupRow.doLongClickCallback(0,0);
verify(listener, times(0)).onLongPress(eq(mGroupRow), eq(0), eq(0),
any(NotificationMenuRowPlugin.MenuItem.class));
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index c21e3ab079ff..ecb2d8190cfc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -107,6 +107,7 @@ import com.android.systemui.statusbar.PulseExpansionHandler;
import com.android.systemui.statusbar.RemoteInputController;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.StatusBarStateControllerImpl;
+import com.android.systemui.statusbar.SuperStatusBarViewFactory;
import com.android.systemui.statusbar.VibratorHelper;
import com.android.systemui.statusbar.notification.BypassHeadsUpNotifier;
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
@@ -134,7 +135,6 @@ import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler;
import com.android.systemui.statusbar.policy.RemoteInputUriController;
import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.statusbar.policy.ZenModeController;
-import com.android.systemui.util.InjectionInflationController;
import org.junit.Before;
import org.junit.Test;
@@ -208,7 +208,6 @@ public class StatusBarTest extends SysuiTestCase {
@Mock private PulseExpansionHandler mPulseExpansionHandler;
@Mock private NotificationWakeUpCoordinator mNotificationWakeUpCoordinator;
@Mock private KeyguardBypassController mKeyguardBypassController;
- @Mock private InjectionInflationController mInjectionInflationController;
@Mock private DynamicPrivacyController mDynamicPrivacyController;
@Mock private NewNotifPipeline mNewNotifPipeline;
@Mock private ZenModeController mZenModeController;
@@ -234,6 +233,7 @@ public class StatusBarTest extends SysuiTestCase {
@Mock private KeyguardLiftController mKeyguardLiftController;
@Mock private CommandQueue mCommandQueue;
@Mock private PluginManager mPluginManager;
+ @Mock private SuperStatusBarViewFactory mSuperStatusBarViewFactory;
@Before
public void setup() throws Exception {
@@ -309,7 +309,6 @@ public class StatusBarTest extends SysuiTestCase {
mKeyguardUpdateMonitor,
mStatusBarIconController,
mDozeLog,
- mInjectionInflationController,
mPulseExpansionHandler,
mNotificationWakeUpCoordinator,
mKeyguardBypassController,
@@ -372,7 +371,8 @@ public class StatusBarTest extends SysuiTestCase {
mDozeScrimController,
mCommandQueue,
mPluginManager,
- mRemoteInputUriController);
+ mRemoteInputUriController,
+ mSuperStatusBarViewFactory);
when(mStatusBarWindowView.findViewById(R.id.lock_icon_container)).thenReturn(
mLockIconContainer);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowControllerTest.java
index a21a658348c4..147edf6589e9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowControllerTest.java
@@ -25,9 +25,9 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.IActivityManager;
+import android.content.res.Resources;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper.RunWithLooper;
-import android.view.ViewGroup;
import android.view.WindowManager;
import androidx.test.filters.SmallTest;
@@ -35,6 +35,7 @@ import androidx.test.filters.SmallTest;
import com.android.internal.colorextraction.ColorExtractor;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.colorextraction.SysuiColorExtractor;
+import com.android.systemui.statusbar.SuperStatusBarViewFactory;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.policy.ConfigurationController;
@@ -52,13 +53,15 @@ public class StatusBarWindowControllerTest extends SysuiTestCase {
@Mock private WindowManager mWindowManager;
@Mock private DozeParameters mDozeParameters;
- @Mock private ViewGroup mStatusBarView;
+ @Mock private StatusBarWindowView mStatusBarView;
@Mock private IActivityManager mActivityManager;
@Mock private SysuiStatusBarStateController mStatusBarStateController;
@Mock private ConfigurationController mConfigurationController;
@Mock private KeyguardBypassController mKeyguardBypassController;
@Mock private SysuiColorExtractor mColorExtractor;
@Mock ColorExtractor.GradientColors mGradientColors;
+ @Mock private SuperStatusBarViewFactory mSuperStatusBarViewFactory;
+ @Mock private Resources mResources;
private StatusBarWindowController mStatusBarWindowController;
@@ -67,11 +70,14 @@ public class StatusBarWindowControllerTest extends SysuiTestCase {
MockitoAnnotations.initMocks(this);
when(mDozeParameters.getAlwaysOn()).thenReturn(true);
when(mColorExtractor.getNeutralColors()).thenReturn(mGradientColors);
+ when(mSuperStatusBarViewFactory.getStatusBarWindowView()).thenReturn(mStatusBarView);
mStatusBarWindowController = new StatusBarWindowController(mContext, mWindowManager,
mActivityManager, mDozeParameters, mStatusBarStateController,
- mConfigurationController, mKeyguardBypassController, mColorExtractor);
- mStatusBarWindowController.add(mStatusBarView, 100 /* height */);
+ mConfigurationController, mKeyguardBypassController, mColorExtractor,
+ mSuperStatusBarViewFactory, mResources);
+
+ mStatusBarWindowController.attach();
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowViewTest.java
index 20fb6599f66e..bf81325eb6f8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowViewTest.java
@@ -35,6 +35,7 @@ import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.DragDownHelper;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.PulseExpansionHandler;
+import com.android.systemui.statusbar.SuperStatusBarViewFactory;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
@@ -72,6 +73,7 @@ public class StatusBarWindowViewTest extends SysuiTestCase {
@Mock private StatusBar mStatusBar;
@Mock private DozeLog mDozeLog;
@Mock private DozeParameters mDozeParameters;
+ @Mock private SuperStatusBarViewFactory mSuperStatusBarViewFactory;
@Before
public void setUp() {
@@ -82,6 +84,8 @@ public class StatusBarWindowViewTest extends SysuiTestCase {
when(mStatusBar.isDozing()).thenReturn(false);
mDependency.injectTestDependency(ShadeController.class, mShadeController);
+ when(mSuperStatusBarViewFactory.getStatusBarWindowView()).thenReturn(mView);
+
mController = new StatusBarWindowViewController.Builder(
new InjectionInflationController(
SystemUIFactory.getInstance().getRootComponent()),
@@ -98,9 +102,9 @@ public class StatusBarWindowViewTest extends SysuiTestCase {
mStatusBarStateController,
mDozeLog,
mDozeParameters,
- new CommandQueue(mContext))
+ new CommandQueue(mContext),
+ mSuperStatusBarViewFactory)
.setShadeController(mShadeController)
- .setStatusBarWindowView(mView)
.build();
mController.setService(mStatusBar);
mController.setDragDownHelper(mDragDownHelper);
diff --git a/packages/Tethering/Android.bp b/packages/Tethering/Android.bp
index 998572fc5679..61bfb92363bd 100644
--- a/packages/Tethering/Android.bp
+++ b/packages/Tethering/Android.bp
@@ -27,6 +27,7 @@ java_defaults {
"androidx.annotation_annotation",
"netd_aidl_interface-java",
"networkstack-aidl-interfaces-java",
+ "android.hardware.tetheroffload.control-V1.0-java",
"tethering-client",
],
manifest: "AndroidManifestBase.xml",
@@ -38,11 +39,39 @@ android_library {
defaults: ["TetheringAndroidLibraryDefaults"],
}
+cc_library_shared {
+ name: "libtetheroffloadjni",
+ srcs: [
+ "jni/com_android_server_connectivity_tethering_OffloadHardwareInterface.cpp",
+ ],
+ shared_libs: [
+ "libnativehelper",
+ "libcutils",
+ "android.hardware.tetheroffload.config@1.0",
+ ],
+ static_libs: [
+ "liblog",
+ "libbase",
+ "libhidlbase",
+ "libutils",
+ ],
+
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wno-unused-parameter",
+ "-Wthread-safety",
+ ],
+}
+
// Common defaults for compiling the actual APK.
java_defaults {
name: "TetheringAppDefaults",
platform_apis: true,
privileged: true,
+ jni_libs: [
+ "libtetheroffloadjni",
+ ],
resource_dirs: [
"res",
],
@@ -71,6 +100,8 @@ filegroup {
name: "tethering-servicescore-srcs",
srcs: [
"src/com/android/server/connectivity/tethering/EntitlementManager.java",
+ "src/com/android/server/connectivity/tethering/OffloadController.java",
+ "src/com/android/server/connectivity/tethering/OffloadHardwareInterface.java",
"src/com/android/server/connectivity/tethering/TetheringConfiguration.java",
"src/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java",
],
@@ -88,3 +119,11 @@ filegroup {
"src/android/net/util/PrefixUtils.java",
],
}
+
+// This group would be removed when tethering migration is done.
+filegroup {
+ name: "tethering-jni-srcs",
+ srcs: [
+ "jni/com_android_server_connectivity_tethering_OffloadHardwareInterface.cpp",
+ ],
+}
diff --git a/services/core/jni/com_android_server_connectivity_tethering_OffloadHardwareInterface.cpp b/packages/Tethering/jni/com_android_server_connectivity_tethering_OffloadHardwareInterface.cpp
index 3eaf48845a2f..3eaf48845a2f 100644
--- a/services/core/jni/com_android_server_connectivity_tethering_OffloadHardwareInterface.cpp
+++ b/packages/Tethering/jni/com_android_server_connectivity_tethering_OffloadHardwareInterface.cpp
diff --git a/services/core/java/com/android/server/connectivity/tethering/OffloadController.java b/packages/Tethering/src/com/android/server/connectivity/tethering/OffloadController.java
index a3c299814a7a..16734d83e3aa 100644
--- a/services/core/java/com/android/server/connectivity/tethering/OffloadController.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/OffloadController.java
@@ -36,8 +36,8 @@ import android.net.netlink.NetlinkSocket;
import android.net.util.IpUtils;
import android.net.util.SharedLog;
import android.os.Handler;
-import android.os.Looper;
import android.os.INetworkManagementService;
+import android.os.Looper;
import android.os.RemoteException;
import android.os.SystemClock;
import android.provider.Settings;
@@ -60,7 +60,6 @@ import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.TimeUnit;
/**
* A class to encapsulate the business logic of programming the tethering
@@ -74,7 +73,7 @@ public class OffloadController {
private static final String ANYIP = "0.0.0.0";
private static final ForwardedStats EMPTY_STATS = new ForwardedStats();
- private static enum UpdateType { IF_NEEDED, FORCE };
+ private enum UpdateType { IF_NEEDED, FORCE };
private final Handler mHandler;
private final OffloadHardwareInterface mHwInterface;
@@ -128,6 +127,7 @@ public class OffloadController {
}
}
+ /** Start hardware offload. */
public boolean start() {
if (started()) return true;
@@ -235,6 +235,7 @@ public class OffloadController {
return isStarted;
}
+ /** Stop hardware offload. */
public void stop() {
// Completely stops tethering offload. After this method is called, it is no longer safe to
// call any HAL method, no callbacks from the hardware will be delivered, and any in-flight
@@ -258,7 +259,9 @@ public class OffloadController {
// getTetherStats() is the only function in OffloadController that can be called from
// a different thread. Do not attempt to update stats by querying the offload HAL
// synchronously from a different thread than our Handler thread. http://b/64771555.
- Runnable updateStats = () -> { updateStatsForCurrentUpstream(); };
+ Runnable updateStats = () -> {
+ updateStatsForCurrentUpstream();
+ };
if (Looper.myLooper() == mHandler.getLooper()) {
updateStats.run();
} else {
@@ -358,6 +361,7 @@ public class OffloadController {
}
}
+ /** Set current tethering upstream LinkProperties. */
public void setUpstreamLinkProperties(LinkProperties lp) {
if (!started() || Objects.equals(mUpstreamLinkProperties, lp)) return;
@@ -376,6 +380,7 @@ public class OffloadController {
pushUpstreamParameters(prevUpstream);
}
+ /** Set local prefixes. */
public void setLocalPrefixes(Set<IpPrefix> localPrefixes) {
mExemptPrefixes = localPrefixes;
@@ -383,6 +388,7 @@ public class OffloadController {
computeAndPushLocalPrefixes(UpdateType.IF_NEEDED);
}
+ /** Update current downstream LinkProperties. */
public void notifyDownstreamLinkProperties(LinkProperties lp) {
final String ifname = lp.getInterfaceName();
final LinkProperties oldLp = mDownstreams.put(ifname, new LinkProperties(lp));
@@ -421,6 +427,7 @@ public class OffloadController {
}
}
+ /** Remove downstream interface from offload hardware. */
public void removeDownstreamInterface(String ifname) {
final LinkProperties lp = mDownstreams.remove(ifname);
if (lp == null) return;
@@ -481,7 +488,7 @@ public class OffloadController {
iface, v4addr, v4gateway, (v6gateways.isEmpty() ? null : v6gateways));
if (!success) {
- return success;
+ return success;
}
// Update stats after we've told the hardware to change routing so we don't miss packets.
@@ -545,6 +552,7 @@ public class OffloadController {
return false;
}
+ /** Dump information. */
public void dump(IndentingPrintWriter pw) {
if (isOffloadDisabled()) {
pw.println("Offload disabled");
@@ -630,7 +638,7 @@ public class OffloadController {
if (ip instanceof Inet4Address) {
return (Inet4Address) ip;
}
- } catch (IllegalArgumentException iae) {}
+ } catch (IllegalArgumentException iae) { }
return null;
}
diff --git a/services/core/java/com/android/server/connectivity/tethering/OffloadHardwareInterface.java b/packages/Tethering/src/com/android/server/connectivity/tethering/OffloadHardwareInterface.java
index 207f86762b95..01339a4a2c33 100644
--- a/services/core/java/com/android/server/connectivity/tethering/OffloadHardwareInterface.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/OffloadHardwareInterface.java
@@ -23,9 +23,9 @@ import android.hardware.tetheroffload.control.V1_0.ITetheringOffloadCallback;
import android.hardware.tetheroffload.control.V1_0.NatTimeoutUpdate;
import android.hardware.tetheroffload.control.V1_0.NetworkProtocol;
import android.hardware.tetheroffload.control.V1_0.OffloadCallbackEvent;
+import android.net.util.SharedLog;
import android.os.Handler;
import android.os.RemoteException;
-import android.net.util.SharedLog;
import android.system.OsConstants;
import java.util.ArrayList;
@@ -55,18 +55,34 @@ public class OffloadHardwareInterface {
private TetheringOffloadCallback mTetheringOffloadCallback;
private ControlCallback mControlCallback;
+ /** The callback to notify status of offload management process. */
public static class ControlCallback {
+ /** Offload started. */
public void onStarted() {}
+ /**
+ * Offload stopped because an error has occurred in lower layer.
+ */
public void onStoppedError() {}
+ /**
+ * Offload stopped because the device has moved to a bearer on which hardware offload is
+ * not supported. Subsequent calls to setUpstreamParameters and add/removeDownstream will
+ * likely fail and cannot be presumed to be saved inside of the hardware management process.
+ * Upon receiving #onSupportAvailable(), the caller should reprogram the hardware to begin
+ * offload again.
+ */
public void onStoppedUnsupported() {}
+ /** Indicate that offload is able to proivde support for this time. */
public void onSupportAvailable() {}
+ /** Offload stopped because of usage limit reached. */
public void onStoppedLimitReached() {}
+ /** Indicate to update NAT timeout. */
public void onNatTimeoutUpdate(int proto,
String srcAddr, int srcPort,
String dstAddr, int dstPort) {}
}
+ /** The object which records Tx/Rx forwarded bytes. */
public static class ForwardedStats {
public long rxBytes;
public long txBytes;
@@ -76,11 +92,13 @@ public class OffloadHardwareInterface {
txBytes = 0;
}
+ /** Add Tx/Rx bytes. */
public void add(ForwardedStats other) {
rxBytes += other.rxBytes;
txBytes += other.txBytes;
}
+ /** Returns the string representation of this object. */
public String toString() {
return String.format("rx:%s tx:%s", rxBytes, txBytes);
}
@@ -91,14 +109,17 @@ public class OffloadHardwareInterface {
mLog = log.forSubComponent(TAG);
}
+ /** Get default value indicating whether offload is supported. */
public int getDefaultTetherOffloadDisabled() {
return DEFAULT_TETHER_OFFLOAD_DISABLED;
}
+ /** Configure offload management process. */
public boolean initOffloadConfig() {
return configOffload();
}
+ /** Initialize the tethering offload HAL. */
public boolean initOffloadControl(ControlCallback controlCb) {
mControlCallback = controlCb;
@@ -125,8 +146,8 @@ public class OffloadHardwareInterface {
mOffloadControl.initOffload(
mTetheringOffloadCallback,
(boolean success, String errMsg) -> {
- results.success = success;
- results.errMsg = errMsg;
+ results.mSuccess = success;
+ results.mErrMsg = errMsg;
});
} catch (RemoteException e) {
record(logmsg, e);
@@ -134,9 +155,10 @@ public class OffloadHardwareInterface {
}
record(logmsg, results);
- return results.success;
+ return results.mSuccess;
}
+ /** Stop IOffloadControl. */
public void stopOffloadControl() {
if (mOffloadControl != null) {
try {
@@ -154,6 +176,7 @@ public class OffloadHardwareInterface {
mLog.log("stopOffloadControl()");
}
+ /** Get Tx/Rx usage from last query. */
public ForwardedStats getForwardedStats(String upstream) {
final String logmsg = String.format("getForwardedStats(%s)", upstream);
@@ -174,6 +197,7 @@ public class OffloadHardwareInterface {
return stats;
}
+ /** Set local prefixes to offload management process. */
public boolean setLocalPrefixes(ArrayList<String> localPrefixes) {
final String logmsg = String.format("setLocalPrefixes([%s])",
String.join(",", localPrefixes));
@@ -182,8 +206,8 @@ public class OffloadHardwareInterface {
try {
mOffloadControl.setLocalPrefixes(localPrefixes,
(boolean success, String errMsg) -> {
- results.success = success;
- results.errMsg = errMsg;
+ results.mSuccess = success;
+ results.mErrMsg = errMsg;
});
} catch (RemoteException e) {
record(logmsg, e);
@@ -191,9 +215,10 @@ public class OffloadHardwareInterface {
}
record(logmsg, results);
- return results.success;
+ return results.mSuccess;
}
+ /** Set data limit value to offload management process. */
public boolean setDataLimit(String iface, long limit) {
final String logmsg = String.format("setDataLimit(%s, %d)", iface, limit);
@@ -203,8 +228,8 @@ public class OffloadHardwareInterface {
mOffloadControl.setDataLimit(
iface, limit,
(boolean success, String errMsg) -> {
- results.success = success;
- results.errMsg = errMsg;
+ results.mSuccess = success;
+ results.mErrMsg = errMsg;
});
} catch (RemoteException e) {
record(logmsg, e);
@@ -212,9 +237,10 @@ public class OffloadHardwareInterface {
}
record(logmsg, results);
- return results.success;
+ return results.mSuccess;
}
+ /** Set upstream parameters to offload management process. */
public boolean setUpstreamParameters(
String iface, String v4addr, String v4gateway, ArrayList<String> v6gws) {
iface = (iface != null) ? iface : NO_INTERFACE_NAME;
@@ -230,8 +256,8 @@ public class OffloadHardwareInterface {
mOffloadControl.setUpstreamParameters(
iface, v4addr, v4gateway, v6gws,
(boolean success, String errMsg) -> {
- results.success = success;
- results.errMsg = errMsg;
+ results.mSuccess = success;
+ results.mErrMsg = errMsg;
});
} catch (RemoteException e) {
record(logmsg, e);
@@ -239,9 +265,10 @@ public class OffloadHardwareInterface {
}
record(logmsg, results);
- return results.success;
+ return results.mSuccess;
}
+ /** Add downstream prefix to offload management process. */
public boolean addDownstreamPrefix(String ifname, String prefix) {
final String logmsg = String.format("addDownstreamPrefix(%s, %s)", ifname, prefix);
@@ -249,8 +276,8 @@ public class OffloadHardwareInterface {
try {
mOffloadControl.addDownstream(ifname, prefix,
(boolean success, String errMsg) -> {
- results.success = success;
- results.errMsg = errMsg;
+ results.mSuccess = success;
+ results.mErrMsg = errMsg;
});
} catch (RemoteException e) {
record(logmsg, e);
@@ -258,9 +285,10 @@ public class OffloadHardwareInterface {
}
record(logmsg, results);
- return results.success;
+ return results.mSuccess;
}
+ /** Remove downstream prefix from offload management process. */
public boolean removeDownstreamPrefix(String ifname, String prefix) {
final String logmsg = String.format("removeDownstreamPrefix(%s, %s)", ifname, prefix);
@@ -268,8 +296,8 @@ public class OffloadHardwareInterface {
try {
mOffloadControl.removeDownstream(ifname, prefix,
(boolean success, String errMsg) -> {
- results.success = success;
- results.errMsg = errMsg;
+ results.mSuccess = success;
+ results.mErrMsg = errMsg;
});
} catch (RemoteException e) {
record(logmsg, e);
@@ -277,7 +305,7 @@ public class OffloadHardwareInterface {
}
record(logmsg, results);
- return results.success;
+ return results.mSuccess;
}
private void record(String msg, Throwable t) {
@@ -286,7 +314,7 @@ public class OffloadHardwareInterface {
private void record(String msg, CbResults results) {
final String logmsg = msg + YIELDS + results;
- if (!results.success) {
+ if (!results.mSuccess) {
mLog.e(logmsg);
} else {
mLog.log(logmsg);
@@ -298,7 +326,7 @@ public class OffloadHardwareInterface {
public final ControlCallback controlCb;
public final SharedLog log;
- public TetheringOffloadCallback(Handler h, ControlCallback cb, SharedLog sharedLog) {
+ TetheringOffloadCallback(Handler h, ControlCallback cb, SharedLog sharedLog) {
handler = h;
controlCb = cb;
log = sharedLog;
@@ -332,7 +360,7 @@ public class OffloadHardwareInterface {
@Override
public void updateTimeout(NatTimeoutUpdate params) {
handler.post(() -> {
- controlCb.onNatTimeoutUpdate(
+ controlCb.onNatTimeoutUpdate(
networkProtocolToOsConstant(params.proto),
params.src.addr, uint16(params.src.port),
params.dst.addr, uint16(params.dst.port));
@@ -352,15 +380,15 @@ public class OffloadHardwareInterface {
}
private static class CbResults {
- boolean success;
- String errMsg;
+ boolean mSuccess;
+ String mErrMsg;
@Override
public String toString() {
- if (success) {
+ if (mSuccess) {
return "ok";
} else {
- return "fail: " + errMsg;
+ return "fail: " + mErrMsg;
}
}
}
diff --git a/packages/Tethering/tests/unit/Android.bp b/packages/Tethering/tests/unit/Android.bp
index 7c06e5f0d7ce..363be18a73bc 100644
--- a/packages/Tethering/tests/unit/Android.bp
+++ b/packages/Tethering/tests/unit/Android.bp
@@ -25,6 +25,7 @@ android_test {
static_libs: [
"androidx.test.rules",
"frameworks-base-testutils",
+ "net-tests-utils",
"mockito-target-extended-minus-junit4",
"TetheringApiCurrentLib",
"testables",
@@ -46,6 +47,7 @@ filegroup {
name: "tethering-tests-src",
srcs: [
"src/com/android/server/connectivity/tethering/EntitlementManagerTest.java",
+ "src/com/android/server/connectivity/tethering/OffloadControllerTest.java",
"src/com/android/server/connectivity/tethering/TetheringConfigurationTest.java",
"src/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java",
"src/android/net/dhcp/DhcpServingParamsParcelExtTest.java",
diff --git a/tests/net/java/com/android/server/connectivity/tethering/OffloadControllerTest.java b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/OffloadControllerTest.java
index 9931aec01487..8574f5401496 100644
--- a/tests/net/java/com/android/server/connectivity/tethering/OffloadControllerTest.java
+++ b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/OffloadControllerTest.java
@@ -26,10 +26,10 @@ import static android.provider.Settings.Global.TETHER_OFFLOAD_DISABLED;
import static com.android.server.connectivity.tethering.OffloadHardwareInterface.ForwardedStats;
import static com.android.testutils.MiscAssertsKt.assertContainsAll;
+import static com.android.testutils.MiscAssertsKt.assertThrows;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.anyObject;
@@ -148,10 +148,8 @@ public class OffloadControllerTest {
public void testNoSettingsValueDefaultDisabledDoesNotStart() throws Exception {
setupFunctioningHardwareInterface();
when(mHardware.getDefaultTetherOffloadDisabled()).thenReturn(1);
- try {
- Settings.Global.getInt(mContentResolver, TETHER_OFFLOAD_DISABLED);
- fail();
- } catch (SettingNotFoundException expected) {}
+ assertThrows(SettingNotFoundException.class, () ->
+ Settings.Global.getInt(mContentResolver, TETHER_OFFLOAD_DISABLED));
final OffloadController offload = makeOffloadController();
offload.start();
@@ -168,10 +166,8 @@ public class OffloadControllerTest {
public void testNoSettingsValueDefaultEnabledDoesStart() throws Exception {
setupFunctioningHardwareInterface();
when(mHardware.getDefaultTetherOffloadDisabled()).thenReturn(0);
- try {
- Settings.Global.getInt(mContentResolver, TETHER_OFFLOAD_DISABLED);
- fail();
- } catch (SettingNotFoundException expected) {}
+ assertThrows(SettingNotFoundException.class, () ->
+ Settings.Global.getInt(mContentResolver, TETHER_OFFLOAD_DISABLED));
final OffloadController offload = makeOffloadController();
offload.start();
diff --git a/services/core/java/com/android/server/AlarmManagerInternal.java b/services/core/java/com/android/server/AlarmManagerInternal.java
index 5b0de5e2aae0..0a735029eead 100644
--- a/services/core/java/com/android/server/AlarmManagerInternal.java
+++ b/services/core/java/com/android/server/AlarmManagerInternal.java
@@ -16,6 +16,8 @@
package com.android.server;
+import android.app.PendingIntent;
+
public interface AlarmManagerInternal {
// Some other components in the system server need to know about
// broadcast alarms currently in flight
@@ -30,4 +32,10 @@ public interface AlarmManagerInternal {
boolean isIdling();
public void removeAlarmsForUid(int uid);
public void registerInFlightListener(InFlightListener callback);
+
+ /**
+ * Removes any alarm with the given pending intent with equality determined using
+ * {@link android.app.PendingIntent#equals(java.lang.Object) PendingIntent.equals}
+ */
+ void remove(PendingIntent rec);
}
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index e757b4e1a070..e4d477a03afc 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -213,7 +213,6 @@ class AlarmManagerService extends SystemService {
IAlarmListener mTimeTickTrigger;
PendingIntent mDateChangeSender;
Random mRandom;
- PendingIntent.CancelListener mOperationCancelListener;
boolean mInteractive = true;
long mNonInteractiveStartTime;
long mNonInteractiveTime;
@@ -1460,7 +1459,6 @@ class AlarmManagerService extends SystemService {
synchronized (mLock) {
mHandler = new AlarmHandler();
- mOperationCancelListener = (intent) -> removeImpl(intent, null);
mConstants = new Constants(mHandler);
mAppWakeupHistory = new AppWakeupHistory(Constants.DEFAULT_APP_STANDBY_WINDOW);
@@ -1715,9 +1713,6 @@ class AlarmManagerService extends SystemService {
} else {
maxElapsed = triggerElapsed + windowLength;
}
- if (operation != null) {
- operation.registerCancelListener(mOperationCancelListener);
- }
synchronized (mLock) {
if (DEBUG_BATCH) {
Slog.v(TAG, "set(" + operation + ") : type=" + type
@@ -1730,8 +1725,6 @@ class AlarmManagerService extends SystemService {
"Maximum limit of concurrent alarms " + mConstants.MAX_ALARMS_PER_UID
+ " reached for uid: " + UserHandle.formatUid(callingUid)
+ ", callingPackage: " + callingPackage;
- mHandler.obtainMessage(AlarmHandler.UNREGISTER_CANCEL_LISTENER,
- operation).sendToTarget();
Slog.w(TAG, errorMsg);
throw new IllegalStateException(errorMsg);
}
@@ -1752,8 +1745,6 @@ class AlarmManagerService extends SystemService {
if (ActivityManager.getService().isAppStartModeDisabled(callingUid, callingPackage)) {
Slog.w(TAG, "Not setting alarm from " + callingUid + ":" + a
+ " -- package not allowed to start");
- mHandler.obtainMessage(AlarmHandler.UNREGISTER_CANCEL_LISTENER,
- operation).sendToTarget();
return;
}
} catch (RemoteException e) {
@@ -1970,6 +1961,11 @@ class AlarmManagerService extends SystemService {
}
@Override
+ public void remove(PendingIntent pi) {
+ mHandler.obtainMessage(AlarmHandler.REMOVE_FOR_CANCELED, pi).sendToTarget();
+ }
+
+ @Override
public void registerInFlightListener(InFlightListener callback) {
synchronized (mLock) {
mInFlightListeners.add(callback);
@@ -2074,8 +2070,6 @@ class AlarmManagerService extends SystemService {
synchronized (mLock) {
removeLocked(operation, listener);
}
- mHandler.obtainMessage(AlarmHandler.UNREGISTER_CANCEL_LISTENER,
- operation).sendToTarget();
}
@Override
@@ -4078,7 +4072,7 @@ class AlarmManagerService extends SystemService {
public static final int APP_STANDBY_BUCKET_CHANGED = 5;
public static final int CHARGING_STATUS_CHANGED = 6;
public static final int REMOVE_FOR_STOPPED = 7;
- public static final int UNREGISTER_CANCEL_LISTENER = 8;
+ public static final int REMOVE_FOR_CANCELED = 8;
AlarmHandler() {
super(Looper.myLooper());
@@ -4161,10 +4155,10 @@ class AlarmManagerService extends SystemService {
}
break;
- case UNREGISTER_CANCEL_LISTENER:
- final PendingIntent pi = (PendingIntent) msg.obj;
- if (pi != null) {
- pi.unregisterCancelListener(mOperationCancelListener);
+ case REMOVE_FOR_CANCELED:
+ final PendingIntent operation = (PendingIntent) msg.obj;
+ synchronized (mLock) {
+ removeLocked(operation, null);
}
break;
@@ -4644,11 +4638,6 @@ class AlarmManagerService extends SystemService {
Intent.EXTRA_ALARM_COUNT, alarm.count),
mDeliveryTracker, mHandler, null,
allowWhileIdle ? mIdleOptions : null);
- if (alarm.repeatInterval == 0) {
- // Keep the listener for repeating alarms until they get cancelled
- mHandler.obtainMessage(AlarmHandler.UNREGISTER_CANCEL_LISTENER,
- alarm.operation).sendToTarget();
- }
} catch (PendingIntent.CanceledException e) {
if (alarm.repeatInterval > 0) {
// This IntentSender is no longer valid, but this
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index 39f039af330c..e1f65979bec3 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -43,7 +43,6 @@ import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.content.pm.Signature;
import android.content.res.Resources;
-import android.database.ContentObserver;
import android.hardware.location.ActivityRecognitionHardware;
import android.location.Address;
import android.location.Criteria;
@@ -79,7 +78,6 @@ import android.os.WorkSource.WorkChain;
import android.provider.Settings;
import android.stats.location.LocationStatsEnums;
import android.text.TextUtils;
-import android.util.ArraySet;
import android.util.EventLog;
import android.util.Log;
import android.util.Slog;
@@ -99,12 +97,12 @@ import com.android.server.location.CallerIdentity;
import com.android.server.location.GeocoderProxy;
import com.android.server.location.GeofenceManager;
import com.android.server.location.GeofenceProxy;
-import com.android.server.location.LocationBlacklist;
import com.android.server.location.LocationFudger;
import com.android.server.location.LocationProviderProxy;
import com.android.server.location.LocationRequestStatistics;
import com.android.server.location.LocationRequestStatistics.PackageProviderKey;
import com.android.server.location.LocationRequestStatistics.PackageStatistics;
+import com.android.server.location.LocationSettingsStore;
import com.android.server.location.MockProvider;
import com.android.server.location.PassiveProvider;
import com.android.server.pm.permission.PermissionManagerServiceInternal;
@@ -183,13 +181,6 @@ public class LocationManagerService extends ILocationManager.Stub {
private static final int FOREGROUND_IMPORTANCE_CUTOFF
= ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE;
- // default background throttling interval if not overriden in settings
- private static final long DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS = 30 * 60 * 1000;
-
- // Default value for maximum age of last location returned to applications with foreground-only
- // location permissions.
- private static final long DEFAULT_LAST_LOCATION_MAX_AGE_MS = 20 * 60 * 1000;
-
// Location Providers may sometimes deliver location updates
// slightly faster that requested - provide grace period so
// we don't unnecessarily filter events that are otherwise on
@@ -208,13 +199,14 @@ public class LocationManagerService extends ILocationManager.Stub {
private ActivityManager mActivityManager;
private UserManager mUserManager;
+ private LocationSettingsStore mSettingsStore;
+
private GeofenceManager mGeofenceManager;
private LocationFudger mLocationFudger;
private GeocoderProxy mGeocodeProvider;
@Nullable
private GnssManagerService mGnssManagerService;
private PassiveProvider mPassiveProvider; // track passive provider for special cases
- private LocationBlacklist mBlacklist;
@GuardedBy("mLock")
private String mExtraLocationControllerPackage;
private boolean mExtraLocationControllerPackageEnabled;
@@ -245,10 +237,6 @@ public class LocationManagerService extends ILocationManager.Stub {
private final HashMap<String, Location> mLastLocationCoarseInterval =
new HashMap<>();
- private final ArraySet<String> mBackgroundThrottlePackageWhitelist = new ArraySet<>();
-
- private final ArraySet<String> mIgnoreSettingsPackageWhitelist = new ArraySet<>();
-
// current active user on the device - other users are denied location data
private int mCurrentUserId = UserHandle.USER_SYSTEM;
private int[] mCurrentUserProfiles = new int[]{UserHandle.USER_SYSTEM};
@@ -287,16 +275,19 @@ public class LocationManagerService extends ILocationManager.Stub {
@GuardedBy("mLock")
private void initializeLocked() {
- mAppOps = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
mPackageManager = mContext.getPackageManager();
- mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
- mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
- mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+ mAppOps = mContext.getSystemService(AppOpsManager.class);
+ mPowerManager = mContext.getSystemService(PowerManager.class);
+ mActivityManager = mContext.getSystemService(ActivityManager.class);
+ mUserManager = mContext.getSystemService(UserManager.class);
+
+ mSettingsStore = new LocationSettingsStore(mContext, mHandler);
mLocationFudger = new LocationFudger(mContext, mHandler);
- mBlacklist = new LocationBlacklist(mContext, mHandler);
- mBlacklist.init();
- mGeofenceManager = new GeofenceManager(mContext, mBlacklist);
+ mGeofenceManager = new GeofenceManager(mContext, mSettingsStore);
+
+ PowerManagerInternal localPowerManager =
+ LocalServices.getService(PowerManagerInternal.class);
// prepare providers
initializeProvidersLocked();
@@ -327,7 +318,6 @@ public class LocationManagerService extends ILocationManager.Stub {
}
});
});
-
mActivityManager.addOnUidImportanceListener(
(uid, importance) -> {
// listener invoked on ui thread, move to our thread to reduce risk of blocking
@@ -339,63 +329,7 @@ public class LocationManagerService extends ILocationManager.Stub {
});
},
FOREGROUND_IMPORTANCE_CUTOFF);
- mContext.getContentResolver().registerContentObserver(
- Settings.Secure.getUriFor(Settings.Secure.LOCATION_MODE), true,
- new ContentObserver(mHandler) {
- @Override
- public void onChange(boolean selfChange) {
- synchronized (mLock) {
- onLocationModeChangedLocked(true);
- }
- }
- }, UserHandle.USER_ALL);
- mContext.getContentResolver().registerContentObserver(
- Settings.Secure.getUriFor(Settings.Secure.LOCATION_PROVIDERS_ALLOWED), true,
- new ContentObserver(mHandler) {
- @Override
- public void onChange(boolean selfChange) {
- synchronized (mLock) {
- onProviderAllowedChangedLocked();
- }
- }
- }, UserHandle.USER_ALL);
- mContext.getContentResolver().registerContentObserver(
- Settings.Global.getUriFor(Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS),
- true,
- new ContentObserver(mHandler) {
- @Override
- public void onChange(boolean selfChange) {
- synchronized (mLock) {
- onBackgroundThrottleIntervalChangedLocked();
- }
- }
- }, UserHandle.USER_ALL);
- mContext.getContentResolver().registerContentObserver(
- Settings.Global.getUriFor(
- Settings.Global.LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST),
- true,
- new ContentObserver(mHandler) {
- @Override
- public void onChange(boolean selfChange) {
- synchronized (mLock) {
- onBackgroundThrottleWhitelistChangedLocked();
- }
- }
- }, UserHandle.USER_ALL);
- mContext.getContentResolver().registerContentObserver(
- Settings.Global.getUriFor(
- Settings.Global.LOCATION_IGNORE_SETTINGS_PACKAGE_WHITELIST),
- true,
- new ContentObserver(mHandler) {
- @Override
- public void onChange(boolean selfChange) {
- synchronized (mLock) {
- onIgnoreSettingsWhitelistChangedLocked();
- }
- }
- }, UserHandle.USER_ALL);
- PowerManagerInternal localPowerManager =
- LocalServices.getService(PowerManagerInternal.class);
+
localPowerManager.registerLowPowerModeObserver(ServiceType.LOCATION,
state -> {
// listener invoked on ui thread, move to our thread to reduce risk of blocking
@@ -406,6 +340,33 @@ public class LocationManagerService extends ILocationManager.Stub {
}
});
});
+ mBatterySaverMode = mPowerManager.getLocationPowerSaveMode();
+
+ mSettingsStore.addOnLocationEnabledChangedListener(() -> {
+ synchronized (mLock) {
+ onLocationModeChangedLocked(true);
+ }
+ });
+ mSettingsStore.addOnLocationProvidersAllowedChangedListener(() -> {
+ synchronized (mLock) {
+ onProviderAllowedChangedLocked();
+ }
+ });
+ mSettingsStore.addOnBackgroundThrottleIntervalChangedListener(() -> {
+ synchronized (mLock) {
+ onBackgroundThrottleIntervalChangedLocked();
+ }
+ });
+ mSettingsStore.addOnBackgroundThrottlePackageWhitelistChangedListener(() -> {
+ synchronized (mLock) {
+ onBackgroundThrottleWhitelistChangedLocked();
+ }
+ });
+ mSettingsStore.addOnIgnoreSettingsPackageWhitelistChangedListener(() -> {
+ synchronized (mLock) {
+ onIgnoreSettingsWhitelistChangedLocked();
+ }
+ });
new PackageMonitor() {
@Override
@@ -453,11 +414,6 @@ public class LocationManagerService extends ILocationManager.Stub {
// provider initialization, and propagates changes until a steady state is reached
mCurrentUserId = UserHandle.USER_NULL;
onUserChangedLocked(ActivityManager.getCurrentUser());
-
- // initialize in-memory settings values
- onBackgroundThrottleWhitelistChangedLocked();
- onIgnoreSettingsWhitelistChangedLocked();
- onBatterySaverModeChangedLocked(mPowerManager.getLocationPowerSaveMode());
}
@GuardedBy("mLock")
@@ -479,6 +435,10 @@ public class LocationManagerService extends ILocationManager.Stub {
@GuardedBy("mLock")
private void onBatterySaverModeChangedLocked(int newLocationMode) {
+ if (mBatterySaverMode == newLocationMode) {
+ return;
+ }
+
if (D) {
Slog.d(TAG,
"Battery Saver location mode changed from "
@@ -486,11 +446,8 @@ public class LocationManagerService extends ILocationManager.Stub {
+ locationPowerSaveModeToString(newLocationMode));
}
- if (mBatterySaverMode == newLocationMode) {
- return;
- }
-
mBatterySaverMode = newLocationMode;
+
for (LocationProvider p : mProviders) {
applyRequirementsLocked(p);
}
@@ -588,17 +545,6 @@ public class LocationManagerService extends ILocationManager.Stub {
@GuardedBy("mLock")
private void onBackgroundThrottleWhitelistChangedLocked() {
- mBackgroundThrottlePackageWhitelist.clear();
- mBackgroundThrottlePackageWhitelist.addAll(
- SystemConfig.getInstance().getAllowUnthrottledLocation());
-
- String setting = Settings.Global.getString(
- mContext.getContentResolver(),
- Settings.Global.LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST);
- if (!TextUtils.isEmpty(setting)) {
- mBackgroundThrottlePackageWhitelist.addAll(Arrays.asList(setting.split(",")));
- }
-
for (LocationProvider p : mProviders) {
applyRequirementsLocked(p);
}
@@ -606,17 +552,6 @@ public class LocationManagerService extends ILocationManager.Stub {
@GuardedBy("lock")
private void onIgnoreSettingsWhitelistChangedLocked() {
- mIgnoreSettingsPackageWhitelist.clear();
- mIgnoreSettingsPackageWhitelist.addAll(
- SystemConfig.getInstance().getAllowIgnoreLocationSettings());
-
- String setting = Settings.Global.getString(
- mContext.getContentResolver(),
- Settings.Global.LOCATION_IGNORE_SETTINGS_PACKAGE_WHITELIST);
- if (!TextUtils.isEmpty(setting)) {
- mIgnoreSettingsPackageWhitelist.addAll(Arrays.asList(setting.split(",")));
- }
-
for (LocationProvider p : mProviders) {
applyRequirementsLocked(p);
}
@@ -859,8 +794,6 @@ public class LocationManagerService extends ILocationManager.Stub {
mCurrentUserId = userId;
onUserProfilesChangedLocked();
- mBlacklist.switchUser(userId);
-
// if the user changes, per-user settings may also have changed
onLocationModeChangedLocked(false);
onProviderAllowedChangedLocked();
@@ -1083,11 +1016,8 @@ public class LocationManagerService extends ILocationManager.Stub {
@GuardedBy("mLock")
public void onAllowedChangedLocked() {
if (mIsManagedBySettings) {
- String allowedProviders = Settings.Secure.getStringForUser(
- mContext.getContentResolver(),
- Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
- mCurrentUserId);
- boolean allowed = TextUtils.delimitedStringContains(allowedProviders, ',', mName);
+ boolean allowed = mSettingsStore.getLocationProvidersAllowed(
+ mCurrentUserId).contains(mName);
if (allowed == mAllowed) {
return;
@@ -1909,10 +1839,7 @@ public class LocationManagerService extends ILocationManager.Stub {
long identity = Binder.clearCallingIdentity();
try {
- backgroundThrottleInterval = Settings.Global.getLong(
- mContext.getContentResolver(),
- Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS,
- DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS);
+ backgroundThrottleInterval = mSettingsStore.getBackgroundThrottleIntervalMs();
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -2032,16 +1959,12 @@ public class LocationManagerService extends ILocationManager.Stub {
@Override
public String[] getBackgroundThrottlingWhitelist() {
- synchronized (mLock) {
- return mBackgroundThrottlePackageWhitelist.toArray(new String[0]);
- }
+ return mSettingsStore.getBackgroundThrottlePackageWhitelist().toArray(new String[0]);
}
@Override
public String[] getIgnoreSettingsWhitelist() {
- synchronized (mLock) {
- return mIgnoreSettingsPackageWhitelist.toArray(new String[0]);
- }
+ return mSettingsStore.getIgnoreSettingsPackageWhitelist().toArray(new String[0]);
}
@GuardedBy("mLock")
@@ -2050,7 +1973,8 @@ public class LocationManagerService extends ILocationManager.Stub {
return true;
}
- if (mBackgroundThrottlePackageWhitelist.contains(callerIdentity.mPackageName)) {
+ if (mSettingsStore.getBackgroundThrottlePackageWhitelist().contains(
+ callerIdentity.mPackageName)) {
return true;
}
@@ -2064,7 +1988,7 @@ public class LocationManagerService extends ILocationManager.Stub {
return false;
}
- if (mIgnoreSettingsPackageWhitelist.contains(
+ if (mSettingsStore.getIgnoreSettingsPackageWhitelist().contains(
record.mReceiver.mCallerIdentity.mPackageName)) {
return true;
}
@@ -2081,23 +2005,13 @@ public class LocationManagerService extends ILocationManager.Stub {
private boolean mIsForegroundUid;
private Location mLastFixBroadcast;
private Throwable mStackTrace; // for debugging only
+ private long mExpirationRealtimeMs;
/**
* Note: must be constructed with lock held.
*/
private UpdateRecord(String provider, LocationRequest request, Receiver receiver) {
- // translate expireIn value into expireAt
- long elapsedRealtime = SystemClock.elapsedRealtime();
- long expireAt;
- // Check for > Long.MAX_VALUE overflow (elapsedRealtime > 0):
- if (request.getExpireIn() > Long.MAX_VALUE - elapsedRealtime) {
- expireAt = Long.MAX_VALUE;
- } else {
- expireAt = Math.max(request.getExpireIn() + elapsedRealtime, 0);
- }
- request.setExpireAt(Math.min(request.getExpireAt(), expireAt));
- request.setExpireIn(Long.MAX_VALUE);
-
+ mExpirationRealtimeMs = request.getExpirationRealtimeMs(SystemClock.elapsedRealtime());
mProvider = provider;
mRealRequest = request;
mRequest = request;
@@ -2472,7 +2386,8 @@ public class LocationManagerService extends ILocationManager.Stub {
final int uid = Binder.getCallingUid();
final long identity = Binder.clearCallingIdentity();
try {
- if (mBlacklist.isBlacklisted(packageName)) {
+ if (mSettingsStore.isLocationPackageBlacklisted(UserHandle.getUserId(uid),
+ packageName)) {
if (D) {
Log.d(TAG, "not returning last loc for blacklisted app: "
+ packageName);
@@ -2513,10 +2428,7 @@ public class LocationManagerService extends ILocationManager.Stub {
String op = resolutionLevelToOpStr(allowedResolutionLevel);
long locationAgeMs = TimeUnit.NANOSECONDS.toMillis(
SystemClock.elapsedRealtime() - location.getElapsedRealtimeNanos());
- if ((locationAgeMs > Settings.Global.getLong(
- mContext.getContentResolver(),
- Settings.Global.LOCATION_LAST_LOCATION_MAX_AGE_MILLIS,
- DEFAULT_LAST_LOCATION_MAX_AGE_MS))
+ if (locationAgeMs > mSettingsStore.getMaxLastLocationAgeMs()
&& (mAppOps.unsafeCheckOp(op, uid, packageName)
== AppOpsManager.MODE_FOREGROUND)) {
return null;
@@ -2575,11 +2487,7 @@ public class LocationManagerService extends ILocationManager.Stub {
boolean foreground = LocationManagerServiceUtils.isImportanceForeground(
mActivityManager.getPackageImportance(packageName));
if (!foreground) {
- long backgroundThrottleIntervalMs = Settings.Global.getLong(
- mContext.getContentResolver(),
- Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS,
- DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS);
- if (locationAgeMs < backgroundThrottleIntervalMs) {
+ if (locationAgeMs < mSettingsStore.getBackgroundThrottleIntervalMs()) {
// not allowed to request new locations, so we can't return anything
return false;
}
@@ -2910,11 +2818,7 @@ public class LocationManagerService extends ILocationManager.Stub {
long identity = Binder.clearCallingIdentity();
try {
- return Settings.Secure.getIntForUser(
- mContext.getContentResolver(),
- Settings.Secure.LOCATION_MODE,
- Settings.Secure.LOCATION_MODE_OFF,
- userId) != Settings.Secure.LOCATION_MODE_OFF;
+ return mSettingsStore.isLocationEnabled(userId);
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -2969,7 +2873,7 @@ public class LocationManagerService extends ILocationManager.Stub {
}
// Check whether the expiry date has passed
- return record.mRealRequest.getExpireAt() >= now;
+ return record.mExpirationRealtimeMs >= now;
}
@GuardedBy("mLock")
@@ -3050,7 +2954,8 @@ public class LocationManagerService extends ILocationManager.Stub {
continue;
}
- if (mBlacklist.isBlacklisted(receiver.mCallerIdentity.mPackageName)) {
+ if (mSettingsStore.isLocationPackageBlacklisted(receiverUserId,
+ receiver.mCallerIdentity.mPackageName)) {
if (D) {
Log.d(TAG, "skipping loc update for blacklisted app: " +
receiver.mCallerIdentity.mPackageName);
@@ -3100,7 +3005,7 @@ public class LocationManagerService extends ILocationManager.Stub {
}
// track expired records
- if (r.mRealRequest.getNumUpdates() <= 0 || r.mRealRequest.getExpireAt() < now) {
+ if (r.mRealRequest.getNumUpdates() <= 0 || r.mExpirationRealtimeMs < now) {
// notify the client it can remove this listener
r.mReceiver.callRemovedLocked();
if (deadUpdateRecords == null) {
@@ -3392,33 +3297,11 @@ public class LocationManagerService extends ILocationManager.Stub {
ipw.decreaseIndent();
}
- if (mBlacklist != null) {
- mBlacklist.dump(ipw);
- }
-
if (mExtraLocationControllerPackage != null) {
ipw.println("Location Controller Extra Package: " + mExtraLocationControllerPackage
+ (mExtraLocationControllerPackageEnabled ? " [enabled]" : "[disabled]"));
}
- if (!mBackgroundThrottlePackageWhitelist.isEmpty()) {
- ipw.println("Throttling Whitelisted Packages:");
- ipw.increaseIndent();
- for (String packageName : mBackgroundThrottlePackageWhitelist) {
- ipw.println(packageName);
- }
- ipw.decreaseIndent();
- }
-
- if (!mIgnoreSettingsPackageWhitelist.isEmpty()) {
- ipw.println("Bypass Whitelisted Packages:");
- ipw.increaseIndent();
- for (String packageName : mIgnoreSettingsPackageWhitelist) {
- ipw.println(packageName);
- }
- ipw.decreaseIndent();
- }
-
if (mLocationFudger != null) {
ipw.println("Location Fudger:");
ipw.increaseIndent();
@@ -3426,6 +3309,8 @@ public class LocationManagerService extends ILocationManager.Stub {
ipw.decreaseIndent();
}
+ mSettingsStore.dump(fd, pw, args);
+
ipw.println("Location Providers:");
ipw.increaseIndent();
for (LocationProvider provider : mProviders) {
diff --git a/services/core/java/com/android/server/am/PendingIntentController.java b/services/core/java/com/android/server/am/PendingIntentController.java
index d75591cc7432..df76713d58a6 100644
--- a/services/core/java/com/android/server/am/PendingIntentController.java
+++ b/services/core/java/com/android/server/am/PendingIntentController.java
@@ -43,6 +43,7 @@ import android.util.Slog;
import com.android.internal.os.IResultReceiver;
import com.android.internal.util.function.pooled.PooledLambda;
+import com.android.server.AlarmManagerInternal;
import com.android.server.LocalServices;
import com.android.server.wm.ActivityTaskManagerInternal;
import com.android.server.wm.SafeActivityOptions;
@@ -293,6 +294,8 @@ public class PendingIntentController {
PendingIntentController::handlePendingIntentCancelled, this, callbacks);
mH.sendMessage(m);
}
+ final AlarmManagerInternal ami = LocalServices.getService(AlarmManagerInternal.class);
+ ami.remove(new PendingIntent(rec));
}
private void handlePendingIntentCancelled(RemoteCallbackList<IResultReceiver> callbacks) {
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index f2f1e0286a58..8be31a6e07c2 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -1323,7 +1323,7 @@ public final class ProcessList {
final int procCount = procs.size();
for (int i = 0; i < procCount; i++) {
final int procUid = procs.keyAt(i);
- if (UserHandle.isApp(procUid) || !UserHandle.isSameUser(procUid, uid)) {
+ if (!UserHandle.isCore(procUid) || !UserHandle.isSameUser(procUid, uid)) {
// Don't use an app process or different user process for system component.
continue;
}
diff --git a/services/core/java/com/android/server/attention/AttentionManagerService.java b/services/core/java/com/android/server/attention/AttentionManagerService.java
index 67d358910de1..232bc08e5b5c 100644
--- a/services/core/java/com/android/server/attention/AttentionManagerService.java
+++ b/services/core/java/com/android/server/attention/AttentionManagerService.java
@@ -21,6 +21,7 @@ import static android.service.attention.AttentionService.ATTENTION_FAILURE_CANCE
import static android.service.attention.AttentionService.ATTENTION_FAILURE_UNKNOWN;
import android.Manifest;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.attention.AttentionManagerInternal;
@@ -85,6 +86,10 @@ public class AttentionManagerService extends SystemService {
/** If the check attention called within that period - cached value will be returned. */
private static final long STALE_AFTER_MILLIS = 5_000;
+ /** The size of the buffer that stores recent attention check results. */
+ @VisibleForTesting
+ protected static final int ATTENTION_CACHE_BUFFER_SIZE = 5;
+
/** DeviceConfig flag name, if {@code true}, enables AttentionManagerService features. */
private static final String SERVICE_ENABLED = "service_enabled";
private static String sTestAttentionServicePackage;
@@ -192,7 +197,8 @@ public class AttentionManagerService extends SystemService {
userState.bindLocked();
// throttle frequent requests
- final AttentionCheckCache cache = userState.mAttentionCheckCache;
+ final AttentionCheckCache cache = userState.mAttentionCheckCacheBuffer == null ? null
+ : userState.mAttentionCheckCacheBuffer.getLast();
if (cache != null && now < cache.mLastComputed + STALE_AFTER_MILLIS) {
callbackInternal.onSuccess(cache.mResult, cache.mTimestamp);
return true;
@@ -236,9 +242,11 @@ public class AttentionManagerService extends SystemService {
}
synchronized (mLock) {
- userState.mAttentionCheckCache = new AttentionCheckCache(
- SystemClock.uptimeMillis(), result,
- timestamp);
+ if (userState.mAttentionCheckCacheBuffer == null) {
+ userState.mAttentionCheckCacheBuffer = new AttentionCheckCacheBuffer();
+ }
+ userState.mAttentionCheckCacheBuffer.add(
+ new AttentionCheckCache(SystemClock.uptimeMillis(), result, timestamp));
}
StatsLog.write(
StatsLog.ATTENTION_MANAGER_SERVICE_RESULT_REPORTED,
@@ -421,7 +429,41 @@ public class AttentionManagerService extends SystemService {
}
}
- private static final class AttentionCheckCache {
+ @VisibleForTesting
+ protected static final class AttentionCheckCacheBuffer {
+ private final AttentionCheckCache[] mQueue;
+ private int mStartIndex;
+ private int mSize;
+
+ AttentionCheckCacheBuffer() {
+ mQueue = new AttentionCheckCache[ATTENTION_CACHE_BUFFER_SIZE];
+ mStartIndex = 0;
+ mSize = 0;
+ }
+
+ public AttentionCheckCache getLast() {
+ int lastIdx = (mStartIndex + mSize - 1) % ATTENTION_CACHE_BUFFER_SIZE;
+ return mSize == 0 ? null : mQueue[lastIdx];
+ }
+
+ public void add(@NonNull AttentionCheckCache cache) {
+ int nextIndex = (mStartIndex + mSize) % ATTENTION_CACHE_BUFFER_SIZE;
+ mQueue[nextIndex] = cache;
+ if (mSize == ATTENTION_CACHE_BUFFER_SIZE) {
+ mStartIndex++;
+ } else {
+ mSize++;
+ }
+ }
+
+ public AttentionCheckCache get(int offset) {
+ return offset >= mSize ? null
+ : mQueue[(mStartIndex + offset) % ATTENTION_CACHE_BUFFER_SIZE];
+ }
+ }
+
+ @VisibleForTesting
+ protected static final class AttentionCheckCache {
private final long mLastComputed;
private final int mResult;
private final long mTimestamp;
@@ -463,7 +505,7 @@ public class AttentionManagerService extends SystemService {
@GuardedBy("mLock")
AttentionCheck mCurrentAttentionCheck;
@GuardedBy("mLock")
- AttentionCheckCache mAttentionCheckCache;
+ AttentionCheckCacheBuffer mAttentionCheckCacheBuffer;
@GuardedBy("mLock")
private boolean mBinding;
@@ -532,13 +574,14 @@ public class AttentionManagerService extends SystemService {
pw.println("is fulfilled:=" + mCurrentAttentionCheck.mIsFulfilled);
pw.decreaseIndent();
}
- pw.println("attention check cache:");
- if (mAttentionCheckCache != null) {
- pw.increaseIndent();
- pw.println("last computed=" + mAttentionCheckCache.mLastComputed);
- pw.println("timestamp=" + mAttentionCheckCache.mTimestamp);
- pw.println("result=" + mAttentionCheckCache.mResult);
- pw.decreaseIndent();
+ if (mAttentionCheckCacheBuffer != null) {
+ pw.println("attention check cache:");
+ for (int i = 0; i < mAttentionCheckCacheBuffer.mSize; i++) {
+ pw.increaseIndent();
+ pw.println("timestamp=" + mAttentionCheckCacheBuffer.get(i).mTimestamp);
+ pw.println("result=" + mAttentionCheckCacheBuffer.get(i).mResult);
+ pw.decreaseIndent();
+ }
}
}
}
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index e285bfdcdf4c..6355af6e0b2d 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -1583,12 +1583,13 @@ public class AudioService extends IAudioService.Stub
setMicrophoneMuteNoCallerCheck(currentUser);
}
- private int rescaleIndex(int index, int srcStream, int dstStream) {
- int srcRange =
- mStreamStates[srcStream].getMaxIndex() - mStreamStates[srcStream].getMinIndex();
- int dstRange =
- mStreamStates[dstStream].getMaxIndex() - mStreamStates[dstStream].getMinIndex();
+ private int getIndexRange(int streamType) {
+ return (mStreamStates[streamType].getMaxIndex() - mStreamStates[streamType].getMinIndex());
+ }
+ private int rescaleIndex(int index, int srcStream, int dstStream) {
+ int srcRange = getIndexRange(srcStream);
+ int dstRange = getIndexRange(dstStream);
if (srcRange == 0) {
Log.e(TAG, "rescaleIndex : index range should not be zero");
return mStreamStates[dstStream].getMinIndex();
@@ -1599,6 +1600,17 @@ public class AudioService extends IAudioService.Stub
/ srcRange;
}
+ private int rescaleStep(int step, int srcStream, int dstStream) {
+ int srcRange = getIndexRange(srcStream);
+ int dstRange = getIndexRange(dstStream);
+ if (srcRange == 0) {
+ Log.e(TAG, "rescaleStep : index range should not be zero");
+ return 0;
+ }
+
+ return ((step * dstRange + srcRange / 2) / srcRange);
+ }
+
///////////////////////////////////////////////////////////////////////////
// IPC methods
///////////////////////////////////////////////////////////////////////////
@@ -1775,7 +1787,7 @@ public class AudioService extends IAudioService.Stub
}
} else {
// convert one UI step (+/-1) into a number of internal units on the stream alias
- step = rescaleIndex(10, streamType, streamTypeAlias);
+ step = rescaleStep(10, streamType, streamTypeAlias);
}
// If either the client forces allowing ringer modes for this adjustment,
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 2c23c51216a8..67a23dd73854 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -496,8 +496,6 @@ public class InputManagerService extends IInputManager.Stub
}
InputChannel[] inputChannels = InputChannel.openInputChannelPair(inputChannelName);
- // Give the output channel a token just for identity purposes.
- inputChannels[0].setToken(new Binder());
nativeRegisterInputMonitor(mPtr, inputChannels[0], displayId, false /*isGestureMonitor*/);
inputChannels[0].dispose(); // don't need to retain the Java object reference
return inputChannels[1];
@@ -528,7 +526,6 @@ public class InputManagerService extends IInputManager.Stub
try {
InputChannel[] inputChannels = InputChannel.openInputChannelPair(inputChannelName);
InputMonitorHost host = new InputMonitorHost(inputChannels[0]);
- inputChannels[0].setToken(host.asBinder());
nativeRegisterInputMonitor(mPtr, inputChannels[0], displayId,
true /*isGestureMonitor*/);
return new InputMonitor(inputChannels[1], host);
@@ -547,7 +544,6 @@ public class InputManagerService extends IInputManager.Stub
if (inputChannel == null) {
throw new IllegalArgumentException("inputChannel must not be null.");
}
- inputChannel.setToken(new Binder());
nativeRegisterInputChannel(mPtr, inputChannel);
}
@@ -2188,7 +2184,7 @@ public class InputManagerService extends IInputManager.Stub
@Override
public void pilferPointers() {
- nativePilferPointers(mPtr, asBinder());
+ nativePilferPointers(mPtr, mInputChannel.getToken());
}
@Override
diff --git a/services/core/java/com/android/server/location/GeofenceManager.java b/services/core/java/com/android/server/location/GeofenceManager.java
index 17a21694e725..81c06d7125f9 100644
--- a/services/core/java/com/android/server/location/GeofenceManager.java
+++ b/services/core/java/com/android/server/location/GeofenceManager.java
@@ -18,12 +18,11 @@ package com.android.server.location;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.ActivityManager;
import android.app.AppOpsManager;
import android.app.PendingIntent;
-import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
-import android.database.ContentObserver;
import android.location.Geofence;
import android.location.Location;
import android.location.LocationListener;
@@ -31,13 +30,14 @@ import android.location.LocationManager;
import android.location.LocationRequest;
import android.os.Bundle;
import android.os.Handler;
+import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
import android.os.SystemClock;
-import android.os.UserHandle;
-import android.provider.Settings;
+import android.util.Log;
import android.util.Slog;
+import com.android.server.FgThread;
import com.android.server.LocationManagerService;
import com.android.server.PendingIntentUtils;
@@ -48,7 +48,7 @@ import java.util.List;
public class GeofenceManager implements LocationListener, PendingIntent.OnFinished {
private static final String TAG = "GeofenceManager";
- private static final boolean D = LocationManagerService.D;
+ private static final boolean D = Log.isLoggable(TAG, Log.DEBUG);
private static final int MSG_UPDATE_FENCES = 1;
@@ -64,10 +64,6 @@ public class GeofenceManager implements LocationListener, PendingIntent.OnFinish
*/
private static final long MAX_AGE_NANOS = 5 * 60 * 1000000000L; // five minutes
- /**
- * The default value of most frequent update interval allowed.
- */
- private static final long DEFAULT_MIN_INTERVAL_MS = 30 * 60 * 1000; // 30 minutes
/**
* Least frequent update interval allowed.
@@ -75,11 +71,13 @@ public class GeofenceManager implements LocationListener, PendingIntent.OnFinish
private static final long MAX_INTERVAL_MS = 2 * 60 * 60 * 1000; // two hours
private final Context mContext;
+ private final GeofenceHandler mHandler;
+
private final LocationManager mLocationManager;
private final AppOpsManager mAppOps;
private final PowerManager.WakeLock mWakeLock;
- private final GeofenceHandler mHandler;
- private final LocationBlacklist mBlacklist;
+
+ private final LocationSettingsStore mSettingsStore;
private final Object mLock = new Object();
@@ -113,43 +111,17 @@ public class GeofenceManager implements LocationListener, PendingIntent.OnFinish
*/
private boolean mPendingUpdate;
- /**
- * The actual value of most frequent update interval allowed.
- */
- private long mEffectiveMinIntervalMs;
- private ContentResolver mResolver;
-
- public GeofenceManager(Context context, LocationBlacklist blacklist) {
+ public GeofenceManager(Context context, LocationSettingsStore settingsStore) {
mContext = context;
- mLocationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
- mAppOps = (AppOpsManager)mContext.getSystemService(Context.APP_OPS_SERVICE);
- PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
- mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
- mHandler = new GeofenceHandler();
- mBlacklist = blacklist;
- mResolver = mContext.getContentResolver();
- updateMinInterval();
- mResolver.registerContentObserver(
- Settings.Global.getUriFor(
- Settings.Global.LOCATION_BACKGROUND_THROTTLE_PROXIMITY_ALERT_INTERVAL_MS),
- true,
- new ContentObserver(mHandler) {
- @Override
- public void onChange(boolean selfChange) {
- synchronized (mLock) {
- updateMinInterval();
- }
- }
- }, UserHandle.USER_ALL);
- }
+ mHandler = new GeofenceHandler(FgThread.getHandler().getLooper());
- /**
- * Updates the minimal location request frequency.
- */
- private void updateMinInterval() {
- mEffectiveMinIntervalMs = Settings.Global.getLong(mResolver,
- Settings.Global.LOCATION_BACKGROUND_THROTTLE_PROXIMITY_ALERT_INTERVAL_MS,
- DEFAULT_MIN_INTERVAL_MS);
+ mLocationManager = mContext.getSystemService(LocationManager.class);
+ mAppOps = mContext.getSystemService(AppOpsManager.class);
+
+ mWakeLock = mContext.getSystemService(PowerManager.class).newWakeLock(
+ PowerManager.PARTIAL_WAKE_LOCK, TAG);
+
+ mSettingsStore = settingsStore;
}
public void addFence(LocationRequest request, Geofence geofence, PendingIntent intent,
@@ -161,8 +133,8 @@ public class GeofenceManager implements LocationListener, PendingIntent.OnFinish
}
GeofenceState state = new GeofenceState(geofence,
- request.getExpireAt(), allowedResolutionLevel, uid, packageName, featureId,
- listenerIdentifier, intent);
+ request.getExpirationRealtimeMs(SystemClock.elapsedRealtime()),
+ allowedResolutionLevel, uid, packageName, featureId, listenerIdentifier, intent);
synchronized (mLock) {
// first make sure it doesn't already exist
for (int i = mFences.size() - 1; i >= 0; i--) {
@@ -294,7 +266,8 @@ public class GeofenceManager implements LocationListener, PendingIntent.OnFinish
double minFenceDistance = Double.MAX_VALUE;
boolean needUpdates = false;
for (GeofenceState state : mFences) {
- if (mBlacklist.isBlacklisted(state.mPackageName)) {
+ if (mSettingsStore.isLocationPackageBlacklisted(ActivityManager.getCurrentUser(),
+ state.mPackageName)) {
if (D) {
Slog.d(TAG, "skipping geofence processing for blacklisted app: "
+ state.mPackageName);
@@ -340,10 +313,11 @@ public class GeofenceManager implements LocationListener, PendingIntent.OnFinish
// Compute a location update interval based on the distance to the nearest fence.
long intervalMs;
if (location != null && Double.compare(minFenceDistance, Double.MAX_VALUE) != 0) {
- intervalMs = (long)Math.min(MAX_INTERVAL_MS, Math.max(mEffectiveMinIntervalMs,
+ intervalMs = (long) Math.min(MAX_INTERVAL_MS, Math.max(
+ mSettingsStore.getBackgroundThrottleProximityAlertIntervalMs(),
minFenceDistance * 1000 / MAX_SPEED_M_S));
} else {
- intervalMs = mEffectiveMinIntervalMs;
+ intervalMs = mSettingsStore.getBackgroundThrottleProximityAlertIntervalMs();
}
if (!mReceivingLocationUpdates || mLocationUpdateInterval != intervalMs) {
mReceivingLocationUpdates = true;
@@ -436,13 +410,16 @@ public class GeofenceManager implements LocationListener, PendingIntent.OnFinish
}
@Override
- public void onStatusChanged(String provider, int status, Bundle extras) { }
+ public void onStatusChanged(String provider, int status, Bundle extras) {
+ }
@Override
- public void onProviderEnabled(String provider) { }
+ public void onProviderEnabled(String provider) {
+ }
@Override
- public void onProviderDisabled(String provider) { }
+ public void onProviderDisabled(String provider) {
+ }
@Override
public void onSendFinished(PendingIntent pendingIntent, Intent intent, int resultCode,
@@ -457,17 +434,14 @@ public class GeofenceManager implements LocationListener, PendingIntent.OnFinish
}
private final class GeofenceHandler extends Handler {
- public GeofenceHandler() {
- super(true /*async*/);
+ private GeofenceHandler(Looper looper) {
+ super(looper);
}
@Override
public void handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_UPDATE_FENCES: {
- updateFences();
- break;
- }
+ if (msg.what == MSG_UPDATE_FENCES) {
+ updateFences();
}
}
}
diff --git a/services/core/java/com/android/server/location/LocationBlacklist.java b/services/core/java/com/android/server/location/LocationBlacklist.java
deleted file mode 100644
index 3f3f82871c0f..000000000000
--- a/services/core/java/com/android/server/location/LocationBlacklist.java
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-package com.android.server.location;
-
-import android.content.Context;
-import android.database.ContentObserver;
-import android.os.Handler;
-import android.os.UserHandle;
-import android.provider.Settings;
-import android.util.Log;
-import android.util.Slog;
-
-import com.android.server.LocationManagerService;
-
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.Arrays;
-
-/**
- * Allows applications to be blacklisted from location updates at run-time.
- *
- * This is a silent blacklist. Applications can still call Location Manager
- * API's, but they just won't receive any locations.
- */
-public final class LocationBlacklist extends ContentObserver {
- private static final String TAG = "LocationBlacklist";
- private static final boolean D = LocationManagerService.D;
- private static final String BLACKLIST_CONFIG_NAME = "locationPackagePrefixBlacklist";
- private static final String WHITELIST_CONFIG_NAME = "locationPackagePrefixWhitelist";
-
- private final Context mContext;
- private final Object mLock = new Object();
-
- // all fields below synchronized on mLock
- private String[] mWhitelist = new String[0];
- private String[] mBlacklist = new String[0];
-
- private int mCurrentUserId = UserHandle.USER_SYSTEM;
-
- public LocationBlacklist(Context context, Handler handler) {
- super(handler);
- mContext = context;
- }
-
- public void init() {
- mContext.getContentResolver().registerContentObserver(Settings.Secure.getUriFor(
- BLACKLIST_CONFIG_NAME), false, this, UserHandle.USER_ALL);
-// mContext.getContentResolver().registerContentObserver(Settings.Secure.getUriFor(
-// WHITELIST_CONFIG_NAME), false, this, UserHandle.USER_ALL);
- reloadBlacklist();
- }
-
- private void reloadBlacklistLocked() {
- mWhitelist = getStringArrayLocked(WHITELIST_CONFIG_NAME);
- if (D) Slog.d(TAG, "whitelist: " + Arrays.toString(mWhitelist));
- mBlacklist = getStringArrayLocked(BLACKLIST_CONFIG_NAME);
- if (D) Slog.d(TAG, "blacklist: " + Arrays.toString(mBlacklist));
- }
-
- private void reloadBlacklist() {
- synchronized (mLock) {
- reloadBlacklistLocked();
- }
- }
-
- /**
- * Return true if in blacklist
- * (package name matches blacklist, and does not match whitelist)
- */
- public boolean isBlacklisted(String packageName) {
- synchronized (mLock) {
- for (String black : mBlacklist) {
- if (packageName.startsWith(black)) {
- if (inWhitelist(packageName)) {
- continue;
- } else {
- if (D) Log.d(TAG, "dropping location (blacklisted): "
- + packageName + " matches " + black);
- return true;
- }
- }
- }
- }
- return false;
- }
-
- /**
- * Return true if any of packages are in whitelist
- */
- private boolean inWhitelist(String pkg) {
- synchronized (mLock) {
- for (String white : mWhitelist) {
- if (pkg.startsWith(white)) return true;
- }
- }
- return false;
- }
-
- @Override
- public void onChange(boolean selfChange) {
- reloadBlacklist();
- }
-
- public void switchUser(int userId) {
- synchronized(mLock) {
- mCurrentUserId = userId;
- reloadBlacklistLocked();
- }
- }
-
- private String[] getStringArrayLocked(String key) {
- String flatString;
- synchronized(mLock) {
- flatString = Settings.Secure.getStringForUser(mContext.getContentResolver(), key,
- mCurrentUserId);
- }
- if (flatString == null) {
- return new String[0];
- }
- String[] splitStrings = flatString.split(",");
- ArrayList<String> result = new ArrayList<String>();
- for (String pkg : splitStrings) {
- pkg = pkg.trim();
- if (pkg.isEmpty()) {
- continue;
- }
- result.add(pkg);
- }
- return result.toArray(new String[result.size()]);
- }
-
- public void dump(PrintWriter pw) {
- pw.println("mWhitelist=" + Arrays.toString(mWhitelist) + " mBlacklist=" +
- Arrays.toString(mBlacklist));
- }
-}
diff --git a/services/core/java/com/android/server/location/LocationSettingsStore.java b/services/core/java/com/android/server/location/LocationSettingsStore.java
new file mode 100644
index 000000000000..a4b6d97e9471
--- /dev/null
+++ b/services/core/java/com/android/server/location/LocationSettingsStore.java
@@ -0,0 +1,461 @@
+/*
+ * 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.
+ */
+
+package com.android.server.location;
+
+import static android.provider.Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS;
+import static android.provider.Settings.Global.LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST;
+import static android.provider.Settings.Global.LOCATION_BACKGROUND_THROTTLE_PROXIMITY_ALERT_INTERVAL_MS;
+import static android.provider.Settings.Global.LOCATION_IGNORE_SETTINGS_PACKAGE_WHITELIST;
+import static android.provider.Settings.Global.LOCATION_LAST_LOCATION_MAX_AGE_MILLIS;
+import static android.provider.Settings.Secure.LOCATION_MODE;
+import static android.provider.Settings.Secure.LOCATION_MODE_OFF;
+import static android.provider.Settings.Secure.LOCATION_PROVIDERS_ALLOWED;
+
+import android.app.ActivityManager;
+import android.content.Context;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.text.TextUtils;
+
+import com.android.internal.util.IndentingPrintWriter;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+/**
+ * Provides accessors and listeners for all location related settings.
+ */
+public class LocationSettingsStore {
+
+ private static final String LOCATION_PACKAGE_BLACKLIST = "locationPackagePrefixBlacklist";
+ private static final String LOCATION_PACKAGE_WHITELIST = "locationPackagePrefixWhitelist";
+
+ private static final long DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS = 30 * 60 * 1000;
+ private static final long DEFAULT_BACKGROUND_THROTTLE_PROXIMITY_ALERT_INTERVAL_MS =
+ 30 * 60 * 1000;
+ private static final long DEFAULT_MAX_LAST_LOCATION_AGE_MS = 20 * 60 * 1000;
+
+ private final Context mContext;
+
+ private final IntegerSecureSetting mLocationMode;
+ private final StringListCachedSecureSetting mLocationProvidersAllowed;
+ private final LongGlobalSetting mBackgroundThrottleIntervalMs;
+ private final StringListCachedSecureSetting mLocationPackageBlacklist;
+ private final StringListCachedSecureSetting mLocationPackageWhitelist;
+ private final StringListCachedGlobalSetting mBackgroundThrottlePackageWhitelist;
+ private final StringListCachedGlobalSetting mIgnoreSettingsPackageWhitelist;
+
+ public LocationSettingsStore(Context context, Handler handler) {
+ mContext = context;
+
+ mLocationMode = new IntegerSecureSetting(context, LOCATION_MODE, handler);
+ mLocationProvidersAllowed = new StringListCachedSecureSetting(context,
+ LOCATION_PROVIDERS_ALLOWED, handler);
+ mBackgroundThrottleIntervalMs = new LongGlobalSetting(context,
+ LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS, handler);
+ mLocationPackageBlacklist = new StringListCachedSecureSetting(context,
+ LOCATION_PACKAGE_BLACKLIST, handler);
+ mLocationPackageWhitelist = new StringListCachedSecureSetting(context,
+ LOCATION_PACKAGE_WHITELIST, handler);
+ mBackgroundThrottlePackageWhitelist = new StringListCachedGlobalSetting(context,
+ LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST, handler);
+ mIgnoreSettingsPackageWhitelist = new StringListCachedGlobalSetting(context,
+ LOCATION_IGNORE_SETTINGS_PACKAGE_WHITELIST, handler);
+ }
+
+ /**
+ * Retrieve if location is enabled or not.
+ */
+ public boolean isLocationEnabled(int userId) {
+ return mLocationMode.getValueForUser(LOCATION_MODE_OFF, userId) != LOCATION_MODE_OFF;
+ }
+
+ /**
+ * Add a listener for changes to the location enabled setting.
+ */
+ public void addOnLocationEnabledChangedListener(Runnable listener) {
+ mLocationMode.addListener(listener);
+ }
+
+ /**
+ * Remove a listener for changes to the location enabled setting.
+ */
+ public void removeOnLocationEnabledChangedListener(Runnable listener) {
+ mLocationMode.addListener(listener);
+ }
+
+ /**
+ * Retrieve the currently allowed location providers.
+ */
+ public List<String> getLocationProvidersAllowed(int userId) {
+ return mLocationProvidersAllowed.getValueForUser(userId);
+ }
+
+ /**
+ * Add a listener for changes to the currently allowed location providers.
+ */
+ public void addOnLocationProvidersAllowedChangedListener(Runnable runnable) {
+ mLocationProvidersAllowed.addListener(runnable);
+ }
+
+ /**
+ * Remove a listener for changes to the currently allowed location providers.
+ */
+ public void removeOnLocationProvidersAllowedChangedListener(Runnable runnable) {
+ mLocationProvidersAllowed.removeListener(runnable);
+ }
+
+ /**
+ * Retrieve the background throttle interval.
+ */
+ public long getBackgroundThrottleIntervalMs() {
+ return mBackgroundThrottleIntervalMs.getValue(DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS);
+ }
+
+ /**
+ * Add a listener for changes to the background throttle interval.
+ */
+ public void addOnBackgroundThrottleIntervalChangedListener(Runnable listener) {
+ mBackgroundThrottleIntervalMs.addListener(listener);
+ }
+
+ /**
+ * Remove a listener for changes to the background throttle interval.
+ */
+ public void removeOnBackgroundThrottleIntervalChangedListener(Runnable listener) {
+ mBackgroundThrottleIntervalMs.removeListener(listener);
+ }
+
+ /**
+ * Check if the given package is blacklisted for location access.
+ */
+ public boolean isLocationPackageBlacklisted(int userId, String packageName) {
+ List<String> locationPackageBlacklist = mLocationPackageBlacklist.getValueForUser(userId);
+ if (locationPackageBlacklist.isEmpty()) {
+ return false;
+ }
+
+ List<String> locationPackageWhitelist = mLocationPackageWhitelist.getValueForUser(userId);
+ for (String locationWhitelistPackage : locationPackageWhitelist) {
+ if (packageName.startsWith(locationWhitelistPackage)) {
+ return false;
+ }
+ }
+
+ for (String locationBlacklistPackage : locationPackageBlacklist) {
+ if (packageName.startsWith(locationBlacklistPackage)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Retrieve the background throttle package whitelist.
+ */
+ public List<String> getBackgroundThrottlePackageWhitelist() {
+ return mBackgroundThrottlePackageWhitelist.getValue();
+ }
+
+ /**
+ * Add a listener for changes to the background throttle package whitelist.
+ */
+ public void addOnBackgroundThrottlePackageWhitelistChangedListener(Runnable listener) {
+ mBackgroundThrottlePackageWhitelist.addListener(listener);
+ }
+
+ /**
+ * Remove a listener for changes to the background throttle package whitelist.
+ */
+ public void removeOnBackgroundThrottlePackageWhitelistChangedListener(Runnable listener) {
+ mBackgroundThrottlePackageWhitelist.removeListener(listener);
+ }
+
+ /**
+ * Retrieve the ignore settings package whitelist.
+ */
+ public List<String> getIgnoreSettingsPackageWhitelist() {
+ return mIgnoreSettingsPackageWhitelist.getValue();
+ }
+
+ /**
+ * Add a listener for changes to the ignore settings package whitelist.
+ */
+ public void addOnIgnoreSettingsPackageWhitelistChangedListener(Runnable listener) {
+ mIgnoreSettingsPackageWhitelist.addListener(listener);
+ }
+
+ /**
+ * Remove a listener for changes to the ignore settings package whitelist.
+ */
+ public void removeOnIgnoreSettingsPackageWhitelistChangedListener(Runnable listener) {
+ mIgnoreSettingsPackageWhitelist.removeListener(listener);
+ }
+
+ /**
+ * Retrieve the background throttling proximity alert interval.
+ */
+ public long getBackgroundThrottleProximityAlertIntervalMs() {
+ return Settings.Global.getLong(mContext.getContentResolver(),
+ LOCATION_BACKGROUND_THROTTLE_PROXIMITY_ALERT_INTERVAL_MS,
+ DEFAULT_BACKGROUND_THROTTLE_PROXIMITY_ALERT_INTERVAL_MS);
+ }
+
+ public long getMaxLastLocationAgeMs() {
+ return Settings.Global.getLong(
+ mContext.getContentResolver(),
+ LOCATION_LAST_LOCATION_MAX_AGE_MILLIS,
+ DEFAULT_MAX_LAST_LOCATION_AGE_MS);
+ }
+
+ /**
+ * Dump info for debugging.
+ */
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
+ int userId = ActivityManager.getCurrentUser();
+
+ ipw.println("--Location Settings--");
+ ipw.increaseIndent();
+
+ ipw.print("Location Enabled: ");
+ ipw.println(isLocationEnabled(userId));
+
+ ipw.print("Location Providers Allowed: ");
+ ipw.println(getLocationProvidersAllowed(userId));
+
+ List<String> locationPackageBlacklist = mLocationPackageBlacklist.getValueForUser(userId);
+ if (!locationPackageBlacklist.isEmpty()) {
+ ipw.println("Location Blacklisted Packages:");
+ ipw.increaseIndent();
+ for (String packageName : locationPackageBlacklist) {
+ ipw.println(packageName);
+ }
+ ipw.decreaseIndent();
+
+ List<String> locationPackageWhitelist = mLocationPackageWhitelist.getValueForUser(
+ userId);
+ if (!locationPackageWhitelist.isEmpty()) {
+ ipw.println("Location Whitelisted Packages:");
+ ipw.increaseIndent();
+ for (String packageName : locationPackageWhitelist) {
+ ipw.println(packageName);
+ }
+ ipw.decreaseIndent();
+ }
+ }
+
+ List<String> backgroundThrottlePackageWhitelist =
+ mBackgroundThrottlePackageWhitelist.getValue();
+ if (!backgroundThrottlePackageWhitelist.isEmpty()) {
+ ipw.println("Throttling Whitelisted Packages:");
+ ipw.increaseIndent();
+ for (String packageName : backgroundThrottlePackageWhitelist) {
+ ipw.println(packageName);
+ }
+ ipw.decreaseIndent();
+ }
+
+ List<String> ignoreSettingsPackageWhitelist = mIgnoreSettingsPackageWhitelist.getValue();
+ if (!ignoreSettingsPackageWhitelist.isEmpty()) {
+ ipw.println("Bypass Whitelisted Packages:");
+ ipw.increaseIndent();
+ for (String packageName : ignoreSettingsPackageWhitelist) {
+ ipw.println(packageName);
+ }
+ ipw.decreaseIndent();
+ }
+ }
+
+ private abstract static class ObservingSetting extends ContentObserver {
+
+ private final CopyOnWriteArrayList<Runnable> mListeners;
+
+ private ObservingSetting(Context context, String settingName, Handler handler) {
+ super(handler);
+ mListeners = new CopyOnWriteArrayList<>();
+
+ context.getContentResolver().registerContentObserver(
+ getUriFor(settingName), false, this, UserHandle.USER_ALL);
+ }
+
+ public void addListener(Runnable listener) {
+ mListeners.add(listener);
+ }
+
+ public void removeListener(Runnable listener) {
+ mListeners.remove(listener);
+ }
+
+ protected abstract Uri getUriFor(String settingName);
+
+ @Override
+ public void onChange(boolean selfChange, Uri uri, int userId) {
+ for (Runnable listener : mListeners) {
+ listener.run();
+ }
+ }
+ }
+
+ private static class IntegerSecureSetting extends ObservingSetting {
+
+ private final Context mContext;
+ private final String mSettingName;
+
+ private IntegerSecureSetting(Context context, String settingName, Handler handler) {
+ super(context, settingName, handler);
+ mContext = context;
+ mSettingName = settingName;
+ }
+
+ public int getValueForUser(int defaultValue, int userId) {
+ return Settings.Secure.getIntForUser(mContext.getContentResolver(), mSettingName,
+ defaultValue, userId);
+ }
+
+ @Override
+ protected Uri getUriFor(String settingName) {
+ return Settings.Secure.getUriFor(settingName);
+ }
+ }
+
+ private static class StringListCachedSecureSetting extends ObservingSetting {
+
+ private final Context mContext;
+ private final String mSettingName;
+
+ private int mCachedUserId = UserHandle.USER_NULL;
+ private List<String> mCachedValue;
+
+ private StringListCachedSecureSetting(Context context, String settingName,
+ Handler handler) {
+ super(context, settingName, handler);
+ mContext = context;
+ mSettingName = settingName;
+ }
+
+ public synchronized List<String> getValueForUser(int userId) {
+ if (userId != mCachedUserId) {
+ String setting = Settings.Secure.getStringForUser(mContext.getContentResolver(),
+ mSettingName, userId);
+ if (TextUtils.isEmpty(setting)) {
+ mCachedValue = Collections.emptyList();
+ } else {
+ mCachedValue = Arrays.asList(setting.split(","));
+ }
+ mCachedUserId = userId;
+ }
+
+ return mCachedValue;
+ }
+
+ public synchronized void invalidateForUser(int userId) {
+ if (mCachedUserId == userId) {
+ mCachedUserId = UserHandle.USER_NULL;
+ mCachedValue = null;
+ }
+ }
+
+ @Override
+ public void onChange(boolean selfChange, Uri uri, int userId) {
+ invalidateForUser(userId);
+ super.onChange(selfChange, uri, userId);
+ }
+
+ @Override
+ protected Uri getUriFor(String settingName) {
+ return Settings.Secure.getUriFor(settingName);
+ }
+ }
+
+ private static class LongGlobalSetting extends ObservingSetting {
+
+ private final Context mContext;
+ private final String mSettingName;
+
+ private LongGlobalSetting(Context context, String settingName, Handler handler) {
+ super(context, settingName, handler);
+ mContext = context;
+ mSettingName = settingName;
+ }
+
+ public long getValue(long defaultValue) {
+ return Settings.Global.getLong(mContext.getContentResolver(), mSettingName,
+ defaultValue);
+ }
+
+ @Override
+ protected Uri getUriFor(String settingName) {
+ return Settings.Global.getUriFor(settingName);
+ }
+ }
+
+ private static class StringListCachedGlobalSetting extends ObservingSetting {
+
+ private final Context mContext;
+ private final String mSettingName;
+
+ private boolean mValid;
+ private List<String> mCachedValue;
+
+ private StringListCachedGlobalSetting(Context context, String settingName,
+ Handler handler) {
+ super(context, settingName, handler);
+ mContext = context;
+ mSettingName = settingName;
+ }
+
+ public synchronized List<String> getValue() {
+ if (!mValid) {
+ String setting = Settings.Global.getString(mContext.getContentResolver(),
+ mSettingName);
+ if (TextUtils.isEmpty(setting)) {
+ mCachedValue = Collections.emptyList();
+ } else {
+ mCachedValue = Arrays.asList(setting.split(","));
+ }
+ mValid = true;
+ }
+
+ return mCachedValue;
+ }
+
+ public synchronized void invalidate() {
+ mValid = false;
+ mCachedValue = null;
+ }
+
+ @Override
+ public void onChange(boolean selfChange, Uri uri, int userId) {
+ invalidate();
+ super.onChange(selfChange, uri, userId);
+ }
+
+ @Override
+ protected Uri getUriFor(String settingName) {
+ return Settings.Global.getUriFor(settingName);
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index 193e0afc529e..c25e206d9104 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -1316,7 +1316,6 @@ public class MediaSessionService extends SystemService implements Monitor {
* pressed.
*
* @param packageName The caller's package name, obtained by Context#getPackageName()
- * @param opPackageName The caller's op package name, obtained by Context#getOpPackageName()
* @param sessionToken token for the session that the controller is pointing to
* @param keyEvent media key event
* @see #dispatchVolumeKeyEvent
@@ -1330,15 +1329,15 @@ public class MediaSessionService extends SystemService implements Monitor {
try {
synchronized (mLock) {
MediaSessionRecord record = getMediaSessionRecordLocked(sessionToken);
- if (record == null) {
- Log.w(TAG, "Failed to find session to dispatch key event.");
- return false;
- }
- if (DEBUG) {
+ if (DEBUG_KEY_EVENT) {
Log.d(TAG, "dispatchMediaKeyEventToSessionAsSystemService, pkg="
+ packageName + ", pid=" + pid + ", uid=" + uid + ", sessionToken="
+ sessionToken + ", event=" + keyEvent + ", session=" + record);
}
+ if (record == null) {
+ Log.w(TAG, "Failed to find session to dispatch key event.");
+ return false;
+ }
return record.sendMediaButton(packageName, pid, uid, true /* asSystemService */,
keyEvent, 0, null);
}
@@ -1688,6 +1687,12 @@ public class MediaSessionService extends SystemService implements Monitor {
try {
synchronized (mLock) {
MediaSessionRecord record = getMediaSessionRecordLocked(sessionToken);
+ if (DEBUG_KEY_EVENT) {
+ Log.d(TAG, "dispatchVolumeKeyEventToSessionAsSystemService, pkg="
+ + packageName + ", opPkg=" + opPackageName + ", pid=" + pid
+ + ", uid=" + uid + ", sessionToken=" + sessionToken + ", event="
+ + keyEvent + ", session=" + record);
+ }
if (record == null) {
Log.w(TAG, "Failed to find session to dispatch key event, token="
+ sessionToken + ". Fallbacks to the default handling.");
@@ -1695,12 +1700,6 @@ public class MediaSessionService extends SystemService implements Monitor {
keyEvent, AudioManager.USE_DEFAULT_STREAM_TYPE, false);
return;
}
- if (DEBUG) {
- Log.d(TAG, "dispatchVolumeKeyEventToSessionAsSystemService, pkg="
- + packageName + ", opPkg=" + opPackageName + ", pid=" + pid
- + ", uid=" + uid + ", sessionToken=" + sessionToken + ", event="
- + keyEvent + ", session=" + record);
- }
switch (keyEvent.getAction()) {
case KeyEvent.ACTION_DOWN: {
int direction = 0;
diff --git a/services/core/java/com/android/server/pm/AppsFilter.java b/services/core/java/com/android/server/pm/AppsFilter.java
index dc0cd184c188..5195a521dd17 100644
--- a/services/core/java/com/android/server/pm/AppsFilter.java
+++ b/services/core/java/com/android/server/pm/AppsFilter.java
@@ -211,7 +211,7 @@ public class AppsFilter {
final Uri data = intent.getData();
if ("content".equalsIgnoreCase(intent.getScheme())
&& data != null
- && providerInfo.authority.equalsIgnoreCase(data.getAuthority())) {
+ && Objects.equals(providerInfo.authority, data.getAuthority())) {
return true;
}
}
diff --git a/services/core/java/com/android/server/pm/UserSystemPackageInstaller.java b/services/core/java/com/android/server/pm/UserSystemPackageInstaller.java
index 91df33a8a16f..ef6b24cd198c 100644
--- a/services/core/java/com/android/server/pm/UserSystemPackageInstaller.java
+++ b/services/core/java/com/android/server/pm/UserSystemPackageInstaller.java
@@ -116,13 +116,13 @@ class UserSystemPackageInstaller {
* <p>Packages that are whitelisted, but then blacklisted so that they aren't to be installed on
* any user, are purposefully still present in this list.
*/
- private final ArrayMap<String, Integer> mWhitelitsedPackagesForUserTypes;
+ private final ArrayMap<String, Integer> mWhitelistedPackagesForUserTypes;
private final UserManagerService mUm;
UserSystemPackageInstaller(UserManagerService ums) {
mUm = ums;
- mWhitelitsedPackagesForUserTypes =
+ mWhitelistedPackagesForUserTypes =
determineWhitelistedPackagesForUserTypes(SystemConfig.getInstance());
}
@@ -130,7 +130,7 @@ class UserSystemPackageInstaller {
@VisibleForTesting
UserSystemPackageInstaller(UserManagerService ums, ArrayMap<String, Integer> whitelist) {
mUm = ums;
- mWhitelitsedPackagesForUserTypes = whitelist;
+ mWhitelistedPackagesForUserTypes = whitelist;
}
/**
@@ -249,7 +249,7 @@ class UserSystemPackageInstaller {
return (whitelistMode & USER_TYPE_PACKAGE_WHITELIST_MODE_IMPLICIT_WHITELIST) != 0;
}
- /** Gets the PackageWhitelistMode for use of {@link #mWhitelitsedPackagesForUserTypes}. */
+ /** Gets the PackageWhitelistMode for use of {@link #mWhitelistedPackagesForUserTypes}. */
private @PackageWhitelistMode int getWhitelistMode() {
final int runtimeMode = SystemProperties.getInt(
PACKAGE_WHITELIST_MODE_PROP, USER_TYPE_PACKAGE_WHITELIST_MODE_DEVICE_DEFAULT);
@@ -290,7 +290,7 @@ class UserSystemPackageInstaller {
if (!pkg.isSystem()) {
return;
}
- if (shouldInstallPackage(pkg, mWhitelitsedPackagesForUserTypes,
+ if (shouldInstallPackage(pkg, mWhitelistedPackagesForUserTypes,
whitelistedPackages, isImplicitWhitelistMode, isSystemUser)) {
// Although the whitelist uses manifest names, this function returns packageNames.
installPackages.add(pkg.packageName);
@@ -340,10 +340,10 @@ class UserSystemPackageInstaller {
*/
@VisibleForTesting
@NonNull Set<String> getWhitelistedPackagesForUserType(int flags) {
- Set<String> installablePkgs = new ArraySet<>(mWhitelitsedPackagesForUserTypes.size());
- for (int i = 0; i < mWhitelitsedPackagesForUserTypes.size(); i++) {
- String pkgName = mWhitelitsedPackagesForUserTypes.keyAt(i);
- int whitelistedUserTypes = mWhitelitsedPackagesForUserTypes.valueAt(i);
+ Set<String> installablePkgs = new ArraySet<>(mWhitelistedPackagesForUserTypes.size());
+ for (int i = 0; i < mWhitelistedPackagesForUserTypes.size(); i++) {
+ String pkgName = mWhitelistedPackagesForUserTypes.keyAt(i);
+ int whitelistedUserTypes = mWhitelistedPackagesForUserTypes.valueAt(i);
if ((flags & whitelistedUserTypes) != 0) {
installablePkgs.add(pkgName);
}
@@ -360,7 +360,7 @@ class UserSystemPackageInstaller {
* completely blacklists an AOSP app).
*/
private Set<String> getWhitelistedSystemPackages() {
- return mWhitelitsedPackagesForUserTypes.keySet();
+ return mWhitelistedPackagesForUserTypes.keySet();
}
/**
@@ -456,18 +456,28 @@ class UserSystemPackageInstaller {
}
void dump(PrintWriter pw) {
- pw.print("Whitelisted packages per user type");
- final int size = mWhitelitsedPackagesForUserTypes.size();
+ final String prefix = " ";
+ final int mode = getWhitelistMode();
+ pw.println("Whitelisted packages per user type");
+ pw.print(prefix); pw.print("Mode: ");
+ pw.print(mode);
+ pw.print(isEnforceMode(mode) ? " (enforced)" : "");
+ pw.print(isLogMode(mode) ? " (logged)" : "");
+ pw.print(isImplicitWhitelistMode(mode) ? " (implicit)" : "");
+ pw.println();
+
+ final int size = mWhitelistedPackagesForUserTypes.size();
if (size == 0) {
- pw.println(": N/A");
+ pw.print(prefix); pw.println("No packages");
return;
}
- pw.println(" (" + size + " packages)");
+ final String prefix2 = prefix + prefix;
+ pw.print(prefix); pw.print(size); pw.println(" packages:");
for (int i = 0; i < size; i++) {
- final String pkgName = mWhitelitsedPackagesForUserTypes.keyAt(i);
+ final String pkgName = mWhitelistedPackagesForUserTypes.keyAt(i);
final String whitelistedUserTypes =
- UserInfo.flagsToString(mWhitelitsedPackagesForUserTypes.valueAt(i));
- pw.println(" " + pkgName + ": " + whitelistedUserTypes);
+ UserInfo.flagsToString(mWhitelistedPackagesForUserTypes.valueAt(i));
+ pw.print(prefix2); pw.print(pkgName); pw.print(": "); pw.println(whitelistedUserTypes);
}
}
}
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
index ec64ee6d52de..b6934c9ce604 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
@@ -16,7 +16,6 @@
package com.android.server.statusbar;
-import android.graphics.Rect;
import android.os.Bundle;
import android.view.InsetsState.InternalInsetType;
import android.view.WindowInsetsController.Appearance;
@@ -79,9 +78,7 @@ public interface StatusBarManagerInternal {
void startAssist(Bundle args);
void onCameraLaunchGestureDetected(int source);
void topAppWindowChanged(int displayId, boolean isFullscreen, boolean isImmersive);
- void setSystemUiVisibility(int displayId, int vis, int fullscreenStackVis, int dockedStackVis,
- int mask, Rect fullscreenBounds, Rect dockedBounds, boolean isNavbarColorManagedByIme,
- String cause);
+ void setDisableFlags(int displayId, int flags, String cause);
void toggleSplitScreen();
void appTransitionFinished(int displayId);
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index effeb80298b8..25c41f5cdd6b 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -25,7 +25,6 @@ import android.app.Notification;
import android.app.StatusBarManager;
import android.content.ComponentName;
import android.content.Context;
-import android.graphics.Rect;
import android.hardware.biometrics.IBiometricServiceReceiverInternal;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManager.DisplayListener;
@@ -43,10 +42,11 @@ import android.os.UserHandle;
import android.service.notification.NotificationStats;
import android.text.TextUtils;
import android.util.ArrayMap;
-import android.util.Log;
+import android.util.ArraySet;
import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
+import android.view.InsetsState.InternalInsetType;
import android.view.WindowInsetsController.Appearance;
import com.android.internal.R;
@@ -263,12 +263,8 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D
}
@Override
- public void setSystemUiVisibility(int displayId, int vis, int fullscreenStackVis,
- int dockedStackVis, int mask, Rect fullscreenBounds, Rect dockedBounds,
- boolean isNavbarColorManagedByIme, String cause) {
- StatusBarManagerService.this.setSystemUiVisibility(displayId, vis, fullscreenStackVis,
- dockedStackVis, mask, fullscreenBounds, dockedBounds, isNavbarColorManagedByIme,
- cause);
+ public void setDisableFlags(int displayId, int flags, String cause) {
+ StatusBarManagerService.this.setDisableFlags(displayId, flags, cause);
}
@Override
@@ -473,7 +469,10 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D
@Override
public void onSystemBarAppearanceChanged(int displayId, @Appearance int appearance,
AppearanceRegion[] appearanceRegions, boolean navbarColorManagedByIme) {
- // TODO (b/118118435): save the information to UiState
+ final UiState state = getUiState(displayId);
+ if (!state.appearanceEquals(appearance, appearanceRegions, navbarColorManagedByIme)) {
+ state.setAppearance(appearance, appearanceRegions, navbarColorManagedByIme);
+ }
if (mBar != null) {
try {
mBar.onSystemBarAppearanceChanged(displayId, appearance, appearanceRegions,
@@ -483,7 +482,8 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D
}
@Override
- public void showTransient(int displayId, int[] types) {
+ public void showTransient(int displayId, @InternalInsetType int[] types) {
+ getUiState(displayId).showTransient(types);
if (mBar != null) {
try {
mBar.showTransient(displayId, types);
@@ -492,7 +492,8 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D
}
@Override
- public void abortTransient(int displayId, int[] types) {
+ public void abortTransient(int displayId, @InternalInsetType int[] types) {
+ getUiState(displayId).clearTransient(types);
if (mBar != null) {
try {
mBar.abortTransient(displayId, types);
@@ -896,54 +897,20 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D
}
}
- @Override
- public void setSystemUiVisibility(int displayId, int vis, int mask, String cause) {
- final UiState state = getUiState(displayId);
- setSystemUiVisibility(displayId, vis, 0, 0, mask,
- state.mFullscreenStackBounds, state.mDockedStackBounds,
- state.mNavbarColorManagedByIme, cause);
- }
-
- private void setSystemUiVisibility(int displayId, int vis, int fullscreenStackVis,
- int dockedStackVis, int mask, Rect fullscreenBounds, Rect dockedBounds,
- boolean isNavbarColorManagedByIme, String cause) {
+ private void setDisableFlags(int displayId, int flags, String cause) {
// also allows calls from window manager which is in this process.
enforceStatusBarService();
- if (SPEW) Slog.d(TAG, "setSystemUiVisibility(0x" + Integer.toHexString(vis) + ")");
-
- synchronized (mLock) {
- updateUiVisibilityLocked(displayId, vis, fullscreenStackVis, dockedStackVis, mask,
- fullscreenBounds, dockedBounds, isNavbarColorManagedByIme);
- disableLocked(
- displayId,
- mCurrentUserId,
- vis & StatusBarManager.DISABLE_MASK,
- mSysUiVisToken,
- cause, 1);
+ final int unknownFlags = flags & ~StatusBarManager.DISABLE_MASK;
+ if (unknownFlags != 0) {
+ Slog.e(TAG, "Unknown disable flags: 0x" + Integer.toHexString(unknownFlags),
+ new RuntimeException());
}
- }
- private void updateUiVisibilityLocked(final int displayId, final int vis,
- final int fullscreenStackVis, final int dockedStackVis, final int mask,
- final Rect fullscreenBounds, final Rect dockedBounds,
- final boolean isNavbarColorManagedByIme) {
- final UiState state = getUiState(displayId);
- if (!state.systemUiStateEquals(vis, fullscreenStackVis, dockedStackVis,
- fullscreenBounds, dockedBounds, isNavbarColorManagedByIme)) {
- state.setSystemUiState(vis, fullscreenStackVis, dockedStackVis, fullscreenBounds,
- dockedBounds, isNavbarColorManagedByIme);
- mHandler.post(() -> {
- if (mBar != null) {
- try {
- mBar.setSystemUiVisibility(displayId, vis, fullscreenStackVis,
- dockedStackVis, mask, fullscreenBounds, dockedBounds,
- isNavbarColorManagedByIme);
- } catch (RemoteException ex) {
- Log.w(TAG, "Can not get StatusBar!");
- }
- }
- });
+ if (SPEW) Slog.d(TAG, "setDisableFlags(0x" + Integer.toHexString(flags) + ")");
+
+ synchronized (mLock) {
+ disableLocked(displayId, mCurrentUserId, flags, mSysUiVisToken, cause, 1);
}
}
@@ -965,11 +932,10 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D
}
private class UiState {
- private int mSystemUiVisibility = 0;
- private int mFullscreenStackSysUiVisibility = 0;
- private int mDockedStackSysUiVisibility = 0;
- private final Rect mFullscreenStackBounds = new Rect();
- private final Rect mDockedStackBounds = new Rect();
+ private @Appearance int mAppearance = 0;
+ private AppearanceRegion[] mAppearanceRegions = new AppearanceRegion[0];
+ private ArraySet<Integer> mTransientBarTypes = new ArraySet<>();
+ private boolean mNavbarColorManagedByIme = false;
private boolean mFullscreen = false;
private boolean mImmersive = false;
private int mDisabled1 = 0;
@@ -978,53 +944,63 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D
private int mImeBackDisposition = 0;
private boolean mShowImeSwitcher = false;
private IBinder mImeToken = null;
- private boolean mNavbarColorManagedByIme = false;
- private int getDisabled1() {
- return mDisabled1;
+ private void setAppearance(@Appearance int appearance,
+ AppearanceRegion[] appearanceRegions, boolean navbarColorManagedByIme) {
+ mAppearance = appearance;
+ mAppearanceRegions = appearanceRegions;
+ mNavbarColorManagedByIme = navbarColorManagedByIme;
}
- private int getDisabled2() {
- return mDisabled2;
+ private boolean appearanceEquals(@Appearance int appearance,
+ AppearanceRegion[] appearanceRegions, boolean navbarColorManagedByIme) {
+ if (mAppearance != appearance || mAppearanceRegions.length != appearanceRegions.length
+ || mNavbarColorManagedByIme != navbarColorManagedByIme) {
+ return false;
+ }
+ for (int i = appearanceRegions.length - 1; i >= 0; i--) {
+ if (!mAppearanceRegions[i].equals(appearanceRegions[i])) {
+ return false;
+ }
+ }
+ return true;
}
- private void setDisabled(int disabled1, int disabled2) {
- mDisabled1 = disabled1;
- mDisabled2 = disabled2;
+ private void showTransient(@InternalInsetType int[] types) {
+ for (int type : types) {
+ mTransientBarTypes.add(type);
+ }
+ }
+
+ private void clearTransient(@InternalInsetType int[] types) {
+ for (int type : types) {
+ mTransientBarTypes.remove(type);
+ }
}
private void setFullscreen(boolean isFullscreen) {
mFullscreen = isFullscreen;
}
- private void setImmersive(boolean immersive) {
- mImmersive = immersive;
+ private void setImmersive(boolean isImmersive) {
+ mImmersive = isImmersive;
}
- private boolean disableEquals(int disabled1, int disabled2) {
- return mDisabled1 == disabled1 && mDisabled2 == disabled2;
+ private int getDisabled1() {
+ return mDisabled1;
}
- private void setSystemUiState(final int vis, final int fullscreenStackVis,
- final int dockedStackVis, final Rect fullscreenBounds, final Rect dockedBounds,
- final boolean navbarColorManagedByIme) {
- mSystemUiVisibility = vis;
- mFullscreenStackSysUiVisibility = fullscreenStackVis;
- mDockedStackSysUiVisibility = dockedStackVis;
- mFullscreenStackBounds.set(fullscreenBounds);
- mDockedStackBounds.set(dockedBounds);
- mNavbarColorManagedByIme = navbarColorManagedByIme;
+ private int getDisabled2() {
+ return mDisabled2;
}
- private boolean systemUiStateEquals(final int vis, final int fullscreenStackVis,
- final int dockedStackVis, final Rect fullscreenBounds, final Rect dockedBounds,
- final boolean navbarColorManagedByIme) {
- return mSystemUiVisibility == vis
- && mFullscreenStackSysUiVisibility == fullscreenStackVis
- && mDockedStackSysUiVisibility == dockedStackVis
- && mFullscreenStackBounds.equals(fullscreenBounds)
- && mDockedStackBounds.equals(dockedBounds)
- && mNavbarColorManagedByIme == navbarColorManagedByIme;
+ private void setDisabled(int disabled1, int disabled2) {
+ mDisabled1 = disabled1;
+ mDisabled2 = disabled2;
+ }
+
+ private boolean disableEquals(int disabled1, int disabled2) {
+ return mDisabled1 == disabled1 && mDisabled2 == disabled2;
}
private void setImeWindowState(final int vis, final int backDisposition,
@@ -1084,13 +1060,16 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D
// TODO(b/118592525): Currently, status bar only works on the default display.
// Make it aware of multi-display if needed.
final UiState state = mDisplayUiState.get(DEFAULT_DISPLAY);
+ final int[] transientBarTypes = new int[state.mTransientBarTypes.size()];
+ for (int i = 0; i < transientBarTypes.length; i++) {
+ transientBarTypes[i] = state.mTransientBarTypes.valueAt(i);
+ }
return new RegisterStatusBarResult(icons, gatherDisableActionsLocked(mCurrentUserId, 1),
- state.mSystemUiVisibility, state.mImeWindowVis,
+ state.mAppearance, state.mAppearanceRegions, state.mImeWindowVis,
state.mImeBackDisposition, state.mShowImeSwitcher,
- gatherDisableActionsLocked(mCurrentUserId, 2),
- state.mFullscreenStackSysUiVisibility, state.mDockedStackSysUiVisibility,
- state.mImeToken, state.mFullscreenStackBounds, state.mDockedStackBounds,
- state.mNavbarColorManagedByIme, state.mFullscreen, state.mImmersive);
+ gatherDisableActionsLocked(mCurrentUserId, 2), state.mImeToken,
+ state.mNavbarColorManagedByIme, state.mFullscreen, state.mImmersive,
+ transientBarTypes);
}
}
diff --git a/services/core/java/com/android/server/wallpaper/GLHelper.java b/services/core/java/com/android/server/wallpaper/GLHelper.java
new file mode 100644
index 000000000000..1d733f53f055
--- /dev/null
+++ b/services/core/java/com/android/server/wallpaper/GLHelper.java
@@ -0,0 +1,148 @@
+/*
+ * 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.
+ */
+
+package com.android.server.wallpaper;
+
+import static android.opengl.EGL14.EGL_ALPHA_SIZE;
+import static android.opengl.EGL14.EGL_BLUE_SIZE;
+import static android.opengl.EGL14.EGL_CONFIG_CAVEAT;
+import static android.opengl.EGL14.EGL_CONTEXT_CLIENT_VERSION;
+import static android.opengl.EGL14.EGL_DEFAULT_DISPLAY;
+import static android.opengl.EGL14.EGL_DEPTH_SIZE;
+import static android.opengl.EGL14.EGL_GREEN_SIZE;
+import static android.opengl.EGL14.EGL_HEIGHT;
+import static android.opengl.EGL14.EGL_NONE;
+import static android.opengl.EGL14.EGL_NO_CONTEXT;
+import static android.opengl.EGL14.EGL_NO_DISPLAY;
+import static android.opengl.EGL14.EGL_NO_SURFACE;
+import static android.opengl.EGL14.EGL_OPENGL_ES2_BIT;
+import static android.opengl.EGL14.EGL_RED_SIZE;
+import static android.opengl.EGL14.EGL_RENDERABLE_TYPE;
+import static android.opengl.EGL14.EGL_STENCIL_SIZE;
+import static android.opengl.EGL14.EGL_WIDTH;
+import static android.opengl.EGL14.eglChooseConfig;
+import static android.opengl.EGL14.eglCreateContext;
+import static android.opengl.EGL14.eglCreatePbufferSurface;
+import static android.opengl.EGL14.eglDestroyContext;
+import static android.opengl.EGL14.eglDestroySurface;
+import static android.opengl.EGL14.eglGetDisplay;
+import static android.opengl.EGL14.eglGetError;
+import static android.opengl.EGL14.eglInitialize;
+import static android.opengl.EGL14.eglMakeCurrent;
+import static android.opengl.EGL14.eglTerminate;
+import static android.opengl.GLES20.GL_MAX_TEXTURE_SIZE;
+import static android.opengl.GLES20.glGetIntegerv;
+
+import android.opengl.EGLConfig;
+import android.opengl.EGLContext;
+import android.opengl.EGLDisplay;
+import android.opengl.EGLSurface;
+import android.opengl.GLUtils;
+import android.os.SystemProperties;
+import android.util.Log;
+
+class GLHelper {
+ private static final String TAG = GLHelper.class.getSimpleName();
+ private static final int sMaxTextureSize;
+
+ static {
+ int maxTextureSize = SystemProperties.getInt("sys.max_texture_size", 0);
+ sMaxTextureSize = maxTextureSize > 0 ? maxTextureSize : retrieveTextureSizeFromGL();
+ }
+
+ private static int retrieveTextureSizeFromGL() {
+ try {
+ String err;
+
+ // Before we can retrieve info from GL,
+ // we have to create EGLContext, EGLConfig and EGLDisplay first.
+ // We will fail at querying info from GL once one of above failed.
+ // When this happens, we will use defValue instead.
+ EGLDisplay eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ if (eglDisplay == null || eglDisplay == EGL_NO_DISPLAY) {
+ err = "eglGetDisplay failed: " + GLUtils.getEGLErrorString(eglGetError());
+ throw new RuntimeException(err);
+ }
+
+ if (!eglInitialize(eglDisplay, null, 0 /* majorOffset */, null, 1 /* minorOffset */)) {
+ err = "eglInitialize failed: " + GLUtils.getEGLErrorString(eglGetError());
+ throw new RuntimeException(err);
+ }
+
+ EGLConfig eglConfig = null;
+ int[] configsCount = new int[1];
+ EGLConfig[] configs = new EGLConfig[1];
+ int[] configSpec = new int[] {
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+ EGL_RED_SIZE, 8,
+ EGL_GREEN_SIZE, 8,
+ EGL_BLUE_SIZE, 8,
+ EGL_ALPHA_SIZE, 0,
+ EGL_DEPTH_SIZE, 0,
+ EGL_STENCIL_SIZE, 0,
+ EGL_CONFIG_CAVEAT, EGL_NONE,
+ EGL_NONE
+ };
+
+ if (!eglChooseConfig(eglDisplay, configSpec, 0 /* attrib_listOffset */,
+ configs, 0 /* configOffset */, 1 /* config_size */,
+ configsCount, 0 /* num_configOffset */)) {
+ err = "eglChooseConfig failed: " + GLUtils.getEGLErrorString(eglGetError());
+ throw new RuntimeException(err);
+ } else if (configsCount[0] > 0) {
+ eglConfig = configs[0];
+ }
+
+ if (eglConfig == null) {
+ throw new RuntimeException("eglConfig not initialized!");
+ }
+
+ int[] attr_list = new int[] {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
+ EGLContext eglContext = eglCreateContext(
+ eglDisplay, eglConfig, EGL_NO_CONTEXT, attr_list, 0 /* offset */);
+
+ if (eglContext == null || eglContext == EGL_NO_CONTEXT) {
+ err = "eglCreateContext failed: " + GLUtils.getEGLErrorString(eglGetError());
+ throw new RuntimeException(err);
+ }
+
+ // We create a push buffer temporarily for querying info from GL.
+ int[] attrs = {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE};
+ EGLSurface eglSurface =
+ eglCreatePbufferSurface(eglDisplay, eglConfig, attrs, 0 /* offset */);
+ eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext);
+
+ // Now, we are ready to query the info from GL.
+ int[] maxSize = new int[1];
+ glGetIntegerv(GL_MAX_TEXTURE_SIZE, maxSize, 0 /* offset */);
+
+ // We have got the info we want, release all egl resources.
+ eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ eglDestroySurface(eglDisplay, eglSurface);
+ eglDestroyContext(eglDisplay, eglContext);
+ eglTerminate(eglDisplay);
+ return maxSize[0];
+ } catch (RuntimeException e) {
+ Log.w(TAG, "Retrieve from GL failed", e);
+ return Integer.MAX_VALUE;
+ }
+ }
+
+ static int getMaxTextureSize() {
+ return sMaxTextureSize;
+ }
+}
+
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index 3663f4696a27..3cc6428c792b 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -134,6 +134,9 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
private static final boolean DEBUG = false;
private static final boolean DEBUG_LIVE = true;
+ // This 100MB limitation is defined in RecordingCanvas.
+ private static final int MAX_BITMAP_SIZE = 100 * 1024 * 1024;
+
public static class Lifecycle extends SystemService {
private IWallpaperManagerService mService;
@@ -572,7 +575,9 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
// Only generate crop for default display.
final DisplayData wpData = getDisplayDataOrCreate(DEFAULT_DISPLAY);
- Rect cropHint = new Rect(wallpaper.cropHint);
+ final Rect cropHint = new Rect(wallpaper.cropHint);
+ final DisplayInfo displayInfo = new DisplayInfo();
+ mDisplayManager.getDisplay(DEFAULT_DISPLAY).getDisplayInfo(displayInfo);
if (DEBUG) {
Slog.v(TAG, "Generating crop for new wallpaper(s): 0x"
@@ -618,12 +623,12 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
}
// scale if the crop height winds up not matching the recommended metrics
- needScale = (wpData.mHeight != cropHint.height());
+ needScale = wpData.mHeight != cropHint.height()
+ || cropHint.height() > GLHelper.getMaxTextureSize()
+ || cropHint.width() > GLHelper.getMaxTextureSize();
//make sure screen aspect ratio is preserved if width is scaled under screen size
if (needScale) {
- final DisplayInfo displayInfo = new DisplayInfo();
- mDisplayManager.getDisplay(DEFAULT_DISPLAY).getDisplayInfo(displayInfo);
final float scaleByHeight = (float) wpData.mHeight / (float) cropHint.height();
final int newWidth = (int) (cropHint.width() * scaleByHeight);
if (newWidth < displayInfo.logicalWidth) {
@@ -644,14 +649,29 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
if (!needCrop && !needScale) {
// Simple case: the nominal crop fits what we want, so we take
// the whole thing and just copy the image file directly.
- if (DEBUG) {
- Slog.v(TAG, "Null crop of new wallpaper; copying");
+
+ // TODO: It is not accurate to estimate bitmap size without decoding it,
+ // may be we can try to remove this optimized way in the future,
+ // that means, we will always go into the 'else' block.
+
+ // This is just a quick estimation, may be smaller than it is.
+ long estimateSize = options.outWidth * options.outHeight * 4;
+
+ // A bitmap over than MAX_BITMAP_SIZE will make drawBitmap() fail.
+ // Please see: RecordingCanvas#throwIfCannotDraw.
+ if (estimateSize < MAX_BITMAP_SIZE) {
+ success = FileUtils.copyFile(wallpaper.wallpaperFile, wallpaper.cropFile);
}
- success = FileUtils.copyFile(wallpaper.wallpaperFile, wallpaper.cropFile);
+
if (!success) {
wallpaper.cropFile.delete();
// TODO: fall back to default wallpaper in this case
}
+
+ if (DEBUG) {
+ Slog.v(TAG, "Null crop of new wallpaper, estimate size="
+ + estimateSize + ", success=" + success);
+ }
} else {
// Fancy case: crop and scale. First, we decode and scale down if appropriate.
FileOutputStream f = null;
@@ -665,49 +685,78 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
// We calculate the largest power-of-two under the actual ratio rather than
// just let the decode take care of it because we also want to remap where the
// cropHint rectangle lies in the decoded [super]rect.
- final BitmapFactory.Options scaler;
final int actualScale = cropHint.height() / wpData.mHeight;
int scale = 1;
- while (2*scale < actualScale) {
+ while (2 * scale <= actualScale) {
scale *= 2;
}
- if (scale > 1) {
- scaler = new BitmapFactory.Options();
- scaler.inSampleSize = scale;
+ options.inSampleSize = scale;
+ options.inJustDecodeBounds = false;
+
+ final Rect estimateCrop = new Rect(cropHint);
+ estimateCrop.scale(1f / options.inSampleSize);
+ final float hRatio = (float) wpData.mHeight / estimateCrop.height();
+ final int destHeight = (int) (estimateCrop.height() * hRatio);
+ final int destWidth = (int) (estimateCrop.width() * hRatio);
+
+ // We estimated an invalid crop, try to adjust the cropHint to get a valid one.
+ if (destWidth > GLHelper.getMaxTextureSize()) {
+ int newHeight = (int) (wpData.mHeight / hRatio);
+ int newWidth = (int) (wpData.mWidth / hRatio);
+
if (DEBUG) {
- Slog.v(TAG, "Downsampling cropped rect with scale " + scale);
+ Slog.v(TAG, "Invalid crop dimensions, trying to adjust.");
}
- } else {
- scaler = null;
+
+ estimateCrop.set(cropHint);
+ estimateCrop.left += (cropHint.width() - newWidth) / 2;
+ estimateCrop.top += (cropHint.height() - newHeight) / 2;
+ estimateCrop.right = estimateCrop.left + newWidth;
+ estimateCrop.bottom = estimateCrop.top + newHeight;
+ cropHint.set(estimateCrop);
+ estimateCrop.scale(1f / options.inSampleSize);
+ }
+
+ // We've got the safe cropHint; now we want to scale it properly to
+ // the desired rectangle.
+ // That's a height-biased operation: make it fit the hinted height.
+ final int safeHeight = (int) (estimateCrop.height() * hRatio);
+ final int safeWidth = (int) (estimateCrop.width() * hRatio);
+
+ if (DEBUG) {
+ Slog.v(TAG, "Decode parameters:");
+ Slog.v(TAG, " cropHint=" + cropHint + ", estimateCrop=" + estimateCrop);
+ Slog.v(TAG, " down sampling=" + options.inSampleSize
+ + ", hRatio=" + hRatio);
+ Slog.v(TAG, " dest=" + destWidth + "x" + destHeight);
+ Slog.v(TAG, " safe=" + safeWidth + "x" + safeHeight);
+ Slog.v(TAG, " maxTextureSize=" + GLHelper.getMaxTextureSize());
}
- Bitmap cropped = decoder.decodeRegion(cropHint, scaler);
+
+ Bitmap cropped = decoder.decodeRegion(cropHint, options);
decoder.recycle();
if (cropped == null) {
Slog.e(TAG, "Could not decode new wallpaper");
} else {
- // We've got the extracted crop; now we want to scale it properly to
- // the desired rectangle. That's a height-biased operation: make it
- // fit the hinted height, and accept whatever width we end up with.
- cropHint.offsetTo(0, 0);
- cropHint.right /= scale; // adjust by downsampling factor
- cropHint.bottom /= scale;
- final float heightR =
- ((float) wpData.mHeight) / ((float) cropHint.height());
- if (DEBUG) {
- Slog.v(TAG, "scale " + heightR + ", extracting " + cropHint);
- }
- final int destWidth = (int)(cropHint.width() * heightR);
+ // We are safe to create final crop with safe dimensions now.
final Bitmap finalCrop = Bitmap.createScaledBitmap(cropped,
- destWidth, wpData.mHeight, true);
+ safeWidth, safeHeight, true);
if (DEBUG) {
Slog.v(TAG, "Final extract:");
Slog.v(TAG, " dims: w=" + wpData.mWidth
+ " h=" + wpData.mHeight);
- Slog.v(TAG, " out: w=" + finalCrop.getWidth()
+ Slog.v(TAG, " out: w=" + finalCrop.getWidth()
+ " h=" + finalCrop.getHeight());
}
+ // A bitmap over than MAX_BITMAP_SIZE will make drawBitmap() fail.
+ // Please see: RecordingCanvas#throwIfCannotDraw.
+ if (finalCrop.getByteCount() > MAX_BITMAP_SIZE) {
+ throw new RuntimeException(
+ "Too large bitmap, limit=" + MAX_BITMAP_SIZE);
+ }
+
f = new FileOutputStream(wallpaper.cropFile);
bos = new BufferedOutputStream(f, 32*1024);
finalCrop.compress(Bitmap.CompressFormat.JPEG, 100, bos);
@@ -1997,6 +2046,11 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
if (!isWallpaperSupported(callingPackage)) {
return;
}
+
+ // Make sure both width and height are not larger than max texture size.
+ width = Math.min(width, GLHelper.getMaxTextureSize());
+ height = Math.min(height, GLHelper.getMaxTextureSize());
+
synchronized (mLock) {
int userId = UserHandle.getCallingUserId();
WallpaperData wallpaper = getWallpaperSafeLocked(userId, FLAG_SYSTEM);
diff --git a/services/core/java/com/android/server/wm/ActivityDisplay.java b/services/core/java/com/android/server/wm/ActivityDisplay.java
index 48a7b73a5fc1..12681133d9c4 100644
--- a/services/core/java/com/android/server/wm/ActivityDisplay.java
+++ b/services/core/java/com/android/server/wm/ActivityDisplay.java
@@ -41,7 +41,6 @@ import static com.android.server.am.ActivityDisplayProto.RESUMED_ACTIVITY;
import static com.android.server.am.ActivityDisplayProto.SINGLE_TASK_INSTANCE;
import static com.android.server.am.ActivityDisplayProto.STACKS;
import static com.android.server.wm.ActivityStack.ActivityState.RESUMED;
-import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_VISIBLE;
import static com.android.server.wm.ActivityStackSupervisor.TAG_TASKS;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STACK;
@@ -1523,7 +1522,7 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> {
final ActivityStack stack = getChildAt(i);
final ArrayList<TaskRecord> tasks = stack.getAllTasks();
for (int j = tasks.size() - 1; j >= 0; --j) {
- stack.removeTask(tasks.get(j), "removeAllTasks", REMOVE_TASK_MODE_DESTROYING);
+ stack.removeChild(tasks.get(j), "removeAllTasks");
}
}
}
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index d4dd033f38e6..d36004101b0e 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -1148,56 +1148,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
}
}
- // TODO(task-unify): Remove once TaskRecord and Task are unified.
TaskRecord getTaskRecord() {
return task;
}
/**
- * Sets reference to the {@link TaskRecord} the {@link ActivityRecord} will treat as its parent.
- * Note that this does not actually add the {@link ActivityRecord} as a {@link TaskRecord}
- * children. However, this method will clean up references to this {@link ActivityRecord} in
- * {@link ActivityStack}.
- * @param task The new parent {@link TaskRecord}.
- */
- // TODO(task-unify): Can be remove after task level unification. Callers can just use addChild
- void setTask(TaskRecord task) {
- // Do nothing if the {@link TaskRecord} is the same as the current {@link getTaskRecord}.
- if (task != null && task == getTaskRecord()) {
- return;
- }
-
- final ActivityStack oldStack = getActivityStack();
- final ActivityStack newStack = task != null ? task.getStack() : null;
-
- // Inform old stack (if present) of activity removal and new stack (if set) of activity
- // addition.
- if (oldStack != newStack) {
- if (oldStack != null) {
- oldStack.onActivityRemovedFromStack(this);
- }
-
- if (newStack != null) {
- newStack.onActivityAddedToStack(this);
- }
- }
-
- final TaskRecord oldTask = this.task;
- this.task = task;
-
- // This is attaching the activity to the task which we only want to do once.
- // TODO(task-unify): Need to re-work after unifying the task level since it will already
- // have a parent then. Just need to restructure the re-parent case not to do this. NOTE that
- // the reparenting flag passed in can't be used directly for this as it isn't set in
- // ActivityRecord#reparent() case that ends up calling this method.
- if (task != null && getParent() == null) {
- task.addChild(this);
- } else {
- onParentChanged(task, oldTask);
- }
- }
-
- /**
* Sets the Task on this activity for the purposes of re-use during launch where we will
* re-use another activity instead of this one for the launch.
*/
@@ -1220,8 +1175,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
@Override
void onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent) {
- final TaskRecord oldTask = (oldParent != null) ? ((Task) oldParent).mTaskRecord : null;
- final TaskRecord newTask = (newParent != null) ? ((Task) newParent).mTaskRecord : null;
+ final TaskRecord oldTask = oldParent != null ? (TaskRecord) oldParent : null;
+ final TaskRecord newTask = newParent != null ? (TaskRecord) newParent : null;
this.task = newTask;
super.onParentChanged(newParent, oldParent);
@@ -1230,14 +1185,12 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
if (oldParent == null && newParent != null) {
// First time we are adding the activity to the system.
- // TODO(task-unify): See if mVoiceInteraction variable is really needed after task level
- // unification.
- mVoiceInteraction = task.mTaskRecord != null && task.mTaskRecord.voiceSession != null;
+ mVoiceInteraction = newTask.voiceSession != null;
mInputDispatchingTimeoutNanos = getInputDispatchingTimeoutLocked(this) * 1000000L;
onDisplayChanged(task.getDisplayContent());
- if (task.mTaskRecord != null) {
- task.mTaskRecord.updateOverrideConfigurationFromLaunchBounds();
- }
+ // TODO(b/36505427): Maybe this call should be moved inside
+ // updateOverrideConfiguration()
+ newTask.updateOverrideConfigurationFromLaunchBounds();
// Make sure override configuration is up-to-date before using to create window
// controller.
updateSizeCompatMode();
@@ -1279,8 +1232,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// Inform old stack (if present) of activity removal and new stack (if set) of activity
// addition.
if (oldStack != newStack) {
- // TODO(task-unify): Might be better to use onChildAdded and onChildRemoved signal for
- // this once task level is unified.
if (oldStack != null) {
oldStack.onActivityRemovedFromStack(this);
}
@@ -1964,15 +1915,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
ProtoLog.i(WM_DEBUG_ADD_REMOVE, "reparent: moving activity=%s"
+ " to task=%d at %d", this, task.mTaskId, position);
-
- reparent(newTask.getTask(), position);
- }
-
- // TODO(task-unify): Remove once Task level is unified.
- void onParentChanged(TaskRecord newParent, TaskRecord oldParent) {
- onParentChanged(
- newParent != null ? newParent.mTask : null,
- oldParent != null ? oldParent.mTask : null);
+ reparent(newTask, position);
}
private boolean isHomeIntent(Intent intent) {
@@ -2051,7 +1994,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
/**
* @return Stack value from current task, null if there is no task.
*/
- // TODO: Remove once ActivityStack and TaskStack are unified.
+ // TODO(stack-unify): Remove once ActivityStack and TaskStack are unified.
<T extends ActivityStack> T getActivityStack() {
return task != null ? (T) task.getStack() : null;
}
@@ -2339,7 +2282,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
/** Finish all activities in the task with the same affinity as this one. */
void finishActivityAffinity() {
- final ArrayList<ActivityRecord> activities = getTaskRecord().mActivities;
+ final ArrayList<ActivityRecord> activities = getTaskRecord().mChildren;
for (int index = activities.indexOf(this); index >= 0; --index) {
final ActivityRecord cur = activities.get(index);
if (!Objects.equals(cur.taskAffinity, taskAffinity)) {
@@ -2451,7 +2394,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
mUserId, System.identityHashCode(this),
task.mTaskId, shortComponentName, reason);
- final ArrayList<ActivityRecord> activities = task.mActivities;
+ final ArrayList<ActivityRecord> activities = task.mChildren;
final int index = activities.indexOf(this);
if (index < (task.getChildCount() - 1)) {
if ((intent.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
@@ -2505,7 +2448,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// When finishing the activity preemptively take the snapshot before the app window
// is marked as hidden and any configuration changes take place
if (mAtmService.mWindowManager.mTaskSnapshotController != null) {
- final ArraySet<Task> tasks = Sets.newArraySet(task.mTask);
+ final ArraySet<Task> tasks = Sets.newArraySet(task);
mAtmService.mWindowManager.mTaskSnapshotController.snapshotTasks(tasks);
mAtmService.mWindowManager.mTaskSnapshotController
.addSkipClosingAppSnapshotTasks(tasks);
@@ -2547,7 +2490,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// In this case, we can set the visibility of all the task overlay activities when
// we detect the last one is finishing to keep them in sync.
if (task.onlyHasTaskOverlayActivities(true /* excludeFinishing */)) {
- for (ActivityRecord taskOverlay : task.mActivities) {
+ for (int i = task.getChildCount() - 1; i >= 0 ; --i) {
+ final ActivityRecord taskOverlay = task.getChildAt(i);
if (!taskOverlay.mTaskOverlay) {
continue;
}
@@ -2819,8 +2763,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
}
/** Note: call {@link #cleanUp(boolean, boolean)} before this method. */
- // TODO(task-unify): Look into consolidating this with TaskRecord.removeChild once we unify
- // task level.
void removeFromHistory(String reason) {
finishActivityResults(Activity.RESULT_CANCELED, null /* resultData */);
makeFinishingLocked();
@@ -4612,16 +4554,25 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
}
/**
- * Check if activity should be moved to RESUMED state. The activity:
- * - should be eligible to be made active (see {@link #shouldMakeActive(ActivityRecord)})
- * - should be focusable
+ * Check if activity should be moved to RESUMED state.
+ * See {@link #shouldBeResumed(ActivityRecord)}
* @param activeActivity the activity that is active or just completed pause action. We won't
* resume if this activity is active.
*/
@VisibleForTesting
boolean shouldResumeActivity(ActivityRecord activeActivity) {
- return shouldMakeActive(activeActivity) && isFocusable() && !isState(RESUMED)
- && getActivityStack().getVisibility(activeActivity) == STACK_VISIBILITY_VISIBLE;
+ return shouldBeResumed(activeActivity) && !isState(RESUMED);
+ }
+
+ /**
+ * Check if activity should be RESUMED now. The activity:
+ * - should be eligible to be made active (see {@link #shouldMakeActive(ActivityRecord)})
+ * - should be focusable
+ */
+ private boolean shouldBeResumed(ActivityRecord activeActivity) {
+ return shouldMakeActive(activeActivity) && isFocusable()
+ && getActivityStack().getVisibility(activeActivity) == STACK_VISIBILITY_VISIBLE
+ && canResumeByCompat();
}
/**
@@ -4659,7 +4610,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
}
// Check if position in task allows to become paused
- final int positionInTask = task.mActivities.indexOf(this);
+ final int positionInTask = task.mChildren.indexOf(this);
if (positionInTask == -1) {
throw new IllegalStateException("Activity not found in its task");
}
@@ -5387,7 +5338,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
return INVALID_TASK_ID;
}
final TaskRecord task = r.task;
- final int activityNdx = task.mActivities.indexOf(r);
+ final int activityNdx = task.mChildren.indexOf(r);
if (activityNdx < 0
|| (onlyRoot && activityNdx > task.findRootIndex(true /* effectiveRoot */))) {
return INVALID_TASK_ID;
@@ -5751,7 +5702,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
@Override
boolean isWaitingForTransitionStart() {
final DisplayContent dc = getDisplayContent();
- // TODO: Test for null can be removed once unification is done.
+ // TODO(display-unify): Test for null can be removed once unification is done.
if (dc == null) return false;
return dc.mAppTransition.isTransitionSet()
&& (dc.mOpeningApps.contains(this)
@@ -6559,8 +6510,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// If the changes come from change-listener, the incoming parent configuration is
// still the old one. Make sure their orientations are the same to reduce computing
// the compatibility bounds for the intermediate state.
- && (task.mTaskRecord == null || task.mTaskRecord
- .getConfiguration().orientation == newParentConfig.orientation)) {
+ && (task.getConfiguration().orientation == newParentConfig.orientation)) {
final Rect taskBounds = task.getBounds();
// Since we only center the activity horizontally, if only the fixed height is smaller
// than its container, the override bounds don't need to take effect.
@@ -6878,8 +6828,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
preserveWindow &= isResizeOnlyChange(changes);
final boolean hasResizeChange = hasResizeChange(changes & ~info.getRealConfigChanged());
if (hasResizeChange) {
- final boolean isDragResizing =
- getTaskRecord().getTask().isDragResizing();
+ final boolean isDragResizing = getTaskRecord().isDragResizing();
mRelaunchReason = isDragResizing ? RELAUNCH_REASON_FREE_RESIZE
: RELAUNCH_REASON_WINDOWING_MODE_RESIZE;
} else {
@@ -6897,23 +6846,14 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
deferRelaunchUntilPaused = true;
preserveWindowOnDeferredRelaunch = preserveWindow;
return true;
- } else if (mState == RESUMED) {
- // Try to optimize this case: the configuration is changing and we need to restart
- // the top, resumed activity. Instead of doing the normal handshaking, just say
- // "restart!".
+ } else {
if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
- "Config is relaunching resumed " + this);
-
+ "Config is relaunching " + this);
if (DEBUG_STATES && !visible) {
- Slog.v(TAG_STATES, "Config is relaunching resumed invisible activity " + this
+ Slog.v(TAG_STATES, "Config is relaunching invisible activity " + this
+ " called by " + Debug.getCallers(4));
}
-
- relaunchActivityLocked(true /* andResume */, preserveWindow);
- } else {
- if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
- "Config is relaunching non-resumed " + this);
- relaunchActivityLocked(false /* andResume */, preserveWindow);
+ relaunchActivityLocked(preserveWindow);
}
// All done... tell the caller we weren't able to keep this activity around.
@@ -7011,12 +6951,13 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
| CONFIG_SCREEN_LAYOUT)) != 0;
}
- void relaunchActivityLocked(boolean andResume, boolean preserveWindow) {
+ void relaunchActivityLocked(boolean preserveWindow) {
if (mAtmService.mSuppressResizeConfigChanges && preserveWindow) {
configChangeFlags = 0;
return;
}
+ final boolean andResume = shouldBeResumed(null /*activeActivity*/);
List<ResultInfo> pendingResults = null;
List<ReferrerIntent> pendingNewIntents = null;
if (andResume) {
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index 8e3995bfd872..593318de34e1 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -254,7 +254,11 @@ class ActivityStack extends ConfigurationContainer {
@Override
protected void onParentChanged(
ConfigurationContainer newParent, ConfigurationContainer oldParent) {
- ActivityDisplay display = getParent();
+ if (oldParent != null) {
+ mPrevDisplayId = ((ActivityDisplay) oldParent).mDisplayId;
+ }
+
+ final ActivityDisplay display = getParent();
if (display != null) {
// Rotations are relative to the display. This means if there are 2 displays rotated
// differently (eg. 2 monitors with one landscape and one portrait), moving a stack
@@ -292,18 +296,6 @@ class ActivityStack extends ConfigurationContainer {
RESTARTING_PROCESS
}
- @VisibleForTesting
- /* The various modes for the method {@link #removeTask}. */
- // Task is being completely removed from all stacks in the system.
- protected static final int REMOVE_TASK_MODE_DESTROYING = 0;
- // Task is being removed from this stack so we can add it to another stack. In the case we are
- // moving we don't want to perform some operations on the task like removing it from window
- // manager or recents.
- static final int REMOVE_TASK_MODE_MOVING = 1;
- // Similar to {@link #REMOVE_TASK_MODE_MOVING} and the task will be added to the top of its new
- // stack and the new stack will be on top of all stacks.
- static final int REMOVE_TASK_MODE_MOVING_TO_TOP = 2;
-
final ActivityTaskManagerService mService;
final WindowManagerService mWindowManager;
@@ -381,6 +373,8 @@ class ActivityStack extends ConfigurationContainer {
final int mStackId;
/** The attached Display's unique identifier, or -1 if detached */
int mDisplayId;
+ // Id of the previous display the stack was on.
+ int mPrevDisplayId = INVALID_DISPLAY;
/** Stores the override windowing-mode from before a transient mode change (eg. split) */
private int mRestoreOverrideWindowingMode = WINDOWING_MODE_UNDEFINED;
@@ -962,7 +956,7 @@ class ActivityStack extends ConfigurationContainer {
void positionChildWindowContainerAtTop(TaskRecord child) {
if (mTaskStack != null) {
// TODO: Remove after unification. This cannot be false after that.
- mTaskStack.positionChildAtTop(child.getTask(), true /* includingParents */);
+ mTaskStack.positionChildAtTop(child, true /* includingParents */);
}
}
@@ -974,7 +968,7 @@ class ActivityStack extends ConfigurationContainer {
child.getStack(), true /* ignoreCurrent */);
if (mTaskStack != null) {
// TODO: Remove after unification. This cannot be false after that.
- mTaskStack.positionChildAtBottom(child.getTask(),
+ mTaskStack.positionChildAtBottom(child,
nextFocusableStack == null /* includingParents */);
}
}
@@ -1168,7 +1162,7 @@ class ActivityStack extends ConfigurationContainer {
}
final TaskRecord task = r.getTaskRecord();
final ActivityStack stack = r.getActivityStack();
- if (stack != null && task.mActivities.contains(r) && mTaskHistory.contains(task)) {
+ if (stack != null && task.mChildren.contains(r) && mTaskHistory.contains(task)) {
if (stack != this) Slog.w(TAG,
"Illegal state! task does not point to stack it is in.");
return r;
@@ -1183,7 +1177,8 @@ class ActivityStack extends ConfigurationContainer {
/** Checks if there are tasks with specific UID in the stack. */
boolean isUidPresent(int uid) {
for (TaskRecord task : mTaskHistory) {
- for (ActivityRecord r : task.mActivities) {
+ for (int i = task.getChildCount() - 1; i >= 0 ; --i) {
+ final ActivityRecord r = task.getChildAt(i);
if (r.getUid() == uid) {
return true;
}
@@ -1195,7 +1190,8 @@ class ActivityStack extends ConfigurationContainer {
/** Get all UIDs that are present in the stack. */
void getPresentUIDs(IntArray presentUIDs) {
for (TaskRecord task : mTaskHistory) {
- for (ActivityRecord r : task.mActivities) {
+ for (int i = task.getChildCount() - 1; i >= 0 ; --i) {
+ final ActivityRecord r = task.getChildAt(i);
presentUIDs.add(r.getUid());
}
}
@@ -1207,12 +1203,6 @@ class ActivityStack extends ConfigurationContainer {
return display != null && display.isSingleTaskInstance();
}
- private void removeActivitiesFromLRUList(TaskRecord task) {
- for (ActivityRecord r : task.mActivities) {
- mLRUActivities.remove(r);
- }
- }
-
/** @return {@code true} if LRU list contained the specified activity. */
final boolean removeActivityFromLRUList(ActivityRecord activity) {
return mLRUActivities.remove(activity);
@@ -1792,8 +1782,7 @@ class ActivityStack extends ConfigurationContainer {
if (prev.deferRelaunchUntilPaused) {
// Complete the deferred relaunch that was waiting for pause to complete.
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Re-launching after pause: " + prev);
- prev.relaunchActivityLocked(false /* andResume */,
- prev.preserveWindowOnDeferredRelaunch);
+ prev.relaunchActivityLocked(prev.preserveWindowOnDeferredRelaunch);
} else if (wasStopping) {
// We are also stopping, the stop request must have gone soon after the pause.
// We can't clobber it, because the stop confirmation will not be handled.
@@ -3016,19 +3005,19 @@ class ActivityStack extends ConfigurationContainer {
mTaskHistory.remove(task);
mTaskHistory.add(position, task);
if (mTaskStack != null) {
- // TODO: this could not be false after unification.
- mTaskStack.positionChildAt(task.getTask(), position);
+ // TODO: this can not be false after unification Stack.
+ mTaskStack.positionChildAt(task, position);
}
- updateTaskMovement(task, true);
+ task.updateTaskMovement(true);
}
- private void insertTaskAtTop(TaskRecord task, ActivityRecord starting) {
- // TODO: Better place to put all the code below...may be addTask...
+ void insertTaskAtTop(TaskRecord task, ActivityRecord starting) {
+ // TODO: Better place to put all the code below...may be addChild...
mTaskHistory.remove(task);
// Now put task at top.
final int position = getAdjustedPositionForTask(task, mTaskHistory.size(), starting);
mTaskHistory.add(position, task);
- updateTaskMovement(task, true);
+ task.updateTaskMovement(true);
positionChildWindowContainerAtTop(task);
}
@@ -3036,7 +3025,7 @@ class ActivityStack extends ConfigurationContainer {
mTaskHistory.remove(task);
final int position = getAdjustedPositionForTask(task, 0, null);
mTaskHistory.add(position, task);
- updateTaskMovement(task, true);
+ task.updateTaskMovement(true);
positionChildWindowContainerAtBottom(task);
}
@@ -3070,7 +3059,7 @@ class ActivityStack extends ConfigurationContainer {
if (!startIt) {
if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to task "
+ task, new RuntimeException("here").fillInStackTrace());
- r.setTask(rTask);
+ rTask.positionChildAtTop(r);
ActivityOptions.abort(options);
return;
}
@@ -3097,7 +3086,7 @@ class ActivityStack extends ConfigurationContainer {
// Slot the activity into the history stack and proceed
if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to stack to task " + task,
new RuntimeException("here").fillInStackTrace());
- r.setTask(task);
+ task.positionChildAtTop(r);
// The transition animation and starting window are not needed if {@code allowMoveToFront}
// is false, because the activity won't be visible.
@@ -3272,7 +3261,7 @@ class ActivityStack extends ConfigurationContainer {
// with the same affinity is unlikely to be in the same stack.
final TaskRecord targetTask;
final ActivityRecord bottom =
- !mTaskHistory.isEmpty() && !mTaskHistory.get(0).mActivities.isEmpty() ?
+ !mTaskHistory.isEmpty() && mTaskHistory.get(0).hasChild() ?
mTaskHistory.get(0).getChildAt(0) : null;
if (bottom != null && target.taskAffinity.equals(bottom.getTaskRecord().affinity)) {
// If the activity currently at the bottom has the
@@ -3483,7 +3472,7 @@ class ActivityStack extends ConfigurationContainer {
// instance of the same activity? Then we drop the instance
// below so it remains singleTop.
if (target.info.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP) {
- final ArrayList<ActivityRecord> taskActivities = task.mActivities;
+ final ArrayList<ActivityRecord> taskActivities = task.mChildren;
final int targetNdx = taskActivities.indexOf(target);
if (targetNdx > 0) {
final ActivityRecord p = taskActivities.get(targetNdx - 1);
@@ -3637,7 +3626,7 @@ class ActivityStack extends ConfigurationContainer {
finishedTask = r.getTaskRecord();
int taskNdx = mTaskHistory.indexOf(finishedTask);
final TaskRecord task = finishedTask;
- int activityNdx = task.mActivities.indexOf(r);
+ int activityNdx = task.mChildren.indexOf(r);
getDisplay().mDisplayContent.prepareAppTransition(
TRANSIT_CRASHING_ACTIVITY_CLOSE, false /* alwaysKeepCurrent */);
r.finishIfPossible(reason, false /* oomAdj */);
@@ -3774,7 +3763,7 @@ class ActivityStack extends ConfigurationContainer {
final boolean navigateUpToLocked(ActivityRecord srec, Intent destIntent, int resultCode,
Intent resultData) {
final TaskRecord task = srec.getTaskRecord();
- final ArrayList<ActivityRecord> activities = task.mActivities;
+ final ArrayList<ActivityRecord> activities = task.mChildren;
final int start = activities.indexOf(srec);
if (!mTaskHistory.contains(task) || (start < 0)) {
return false;
@@ -3868,8 +3857,16 @@ class ActivityStack extends ConfigurationContainer {
* an activity moves away from the stack.
*/
void onActivityRemovedFromStack(ActivityRecord r) {
+ removeActivityFromLRUList(r);
removeTimeoutsForActivity(r);
+ // TODO(stack-unify): null check will no longer be needed.
+ if (mTaskStack != null) {
+ mTaskStack.mExitingActivities.remove(r);
+ }
+ // TODO(stack-unify): Remove if no bugs showed up...
+ //r.mIsExiting = false;
+
if (mResumedActivity != null && mResumedActivity == r) {
setResumedActivity(null, "onActivityRemovedFromStack");
}
@@ -4062,7 +4059,7 @@ class ActivityStack extends ConfigurationContainer {
if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP,
"Removing app " + app + " from history with " + i + " entries");
for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
+ final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mChildren;
mTmpActivities.clear();
mTmpActivities.addAll(activities);
@@ -4151,19 +4148,6 @@ class ActivityStack extends ConfigurationContainer {
getDisplay().mDisplayContent.prepareAppTransition(transit, false);
}
- private void updateTaskMovement(TaskRecord task, boolean toFront) {
- if (task.isPersistable) {
- task.mLastTimeMoved = System.currentTimeMillis();
- // Sign is used to keep tasks sorted when persisted. Tasks sent to the bottom most
- // recently will be most negative, tasks sent to the bottom before that will be less
- // negative. Similarly for recent tasks moved to the top which will be most positive.
- if (!toFront) {
- task.mLastTimeMoved *= -1;
- }
- }
- mRootActivityContainer.invalidateTaskLayers();
- }
-
final void moveTaskToFrontLocked(TaskRecord tr, boolean noAnimation, ActivityOptions options,
AppTimeTracker timeTracker, String reason) {
if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "moveTaskToFront: " + tr);
@@ -4296,7 +4280,7 @@ class ActivityStack extends ConfigurationContainer {
mTaskHistory.remove(tr);
mTaskHistory.add(0, tr);
- updateTaskMovement(tr, false);
+ tr.updateTaskMovement(false);
getDisplay().mDisplayContent.prepareAppTransition(TRANSIT_TASK_TO_BACK, false);
moveToBack("moveTaskToBackLocked", tr);
@@ -4335,7 +4319,7 @@ class ActivityStack extends ConfigurationContainer {
for (int taskIndex = mTaskHistory.indexOf(startTask); taskIndex >= 0; --taskIndex) {
final TaskRecord task = mTaskHistory.get(taskIndex);
- final ArrayList<ActivityRecord> activities = task.mActivities;
+ final ArrayList<ActivityRecord> activities = task.mChildren;
int activityIndex = (start.getTaskRecord() == task)
? activities.indexOf(start) : activities.size() - 1;
for (; activityIndex >= 0; --activityIndex) {
@@ -4375,10 +4359,10 @@ class ActivityStack extends ConfigurationContainer {
final TaskRecord task = mTaskHistory.get(i);
if (task.isResizeable()) {
if (tempTaskInsetBounds != null && !tempTaskInsetBounds.isEmpty()) {
- task.setDisplayedBounds(taskBounds);
+ task.setOverrideDisplayedBounds(taskBounds);
task.setBounds(tempTaskInsetBounds);
} else {
- task.setDisplayedBounds(null);
+ task.setOverrideDisplayedBounds(null);
task.setBounds(taskBounds);
}
}
@@ -4430,9 +4414,9 @@ class ActivityStack extends ConfigurationContainer {
for (int i = mTaskHistory.size() - 1; i >= 0; i--) {
final TaskRecord task = mTaskHistory.get(i);
if (bounds == null || bounds.isEmpty()) {
- task.setDisplayedBounds(null);
+ task.setOverrideDisplayedBounds(null);
} else if (task.isResizeable()) {
- task.setDisplayedBounds(bounds);
+ task.setOverrideDisplayedBounds(bounds);
}
}
}
@@ -4477,7 +4461,7 @@ class ActivityStack extends ConfigurationContainer {
TaskRecord lastTask = null;
ComponentName homeActivity = null;
for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
+ final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mChildren;
mTmpActivities.clear();
mTmpActivities.addAll(activities);
@@ -4675,7 +4659,7 @@ class ActivityStack extends ConfigurationContainer {
pw.println(prefix + "mLastNonFullscreenBounds=" + task.mLastNonFullscreenBounds);
pw.println(prefix + "* " + task);
task.dump(pw, prefix + " ");
- dumpHistoryList(fd, pw, mTaskHistory.get(taskNdx).mActivities,
+ dumpHistoryList(fd, pw, mTaskHistory.get(taskNdx).mChildren,
prefix, "Hist", true, !dumpAll, dumpClient, dumpPackage, false, null, task);
}
return true;
@@ -4686,15 +4670,15 @@ class ActivityStack extends ConfigurationContainer {
if ("all".equals(name)) {
for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- activities.addAll(mTaskHistory.get(taskNdx).mActivities);
+ activities.addAll(mTaskHistory.get(taskNdx).mChildren);
}
} else if ("top".equals(name)) {
final int top = mTaskHistory.size() - 1;
if (top >= 0) {
- final ArrayList<ActivityRecord> list = mTaskHistory.get(top).mActivities;
- int listTop = list.size() - 1;
+ final TaskRecord task = mTaskHistory.get(top);
+ int listTop = task.getChildCount() - 1;
if (listTop >= 0) {
- activities.add(list.get(listTop));
+ activities.add(task.getChildAt(listTop));
}
}
} else {
@@ -4702,7 +4686,9 @@ class ActivityStack extends ConfigurationContainer {
matcher.build(name);
for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- for (ActivityRecord r1 : mTaskHistory.get(taskNdx).mActivities) {
+ final TaskRecord task = mTaskHistory.get(taskNdx);
+ for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
+ final ActivityRecord r1 = task.getChildAt(activityNdx);
if (matcher.match(r1, r1.intent.getComponent())) {
activities.add(r1);
}
@@ -4734,58 +4720,51 @@ class ActivityStack extends ConfigurationContainer {
return starting;
}
- /**
- * Removes the input task from this stack.
- *
- * @param task to remove.
- * @param reason for removal.
- * @param mode task removal mode. Either {@link #REMOVE_TASK_MODE_DESTROYING},
- * {@link #REMOVE_TASK_MODE_MOVING}, {@link #REMOVE_TASK_MODE_MOVING_TO_TOP}.
- */
- void removeTask(TaskRecord task, String reason, int mode) {
- if (!mTaskHistory.remove(task)) {
- // Not really in this stack anymore...
- return;
+ // TODO(stack-unify): Merge into removeChild method below.
+ void onChildRemoved(TaskRecord child, DisplayContent dc) {
+ mTaskHistory.remove(child);
+ EventLog.writeEvent(EventLogTags.AM_REMOVE_TASK, child.mTaskId, mStackId);
+
+ ActivityDisplay display = getDisplay();
+ if (display == null && dc != null) {
+ display = dc.mActivityDisplay;
}
- EventLog.writeEvent(EventLogTags.AM_REMOVE_TASK, task.mTaskId, getStackId());
+ if (display.isSingleTaskInstance()) {
+ mService.notifySingleTaskDisplayEmpty(display.mDisplayId);
+ }
- removeActivitiesFromLRUList(task);
- updateTaskMovement(task, true);
+ display.mDisplayContent.setLayoutNeeded();
- if (mode == REMOVE_TASK_MODE_DESTROYING) {
- task.cleanUpResourcesForDestroy();
+ if (mTaskHistory.isEmpty()) {
+ // Stack is now empty...
+ remove();
}
+ }
+ /**
+ * Removes the input task from this stack.
+ *
+ * @param task to remove.
+ * @param reason for removal.
+ */
+ void removeChild(TaskRecord task, String reason) {
final ActivityDisplay display = getDisplay();
- if (mTaskHistory.isEmpty()) {
- if (DEBUG_STACK) Slog.i(TAG_STACK, "removeTask: removing stack=" + this);
+ final boolean topFocused = mRootActivityContainer.isTopDisplayFocusedStack(this);
+ mTaskStack.removeChild(task);
+ moveHomeStackToFrontIfNeeded(topFocused, display, reason);
+ }
+
+ void moveHomeStackToFrontIfNeeded(
+ boolean wasTopFocusedStack, ActivityDisplay display, String reason) {
+ if (mTaskHistory.isEmpty() && wasTopFocusedStack) {
// We only need to adjust focused stack if this stack is in focus and we are not in the
// process of moving the task to the top of the stack that will be focused.
- if (mode != REMOVE_TASK_MODE_MOVING_TO_TOP
- && mRootActivityContainer.isTopDisplayFocusedStack(this)) {
- String myReason = reason + " leftTaskHistoryEmpty";
- if (!inMultiWindowMode() || adjustFocusToNextFocusableStack(myReason) == null) {
- display.moveHomeStackToFront(myReason);
- }
- }
- if (isAttached()) {
- display.positionChildAtBottom(this);
- }
- if (!isActivityTypeHome() || !isAttached()) {
- remove();
+ String myReason = reason + " leftTaskHistoryEmpty";
+ if (!inMultiWindowMode() || adjustFocusToNextFocusableStack(myReason) == null) {
+ display.moveHomeStackToFront(myReason);
}
}
-
- task.setStack(null);
-
- // Notify if a task from the pinned stack is being removed (or moved depending on the mode)
- if (inPinnedWindowingMode()) {
- mService.getTaskChangeNotificationController().notifyActivityUnpinned();
- }
- if (display != null && display.isSingleTaskInstance()) {
- mService.notifySingleTaskDisplayEmpty(display.mDisplayId);
- }
}
TaskRecord createTaskRecord(int taskId, ActivityInfo info, Intent intent,
@@ -4800,9 +4779,9 @@ class ActivityStack extends ConfigurationContainer {
boolean toTop, ActivityRecord activity, ActivityRecord source,
ActivityOptions options) {
final TaskRecord task = TaskRecord.create(
- mService, taskId, info, intent, voiceSession, voiceInteractor);
+ mService, taskId, info, intent, voiceSession, voiceInteractor, this);
// add the task to stack first, mTaskPositioner might need the stack association
- addTask(task, toTop, "createTaskRecord");
+ addChild(task, toTop, (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0);
final int displayId = mDisplayId != INVALID_DISPLAY ? mDisplayId : DEFAULT_DISPLAY;
final boolean isLockscreenShown = mService.mStackSupervisor.getKeyguardController()
.isKeyguardOrAodShowing(displayId);
@@ -4811,7 +4790,6 @@ class ActivityStack extends ConfigurationContainer {
&& !matchParentBounds() && task.isResizeable() && !isLockscreenShown) {
task.setBounds(getRequestedOverrideBounds());
}
- task.createTask(toTop, (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0);
return task;
}
@@ -4819,34 +4797,31 @@ class ActivityStack extends ConfigurationContainer {
return new ArrayList<>(mTaskHistory);
}
- void addTask(final TaskRecord task, final boolean toTop, String reason) {
- addTask(task, toTop ? MAX_VALUE : 0, true /* schedulePictureInPictureModeChange */, reason);
- if (toTop) {
- // TODO: figure-out a way to remove this call.
- positionChildWindowContainerAtTop(task);
- }
+ // TODO(stack-unify): Merge with addChild below.
+ void onChildAdded(TaskRecord task, int position) {
+ final boolean toTop = position >= mTaskHistory.size();
+ mTaskHistory.add(position, task);
+
+ // TODO: Feels like this should go in TaskRecord#onParentChanged
+ task.updateTaskMovement(toTop);
}
- // TODO: This shouldn't allow automatic reparenting. Remove the call to preAddTask and deal
- // with the fall-out...
- void addTask(final TaskRecord task, int position, boolean schedulePictureInPictureModeChange,
- String reason) {
- // TODO: Is this remove really needed? Need to look into the call path for the other addTask
- mTaskHistory.remove(task);
+ void addChild(final TaskRecord task, final boolean toTop, boolean showForAllUsers) {
if (isSingleTaskInstance() && !mTaskHistory.isEmpty()) {
throw new IllegalStateException("Can only have one child on stack=" + this);
}
- position = getAdjustedPositionForTask(task, position, null /* starting */);
- final boolean toTop = position >= mTaskHistory.size();
- final ActivityStack prevStack = preAddTask(task, reason, toTop);
-
- mTaskHistory.add(position, task);
- task.setStack(this);
+ final int position =
+ getAdjustedPositionForTask(task, toTop ? MAX_VALUE : 0, null /* starting */);
- updateTaskMovement(task, toTop);
+ // We only want to move the parents to the parents if we are creating this task at the
+ // top of its stack.
+ mTaskStack.addChild(task, position, showForAllUsers, toTop /*moveParents*/);
- postAddTask(task, prevStack, schedulePictureInPictureModeChange);
+ if (toTop) {
+ // TODO: figure-out a way to remove this call.
+ positionChildWindowContainerAtTop(task);
+ }
}
void positionChildAt(TaskRecord task, int index) {
@@ -4861,8 +4836,14 @@ class ActivityStack extends ConfigurationContainer {
final ActivityRecord topRunningActivity = task.topRunningActivityLocked();
final boolean wasResumed = topRunningActivity == task.getStack().mResumedActivity;
insertTaskAtPosition(task, index);
- task.setStack(this);
- postAddTask(task, null /* prevStack */, true /* schedulePictureInPictureModeChange */);
+
+ // TODO: Investigate if this random code is really needed.
+ if (task.voiceSession != null) {
+ try {
+ task.voiceSession.taskStarted(task.intent, task.mTaskId);
+ } catch (RemoteException e) {
+ }
+ }
if (wasResumed) {
if (mResumedActivity != null) {
@@ -4879,32 +4860,6 @@ class ActivityStack extends ConfigurationContainer {
mRootActivityContainer.resumeFocusedStacksTopActivities();
}
- private ActivityStack preAddTask(TaskRecord task, String reason, boolean toTop) {
- final ActivityStack prevStack = task.getStack();
- if (prevStack != null && prevStack != this) {
- prevStack.removeTask(task, reason,
- toTop ? REMOVE_TASK_MODE_MOVING_TO_TOP : REMOVE_TASK_MODE_MOVING);
- }
- return prevStack;
- }
-
- /**
- * @param schedulePictureInPictureModeChange specifies whether or not to schedule the PiP mode
- * change. Callers may set this to false if they are explicitly scheduling PiP mode
- * changes themselves, like during the PiP animation
- */
- private void postAddTask(TaskRecord task, ActivityStack prevStack,
- boolean schedulePictureInPictureModeChange) {
- if (schedulePictureInPictureModeChange && prevStack != null) {
- mStackSupervisor.scheduleUpdatePictureInPictureModeIfNeeded(task, prevStack);
- } else if (task.voiceSession != null) {
- try {
- task.voiceSession.taskStarted(task.intent, task.mTaskId);
- } catch (RemoteException e) {
- }
- }
- }
-
public void setAlwaysOnTop(boolean alwaysOnTop) {
if (isAlwaysOnTop() == alwaysOnTop) {
return;
diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index dc3d2631a5d7..f8a7397f10df 100644
--- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
@@ -52,7 +52,6 @@ import static android.view.WindowManager.TRANSIT_DOCK_TASK_FROM_RECENTS;
import static com.android.server.wm.ActivityStack.ActivityState.PAUSED;
import static com.android.server.wm.ActivityStack.ActivityState.PAUSING;
-import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_MOVING;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ALL;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_IDLE;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_PAUSE;
@@ -83,6 +82,7 @@ import static com.android.server.wm.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT;
import static com.android.server.wm.TaskRecord.REPARENT_LEAVE_STACK_IN_PLACE;
import static com.android.server.wm.TaskRecord.REPARENT_MOVE_STACK_TO_FRONT;
import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
+import static com.android.server.wm.WindowContainer.POSITION_TOP;
import android.Manifest;
import android.app.Activity;
@@ -1420,7 +1420,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
// WM resizeTask must be done after the task is moved to the correct stack,
// because Task's setBounds() also updates dim layer's bounds, but that has
// dependency on the stack.
- task.resizeWindowContainer();
+ task.resize(false /* relayout */, false /* forced */);
}
}
@@ -1885,26 +1885,22 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
final ActivityStack stack =
mRootActivityContainer.getLaunchStack(null, aOptions, task, onTop);
final ActivityStack currentStack = task.getStack();
+
+ if (currentStack == stack) {
+ // Nothing else to do since it is already restored in the right stack.
+ return true;
+ }
+
if (currentStack != null) {
- // Task has already been restored once. See if we need to do anything more
- if (currentStack == stack) {
- // Nothing else to do since it is already restored in the right stack.
- return true;
- }
- // Remove current stack association, so we can re-associate the task with the
- // right stack below.
- currentStack.removeTask(task, "restoreRecentTaskLocked", REMOVE_TASK_MODE_MOVING);
+ // Task has already been restored once. Just re-parent it to the new stack.
+ task.reparent(stack.mTaskStack,
+ POSITION_TOP, true /*moveParents*/, "restoreRecentTaskLocked");
+ return true;
}
- stack.addTask(task, onTop, "restoreRecentTask");
- // TODO: move call for creation here and other place into Stack.addTask()
- task.createTask(onTop, true /* showForAllUsers */);
+ stack.addChild(task, onTop, true /* showForAllUsers */);
if (DEBUG_RECENTS) Slog.v(TAG_RECENTS,
"Added restored task=" + task + " to stack=" + stack);
- for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
- final ActivityRecord r = task.getChildAt(activityNdx);
- r.setTask(task);
- }
return true;
}
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index d1bb2559e5be..6edcb0298938 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -50,6 +50,7 @@ import static android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS;
import static android.content.Intent.FLAG_ACTIVITY_SINGLE_TOP;
import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
import static android.content.pm.ActivityInfo.DOCUMENT_LAUNCH_ALWAYS;
+import static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
import static android.content.pm.ActivityInfo.LAUNCH_MULTIPLE;
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE;
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
@@ -1842,7 +1843,7 @@ class ActivityStarter {
// {@code ActivityRecord} removing its reference to the {@code TaskRecord}. The task
// reference is needed in the call below to {@link setTargetStackAndMoveToFrontIfNeeded}
if (targetTaskTop.getTaskRecord() == null) {
- targetTaskTop.setTask(targetTask);
+ targetTask.addChild(targetTaskTop);
}
if (top != null) {
@@ -1862,8 +1863,8 @@ class ActivityStarter {
// Go ahead and reset it.
mTargetStack = computeStackFocus(mSourceRecord, false /* newTask */,
mLaunchFlags, mOptions);
- mTargetStack.addTask(targetTask,
- !mLaunchTaskBehind /* toTop */, "complyActivityFlags");
+ mTargetStack.addChild(targetTask, !mLaunchTaskBehind /* toTop */,
+ (mStartActivity.info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0);
}
}
} else if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) == 0 && !mAddingToTask
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 222f26edaf5d..da7af5fdd369 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -85,7 +85,6 @@ import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.Scr
import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.ScreenCompatPackage.PACKAGE;
import static com.android.server.wm.ActivityStack.ActivityState.DESTROYED;
import static com.android.server.wm.ActivityStack.ActivityState.DESTROYING;
-import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
import static com.android.server.wm.ActivityStackSupervisor.DEFER_RESUME;
import static com.android.server.wm.ActivityStackSupervisor.ON_TOP;
import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS;
@@ -1996,7 +1995,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
return false;
}
final TaskRecord task = r.getTaskRecord();
- int index = task.mActivities.lastIndexOf(r);
+ int index = task.mChildren.lastIndexOf(r);
if (index > 0) {
ActivityRecord under = task.getChildAt(index - 1);
under.returningOptions = safeOptions != null ? safeOptions.getOptions(r) : null;
@@ -2221,18 +2220,10 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
Slog.w(TAG, "getTaskBounds: taskId=" + taskId + " not found");
return rect;
}
- if (task.getStack() != null) {
- // Return the bounds from window manager since it will be adjusted for various
- // things like the presense of a docked stack for tasks that aren't resizeable.
- task.getWindowContainerBounds(rect);
- } else {
- // Task isn't in window manager yet since it isn't associated with a stack.
- // Return the persist value from activity manager
- if (!task.matchParentBounds()) {
- rect.set(task.getBounds());
- } else if (task.mLastNonFullscreenBounds != null) {
- rect.set(task.mLastNonFullscreenBounds);
- }
+ if (task.getParent() != null) {
+ rect.set(task.getBounds());
+ } else if (task.mLastNonFullscreenBounds != null) {
+ rect.set(task.mLastNonFullscreenBounds);
}
}
} finally {
@@ -2249,7 +2240,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
final TaskRecord tr = mRootActivityContainer.anyTaskForId(id,
MATCH_TASK_IN_STACKS_OR_RECENT_TASKS);
if (tr != null) {
- return tr.mTaskDescription;
+ return tr.getTaskDescription();
}
}
return null;
@@ -3168,10 +3159,10 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
null /* voiceSession */, null /* voiceInteractor */, !ON_TOP);
if (!mRecentTasks.addToBottom(task)) {
// The app has too many tasks already and we can't add any more
- stack.removeTask(task, "addAppTask", REMOVE_TASK_MODE_DESTROYING);
+ stack.removeChild(task, "addAppTask");
return INVALID_TASK_ID;
}
- task.mTaskDescription.copyFrom(description);
+ task.getTaskDescription().copyFrom(description);
// TODO: Send the thumbnail to WM to store it.
@@ -4489,7 +4480,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
Slog.w(TAG, "cancelTaskWindowTransition: taskId=" + taskId + " not found");
return;
}
- task.cancelWindowTransition();
+ task.cancelTaskWindowTransition();
}
} finally {
Binder.restoreCallingIdentity(ident);
diff --git a/services/core/java/com/android/server/wm/ConfigurationContainer.java b/services/core/java/com/android/server/wm/ConfigurationContainer.java
index 8b4f7cc571f8..30f3bc5e70fb 100644
--- a/services/core/java/com/android/server/wm/ConfigurationContainer.java
+++ b/services/core/java/com/android/server/wm/ConfigurationContainer.java
@@ -134,9 +134,9 @@ public abstract class ConfigurationContainer<E extends ConfigurationContainer> {
onConfigurationChanged(newParentConfig, true /*forwardToChildren*/);
}
- // TODO: Consolidate with onConfigurationChanged() method above once unification is done. This
- // is only currently need during the process of unification where we don't want configuration
- // forwarded to a child from both parents.
+ // TODO(root-unify): Consolidate with onConfigurationChanged() method above once unification is
+ // done. This is only currently need during the process of unification where we don't want
+ // configuration forwarded to a child from both parents.
public void onConfigurationChanged(Configuration newParentConfig, boolean forwardToChildren) {
mResolvedTmpConfig.setTo(mResolvedOverrideConfiguration);
resolveOverrideConfiguration(newParentConfig);
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 89568ebf4277..d1d468b5ae3d 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -2409,7 +2409,19 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
/** Returns true if a removal action is still being deferred. */
@Override
boolean checkCompleteDeferredRemoval() {
- final boolean stillDeferringRemoval = super.checkCompleteDeferredRemoval();
+ boolean stillDeferringRemoval = false;
+
+ for (int i = getChildCount() - 1; i >= 0; --i) {
+ final DisplayChildWindowContainer child = getChildAt(i);
+ stillDeferringRemoval |= child.checkCompleteDeferredRemoval();
+ if (getChildCount() == 0) {
+ // If this display is pending to be removed because it contains an activity with
+ // {@link ActivityRecord#mIsExiting} is true, this display may be removed when
+ // completing the removal of the last activity from
+ // {@link ActivityRecord#checkCompleteDeferredRemoval}.
+ return false;
+ }
+ }
if (!stillDeferringRemoval && mDeferredRemoval) {
removeImmediately();
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 6e238b33d8dd..fcfd9ded9ad7 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -144,13 +144,16 @@ import android.view.InputChannel;
import android.view.InputDevice;
import android.view.InputEvent;
import android.view.InputEventReceiver;
+import android.view.InsetsFlags;
import android.view.InsetsState;
+import android.view.InsetsState.InternalInsetType;
import android.view.MotionEvent;
import android.view.PointerIcon;
import android.view.Surface;
import android.view.View;
import android.view.ViewRootImpl;
import android.view.WindowInsets;
+import android.view.WindowInsetsController.Appearance;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import android.view.WindowManagerGlobal;
@@ -332,8 +335,6 @@ public class DisplayPolicy {
private int mResettingSystemUiFlags = 0;
// Bits that we are currently always keeping cleared.
private int mForceClearedSystemUiFlags = 0;
- private int mLastFullscreenStackSysUiFlags;
- private int mLastDockedStackSysUiFlags;
private int mLastAppearance;
private int mLastFullscreenAppearance;
private int mLastDockedAppearance;
@@ -3172,11 +3173,6 @@ public class DisplayPolicy {
&= ~PolicyControl.adjustClearableFlags(win, View.SYSTEM_UI_CLEARABLE_FLAGS);
}
- final int appearance = win.mAttrs.insetsFlags.appearance;
- final int fullscreenVisibility = updateLightStatusBarLw(0 /* vis */,
- mTopFullscreenOpaqueWindowState, mTopFullscreenOpaqueOrDimmingWindowState);
- final int dockedVisibility = updateLightStatusBarLw(0 /* vis */,
- mTopDockedOpaqueWindowState, mTopDockedOpaqueOrDimmingWindowState);
final int fullscreenAppearance = updateLightStatusBarAppearanceLw(0 /* vis */,
mTopFullscreenOpaqueWindowState, mTopFullscreenOpaqueOrDimmingWindowState);
final int dockedAppearance = updateLightStatusBarAppearanceLw(0 /* vis */,
@@ -3190,9 +3186,9 @@ public class DisplayPolicy {
final Pair<Integer, Boolean> result =
updateSystemBarsLw(win, mLastSystemUiFlags, tmpVisibility);
final int visibility = result.first;
+ final int appearance = win.mAttrs.insetsFlags.appearance
+ | InsetsFlags.getAppearance(visibility);
final int diff = visibility ^ mLastSystemUiFlags;
- final int fullscreenDiff = fullscreenVisibility ^ mLastFullscreenStackSysUiFlags;
- final int dockedDiff = dockedVisibility ^ mLastDockedStackSysUiFlags;
final InsetsPolicy insetsPolicy = getInsetsPolicy();
final boolean isFullscreen = (visibility & (View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION)) != 0
@@ -3205,7 +3201,7 @@ public class DisplayPolicy {
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY)) != 0
|| behavior == BEHAVIOR_SHOW_BARS_BY_SWIPE
|| behavior == BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
- if (diff == 0 && fullscreenDiff == 0 && dockedDiff == 0
+ if (diff == 0
&& mLastAppearance == appearance
&& mLastFullscreenAppearance == fullscreenAppearance
&& mLastDockedAppearance == dockedAppearance
@@ -3216,9 +3212,12 @@ public class DisplayPolicy {
&& mLastDockedStackBounds.equals(mDockedStackBounds)) {
return 0;
}
+
+ // Obtains which types should show transient and which types should abort transient.
+ // If there is no transient state change, this pair will contain two empty arrays.
+ final Pair<int[], int[]> transientState = getTransientState(visibility, mLastSystemUiFlags);
+
mLastSystemUiFlags = visibility;
- mLastFullscreenStackSysUiFlags = fullscreenVisibility;
- mLastDockedStackSysUiFlags = dockedVisibility;
mLastAppearance = appearance;
mLastFullscreenAppearance = fullscreenAppearance;
mLastDockedAppearance = dockedAppearance;
@@ -3240,14 +3239,16 @@ public class DisplayPolicy {
StatusBarManagerInternal statusBar = getStatusBarManagerInternal();
if (statusBar != null) {
final int displayId = getDisplayId();
- // TODO(b/118118435): disabled flags only
- statusBar.setSystemUiVisibility(displayId, visibility, fullscreenVisibility,
- dockedVisibility, 0xffffffff, fullscreenStackBounds,
- dockedStackBounds, isNavbarColorManagedByIme, win.toString());
- if (ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_FULL) {
- statusBar.onSystemBarAppearanceChanged(displayId, appearance,
- appearanceRegions, isNavbarColorManagedByIme);
+ statusBar.setDisableFlags(displayId, visibility & StatusBarManager.DISABLE_MASK,
+ win.toString());
+ if (transientState.first.length > 0) {
+ statusBar.showTransient(displayId, transientState.first);
}
+ if (transientState.second.length > 0) {
+ statusBar.abortTransient(displayId, transientState.second);
+ }
+ statusBar.onSystemBarAppearanceChanged(displayId, appearance,
+ appearanceRegions, isNavbarColorManagedByIme);
statusBar.topAppWindowChanged(displayId, isFullscreen, isImmersive);
// TODO(b/118118435): Remove this after removing system UI visibilities.
@@ -3258,23 +3259,28 @@ public class DisplayPolicy {
return diff;
}
- private int updateLightStatusBarLw(int vis, WindowState opaque, WindowState opaqueOrDimming) {
- final boolean onKeyguard = isStatusBarKeyguard() && !isKeyguardOccluded();
- final WindowState statusColorWin = onKeyguard ? mStatusBar : opaqueOrDimming;
- if (statusColorWin != null && (statusColorWin == opaque || onKeyguard)) {
- // If the top fullscreen-or-dimming window is also the top fullscreen, respect
- // its light flag.
- vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
- vis |= PolicyControl.getSystemUiVisibility(statusColorWin, null)
- & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
- } else if (statusColorWin != null && statusColorWin.isDimming()) {
- // Otherwise if it's dimming, clear the light flag.
- vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
+ private static Pair<int[], int[]> getTransientState(int vis, int oldVis) {
+ final IntArray typesToShow = new IntArray(0);
+ final IntArray typesToAbort = new IntArray(0);
+ updateTransientState(vis, oldVis, View.STATUS_BAR_TRANSIENT, TYPE_TOP_BAR, typesToShow,
+ typesToAbort);
+ updateTransientState(vis, oldVis, View.NAVIGATION_BAR_TRANSIENT,
+ InsetsState.TYPE_NAVIGATION_BAR, typesToShow, typesToAbort);
+ return Pair.create(typesToShow.toArray(), typesToAbort.toArray());
+ }
+
+ private static void updateTransientState(int vis, int oldVis, int transientFlag,
+ @InternalInsetType int type, IntArray typesToShow, IntArray typesToAbort) {
+ final boolean wasTransient = (oldVis & transientFlag) != 0;
+ final boolean isTransient = (vis & transientFlag) != 0;
+ if (!wasTransient && isTransient) {
+ typesToShow.add(type);
+ } else if (wasTransient && !isTransient) {
+ typesToAbort.add(type);
}
- return vis;
}
- private int updateLightStatusBarAppearanceLw(int appearance, WindowState opaque,
+ private int updateLightStatusBarAppearanceLw(@Appearance int appearance, WindowState opaque,
WindowState opaqueOrDimming) {
final boolean onKeyguard = isStatusBarKeyguard() && !isKeyguardOccluded();
final WindowState statusColorWin = onKeyguard ? mStatusBar : opaqueOrDimming;
@@ -3282,7 +3288,10 @@ public class DisplayPolicy {
// If the top fullscreen-or-dimming window is also the top fullscreen, respect
// its light flag.
appearance &= ~APPEARANCE_LIGHT_TOP_BAR;
- appearance |= statusColorWin.mAttrs.insetsFlags.appearance & APPEARANCE_LIGHT_TOP_BAR;
+ final int legacyAppearance = InsetsFlags.getAppearance(
+ PolicyControl.getSystemUiVisibility(statusColorWin, null));
+ appearance |= (statusColorWin.mAttrs.insetsFlags.appearance | legacyAppearance)
+ & APPEARANCE_LIGHT_TOP_BAR;
} else if (statusColorWin != null && statusColorWin.isDimming()) {
// Otherwise if it's dimming, clear the light flag.
appearance &= ~APPEARANCE_LIGHT_TOP_BAR;
diff --git a/services/core/java/com/android/server/wm/RecentsAnimation.java b/services/core/java/com/android/server/wm/RecentsAnimation.java
index 2dae12642be3..01cbc5d1e880 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimation.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimation.java
@@ -211,9 +211,9 @@ class RecentsAnimation implements RecentsAnimationCallbacks,
// If there are multiple tasks in the target stack (ie. the home stack, with 3p
// and default launchers coexisting), then move the task to the top as a part of
// moving the stack to the front
- if (targetStack.topTask() != targetActivity.getTaskRecord()) {
- targetStack.addTask(targetActivity.getTaskRecord(), true /* toTop */,
- "startRecentsActivity");
+ final TaskRecord task = targetActivity.getTaskRecord();
+ if (targetStack.topTask() != task) {
+ targetStack.insertTaskAtTop(task, targetActivity);
}
} else {
// No recents activity, create the new recents activity bottom most
diff --git a/services/core/java/com/android/server/wm/RootActivityContainer.java b/services/core/java/com/android/server/wm/RootActivityContainer.java
index 51a3e7205489..dc78922ef4fc 100644
--- a/services/core/java/com/android/server/wm/RootActivityContainer.java
+++ b/services/core/java/com/android/server/wm/RootActivityContainer.java
@@ -1265,8 +1265,7 @@ class RootActivityContainer extends ConfigurationContainer
: task.realActivity != null ? task.realActivity.flattenToString()
: task.getTopActivity() != null ? task.getTopActivity().packageName
: "unknown";
- taskBounds[i] = new Rect();
- task.getWindowContainerBounds(taskBounds[i]);
+ taskBounds[i] = mService.getTaskBounds(task.mTaskId);
taskUserIds[i] = task.mUserId;
}
info.taskIds = taskIds;
@@ -1876,7 +1875,12 @@ class RootActivityContainer extends ConfigurationContainer
ActivityStack getNextFocusableStack(@NonNull ActivityStack currentFocus,
boolean ignoreCurrent) {
// First look for next focusable stack on the same display
- final ActivityDisplay preferredDisplay = currentFocus.getDisplay();
+ ActivityDisplay preferredDisplay = currentFocus.getDisplay();
+ if (preferredDisplay == null) {
+ // Stack is currently detached because it is being removed. Use the previous display it
+ // was on.
+ preferredDisplay = getActivityDisplay(currentFocus.mPrevDisplayId);
+ }
final ActivityStack preferredFocusableStack = preferredDisplay.getNextFocusableStack(
currentFocus, ignoreCurrent);
if (preferredFocusableStack != null) {
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index f5d3affa89ef..149bcfb991ea 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -206,7 +206,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
}
@Override
- void onChildPositionChanged() {
+ void onChildPositionChanged(WindowContainer child) {
mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL,
!mWmService.mPerDisplayFocusEnabled /* updateInputWindows */);
}
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 634990b5fdf2..dce15bc8acf8 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -16,6 +16,7 @@
package com.android.server.wm;
+import static android.app.ActivityTaskManager.INVALID_STACK_ID;
import static android.app.ActivityTaskManager.RESIZE_MODE_SYSTEM_SCREEN_ROTATION;
import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY;
import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY;
@@ -24,6 +25,7 @@ import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
import static android.content.res.Configuration.EMPTY;
import static android.view.SurfaceControl.METADATA_TASK_ID;
+import static com.android.server.EventLogTags.WM_TASK_CREATED;
import static com.android.server.EventLogTags.WM_TASK_REMOVED;
import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER;
import static com.android.server.wm.TaskProto.APP_WINDOW_TOKENS;
@@ -63,17 +65,21 @@ import java.util.function.Consumer;
class Task extends WindowContainer<ActivityRecord> implements ConfigurationContainerListener{
static final String TAG = TAG_WITH_CLASS_NAME ? "Task" : TAG_WM;
+ final ActivityTaskManagerService mAtmService;
+
// TODO: Track parent marks like this in WindowContainer.
TaskStack mStack;
/* Unique identifier for this task. */
final int mTaskId;
/* User for which this task was created. */
- final int mUserId;
+ // TODO: Make final
+ int mUserId;
final Rect mPreparedFrozenBounds = new Rect();
final Configuration mPreparedFrozenMergedConfig = new Configuration();
// If non-empty, bounds used to display the task during animations/interactions.
+ // TODO(b/119687367): This member is temporary.
private final Rect mOverrideDisplayedBounds = new Rect();
/** ID of the display which rotation {@link #mRotation} has. */
@@ -90,11 +96,12 @@ class Task extends WindowContainer<ActivityRecord> implements ConfigurationConta
private Rect mTmpRect2 = new Rect();
// Resize mode of the task. See {@link ActivityInfo#resizeMode}
- private int mResizeMode;
+ // Based on the {@link ActivityInfo#resizeMode} of the root activity.
+ int mResizeMode;
- // Whether the task supports picture-in-picture.
- // See {@link ActivityInfo#FLAG_SUPPORTS_PICTURE_IN_PICTURE}
- private boolean mSupportsPictureInPicture;
+ // Whether or not this task and its activities support PiP. Based on the
+ // {@link ActivityInfo#FLAG_SUPPORTS_PICTURE_IN_PICTURE} flag of the root activity.
+ boolean mSupportsPictureInPicture;
// Whether the task is currently being drag-resized
private boolean mDragResizing;
@@ -116,40 +123,23 @@ class Task extends WindowContainer<ActivityRecord> implements ConfigurationConta
/** @see #setCanAffectSystemUiFlags */
private boolean mCanAffectSystemUiFlags = true;
- // TODO: remove after unification
- TaskRecord mTaskRecord;
-
- // TODO: Remove after unification.
- @Override
- public void onConfigurationChanged(Configuration newParentConfig, boolean forwardToChildren) {
- // Forward configuration changes in cases
- // - children won't get it from TaskRecord
- // - it's a pinned task
- forwardToChildren &= (mTaskRecord == null) || inPinnedWindowingMode();
- super.onConfigurationChanged(newParentConfig, forwardToChildren);
- }
-
- Task(int taskId, TaskStack stack, int userId, WindowManagerService service, int resizeMode,
- boolean supportsPictureInPicture, TaskDescription taskDescription,
- TaskRecord taskRecord) {
- super(service);
+ Task(int taskId, TaskStack stack, int userId, int resizeMode, boolean supportsPictureInPicture,
+ TaskDescription taskDescription, ActivityTaskManagerService atm) {
+ super(atm.mWindowManager);
+ mAtmService = atm;
mTaskId = taskId;
mStack = stack;
mUserId = userId;
mResizeMode = resizeMode;
mSupportsPictureInPicture = supportsPictureInPicture;
- mTaskRecord = taskRecord;
mTaskDescription = taskDescription;
+ EventLog.writeEvent(WM_TASK_CREATED, mTaskId,
+ stack != null ? stack.mStackId : INVALID_STACK_ID);
// Tasks have no set orientation value (including SCREEN_ORIENTATION_UNSPECIFIED).
setOrientation(SCREEN_ORIENTATION_UNSET);
- if (mTaskRecord != null) {
- // This can be null when we call createTaskInStack in WindowTestUtils. Remove this after
- // unification.
- mTaskRecord.registerConfigurationChangeListener(this);
- } else {
- setBounds(getResolvedOverrideBounds());
- }
+ // TODO(task-merge): Is this really needed?
+ setBounds(getResolvedOverrideBounds());
}
@Override
@@ -157,37 +147,40 @@ class Task extends WindowContainer<ActivityRecord> implements ConfigurationConta
return mStack != null ? mStack.getDisplayContent() : null;
}
- private int getAdjustedAddPosition(int suggestedPosition) {
- final int size = mChildren.size();
- if (suggestedPosition >= size) {
- return Math.min(size, suggestedPosition);
+ int getAdjustedAddPosition(ActivityRecord r, int suggestedPosition) {
+ int maxPosition = mChildren.size();
+ if (!r.mTaskOverlay) {
+ // We want to place all non-overlay activities below overlays.
+ while (maxPosition > 0) {
+ final ActivityRecord current = mChildren.get(maxPosition - 1);
+ if (current.mTaskOverlay && !current.removed) {
+ --maxPosition;
+ continue;
+ }
+ break;
+ }
+ if (maxPosition < 0) {
+ maxPosition = 0;
+ }
}
- for (int pos = 0; pos < size && pos < suggestedPosition; ++pos) {
+ if (suggestedPosition >= maxPosition) {
+ return Math.min(maxPosition, suggestedPosition);
+ }
+
+ for (int pos = 0; pos < maxPosition && pos < suggestedPosition; ++pos) {
// TODO: Confirm that this is the behavior we want long term.
if (mChildren.get(pos).removed) {
// suggestedPosition assumes removed tokens are actually gone.
++suggestedPosition;
}
}
- return Math.min(size, suggestedPosition);
- }
-
- @Override
- void addChild(ActivityRecord child, int position) {
- position = getAdjustedAddPosition(position);
- super.addChild(child, position);
-
- // Inform the TaskRecord side of the child addition
- // TODO(task-unify): Will be removed after task unification.
- if (mTaskRecord != null) {
- mTaskRecord.onChildAdded(child, position);
- }
+ return Math.min(maxPosition, suggestedPosition);
}
@Override
void positionChildAt(int position, ActivityRecord child, boolean includingParents) {
- position = getAdjustedAddPosition(position);
+ position = getAdjustedAddPosition(child, position);
super.positionChildAt(position, child, includingParents);
}
@@ -222,47 +215,34 @@ class Task extends WindowContainer<ActivityRecord> implements ConfigurationConta
void removeImmediately() {
if (DEBUG_STACK) Slog.i(TAG, "removeTask: removing taskId=" + mTaskId);
EventLog.writeEvent(WM_TASK_REMOVED, mTaskId, "removeTask");
- if (mTaskRecord != null) {
- mTaskRecord.unregisterConfigurationChangeListener(this);
- }
-
super.removeImmediately();
}
- void reparent(TaskStack stack, int position, boolean moveParents) {
- if (stack == mStack) {
- throw new IllegalArgumentException(
- "task=" + this + " already child of stack=" + mStack);
- }
- if (stack == null) {
- throw new IllegalArgumentException("reparent: could not find stack.");
- }
+ // TODO: Consolidate this with TaskRecord.reparent()
+ void reparent(TaskStack stack, int position, boolean moveParents, String reason) {
if (DEBUG_STACK) Slog.i(TAG, "reParentTask: removing taskId=" + mTaskId
+ " from stack=" + mStack);
EventLog.writeEvent(WM_TASK_REMOVED, mTaskId, "reParentTask");
- final DisplayContent prevDisplayContent = getDisplayContent();
-
- // If we are moving from the fullscreen stack to the pinned stack
- // then we want to preserve our insets so that there will not
- // be a jump in the area covered by system decorations. We rely
- // on the pinned animation to later unset this value.
- if (stack.inPinnedWindowingMode()) {
- mPreserveNonFloatingState = true;
- } else {
- mPreserveNonFloatingState = false;
- }
- getParent().removeChild(this);
- stack.addTask(this, position, showForAllUsers(), moveParents);
+ final ActivityStack prevStack = mStack.mActivityStack;
+ final boolean wasTopFocusedStack =
+ mAtmService.mRootActivityContainer.isTopDisplayFocusedStack(prevStack);
+ final ActivityDisplay prevStackDisplay = prevStack.getDisplay();
- // Relayout display(s).
- final DisplayContent displayContent = stack.getDisplayContent();
- displayContent.setLayoutNeeded();
- if (prevDisplayContent != displayContent) {
- onDisplayChanged(displayContent);
- prevDisplayContent.setLayoutNeeded();
+ reparent(stack, position);
+
+ if (!moveParents) {
+ // Only move home stack forward if we are not going to move the new parent forward.
+ prevStack.moveHomeStackToFrontIfNeeded(wasTopFocusedStack, prevStackDisplay, reason);
}
- getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
+
+ mStack = stack;
+ stack.positionChildAt(position, this, moveParents);
+
+ // If we are moving from the fullscreen stack to the pinned stack then we want to preserve
+ // our insets so that there will not be a jump in the area covered by system decorations.
+ // We rely on the pinned animation to later unset this value.
+ mPreserveNonFloatingState = stack.inPinnedWindowingMode();
}
/** @see ActivityTaskManagerService#positionTaskInStack(int, int, int). */
@@ -270,46 +250,6 @@ class Task extends WindowContainer<ActivityRecord> implements ConfigurationConta
mStack.positionChildAt(position, this, false /* includingParents */);
}
- @Override
- void onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent) {
- super.onParentChanged(newParent, oldParent);
-
- // Update task bounds if needed.
- adjustBoundsForDisplayChangeIfNeeded(getDisplayContent());
-
- if (getWindowConfiguration().windowsAreScaleable()) {
- // We force windows out of SCALING_MODE_FREEZE so that we can continue to animate them
- // while a resize is pending.
- forceWindowsScaleable(true /* force */);
- } else {
- forceWindowsScaleable(false /* force */);
- }
- }
-
- @Override
- void removeChild(ActivityRecord child) {
- if (!mChildren.contains(child)) {
- Slog.e(TAG, "removeChild: token=" + this + " not found.");
- return;
- }
-
- super.removeChild(child);
-
- // Inform the TaskRecord side of the child removal
- // TODO(task-unify): Will be removed after task unification.
- if (mTaskRecord != null) {
- mTaskRecord.onChildRemoved(child);
- }
-
- // TODO(task-unify): Need to make this account for what we are doing in
- // ActivityRecord.removeFromHistory so that the task isn't removed in some situations when
- // we unify task level.
- if (mChildren.isEmpty()) {
- EventLog.writeEvent(WM_TASK_REMOVED, mTaskId, "removeActivity: last activity");
- removeIfPossible();
- }
- }
-
void setSendingToBottom(boolean toBottom) {
for (int appTokenNdx = 0; appTokenNdx < mChildren.size(); appTokenNdx++) {
mChildren.get(appTokenNdx).sendingToBottom = toBottom;
@@ -331,7 +271,7 @@ class Task extends WindowContainer<ActivityRecord> implements ConfigurationConta
@Override
public int setBounds(Rect bounds) {
int rotation = Surface.ROTATION_0;
- final DisplayContent displayContent = mStack.getDisplayContent();
+ final DisplayContent displayContent = mStack != null ? mStack.getDisplayContent() : null;
if (displayContent != null) {
rotation = displayContent.getDisplayInfo().rotation;
} else if (bounds == null) {
@@ -355,9 +295,8 @@ class Task extends WindowContainer<ActivityRecord> implements ConfigurationConta
// No one in higher hierarchy handles this request, let's adjust our bounds to fulfill
// it if possible.
- // TODO: Move to TaskRecord after unification is done.
- if (mTaskRecord != null && mTaskRecord.getParent() != null) {
- mTaskRecord.onConfigurationChanged(mTaskRecord.getParent().getConfiguration());
+ if (getParent() != null) {
+ onConfigurationChanged(getParent().getConfiguration());
return true;
}
return false;
@@ -379,8 +318,9 @@ class Task extends WindowContainer<ActivityRecord> implements ConfigurationConta
}
/**
- * Sets bounds that override where the task is displayed. Used during transient operations
- * like animation / interaction.
+ * Displayed bounds are used to set where the task is drawn at any given time. This is
+ * separate from its actual bounds so that the app doesn't see any meaningful configuration
+ * changes during transitionary periods.
*/
void setOverrideDisplayedBounds(Rect overrideDisplayedBounds) {
if (overrideDisplayedBounds != null) {
@@ -399,13 +339,13 @@ class Task extends WindowContainer<ActivityRecord> implements ConfigurationConta
return mOverrideDisplayedBounds;
}
- void setResizeable(int resizeMode) {
- mResizeMode = resizeMode;
+ boolean isResizeable(boolean checkSupportsPip) {
+ return (mAtmService.mForceResizableActivities || ActivityInfo.isResizeableMode(mResizeMode)
+ || (checkSupportsPip && mSupportsPictureInPicture));
}
boolean isResizeable() {
- return ActivityInfo.isResizeableMode(mResizeMode) || mSupportsPictureInPicture
- || mWmService.mAtmService.mForceResizableActivities;
+ return isResizeable(true /* checkSupportsPip */);
}
/**
@@ -462,6 +402,10 @@ class Task extends WindowContainer<ActivityRecord> implements ConfigurationConta
}
}
+ /**
+ * Gets the current overridden displayed bounds. These will be empty if the task is not
+ * currently overriding where it is displayed.
+ */
@Override
public Rect getDisplayedBounds() {
if (mOverrideDisplayedBounds.isEmpty()) {
@@ -577,7 +521,7 @@ class Task extends WindowContainer<ActivityRecord> implements ConfigurationConta
setDragResizing(resizing, DRAG_RESIZE_MODE_DOCKED_DIVIDER);
}
- private void adjustBoundsForDisplayChangeIfNeeded(final DisplayContent displayContent) {
+ void adjustBoundsForDisplayChangeIfNeeded(final DisplayContent displayContent) {
if (displayContent == null) {
return;
}
@@ -618,9 +562,7 @@ class Task extends WindowContainer<ActivityRecord> implements ConfigurationConta
displayContent.rotateBounds(mRotation, newRotation, mTmpRect2);
if (setBounds(mTmpRect2) != BOUNDS_CHANGE_NONE) {
- if (mTaskRecord != null) {
- mTaskRecord.requestResize(getBounds(), RESIZE_MODE_SYSTEM_SCREEN_ROTATION);
- }
+ mAtmService.resizeTask(mTaskId, getBounds(), RESIZE_MODE_SYSTEM_SCREEN_ROTATION);
}
}
@@ -758,7 +700,8 @@ class Task extends WindowContainer<ActivityRecord> implements ConfigurationConta
}
void onSnapshotChanged(ActivityManager.TaskSnapshot snapshot) {
- mTaskRecord.onSnapshotChanged(snapshot);
+ mAtmService.getTaskChangeNotificationController().notifyTaskSnapshotChanged(
+ mTaskId, snapshot);
}
TaskDescription getTaskDescription() {
@@ -794,11 +737,6 @@ class Task extends WindowContainer<ActivityRecord> implements ConfigurationConta
mDimmer.dontAnimateExit();
}
- @Override
- public String toString() {
- return "{taskId=" + mTaskId + " appTokens=" + mChildren + "}";
- }
-
String getName() {
return toShortString();
}
@@ -825,9 +763,8 @@ class Task extends WindowContainer<ActivityRecord> implements ConfigurationConta
}
}
- @CallSuper
- @Override
- public void writeToProto(ProtoOutputStream proto, long fieldId,
+ // TODO(proto-merge): Remove once protos for TaskRecord and Task are merged.
+ void writeToProtoInnerTaskOnly(ProtoOutputStream proto, long fieldId,
@WindowTraceLogLevel int logLevel) {
if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible()) {
return;
@@ -843,8 +780,10 @@ class Task extends WindowContainer<ActivityRecord> implements ConfigurationConta
proto.write(FILLS_PARENT, matchParentBounds());
getBounds().writeToProto(proto, BOUNDS);
mOverrideDisplayedBounds.writeToProto(proto, DISPLAYED_BOUNDS);
- proto.write(SURFACE_WIDTH, mSurfaceControl.getWidth());
- proto.write(SURFACE_HEIGHT, mSurfaceControl.getHeight());
+ if (mSurfaceControl != null) {
+ proto.write(SURFACE_WIDTH, mSurfaceControl.getWidth());
+ proto.write(SURFACE_HEIGHT, mSurfaceControl.getHeight());
+ }
proto.end(token);
}
diff --git a/services/core/java/com/android/server/wm/TaskRecord.java b/services/core/java/com/android/server/wm/TaskRecord.java
index 6920d9d3a770..672827fbb5ee 100644
--- a/services/core/java/com/android/server/wm/TaskRecord.java
+++ b/services/core/java/com/android/server/wm/TaskRecord.java
@@ -52,11 +52,10 @@ import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.provider.Settings.Secure.USER_SETUP_COMPLETE;
import static android.view.Display.DEFAULT_DISPLAY;
-import static com.android.server.EventLogTags.WM_TASK_CREATED;
+import static com.android.server.EventLogTags.WM_TASK_REMOVED;
import static com.android.server.am.TaskRecordProto.ACTIVITIES;
import static com.android.server.am.TaskRecordProto.ACTIVITY_TYPE;
import static com.android.server.am.TaskRecordProto.BOUNDS;
-import static com.android.server.am.TaskRecordProto.CONFIGURATION_CONTAINER;
import static com.android.server.am.TaskRecordProto.FULLSCREEN;
import static com.android.server.am.TaskRecordProto.ID;
import static com.android.server.am.TaskRecordProto.LAST_NON_FULLSCREEN_BOUNDS;
@@ -66,11 +65,9 @@ import static com.android.server.am.TaskRecordProto.ORIG_ACTIVITY;
import static com.android.server.am.TaskRecordProto.REAL_ACTIVITY;
import static com.android.server.am.TaskRecordProto.RESIZE_MODE;
import static com.android.server.am.TaskRecordProto.STACK_ID;
+import static com.android.server.am.TaskRecordProto.TASK;
import static com.android.server.wm.ActivityRecord.FINISH_RESULT_REMOVED;
import static com.android.server.wm.ActivityRecord.STARTING_WINDOW_SHOWN;
-import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
-import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_MOVING;
-import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_MOVING_TO_TOP;
import static com.android.server.wm.ActivityStackSupervisor.ON_TOP;
import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS;
import static com.android.server.wm.ActivityStackSupervisor.REMOVE_FROM_RECENTS;
@@ -85,10 +82,6 @@ import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_TASKS
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
-import static com.android.server.wm.WindowContainer.POSITION_BOTTOM;
-import static com.android.server.wm.WindowContainer.POSITION_TOP;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
-import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import static java.lang.Integer.MAX_VALUE;
@@ -143,7 +136,7 @@ import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Objects;
-class TaskRecord extends ConfigurationContainer {
+class TaskRecord extends Task {
private static final String TAG = TAG_WITH_CLASS_NAME ? "TaskRecord" : TAG_ATM;
private static final String TAG_ADD_REMOVE = TAG + POSTFIX_ADD_REMOVE;
private static final String TAG_RECENTS = TAG + POSTFIX_RECENTS;
@@ -212,7 +205,6 @@ class TaskRecord extends ConfigurationContainer {
*/
private static TaskRecordFactory sTaskRecordFactory;
- final int mTaskId; // Unique identifier for this task.
String affinity; // The affinity name for this task, or null; may change identity.
String rootAffinity; // Initial base affinity, or null; does not change from initial root.
final IVoiceInteractionSession voiceSession; // Voice interaction session driving task
@@ -238,17 +230,11 @@ class TaskRecord extends ConfigurationContainer {
boolean hasBeenVisible; // Set if any activities in the task have been visible to the user.
String stringName; // caching of toString() result.
- int mUserId; // user for which this task was created
boolean mUserSetupComplete; // The user set-up is complete as of the last time the task activity
// was changed.
int numFullscreen; // Number of fullscreen activities.
- int mResizeMode; // The resize mode of this task and its activities.
- // Based on the {@link ActivityInfo#resizeMode} of the root activity.
- private boolean mSupportsPictureInPicture; // Whether or not this task and its activities
- // support PiP. Based on the {@link ActivityInfo#FLAG_SUPPORTS_PICTURE_IN_PICTURE} flag
- // of the root activity.
/** Can't be put in lockTask mode. */
final static int LOCK_TASK_AUTH_DONT_LOCK = 0;
/** Can enter app pinning with user approval. Can never start over existing lockTask task. */
@@ -264,13 +250,6 @@ class TaskRecord extends ConfigurationContainer {
int mLockTaskUid = -1; // The uid of the application that called startLockTask().
- // This represents the last resolved activity values for this task
- // NOTE: This value needs to be persisted with each task
- TaskDescription mTaskDescription;
-
- /** List of all activities in the task arranged in history order */
- final ArrayList<ActivityRecord> mActivities;
-
/** Current stack. Setter must always be used to update the value. */
private ActivityStack mStack;
@@ -308,8 +287,6 @@ class TaskRecord extends ConfigurationContainer {
int mCallingUid;
String mCallingPackage;
- final ActivityTaskManagerService mAtmService;
-
private final Rect mTmpStableBounds = new Rect();
private final Rect mTmpNonDecorBounds = new Rect();
private final Rect mTmpBounds = new Rect();
@@ -328,17 +305,9 @@ class TaskRecord extends ConfigurationContainer {
// This number will be assigned when we evaluate OOM scores for all visible tasks.
int mLayerRank = -1;
- // When non-empty, this represents the bounds this task will be drawn at. This gets set during
- // transient operations such as split-divider dragging and animations.
- // TODO(b/119687367): This member is temporary.
- final Rect mDisplayedBounds = new Rect();
-
/** Helper object used for updating override configuration. */
private Configuration mTmpConfig = new Configuration();
- // TODO: remove after unification
- Task mTask;
-
/** Used by fillTaskInfo */
final TaskActivitiesReport mReuseActivitiesReport = new TaskActivitiesReport();
@@ -346,21 +315,21 @@ class TaskRecord extends ConfigurationContainer {
* Don't use constructor directly. Use {@link #create(ActivityTaskManagerService, int,
* ActivityInfo, Intent, TaskDescription)} instead.
*/
- TaskRecord(ActivityTaskManagerService atmService, int _taskId, ActivityInfo info,
- Intent _intent, IVoiceInteractionSession _voiceSession,
- IVoiceInteractor _voiceInteractor, TaskDescription _taskDescription) {
+ TaskRecord(ActivityTaskManagerService atmService, int _taskId, ActivityInfo info, Intent _intent,
+ IVoiceInteractionSession _voiceSession, IVoiceInteractor _voiceInteractor,
+ TaskDescription _taskDescription, ActivityStack stack) {
this(atmService, _taskId, _intent, null /*_affinityIntent*/, null /*_affinity*/,
null /*_rootAffinity*/, null /*_realActivity*/, null /*_origActivity*/,
false /*_rootWasReset*/, false /*_autoRemoveRecents*/, false /*_askedCompatMode*/,
UserHandle.getUserId(info.applicationInfo.uid), 0 /*_effectiveUid*/,
- null /*_lastDescription*/, new ArrayList<>(), System.currentTimeMillis(),
+ null /*_lastDescription*/, System.currentTimeMillis(),
true /*neverRelinquishIdentity*/,
_taskDescription != null ? _taskDescription : new TaskDescription(),
_taskId, INVALID_TASK_ID, INVALID_TASK_ID, 0 /*taskAffiliationColor*/,
info.applicationInfo.uid, info.packageName, info.resizeMode,
info.supportsPictureInPicture(), false /*_realActivitySuspended*/,
false /*userSetupComplete*/, INVALID_MIN_SIZE, INVALID_MIN_SIZE, info,
- _voiceSession, _voiceInteractor);
+ _voiceSession, _voiceInteractor, stack);
}
/** Don't use constructor directly. This is only used by XML parser. */
@@ -368,15 +337,16 @@ class TaskRecord extends ConfigurationContainer {
Intent _affinityIntent, String _affinity, String _rootAffinity,
ComponentName _realActivity, ComponentName _origActivity, boolean _rootWasReset,
boolean _autoRemoveRecents, boolean _askedCompatMode, int _userId,
- int _effectiveUid, String _lastDescription, ArrayList<ActivityRecord> activities,
+ int _effectiveUid, String _lastDescription,
long lastTimeMoved, boolean neverRelinquishIdentity,
TaskDescription _lastTaskDescription, int taskAffiliation, int prevTaskId,
int nextTaskId, int taskAffiliationColor, int callingUid, String callingPackage,
int resizeMode, boolean supportsPictureInPicture, boolean _realActivitySuspended,
boolean userSetupComplete, int minWidth, int minHeight, ActivityInfo info,
- IVoiceInteractionSession _voiceSession, IVoiceInteractor _voiceInteractor) {
- mAtmService = atmService;
- mTaskId = _taskId;
+ IVoiceInteractionSession _voiceSession, IVoiceInteractor _voiceInteractor,
+ ActivityStack stack) {
+ super(_taskId, stack != null ? stack.mTaskStack : null, _userId, resizeMode,
+ supportsPictureInPicture, _lastTaskDescription, atmService);
mRemoteToken = new RemoteToken(this);
affinityIntent = _affinityIntent;
affinity = _affinity;
@@ -390,15 +360,12 @@ class TaskRecord extends ConfigurationContainer {
isAvailable = true;
autoRemoveRecents = _autoRemoveRecents;
askedCompatMode = _askedCompatMode;
- mUserId = _userId;
mUserSetupComplete = userSetupComplete;
effectiveUid = _effectiveUid;
touchActiveTime();
lastDescription = _lastDescription;
- mActivities = activities;
mLastTimeMoved = lastTimeMoved;
mNeverRelinquishIdentity = neverRelinquishIdentity;
- mTaskDescription = _lastTaskDescription;
mAffiliatedTaskId = taskAffiliation;
mAffiliatedTaskColor = taskAffiliationColor;
mPrevAffiliateTaskId = prevTaskId;
@@ -406,7 +373,6 @@ class TaskRecord extends ConfigurationContainer {
mCallingUid = callingUid;
mCallingPackage = callingPackage;
mResizeMode = resizeMode;
- mSupportsPictureInPicture = supportsPictureInPicture;
if (info != null) {
setIntent(_intent, info);
setMinDimensions(info);
@@ -418,39 +384,6 @@ class TaskRecord extends ConfigurationContainer {
mAtmService.getTaskChangeNotificationController().notifyTaskCreated(_taskId, realActivity);
}
- Task getTask() {
- return mTask;
- }
-
- void createTask(boolean onTop, boolean showForAllUsers) {
- if (mTask != null) {
- throw new IllegalArgumentException("mTask=" + mTask
- + " already created for task=" + this);
- }
-
- final Rect bounds = updateOverrideConfigurationFromLaunchBounds();
- final TaskStack stack = getStack().getTaskStack();
-
- if (stack == null) {
- throw new IllegalArgumentException("TaskRecord: invalid stack=" + mStack);
- }
- EventLog.writeEvent(WM_TASK_CREATED, mTaskId, stack.mStackId);
- mTask = new Task(mTaskId, stack, mUserId, mAtmService.mWindowManager, mResizeMode,
- mSupportsPictureInPicture, mTaskDescription, this);
- final int position = onTop ? POSITION_TOP : POSITION_BOTTOM;
-
- if (!mDisplayedBounds.isEmpty()) {
- mTask.setOverrideDisplayedBounds(mDisplayedBounds);
- }
- // We only want to move the parents to the parents if we are creating this task at the
- // top of its stack.
- stack.addTask(mTask, position, showForAllUsers, onTop /* moveParents */);
- }
-
- void setTask(Task task) {
- mTask = task;
- }
-
void cleanUpResourcesForDestroy() {
if (hasChild()) {
return;
@@ -473,60 +406,33 @@ class TaskRecord extends ConfigurationContainer {
mAtmService.mStackSupervisor.mRecentTasks.remove(this);
}
- removeWindowContainer();
+ removeIfPossible();
}
@VisibleForTesting
- void removeWindowContainer() {
+ @Override
+ void removeIfPossible() {
mAtmService.getLockTaskController().clearLockedTask(this);
- if (mTask == null) {
- if (DEBUG_STACK) Slog.i(TAG_WM, "removeTask: could not find taskId=" + mTaskId);
- return;
- }
- mTask.removeIfPossible();
- mTask = null;
- if (!getWindowConfiguration().persistTaskBounds()) {
- // Reset current bounds for task whose bounds shouldn't be persisted so it uses
- // default configuration the next time it launches.
- setBounds(null);
- }
+ super.removeIfPossible();
mAtmService.getTaskChangeNotificationController().notifyTaskRemoved(mTaskId);
}
- void onSnapshotChanged(TaskSnapshot snapshot) {
- mAtmService.getTaskChangeNotificationController().notifyTaskSnapshotChanged(mTaskId, snapshot);
- }
-
void setResizeMode(int resizeMode) {
if (mResizeMode == resizeMode) {
return;
}
mResizeMode = resizeMode;
- mTask.setResizeable(resizeMode);
mAtmService.mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
mAtmService.mRootActivityContainer.resumeFocusedStacksTopActivities();
}
- void setTaskDockedResizing(boolean resizing) {
- if (mTask == null) {
- Slog.w(TAG_WM, "setTaskDockedResizing: taskId " + mTaskId + " not found.");
- return;
- }
- mTask.setTaskDockedResizing(resizing);
- }
-
- // TODO: Consolidate this with the resize() method below.
- public void requestResize(Rect bounds, int resizeMode) {
- mAtmService.resizeTask(mTaskId, bounds, resizeMode);
- }
-
boolean resize(Rect bounds, int resizeMode, boolean preserveWindow, boolean deferResume) {
mAtmService.deferWindowLayout();
try {
final boolean forced = (resizeMode & RESIZE_MODE_FORCED) != 0;
- if (mTask == null) {
+ if (getParent() == null) {
// Task doesn't exist in window manager yet (e.g. was restored from recents).
// All we can do for now is update the bounds so it can be used when the task is
// added to window manager.
@@ -577,7 +483,7 @@ class TaskRecord extends ConfigurationContainer {
}
}
}
- mTask.resize(kept, forced);
+ resize(kept, forced);
saveLaunchingStateIfNeeded();
@@ -588,19 +494,6 @@ class TaskRecord extends ConfigurationContainer {
}
}
- // TODO: Investigate combining with the resize() method above.
- void resizeWindowContainer() {
- mTask.resize(false /* relayout */, false /* forced */);
- }
-
- void getWindowContainerBounds(Rect bounds) {
- if (mTask != null) {
- mTask.getBounds(bounds);
- } else {
- bounds.setEmpty();
- }
- }
-
/**
* Convenience method to reparent a task to the top or bottom position of the stack.
*/
@@ -708,32 +601,16 @@ class TaskRecord extends ConfigurationContainer {
// Adjust the position for the new parent stack as needed.
position = toStack.getAdjustedPositionForTask(this, position, null /* starting */);
- // Must reparent first in window manager to avoid a situation where AM can delete the
- // we are coming from in WM before we reparent because it became empty.
- mTask.reparent(toStack.getTaskStack(), position,
- moveStackMode == REPARENT_MOVE_STACK_TO_FRONT);
-
final boolean moveStackToFront = moveStackMode == REPARENT_MOVE_STACK_TO_FRONT
|| (moveStackMode == REPARENT_KEEP_STACK_AT_FRONT && (wasFocused || wasFront));
- // Move the task
- sourceStack.removeTask(this, reason, moveStackToFront
- ? REMOVE_TASK_MODE_MOVING_TO_TOP : REMOVE_TASK_MODE_MOVING);
- toStack.addTask(this, position, false /* schedulePictureInPictureModeChange */, reason);
+
+ reparent(toStack.getTaskStack(), position, moveStackToFront, reason);
if (schedulePictureInPictureModeChange) {
// Notify of picture-in-picture mode changes
supervisor.scheduleUpdatePictureInPictureModeIfNeeded(this, sourceStack);
}
- // TODO: Ensure that this is actually necessary here
- // Notify the voice session if required
- if (voiceSession != null) {
- try {
- voiceSession.taskStarted(intent, mTaskId);
- } catch (RemoteException e) {
- }
- }
-
// If the task had focus before (or we're requested to move focus), move focus to the
// new stack by moving the stack to the front.
if (r != null) {
@@ -809,14 +686,6 @@ class TaskRecord extends ConfigurationContainer {
|| targetWindowingMode == WINDOWING_MODE_FREEFORM;
}
- void cancelWindowTransition() {
- if (mTask == null) {
- Slog.w(TAG_WM, "cancelWindowTransition: taskId " + mTaskId + " not found.");
- return;
- }
- mTask.cancelTaskWindowTransition();
- }
-
/**
* DO NOT HOLD THE ACTIVITY MANAGER LOCK WHEN CALLING THIS METHOD!
*/
@@ -970,65 +839,103 @@ class TaskRecord extends ConfigurationContainer {
return (T) mStack;
}
- /**
- * Must be used for setting parent stack because it performs configuration updates.
- * Must be called after adding task as a child to the stack.
- */
- // TODO(task-unify): Remove or rework after task level unification.
- void setStack(ActivityStack stack) {
- if (stack != null && !stack.isInStackLocked(this)) {
- throw new IllegalStateException("Task must be added as a Stack child first.");
- }
- final ActivityStack oldStack = mStack;
- mStack = stack;
+ // TODO(stack-unify): Can be removed on stack unified.
+ void onParentChanged(ActivityStack newParent, ActivityStack oldParent) {
+ onParentChanged(
+ newParent != null ? newParent.mTaskStack : null,
+ oldParent != null ? oldParent.mTaskStack : null);
+ }
+
+ @Override
+ void onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent) {
+ final ActivityStack oldStack = (oldParent != null)
+ ? ((TaskStack) oldParent).mActivityStack : null;
+ final ActivityStack newStack = (newParent != null)
+ ? ((TaskStack) newParent).mActivityStack : null;
+
+ mStack = newStack;
- // If the new {@link TaskRecord} is from a different {@link ActivityStack}, remove this
- // {@link ActivityRecord} from its current {@link ActivityStack}.
+ super.onParentChanged(newParent, oldParent);
- if (oldStack != mStack) {
+ if (oldStack != null) {
for (int i = getChildCount() - 1; i >= 0; --i) {
final ActivityRecord activity = getChildAt(i);
+ oldStack.onActivityRemovedFromStack(activity);
+ }
- if (oldStack != null) {
- oldStack.onActivityRemovedFromStack(activity);
- }
+ updateTaskMovement(true /*toFront*/);
- if (mStack != null) {
- stack.onActivityAddedToStack(activity);
+ if (oldStack.inPinnedWindowingMode()
+ && (newStack == null || !newStack.inPinnedWindowingMode())) {
+ // Notify if a task from the pinned stack is being removed
+ // (or moved depending on the mode).
+ mAtmService.getTaskChangeNotificationController().notifyActivityUnpinned();
+ }
+ }
+
+ if (newStack != null) {
+ for (int i = getChildCount() - 1; i >= 0; --i) {
+ final ActivityRecord activity = getChildAt(i);
+ newStack.onActivityAddedToStack(activity);
+ }
+
+ // TODO: Ensure that this is actually necessary here
+ // Notify the voice session if required
+ if (voiceSession != null) {
+ try {
+ voiceSession.taskStarted(intent, mTaskId);
+ } catch (RemoteException e) {
}
}
}
- onParentChanged(mStack, oldStack);
- }
+ // First time we are adding the task to the system.
+ if (oldParent == null && newParent != null) {
- /**
- * @return Id of current stack, {@link INVALID_STACK_ID} if no stack is set.
- */
- int getStackId() {
- return mStack != null ? mStack.mStackId : INVALID_STACK_ID;
- }
+ // TODO: Super random place to be doing this, but aligns with what used to be done
+ // before we unified Task level. Look into if this can be done in a better place.
+ updateOverrideConfigurationFromLaunchBounds();
+ }
- @Override
- protected int getChildCount() {
- return mActivities.size();
- }
+ // Task is being removed.
+ if (oldParent != null && newParent == null) {
+ cleanUpResourcesForDestroy();
+ }
- @Override
- protected ActivityRecord getChildAt(int index) {
- return mActivities.get(index);
+
+ // Update task bounds if needed.
+ adjustBoundsForDisplayChangeIfNeeded(getDisplayContent());
+
+ if (getWindowConfiguration().windowsAreScaleable()) {
+ // We force windows out of SCALING_MODE_FREEZE so that we can continue to animate them
+ // while a resize is pending.
+ forceWindowsScaleable(true /* force */);
+ } else {
+ forceWindowsScaleable(false /* force */);
+ }
+
+ mAtmService.mRootActivityContainer.updateUIDsPresentOnDisplay();
}
- @Override
- protected ConfigurationContainer getParent() {
- return mStack;
+ /** TODO(task-merge): Consolidate into {@link TaskStack#onChildPositionChanged}. */
+ void updateTaskMovement(boolean toFront) {
+ if (isPersistable) {
+ mLastTimeMoved = System.currentTimeMillis();
+ // Sign is used to keep tasks sorted when persisted. Tasks sent to the bottom most
+ // recently will be most negative, tasks sent to the bottom before that will be less
+ // negative. Similarly for recent tasks moved to the top which will be most positive.
+ if (!toFront) {
+ mLastTimeMoved *= -1;
+ }
+ }
+ mAtmService.mRootActivityContainer.invalidateTaskLayers();
}
- @Override
- protected void onParentChanged(
- ConfigurationContainer newParent, ConfigurationContainer oldParent) {
- super.onParentChanged(newParent, oldParent);
- mAtmService.mRootActivityContainer.updateUIDsPresentOnDisplay();
+ /**
+ * @return Id of current stack, {@link ActivityTaskManager#INVALID_STACK_ID} if no stack is set.
+ */
+ int getStackId() {
+ return mStack != null ? mStack.mStackId : INVALID_STACK_ID;
}
// Close up recents linked list.
@@ -1121,16 +1028,6 @@ class TaskRecord extends ConfigurationContainer {
return null;
}
- boolean isVisible() {
- for (int i = getChildCount() - 1; i >= 0; --i) {
- final ActivityRecord r = getChildAt(i);
- if (r.visible) {
- return true;
- }
- }
- return false;
- }
-
/**
* Return true if any activities in this task belongs to input uid.
*/
@@ -1210,15 +1107,10 @@ class TaskRecord extends ConfigurationContainer {
* Reorder the history stack so that the passed activity is brought to the front.
*/
final void moveActivityToFrontLocked(ActivityRecord newTop) {
- if (DEBUG_ADD_REMOVE) Slog.i(TAG_ADD_REMOVE,
- "Removing and adding activity " + newTop
- + " to stack at top callers=" + Debug.getCallers(4));
-
- mActivities.remove(newTop);
- mActivities.add(newTop);
+ if (DEBUG_ADD_REMOVE) Slog.i(TAG_ADD_REMOVE, "Removing and adding activity "
+ + newTop + " to stack at top callers=" + Debug.getCallers(4));
- // Make sure window manager is aware of the position change.
- mTask.positionChildAtTop(newTop);
+ positionChildAtTop(newTop);
updateEffectiveIntent();
}
@@ -1232,19 +1124,29 @@ class TaskRecord extends ConfigurationContainer {
return getChildAt(0).getActivityType();
}
- /** Called when a Task child is added from the Task.java side. */
- // TODO(task-unify): Just override addChild to do what is needed when someone calls to add a
- // child.
- void onChildAdded(ActivityRecord r, int index) {
+ @Override
+ void addChild(ActivityRecord r, int index) {
+ if (r.getParent() != null) {
+ // Shouldn't already have a parent since we are just adding to the task...Maybe you
+ // meant to use reparent?
+ throw new IllegalStateException(
+ "r=" + r + " parent=" + r.getParent() + " task=" + this);
+ }
+
+ // If this task had any child before we added this one.
+ boolean hadChild = hasChild();
+
+ index = getAdjustedAddPosition(r, index);
+ super.addChild(r, index);
+
+ ProtoLog.v(WM_DEBUG_ADD_REMOVE, "addChild: %s at top.", this);
r.inHistory = true;
- // Remove r first, and if it wasn't already in the list and it's fullscreen, count it.
- if (!mActivities.remove(r) && r.occludesParent()) {
- // Was not previously in list.
+ if (r.occludesParent()) {
numFullscreen++;
}
// Only set this based on the first activity
- if (!hasChild()) {
+ if (!hadChild) {
if (r.getActivityType() == ACTIVITY_TYPE_UNDEFINED) {
// Normally non-standard activity type for the activity record will be set when the
// object is created, however we delay setting the standard application type until
@@ -1264,20 +1166,6 @@ class TaskRecord extends ConfigurationContainer {
r.setActivityType(getActivityType());
}
- final int size = getChildCount();
-
- if (index == size && size > 0) {
- final ActivityRecord top = getChildAt(size - 1);
- if (top.mTaskOverlay) {
- // Place below the task overlay activity since the overlay activity should always
- // be on top.
- index--;
- }
- }
-
- index = Math.min(size, index);
- mActivities.add(index, r);
-
updateEffectiveIntent();
if (r.isPersistable()) {
mAtmService.notifyTaskPersisterLocked(this, false);
@@ -1288,31 +1176,23 @@ class TaskRecord extends ConfigurationContainer {
mAtmService.mRootActivityContainer.updateUIDsPresentOnDisplay();
}
- // TODO(task-unify): Merge onChildAdded method below into this since task will be a single
- // object.
void addChild(ActivityRecord r) {
- if (r.getParent() != null) {
- // Shouldn't already have a parent since we are just adding to the task...
- throw new IllegalStateException(
- "r=" + r + " parent=" + r.getParent() + " task=" + this);
- }
+ addChild(r, Integer.MAX_VALUE /* add on top */);
+ }
- ProtoLog.v(WM_DEBUG_ADD_REMOVE, "addChild: %s at top.", this);
- // This means the activity isn't attached to Task.java yet. Go ahead and do that.
- // TODO(task-unify): Remove/call super once we unify task level.
- if (mTask != null) {
- mTask.addChild(r, Integer.MAX_VALUE /* add on top */);
- } else {
- onChildAdded(r, Integer.MAX_VALUE);
- }
+ @Override
+ void removeChild(ActivityRecord r) {
+ removeChild(r, "removeChild");
}
- /** Called when a Task child is removed from the Task.java side. */
- // TODO(task-unify): Just override removeChild to do what is needed when someone calls to remove
- // a child.
- void onChildRemoved(ActivityRecord r) {
- if (mActivities.remove(r) && r.occludesParent()) {
- // Was previously in list.
+ void removeChild(ActivityRecord r, String reason) {
+ if (!mChildren.contains(r)) {
+ Slog.e(TAG, "removeChild: r=" + r + " not found in t=" + this);
+ return;
+ }
+
+ super.removeChild(r);
+ if (r.occludesParent()) {
numFullscreen--;
}
if (r.isPersistable()) {
@@ -1336,16 +1216,19 @@ class TaskRecord extends ConfigurationContainer {
// When destroying a task, tell the supervisor to remove it so that any activity it
// has can be cleaned up correctly. This is currently the only place where we remove
// a task with the DESTROYING mode, so instead of passing the onlyHasTaskOverlays
- // state into removeTask(), we just clear the task here before the other residual
+ // state into removeChild(), we just clear the task here before the other residual
// work.
- // TODO: If the callers to removeTask() changes such that we have multiple places
- // where we are destroying the task, move this back into removeTask()
+ // TODO: If the callers to removeChild() changes such that we have multiple places
+ // where we are destroying the task, move this back into removeChild()
mAtmService.mStackSupervisor.removeTaskByIdLocked(mTaskId, false /* killProcess */,
- !REMOVE_FROM_RECENTS, "onChildRemoved");
+ !REMOVE_FROM_RECENTS, reason);
}
} else if (!mReuseTask) {
// Remove entire task if it doesn't have any activity left and it isn't marked for reuse
- mStack.removeTask(this, "onChildRemoved", REMOVE_TASK_MODE_DESTROYING);
+ mStack.removeChild(this, reason);
+ EventLog.writeEvent(WM_TASK_REMOVED, mTaskId,
+ "removeChild: last r=" + r + " in t=" + this);
+ removeIfPossible();
}
}
@@ -1380,7 +1263,7 @@ class TaskRecord extends ConfigurationContainer {
* Completely remove all activities associated with an existing
* task starting at a specified index.
*/
- final void performClearTaskAtIndexLocked(int activityNdx, String reason) {
+ private void performClearTaskAtIndexLocked(int activityNdx, String reason) {
int numActivities = getChildCount();
for ( ; activityNdx < numActivities; ++activityNdx) {
final ActivityRecord r = getChildAt(activityNdx);
@@ -1390,7 +1273,7 @@ class TaskRecord extends ConfigurationContainer {
if (mStack == null) {
// Task was restored from persistent storage.
r.takeFromHistory();
- mActivities.remove(activityNdx);
+ removeChild(r);
--activityNdx;
--numActivities;
} else if (r.finishIfPossible(Activity.RESULT_CANCELED, null /* resultData */, reason,
@@ -1526,20 +1409,13 @@ class TaskRecord extends ConfigurationContainer {
" mLockTaskAuth=" + lockTaskAuthToString());
}
- private boolean isResizeable(boolean checkSupportsPip) {
- return (mAtmService.mForceResizableActivities || ActivityInfo.isResizeableMode(mResizeMode)
- || (checkSupportsPip && mSupportsPictureInPicture));
- }
-
- boolean isResizeable() {
- return isResizeable(true /* checkSupportsPip */);
- }
-
@Override
public boolean supportsSplitScreenWindowingMode() {
// A task can not be docked even if it is considered resizeable because it only supports
// picture-in-picture mode but has a non-resizeable resizeMode
return super.supportsSplitScreenWindowingMode()
+ // TODO(task-group): Probably makes sense to move this and associated code into
+ // WindowContainer so it affects every node.
&& mAtmService.mSupportsSplitScreenMultiWindow
&& (mAtmService.mForceResizableActivities
|| (isResizeable(false /* checkSupportsPip */)
@@ -1672,15 +1548,13 @@ class TaskRecord extends ConfigurationContainer {
}
topActivity = false;
}
- mTaskDescription = new TaskDescription(label, null, iconResource, iconFilename,
- colorPrimary, colorBackground, statusBarColor, navigationBarColor,
+ final TaskDescription taskDescription = new TaskDescription(label, null, iconResource,
+ iconFilename, colorPrimary, colorBackground, statusBarColor, navigationBarColor,
statusBarContrastWhenTransparent, navigationBarContrastWhenTransparent);
- if (mTask != null) {
- mTask.setTaskDescription(mTaskDescription);
- }
+ setTaskDescription(taskDescription);
// Update the task affiliation color if we are the parent of the group
if (mTaskId == mAffiliatedTaskId) {
- mAffiliatedTaskColor = mTaskDescription.getPrimaryColor();
+ mAffiliatedTaskColor = taskDescription.getPrimaryColor();
}
}
}
@@ -1903,38 +1777,6 @@ class TaskRecord extends ConfigurationContainer {
}
/**
- * Displayed bounds are used to set where the task is drawn at any given time. This is
- * separate from its actual bounds so that the app doesn't see any meaningful configuration
- * changes during transitionary periods.
- */
- void setDisplayedBounds(Rect bounds) {
- if (bounds == null) {
- mDisplayedBounds.setEmpty();
- } else {
- mDisplayedBounds.set(bounds);
- }
- if (mTask != null) {
- mTask.setOverrideDisplayedBounds(
- mDisplayedBounds.isEmpty() ? null : mDisplayedBounds);
- }
- }
-
- /**
- * Gets the current overridden displayed bounds. These will be empty if the task is not
- * currently overriding where it is displayed.
- */
- Rect getDisplayedBounds() {
- return mDisplayedBounds;
- }
-
- /**
- * @return {@code true} if this has overridden displayed bounds.
- */
- boolean hasDisplayedBounds() {
- return !mDisplayedBounds.isEmpty();
- }
-
- /**
* Intersects inOutBounds with intersectBounds-intersectInsets. If inOutBounds is larger than
* intersectBounds on a side, then the respective side will not be intersected.
*
@@ -2190,16 +2032,10 @@ class TaskRecord extends ConfigurationContainer {
computeConfigResourceOverrides(getResolvedOverrideConfiguration(), newParentConfig);
}
- /** @see WindowContainer#handlesOrientationChangeFromDescendant */
- boolean handlesOrientationChangeFromDescendant() {
- return mTask != null && mTask.getParent() != null
- && mTask.getParent().handlesOrientationChangeFromDescendant();
- }
-
/**
- * Compute bounds (letterbox or pillarbox) for {@link #WINDOWING_MODE_FULLSCREEN} when the
- * parent doesn't handle the orientation change and the requested orientation is different from
- * the parent.
+ * Compute bounds (letterbox or pillarbox) for
+ * {@link WindowConfiguration#WINDOWING_MODE_FULLSCREEN} when the parent doesn't handle the
+ * orientation change and the requested orientation is different from the parent.
*/
void computeFullscreenBounds(@NonNull Rect outBounds, @Nullable ActivityRecord refActivity,
@NonNull Rect parentBounds, int parentOrientation) {
@@ -2345,7 +2181,7 @@ class TaskRecord extends ConfigurationContainer {
info.realActivity = realActivity;
info.numActivities = mReuseActivitiesReport.numActivities;
info.lastActiveTime = lastActiveTime;
- info.taskDescription = new ActivityManager.TaskDescription(mTaskDescription);
+ info.taskDescription = new ActivityManager.TaskDescription(getTaskDescription());
info.supportsSplitScreenMultiWindow = supportsSplitScreenWindowingMode();
info.resizeMode = mResizeMode;
info.configuration.setTo(getConfiguration());
@@ -2435,7 +2271,7 @@ class TaskRecord extends ConfigurationContainer {
}
pw.println(")");
}
- pw.print(prefix); pw.print("Activities="); pw.println(mActivities);
+ pw.print(prefix); pw.print("Activities="); pw.println(mChildren);
if (!askedCompatMode || !inRecents || !isAvailable) {
pw.print(prefix); pw.print("askedCompatMode="); pw.print(askedCompatMode);
pw.print(" inRecents="); pw.print(inRecents);
@@ -2490,6 +2326,7 @@ class TaskRecord extends ConfigurationContainer {
return toString();
}
+ @Override
public void writeToProto(ProtoOutputStream proto, long fieldId,
@WindowTraceLogLevel int logLevel) {
if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible()) {
@@ -2497,13 +2334,13 @@ class TaskRecord extends ConfigurationContainer {
}
final long token = proto.start(fieldId);
- super.writeToProto(proto, CONFIGURATION_CONTAINER, logLevel);
+ writeToProtoInnerTaskOnly(proto, TASK, logLevel);
proto.write(ID, mTaskId);
for (int i = getChildCount() - 1; i >= 0; i--) {
- ActivityRecord activity = getChildAt(i);
+ final ActivityRecord activity = getChildAt(i);
activity.writeToProto(proto, ACTIVITIES);
}
- proto.write(STACK_ID, mStack.mStackId);
+ proto.write(STACK_ID, getStackId());
if (mLastNonFullscreenBounds != null) {
mLastNonFullscreenBounds.writeToProto(proto, LAST_NON_FULLSCREEN_BOUNDS);
}
@@ -2579,8 +2416,8 @@ class TaskRecord extends ConfigurationContainer {
if (lastDescription != null) {
out.attribute(null, ATTR_LASTDESCRIPTION, lastDescription.toString());
}
- if (mTaskDescription != null) {
- mTaskDescription.saveToXml(out);
+ if (getTaskDescription() != null) {
+ getTaskDescription().saveToXml(out);
}
out.attribute(null, ATTR_TASK_AFFILIATION_COLOR, String.valueOf(mAffiliatedTaskColor));
out.attribute(null, ATTR_TASK_AFFILIATION, String.valueOf(mAffiliatedTaskId));
@@ -2641,14 +2478,14 @@ class TaskRecord extends ConfigurationContainer {
static TaskRecord create(ActivityTaskManagerService service, int taskId, ActivityInfo info,
Intent intent, IVoiceInteractionSession voiceSession,
- IVoiceInteractor voiceInteractor) {
+ IVoiceInteractor voiceInteractor, ActivityStack stack) {
return getTaskRecordFactory().create(
- service, taskId, info, intent, voiceSession, voiceInteractor);
+ service, taskId, info, intent, voiceSession, voiceInteractor, stack);
}
static TaskRecord create(ActivityTaskManagerService service, int taskId, ActivityInfo info,
- Intent intent, TaskDescription taskDescription) {
- return getTaskRecordFactory().create(service, taskId, info, intent, taskDescription);
+ Intent intent, TaskDescription taskDescription, ActivityStack stack) {
+ return getTaskRecordFactory().create(service, taskId, info, intent, taskDescription, stack);
}
static TaskRecord restoreFromXml(XmlPullParser in, ActivityStackSupervisor stackSupervisor)
@@ -2665,15 +2502,15 @@ class TaskRecord extends ConfigurationContainer {
TaskRecord create(ActivityTaskManagerService service, int taskId, ActivityInfo info,
Intent intent, IVoiceInteractionSession voiceSession,
- IVoiceInteractor voiceInteractor) {
+ IVoiceInteractor voiceInteractor, ActivityStack stack) {
return new TaskRecord(service, taskId, info, intent, voiceSession, voiceInteractor,
- null /*taskDescription*/);
+ null /*taskDescription*/, stack);
}
TaskRecord create(ActivityTaskManagerService service, int taskId, ActivityInfo info,
- Intent intent, TaskDescription taskDescription) {
+ Intent intent, TaskDescription taskDescription, ActivityStack stack) {
return new TaskRecord(service, taskId, info, intent, null /*voiceSession*/,
- null /*voiceInteractor*/, taskDescription);
+ null /*voiceInteractor*/, taskDescription, stack);
}
/**
@@ -2683,20 +2520,20 @@ class TaskRecord extends ConfigurationContainer {
Intent affinityIntent, String affinity, String rootAffinity,
ComponentName realActivity, ComponentName origActivity, boolean rootWasReset,
boolean autoRemoveRecents, boolean askedCompatMode, int userId,
- int effectiveUid, String lastDescription, ArrayList<ActivityRecord> activities,
+ int effectiveUid, String lastDescription,
long lastTimeMoved, boolean neverRelinquishIdentity,
TaskDescription lastTaskDescription, int taskAffiliation, int prevTaskId,
int nextTaskId, int taskAffiliationColor, int callingUid, String callingPackage,
int resizeMode, boolean supportsPictureInPicture, boolean realActivitySuspended,
- boolean userSetupComplete, int minWidth, int minHeight) {
+ boolean userSetupComplete, int minWidth, int minHeight, ActivityStack stack) {
return new TaskRecord(service, taskId, intent, affinityIntent, affinity,
rootAffinity, realActivity, origActivity, rootWasReset, autoRemoveRecents,
- askedCompatMode, userId, effectiveUid, lastDescription, activities,
+ askedCompatMode, userId, effectiveUid, lastDescription,
lastTimeMoved, neverRelinquishIdentity, lastTaskDescription, taskAffiliation,
prevTaskId, nextTaskId, taskAffiliationColor, callingUid, callingPackage,
resizeMode, supportsPictureInPicture, realActivitySuspended, userSetupComplete,
minWidth, minHeight, null /*ActivityInfo*/, null /*_voiceSession*/,
- null /*_voiceInteractor*/);
+ null /*_voiceInteractor*/, stack);
}
TaskRecord restoreFromXml(XmlPullParser in, ActivityStackSupervisor stackSupervisor)
@@ -2908,15 +2745,15 @@ class TaskRecord extends ConfigurationContainer {
taskId, intent, affinityIntent,
affinity, rootAffinity, realActivity, origActivity, rootHasReset,
autoRemoveRecents, askedCompatMode, userId, effectiveUid, lastDescription,
- activities, lastTimeOnTop, neverRelinquishIdentity, taskDescription,
+ lastTimeOnTop, neverRelinquishIdentity, taskDescription,
taskAffiliation, prevTaskId, nextTaskId, taskAffiliationColor, callingUid,
callingPackage, resizeMode, supportsPictureInPicture, realActivitySuspended,
- userSetupComplete, minWidth, minHeight);
+ userSetupComplete, minWidth, minHeight, null /*stack*/);
task.mLastNonFullscreenBounds = lastNonFullscreenBounds;
task.setBounds(lastNonFullscreenBounds);
for (int activityNdx = activities.size() - 1; activityNdx >=0; --activityNdx) {
- activities.get(activityNdx).setTask(task);
+ task.addChild(activities.get(activityNdx));
}
if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "Restored task=" + task);
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 56211e25f421..68b76fb14174 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -116,7 +116,6 @@ public class TaskStack extends WindowContainer<Task> implements
/** ActivityRecords that are exiting, but still on screen for animations. */
final ArrayList<ActivityRecord> mExitingActivities = new ArrayList<>();
- final ArrayList<ActivityRecord> mTmpActivities = new ArrayList<>();
/** Detach this stack from its display when animation completes. */
// TODO: maybe tie this to WindowContainer#removeChild some how...
@@ -330,7 +329,7 @@ public class TaskStack extends WindowContainer<Task> implements
}
/** Bounds of the stack with other system factors taken into consideration. */
- public void getDimBounds(Rect out) {
+ void getDimBounds(Rect out) {
getBounds(out);
}
@@ -482,11 +481,6 @@ public class TaskStack extends WindowContainer<Task> implements
dividerSize);
}
- // TODO: Checkout the call points of this method and the ones below to see how they can fit in WC.
- void addTask(Task task, int position) {
- addTask(task, position, task.showForAllUsers(), true /* moveParents */);
- }
-
/**
* Put a Task in this stack. Used for adding only.
* When task is added to top of the stack, the entire branch of the hierarchy (including stack
@@ -495,22 +489,21 @@ public class TaskStack extends WindowContainer<Task> implements
* @param position Target position to add the task to.
* @param showForAllUsers Whether to show the task regardless of the current user.
*/
- void addTask(Task task, int position, boolean showForAllUsers, boolean moveParents) {
- final TaskStack currentStack = task.mStack;
- // TODO: We pass stack to task's constructor, but we still need to call this method.
- // This doesn't make sense, mStack will already be set equal to "this" at this point.
- if (currentStack != null && currentStack.mStackId != mStackId) {
- throw new IllegalStateException("Trying to add taskId=" + task.mTaskId
- + " to stackId=" + mStackId
- + ", but it is already attached to stackId=" + task.mStack.mStackId);
- }
-
+ void addChild(Task task, int position, boolean showForAllUsers, boolean moveParents) {
// Add child task.
task.mStack = this;
addChild(task, null);
// Move child to a proper position, as some restriction for position might apply.
- positionChildAt(position, task, moveParents /* includingParents */, showForAllUsers);
+ position = positionChildAt(
+ position, task, moveParents /* includingParents */, showForAllUsers);
+ // TODO(task-merge): Remove cast.
+ mActivityStack.onChildAdded((TaskRecord) task, position);
+ }
+
+ @Override
+ void addChild(Task task, int position) {
+ addChild(task, position, task.showForAllUsers(), false /* includingParents */);
}
void positionChildAt(Task child, int position) {
@@ -563,13 +556,12 @@ public class TaskStack extends WindowContainer<Task> implements
/**
* Overridden version of {@link TaskStack#positionChildAt(int, Task, boolean)}. Used in
- * {@link TaskStack#addTask(Task, int, boolean showForAllUsers, boolean)}, as it can receive
- * showForAllUsers param from {@link AppWindowToken} instead of {@link Task#showForAllUsers()}.
+ * {@link TaskStack#addChild(Task, int, boolean showForAllUsers, boolean)}, as it can receive
+ * showForAllUsers param from {@link ActivityRecord} instead of {@link Task#showForAllUsers()}.
*/
- private void positionChildAt(int position, Task child, boolean includingParents,
+ int positionChildAt(int position, Task child, boolean includingParents,
boolean showForAllUsers) {
- final int targetPosition = findPositionForTask(child, position, showForAllUsers,
- false /* addingNew */);
+ final int targetPosition = findPositionForTask(child, position, showForAllUsers);
super.positionChildAt(targetPosition, child, includingParents);
// Log positioning.
@@ -578,6 +570,14 @@ public class TaskStack extends WindowContainer<Task> implements
final int toTop = targetPosition == mChildren.size() - 1 ? 1 : 0;
EventLog.writeEvent(EventLogTags.WM_TASK_MOVED, child.mTaskId, toTop, targetPosition);
+
+ return targetPosition;
+ }
+
+ @Override
+ void onChildPositionChanged(WindowContainer child) {
+ // TODO(task-merge): Read comment on updateTaskMovement method.
+ //((TaskRecord) child).updateTaskMovement(true);
}
void reparent(int displayId, Rect outStackBounds, boolean onTop) {
@@ -597,14 +597,13 @@ public class TaskStack extends WindowContainer<Task> implements
// TODO: We should really have users as a window container in the hierarchy so that we don't
// have to do complicated things like we are doing in this method.
- private int findPositionForTask(Task task, int targetPosition, boolean showForAllUsers,
- boolean addingNew) {
+ private int findPositionForTask(Task task, int targetPosition, boolean showForAllUsers) {
final boolean canShowTask =
showForAllUsers || mWmService.isCurrentProfileLocked(task.mUserId);
final int stackSize = mChildren.size();
int minPosition = 0;
- int maxPosition = addingNew ? stackSize : stackSize - 1;
+ int maxPosition = stackSize - 1;
if (canShowTask) {
minPosition = computeMinPosition(minPosition, stackSize);
@@ -615,8 +614,7 @@ public class TaskStack extends WindowContainer<Task> implements
// preserve POSITION_BOTTOM/POSITION_TOP positions if they are still valid.
if (targetPosition == POSITION_BOTTOM && minPosition == 0) {
return POSITION_BOTTOM;
- } else if (targetPosition == POSITION_TOP
- && maxPosition == (addingNew ? stackSize : stackSize - 1)) {
+ } else if (targetPosition == POSITION_TOP && maxPosition == (stackSize - 1)) {
return POSITION_TOP;
}
// Reset position based on minimum/maximum possible positions.
@@ -669,24 +667,17 @@ public class TaskStack extends WindowContainer<Task> implements
*/
@Override
void removeChild(Task task) {
+ if (!mChildren.contains(task)) {
+ // Not really in this stack anymore...
+ return;
+ }
if (DEBUG_TASK_MOVEMENT) Slog.d(TAG_WM, "removeChild: task=" + task);
super.removeChild(task);
task.mStack = null;
- if (mDisplayContent != null) {
- if (mChildren.isEmpty()) {
- getParent().positionChildAt(POSITION_BOTTOM, this, false /* includingParents */);
- }
- mDisplayContent.setLayoutNeeded();
- }
- for (int appNdx = mExitingActivities.size() - 1; appNdx >= 0; --appNdx) {
- final ActivityRecord activity = mExitingActivities.get(appNdx);
- if (activity.getTask() == task) {
- activity.mIsExiting = false;
- mExitingActivities.remove(appNdx);
- }
- }
+ // TODO(task-merge): Remove cast.
+ mActivityStack.onChildRemoved((TaskRecord) task, mDisplayContent);
}
@Override
@@ -1298,7 +1289,7 @@ public class TaskStack extends WindowContainer<Task> implements
super.writeToProto(proto, WINDOW_CONTAINER, logLevel);
proto.write(ID, mStackId);
for (int taskNdx = mChildren.size() - 1; taskNdx >= 0; taskNdx--) {
- mChildren.get(taskNdx).writeToProto(proto, TASKS, logLevel);
+ mChildren.get(taskNdx).writeToProtoInnerTaskOnly(proto, TASKS, logLevel);
}
proto.write(FILLS_PARENT, matchParentBounds());
getRawBounds().writeToProto(proto, BOUNDS);
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 7ce2b5eb727b..a393ba65fbc9 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -428,7 +428,7 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
parent.mTreeWeight += child.mTreeWeight;
parent = parent.getParent();
}
- onChildPositionChanged();
+ onChildPositionChanged(child);
}
/**
@@ -454,7 +454,7 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
parent.mTreeWeight -= child.mTreeWeight;
parent = parent.getParent();
}
- onChildPositionChanged();
+ onChildPositionChanged(child);
}
/**
@@ -583,7 +583,7 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
if (mChildren.peekLast() != child) {
mChildren.remove(child);
mChildren.add(child);
- onChildPositionChanged();
+ onChildPositionChanged(child);
}
if (includingParents && getParent() != null) {
getParent().positionChildAt(POSITION_TOP, this /* child */,
@@ -594,7 +594,7 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
if (mChildren.peekFirst() != child) {
mChildren.remove(child);
mChildren.addFirst(child);
- onChildPositionChanged();
+ onChildPositionChanged(child);
}
if (includingParents && getParent() != null) {
getParent().positionChildAt(POSITION_BOTTOM, this /* child */,
@@ -608,14 +608,14 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
// doing this adjustment here and remove any adjustments in the callers.
mChildren.remove(child);
mChildren.add(position, child);
- onChildPositionChanged();
+ onChildPositionChanged(child);
}
}
/**
* Notify that a child's position has changed. Possible changes are adding or removing a child.
*/
- void onChildPositionChanged() { }
+ void onChildPositionChanged(WindowContainer child) { }
/**
* Update override configuration and recalculate full config.
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 17e67ebf617f..344befad8fa9 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -638,7 +638,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
private boolean mIsDimming = false;
private @Nullable InsetsSourceProvider mControllableInsetProvider;
- private InsetsState mClientInsetsState = new InsetsState();
+ private InsetsState mClientInsetsState;
private static final float DEFAULT_DIM_AMOUNT_DEAD_WINDOW = 0.5f;
private KeyInterceptionInfo mKeyInterceptionInfo;
@@ -767,6 +767,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
mSeq = seq;
mPowerManagerWrapper = powerManagerWrapper;
mForceSeamlesslyRotate = token.mRoundedCornerOverlay;
+ mClientInsetsState =
+ getDisplayContent().getInsetsStateController().getInsetsForDispatch(this);
if (DEBUG) {
Slog.v(TAG, "Window " + this + " client=" + c.asBinder()
+ " token=" + token + " (" + mAttrs.token + ")" + " params=" + a);
@@ -2207,7 +2209,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
mInputChannel = inputChannels[0];
mClientChannel = inputChannels[1];
mWmService.mInputManager.registerInputChannel(mInputChannel);
- mClientChannel.setToken(mInputChannel.getToken());
mInputWindowHandle.token = mInputChannel.getToken();
if (outInputChannel != null) {
mClientChannel.transferTo(outInputChannel);
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index da355ea0ca3b..425b4b632971 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -23,7 +23,6 @@ cc_library_static {
"com_android_server_AlarmManagerService.cpp",
"com_android_server_am_BatteryStatsService.cpp",
"com_android_server_connectivity_Vpn.cpp",
- "com_android_server_connectivity_tethering_OffloadHardwareInterface.cpp",
"com_android_server_ConsumerIrService.cpp",
"com_android_server_devicepolicy_CryptoTestHelper.cpp",
"com_android_server_HardwarePropertiesManagerService.cpp",
@@ -54,6 +53,7 @@ cc_library_static {
"com_android_server_am_LowMemDetector.cpp",
"onload.cpp",
":lib_networkStatsFactory_native",
+ ":tethering-jni-srcs",
],
include_dirs: [
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index 35e2436817df..b546a1d9ef4e 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -1596,8 +1596,8 @@ static jboolean nativeTransferTouchFocus(JNIEnv* env,
return JNI_FALSE;
}
- if (im->getInputManager()->getDispatcher()->
- transferTouchFocus(fromChannel->getToken(), toChannel->getToken())) {
+ if (im->getInputManager()->getDispatcher()->transferTouchFocus(
+ fromChannel->getConnectionToken(), toChannel->getConnectionToken())) {
return JNI_TRUE;
} else {
return JNI_FALSE;
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 2009dbdca448..ef9e69df01df 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -439,7 +439,7 @@ public final class SystemServer {
// In case the runtime switched since last boot (such as when
// the old runtime was removed in an OTA), set the system
- // property so that it is in sync. We can | xq oqi't do this in
+ // property so that it is in sync. We can't do this in
// libnativehelper's JniInvocation::Init code where we already
// had to fallback to a different runtime because it is
// running as root and we need to be the system user to set
diff --git a/services/net/Android.bp b/services/net/Android.bp
index e24dec562a46..c56ecd6e19e7 100644
--- a/services/net/Android.bp
+++ b/services/net/Android.bp
@@ -29,6 +29,7 @@ filegroup {
"java/android/net/ConnectivityModuleConnector.java",
"java/android/net/NetworkStackClient.java",
"java/android/net/ip/InterfaceController.java",
+ "java/android/net/netlink/*.java",
"java/android/net/util/InterfaceParams.java",
"java/android/net/util/NetdService.java",
"java/android/net/util/NetworkConstants.java",
diff --git a/services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java
index 485f436f7f65..556f96ace5d2 100644
--- a/services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java
@@ -24,6 +24,7 @@ import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_FREQUENT;
import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_RARE;
import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_WORKING_SET;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doCallRealMethod;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doThrow;
@@ -35,6 +36,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
import static com.android.server.AlarmManagerService.ACTIVE_INDEX;
import static com.android.server.AlarmManagerService.AlarmHandler.APP_STANDBY_BUCKET_CHANGED;
import static com.android.server.AlarmManagerService.AlarmHandler.CHARGING_STATUS_CHANGED;
+import static com.android.server.AlarmManagerService.AlarmHandler.REMOVE_FOR_CANCELED;
import static com.android.server.AlarmManagerService.Constants.KEY_ALLOW_WHILE_IDLE_LONG_TIME;
import static com.android.server.AlarmManagerService.Constants.KEY_ALLOW_WHILE_IDLE_SHORT_TIME;
import static com.android.server.AlarmManagerService.Constants.KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION;
@@ -80,9 +82,9 @@ import android.provider.Settings;
import android.util.Log;
import android.util.SparseArray;
-import androidx.test.filters.FlakyTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.dx.mockito.inline.extended.MockedVoidMethod;
import com.android.internal.annotations.GuardedBy;
import com.android.server.usage.AppStandbyInternal;
@@ -171,7 +173,6 @@ public class AlarmManagerServiceTest {
}
public class Injector extends AlarmManagerService.Injector {
- boolean mIsAutomotiveOverride;
Injector(Context context) {
super(context);
@@ -257,12 +258,13 @@ public class AlarmManagerServiceTest {
.startMocking();
doReturn(mIActivityManager).when(ActivityManager::getService);
doReturn(mAppStateTracker).when(() -> LocalServices.getService(AppStateTracker.class));
- doReturn(null)
- .when(() -> LocalServices.getService(DeviceIdleInternal.class));
doReturn(mAppStandbyInternal).when(
() -> LocalServices.getService(AppStandbyInternal.class));
doReturn(mUsageStatsManagerInternal).when(
() -> LocalServices.getService(UsageStatsManagerInternal.class));
+ doCallRealMethod().when((MockedVoidMethod) () ->
+ LocalServices.addService(eq(AlarmManagerInternal.class), any()));
+ doCallRealMethod().when(() -> LocalServices.getService(AlarmManagerInternal.class));
when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE),
eq(UserHandle.getUserId(TEST_CALLING_UID)), anyLong()))
.thenReturn(STANDBY_BUCKET_ACTIVE);
@@ -455,7 +457,6 @@ public class AlarmManagerServiceTest {
assertEquals(expectedTriggerTime, mTestTimer.getElapsed());
}
- @FlakyTest(bugId = 130313408)
@Test
public void testEarliestAlarmSet() {
final PendingIntent pi6 = getNewMockPendingIntent();
@@ -600,11 +601,15 @@ public class AlarmManagerServiceTest {
anyLong())).thenReturn(bucket);
mAppStandbyListener.onAppIdleStateChanged(TEST_CALLING_PACKAGE,
UserHandle.getUserId(TEST_CALLING_UID), false, bucket, 0);
+ assertAndHandleMessageSync(APP_STANDBY_BUCKET_CHANGED);
+ }
+
+ private void assertAndHandleMessageSync(int what) {
final ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
verify(mService.mHandler, atLeastOnce()).sendMessage(messageCaptor.capture());
final Message lastMessage = messageCaptor.getValue();
assertEquals("Unexpected message send to handler", lastMessage.what,
- APP_STANDBY_BUCKET_CHANGED);
+ what);
mService.mHandler.handleMessage(lastMessage);
}
@@ -664,12 +669,7 @@ public class AlarmManagerServiceTest {
mChargingReceiver.onReceive(mMockContext,
new Intent(parole ? BatteryManager.ACTION_CHARGING
: BatteryManager.ACTION_DISCHARGING));
- final ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
- verify(mService.mHandler, atLeastOnce()).sendMessage(messageCaptor.capture());
- final Message lastMessage = messageCaptor.getValue();
- assertEquals("Unexpected message send to handler", lastMessage.what,
- CHARGING_STATUS_CHANGED);
- mService.mHandler.handleMessage(lastMessage);
+ assertAndHandleMessageSync(CHARGING_STATUS_CHANGED);
}
@Test
@@ -971,12 +971,13 @@ public class AlarmManagerServiceTest {
}
@Test
- public void alarmCountOnPendingIntentCancel() {
+ public void alarmCountOnRemoveForCanceled() {
+ final AlarmManagerInternal ami = LocalServices.getService(AlarmManagerInternal.class);
final PendingIntent pi = getNewMockPendingIntent();
- setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 123, pi);
- verify(pi).registerCancelListener(mService.mOperationCancelListener);
+ setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + 12345, pi);
assertEquals(1, mService.mAlarmsPerUid.get(TEST_CALLING_UID));
- mService.mOperationCancelListener.onCancelled(pi);
+ ami.remove(pi);
+ assertAndHandleMessageSync(REMOVE_FOR_CANCELED);
assertEquals(0, mService.mAlarmsPerUid.get(TEST_CALLING_UID));
}
@@ -985,5 +986,6 @@ public class AlarmManagerServiceTest {
if (mMockingSession != null) {
mMockingSession.finishMocking();
}
+ LocalServices.removeServiceForTest(AlarmManagerInternal.class);
}
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/PendingIntentControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/am/PendingIntentControllerTest.java
new file mode 100644
index 000000000000..3975f0baa22a
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/am/PendingIntentControllerTest.java
@@ -0,0 +1,130 @@
+/*
+ * 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.
+ */
+
+package com.android.server.am;
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.when;
+
+import android.app.ActivityManager;
+import android.app.ActivityManagerInternal;
+import android.app.AppGlobals;
+import android.app.PendingIntent;
+import android.content.Intent;
+import android.content.pm.IPackageManager;
+import android.os.Looper;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.server.AlarmManagerInternal;
+import com.android.server.LocalServices;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoSession;
+import org.mockito.quality.Strictness;
+
+@RunWith(AndroidJUnit4.class)
+public class PendingIntentControllerTest {
+ private static final String TEST_PACKAGE_NAME = "test-package-1";
+ private static final int TEST_CALLING_UID = android.os.Process.myUid();
+ private static final Intent[] TEST_INTENTS = new Intent[]{new Intent("com.test.intent")};
+
+ @Mock
+ private UserController mUserController;
+ @Mock
+ private AlarmManagerInternal mAlarmManagerInternal;
+ @Mock
+ private ActivityManagerInternal mActivityManagerInternal;
+ @Mock
+ private IPackageManager mIPackageManager;
+
+ private MockitoSession mMockingSession;
+ private PendingIntentController mPendingIntentController;
+
+ @Before
+ public void setUp() throws Exception {
+ mMockingSession = mockitoSession()
+ .initMocks(this)
+ .mockStatic(LocalServices.class)
+ .mockStatic(AppGlobals.class)
+ .strictness(Strictness.LENIENT) // Needed to stub LocalServices.getService twice
+ .startMocking();
+ doReturn(mAlarmManagerInternal).when(
+ () -> LocalServices.getService(AlarmManagerInternal.class));
+ doReturn(mActivityManagerInternal).when(
+ () -> LocalServices.getService(ActivityManagerInternal.class));
+ doReturn(mIPackageManager).when(() -> AppGlobals.getPackageManager());
+ when(mIPackageManager.getPackageUid(eq(TEST_PACKAGE_NAME), anyInt(), anyInt())).thenReturn(
+ TEST_CALLING_UID);
+ mPendingIntentController = new PendingIntentController(Looper.getMainLooper(),
+ mUserController);
+ mPendingIntentController.onActivityManagerInternalAdded();
+ }
+
+ private PendingIntentRecord createPendingIntentRecord(int flags) {
+ return mPendingIntentController.getIntentSender(ActivityManager.INTENT_SENDER_BROADCAST,
+ TEST_PACKAGE_NAME, TEST_CALLING_UID, 0, null, null, 0, TEST_INTENTS, null, flags,
+ null);
+ }
+
+ @Test
+ public void alarmsRemovedOnCancel() {
+ final PendingIntentRecord pir = createPendingIntentRecord(0);
+ mPendingIntentController.cancelIntentSender(pir);
+ final ArgumentCaptor<PendingIntent> piCaptor = ArgumentCaptor.forClass(PendingIntent.class);
+ verify(mAlarmManagerInternal).remove(piCaptor.capture());
+ assertEquals("Wrong target for pending intent passed to alarm manager", pir,
+ piCaptor.getValue().getTarget());
+ }
+
+ @Test
+ public void alarmsRemovedOnRecreateWithCancelCurrent() {
+ final PendingIntentRecord pir = createPendingIntentRecord(0);
+ createPendingIntentRecord(PendingIntent.FLAG_CANCEL_CURRENT);
+ final ArgumentCaptor<PendingIntent> piCaptor = ArgumentCaptor.forClass(PendingIntent.class);
+ verify(mAlarmManagerInternal).remove(piCaptor.capture());
+ assertEquals("Wrong target for pending intent passed to alarm manager", pir,
+ piCaptor.getValue().getTarget());
+ }
+
+ @Test
+ public void alarmsRemovedOnSendingOneShot() {
+ final PendingIntentRecord pir = createPendingIntentRecord(PendingIntent.FLAG_ONE_SHOT);
+ pir.send(0, null, null, null, null, null, null);
+ final ArgumentCaptor<PendingIntent> piCaptor = ArgumentCaptor.forClass(PendingIntent.class);
+ verify(mAlarmManagerInternal).remove(piCaptor.capture());
+ assertEquals("Wrong target for pending intent passed to alarm manager", pir,
+ piCaptor.getValue().getTarget());
+ }
+
+ @After
+ public void tearDown() {
+ if (mMockingSession != null) {
+ mMockingSession.finishMocking();
+ }
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/attention/AttentionManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/attention/AttentionManagerServiceTest.java
index 184dc3dfed62..a47a5671ccb3 100644
--- a/services/tests/servicestests/src/com/android/server/attention/AttentionManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/attention/AttentionManagerServiceTest.java
@@ -16,6 +16,8 @@
package com.android.server.attention;
+import static com.android.server.attention.AttentionManagerService.ATTENTION_CACHE_BUFFER_SIZE;
+
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
@@ -39,6 +41,8 @@ import android.service.attention.IAttentionService;
import androidx.test.filters.SmallTest;
import com.android.server.attention.AttentionManagerService.AttentionCheck;
+import com.android.server.attention.AttentionManagerService.AttentionCheckCache;
+import com.android.server.attention.AttentionManagerService.AttentionCheckCacheBuffer;
import com.android.server.attention.AttentionManagerService.AttentionHandler;
import com.android.server.attention.AttentionManagerService.UserState;
@@ -56,11 +60,16 @@ public class AttentionManagerServiceTest {
private AttentionManagerService mSpyAttentionManager;
private UserState mSpyUserState;
private final int mTimeout = 1000;
- @Mock private AttentionCallbackInternal mMockAttentionCallbackInternal;
- @Mock private AttentionHandler mMockHandler;
- @Mock private IAttentionCallback mMockIAttentionCallback;
- @Mock private IPowerManager mMockIPowerManager;
- @Mock Context mContext;
+ @Mock
+ private AttentionCallbackInternal mMockAttentionCallbackInternal;
+ @Mock
+ private AttentionHandler mMockHandler;
+ @Mock
+ private IAttentionCallback mMockIAttentionCallback;
+ @Mock
+ private IPowerManager mMockIPowerManager;
+ @Mock
+ Context mContext;
@Before
public void setUp() throws RemoteException {
@@ -140,12 +149,45 @@ public class AttentionManagerServiceTest {
mSpyAttentionManager.onSwitchUser(userId);
}
+ @Test
+ public void testAttentionCheckCacheBuffer_getLast_returnTheLastElement() {
+ AttentionCheckCacheBuffer buffer = new AttentionCheckCacheBuffer();
+ buffer.add(new AttentionCheckCache(0, 0, 1L));
+ AttentionCheckCache cache = new AttentionCheckCache(0, 0, 2L);
+ buffer.add(cache);
+ assertThat(buffer.getLast()).isEqualTo(cache);
+ }
+
+ @Test
+ public void testAttentionCheckCacheBuffer_get_returnNullWhenOutOfBoundary() {
+ AttentionCheckCacheBuffer buffer = new AttentionCheckCacheBuffer();
+ assertThat(buffer.get(1)).isNull();
+ }
+
+ @Test
+ public void testAttentionCheckCacheBuffer_get_handleCircularIndexing() {
+ AttentionCheckCacheBuffer buffer = new AttentionCheckCacheBuffer();
+ AttentionCheckCache cache = new AttentionCheckCache(0L, 0, 1L);
+ // Insert SIZE+1 elements.
+ for (int i = 0; i <= ATTENTION_CACHE_BUFFER_SIZE; i++) {
+ if (i == 1) {
+ buffer.add(cache);
+ } else {
+ buffer.add(new AttentionCheckCache(0L, 0, i));
+ }
+ }
+ // The element that was at index 1 should be at index 0 after inserting SIZE + 1 elements.
+ assertThat(buffer.get(0)).isEqualTo(cache);
+ }
+
private class MockIAttentionService implements IAttentionService {
public void checkAttention(IAttentionCallback callback) throws RemoteException {
callback.onSuccess(0, 0);
}
+
public void cancelAttentionCheck(IAttentionCallback callback) {
}
+
public IBinder asBinder() {
return null;
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index 38d6c9c1e4db..2ce37f1be4c5 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -53,8 +53,6 @@ import static com.android.server.wm.ActivityStack.ActivityState.RESUMED;
import static com.android.server.wm.ActivityStack.ActivityState.STARTED;
import static com.android.server.wm.ActivityStack.ActivityState.STOPPED;
import static com.android.server.wm.ActivityStack.ActivityState.STOPPING;
-import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
-import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_MOVING;
import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_INVISIBLE;
import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_VISIBLE;
import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT;
@@ -136,13 +134,13 @@ public class ActivityRecordTests extends ActivityTestsBase {
@Test
public void testStackCleanupOnActivityRemoval() {
- mTask.mTask.removeChild(mActivity);
+ mTask.removeChild(mActivity);
verify(mStack, times(1)).onActivityRemovedFromStack(any());
}
@Test
public void testStackCleanupOnTaskRemoval() {
- mStack.removeTask(mTask, null /*reason*/, REMOVE_TASK_MODE_MOVING);
+ mStack.removeChild(mTask, null /*reason*/);
// Stack should be gone on task removal.
assertNull(mService.mRootActivityContainer.getStack(mStack.mStackId));
}
@@ -325,7 +323,7 @@ public class ActivityRecordTests extends ActivityTestsBase {
: ORIENTATION_PORTRAIT;
mTask.onRequestedOverrideConfigurationChanged(newConfig);
- doReturn(true).when(mTask.mTask).isDragResizing();
+ doReturn(true).when(mTask).isDragResizing();
mActivity.mRelaunchReason = ActivityTaskManagerService.RELAUNCH_REASON_NONE;
@@ -382,7 +380,7 @@ public class ActivityRecordTests extends ActivityTestsBase {
}
// Mimic the behavior that display doesn't handle app's requested orientation.
- final DisplayContent dc = mTask.mTask.getDisplayContent();
+ final DisplayContent dc = mTask.getDisplayContent();
doReturn(false).when(dc).onDescendantOrientationChanged(any(), any());
doReturn(false).when(dc).handlesOrientationChangeFromDescendant();
@@ -1174,7 +1172,7 @@ public class ActivityRecordTests extends ActivityTestsBase {
// Empty the home stack.
final ActivityStack homeStack = mActivity.getDisplay().getHomeStack();
for (TaskRecord t : homeStack.getAllTasks()) {
- homeStack.removeTask(t, "test", REMOVE_TASK_MODE_DESTROYING);
+ homeStack.removeChild(t, "test");
}
mActivity.finishing = true;
doReturn(false).when(mRootActivityContainer).resumeFocusedStacksTopActivities();
@@ -1200,7 +1198,7 @@ public class ActivityRecordTests extends ActivityTestsBase {
// Empty the home stack.
final ActivityStack homeStack = mActivity.getDisplay().getHomeStack();
for (TaskRecord t : homeStack.getAllTasks()) {
- homeStack.removeTask(t, "test", REMOVE_TASK_MODE_DESTROYING);
+ homeStack.removeChild(t, "test");
}
mActivity.finishing = true;
spyOn(mStack);
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
index fcebb81fd658..cc0cc3f85d50 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
@@ -38,7 +38,6 @@ import static com.android.server.wm.ActivityStack.ActivityState.PAUSING;
import static com.android.server.wm.ActivityStack.ActivityState.RESUMED;
import static com.android.server.wm.ActivityStack.ActivityState.STOPPED;
import static com.android.server.wm.ActivityStack.ActivityState.STOPPING;
-import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_INVISIBLE;
import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_VISIBLE;
import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT;
@@ -93,21 +92,6 @@ public class ActivityStackTests extends ActivityTestsBase {
}
@Test
- public void testEmptyTaskCleanupOnRemove() {
- assertNotNull(mTask.getTask());
- mStack.removeTask(mTask, "testEmptyTaskCleanupOnRemove", REMOVE_TASK_MODE_DESTROYING);
- assertNull(mTask.getTask());
- }
-
- @Test
- public void testOccupiedTaskCleanupOnRemove() {
- final ActivityRecord r = new ActivityBuilder(mService).setTask(mTask).build();
- assertNotNull(mTask.getTask());
- mStack.removeTask(mTask, "testOccupiedTaskCleanupOnRemove", REMOVE_TASK_MODE_DESTROYING);
- assertNotNull(mTask.getTask());
- }
-
- @Test
public void testResumedActivity() {
final ActivityRecord r = new ActivityBuilder(mService).setTask(mTask).build();
assertNull(mStack.getResumedActivity());
@@ -996,27 +980,6 @@ public class ActivityStackTests extends ActivityTestsBase {
}
@Test
- public void testAdjustFocusedStackToHomeWhenNoActivity() {
- final ActivityStack homeStask = mDefaultDisplay.getHomeStack();
- TaskRecord homeTask = homeStask.topTask();
- if (homeTask == null) {
- // Create home task if there isn't one.
- homeTask = new TaskBuilder(mSupervisor).setStack(homeStask).build();
- }
-
- final ActivityRecord topActivity = new ActivityBuilder(mService).setTask(mTask).build();
- mStack.moveToFront("testAdjustFocusedStack");
-
- // Simulate that home activity has not been started or is force-stopped.
- homeStask.removeTask(homeTask, "testAdjustFocusedStack", REMOVE_TASK_MODE_DESTROYING);
-
- // Finish the only activity.
- topActivity.finishIfPossible("testAdjustFocusedStack", false /* oomAdj */);
- // Although home stack is empty, it should still be the focused stack.
- assertEquals(homeStask, mDefaultDisplay.getFocusedStack());
- }
-
- @Test
public void testWontFinishHomeStackImmediately() {
final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
index ace5d4efa39b..a28bbb60d70c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
@@ -715,7 +715,7 @@ public class ActivityStarterTests extends ActivityTestsBase {
if (startedActivity != null && startedActivity.getTaskRecord() != null) {
// Remove the activity so it doesn't interfere with with subsequent activity launch
// tests from this method.
- startedActivity.getTaskRecord().mTask.removeChild(startedActivity);
+ startedActivity.getTaskRecord().removeChild(startedActivity);
}
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
index 78db6c92772f..1db8f1b1b596 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
@@ -269,7 +269,7 @@ class ActivityTestsBase extends SystemServiceTestsBase {
// fullscreen value is normally read from resources in ctor, so for testing we need
// to set it somewhere else since we can't mock resources.
doReturn(true).when(activity).occludesParent();
- activity.setTask(mTaskRecord);
+ mTaskRecord.addChild(activity);
// Make visible by default...
activity.setHidden(false);
}
@@ -376,15 +376,13 @@ class ActivityTestsBase extends SystemServiceTestsBase {
final TaskRecord task = new TaskRecord(mSupervisor.mService, mTaskId, aInfo,
intent /*intent*/, mVoiceSession, null /*_voiceInteractor*/,
- null /*taskDescription*/);
+ null /*taskDescription*/, mStack);
spyOn(task);
task.mUserId = mUserId;
if (mStack != null) {
mStack.moveToFront("test");
- mStack.addTask(task, true, "creating test task");
- task.createTask(true, true);
- spyOn(task.mTask);
+ mStack.addChild(task, true, true);
}
return task;
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java
index 1fb6a563aa40..c5301b8a8c6e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java
@@ -165,7 +165,7 @@ public class AppChangeTransitionTests extends WindowTestsBase {
// setup currently defaults to no snapshot.
setUpOnDisplay(mDisplayContent);
- mTask.mTaskRecord.setWindowingMode(WINDOWING_MODE_FREEFORM);
+ mTask.setWindowingMode(WINDOWING_MODE_FREEFORM);
assertEquals(1, mDisplayContent.mChangingApps.size());
assertTrue(mActivity.isInChangeTransition());
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
index 2f0486d3e81b..d33dbd1dda7c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
@@ -48,7 +48,7 @@ import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
+import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
import android.content.res.Configuration;
@@ -63,7 +63,6 @@ import androidx.test.filters.SmallTest;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.mockito.Mockito;
/**
* Tests for the {@link ActivityRecord} class.
@@ -209,9 +208,11 @@ public class AppWindowTokenTests extends WindowTestsBase {
@Test
public void testSizeCompatBounds() {
+ // TODO(task-merge): Move once Task is merged into TaskRecord
+ final TaskRecord tr = (TaskRecord) mTask;
// Disable the real configuration resolving because we only simulate partial flow.
// TODO: Have test use full flow.
- doNothing().when(mTask.mTaskRecord).computeConfigResourceOverrides(any(), any());
+ doNothing().when(tr).computeConfigResourceOverrides(any(), any());
final Rect fixedBounds = mActivity.getRequestedOverrideConfiguration().windowConfiguration
.getBounds();
fixedBounds.set(0, 0, 1200, 1600);
@@ -337,11 +338,9 @@ public class AppWindowTokenTests extends WindowTestsBase {
mDisplayContent.getDisplayRotation().setFixedToUserRotation(
DisplayRotation.FIXED_TO_USER_ROTATION_ENABLED);
-
- mTask.mTaskRecord = Mockito.mock(TaskRecord.class, RETURNS_DEEP_STUBS);
+ reset(mTask);
mActivity.reportDescendantOrientationChangeIfNeeded();
-
- verify(mTask.mTaskRecord).onConfigurationChanged(any(Configuration.class));
+ verify(mTask).onConfigurationChanged(any(Configuration.class));
}
@Test
@@ -451,6 +450,7 @@ public class AppWindowTokenTests extends WindowTestsBase {
@Test
public void testTransitionAnimationBounds() {
+ removeGlobalMinSizeRestriction();
final Rect stackBounds = new Rect(0, 0, 1000, 600);
final Rect taskBounds = new Rect(100, 400, 600, 800);
mStack.setBounds(stackBounds);
@@ -458,16 +458,16 @@ public class AppWindowTokenTests extends WindowTestsBase {
// Check that anim bounds for freeform window match task bounds
mTask.setWindowingMode(WINDOWING_MODE_FREEFORM);
- assertEquals(taskBounds, mActivity.getAnimationBounds(STACK_CLIP_NONE));
+ assertEquals(mTask.getBounds(), mActivity.getAnimationBounds(STACK_CLIP_NONE));
// STACK_CLIP_AFTER_ANIM should use task bounds since they will be clipped by
// bounds animation layer.
mTask.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
- assertEquals(taskBounds, mActivity.getAnimationBounds(STACK_CLIP_AFTER_ANIM));
+ assertEquals(mTask.getBounds(), mActivity.getAnimationBounds(STACK_CLIP_AFTER_ANIM));
// STACK_CLIP_BEFORE_ANIM should use stack bounds since it won't be clipped later.
mTask.setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
- assertEquals(stackBounds, mActivity.getAnimationBounds(STACK_CLIP_BEFORE_ANIM));
+ assertEquals(mStack.getBounds(), mActivity.getAnimationBounds(STACK_CLIP_BEFORE_ANIM));
}
@Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
index 8c2ae5a7659a..55947ae9626f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
@@ -178,11 +178,14 @@ public class InsetsPolicyTest extends WindowTestsBase {
@Test
public void testShowTransientBars_topCanBeTransient_appGetsTopFakeControl() {
+ // Adding app window before setting source visibility is to prevent the visibility from
+ // being cleared by InsetsSourceProvider.updateVisibility.
+ final WindowState app = addWindow(TYPE_APPLICATION, "app");
+
addWindow(TYPE_STATUS_BAR, "topBar")
.getControllableInsetProvider().getSource().setVisible(false);
addWindow(TYPE_NAVIGATION_BAR, "navBar")
.getControllableInsetProvider().getSource().setVisible(true);
- final WindowState app = addWindow(TYPE_APPLICATION, "app");
final InsetsPolicy policy = mDisplayContent.getInsetsPolicy();
policy.updateBarControlTarget(app);
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
index cc598ffa63bd..69091c61ec90 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
@@ -885,7 +885,7 @@ public class RecentTasksTest extends ActivityTestsBase {
final int taskId = task.mTaskId;
mRecentTasks.add(task);
// Only keep the task in RecentTasks.
- task.removeWindowContainer();
+ task.removeIfPossible();
mStack.remove();
// The following APIs should not restore task from recents to the active list.
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
index 839ddb2038ff..ca8f5351c73a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
@@ -196,9 +196,6 @@ public class RecentsAnimationTest extends ActivityTestsBase {
doReturn(app).when(mService).getProcessController(eq(recentActivity.processName), anyInt());
ClientLifecycleManager lifecycleManager = mService.getLifecycleManager();
doNothing().when(lifecycleManager).scheduleTransaction(any());
- AppWarnings appWarnings = mService.getAppWarningsLocked();
- spyOn(appWarnings);
- doNothing().when(appWarnings).onStartActivity(any());
startRecentsActivity();
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
index aa97de72e507..63f70c05f203 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
@@ -36,7 +36,6 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.server.wm.ActivityDisplay.POSITION_TOP;
-import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
import static com.android.server.wm.ActivityStackSupervisor.ON_TOP;
import static com.android.server.wm.RootActivityContainer.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE;
@@ -272,8 +271,7 @@ public class RootActivityContainerTests extends ActivityTestsBase {
assertTrue(pinnedActivity.isFocusable());
// Without the overridding activity, stack should not be focusable.
- pinnedStack.removeTask(pinnedActivity.getTaskRecord(), "testFocusability",
- REMOVE_TASK_MODE_DESTROYING);
+ pinnedStack.removeChild(pinnedActivity.getTaskRecord(), "testFocusability");
assertFalse(pinnedStack.isFocusable());
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
index fa1f435a37c0..ad1d1afe7603 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
@@ -437,6 +437,10 @@ public class SystemServicesTestRule implements TestRule {
spyOn(getLockTaskController());
spyOn(getTaskChangeNotificationController());
initRootActivityContainerMocks();
+
+ AppWarnings appWarnings = getAppWarningsLocked();
+ spyOn(appWarnings);
+ doNothing().when(appWarnings).onStartActivity(any());
}
void initRootActivityContainerMocks() {
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskPositionerTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskPositionerTests.java
index df55b39b0817..012eb5252c50 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskPositionerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskPositionerTests.java
@@ -79,8 +79,9 @@ public class TaskPositionerTests extends WindowTestsBase {
// This should be the same calculation as the TaskPositioner uses.
mMinVisibleWidth = dipToPixel(MINIMUM_VISIBLE_WIDTH_IN_DP, dm);
mMinVisibleHeight = dipToPixel(MINIMUM_VISIBLE_HEIGHT_IN_DP, dm);
+ removeGlobalMinSizeRestriction();
- mPositioner = new TaskPositioner(mWm, mock(IActivityTaskManager.class));
+ mPositioner = new TaskPositioner(mWm, mWm.mAtmService);
mPositioner.register(mDisplayContent);
mWindow = createWindow(null, TYPE_BASE_APPLICATION, "window");
@@ -493,10 +494,7 @@ public class TaskPositionerTests extends WindowTestsBase {
+ ") " + Log.getStackTraceString(new Throwable()));
}
}
- assertEquals("left", expected.left, actual.left);
- assertEquals("right", expected.right, actual.right);
- assertEquals("top", expected.top, actual.top);
- assertEquals("bottom", expected.bottom, actual.bottom);
+ assertEquals(expected, actual);
}
@FlakyTest(bugId = 129492888)
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskPositioningControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskPositioningControllerTests.java
index f8d49ad18664..d2342f081fa1 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskPositioningControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskPositioningControllerTests.java
@@ -66,7 +66,8 @@ public class TaskPositioningControllerTests extends WindowTestsBase {
any(InputChannel.class))).thenReturn(true);
mWindow = createWindow(null, TYPE_BASE_APPLICATION, "window");
- mWindow.getTask().setResizeable(RESIZE_MODE_RESIZEABLE);
+ // TODO(task-merge): Remove cast.
+ ((TaskRecord) mWindow.getTask()).setResizeMode(RESIZE_MODE_RESIZEABLE);
mWindow.mInputChannel = new InputChannel();
mWm.mWindowMap.put(mWindow.mClient.asBinder(), mWindow);
doReturn(mock(InputMonitor.class)).when(mDisplayContent).getInputMonitor();
@@ -142,7 +143,8 @@ public class TaskPositioningControllerTests extends WindowTestsBase {
doReturn(mWindow.getTask()).when(content).findTaskForResizePoint(anyInt(), anyInt());
assertNotNull(mWindow.getTask().getTopVisibleAppMainWindow());
- mWindow.getTask().setResizeable(RESIZE_MODE_UNRESIZEABLE);
+ // TODO(task-merge): Remove cast.
+ ((TaskRecord) mWindow.getTask()).setResizeMode(RESIZE_MODE_UNRESIZEABLE);
mTarget.handleTapOutsideTask(content, 0, 0);
// Wait until the looper processes finishTaskPositioning.
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
index a4e38f15e0e7..2cafc965e648 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
@@ -132,7 +132,7 @@ public class TaskRecordTests extends ActivityTestsBase {
@Test
public void testCopyBaseIntentForTaskInfo() {
final TaskRecord task = createTaskRecord(1);
- task.mTaskDescription = new ActivityManager.TaskDescription();
+ task.setTaskDescription(new ActivityManager.TaskDescription());
final TaskInfo info = task.getTaskInfo();
// The intent of info should be a copy so assert that they are different instances.
@@ -348,10 +348,12 @@ public class TaskRecordTests extends ActivityTestsBase {
TaskRecord task = stack.getChildAt(0);
ActivityRecord root = task.getTopActivity();
- final WindowContainer parentWindowContainer = mock(WindowContainer.class);
- Mockito.doReturn(parentWindowContainer).when(task.mTask).getParent();
- Mockito.doReturn(true).when(parentWindowContainer)
- .handlesOrientationChangeFromDescendant();
+ final WindowContainer parentWindowContainer =
+ new WindowContainer(mSystemServicesTestRule.getWindowManagerService());
+ spyOn(parentWindowContainer);
+ parentWindowContainer.setBounds(fullScreenBounds);
+ doReturn(parentWindowContainer).when(task).getParent();
+ doReturn(true).when(parentWindowContainer).handlesOrientationChangeFromDescendant();
// Setting app to fixed portrait fits within parent, but TaskRecord shouldn't adjust the
// bounds because its parent says it will handle it at a later time.
@@ -433,7 +435,7 @@ public class TaskRecordTests extends ActivityTestsBase {
info.targetActivity = targetClassName;
final TaskRecord task = TaskRecord.create(mService, 1 /* taskId */, info, intent,
- null /* taskDescription */);
+ null /* taskDescription */, null /*stack*/);
assertEquals("The alias activity component should be saved in task intent.", aliasClassName,
task.intent.getComponent().getClassName());
@@ -834,8 +836,9 @@ public class TaskRecordTests extends ActivityTestsBase {
private TaskRecord createTaskRecord(int taskId) {
return new TaskRecord(mService, taskId, new Intent(), null, null, null,
ActivityBuilder.getDefaultComponent(), null, false, false, false, 0, 10050, null,
- new ArrayList<>(), 0, false, null, 0, 0, 0, 0, 0, null, 0, false, false, false, 0,
- 0, null /*ActivityInfo*/, null /*_voiceSession*/, null /*_voiceInteractor*/);
+ 0, false, null, 0, 0, 0, 0, 0, null, 0, false, false, false, 0,
+ 0, null /*ActivityInfo*/, null /*_voiceSession*/, null /*_voiceInteractor*/,
+ null /*stack*/);
}
private static class TestTaskRecordFactory extends TaskRecordFactory {
@@ -843,16 +846,16 @@ public class TaskRecordTests extends ActivityTestsBase {
@Override
TaskRecord create(ActivityTaskManagerService service, int taskId, ActivityInfo info,
- Intent intent,
- IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor) {
+ Intent intent, IVoiceInteractionSession voiceSession,
+ IVoiceInteractor voiceInteractor, ActivityStack stack) {
mCreated = true;
return null;
}
@Override
TaskRecord create(ActivityTaskManagerService service, int taskId, ActivityInfo info,
- Intent intent,
- ActivityManager.TaskDescription taskDescription) {
+ Intent intent, ActivityManager.TaskDescription taskDescription,
+ ActivityStack stack) {
mCreated = true;
return null;
}
@@ -863,14 +866,14 @@ public class TaskRecordTests extends ActivityTestsBase {
ComponentName realActivity,
ComponentName origActivity, boolean rootWasReset, boolean autoRemoveRecents,
boolean askedCompatMode, int userId, int effectiveUid, String lastDescription,
- ArrayList<ActivityRecord> activities, long lastTimeMoved,
+ long lastTimeMoved,
boolean neverRelinquishIdentity,
ActivityManager.TaskDescription lastTaskDescription,
int taskAffiliation, int prevTaskId, int nextTaskId, int taskAffiliationColor,
int callingUid, String callingPackage, int resizeMode,
boolean supportsPictureInPicture,
boolean realActivitySuspended, boolean userSetupComplete, int minWidth,
- int minHeight) {
+ int minHeight, ActivityStack stack) {
mCreated = true;
return null;
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
index 4dfa26644fa9..cb2e1e03a446 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
@@ -16,6 +16,8 @@
package com.android.server.wm;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
@@ -92,7 +94,7 @@ public class TaskTests extends WindowTestsBase {
boolean gotException = false;
try {
- task.reparent(stackController1, 0, false/* moveParents */);
+ task.reparent(stackController1, 0, false/* moveParents */, "testReparent");
} catch (IllegalArgumentException e) {
gotException = true;
}
@@ -100,14 +102,14 @@ public class TaskTests extends WindowTestsBase {
gotException = false;
try {
- task.reparent(null, 0, false/* moveParents */);
+ task.reparent(null, 0, false/* moveParents */, "testReparent");
} catch (IllegalArgumentException e) {
gotException = true;
}
assertTrue("Should not be able to reparent to a stack that doesn't exist",
gotException);
- task.reparent(stackController2, 0, false/* moveParents */);
+ task.reparent(stackController2, 0, false/* moveParents */, "testReparent");
assertEquals(stackController2, task.getParent());
assertEquals(0, task.getParent().mChildren.indexOf(task));
assertEquals(1, task2.getParent().mChildren.indexOf(task2));
@@ -125,7 +127,7 @@ public class TaskTests extends WindowTestsBase {
final TaskStack stack2 = createTaskStackOnDisplay(dc);
final Task task2 = createTaskInStack(stack2, 0 /* userId */);
// Reparent and check state
- task.reparent(stack2, 0, false /* moveParents */);
+ task.reparent(stack2, 0, false /* moveParents */, "testReparent_BetweenDisplays");
assertEquals(stack2, task.getParent());
assertEquals(0, task.getParent().mChildren.indexOf(task));
assertEquals(1, task2.getParent().mChildren.indexOf(task2));
@@ -138,6 +140,7 @@ public class TaskTests extends WindowTestsBase {
final Task task = createTaskInStack(stack1, 0 /* userId */);
// Check that setting bounds also updates surface position
+ task.setWindowingMode(WINDOWING_MODE_FREEFORM);
Rect bounds = new Rect(10, 10, 100, 200);
task.setBounds(bounds);
assertEquals(new Point(bounds.left, bounds.top), task.getLastSurfacePosition());
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java
index 8cd97cb8a344..428d869fe3cd 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java
@@ -255,6 +255,7 @@ public class WindowFrameTests extends WindowTestsBase {
@Test
public void testLayoutNonfullscreenTask() {
+ removeGlobalMinSizeRestriction();
final DisplayInfo displayInfo = mWm.getDefaultDisplayContentLocked().getDisplayInfo();
final int logicalWidth = displayInfo.logicalWidth;
final int logicalHeight = displayInfo.logicalHeight;
@@ -264,8 +265,8 @@ public class WindowFrameTests extends WindowTestsBase {
WindowState w = createWindow();
final Task task = w.getTask();
// Use split-screen because it is non-fullscreen, but also not floating
- task.mTaskRecord.setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
- task.mTaskRecord.setBounds(taskBounds);
+ task.setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
+ task.setBounds(taskBounds);
// The bounds we are requesting might be different from what the system resolved based on
// other factors.
final Rect resolvedTaskBounds = task.getBounds();
@@ -303,8 +304,8 @@ public class WindowFrameTests extends WindowTestsBase {
final int insetTop = logicalHeight / 5;
final int insetRight = insetLeft + (resolvedTaskBounds.right - resolvedTaskBounds.left);
final int insetBottom = insetTop + (resolvedTaskBounds.bottom - resolvedTaskBounds.top);
- task.mTaskRecord.setDisplayedBounds(resolvedTaskBounds);
- task.mTaskRecord.setBounds(insetLeft, insetTop, insetRight, insetBottom);
+ task.setOverrideDisplayedBounds(resolvedTaskBounds);
+ task.setBounds(insetLeft, insetTop, insetRight, insetBottom);
windowFrames.setFrames(pf, pf, pf, cf, cf, pf, cf, mEmptyRect);
w.computeFrameLw();
assertEquals(resolvedTaskBounds, w.getFrameLw());
@@ -477,7 +478,7 @@ public class WindowFrameTests extends WindowTestsBase {
WindowState w = createWindow();
final Task task = w.getTask();
w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
- task.mTaskRecord.setWindowingMode(WINDOWING_MODE_FREEFORM);
+ task.setWindowingMode(WINDOWING_MODE_FREEFORM);
DisplayContent dc = mTestDisplayContent;
dc.mInputMethodTarget = w;
@@ -499,7 +500,7 @@ public class WindowFrameTests extends WindowTestsBase {
// First check that it only gets moved up enough to show window.
final Rect winRect = new Rect(200, 200, 300, 500);
- task.mTaskRecord.setBounds(winRect);
+ task.setBounds(winRect);
w.getWindowFrames().setFrames(pf, df, of, cf, vf, dcf, sf, mEmptyRect);
w.computeFrameLw();
@@ -511,7 +512,7 @@ public class WindowFrameTests extends WindowTestsBase {
// Now check that it won't get moved beyond the top and then has appropriate insets
winRect.bottom = 600;
- task.mTaskRecord.setBounds(winRect);
+ task.setBounds(winRect);
w.setBounds(winRect);
w.getWindowFrames().setFrames(pf, df, of, cf, vf, dcf, sf, mEmptyRect);
w.computeFrameLw();
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
index 51daf6567a47..3f32e33a76ec 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
@@ -42,7 +42,7 @@ class WindowTestUtils {
.setUserId(userId)
.setStack(stack.mActivityStack)
.build();
- return task.mTask;
+ return task;
}
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
index 780fed9805cb..c3f59eb75460 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -384,7 +384,7 @@ class WindowTestsBase extends SystemServiceTestsBase {
}
/** Sets the default minimum task size to 1 so that tests can use small task sizes */
- public void removeGlobalMinSizeRestriction() {
+ void removeGlobalMinSizeRestriction() {
mWm.mAtmService.mRootActivityContainer.mDefaultMinSizeOfResizeableTaskDp = 1;
}
}
diff --git a/services/usage/java/com/android/server/usage/UsageStatsProtoV2.java b/services/usage/java/com/android/server/usage/UsageStatsProtoV2.java
index 7d8e430e5416..b68e04f9b29f 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsProtoV2.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsProtoV2.java
@@ -448,10 +448,10 @@ final class UsageStatsProtoV2 {
final long packagesToken = proto.start(
IntervalStatsObfuscatedProto.PACKAGES);
UsageStats usageStats = parseUsageStats(proto, stats.beginTime);
+ proto.end(packagesToken);
if (usageStats.mPackageToken != PackagesTokenData.UNASSIGNED_TOKEN) {
stats.packageStatsObfuscated.put(usageStats.mPackageToken, usageStats);
}
- proto.end(packagesToken);
} catch (IOException e) {
Slog.e(TAG, "Unable to read some usage stats from proto.", e);
}
@@ -484,6 +484,13 @@ final class UsageStatsProtoV2 {
if (stats.endTime == 0) {
stats.endTime = stats.beginTime;
}
+ // update the begin and end time stamps for all usage stats
+ final int usageStatsSize = stats.packageStatsObfuscated.size();
+ for (int i = 0; i < usageStatsSize; i++) {
+ final UsageStats usageStats = stats.packageStatsObfuscated.valueAt(i);
+ usageStats.mBeginTimeStamp = stats.beginTime;
+ usageStats.mEndTimeStamp = stats.endTime;
+ }
return;
}
}
diff --git a/startop/view_compiler/Android.bp b/startop/view_compiler/Android.bp
index c380d291d573..7cc233b2439e 100644
--- a/startop/view_compiler/Android.bp
+++ b/startop/view_compiler/Android.bp
@@ -16,7 +16,6 @@
cc_defaults {
name: "viewcompiler_defaults",
- defaults: ["libdexfile_static_defaults"],
header_libs: [
"libbase_headers",
],
@@ -30,6 +29,7 @@ cc_defaults {
"liblog",
"libutils",
"libziparchive",
+ "libz",
],
cppflags: ["-std=c++17"],
target: {
diff --git a/startop/view_compiler/dex_builder.cc b/startop/view_compiler/dex_builder.cc
index 48b44d0fc99b..50cf5a50d7a8 100644
--- a/startop/view_compiler/dex_builder.cc
+++ b/startop/view_compiler/dex_builder.cc
@@ -16,8 +16,6 @@
#include "dex_builder.h"
-#include "dex/descriptors_names.h"
-
#include <fstream>
#include <memory>
@@ -30,8 +28,6 @@ using std::string;
using ::dex::kAccPublic;
using Op = Instruction::Op;
-using Opcode = ::art::Instruction::Code;
-
const TypeDescriptor TypeDescriptor::Int() { return TypeDescriptor{"I"}; };
const TypeDescriptor TypeDescriptor::Void() { return TypeDescriptor{"V"}; };
@@ -43,20 +39,29 @@ constexpr uint8_t kDexFileMagic[]{0x64, 0x65, 0x78, 0x0a, 0x30, 0x33, 0x38, 0x00
constexpr size_t kMaxEncodedStringLength{5};
// Converts invoke-* to invoke-*/range
-constexpr Opcode InvokeToInvokeRange(Opcode opcode) {
+constexpr ::dex::Opcode InvokeToInvokeRange(::dex::Opcode opcode) {
switch (opcode) {
- case ::art::Instruction::INVOKE_VIRTUAL:
- return ::art::Instruction::INVOKE_VIRTUAL_RANGE;
- case ::art::Instruction::INVOKE_DIRECT:
- return ::art::Instruction::INVOKE_DIRECT_RANGE;
- case ::art::Instruction::INVOKE_STATIC:
- return ::art::Instruction::INVOKE_STATIC_RANGE;
- case ::art::Instruction::INVOKE_INTERFACE:
- return ::art::Instruction::INVOKE_INTERFACE_RANGE;
+ case ::dex::Opcode::OP_INVOKE_VIRTUAL:
+ return ::dex::Opcode::OP_INVOKE_VIRTUAL_RANGE;
+ case ::dex::Opcode::OP_INVOKE_DIRECT:
+ return ::dex::Opcode::OP_INVOKE_DIRECT_RANGE;
+ case ::dex::Opcode::OP_INVOKE_STATIC:
+ return ::dex::Opcode::OP_INVOKE_STATIC_RANGE;
+ case ::dex::Opcode::OP_INVOKE_INTERFACE:
+ return ::dex::Opcode::OP_INVOKE_INTERFACE_RANGE;
default:
LOG(FATAL) << opcode << " is not a recognized invoke opcode.";
- UNREACHABLE();
+ __builtin_unreachable();
+ }
+}
+
+std::string DotToDescriptor(const char* class_name) {
+ std::string descriptor(class_name);
+ std::replace(descriptor.begin(), descriptor.end(), '.', '/');
+ if (descriptor.length() > 0 && descriptor[0] != '[') {
+ descriptor = "L" + descriptor + ";";
}
+ return descriptor;
}
} // namespace
@@ -178,7 +183,7 @@ void WriteTestDexFile(const string& filename) {
}
TypeDescriptor TypeDescriptor::FromClassname(const std::string& name) {
- return TypeDescriptor{art::DotToDescriptor(name.c_str())};
+ return TypeDescriptor{DotToDescriptor(name.c_str())};
}
DexBuilder::DexBuilder() : dex_file_{std::make_shared<ir::DexFile>()} {
@@ -219,11 +224,11 @@ ir::String* DexBuilder::GetOrAddString(const std::string& string) {
ClassBuilder DexBuilder::MakeClass(const std::string& name) {
auto* class_def = Alloc<ir::Class>();
- ir::Type* type_def = GetOrAddType(art::DotToDescriptor(name.c_str()));
+ ir::Type* type_def = GetOrAddType(DotToDescriptor(name.c_str()));
type_def->class_def = class_def;
class_def->type = type_def;
- class_def->super_class = GetOrAddType(art::DotToDescriptor("java.lang.Object"));
+ class_def->super_class = GetOrAddType(DotToDescriptor("java.lang.Object"));
class_def->access_flags = kAccPublic;
return ClassBuilder{this, name, class_def};
}
@@ -378,26 +383,26 @@ void MethodBuilder::EncodeInstructions() {
void MethodBuilder::EncodeInstruction(const Instruction& instruction) {
switch (instruction.opcode()) {
case Instruction::Op::kReturn:
- return EncodeReturn(instruction, ::art::Instruction::RETURN);
+ return EncodeReturn(instruction, ::dex::Opcode::OP_RETURN);
case Instruction::Op::kReturnObject:
- return EncodeReturn(instruction, ::art::Instruction::RETURN_OBJECT);
+ return EncodeReturn(instruction, ::dex::Opcode::OP_RETURN_OBJECT);
case Instruction::Op::kMove:
case Instruction::Op::kMoveObject:
return EncodeMove(instruction);
case Instruction::Op::kInvokeVirtual:
- return EncodeInvoke(instruction, art::Instruction::INVOKE_VIRTUAL);
+ return EncodeInvoke(instruction, ::dex::Opcode::OP_INVOKE_VIRTUAL);
case Instruction::Op::kInvokeDirect:
- return EncodeInvoke(instruction, art::Instruction::INVOKE_DIRECT);
+ return EncodeInvoke(instruction, ::dex::Opcode::OP_INVOKE_DIRECT);
case Instruction::Op::kInvokeStatic:
- return EncodeInvoke(instruction, art::Instruction::INVOKE_STATIC);
+ return EncodeInvoke(instruction, ::dex::Opcode::OP_INVOKE_STATIC);
case Instruction::Op::kInvokeInterface:
- return EncodeInvoke(instruction, art::Instruction::INVOKE_INTERFACE);
+ return EncodeInvoke(instruction, ::dex::Opcode::OP_INVOKE_INTERFACE);
case Instruction::Op::kBindLabel:
return BindLabel(instruction.args()[0]);
case Instruction::Op::kBranchEqz:
- return EncodeBranch(art::Instruction::IF_EQZ, instruction);
+ return EncodeBranch(::dex::Opcode::OP_IF_EQZ, instruction);
case Instruction::Op::kBranchNEqz:
- return EncodeBranch(art::Instruction::IF_NEZ, instruction);
+ return EncodeBranch(::dex::Opcode::OP_IF_NEZ, instruction);
case Instruction::Op::kNew:
return EncodeNew(instruction);
case Instruction::Op::kCheckCast:
@@ -410,10 +415,10 @@ void MethodBuilder::EncodeInstruction(const Instruction& instruction) {
}
}
-void MethodBuilder::EncodeReturn(const Instruction& instruction, ::art::Instruction::Code opcode) {
+void MethodBuilder::EncodeReturn(const Instruction& instruction, ::dex::Opcode opcode) {
CHECK(!instruction.dest().has_value());
if (instruction.args().size() == 0) {
- Encode10x(art::Instruction::RETURN_VOID);
+ Encode10x(::dex::Opcode::OP_RETURN_VOID);
} else {
CHECK_EQ(1, instruction.args().size());
size_t source = RegisterValue(instruction.args()[0]);
@@ -433,27 +438,27 @@ void MethodBuilder::EncodeMove(const Instruction& instruction) {
if (source.is_immediate()) {
// TODO: support more registers
CHECK_LT(RegisterValue(*instruction.dest()), 16);
- Encode11n(art::Instruction::CONST_4, RegisterValue(*instruction.dest()), source.value());
+ Encode11n(::dex::Opcode::OP_CONST_4, RegisterValue(*instruction.dest()), source.value());
} else if (source.is_string()) {
constexpr size_t kMaxRegisters = 256;
CHECK_LT(RegisterValue(*instruction.dest()), kMaxRegisters);
CHECK_LT(source.value(), 65536); // make sure we don't need a jumbo string
- Encode21c(::art::Instruction::CONST_STRING, RegisterValue(*instruction.dest()), source.value());
+ Encode21c(::dex::Opcode::OP_CONST_STRING, RegisterValue(*instruction.dest()), source.value());
} else if (source.is_variable()) {
// For the moment, we only use this when we need to reshuffle registers for
// an invoke instruction, meaning we are too big for the 4-bit version.
// We'll err on the side of caution and always generate the 16-bit form of
// the instruction.
- Opcode opcode = instruction.opcode() == Instruction::Op::kMove
- ? ::art::Instruction::MOVE_16
- : ::art::Instruction::MOVE_OBJECT_16;
+ auto opcode = instruction.opcode() == Instruction::Op::kMove
+ ? ::dex::Opcode::OP_MOVE_16
+ : ::dex::Opcode::OP_MOVE_OBJECT_16;
Encode32x(opcode, RegisterValue(*instruction.dest()), RegisterValue(source));
} else {
UNIMPLEMENTED(FATAL);
}
}
-void MethodBuilder::EncodeInvoke(const Instruction& instruction, ::art::Instruction::Code opcode) {
+void MethodBuilder::EncodeInvoke(const Instruction& instruction, ::dex::Opcode opcode) {
constexpr size_t kMaxArgs = 5;
// Currently, we only support up to 5 arguments.
@@ -480,8 +485,8 @@ void MethodBuilder::EncodeInvoke(const Instruction& instruction, ::art::Instruct
for (size_t i = 0; i < instruction.args().size(); ++i) {
Instruction::Op move_op;
- if (opcode == ::art::Instruction::INVOKE_VIRTUAL ||
- opcode == ::art::Instruction::INVOKE_DIRECT) {
+ if (opcode == ::dex::Opcode::OP_INVOKE_VIRTUAL ||
+ opcode == ::dex::Opcode::OP_INVOKE_DIRECT) {
// In this case, there is an implicit `this` argument, which is always an object.
if (i == 0) {
move_op = Instruction::Op::kMoveObject;
@@ -514,8 +519,8 @@ void MethodBuilder::EncodeInvoke(const Instruction& instruction, ::art::Instruct
// If there is a return value, add a move-result instruction
if (instruction.dest().has_value()) {
- Encode11x(instruction.result_is_object() ? art::Instruction::MOVE_RESULT_OBJECT
- : art::Instruction::MOVE_RESULT,
+ Encode11x(instruction.result_is_object() ? ::dex::Opcode::OP_MOVE_RESULT_OBJECT
+ : ::dex::Opcode::OP_MOVE_RESULT,
RegisterValue(*instruction.dest()));
}
@@ -523,7 +528,7 @@ void MethodBuilder::EncodeInvoke(const Instruction& instruction, ::art::Instruct
}
// Encodes a conditional branch that tests a single argument.
-void MethodBuilder::EncodeBranch(art::Instruction::Code op, const Instruction& instruction) {
+void MethodBuilder::EncodeBranch(::dex::Opcode op, const Instruction& instruction) {
const auto& args = instruction.args();
const auto& test_value = args[0];
const auto& branch_target = args[1];
@@ -546,7 +551,7 @@ void MethodBuilder::EncodeNew(const Instruction& instruction) {
const Value& type = instruction.args()[0];
CHECK_LT(RegisterValue(*instruction.dest()), 256);
CHECK(type.is_type());
- Encode21c(::art::Instruction::NEW_INSTANCE, RegisterValue(*instruction.dest()), type.value());
+ Encode21c(::dex::Opcode::OP_NEW_INSTANCE, RegisterValue(*instruction.dest()), type.value());
}
void MethodBuilder::EncodeCast(const Instruction& instruction) {
@@ -558,7 +563,7 @@ void MethodBuilder::EncodeCast(const Instruction& instruction) {
const Value& type = instruction.args()[0];
CHECK_LT(RegisterValue(*instruction.dest()), 256);
CHECK(type.is_type());
- Encode21c(::art::Instruction::CHECK_CAST, RegisterValue(*instruction.dest()), type.value());
+ Encode21c(::dex::Opcode::OP_CHECK_CAST, RegisterValue(*instruction.dest()), type.value());
}
void MethodBuilder::EncodeFieldOp(const Instruction& instruction) {
@@ -569,7 +574,7 @@ void MethodBuilder::EncodeFieldOp(const Instruction& instruction) {
CHECK(instruction.dest()->is_variable());
CHECK_EQ(0, instruction.args().size());
- Encode21c(::art::Instruction::SGET,
+ Encode21c(::dex::Opcode::OP_SGET,
RegisterValue(*instruction.dest()),
instruction.index_argument());
break;
@@ -579,7 +584,7 @@ void MethodBuilder::EncodeFieldOp(const Instruction& instruction) {
CHECK_EQ(1, args.size());
CHECK(args[0].is_variable());
- Encode21c(::art::Instruction::SPUT, RegisterValue(args[0]), instruction.index_argument());
+ Encode21c(::dex::Opcode::OP_SPUT, RegisterValue(args[0]), instruction.index_argument());
break;
}
case Instruction::Op::kGetInstanceField: {
@@ -587,7 +592,7 @@ void MethodBuilder::EncodeFieldOp(const Instruction& instruction) {
CHECK(instruction.dest()->is_variable());
CHECK_EQ(1, instruction.args().size());
- Encode22c(::art::Instruction::IGET,
+ Encode22c(::dex::Opcode::OP_IGET,
RegisterValue(*instruction.dest()),
RegisterValue(args[0]),
instruction.index_argument());
@@ -599,7 +604,7 @@ void MethodBuilder::EncodeFieldOp(const Instruction& instruction) {
CHECK(args[0].is_variable());
CHECK(args[1].is_variable());
- Encode22c(::art::Instruction::IPUT,
+ Encode22c(::dex::Opcode::OP_IPUT,
RegisterValue(args[1]),
RegisterValue(args[0]),
instruction.index_argument());
diff --git a/startop/view_compiler/dex_builder.h b/startop/view_compiler/dex_builder.h
index 3924e77fab59..3ae37ce1f762 100644
--- a/startop/view_compiler/dex_builder.h
+++ b/startop/view_compiler/dex_builder.h
@@ -24,7 +24,9 @@
#include <unordered_map>
#include <vector>
-#include "dex/dex_instruction.h"
+#include "android-base/logging.h"
+
+#include "slicer/dex_bytecode.h"
#include "slicer/dex_ir.h"
#include "slicer/writer.h"
@@ -364,11 +366,11 @@ class MethodBuilder {
// Encodes a return instruction. For instructions with no return value, the opcode field is
// ignored. Otherwise, this specifies which return instruction will be used (return,
// return-object, etc.)
- void EncodeReturn(const Instruction& instruction, ::art::Instruction::Code opcode);
+ void EncodeReturn(const Instruction& instruction, ::dex::Opcode opcode);
void EncodeMove(const Instruction& instruction);
- void EncodeInvoke(const Instruction& instruction, ::art::Instruction::Code opcode);
- void EncodeBranch(art::Instruction::Code op, const Instruction& instruction);
+ void EncodeInvoke(const Instruction& instruction, ::dex::Opcode opcode);
+ void EncodeBranch(::dex::Opcode op, const Instruction& instruction);
void EncodeNew(const Instruction& instruction);
void EncodeCast(const Instruction& instruction);
void EncodeFieldOp(const Instruction& instruction);
@@ -377,17 +379,18 @@ class MethodBuilder {
// https://source.android.com/devices/tech/dalvik/instruction-formats for documentation of
// formats.
- inline void Encode10x(art::Instruction::Code opcode) {
+ inline void Encode10x(::dex::Opcode opcode) {
// 00|op
- buffer_.push_back(opcode);
+ static_assert(sizeof(uint8_t) == sizeof(::dex::Opcode));
+ buffer_.push_back(static_cast<uint8_t>(opcode));
}
- inline void Encode11x(art::Instruction::Code opcode, uint8_t a) {
+ inline void Encode11x(::dex::Opcode opcode, uint8_t a) {
// aa|op
buffer_.push_back((a << 8) | opcode);
}
- inline void Encode11n(art::Instruction::Code opcode, uint8_t a, int8_t b) {
+ inline void Encode11n(::dex::Opcode opcode, uint8_t a, int8_t b) {
// b|a|op
// Make sure the fields are in bounds (4 bits for a, 4 bits for b).
@@ -398,13 +401,13 @@ class MethodBuilder {
buffer_.push_back(((b & 0xf) << 12) | (a << 8) | opcode);
}
- inline void Encode21c(art::Instruction::Code opcode, uint8_t a, uint16_t b) {
+ inline void Encode21c(::dex::Opcode opcode, uint8_t a, uint16_t b) {
// aa|op|bbbb
buffer_.push_back((a << 8) | opcode);
buffer_.push_back(b);
}
- inline void Encode22c(art::Instruction::Code opcode, uint8_t a, uint8_t b, uint16_t c) {
+ inline void Encode22c(::dex::Opcode opcode, uint8_t a, uint8_t b, uint16_t c) {
// b|a|op|bbbb
CHECK(IsShortRegister(a));
CHECK(IsShortRegister(b));
@@ -412,13 +415,13 @@ class MethodBuilder {
buffer_.push_back(c);
}
- inline void Encode32x(art::Instruction::Code opcode, uint16_t a, uint16_t b) {
+ inline void Encode32x(::dex::Opcode opcode, uint16_t a, uint16_t b) {
buffer_.push_back(opcode);
buffer_.push_back(a);
buffer_.push_back(b);
}
- inline void Encode35c(art::Instruction::Code opcode, size_t a, uint16_t b, uint8_t c, uint8_t d,
+ inline void Encode35c(::dex::Opcode opcode, size_t a, uint16_t b, uint8_t c, uint8_t d,
uint8_t e, uint8_t f, uint8_t g) {
// a|g|op|bbbb|f|e|d|c
@@ -433,7 +436,7 @@ class MethodBuilder {
buffer_.push_back((f << 12) | (e << 8) | (d << 4) | c);
}
- inline void Encode3rc(art::Instruction::Code opcode, size_t a, uint16_t b, uint16_t c) {
+ inline void Encode3rc(::dex::Opcode opcode, size_t a, uint16_t b, uint16_t c) {
CHECK_LE(a, 255);
buffer_.push_back((a << 8) | opcode);
buffer_.push_back(b);
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 010446492d16..dbada25f50a8 100755
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -828,13 +828,6 @@ public class CarrierConfigManager {
"disable_severe_when_extreme_disabled_bool";
/**
- * The message expiration time in milliseconds for duplicate detection purposes.
- * @hide
- */
- public static final String KEY_MESSAGE_EXPIRATION_TIME_LONG =
- "message_expiration_time_long";
-
- /**
* The data call retry configuration for different types of APN.
* @hide
*/
@@ -3371,7 +3364,6 @@ public class CarrierConfigManager {
sDefaults.putBoolean(KEY_BROADCAST_EMERGENCY_CALL_STATE_CHANGES_BOOL, false);
sDefaults.putBoolean(KEY_ALWAYS_SHOW_EMERGENCY_ALERT_ONOFF_BOOL, false);
sDefaults.putBoolean(KEY_DISABLE_SEVERE_WHEN_EXTREME_DISABLED_BOOL, true);
- sDefaults.putLong(KEY_MESSAGE_EXPIRATION_TIME_LONG, 86400000L);
sDefaults.putStringArray(KEY_CARRIER_DATA_CALL_RETRY_CONFIG_STRINGS, new String[]{
"default:default_randomization=2000,5000,10000,20000,40000,80000:5000,160000:5000,"
+ "320000:5000,640000:5000,1280000:5000,1800000:5000",
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index b5e91d0bad85..75e4fec97825 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -2371,12 +2371,10 @@ public class SubscriptionManager {
* @param plans the list of plans. The first plan is always the primary and
* most important plan. Any additional plans are secondary and
* may not be displayed or used by decision making logic.
- * The list of all plans must meet the requirements defined in
- * {@link SubscriptionPlan.Builder#setNetworkTypes(int[])}.
* @throws SecurityException if the caller doesn't meet the requirements
* outlined above.
* @throws IllegalArgumentException if plans don't meet the requirements
- * mentioned above.
+ * defined in {@link SubscriptionPlan}.
*/
public void setSubscriptionPlans(int subId, @NonNull List<SubscriptionPlan> plans) {
try {
diff --git a/telephony/java/android/telephony/SubscriptionPlan.java b/telephony/java/android/telephony/SubscriptionPlan.java
index e24eb2696c6c..28a5c2086ede 100644
--- a/telephony/java/android/telephony/SubscriptionPlan.java
+++ b/telephony/java/android/telephony/SubscriptionPlan.java
@@ -44,6 +44,14 @@ import java.util.Objects;
* as explaining how much mobile data they have remaining, and what will happen
* when they run out.
*
+ * If specifying network types, the developer must supply at least one plan
+ * that applies to all network types (default), and all additional plans
+ * may not include a particular network type more than once.
+ * This is enforced by {@link SubscriptionManager} when setting the plans.
+ *
+ * Plan selection will prefer plans that have specific network types defined
+ * over plans that apply to all network types.
+ *
* @see SubscriptionManager#setSubscriptionPlans(int, java.util.List)
* @see SubscriptionManager#getSubscriptionPlans(int)
*/
@@ -213,7 +221,7 @@ public final class SubscriptionPlan implements Parcelable {
/**
* Return an array containing all {@link NetworkType}s this SubscriptionPlan applies to.
- * A null array means this SubscriptionPlan applies to all network types.
+ * A null value means this SubscriptionPlan applies to all network types.
*/
public @Nullable @NetworkType int[] getNetworkTypes() {
return networkTypes;
@@ -372,20 +380,13 @@ public final class SubscriptionPlan implements Parcelable {
/**
* Set the network types this SubscriptionPlan applies to.
- * The developer must supply at least one plan that applies to all network types (default),
- * and all additional plans may not include a particular network type more than once.
- * Plan selection will prefer plans that have specific network types defined
- * over plans that apply to all network types.
*
* @param networkTypes a set of all {@link NetworkType}s that apply to this plan.
- * A null value or empty array means the plan applies to all network types.
+ * A null value means the plan applies to all network types,
+ * and an empty array means the plan applies to no network types.
*/
public @NonNull Builder setNetworkTypes(@Nullable @NetworkType int[] networkTypes) {
- if (networkTypes == null || networkTypes.length == 0) {
- plan.networkTypes = null;
- } else {
- plan.networkTypes = networkTypes;
- }
+ plan.networkTypes = networkTypes;
return this;
}
}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 0c663f85b99c..4eb5a362efae 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -9567,18 +9567,37 @@ public class TelephonyManager {
}
/**
- * Resets Telephony and IMS settings back to factory defaults.
+ * Resets telephony manager settings back to factory defaults.
*
* @hide
*/
- @SystemApi
- @RequiresPermission(Manifest.permission.CONNECTIVITY_INTERNAL)
public void factoryReset(int subId) {
try {
Log.d(TAG, "factoryReset: subId=" + subId);
ITelephony telephony = getITelephony();
- if (telephony != null)
+ if (telephony != null) {
telephony.factoryReset(subId);
+ }
+ } catch (RemoteException e) {
+ }
+ }
+
+
+ /**
+ * Resets Telephony and IMS settings back to factory defaults only for the subscription
+ * associated with this instance.
+ * @see #createForSubscriptionId(int)
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(Manifest.permission.CONNECTIVITY_INTERNAL)
+ public void resetSettings() {
+ try {
+ Log.d(TAG, "resetSettings: subId=" + getSubId());
+ ITelephony telephony = getITelephony();
+ if (telephony != null) {
+ telephony.factoryReset(getSubId());
+ }
} catch (RemoteException e) {
}
}
diff --git a/telephony/java/android/telephony/ims/ImsMmTelManager.java b/telephony/java/android/telephony/ims/ImsMmTelManager.java
index 7cafa1ea068c..9fc8e7563a81 100644
--- a/telephony/java/android/telephony/ims/ImsMmTelManager.java
+++ b/telephony/java/android/telephony/ims/ImsMmTelManager.java
@@ -254,8 +254,8 @@ public class ImsMmTelManager implements RegistrationManager {
* the {@link ImsService} associated with the subscription is not available. This can happen if
* the service crashed, for example. See {@link ImsException#getCode()} for a more detailed
* reason.
- * @deprecated Use {@link #registerImsRegistrationCallback(
- * RegistrationManager.RegistrationCallback, Executor)} instead.
+ * @deprecated Use {@link RegistrationManager#registerImsRegistrationCallback(Executor,
+ * RegistrationManager.RegistrationCallback)} instead.
*/
@Deprecated
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
@@ -285,9 +285,8 @@ public class ImsMmTelManager implements RegistrationManager {
/**{@inheritDoc}*/
@Override
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
- public void registerImsRegistrationCallback(
- @NonNull RegistrationManager.RegistrationCallback c,
- @NonNull @CallbackExecutor Executor executor) throws ImsException {
+ public void registerImsRegistrationCallback(@NonNull @CallbackExecutor Executor executor,
+ @NonNull RegistrationManager.RegistrationCallback c) throws ImsException {
if (c == null) {
throw new IllegalArgumentException("Must include a non-null RegistrationCallback.");
}
@@ -348,8 +347,8 @@ public class ImsMmTelManager implements RegistrationManager {
/**{@inheritDoc}*/
@Override
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
- public void getRegistrationState(@NonNull @ImsRegistrationState Consumer<Integer> stateCallback,
- @NonNull @CallbackExecutor Executor executor) {
+ public void getRegistrationState(@NonNull @CallbackExecutor Executor executor,
+ @NonNull @ImsRegistrationState Consumer<Integer> stateCallback) {
if (stateCallback == null) {
throw new IllegalArgumentException("Must include a non-null callback.");
}
@@ -371,9 +370,9 @@ public class ImsMmTelManager implements RegistrationManager {
/**{@inheritDoc}*/
@Override
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
- public void getRegistrationTransportType(
- @NonNull @AccessNetworkConstants.TransportType Consumer<Integer> transportTypeCallback,
- @NonNull @CallbackExecutor Executor executor) {
+ public void getRegistrationTransportType(@NonNull @CallbackExecutor Executor executor,
+ @NonNull @AccessNetworkConstants.TransportType
+ Consumer<Integer> transportTypeCallback) {
if (transportTypeCallback == null) {
throw new IllegalArgumentException("Must include a non-null callback.");
}
@@ -607,17 +606,17 @@ public class ImsMmTelManager implements RegistrationManager {
* {@link CarrierConfigManager#ACTION_CARRIER_CONFIG_CHANGED} broadcast for this subscription.
* @param capability The capability that is being queried for support on the carrier network.
* @param transportType The transport type of the capability to check support for.
+ * @param executor The executor that the callback will be called with.
* @param callback A consumer containing a Boolean result specifying whether or not the
* capability is supported on this carrier network for the transport specified.
- * @param executor The executor that the callback will be called with.
* @throws ImsException if the subscription is no longer valid or the IMS service is not
* available.
*/
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public void isSupported(@MmTelFeature.MmTelCapabilities.MmTelCapability int capability,
@AccessNetworkConstants.TransportType int transportType,
- @NonNull Consumer<Boolean> callback,
- @NonNull @CallbackExecutor Executor executor) throws ImsException {
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull Consumer<Boolean> callback) throws ImsException {
if (callback == null) {
throw new IllegalArgumentException("Must include a non-null Consumer.");
}
diff --git a/telephony/java/android/telephony/ims/ImsRcsManager.java b/telephony/java/android/telephony/ims/ImsRcsManager.java
index 25bd1caea431..6432016ac2c3 100644
--- a/telephony/java/android/telephony/ims/ImsRcsManager.java
+++ b/telephony/java/android/telephony/ims/ImsRcsManager.java
@@ -141,8 +141,8 @@ public class ImsRcsManager implements RegistrationManager {
/**{@inheritDoc}*/
@Override
public void registerImsRegistrationCallback(
- @NonNull RegistrationManager.RegistrationCallback c,
- @NonNull @CallbackExecutor Executor executor)
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull RegistrationCallback c)
throws ImsException {
if (c == null) {
throw new IllegalArgumentException("Must include a non-null RegistrationCallback.");
@@ -168,8 +168,8 @@ public class ImsRcsManager implements RegistrationManager {
/**{@inheritDoc}*/
@Override
- public void getRegistrationState(@NonNull @ImsRegistrationState Consumer<Integer> stateCallback,
- @NonNull @CallbackExecutor Executor executor) {
+ public void getRegistrationState(@NonNull @CallbackExecutor Executor executor,
+ @NonNull @ImsRegistrationState Consumer<Integer> stateCallback) {
if (stateCallback == null) {
throw new IllegalArgumentException("Must include a non-null stateCallback.");
}
@@ -182,9 +182,9 @@ public class ImsRcsManager implements RegistrationManager {
/**{@inheritDoc}*/
@Override
- public void getRegistrationTransportType(
- @NonNull @AccessNetworkConstants.TransportType Consumer<Integer> transportTypeCallback,
- @NonNull @CallbackExecutor Executor executor) {
+ public void getRegistrationTransportType(@NonNull @CallbackExecutor Executor executor,
+ @NonNull @AccessNetworkConstants.TransportType
+ Consumer<Integer> transportTypeCallback) {
if (transportTypeCallback == null) {
throw new IllegalArgumentException("Must include a non-null transportTypeCallback.");
}
diff --git a/telephony/java/android/telephony/ims/RegistrationManager.java b/telephony/java/android/telephony/ims/RegistrationManager.java
index b4c11e3c32a1..23402b88f3b1 100644
--- a/telephony/java/android/telephony/ims/RegistrationManager.java
+++ b/telephony/java/android/telephony/ims/RegistrationManager.java
@@ -90,7 +90,7 @@ public interface RegistrationManager {
/**
* Callback class for receiving IMS network Registration callback events.
- * @see #registerImsRegistrationCallback(RegistrationCallback, Executor)
+ * @see #registerImsRegistrationCallback(Executor, RegistrationCallback)
* @see #unregisterImsRegistrationCallback(RegistrationCallback)
*/
class RegistrationCallback {
@@ -229,8 +229,8 @@ public interface RegistrationManager {
* When the callback is registered, it will initiate the callback c to be called with the
* current registration state.
*
- * @param c The {@link RegistrationCallback} to be added.
* @param executor The executor the callback events should be run on.
+ * @param c The {@link RegistrationCallback} to be added.
* @see #unregisterImsRegistrationCallback(RegistrationCallback)
* @throws ImsException if the subscription associated with this callback is valid, but
* the {@link ImsService} associated with the subscription is not available. This can happen if
@@ -238,8 +238,8 @@ public interface RegistrationManager {
* reason.
*/
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
- void registerImsRegistrationCallback(@NonNull RegistrationCallback c,
- @NonNull @CallbackExecutor Executor executor) throws ImsException;
+ void registerImsRegistrationCallback(@NonNull @CallbackExecutor Executor executor,
+ @NonNull RegistrationCallback c) throws ImsException;
/**
* Removes an existing {@link RegistrationCallback}.
@@ -250,36 +250,36 @@ public interface RegistrationManager {
*
* @param c The {@link RegistrationCallback} to be removed.
* @see SubscriptionManager.OnSubscriptionsChangedListener
- * @see #registerImsRegistrationCallback(RegistrationCallback, Executor)
+ * @see #registerImsRegistrationCallback(Executor, RegistrationCallback)
*/
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
void unregisterImsRegistrationCallback(@NonNull RegistrationCallback c);
/**
* Gets the registration state of the IMS service.
- * @param stateCallback A callback called on the supplied {@link Executor} that will contain the
- * registration state of the IMS service, which will be one of the
- * following: {@link #REGISTRATION_STATE_NOT_REGISTERED},
- * {@link #REGISTRATION_STATE_REGISTERING}, or
- * {@link #REGISTRATION_STATE_REGISTERED}.
* @param executor The {@link Executor} that will be used to call the IMS registration state
* callback.
+ * @param stateCallback A callback called on the supplied {@link Executor} that will contain the
+ * registration state of the IMS service, which will be one of the
+ * following: {@link #REGISTRATION_STATE_NOT_REGISTERED},
+ * {@link #REGISTRATION_STATE_REGISTERING}, or
+ * {@link #REGISTRATION_STATE_REGISTERED}.
*/
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
- void getRegistrationState(@NonNull @ImsRegistrationState Consumer<Integer> stateCallback,
- @NonNull @CallbackExecutor Executor executor);
+ void getRegistrationState(@NonNull @CallbackExecutor Executor executor,
+ @NonNull @ImsRegistrationState Consumer<Integer> stateCallback);
/**
* Gets the Transport Type associated with the current IMS registration.
- * @param transportTypeCallback The transport type associated with the current IMS registration,
- * which will be one of following:
- * {@link AccessNetworkConstants#TRANSPORT_TYPE_WWAN},
- * {@link AccessNetworkConstants#TRANSPORT_TYPE_WLAN}, or
- * {@link AccessNetworkConstants#TRANSPORT_TYPE_INVALID}.
* @param executor The {@link Executor} that will be used to call the transportTypeCallback.
+ * @param transportTypeCallback The transport type associated with the current IMS registration,
+ * which will be one of following:
+ * {@link AccessNetworkConstants#TRANSPORT_TYPE_WWAN},
+ * {@link AccessNetworkConstants#TRANSPORT_TYPE_WLAN}, or
+ * {@link AccessNetworkConstants#TRANSPORT_TYPE_INVALID}.
*/
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
void getRegistrationTransportType(
- @NonNull @AccessNetworkConstants.TransportType Consumer<Integer> transportTypeCallback,
- @NonNull @CallbackExecutor Executor executor);
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull @AccessNetworkConstants.TransportType Consumer<Integer> transportTypeCallback);
}
diff --git a/tests/BootImageProfileTest/src/com/android/bootimageprofile/BootImageProfileTest.java b/tests/BootImageProfileTest/src/com/android/bootimageprofile/BootImageProfileTest.java
index ead4a28beff4..74aaec1eee34 100644
--- a/tests/BootImageProfileTest/src/com/android/bootimageprofile/BootImageProfileTest.java
+++ b/tests/BootImageProfileTest/src/com/android/bootimageprofile/BootImageProfileTest.java
@@ -108,13 +108,18 @@ public class BootImageProfileTest implements IDeviceTest {
// Test the profile contents contain common methods for core-oj that would normally be AOT
// compiled.
res = mTestDevice.executeShellCommand("profman --dump-classes-and-methods --profile-file="
- + SYSTEM_SERVER_PROFILE + " --apk=/apex/com.android.art/javalib/core-oj.jar");
+ + SYSTEM_SERVER_PROFILE + " --apk=/apex/com.android.art/javalib/core-oj.jar"
+ + " --apk=/system/framework/services.jar");
boolean sawObjectInit = false;
+ boolean sawPmInit = false;
for (String line : res.split("\n")) {
if (line.contains("Ljava/lang/Object;-><init>()V")) {
sawObjectInit = true;
+ } else if (line.contains("Lcom/android/server/pm/PackageManagerService;-><init>")) {
+ sawPmInit = true;
}
}
assertTrue("Did not see Object.<init> in " + res, sawObjectInit);
+ assertTrue("Did not see PackageManagerService.<init> in " + res, sawPmInit);
}
}
diff --git a/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassBase.java b/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassBase.java
index 7d88161a2805..176c7a0ada7b 100644
--- a/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassBase.java
+++ b/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassBase.java
@@ -32,7 +32,7 @@ public class HierrarchicalDataClassBase implements Parcelable {
- // Code below generated by codegen v1.0.12.
+ // Code below generated by codegen v1.0.13.
//
// DO NOT MODIFY!
// CHECKSTYLE:OFF Generated code
@@ -98,8 +98,8 @@ public class HierrarchicalDataClassBase implements Parcelable {
};
@DataClass.Generated(
- time = 1572655992854L,
- codegenVersion = "1.0.12",
+ time = 1573006405823L,
+ codegenVersion = "1.0.13",
sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassBase.java",
inputSignatures = "private int mBaseData\nclass HierrarchicalDataClassBase extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genConstructor=false, genSetters=true)")
@Deprecated
diff --git a/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassChild.java b/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassChild.java
index c930ce535ab6..e348c77c0ac6 100644
--- a/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassChild.java
+++ b/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassChild.java
@@ -46,7 +46,7 @@ public class HierrarchicalDataClassChild extends HierrarchicalDataClassBase {
- // Code below generated by codegen v1.0.12.
+ // Code below generated by codegen v1.0.13.
//
// DO NOT MODIFY!
// CHECKSTYLE:OFF Generated code
@@ -120,8 +120,8 @@ public class HierrarchicalDataClassChild extends HierrarchicalDataClassBase {
};
@DataClass.Generated(
- time = 1572655993858L,
- codegenVersion = "1.0.12",
+ time = 1573006406833L,
+ codegenVersion = "1.0.13",
sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassChild.java",
inputSignatures = "private @android.annotation.NonNull java.lang.String mChildData\nclass HierrarchicalDataClassChild extends com.android.codegentest.HierrarchicalDataClassBase implements []\n@com.android.internal.util.DataClass(genParcelable=true, genConstructor=false, genSetters=true)")
@Deprecated
diff --git a/tests/Codegen/src/com/android/codegentest/ParcelAllTheThingsDataClass.java b/tests/Codegen/src/com/android/codegentest/ParcelAllTheThingsDataClass.java
index 368a5c3a81e8..112d3df02280 100644
--- a/tests/Codegen/src/com/android/codegentest/ParcelAllTheThingsDataClass.java
+++ b/tests/Codegen/src/com/android/codegentest/ParcelAllTheThingsDataClass.java
@@ -19,6 +19,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Parcel;
import android.os.Parcelable;
+import android.util.ArrayMap;
import android.util.SparseArray;
import android.util.SparseIntArray;
@@ -52,7 +53,8 @@ public class ParcelAllTheThingsDataClass implements Parcelable {
- // Code below generated by codegen v1.0.12.
+
+ // Code below generated by codegen v1.0.13.
//
// DO NOT MODIFY!
// CHECKSTYLE:OFF Generated code
@@ -410,8 +412,8 @@ public class ParcelAllTheThingsDataClass implements Parcelable {
}
@DataClass.Generated(
- time = 1572655991821L,
- codegenVersion = "1.0.12",
+ time = 1573006404728L,
+ codegenVersion = "1.0.13",
sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/ParcelAllTheThingsDataClass.java",
inputSignatures = " @android.annotation.NonNull java.lang.String[] mStringArray\n @android.annotation.NonNull int[] mIntArray\n @android.annotation.NonNull java.util.List<java.lang.String> mStringList\n @android.annotation.NonNull java.util.Map<java.lang.String,com.android.codegentest.SampleWithCustomBuilder> mMap\n @android.annotation.NonNull java.util.Map<java.lang.String,java.lang.String> mStringMap\n @android.annotation.NonNull android.util.SparseArray<com.android.codegentest.SampleWithCustomBuilder> mSparseArray\n @android.annotation.NonNull android.util.SparseIntArray mSparseIntArray\n @java.lang.SuppressWarnings({\"WeakerAccess\"}) @android.annotation.Nullable java.lang.Boolean mNullableBoolean\nclass ParcelAllTheThingsDataClass extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genBuilder=true, genAidl=false, genToString=true)")
@Deprecated
diff --git a/tests/Codegen/src/com/android/codegentest/SampleDataClass.java b/tests/Codegen/src/com/android/codegentest/SampleDataClass.java
index 9d52287d631e..0fdcf5918c81 100644
--- a/tests/Codegen/src/com/android/codegentest/SampleDataClass.java
+++ b/tests/Codegen/src/com/android/codegentest/SampleDataClass.java
@@ -342,7 +342,7 @@ public final class SampleDataClass implements Parcelable {
- // Code below generated by codegen v1.0.12.
+ // Code below generated by codegen v1.0.13.
//
// DO NOT MODIFY!
// CHECKSTYLE:OFF Generated code
@@ -1872,8 +1872,8 @@ public final class SampleDataClass implements Parcelable {
}
@DataClass.Generated(
- time = 1572655989589L,
- codegenVersion = "1.0.12",
+ time = 1573006402566L,
+ codegenVersion = "1.0.13",
sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/SampleDataClass.java",
inputSignatures = "public static final java.lang.String STATE_NAME_UNDEFINED\npublic static final java.lang.String STATE_NAME_ON\npublic static final java.lang.String STATE_NAME_OFF\npublic static final int STATE_UNDEFINED\npublic static final int STATE_ON\npublic static final int STATE_OFF\npublic static final @com.android.codegentest.SampleDataClass.RequestFlags int FLAG_MANUAL_REQUEST\npublic static final @com.android.codegentest.SampleDataClass.RequestFlags int FLAG_COMPATIBILITY_MODE_REQUEST\npublic static final @com.android.codegentest.SampleDataClass.RequestFlags int FLAG_AUGMENTED_REQUEST\nprivate int mNum\nprivate int mNum2\nprivate int mNum4\nprivate @android.annotation.Nullable java.lang.String mName\nprivate @android.annotation.NonNull java.lang.String mName2\nprivate @android.annotation.NonNull java.lang.String mName4\nprivate @android.annotation.Nullable android.view.accessibility.AccessibilityNodeInfo mOtherParcelable\nprivate @com.android.internal.util.DataClass.ParcelWith(com.android.codegentest.MyDateParcelling.class) @android.annotation.NonNull java.util.Date mDate\nprivate @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForPattern.class) @android.annotation.NonNull java.util.regex.Pattern mPattern\nprivate @android.annotation.NonNull java.util.List<android.net.LinkAddress> mLinkAddresses2\nprivate @com.android.internal.util.DataClass.PluralOf(\"linkAddress\") @android.annotation.NonNull java.util.ArrayList<android.net.LinkAddress> mLinkAddresses\nprivate @android.annotation.Nullable android.net.LinkAddress[] mLinkAddresses4\nprivate @com.android.codegentest.SampleDataClass.StateName @android.annotation.NonNull java.lang.String mStateName\nprivate @com.android.codegentest.SampleDataClass.RequestFlags int mFlags\nprivate @com.android.codegentest.SampleDataClass.State int mState\npublic @android.annotation.NonNull java.lang.CharSequence charSeq\nprivate final @android.annotation.Nullable android.net.LinkAddress[] mLinkAddresses5\nprivate transient android.net.LinkAddress[] mLinkAddresses6\ntransient int[] mTmpStorage\nprivate @android.annotation.StringRes int mStringRes\nprivate @android.annotation.IntRange(from=0L, to=6L) int mDayOfWeek\nprivate @android.annotation.Size(2L) @android.annotation.NonNull @com.android.internal.util.DataClass.Each @android.annotation.FloatRange(from=0.0) float[] mCoords\nprivate static java.lang.String defaultName4()\nprivate int[] lazyInitTmpStorage()\npublic android.net.LinkAddress[] getLinkAddresses4()\nprivate boolean patternEquals(java.util.regex.Pattern)\nprivate int patternHashCode()\nprivate void onConstructed()\npublic void dump(java.io.PrintWriter)\nclass SampleDataClass extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genBuilder=true, genConstructor=true, genEqualsHashCode=true, genToString=true, genForEachField=true, genSetters=true)")
@Deprecated
diff --git a/tests/Codegen/src/com/android/codegentest/SampleWithCustomBuilder.java b/tests/Codegen/src/com/android/codegentest/SampleWithCustomBuilder.java
index cef32d1051df..cab477dafae9 100644
--- a/tests/Codegen/src/com/android/codegentest/SampleWithCustomBuilder.java
+++ b/tests/Codegen/src/com/android/codegentest/SampleWithCustomBuilder.java
@@ -85,7 +85,7 @@ public class SampleWithCustomBuilder implements Parcelable {
- // Code below generated by codegen v1.0.12.
+ // Code below generated by codegen v1.0.13.
//
// DO NOT MODIFY!
// CHECKSTYLE:OFF Generated code
@@ -253,8 +253,8 @@ public class SampleWithCustomBuilder implements Parcelable {
}
@DataClass.Generated(
- time = 1572655990725L,
- codegenVersion = "1.0.12",
+ time = 1573006403628L,
+ codegenVersion = "1.0.13",
sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/SampleWithCustomBuilder.java",
inputSignatures = " long delayAmount\n @android.annotation.NonNull java.util.concurrent.TimeUnit delayUnit\n long creationTimestamp\nprivate static java.util.concurrent.TimeUnit unparcelDelayUnit(android.os.Parcel)\nprivate void parcelDelayUnit(android.os.Parcel,int)\nclass SampleWithCustomBuilder extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genBuilder=true, genAidl=false, genToString=true)\nabstract com.android.codegentest.SampleWithCustomBuilder.Builder setDelayAmount(long)\npublic abstract com.android.codegentest.SampleWithCustomBuilder.Builder setDelayUnit(java.util.concurrent.TimeUnit)\npublic com.android.codegentest.SampleWithCustomBuilder.Builder setDelay(long,java.util.concurrent.TimeUnit)\nclass BaseBuilder extends java.lang.Object implements []")
@Deprecated
diff --git a/tests/Codegen/src/com/android/codegentest/SampleWithNestedDataClasses.java b/tests/Codegen/src/com/android/codegentest/SampleWithNestedDataClasses.java
index 27055f6a4df8..6190085a4d82 100644
--- a/tests/Codegen/src/com/android/codegentest/SampleWithNestedDataClasses.java
+++ b/tests/Codegen/src/com/android/codegentest/SampleWithNestedDataClasses.java
@@ -36,7 +36,7 @@ public class SampleWithNestedDataClasses {
- // Code below generated by codegen v1.0.12.
+ // Code below generated by codegen v1.0.13.
//
// DO NOT MODIFY!
// CHECKSTYLE:OFF Generated code
@@ -135,8 +135,8 @@ public class SampleWithNestedDataClasses {
};
@DataClass.Generated(
- time = 1572655995915L,
- codegenVersion = "1.0.12",
+ time = 1573006408903L,
+ codegenVersion = "1.0.13",
sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/SampleWithNestedDataClasses.java",
inputSignatures = " @android.annotation.NonNull java.lang.String mBar\nclass NestedDataClass extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true)")
@Deprecated
@@ -160,7 +160,7 @@ public class SampleWithNestedDataClasses {
- // Code below generated by codegen v1.0.12.
+ // Code below generated by codegen v1.0.13.
//
// DO NOT MODIFY!
// CHECKSTYLE:OFF Generated code
@@ -259,8 +259,8 @@ public class SampleWithNestedDataClasses {
};
@DataClass.Generated(
- time = 1572655995924L,
- codegenVersion = "1.0.12",
+ time = 1573006408912L,
+ codegenVersion = "1.0.13",
sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/SampleWithNestedDataClasses.java",
inputSignatures = " @android.annotation.NonNull long mBaz2\nclass NestedDataClass3 extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true)")
@Deprecated
@@ -274,7 +274,7 @@ public class SampleWithNestedDataClasses {
- // Code below generated by codegen v1.0.12.
+ // Code below generated by codegen v1.0.13.
//
// DO NOT MODIFY!
// CHECKSTYLE:OFF Generated code
@@ -373,8 +373,8 @@ public class SampleWithNestedDataClasses {
};
@DataClass.Generated(
- time = 1572655995930L,
- codegenVersion = "1.0.12",
+ time = 1573006408917L,
+ codegenVersion = "1.0.13",
sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/SampleWithNestedDataClasses.java",
inputSignatures = " @android.annotation.NonNull java.lang.String mBaz\nclass NestedDataClass2 extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true)")
@Deprecated
diff --git a/tests/Codegen/src/com/android/codegentest/StaleDataclassDetectorFalsePositivesTest.java b/tests/Codegen/src/com/android/codegentest/StaleDataclassDetectorFalsePositivesTest.java
index 4bfec895fdcb..5a960d7dd002 100644
--- a/tests/Codegen/src/com/android/codegentest/StaleDataclassDetectorFalsePositivesTest.java
+++ b/tests/Codegen/src/com/android/codegentest/StaleDataclassDetectorFalsePositivesTest.java
@@ -51,7 +51,7 @@ public class StaleDataclassDetectorFalsePositivesTest {
- // Code below generated by codegen v1.0.12.
+ // Code below generated by codegen v1.0.13.
//
// DO NOT MODIFY!
// CHECKSTYLE:OFF Generated code
@@ -65,8 +65,8 @@ public class StaleDataclassDetectorFalsePositivesTest {
@DataClass.Generated(
- time = 1572655994865L,
- codegenVersion = "1.0.12",
+ time = 1573006407900L,
+ codegenVersion = "1.0.13",
sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/StaleDataclassDetectorFalsePositivesTest.java",
inputSignatures = "public @android.annotation.NonNull java.lang.String someMethod(int)\nclass StaleDataclassDetectorFalsePositivesTest extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genConstructor=false, genBuilder=false)")
@Deprecated
diff --git a/tools/codegen/src/com/android/codegen/FieldInfo.kt b/tools/codegen/src/com/android/codegen/FieldInfo.kt
index ed35a1dfc599..ebfbbd8163b5 100644
--- a/tools/codegen/src/com/android/codegen/FieldInfo.kt
+++ b/tools/codegen/src/com/android/codegen/FieldInfo.kt
@@ -93,6 +93,8 @@ data class FieldInfo(
// Generic args
val isArray = Type.endsWith("[]")
val isList = FieldClass == "List" || FieldClass == "ArrayList"
+ val isMap = FieldClass == "Map" || FieldClass == "ArrayMap"
+ || FieldClass == "HashMap" || FieldClass == "LinkedHashMap"
val fieldBit = bitAtExpr(index)
var isLast = false
val isFinal = fieldAst.isFinal
@@ -197,7 +199,7 @@ data class FieldInfo(
listOf("String", "CharSequence", "Exception", "Size", "SizeF", "Bundle",
"FileDescriptor", "SparseBooleanArray", "SparseIntArray", "SparseArray") ->
FieldClass
- FieldClass == "Map" && fieldTypeGenegicArgs[0] == "String" -> "Map"
+ isMap && fieldTypeGenegicArgs[0] == "String" -> "Map"
isArray -> when {
FieldInnerType!! in (PRIMITIVE_TYPES + "String") -> FieldInnerType + "Array"
isBinder(FieldInnerType) -> "BinderArray"
diff --git a/tools/codegen/src/com/android/codegen/Generators.kt b/tools/codegen/src/com/android/codegen/Generators.kt
index c25d0c74f251..dc1f4c50abc4 100644
--- a/tools/codegen/src/com/android/codegen/Generators.kt
+++ b/tools/codegen/src/com/android/codegen/Generators.kt
@@ -343,7 +343,7 @@ private fun ClassPrinter.generateBuilderSetters(visibility: String) {
}
}
- if (FieldClass.endsWith("Map") && FieldInnerType != null) {
+ if (isMap && FieldInnerType != null) {
generateBuilderMethod(
name = adderName,
defVisibility = visibility,
@@ -351,7 +351,7 @@ private fun ClassPrinter.generateBuilderSetters(visibility: String) {
paramNames = listOf("key", "value"),
genJavadoc = { +javadocSeeSetter }) {
!singularNameCustomizationHint
- +"if ($name == null) $setterName(new $LinkedHashMap());"
+ +"if ($name == null) $setterName(new ${if (FieldClass == "Map") LinkedHashMap else FieldClass}());"
+"$name.put(key, value);"
+"return$maybeCast this;"
}
@@ -507,7 +507,8 @@ fun ClassPrinter.generateParcelable() {
// Create container if any
val containerInitExpr = when {
- FieldClass.endsWith("Map") -> "new $LinkedHashMap<>()"
+ FieldClass == "Map" -> "new $LinkedHashMap<>()"
+ isMap -> "new $FieldClass()"
FieldClass == "List" || FieldClass == "ArrayList" ->
"new ${classRef("java.util.ArrayList")}<>()"
else -> ""
diff --git a/tools/codegen/src/com/android/codegen/SharedConstants.kt b/tools/codegen/src/com/android/codegen/SharedConstants.kt
index 339057f24833..85c832fcf34f 100644
--- a/tools/codegen/src/com/android/codegen/SharedConstants.kt
+++ b/tools/codegen/src/com/android/codegen/SharedConstants.kt
@@ -1,7 +1,7 @@
package com.android.codegen
const val CODEGEN_NAME = "codegen"
-const val CODEGEN_VERSION = "1.0.12"
+const val CODEGEN_VERSION = "1.0.13"
const val CANONICAL_BUILDER_CLASS = "Builder"
const val BASE_BUILDER_CLASS = "BaseBuilder"
diff --git a/wifi/java/android/net/wifi/ISoftApCallback.aidl b/wifi/java/android/net/wifi/ISoftApCallback.aidl
index 8a252dd1e447..452a655edc7b 100644
--- a/wifi/java/android/net/wifi/ISoftApCallback.aidl
+++ b/wifi/java/android/net/wifi/ISoftApCallback.aidl
@@ -15,6 +15,7 @@
*/
package android.net.wifi;
+import android.net.wifi.SoftApInfo;
import android.net.wifi.WifiClient;
@@ -43,4 +44,11 @@ oneway interface ISoftApCallback
* @param clients the currently connected clients
*/
void onConnectedClientsChanged(in List<WifiClient> clients);
+
+ /**
+ * Service to manager callback providing information of softap.
+ *
+ * @param softApInfo is the softap information. {@link SoftApInfo}
+ */
+ void onInfoChanged(in SoftApInfo softApInfo);
}
diff --git a/wifi/java/android/net/wifi/SoftApInfo.aidl b/wifi/java/android/net/wifi/SoftApInfo.aidl
new file mode 100644
index 000000000000..d4551cfac044
--- /dev/null
+++ b/wifi/java/android/net/wifi/SoftApInfo.aidl
@@ -0,0 +1,20 @@
+/**
+ * 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.
+ */
+
+package android.net.wifi;
+
+parcelable SoftApInfo;
+
diff --git a/wifi/java/android/net/wifi/SoftApInfo.java b/wifi/java/android/net/wifi/SoftApInfo.java
new file mode 100644
index 000000000000..375a9774f570
--- /dev/null
+++ b/wifi/java/android/net/wifi/SoftApInfo.java
@@ -0,0 +1,211 @@
+/*
+ * 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.
+ */
+
+package android.net.wifi;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Objects;
+
+/**
+ * A class representing information about SoftAp.
+ * {@see WifiManager}
+ *
+ * @hide
+ */
+@SystemApi
+public final class SoftApInfo implements Parcelable {
+
+ /**
+ * AP Channel bandwidth is invalid.
+ *
+ * @see #getBandwidth()
+ */
+ public static final int CHANNEL_WIDTH_INVALID = 0;
+
+ /**
+ * AP Channel bandwidth is 20 MHZ but no HT.
+ *
+ * @see #getBandwidth()
+ */
+ public static final int CHANNEL_WIDTH_20MHZ_NOHT = 1;
+
+ /**
+ * AP Channel bandwidth is 20 MHZ.
+ *
+ * @see #getBandwidth()
+ */
+ public static final int CHANNEL_WIDTH_20MHZ = 2;
+
+ /**
+ * AP Channel bandwidth is 40 MHZ.
+ *
+ * @see #getBandwidth()
+ */
+ public static final int CHANNEL_WIDTH_40MHZ = 3;
+
+ /**
+ * AP Channel bandwidth is 80 MHZ.
+ *
+ * @see #getBandwidth()
+ */
+ public static final int CHANNEL_WIDTH_80MHZ = 4;
+
+ /**
+ * AP Channel bandwidth is 160 MHZ, but 80MHZ + 80MHZ.
+ *
+ * @see #getBandwidth()
+ */
+ public static final int CHANNEL_WIDTH_80MHZ_PLUS_MHZ = 5;
+
+ /**
+ * AP Channel bandwidth is 160 MHZ.
+ *
+ * @see #getBandwidth()
+ */
+ public static final int CHANNEL_WIDTH_160MHZ = 6;
+
+ /**
+ * @hide
+ */
+ @IntDef(prefix = { "CHANNEL_WIDTH_" }, value = {
+ CHANNEL_WIDTH_INVALID,
+ CHANNEL_WIDTH_20MHZ_NOHT,
+ CHANNEL_WIDTH_20MHZ,
+ CHANNEL_WIDTH_40MHZ,
+ CHANNEL_WIDTH_80MHZ,
+ CHANNEL_WIDTH_80MHZ_PLUS_MHZ,
+ CHANNEL_WIDTH_160MHZ,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Bandwidth {}
+
+
+ /** The frequency which AP resides on. */
+ private int mFrequency = 0;
+
+ @Bandwidth
+ private int mBandwidth = CHANNEL_WIDTH_INVALID;
+
+ /**
+ * Get the frequency which AP resides on.
+ */
+ public int getFrequency() {
+ return mFrequency;
+ }
+
+ /**
+ * Set the frequency which AP resides on.
+ * @hide
+ */
+ public void setFrequency(int freq) {
+ mFrequency = freq;
+ }
+
+ /**
+ * Get AP Channel bandwidth.
+ *
+ * @return One of {@link #CHANNEL_WIDTH_20MHZ}, {@link #CHANNEL_WIDTH_40MHZ},
+ * {@link #CHANNEL_WIDTH_80MHZ}, {@link #CHANNEL_WIDTH_160MHZ},
+ * {@link #CHANNEL_WIDTH_80MHZ_PLUS_MHZ} or {@link #CHANNEL_WIDTH_UNKNOWN}.
+ */
+ @Bandwidth
+ public int getBandwidth() {
+ return mBandwidth;
+ }
+
+ /**
+ * Set AP Channel bandwidth.
+ * @hide
+ */
+ public void setBandwidth(@Bandwidth int bandwidth) {
+ mBandwidth = bandwidth;
+ }
+
+ /**
+ * @hide
+ */
+ public SoftApInfo(@Nullable SoftApInfo source) {
+ if (source != null) {
+ mFrequency = source.mFrequency;
+ mBandwidth = source.mBandwidth;
+ }
+ }
+
+ /**
+ * @hide
+ */
+ public SoftApInfo() {
+ }
+
+ @Override
+ /** Implement the Parcelable interface. */
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ /** Implement the Parcelable interface */
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeInt(mFrequency);
+ dest.writeInt(mBandwidth);
+ }
+
+ @NonNull
+ /** Implement the Parcelable interface */
+ public static final Creator<SoftApInfo> CREATOR = new Creator<SoftApInfo>() {
+ public SoftApInfo createFromParcel(Parcel in) {
+ SoftApInfo info = new SoftApInfo();
+ info.mFrequency = in.readInt();
+ info.mBandwidth = in.readInt();
+ return info;
+ }
+
+ public SoftApInfo[] newArray(int size) {
+ return new SoftApInfo[size];
+ }
+ };
+
+ @NonNull
+ @Override
+ public String toString() {
+ return "SoftApInfo{"
+ + "bandwidth= " + mBandwidth
+ + ",frequency= " + mFrequency
+ + '}';
+ }
+
+ @Override
+ public boolean equals(@NonNull Object o) {
+ if (this == o) return true;
+ if (!(o instanceof SoftApInfo)) return false;
+ SoftApInfo softApInfo = (SoftApInfo) o;
+ return mFrequency == softApInfo.mFrequency
+ && mBandwidth == softApInfo.mBandwidth;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mFrequency, mBandwidth);
+ }
+}
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 07831c71b0d3..8108fef5d3ee 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -3315,6 +3315,15 @@ public class WifiManager {
* @param clients the currently connected clients
*/
void onConnectedClientsChanged(@NonNull List<WifiClient> clients);
+
+ /**
+ * Called when information of softap changes.
+ *
+ * @param softApInfo is the softap information. {@link SoftApInfo}
+ */
+ default void onInfoChanged(@NonNull SoftApInfo softApInfo) {
+ // Do nothing: can be updated to add SoftApInfo details (e.g. channel) to the UI.
+ }
}
/**
@@ -3354,6 +3363,16 @@ public class WifiManager {
mCallback.onConnectedClientsChanged(clients);
});
}
+
+ @Override
+ public void onInfoChanged(SoftApInfo softApInfo) {
+ if (mVerboseLoggingEnabled) {
+ Log.v(TAG, "SoftApCallbackProxy: onInfoChange: softApInfo=" + softApInfo);
+ }
+ mHandler.post(() -> {
+ mCallback.onInfoChanged(softApInfo);
+ });
+ }
}
/**
diff --git a/wifi/tests/src/android/net/wifi/SoftApInfoTest.java b/wifi/tests/src/android/net/wifi/SoftApInfoTest.java
new file mode 100644
index 000000000000..929f3ab88fd8
--- /dev/null
+++ b/wifi/tests/src/android/net/wifi/SoftApInfoTest.java
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ */
+
+package android.net.wifi;
+
+import android.os.Parcel;
+
+import static org.junit.Assert.assertEquals;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+
+/**
+ * Unit tests for {@link android.net.wifi.SoftApInfo}.
+ */
+@SmallTest
+public class SoftApInfoTest {
+
+ /**
+ * Verifies copy constructor.
+ */
+ @Test
+ public void testCopyOperator() throws Exception {
+ SoftApInfo info = new SoftApInfo();
+ info.setFrequency(2412);
+ info.setBandwidth(SoftApInfo.CHANNEL_WIDTH_20MHZ);
+
+ SoftApInfo copiedInfo = new SoftApInfo(info);
+
+ assertEquals(info, copiedInfo);
+ assertEquals(info.hashCode(), copiedInfo.hashCode());
+ }
+
+ /**
+ * Verifies parcel serialization/deserialization.
+ */
+ @Test
+ public void testParcelOperation() throws Exception {
+ SoftApInfo info = new SoftApInfo();
+ info.setFrequency(2412);
+ info.setBandwidth(SoftApInfo.CHANNEL_WIDTH_20MHZ);
+
+ Parcel parcelW = Parcel.obtain();
+ info.writeToParcel(parcelW, 0);
+ byte[] bytes = parcelW.marshall();
+ parcelW.recycle();
+
+ Parcel parcelR = Parcel.obtain();
+ parcelR.unmarshall(bytes, 0, bytes.length);
+ parcelR.setDataPosition(0);
+ SoftApInfo fromParcel = SoftApInfo.CREATOR.createFromParcel(parcelR);
+
+ assertEquals(info, fromParcel);
+ assertEquals(info.hashCode(), fromParcel.hashCode());
+ }
+
+}
diff --git a/wifi/tests/src/android/net/wifi/WifiManagerTest.java b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
index d2516a33fead..14e994cf0f08 100644
--- a/wifi/tests/src/android/net/wifi/WifiManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
@@ -97,6 +97,8 @@ public class WifiManagerTest {
private static final String TEST_PACKAGE_NAME = "TestPackage";
private static final String TEST_COUNTRY_CODE = "US";
private static final String[] TEST_MAC_ADDRESSES = {"da:a1:19:0:0:0"};
+ private static final int TEST_AP_FREQUENCY = 2412;
+ private static final int TEST_AP_BANDWIDTH = SoftApInfo.CHANNEL_WIDTH_20MHZ;
@Mock Context mContext;
@Mock android.net.wifi.IWifiManager mWifiService;
@@ -122,7 +124,6 @@ public class WifiManagerTest {
mApplicationInfo.targetSdkVersion = Build.VERSION_CODES.Q;
when(mContext.getApplicationInfo()).thenReturn(mApplicationInfo);
when(mContext.getOpPackageName()).thenReturn(TEST_PACKAGE_NAME);
-
mWifiManager = new WifiManager(mContext, mWifiService, mLooper.getLooper());
verify(mWifiService).getVerboseLoggingLevel();
}
@@ -776,11 +777,34 @@ public class WifiManagerTest {
verify(mSoftApCallback).onConnectedClientsChanged(testClients);
}
+
+ /*
+ * Verify client-provided callback is being called through callback proxy
+ */
+ @Test
+ public void softApCallbackProxyCallsOnSoftApInfoChanged() throws Exception {
+ SoftApInfo testSoftApInfo = new SoftApInfo();
+ testSoftApInfo.setFrequency(TEST_AP_FREQUENCY);
+ testSoftApInfo.setBandwidth(TEST_AP_BANDWIDTH);
+ ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor =
+ ArgumentCaptor.forClass(ISoftApCallback.Stub.class);
+ mWifiManager.registerSoftApCallback(mSoftApCallback, mHandler);
+ verify(mWifiService).registerSoftApCallback(any(IBinder.class), callbackCaptor.capture(),
+ anyInt());
+
+ callbackCaptor.getValue().onInfoChanged(testSoftApInfo);
+ mLooper.dispatchAll();
+ verify(mSoftApCallback).onInfoChanged(testSoftApInfo);
+ }
+
/*
* Verify client-provided callback is being called through callback proxy on multiple events
*/
@Test
public void softApCallbackProxyCallsOnMultipleUpdates() throws Exception {
+ SoftApInfo testSoftApInfo = new SoftApInfo();
+ testSoftApInfo.setFrequency(TEST_AP_FREQUENCY);
+ testSoftApInfo.setBandwidth(TEST_AP_BANDWIDTH);
ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor =
ArgumentCaptor.forClass(ISoftApCallback.Stub.class);
mWifiManager.registerSoftApCallback(mSoftApCallback, mHandler);
@@ -790,11 +814,13 @@ public class WifiManagerTest {
final List<WifiClient> testClients = new ArrayList();
callbackCaptor.getValue().onStateChanged(WIFI_AP_STATE_ENABLING, 0);
callbackCaptor.getValue().onConnectedClientsChanged(testClients);
+ callbackCaptor.getValue().onInfoChanged(testSoftApInfo);
callbackCaptor.getValue().onStateChanged(WIFI_AP_STATE_FAILED, SAP_START_FAILURE_GENERAL);
mLooper.dispatchAll();
verify(mSoftApCallback).onStateChanged(WIFI_AP_STATE_ENABLING, 0);
verify(mSoftApCallback).onConnectedClientsChanged(testClients);
+ verify(mSoftApCallback).onInfoChanged(testSoftApInfo);
verify(mSoftApCallback).onStateChanged(WIFI_AP_STATE_FAILED, SAP_START_FAILURE_GENERAL);
}