summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apct-tests/perftests/core/src/android/os/BinderCallsStatsPerfTest.java1
-rw-r--r--config/hiddenapi-light-greylist.txt51
-rw-r--r--core/java/android/app/ActivityManager.java24
-rw-r--r--core/java/android/app/Notification.java391
-rw-r--r--core/java/android/app/PendingIntent.java87
-rw-r--r--core/java/android/app/admin/SystemUpdatePolicy.java115
-rw-r--r--core/java/android/app/backup/BackupManager.java2
-rw-r--r--core/java/android/provider/Settings.java1
-rw-r--r--core/java/android/text/AndroidBidi.java8
-rw-r--r--core/java/android/text/BidiFormatter.java12
-rw-r--r--core/java/android/text/Emoji.java51
-rw-r--r--core/java/android/util/apk/ApkSigningBlockUtils.java19
-rw-r--r--core/java/android/view/IRecentsAnimationController.aidl5
-rw-r--r--core/java/android/view/IWindowManager.aidl5
-rw-r--r--core/java/android/view/ViewRootImpl.java3
-rw-r--r--core/java/android/widget/RemoteViews.java23
-rw-r--r--core/java/com/android/internal/os/BatteryStatsImpl.java25
-rw-r--r--core/java/com/android/internal/os/BinderCallsStats.java146
-rw-r--r--core/java/com/android/internal/widget/ILockSettings.aidl1
-rw-r--r--core/java/com/android/internal/widget/ImageFloatingTextView.java10
-rw-r--r--core/java/com/android/internal/widget/LockPatternUtils.java105
-rw-r--r--core/java/com/android/internal/widget/MessagingGroup.java58
-rw-r--r--core/java/com/android/internal/widget/MessagingLayout.java18
-rw-r--r--core/java/com/android/internal/widget/MessagingMessage.java3
-rw-r--r--core/jni/android_hardware_camera2_DngCreator.cpp4
-rw-r--r--core/res/res/drawable/ic_reply_notification.xml29
-rw-r--r--core/res/res/drawable/ic_reply_notification_large.xml29
-rw-r--r--core/res/res/drawable/notification_reply_background.xml24
-rw-r--r--core/res/res/layout/global_actions_item.xml1
-rw-r--r--core/res/res/layout/notification_material_action_tombstone.xml2
-rw-r--r--core/res/res/layout/notification_material_reply_text.xml28
-rw-r--r--core/res/res/layout/notification_template_material_messaging.xml4
-rw-r--r--core/res/res/layout/notification_template_messaging_group.xml15
-rw-r--r--core/res/res/layout/notification_template_right_icon.xml29
-rw-r--r--core/res/res/values/colors.xml1
-rw-r--r--core/res/res/values/dimens.xml23
-rw-r--r--core/res/res/values/ids.xml1
-rw-r--r--core/res/res/values/symbols.xml13
-rw-r--r--core/tests/BroadcastRadioTests/src/android/hardware/radio/tests/functional/RadioTunerTest.java1
-rw-r--r--core/tests/coretests/src/android/text/EmojiTest.java120
-rw-r--r--location/java/android/location/GnssMeasurementsEvent.java7
-rw-r--r--media/jni/android_media_MediaCodec.cpp5
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java8
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java5
-rw-r--r--packages/SystemUI/res/layout/global_actions_item.xml4
-rw-r--r--packages/SystemUI/res/layout/global_actions_wrapped.xml2
-rw-r--r--packages/SystemUI/res/layout/quick_qs_status_icons.xml13
-rw-r--r--packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml10
-rw-r--r--packages/SystemUI/res/layout/smart_reply_view.xml1
-rw-r--r--packages/SystemUI/res/layout/volume_dnd_icon.xml14
-rw-r--r--packages/SystemUI/res/values-h320dp/config.xml22
-rw-r--r--packages/SystemUI/res/values-h600dp/config.xml22
-rw-r--r--packages/SystemUI/res/values-sw410dp/config.xml3
-rw-r--r--packages/SystemUI/res/values-sw540dp/config.xml24
-rw-r--r--packages/SystemUI/res/values/config.xml1
-rw-r--r--packages/SystemUI/res/values/dimens.xml4
-rw-r--r--packages/SystemUI/res/values/strings.xml2
-rw-r--r--packages/SystemUI/res/values/styles.xml2
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java4
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java8
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java26
-rw-r--r--packages/SystemUI/src/com/android/systemui/Dependency.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/SystemUIFactory.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/AlwaysOnDisplayPolicy.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java17
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeService.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationEntryManager.java62
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java45
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java (renamed from packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyLogger.java)26
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java105
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java31
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java30
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java30
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationEntryManagerTest.java40
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java121
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java36
-rw-r--r--proto/src/metrics_constants.proto20
-rw-r--r--proto/src/task_snapshot.proto1
-rw-r--r--services/core/java/com/android/server/BinderCallsStatsService.java50
-rw-r--r--services/core/java/com/android/server/ConnectivityService.java33
-rw-r--r--services/core/java/com/android/server/DeviceIdleController.java25
-rw-r--r--services/core/java/com/android/server/LocationManagerService.java5
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java77
-rw-r--r--services/core/java/com/android/server/am/ActivityStack.java6
-rw-r--r--services/core/java/com/android/server/am/ActivityStackSupervisor.java45
-rw-r--r--services/core/java/com/android/server/am/ActivityStartController.java7
-rw-r--r--services/core/java/com/android/server/am/ActivityStarter.java40
-rw-r--r--services/core/java/com/android/server/am/AppErrors.java3
-rw-r--r--services/core/java/com/android/server/am/BatteryExternalStatsWorker.java17
-rw-r--r--services/core/java/com/android/server/am/BatteryStatsService.java13
-rw-r--r--services/core/java/com/android/server/am/DeprecatedTargetSdkVersionDialog.java7
-rw-r--r--services/core/java/com/android/server/am/LockTaskController.java5
-rw-r--r--services/core/java/com/android/server/am/RecentTasks.java2
-rw-r--r--services/core/java/com/android/server/am/TaskRecord.java15
-rw-r--r--services/core/java/com/android/server/location/GnssBatchingProvider.java145
-rw-r--r--services/core/java/com/android/server/location/GnssLocationProvider.java92
-rw-r--r--services/core/java/com/android/server/locksettings/LockSettingsService.java30
-rw-r--r--services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java6
-rw-r--r--services/core/java/com/android/server/notification/ManagedServices.java11
-rw-r--r--services/core/java/com/android/server/os/SchedulingPolicyService.java24
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java34
-rw-r--r--services/core/java/com/android/server/pm/ProtectedPackages.java7
-rw-r--r--services/core/java/com/android/server/power/Notifier.java7
-rw-r--r--services/core/java/com/android/server/wm/AppTransition.java40
-rw-r--r--services/core/java/com/android/server/wm/RecentsAnimationController.java16
-rw-r--r--services/core/java/com/android/server/wm/TaskSnapshotController.java7
-rw-r--r--services/core/java/com/android/server/wm/TaskSnapshotLoader.java2
-rw-r--r--services/core/java/com/android/server/wm/TaskSnapshotPersister.java4
-rw-r--r--services/core/java/com/android/server/wm/TaskStack.java5
-rw-r--r--services/core/java/com/android/server/wm/WindowContainer.java1
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java23
-rw-r--r--services/core/jni/com_android_server_location_GnssLocationProvider.cpp36
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java7
-rw-r--r--services/robotests/src/com/android/server/location/GnssBatchingProviderTest.java91
-rw-r--r--services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java49
-rw-r--r--services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java8
-rw-r--r--services/tests/servicestests/src/com/android/server/am/TaskRecordTests.java17
-rw-r--r--services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java27
-rw-r--r--services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java7
-rw-r--r--services/tests/servicestests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java4
-rw-r--r--services/tests/servicestests/src/com/android/server/wm/WindowContainerTests.java44
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java26
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java35
-rw-r--r--tests/net/java/com/android/server/ConnectivityServiceTest.java141
-rw-r--r--tools/aapt2/cmd/Link.cpp61
-rwxr-xr-xtools/fonts/fontchain_linter.py15
-rwxr-xr-xwifi/tests/runtests.sh3
140 files changed, 2735 insertions, 979 deletions
diff --git a/apct-tests/perftests/core/src/android/os/BinderCallsStatsPerfTest.java b/apct-tests/perftests/core/src/android/os/BinderCallsStatsPerfTest.java
index 28d40969aa21..ba072da8071e 100644
--- a/apct-tests/perftests/core/src/android/os/BinderCallsStatsPerfTest.java
+++ b/apct-tests/perftests/core/src/android/os/BinderCallsStatsPerfTest.java
@@ -69,7 +69,6 @@ public class BinderCallsStatsPerfTest {
final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
Binder b = new Binder();
mBinderCallsStats = new BinderCallsStats(false);
- assertNull(mBinderCallsStats.callStarted(b, 0));
while (state.keepRunning()) {
BinderCallsStats.CallSession s = mBinderCallsStats.callStarted(b, 0);
mBinderCallsStats.callEnded(s);
diff --git a/config/hiddenapi-light-greylist.txt b/config/hiddenapi-light-greylist.txt
index 2ba4bebd8df5..26334411d6ee 100644
--- a/config/hiddenapi-light-greylist.txt
+++ b/config/hiddenapi-light-greylist.txt
@@ -147,6 +147,7 @@ Landroid/app/admin/DevicePolicyManager;->throwIfParentInstance(Ljava/lang/String
Landroid/app/admin/IDevicePolicyManager$Stub;->TRANSACTION_packageHasActiveAdmins:I
Landroid/app/admin/IDevicePolicyManager$Stub;->TRANSACTION_removeActiveAdmin:I
Landroid/app/admin/SecurityLog$SecurityEvent;-><init>([B)V
+Landroid/app/ActionBar;->setShowHideAnimationEnabled(Z)V
Landroid/app/AlarmManager;->FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED:I
Landroid/app/AlarmManager;->FLAG_IDLE_UNTIL:I
Landroid/app/AlarmManager;->FLAG_STANDALONE:I
@@ -249,7 +250,9 @@ Landroid/app/Dialog;->mListenersHandler:Landroid/os/Handler;
Landroid/app/Dialog;->mOwnerActivity:Landroid/app/Activity;
Landroid/app/Dialog;->mShowMessage:Landroid/os/Message;
Landroid/app/DownloadManager$Request;->mUri:Landroid/net/Uri;
+Landroid/app/DownloadManager;->setAccessFilename(Z)V
Landroid/app/FragmentManagerImpl;->mAdded:Ljava/util/ArrayList;
+Landroid/app/FragmentManagerImpl;->mStateSaved:Z
Landroid/app/FragmentManagerImpl;->noteStateNotSaved()V
Landroid/app/Fragment;->mChildFragmentManager:Landroid/app/FragmentManagerImpl;
Landroid/app/Fragment;->mWho:Ljava/lang/String;
@@ -373,6 +376,8 @@ Landroid/app/Service;->setForeground(Z)V
Landroid/app/SharedPreferencesImpl;-><init>(Ljava/io/File;I)V
Landroid/app/SharedPreferencesImpl;->mFile:Ljava/io/File;
Landroid/app/SharedPreferencesImpl;->startReloadIfChangedUnexpectedly()V
+Landroid/app/slice/Slice$Builder;-><init>(Landroid/net/Uri;)V
+Landroid/app/slice/Slice$Builder;->setSpec(Landroid/app/slice/SliceSpec;)Landroid/app/slice/Slice$Builder;
Landroid/app/slice/SliceItem;->getTimestamp()J
Landroid/app/slice/SliceManager;->bindSlice(Landroid/net/Uri;Ljava/util/List;)Landroid/app/slice/Slice;
Landroid/app/slice/SliceManager;->pinSlice(Landroid/net/Uri;Ljava/util/List;)V
@@ -484,6 +489,7 @@ Landroid/bluetooth/BluetoothGattCharacteristic;->mService:Landroid/bluetooth/Blu
Landroid/bluetooth/BluetoothGattDescriptor;->mCharacteristic:Landroid/bluetooth/BluetoothGattCharacteristic;
Landroid/bluetooth/BluetoothGattDescriptor;->mInstance:I
Landroid/bluetooth/BluetoothGatt;->mAuthRetryState:I
+Landroid/bluetooth/BluetoothGatt;->mClientIf:I
Landroid/bluetooth/BluetoothGatt;->refresh()Z
Landroid/bluetooth/BluetoothHeadset;->ACTION_ACTIVE_DEVICE_CHANGED:Ljava/lang/String;
Landroid/bluetooth/BluetoothHeadset;->close()V
@@ -508,11 +514,13 @@ Landroid/bluetooth/BluetoothPan;->isValidDevice(Landroid/bluetooth/BluetoothDevi
Landroid/bluetooth/BluetoothPan;->log(Ljava/lang/String;)V
Landroid/bluetooth/BluetoothPan;->setBluetoothTethering(Z)V
Landroid/bluetooth/BluetoothProfile;->PAN:I
+Landroid/bluetooth/BluetoothSocket;->mPfd:Landroid/os/ParcelFileDescriptor;
Landroid/bluetooth/BluetoothUuid;->RESERVED_UUIDS:[Landroid/os/ParcelUuid;
Landroid/bluetooth/IBluetooth;->getAddress()Ljava/lang/String;
Landroid/bluetooth/IBluetoothManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
Landroid/bluetooth/IBluetooth$Stub;->asInterface(Landroid/os/IBinder;)Landroid/bluetooth/IBluetooth;
Landroid/bluetooth/IBluetooth$Stub$Proxy;->getAddress()Ljava/lang/String;
+Landroid/bluetooth/IBluetooth$Stub$Proxy;->getConnectionState(Landroid/bluetooth/BluetoothDevice;)I
Landroid/bluetooth/le/ScanRecord;->parseFromBytes([B)Landroid/bluetooth/le/ScanRecord;
Landroid/content/AsyncTaskLoader;->mExecutor:Ljava/util/concurrent/Executor;
Landroid/content/BroadcastReceiver$PendingResult;-><init>(ILjava/lang/String;Landroid/os/Bundle;IZZLandroid/os/IBinder;II)V
@@ -680,6 +688,7 @@ Landroid/content/res/AssetFileDescriptor;->mStartOffset:J
Landroid/content/res/AssetManager;->addAssetPathAsSharedLibrary(Ljava/lang/String;)I
Landroid/content/res/AssetManager;->addAssetPath(Ljava/lang/String;)I
Landroid/content/res/AssetManager;->applyStyle(JIILandroid/content/res/XmlBlock$Parser;[IJJ)V
+Landroid/content/res/AssetManager;->createTheme()J
Landroid/content/res/AssetManager;->getAssignedPackageIdentifiers()Landroid/util/SparseArray;
Landroid/content/res/AssetManager;->getResourceBagText(II)Ljava/lang/CharSequence;
Landroid/content/res/AssetManager;->getResourceEntryName(I)Ljava/lang/String;
@@ -709,6 +718,8 @@ Landroid/content/res/CompatibilityInfo;->DEFAULT_COMPATIBILITY_INFO:Landroid/con
Landroid/content/res/DrawableCache;->getInstance(JLandroid/content/res/Resources;Landroid/content/res/Resources$Theme;)Landroid/graphics/drawable/Drawable;
Landroid/content/res/DrawableCache;-><init>()V
Landroid/content/res/ObbInfo;->salt:[B
+Landroid/content/res/Resources;->mClassLoader:Ljava/lang/ClassLoader;
+Landroid/content/res/Resources;->mDrawableInflater:Landroid/graphics/drawable/DrawableInflater;
Landroid/content/res/Resources;->getCompatibilityInfo()Landroid/content/res/CompatibilityInfo;
Landroid/content/res/ResourcesImpl;->getAssets()Landroid/content/res/AssetManager;
Landroid/content/res/ResourcesImpl;->mAccessLock:Ljava/lang/Object;
@@ -731,6 +742,7 @@ Landroid/content/res/Resources;->mResourcesImpl:Landroid/content/res/ResourcesIm
Landroid/content/res/Resources;->mSystem:Landroid/content/res/Resources;
Landroid/content/res/Resources;->mTmpValue:Landroid/util/TypedValue;
Landroid/content/res/Resources;->mTypedArrayPool:Landroid/util/Pools$SynchronizedPool;
+Landroid/content/res/Resources;->selectDefaultTheme(II)I
Landroid/content/res/Resources;->setCompatibilityInfo(Landroid/content/res/CompatibilityInfo;)V
Landroid/content/res/Resources;->updateSystemConfiguration(Landroid/content/res/Configuration;Landroid/util/DisplayMetrics;Landroid/content/res/CompatibilityInfo;)V
Landroid/content/res/StringBlock;-><init>(JZ)V
@@ -815,12 +827,15 @@ Landroid/graphics/drawable/BitmapDrawable;->mTargetDensity:I
Landroid/graphics/drawable/BitmapDrawable;->setBitmap(Landroid/graphics/Bitmap;)V
Landroid/graphics/drawable/ColorDrawable$ColorState;->mUseColor:I
Landroid/graphics/drawable/DrawableContainer$DrawableContainerState;->mConstantPadding:Landroid/graphics/Rect;
+Landroid/graphics/drawable/DrawableContainer$DrawableContainerState;->mDrawables:[Landroid/graphics/drawable/Drawable;
Landroid/graphics/drawable/DrawableContainer;->getOpticalInsets()Landroid/graphics/Insets;
Landroid/graphics/drawable/DrawableContainer;->mDrawableContainerState:Landroid/graphics/drawable/DrawableContainer$DrawableContainerState;
Landroid/graphics/drawable/Drawable;->getOpticalInsets()Landroid/graphics/Insets;
Landroid/graphics/drawable/Drawable;->inflateWithAttributes(Landroid/content/res/Resources;Lorg/xmlpull/v1/XmlPullParser;Landroid/content/res/TypedArray;I)V
Landroid/graphics/drawable/Drawable;->mCallback:Ljava/lang/ref/WeakReference;
Landroid/graphics/drawable/Drawable;->parseTintMode(ILandroid/graphics/PorterDuff$Mode;)Landroid/graphics/PorterDuff$Mode;
+Landroid/graphics/drawable/DrawableInflater;->mClassLoader:Ljava/lang/ClassLoader;
+Landroid/graphics/drawable/GradientDrawable;->getOpticalInsets()Landroid/graphics/Insets;
Landroid/graphics/drawable/GradientDrawable$GradientState;->mAngle:I
Landroid/graphics/drawable/GradientDrawable$GradientState;->mGradientColors:[I
Landroid/graphics/drawable/GradientDrawable$GradientState;->mGradient:I
@@ -864,6 +879,10 @@ Landroid/graphics/drawable/StateListDrawable;->getStateDrawableIndex([I)I
Landroid/graphics/drawable/StateListDrawable;->getStateSet(I)[I
Landroid/graphics/drawable/StateListDrawable;->mStateListState:Landroid/graphics/drawable/StateListDrawable$StateListState;
Landroid/graphics/drawable/StateListDrawable;->updateStateFromTypedArray(Landroid/content/res/TypedArray;)V
+Landroid/graphics/drawable/VectorDrawable;->getTargetByName(Ljava/lang/String;)Ljava/lang/Object;
+Landroid/graphics/drawable/VectorDrawable;->mTintFilter:Landroid/graphics/PorterDuffColorFilter;
+Landroid/graphics/drawable/VectorDrawable;->setAllowCaching(Z)V
+Landroid/graphics/drawable/VectorDrawable$VGroup;->setRotation(F)V
Landroid/graphics/FontFamily;->abortCreation()V
Landroid/graphics/FontFamily;->addFontFromAssetManager(Landroid/content/res/AssetManager;Ljava/lang/String;IZIII[Landroid/graphics/fonts/FontVariationAxis;)Z
Landroid/graphics/FontFamily;->addFontFromBuffer(Ljava/nio/ByteBuffer;I[Landroid/graphics/fonts/FontVariationAxis;II)Z
@@ -886,6 +905,7 @@ Landroid/graphics/NinePatch$InsetStruct;-><init>(IIIIIIIIFIF)V
Landroid/graphics/NinePatch;->mBitmap:Landroid/graphics/Bitmap;
Landroid/graphics/Picture;->mNativePicture:J
Landroid/graphics/PixelXorXfermode;-><init>(I)V
+Landroid/graphics/PorterDuffColorFilter;->getColor()I
Landroid/graphics/PorterDuffColorFilter;->setColor(I)V
Landroid/graphics/PorterDuffColorFilter;->setMode(Landroid/graphics/PorterDuff$Mode;)V
Landroid/graphics/Rect;->scale(F)V
@@ -907,6 +927,8 @@ Landroid/hardware/camera2/CameraCharacteristics;->CONTROL_MAX_REGIONS:Landroid/h
Landroid/hardware/camera2/CameraCharacteristics;->DEPTH_AVAILABLE_DEPTH_MIN_FRAME_DURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;
Landroid/hardware/camera2/CameraCharacteristics;->DEPTH_AVAILABLE_DEPTH_STALL_DURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;
Landroid/hardware/camera2/CameraCharacteristics;->DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;
+Landroid/hardware/camera2/CameraCharacteristics$Key;->getNativeKey()Landroid/hardware/camera2/impl/CameraMetadataNative$Key;
+Landroid/hardware/camera2/CameraCharacteristics$Key;-><init>(Ljava/lang/String;Landroid/hardware/camera2/utils/TypeReference;)V
Landroid/hardware/camera2/CameraCharacteristics$Key;-><init>(Ljava/lang/String;Ljava/lang/Class;J)V
Landroid/hardware/camera2/CameraCharacteristics$Key;-><init>(Ljava/lang/String;Ljava/lang/Class;)V
Landroid/hardware/camera2/CameraCharacteristics;->LED_AVAILABLE_LEDS:Landroid/hardware/camera2/CameraCharacteristics$Key;
@@ -931,6 +953,8 @@ Landroid/hardware/camera2/CameraCharacteristics;->SCALER_AVAILABLE_STREAM_CONFIG
Landroid/hardware/camera2/CaptureRequest;->JPEG_GPS_COORDINATES:Landroid/hardware/camera2/CaptureRequest$Key;
Landroid/hardware/camera2/CaptureRequest;->JPEG_GPS_PROCESSING_METHOD:Landroid/hardware/camera2/CaptureRequest$Key;
Landroid/hardware/camera2/CaptureRequest;->JPEG_GPS_TIMESTAMP:Landroid/hardware/camera2/CaptureRequest$Key;
+Landroid/hardware/camera2/CaptureRequest$Key;->getNativeKey()Landroid/hardware/camera2/impl/CameraMetadataNative$Key;
+Landroid/hardware/camera2/CaptureRequest$Key;-><init>(Ljava/lang/String;Landroid/hardware/camera2/utils/TypeReference;)V
Landroid/hardware/camera2/CaptureRequest$Key;-><init>(Ljava/lang/String;Ljava/lang/Class;J)V
Landroid/hardware/camera2/CaptureRequest;->LED_TRANSMIT:Landroid/hardware/camera2/CaptureRequest$Key;
Landroid/hardware/camera2/CaptureRequest;->REQUEST_ID:Landroid/hardware/camera2/CaptureRequest$Key;
@@ -940,6 +964,8 @@ Landroid/hardware/camera2/CaptureRequest;->TONEMAP_CURVE_RED:Landroid/hardware/c
Landroid/hardware/camera2/CaptureResult;->JPEG_GPS_COORDINATES:Landroid/hardware/camera2/CaptureResult$Key;
Landroid/hardware/camera2/CaptureResult;->JPEG_GPS_PROCESSING_METHOD:Landroid/hardware/camera2/CaptureResult$Key;
Landroid/hardware/camera2/CaptureResult;->JPEG_GPS_TIMESTAMP:Landroid/hardware/camera2/CaptureResult$Key;
+Landroid/hardware/camera2/CaptureResult$Key;->getNativeKey()Landroid/hardware/camera2/impl/CameraMetadataNative$Key;
+Landroid/hardware/camera2/CaptureResult$Key;-><init>(Ljava/lang/String;Landroid/hardware/camera2/utils/TypeReference;)V
Landroid/hardware/camera2/CaptureResult$Key;-><init>(Ljava/lang/String;Ljava/lang/Class;J)V
Landroid/hardware/camera2/CaptureResult$Key;-><init>(Ljava/lang/String;Ljava/lang/Class;)V
Landroid/hardware/camera2/CaptureResult;->LED_TRANSMIT:Landroid/hardware/camera2/CaptureResult$Key;
@@ -960,7 +986,9 @@ Landroid/hardware/camera2/CaptureResult;->SYNC_FRAME_NUMBER:Landroid/hardware/ca
Landroid/hardware/camera2/CaptureResult;->TONEMAP_CURVE_BLUE:Landroid/hardware/camera2/CaptureResult$Key;
Landroid/hardware/camera2/CaptureResult;->TONEMAP_CURVE_GREEN:Landroid/hardware/camera2/CaptureResult$Key;
Landroid/hardware/camera2/CaptureResult;->TONEMAP_CURVE_RED:Landroid/hardware/camera2/CaptureResult$Key;
+Landroid/hardware/camera2/impl/CameraMetadataNative$Key;->getTag()I
Landroid/hardware/camera2/impl/CameraMetadataNative;->mMetadataPtr:J
+Landroid/hardware/camera2/utils/TypeReference;->createSpecializedTypeReference(Ljava/lang/reflect/Type;)Landroid/hardware/camera2/utils/TypeReference;
Landroid/hardware/Camera;->addCallbackBuffer([BI)V
Landroid/hardware/Camera;->mNativeContext:J
Landroid/hardware/Camera;->openLegacy(II)Landroid/hardware/Camera;
@@ -1276,6 +1304,10 @@ Landroid/net/ConnectivityManager;->TYPE_NONE:I
Landroid/net/ConnectivityManager;->TYPE_PROXY:I
Landroid/net/ConnectivityManager;->TYPE_WIFI_P2P:I
Landroid/net/http/SslError;->mCertificate:Landroid/net/http/SslCertificate;
+Landroid/net/IConnectivityManager;->getActiveLinkProperties()Landroid/net/LinkProperties;
+Landroid/net/IConnectivityManager;->getActiveNetworkInfo()Landroid/net/NetworkInfo;
+Landroid/net/IConnectivityManager;->getAllNetworkInfo()[Landroid/net/NetworkInfo;
+Landroid/net/IConnectivityManager;->getTetheredIfaces()[Ljava/lang/String;
Landroid/net/IConnectivityManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/IConnectivityManager;
Landroid/net/IConnectivityManager$Stub$Proxy;->getActiveLinkProperties()Landroid/net/LinkProperties;
Landroid/net/IConnectivityManager$Stub$Proxy;->getActiveNetworkInfo()Landroid/net/NetworkInfo;
@@ -1395,6 +1427,7 @@ Landroid/net/wifi/WifiEnterpriseConfig;->getCaCertificateAlias()Ljava/lang/Strin
Landroid/net/wifi/WifiEnterpriseConfig;->getClientCertificateAlias()Ljava/lang/String;
Landroid/net/wifi/WifiInfo;->DEFAULT_MAC_ADDRESS:Ljava/lang/String;
Landroid/net/wifi/WifiInfo;->getMeteredHint()Z
+Landroid/net/wifi/WifiInfo;->getWifiSsid()Landroid/net/wifi/WifiSsid;
Landroid/net/wifi/WifiInfo;->mMacAddress:Ljava/lang/String;
Landroid/net/wifi/WifiInfo;->removeDoubleQuotes(Ljava/lang/String;)Ljava/lang/String;
Landroid/net/wifi/WifiManager;->cancelLocalOnlyHotspotRequest()V
@@ -1403,11 +1436,12 @@ Landroid/net/wifi/WifiManager;->forget(ILandroid/net/wifi/WifiManager$ActionList
Landroid/net/wifi/WifiManager;->isDualBandSupported()Z
Landroid/net/wifi/WifiManager;->mService:Landroid/net/wifi/IWifiManager;
Landroid/net/wifi/WifiManager;->save(Landroid/net/wifi/WifiConfiguration;Landroid/net/wifi/WifiManager$ActionListener;)V
+Landroid/net/wifi/WifiSsid;->getOctets()[B
Landroid/net/wifi/WifiSsid;->NONE:Ljava/lang/String;
Landroid/nfc/NfcAdapter;->getAdapterState()I
Landroid/nfc/NfcAdapter;->getDefaultAdapter()Landroid/nfc/NfcAdapter;
-Landroid/nfc/NfcAdapter;->setNdefPushMessageCallback(Landroid/nfc/NfcAdapter$CreateNdefMessageCallback;Landroid/app/Activity;I)V
Landroid/nfc/NfcAdapter;->getNfcAdapter(Landroid/content/Context;)Landroid/nfc/NfcAdapter;
+Landroid/nfc/NfcAdapter;->setNdefPushMessageCallback(Landroid/nfc/NfcAdapter$CreateNdefMessageCallback;Landroid/app/Activity;I)V
Landroid/opengl/GLSurfaceView$EglHelper;->mEglContext:Ljavax/microedition/khronos/egl/EGLContext;
Landroid/opengl/GLSurfaceView$GLThread;->mEglHelper:Landroid/opengl/GLSurfaceView$EglHelper;
Landroid/opengl/GLSurfaceView;->mGLThread:Landroid/opengl/GLSurfaceView$GLThread;
@@ -1716,6 +1750,7 @@ Landroid/os/WorkSource;->mNum:I
Landroid/os/WorkSource;->mUids:[I
Landroid/os/WorkSource;->setReturningDiffs(Landroid/os/WorkSource;)[Landroid/os/WorkSource;
Landroid/os/WorkSource;->size()I
+Landroid/permissionpresenterservice/RuntimePermissionPresenterService;->onRevokeRuntimePermission(Ljava/lang/String;Ljava/lang/String;)V
Landroid/preference/DialogPreference;->mBuilder:Landroid/app/AlertDialog$Builder;
Landroid/preference/DialogPreference;->mDialogIcon:Landroid/graphics/drawable/Drawable;
Landroid/preference/DialogPreference;->mDialog:Landroid/app/Dialog;
@@ -1995,6 +2030,7 @@ Landroid/R$styleable;->Window_windowBackground:I
Landroid/R$styleable;->Window_windowFrame:I
Landroid/security/keystore/AndroidKeyStoreProvider;->getKeyStoreOperationHandle(Ljava/lang/Object;)J
Landroid/security/KeyStore;->getInstance()Landroid/security/KeyStore;
+Landroid/security/keystore/recovery/RecoveryController;->initRecoveryService(Ljava/lang/String;[B)V
Landroid/security/net/config/RootTrustManager;->checkServerTrusted([Ljava/security/cert/X509Certificate;Ljava/lang/String;Ljava/lang/String;)Ljava/util/List;
Landroid/service/media/IMediaBrowserServiceCallbacks;->onConnectFailed()V
Landroid/service/media/IMediaBrowserServiceCallbacks;->onConnect(Ljava/lang/String;Landroid/media/session/MediaSession$Token;Landroid/os/Bundle;)V
@@ -2290,6 +2326,7 @@ Landroid/view/Choreographer;->mLock:Ljava/lang/Object;
Landroid/view/Choreographer;->scheduleVsyncLocked()V
Landroid/view/Choreographer;->USE_VSYNC:Z
Landroid/view/ContextThemeWrapper;->getThemeResId()I
+Landroid/view/ContextThemeWrapper;->initializeTheme()V
Landroid/view/ContextThemeWrapper;->mInflater:Landroid/view/LayoutInflater;
Landroid/view/ContextThemeWrapper;->mResources:Landroid/content/res/Resources;
Landroid/view/ContextThemeWrapper;->mTheme:Landroid/content/res/Resources$Theme;
@@ -2448,6 +2485,7 @@ Landroid/view/textclassifier/TextClassificationManager;->getTextClassifier(I)Lan
Landroid/view/textclassifier/TextClassifier;->classifyText(Ljava/lang/CharSequence;IILandroid/view/textclassifier/TextClassification$Options;)Landroid/view/textclassifier/TextClassification;
Landroid/view/textclassifier/TextClassifier;->generateLinks(Ljava/lang/CharSequence;Landroid/view/textclassifier/TextLinks$Options;)Landroid/view/textclassifier/TextLinks;
Landroid/view/textclassifier/TextClassifier;->suggestSelection(Ljava/lang/CharSequence;IILandroid/view/textclassifier/TextSelection$Options;)Landroid/view/textclassifier/TextSelection;
+Landroid/view/textclassifier/TextLinks$Options;-><init>()V
Landroid/view/textservice/TextServicesManager;->isSpellCheckerEnabled()Z
Landroid/view/TextureView;->destroyHardwareLayer()V
Landroid/view/TextureView;->destroyHardwareResources()V
@@ -2523,6 +2561,7 @@ Landroid/view/View;->isVisibleToUser(Landroid/graphics/Rect;)Z
Landroid/view/View;->isVisibleToUser()Z
Landroid/view/View$ListenerInfo;-><init>()V
Landroid/view/View$ListenerInfo;->mOnClickListener:Landroid/view/View$OnClickListener;
+Landroid/view/View$ListenerInfo;->mOnDragListener:Landroid/view/View$OnDragListener;
Landroid/view/View$ListenerInfo;->mOnFocusChangeListener:Landroid/view/View$OnFocusChangeListener;
Landroid/view/View$ListenerInfo;->mOnLongClickListener:Landroid/view/View$OnLongClickListener;
Landroid/view/View$ListenerInfo;->mOnTouchListener:Landroid/view/View$OnTouchListener;
@@ -2677,6 +2716,7 @@ Landroid/widget/AbsListView$FlingRunnable;->start(I)V
Landroid/widget/AbsListView;->invokeOnItemScrollListener()V
Landroid/widget/AbsListView;->isVerticalScrollBarHidden()Z
Landroid/widget/AbsListView;->mAdapter:Landroid/widget/ListAdapter;
+Landroid/widget/AbsListView;->mDataSetObserver:Landroid/widget/AbsListView$AdapterDataSetObserver;
Landroid/widget/AbsListView;->mEdgeGlowBottom:Landroid/widget/EdgeEffect;
Landroid/widget/AbsListView;->mEdgeGlowTop:Landroid/widget/EdgeEffect;
Landroid/widget/AbsListView;->mFastScroll:Landroid/widget/FastScroller;
@@ -2784,6 +2824,8 @@ Landroid/widget/ListView;->fillUp(II)Landroid/view/View;
Landroid/widget/ListView;->findViewTraversal(I)Landroid/view/View;
Landroid/widget/ListView;->findViewWithTagTraversal(Ljava/lang/Object;)Landroid/view/View;
Landroid/widget/ListView;->mAreAllItemsSelectable:Z
+Landroid/widget/ListView;->mFooterViewInfos:Ljava/util/ArrayList;
+Landroid/widget/ListView;->mHeaderViewInfos:Ljava/util/ArrayList;
Landroid/widget/ListView;->setSelectionInt(I)V
Landroid/widget/MediaController;->mAnchor:Landroid/view/View;
Landroid/widget/MediaController;->mDecor:Landroid/view/View;
@@ -2873,9 +2915,9 @@ Landroid/widget/Switch;->mThumbDrawable:Landroid/graphics/drawable/Drawable;
Landroid/widget/Switch;->mTrackDrawable:Landroid/graphics/drawable/Drawable;
Landroid/widget/TabHost$IntentContentStrategy;->getContentView()Landroid/view/View;
Landroid/widget/TabHost$IntentContentStrategy;->tabClosed()V
-Landroid/widget/TabHost$TabSpec;->mIndicatorStrategy:Landroid/widget/TabHost$IndicatorStrategy;
Landroid/widget/TabHost;->mTabSpecs:Ljava/util/List;
Landroid/widget/TabHost$TabSpec;->mContentStrategy:Landroid/widget/TabHost$ContentStrategy;
+Landroid/widget/TabHost$TabSpec;->mIndicatorStrategy:Landroid/widget/TabHost$IndicatorStrategy;
Landroid/widget/TabWidget;->mDrawBottomStrips:Z
Landroid/widget/TabWidget;->mSelectedTab:I
Landroid/widget/TabWidget;->setTabSelectionListener(Landroid/widget/TabWidget$OnTabSelectionChanged;)V
@@ -2884,6 +2926,7 @@ Landroid/widget/TextView;->createEditorIfNeeded()V
Landroid/widget/TextView;->getHorizontallyScrolling()Z
Landroid/widget/TextView;->getTextColor(Landroid/content/Context;Landroid/content/res/TypedArray;I)I
Landroid/widget/TextView;->isSingleLine()Z
+Landroid/widget/TextView;->LINES:I
Landroid/widget/TextView;->mCursorDrawableRes:I
Landroid/widget/TextView;->mCurTextColor:I
Landroid/widget/TextView;->mEditor:Landroid/widget/Editor;
@@ -3422,9 +3465,13 @@ Ljava/io/FileDescriptor;->descriptor:I
Ljava/io/FileDescriptor;->getInt$()I
Ljava/io/FileDescriptor;->isSocket$()Z
Ljava/io/FileDescriptor;->setInt$(I)V
+Ljava/io/File;->filePath:Ljava/nio/file/Path;
Ljava/io/File;->fs:Ljava/io/FileSystem;
Ljava/io/FileInputStream;->fd:Ljava/io/FileDescriptor;
Ljava/io/FileOutputStream;->fd:Ljava/io/FileDescriptor;
+Ljava/io/File;->path:Ljava/lang/String;
+Ljava/io/File;->prefixLength:I
+Ljava/io/File;->status:Ljava/io/File$PathStatus;
Ljava/io/ObjectStreamClass;->getConstructorId(Ljava/lang/Class;)J
Ljava/io/ObjectStreamClass;->newInstance(Ljava/lang/Class;J)Ljava/lang/Object;
Ljava/io/ObjectStreamClass;->newInstance()Ljava/lang/Object;
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 289a4dd77723..539a01043657 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -2102,18 +2102,24 @@ public class ActivityManager {
private final GraphicBuffer mSnapshot;
private final int mOrientation;
private final Rect mContentInsets;
+ // Whether this snapshot is a down-sampled version of the full resolution, used mainly for
+ // low-ram devices
private final boolean mReducedResolution;
+ // Whether or not the snapshot is a real snapshot or an app-theme generated snapshot due to
+ // the task having a secure window or having previews disabled
private final boolean mIsRealSnapshot;
+ private final int mWindowingMode;
private final float mScale;
public TaskSnapshot(GraphicBuffer snapshot, int orientation, Rect contentInsets,
- boolean reducedResolution, float scale, boolean isRealSnapshot) {
+ boolean reducedResolution, float scale, boolean isRealSnapshot, int windowingMode) {
mSnapshot = snapshot;
mOrientation = orientation;
mContentInsets = new Rect(contentInsets);
mReducedResolution = reducedResolution;
mScale = scale;
mIsRealSnapshot = isRealSnapshot;
+ mWindowingMode = windowingMode;
}
private TaskSnapshot(Parcel source) {
@@ -2123,6 +2129,7 @@ public class ActivityManager {
mReducedResolution = source.readBoolean();
mScale = source.readFloat();
mIsRealSnapshot = source.readBoolean();
+ mWindowingMode = source.readInt();
}
/**
@@ -2163,6 +2170,13 @@ public class ActivityManager {
}
/**
+ * @return The windowing mode of the task when this snapshot was taken.
+ */
+ public int getWindowingMode() {
+ return mWindowingMode;
+ }
+
+ /**
* @return The scale this snapshot was taken in.
*/
public float getScale() {
@@ -2182,14 +2196,18 @@ public class ActivityManager {
dest.writeBoolean(mReducedResolution);
dest.writeFloat(mScale);
dest.writeBoolean(mIsRealSnapshot);
+ dest.writeInt(mWindowingMode);
}
@Override
public String toString() {
- return "TaskSnapshot{mSnapshot=" + mSnapshot + " mOrientation=" + mOrientation
+ final int width = mSnapshot != null ? mSnapshot.getWidth() : 0;
+ final int height = mSnapshot != null ? mSnapshot.getHeight() : 0;
+ return "TaskSnapshot{mSnapshot=" + mSnapshot + " (" + width + "x" + height + ")"
+ + " mOrientation=" + mOrientation
+ " mContentInsets=" + mContentInsets.toShortString()
+ " mReducedResolution=" + mReducedResolution + " mScale=" + mScale
- + " mIsRealSnapshot=" + mIsRealSnapshot;
+ + " mIsRealSnapshot=" + mIsRealSnapshot + " mWindowingMode=" + mWindowingMode;
}
public static final Creator<TaskSnapshot> CREATOR = new Creator<TaskSnapshot>() {
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 4f88a03db435..eeec7caad7ee 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -972,6 +972,18 @@ public class Notification implements Parcelable
public static final String EXTRA_REMOTE_INPUT_HISTORY = "android.remoteInputHistory";
/**
+ * {@link #extras} key: boolean as supplied to
+ * {@link Builder#setShowRemoteInputSpinner(boolean)}.
+ *
+ * If set to true, then the view displaying the remote input history from
+ * {@link Builder#setRemoteInputHistory(CharSequence[])} will have a progress spinner.
+ *
+ * @see Builder#setShowRemoteInputSpinner(boolean)
+ * @hide
+ */
+ public static final String EXTRA_SHOW_REMOTE_INPUT_SPINNER = "android.remoteInputSpinner";
+
+ /**
* {@link #extras} key: this is a small piece of additional text as supplied to
* {@link Builder#setContentInfo(CharSequence)}.
*/
@@ -3142,10 +3154,14 @@ public class Notification implements Parcelable
private int mCachedContrastColor = COLOR_INVALID;
private int mCachedContrastColorIsFor = COLOR_INVALID;
/**
- * Caches a ambient version of {@link #mCachedContrastColorIsFor}.
+ * Caches a ambient version of {@link #mCachedAmbientColorIsFor}.
*/
private int mCachedAmbientColor = COLOR_INVALID;
private int mCachedAmbientColorIsFor = COLOR_INVALID;
+ /**
+ * A neutral color color that can be used for icons.
+ */
+ private int mNeutralColor = COLOR_INVALID;
/**
* Caches an instance of StandardTemplateParams. Note that this may have been used before,
@@ -3537,6 +3553,15 @@ public class Notification implements Parcelable
}
/**
+ * Sets whether remote history entries view should have a spinner.
+ * @hide
+ */
+ public Builder setShowRemoteInputSpinner(boolean showSpinner) {
+ mN.extras.putBoolean(EXTRA_SHOW_REMOTE_INPUT_SPINNER, showSpinner);
+ return this;
+ }
+
+ /**
* Sets the number of items this notification represents. May be displayed as a badge count
* for Launchers that support badging.
*/
@@ -4278,7 +4303,6 @@ public class Notification implements Parcelable
private void resetStandardTemplate(RemoteViews contentView) {
resetNotificationHeader(contentView);
- resetContentMargins(contentView);
contentView.setViewVisibility(R.id.right_icon, View.GONE);
contentView.setViewVisibility(R.id.title, View.GONE);
contentView.setTextViewText(R.id.title, null);
@@ -4310,24 +4334,23 @@ public class Notification implements Parcelable
mN.mUsesStandardHeader = false;
}
- private void resetContentMargins(RemoteViews contentView) {
- contentView.setViewLayoutMarginEndDimen(R.id.line1, 0);
- contentView.setViewLayoutMarginEndDimen(R.id.text, 0);
- }
-
- private RemoteViews applyStandardTemplate(int resId) {
- return applyStandardTemplate(resId, mParams.reset().fillTextsFrom(this));
+ private RemoteViews applyStandardTemplate(int resId, TemplateBindResult result) {
+ return applyStandardTemplate(resId, mParams.reset().fillTextsFrom(this),
+ result);
}
/**
* @param hasProgress whether the progress bar should be shown and set
+ * @param result
*/
- private RemoteViews applyStandardTemplate(int resId, boolean hasProgress) {
+ private RemoteViews applyStandardTemplate(int resId, boolean hasProgress,
+ TemplateBindResult result) {
return applyStandardTemplate(resId, mParams.reset().hasProgress(hasProgress)
- .fillTextsFrom(this));
+ .fillTextsFrom(this), result);
}
- private RemoteViews applyStandardTemplate(int resId, StandardTemplateParams p) {
+ private RemoteViews applyStandardTemplate(int resId, StandardTemplateParams p,
+ TemplateBindResult result) {
RemoteViews contentView = new BuilderRemoteViews(mContext.getApplicationInfo(), resId);
resetStandardTemplate(contentView);
@@ -4335,7 +4358,7 @@ public class Notification implements Parcelable
final Bundle ex = mN.extras;
updateBackgroundColor(contentView);
bindNotificationHeader(contentView, p.ambient, p.headerTextSecondary);
- bindLargeIcon(contentView, p.hideLargeIcon || p.ambient, p.alwaysShowReply);
+ bindLargeIconAndReply(contentView, p, result);
boolean showProgress = handleProgressBar(p.hasProgress, contentView, ex);
if (p.title != null) {
contentView.setViewVisibility(R.id.title, View.VISIBLE);
@@ -4531,8 +4554,58 @@ public class Notification implements Parcelable
}
}
- private void bindLargeIcon(RemoteViews contentView, boolean hideLargeIcon,
- boolean alwaysShowReply) {
+ private void bindLargeIconAndReply(RemoteViews contentView, StandardTemplateParams p,
+ TemplateBindResult result) {
+ boolean largeIconShown = bindLargeIcon(contentView, p.hideLargeIcon || p.ambient);
+ boolean replyIconShown = bindReplyIcon(contentView, p.hideReplyIcon || p.ambient);
+ contentView.setViewVisibility(R.id.right_icon_container,
+ largeIconShown || replyIconShown ? View.VISIBLE : View.GONE);
+ int marginEnd = calculateMarginEnd(largeIconShown, replyIconShown);
+ contentView.setViewLayoutMarginEnd(R.id.line1, marginEnd);
+ contentView.setViewLayoutMarginEnd(R.id.text, marginEnd);
+ contentView.setViewLayoutMarginEnd(R.id.progress, marginEnd);
+ if (result != null) {
+ result.setIconMarginEnd(marginEnd);
+ }
+ }
+
+ private int calculateMarginEnd(boolean largeIconShown, boolean replyIconShown) {
+ int marginEnd = 0;
+ int contentMargin = mContext.getResources().getDimensionPixelSize(
+ R.dimen.notification_content_margin_end);
+ int iconSize = mContext.getResources().getDimensionPixelSize(
+ R.dimen.notification_right_icon_size);
+ if (replyIconShown) {
+ // The size of the reply icon
+ marginEnd += iconSize;
+
+ int replyInset = mContext.getResources().getDimensionPixelSize(
+ R.dimen.notification_reply_inset);
+ // We're subtracting the inset of the reply icon to make sure it's
+ // aligned nicely on the right, and remove it from the following padding
+ marginEnd -= replyInset * 2;
+ }
+ if (largeIconShown) {
+ // adding size of the right icon
+ marginEnd += iconSize;
+
+ if (replyIconShown) {
+ // We also add some padding to the reply icon if it's around
+ marginEnd += contentMargin;
+ }
+ }
+ if (replyIconShown || largeIconShown) {
+ // The padding to the content
+ marginEnd += contentMargin;
+ }
+ return marginEnd;
+ }
+
+ /**
+ * Bind the large icon.
+ * @return if the largeIcon is visible
+ */
+ private boolean bindLargeIcon(RemoteViews contentView, boolean hideLargeIcon) {
if (mN.mLargeIcon == null && mN.largeIcon != null) {
mN.mLargeIcon = Icon.createWithBitmap(mN.largeIcon);
}
@@ -4541,51 +4614,35 @@ public class Notification implements Parcelable
contentView.setViewVisibility(R.id.right_icon, View.VISIBLE);
contentView.setImageViewIcon(R.id.right_icon, mN.mLargeIcon);
processLargeLegacyIcon(mN.mLargeIcon, contentView);
- int endMargin = R.dimen.notification_content_picture_margin;
- contentView.setViewLayoutMarginEndDimen(R.id.line1, endMargin);
- contentView.setViewLayoutMarginEndDimen(R.id.text, endMargin);
- contentView.setViewLayoutMarginEndDimen(R.id.progress, endMargin);
}
- // Bind the reply action
- Action action = findReplyAction();
+ return showLargeIcon;
+ }
- boolean actionVisible = action != null && (showLargeIcon || alwaysShowReply);
- int replyId = showLargeIcon ? R.id.reply_icon_action : R.id.right_icon;
+ /**
+ * Bind the reply icon.
+ * @return if the reply icon is visible
+ */
+ private boolean bindReplyIcon(RemoteViews contentView, boolean hideReplyIcon) {
+ boolean actionVisible = !hideReplyIcon;
+ Action action = null;
if (actionVisible) {
- // We're only showing the icon as big if we're hiding the large icon
- int contrastColor = resolveContrastColor();
- int iconColor;
- if (showLargeIcon) {
- contentView.setDrawableTint(R.id.reply_icon_action,
- true /* targetBackground */,
- contrastColor, PorterDuff.Mode.SRC_ATOP);
- contentView.setOnClickPendingIntent(R.id.right_icon,
- action.actionIntent);
- contentView.setRemoteInputs(R.id.right_icon, action.mRemoteInputs);
- iconColor = NotificationColorUtil.isColorLight(contrastColor)
- ? Color.BLACK : Color.WHITE;
- } else {
- contentView.setImageViewResource(R.id.right_icon,
- R.drawable.ic_reply_notification_large);
- contentView.setViewVisibility(R.id.right_icon, View.VISIBLE);
- iconColor = contrastColor;
- }
- contentView.setDrawableTint(replyId,
+ action = findReplyAction();
+ actionVisible = action != null;
+ }
+ if (actionVisible) {
+ contentView.setViewVisibility(R.id.reply_icon_action, View.VISIBLE);
+ contentView.setDrawableTint(R.id.reply_icon_action,
false /* targetBackground */,
- iconColor,
+ getNeutralColor(),
PorterDuff.Mode.SRC_ATOP);
- contentView.setOnClickPendingIntent(replyId,
- action.actionIntent);
- contentView.setRemoteInputs(replyId, action.mRemoteInputs);
+ contentView.setOnClickPendingIntent(R.id.reply_icon_action, action.actionIntent);
+ contentView.setRemoteInputs(R.id.reply_icon_action, action.mRemoteInputs);
} else {
- contentView.setRemoteInputs(R.id.right_icon, null);
+ contentView.setRemoteInputs(R.id.reply_icon_action, null);
}
- contentView.setViewVisibility(R.id.reply_icon_action, actionVisible && showLargeIcon
- ? View.VISIBLE
- : View.GONE);
- contentView.setViewVisibility(R.id.right_icon_container, actionVisible || showLargeIcon
- ? View.VISIBLE
- : View.GONE);
+ contentView.setViewVisibility(R.id.reply_icon_action,
+ actionVisible ? View.VISIBLE : View.GONE);
+ return actionVisible;
}
private Action findReplyAction() {
@@ -4620,8 +4677,7 @@ public class Notification implements Parcelable
}
private void bindActivePermissions(RemoteViews contentView, boolean ambient) {
- int color = ambient ? resolveAmbientColor()
- : isColorized() ? getPrimaryTextColor() : resolveContrastColor();
+ int color = ambient ? resolveAmbientColor() : getNeutralColor();
contentView.setDrawableTint(R.id.camera, false, color, PorterDuff.Mode.SRC_ATOP);
contentView.setDrawableTint(R.id.mic, false, color, PorterDuff.Mode.SRC_ATOP);
contentView.setDrawableTint(R.id.overlay, false, color, PorterDuff.Mode.SRC_ATOP);
@@ -4760,6 +4816,8 @@ public class Notification implements Parcelable
big.setViewVisibility(R.id.notification_material_reply_container, View.GONE);
big.setTextViewText(R.id.notification_material_reply_text_1, null);
+ big.setViewVisibility(R.id.notification_material_reply_text_1_container, View.GONE);
+ big.setViewVisibility(R.id.notification_material_reply_progress, View.GONE);
big.setViewVisibility(R.id.notification_material_reply_text_2, View.GONE);
big.setTextViewText(R.id.notification_material_reply_text_2, null);
@@ -4770,13 +4828,15 @@ public class Notification implements Parcelable
R.dimen.notification_content_margin);
}
- private RemoteViews applyStandardTemplateWithActions(int layoutId) {
- return applyStandardTemplateWithActions(layoutId, mParams.reset().fillTextsFrom(this));
+ private RemoteViews applyStandardTemplateWithActions(int layoutId,
+ TemplateBindResult result) {
+ return applyStandardTemplateWithActions(layoutId, mParams.reset().fillTextsFrom(this),
+ result);
}
private RemoteViews applyStandardTemplateWithActions(int layoutId,
- StandardTemplateParams p) {
- RemoteViews big = applyStandardTemplate(layoutId, p);
+ StandardTemplateParams p, TemplateBindResult result) {
+ RemoteViews big = applyStandardTemplate(layoutId, p, result);
resetStandardTemplateWithActions(big);
@@ -4810,10 +4870,19 @@ public class Notification implements Parcelable
CharSequence[] replyText = mN.extras.getCharSequenceArray(EXTRA_REMOTE_INPUT_HISTORY);
if (!p.ambient && validRemoteInput && replyText != null
&& replyText.length > 0 && !TextUtils.isEmpty(replyText[0])) {
+ boolean showSpinner = mN.extras.getBoolean(EXTRA_SHOW_REMOTE_INPUT_SPINNER);
big.setViewVisibility(R.id.notification_material_reply_container, View.VISIBLE);
+ big.setViewVisibility(R.id.notification_material_reply_text_1_container,
+ View.VISIBLE);
big.setTextViewText(R.id.notification_material_reply_text_1,
processTextSpans(replyText[0]));
setTextViewColorSecondary(big, R.id.notification_material_reply_text_1);
+ big.setViewVisibility(R.id.notification_material_reply_progress,
+ showSpinner ? View.VISIBLE : View.GONE);
+ big.setProgressIndeterminateTintList(
+ R.id.notification_material_reply_progress,
+ ColorStateList.valueOf(
+ isColorized() ? getPrimaryTextColor() : resolveContrastColor()));
if (replyText.length > 1 && !TextUtils.isEmpty(replyText[1])) {
big.setViewVisibility(R.id.notification_material_reply_text_2, View.VISIBLE);
@@ -4883,7 +4952,7 @@ public class Notification implements Parcelable
return styleView;
}
}
- return applyStandardTemplate(getBaseLayoutResource());
+ return applyStandardTemplate(getBaseLayoutResource(), null /* result */);
}
private boolean useExistingRemoteView() {
@@ -4902,7 +4971,8 @@ public class Notification implements Parcelable
result = mStyle.makeBigContentView();
hideLine1Text(result);
} else if (mActions.size() != 0) {
- result = applyStandardTemplateWithActions(getBigBaseLayoutResource());
+ result = applyStandardTemplateWithActions(getBigBaseLayoutResource(),
+ null /* result */);
}
makeHeaderExpanded(result);
return result;
@@ -4939,7 +5009,8 @@ public class Notification implements Parcelable
public RemoteViews makeAmbientNotification() {
RemoteViews ambient = applyStandardTemplateWithActions(
R.layout.notification_template_material_ambient,
- mParams.reset().ambient(true).fillTextsFrom(this).hasProgress(false));
+ mParams.reset().ambient(true).fillTextsFrom(this).hasProgress(false),
+ null /* result */);
return ambient;
}
@@ -4982,7 +5053,7 @@ public class Notification implements Parcelable
return null;
}
- return applyStandardTemplateWithActions(getBigBaseLayoutResource());
+ return applyStandardTemplateWithActions(getBigBaseLayoutResource(), null /* result */);
}
/**
@@ -5330,6 +5401,20 @@ public class Notification implements Parcelable
return mCachedContrastColor = color;
}
+ int resolveNeutralColor() {
+ if (mNeutralColor != COLOR_INVALID) {
+ return mNeutralColor;
+ }
+ int background = mContext.getColor(
+ com.android.internal.R.color.notification_material_background_color);
+ mNeutralColor = NotificationColorUtil.resolveDefaultColor(mContext, background);
+ if (Color.alpha(mNeutralColor) < 255) {
+ // alpha doesn't go well for color filters, so let's blend it manually
+ mNeutralColor = NotificationColorUtil.compositeColors(mNeutralColor, background);
+ }
+ return mNeutralColor;
+ }
+
int resolveAmbientColor() {
if (mCachedAmbientColorIsFor == mN.color && mCachedAmbientColorIsFor != COLOR_INVALID) {
return mCachedAmbientColor;
@@ -5562,6 +5647,17 @@ public class Notification implements Parcelable
}
/**
+ * Gets a neutral color that can be used for icons or similar that should not stand out.
+ */
+ private int getNeutralColor() {
+ if (isColorized()) {
+ return getSecondaryTextColor();
+ } else {
+ return resolveNeutralColor();
+ }
+ }
+
+ /**
* Same as getBackgroundColor but also resolved the default color to the background.
*/
private int resolveBackgroundColor() {
@@ -5863,6 +5959,18 @@ public class Notification implements Parcelable
}
protected RemoteViews getStandardView(int layoutId) {
+ return getStandardView(layoutId, null);
+ }
+
+ /**
+ * Get the standard view for this style.
+ *
+ * @param layoutId The layout id to use
+ * @param result The result where template bind information is saved.
+ * @return A remoteView for this style.
+ * @hide
+ */
+ protected RemoteViews getStandardView(int layoutId, TemplateBindResult result) {
checkBuilder();
// Nasty.
@@ -5872,7 +5980,7 @@ public class Notification implements Parcelable
mBuilder.setContentTitle(mBigContentTitle);
}
- RemoteViews contentView = mBuilder.applyStandardTemplateWithActions(layoutId);
+ RemoteViews contentView = mBuilder.applyStandardTemplateWithActions(layoutId, result);
mBuilder.getAllExtras().putCharSequence(EXTRA_TITLE, oldBuilderContentTitle);
@@ -6169,7 +6277,8 @@ public class Notification implements Parcelable
mBuilder.mN.largeIcon = null;
}
- RemoteViews contentView = getStandardView(mBuilder.getBigPictureLayoutResource());
+ RemoteViews contentView = getStandardView(mBuilder.getBigPictureLayoutResource(),
+ null /* result */);
if (mSummaryTextSet) {
contentView.setTextViewText(R.id.text, mBuilder.processTextSpans(
mBuilder.processLegacyText(mSummaryText)));
@@ -6356,7 +6465,9 @@ public class Notification implements Parcelable
CharSequence text = mBuilder.getAllExtras().getCharSequence(EXTRA_TEXT);
mBuilder.getAllExtras().putCharSequence(EXTRA_TEXT, null);
- RemoteViews contentView = getStandardView(mBuilder.getBigTextLayoutResource());
+ TemplateBindResult result = new TemplateBindResult();
+ RemoteViews contentView = getStandardView(mBuilder.getBigTextLayoutResource(), result);
+ contentView.setInt(R.id.big_text, "setImageEndMargin", result.getIconMarginEnd());
mBuilder.getAllExtras().putCharSequence(EXTRA_TEXT, text);
@@ -6739,7 +6850,7 @@ public class Notification implements Parcelable
mBuilder.mOriginalActions = mBuilder.mActions;
mBuilder.mActions = new ArrayList<>();
RemoteViews remoteViews = makeMessagingView(true /* displayImagesAtEnd */,
- true /* showReplyIcon */);
+ false /* hideLargeIcon */);
mBuilder.mActions = mBuilder.mOriginalActions;
mBuilder.mOriginalActions = null;
return remoteViews;
@@ -6826,7 +6937,7 @@ public class Notification implements Parcelable
*/
@Override
public RemoteViews makeBigContentView() {
- return makeMessagingView(false /* displayImagesAtEnd */, false /* showReplyIcon */);
+ return makeMessagingView(false /* displayImagesAtEnd */, true /* hideLargeIcon */);
}
/**
@@ -6834,11 +6945,11 @@ public class Notification implements Parcelable
*
* @param displayImagesAtEnd should images be displayed at the end of the content instead
* of inline.
- * @param showReplyIcon Should the reply affordance be shown at the end of the notification
+ * @param hideRightIcons Should the reply affordance be shown at the end of the notification
* @return the created remoteView.
*/
@NonNull
- private RemoteViews makeMessagingView(boolean displayImagesAtEnd, boolean showReplyIcon) {
+ private RemoteViews makeMessagingView(boolean displayImagesAtEnd, boolean hideRightIcons) {
CharSequence conversationTitle = !TextUtils.isEmpty(super.mBigContentTitle)
? super.mBigContentTitle
: mConversationTitle;
@@ -6849,20 +6960,18 @@ public class Notification implements Parcelable
nameReplacement = conversationTitle;
conversationTitle = null;
}
- boolean hideLargeIcon = !showReplyIcon || isOneToOne;
+ TemplateBindResult bindResult = new TemplateBindResult();
RemoteViews contentView = mBuilder.applyStandardTemplateWithActions(
mBuilder.getMessagingLayoutResource(),
mBuilder.mParams.reset().hasProgress(false).title(conversationTitle).text(null)
- .hideLargeIcon(hideLargeIcon)
- .headerTextSecondary(conversationTitle)
- .alwaysShowReply(showReplyIcon));
+ .hideLargeIcon(hideRightIcons || isOneToOne)
+ .hideReplyIcon(hideRightIcons)
+ .headerTextSecondary(conversationTitle),
+ bindResult);
addExtras(mBuilder.mN.extras);
// also update the end margin if there is an image
- int endMargin = R.dimen.notification_content_margin_end;
- if (showReplyIcon) {
- endMargin = R.dimen.notification_content_plus_picture_margin_end;
- }
- contentView.setViewLayoutMarginEndDimen(R.id.notification_main_column, endMargin);
+ contentView.setViewLayoutMarginEnd(R.id.notification_messaging,
+ bindResult.getIconMarginEnd());
contentView.setInt(R.id.status_bar_latest_event_content, "setLayoutColor",
mBuilder.resolveContrastColor());
contentView.setBoolean(R.id.status_bar_latest_event_content, "setDisplayImagesAtEnd",
@@ -6934,7 +7043,7 @@ public class Notification implements Parcelable
@Override
public RemoteViews makeHeadsUpContentView(boolean increasedHeight) {
RemoteViews remoteViews = makeMessagingView(true /* displayImagesAtEnd */,
- false /* showReplyIcon */);
+ true /* hideLargeIcon */);
remoteViews.setInt(R.id.notification_messaging, "setMaxDisplayedLines", 1);
return remoteViews;
}
@@ -6953,11 +7062,16 @@ public class Notification implements Parcelable
static final String KEY_DATA_MIME_TYPE = "type";
static final String KEY_DATA_URI= "uri";
static final String KEY_EXTRAS_BUNDLE = "extras";
+ static final String KEY_REMOTE_INPUT_HISTORY = "remote_input_history";
private final CharSequence mText;
private final long mTimestamp;
@Nullable
private final Person mSender;
+ /** True if this message was generated from the extra
+ * {@link Notification#EXTRA_REMOTE_INPUT_HISTORY}
+ */
+ private final boolean mRemoteInputHistory;
private Bundle mExtras = new Bundle();
private String mDataMimeType;
@@ -6996,9 +7110,33 @@ public class Notification implements Parcelable
* </p>
*/
public Message(@NonNull CharSequence text, long timestamp, @Nullable Person sender) {
+ this(text, timestamp, sender, false /* remoteHistory */);
+ }
+
+ /**
+ * Constructor
+ * @param text A {@link CharSequence} to be displayed as the message content
+ * @param timestamp Time at which the message arrived
+ * @param sender The {@link Person} who sent the message.
+ * Should be <code>null</code> for messages by the current user, in which case
+ * the platform will insert the user set in {@code MessagingStyle(Person)}.
+ * @param remoteInputHistory True if the messages was generated from the extra
+ * {@link Notification#EXTRA_REMOTE_INPUT_HISTORY}.
+ * <p>
+ * The person provided should contain an Icon, set with
+ * {@link Person.Builder#setIcon(Icon)} and also have a name provided
+ * with {@link Person.Builder#setName(CharSequence)}. If multiple users have the same
+ * name, consider providing a key with {@link Person.Builder#setKey(String)} in order
+ * to differentiate between the different users.
+ * </p>
+ * @hide
+ */
+ public Message(@NonNull CharSequence text, long timestamp, @Nullable Person sender,
+ boolean remoteInputHistory) {
mText = text;
mTimestamp = timestamp;
mSender = sender;
+ mRemoteInputHistory = remoteInputHistory;
}
/**
@@ -7088,6 +7226,15 @@ public class Notification implements Parcelable
return mDataUri;
}
+ /**
+ * @return True if the message was generated from
+ * {@link Notification#EXTRA_REMOTE_INPUT_HISTORY}.
+ * @hide
+ */
+ public boolean isRemoteInputHistory() {
+ return mRemoteInputHistory;
+ }
+
private Bundle toBundle() {
Bundle bundle = new Bundle();
if (mText != null) {
@@ -7108,6 +7255,9 @@ public class Notification implements Parcelable
if (mExtras != null) {
bundle.putBundle(KEY_EXTRAS_BUNDLE, mExtras);
}
+ if (mRemoteInputHistory) {
+ bundle.putBoolean(KEY_REMOTE_INPUT_HISTORY, mRemoteInputHistory);
+ }
return bundle;
}
@@ -7159,7 +7309,8 @@ public class Notification implements Parcelable
}
Message message = new Message(bundle.getCharSequence(KEY_TEXT),
bundle.getLong(KEY_TIMESTAMP),
- senderPerson);
+ senderPerson,
+ bundle.getBoolean(KEY_REMOTE_INPUT_HISTORY, false));
if (bundle.containsKey(KEY_DATA_MIME_TYPE) &&
bundle.containsKey(KEY_DATA_URI)) {
message.setData(bundle.getString(KEY_DATA_MIME_TYPE),
@@ -7275,7 +7426,8 @@ public class Notification implements Parcelable
CharSequence oldBuilderContentText = mBuilder.mN.extras.getCharSequence(EXTRA_TEXT);
mBuilder.getAllExtras().putCharSequence(EXTRA_TEXT, null);
- RemoteViews contentView = getStandardView(mBuilder.getInboxLayoutResource());
+ TemplateBindResult result = new TemplateBindResult();
+ RemoteViews contentView = getStandardView(mBuilder.getInboxLayoutResource(), result);
mBuilder.getAllExtras().putCharSequence(EXTRA_TEXT, oldBuilderContentText);
@@ -7304,7 +7456,8 @@ public class Notification implements Parcelable
mBuilder.processTextSpans(mBuilder.processLegacyText(str)));
mBuilder.setTextViewColorSecondary(contentView, rowIds[i]);
contentView.setViewPadding(rowIds[i], 0, topPadding, 0, 0);
- handleInboxImageMargin(contentView, rowIds[i], first);
+ handleInboxImageMargin(contentView, rowIds[i], first,
+ result.getIconMarginEnd());
if (first) {
onlyViewId = rowIds[i];
} else {
@@ -7336,17 +7489,18 @@ public class Notification implements Parcelable
return !Objects.equals(getLines(), newS.getLines());
}
- private void handleInboxImageMargin(RemoteViews contentView, int id, boolean first) {
+ private void handleInboxImageMargin(RemoteViews contentView, int id, boolean first,
+ int marginEndValue) {
int endMargin = 0;
if (first) {
final int max = mBuilder.mN.extras.getInt(EXTRA_PROGRESS_MAX, 0);
final boolean ind = mBuilder.mN.extras.getBoolean(EXTRA_PROGRESS_INDETERMINATE);
boolean hasProgress = max != 0 || ind;
- if (mBuilder.mN.hasLargeIcon() && !hasProgress) {
- endMargin = R.dimen.notification_content_picture_margin;
+ if (!hasProgress) {
+ endMargin = marginEndValue;
}
}
- contentView.setViewLayoutMarginEndDimen(id, endMargin);
+ contentView.setViewLayoutMarginEnd(id, endMargin);
}
}
@@ -7535,7 +7689,8 @@ public class Notification implements Parcelable
private RemoteViews makeMediaContentView() {
RemoteViews view = mBuilder.applyStandardTemplate(
- R.layout.notification_template_material_media, false /* hasProgress */);
+ R.layout.notification_template_material_media, false, /* hasProgress */
+ null /* result */);
final int numActions = mBuilder.mActions.size();
final int N = mActionsToShowInCompact == null
@@ -7559,7 +7714,7 @@ public class Notification implements Parcelable
// handle the content margin
int endMargin = R.dimen.notification_content_margin_end;
if (mBuilder.mN.hasLargeIcon()) {
- endMargin = R.dimen.notification_content_plus_picture_margin_end;
+ endMargin = R.dimen.notification_media_image_margin_end;
}
view.setViewLayoutMarginEndDimen(R.id.notification_main_column, endMargin);
return view;
@@ -7580,8 +7735,7 @@ public class Notification implements Parcelable
return null;
}
RemoteViews big = mBuilder.applyStandardTemplate(
- R.layout.notification_template_material_big_media,
- false);
+ R.layout.notification_template_material_big_media, false, null /* result */);
if (actionCount > 0) {
big.removeAllViews(com.android.internal.R.id.media_actions);
@@ -7677,16 +7831,18 @@ public class Notification implements Parcelable
if (mBuilder.mActions.size() == 0) {
return makeStandardTemplateWithCustomContent(headsUpContentView);
}
+ TemplateBindResult result = new TemplateBindResult();
RemoteViews remoteViews = mBuilder.applyStandardTemplateWithActions(
- mBuilder.getBigBaseLayoutResource());
- buildIntoRemoteViewContent(remoteViews, headsUpContentView);
+ mBuilder.getBigBaseLayoutResource(), result);
+ buildIntoRemoteViewContent(remoteViews, headsUpContentView, result);
return remoteViews;
}
private RemoteViews makeStandardTemplateWithCustomContent(RemoteViews customContent) {
+ TemplateBindResult result = new TemplateBindResult();
RemoteViews remoteViews = mBuilder.applyStandardTemplate(
- mBuilder.getBaseLayoutResource());
- buildIntoRemoteViewContent(remoteViews, customContent);
+ mBuilder.getBaseLayoutResource(), result);
+ buildIntoRemoteViewContent(remoteViews, customContent, result);
return remoteViews;
}
@@ -7697,14 +7853,15 @@ public class Notification implements Parcelable
if (mBuilder.mActions.size() == 0) {
return makeStandardTemplateWithCustomContent(bigContentView);
}
+ TemplateBindResult result = new TemplateBindResult();
RemoteViews remoteViews = mBuilder.applyStandardTemplateWithActions(
- mBuilder.getBigBaseLayoutResource());
- buildIntoRemoteViewContent(remoteViews, bigContentView);
+ mBuilder.getBigBaseLayoutResource(), result);
+ buildIntoRemoteViewContent(remoteViews, bigContentView, result);
return remoteViews;
}
private void buildIntoRemoteViewContent(RemoteViews remoteViews,
- RemoteViews customContent) {
+ RemoteViews customContent, TemplateBindResult result) {
if (customContent != null) {
// Need to clone customContent before adding, because otherwise it can no longer be
// parceled independently of remoteViews.
@@ -7714,11 +7871,10 @@ public class Notification implements Parcelable
remoteViews.setReapplyDisallowed();
}
// also update the end margin if there is an image
- int endMargin = R.dimen.notification_content_margin_end;
- if (mBuilder.mN.hasLargeIcon()) {
- endMargin = R.dimen.notification_content_plus_picture_margin_end;
- }
- remoteViews.setViewLayoutMarginEndDimen(R.id.notification_main_column, endMargin);
+ Resources resources = mBuilder.mContext.getResources();
+ int endMargin = resources.getDimensionPixelSize(
+ R.dimen.notification_content_margin_end) + result.getIconMarginEnd();
+ remoteViews.setViewLayoutMarginEnd(R.id.notification_main_column, endMargin);
}
/**
@@ -9322,6 +9478,25 @@ public class Notification implements Parcelable
}
}
+ /**
+ * A result object where information about the template that was created is saved.
+ */
+ private static class TemplateBindResult {
+ int mIconMarginEnd;
+
+ /**
+ * Get the margin end that needs to be added to any fields that may overlap
+ * with the right actions.
+ */
+ public int getIconMarginEnd() {
+ return mIconMarginEnd;
+ }
+
+ public void setIconMarginEnd(int iconMarginEnd) {
+ this.mIconMarginEnd = iconMarginEnd;
+ }
+ }
+
private static class StandardTemplateParams {
boolean hasProgress = true;
boolean ambient = false;
@@ -9329,7 +9504,7 @@ public class Notification implements Parcelable
CharSequence text;
CharSequence headerTextSecondary;
boolean hideLargeIcon;
- public boolean alwaysShowReply;
+ boolean hideReplyIcon;
final StandardTemplateParams reset() {
hasProgress = true;
@@ -9360,13 +9535,13 @@ public class Notification implements Parcelable
return this;
}
- final StandardTemplateParams alwaysShowReply(boolean alwaysShowReply) {
- this.alwaysShowReply = alwaysShowReply;
+ final StandardTemplateParams hideLargeIcon(boolean hideLargeIcon) {
+ this.hideLargeIcon = hideLargeIcon;
return this;
}
- final StandardTemplateParams hideLargeIcon(boolean hideLargeIcon) {
- this.hideLargeIcon = hideLargeIcon;
+ final StandardTemplateParams hideReplyIcon(boolean hideReplyIcon) {
+ this.hideReplyIcon = hideReplyIcon;
return this;
}
diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java
index 315259bdf388..bdaf80e374df 100644
--- a/core/java/android/app/PendingIntent.java
+++ b/core/java/android/app/PendingIntent.java
@@ -33,8 +33,11 @@ import android.os.Parcelable;
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.AndroidException;
+import android.util.ArraySet;
import android.util.proto.ProtoOutputStream;
+import com.android.internal.os.IResultReceiver;
+
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -93,7 +96,9 @@ import java.lang.annotation.RetentionPolicy;
*/
public final class PendingIntent implements Parcelable {
private final IIntentSender mTarget;
+ private IResultReceiver mCancelReceiver;
private IBinder mWhitelistToken;
+ private ArraySet<CancelListener> mCancelListeners;
/** @hide */
@IntDef(flag = true,
@@ -964,6 +969,74 @@ public final class PendingIntent implements Parcelable {
}
/**
+ * Register a listener to when this pendingIntent is cancelled. There are no guarantees on which
+ * thread a listener will be called and it's up to the caller to synchronize. This may
+ * trigger a synchronous binder call so should therefore usually be called on a background
+ * thread.
+ *
+ * @hide
+ */
+ public void registerCancelListener(CancelListener cancelListener) {
+ synchronized (this) {
+ if (mCancelReceiver == null) {
+ mCancelReceiver = new IResultReceiver.Stub() {
+ @Override
+ public void send(int resultCode, Bundle resultData) throws RemoteException {
+ notifyCancelListeners();
+ }
+ };
+ }
+ if (mCancelListeners == null) {
+ mCancelListeners = new ArraySet<>();
+ }
+ boolean wasEmpty = mCancelListeners.isEmpty();
+ mCancelListeners.add(cancelListener);
+ if (wasEmpty) {
+ try {
+ ActivityManager.getService().registerIntentSenderCancelListener(mTarget,
+ mCancelReceiver);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ }
+ }
+
+ private void notifyCancelListeners() {
+ ArraySet<CancelListener> cancelListeners;
+ synchronized (this) {
+ cancelListeners = new ArraySet<>(mCancelListeners);
+ }
+ int size = cancelListeners.size();
+ for (int i = 0; i < size; i++) {
+ cancelListeners.valueAt(i).onCancelled(this);
+ }
+ }
+
+ /**
+ * Un-register a listener to when this pendingIntent is cancelled.
+ *
+ * @hide
+ */
+ public void unregisterCancelListener(CancelListener cancelListener) {
+ synchronized (this) {
+ if (mCancelListeners == null) {
+ return;
+ }
+ boolean wasEmpty = mCancelListeners.isEmpty();
+ mCancelListeners.remove(cancelListener);
+ if (mCancelListeners.isEmpty() && !wasEmpty) {
+ try {
+ ActivityManager.getService().unregisterIntentSenderCancelListener(mTarget,
+ mCancelReceiver);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ }
+ }
+
+ /**
* Return the user handle of the application that created this
* PendingIntent, that is the user under which you will actually be
* sending the Intent. The returned UserHandle is supplied by the system, so
@@ -1184,4 +1257,18 @@ public final class PendingIntent implements Parcelable {
public IBinder getWhitelistToken() {
return mWhitelistToken;
}
+
+ /**
+ * A listener to when a pending intent is cancelled
+ *
+ * @hide
+ */
+ public interface CancelListener {
+ /**
+ * Called when a Pending Intent is cancelled.
+ *
+ * @param intent The intent that was cancelled.
+ */
+ void onCancelled(PendingIntent intent);
+ }
}
diff --git a/core/java/android/app/admin/SystemUpdatePolicy.java b/core/java/android/app/admin/SystemUpdatePolicy.java
index 20eef6cc01d8..2a451ff07672 100644
--- a/core/java/android/app/admin/SystemUpdatePolicy.java
+++ b/core/java/android/app/admin/SystemUpdatePolicy.java
@@ -48,7 +48,37 @@ import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
- * A class that represents a local system update policy set by the device owner.
+ * Determines when over-the-air system updates are installed on a device. Only a device policy
+ * controller (DPC) running in device owner mode can set an update policy for the device—by calling
+ * the {@code DevicePolicyManager} method
+ * {@link DevicePolicyManager#setSystemUpdatePolicy setSystemUpdatePolicy()}. An update
+ * policy affects the pending system update (if there is one) and any future updates for the device.
+ *
+ * <p>If a policy is set on a device, the system doesn't notify the user about updates.</p>
+ * <h3>Example</h3>
+ *
+ * <p>The example below shows how a DPC might set a maintenance window for system updates:</p>
+ * <pre><code>
+ * private final MAINTENANCE_WINDOW_START = 1380; // 11pm
+ * private final MAINTENANCE_WINDOW_END = 120; // 2am
+ *
+ * // ...
+ *
+ * // Create the system update policy
+ * SystemUpdatePolicy policy = SystemUpdatePolicy.createWindowedInstallPolicy(
+ * MAINTENANCE_WINDOW_START, MAINTENANCE_WINDOW_END);
+ *
+ * // Get a DevicePolicyManager instance to set the policy on the device
+ * DevicePolicyManager dpm =
+ * (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
+ * ComponentName adminComponent = getComponentName(context);
+ * dpm.setSystemUpdatePolicy(adminComponent, policy);
+ * </code></pre>
+ *
+ * <h3>Developer guide</h3>
+ * To learn more about managing system updates, read
+ * <a href="{@docRoot}/work/dpc/security.html#control_remote_software_updates">Control remote
+ * software updates</a>.
*
* @see DevicePolicyManager#setSystemUpdatePolicy
* @see DevicePolicyManager#getSystemUpdatePolicy
@@ -71,44 +101,37 @@ public final class SystemUpdatePolicy implements Parcelable {
private static final int TYPE_UNKNOWN = -1;
/**
- * Install system update automatically as soon as one is available.
+ * Installs system updates (without user interaction) as soon as they become available. Setting
+ * this policy type immediately installs any pending updates that might be postponed or waiting
+ * for a maintenance window.
*/
public static final int TYPE_INSTALL_AUTOMATIC = 1;
/**
- * Install system update automatically within a daily maintenance window. An update can be
- * delayed for a maximum of 30 days, after which the policy will no longer be effective and the
- * system will revert back to its normal behavior as if no policy were set.
- *
- * <p>After this policy expires, resetting it to any policy other than
- * {@link #TYPE_INSTALL_AUTOMATIC} will produce no effect, as the 30-day maximum delay has
- * already been used up.
- * The {@link #TYPE_INSTALL_AUTOMATIC} policy will still take effect to install the delayed
- * system update immediately.
+ * Installs system updates (without user interaction) during a daily maintenance window. Set the
+ * start and end of the daily maintenance window, as minutes of the day, when creating a new
+ * {@code TYPE_INSTALL_WINDOWED} policy. See
+ * {@link #createWindowedInstallPolicy createWindowedInstallPolicy()}.
*
- * <p>Re-applying this policy or changing it to {@link #TYPE_POSTPONE} within the 30-day period
- * will <i>not</i> extend policy expiration.
- * However, the expiration will be recalculated when a new system update is made available.
+ * <p>No connectivity, not enough disk space, or a low battery are typical reasons Android might
+ * not install a system update in the daily maintenance window. After 30 days trying to install
+ * an update in the maintenance window (regardless of policy changes in this period), the system
+ * prompts the device user to install the update.
*/
public static final int TYPE_INSTALL_WINDOWED = 2;
/**
- * Incoming system updates (except for security updates) will be blocked for a maximum of 30
- * days, after which the policy will no longer be effective and the system will revert back to
- * its normal behavior as if no policy were set.
+ * Postpones the installation of system updates for 30 days. After the 30-day period has ended,
+ * the system prompts the device user to install the update.
*
- * <p><b>Note:</b> security updates (e.g. monthly security patches) may <i>not</i> be affected
- * by this policy, depending on the policy set by the device manufacturer and carrier.
+ * <p>The system limits each update to one 30-day postponement. The period begins when the
+ * system first postpones the update and setting new {@code TYPE_POSTPONE} policies won’t extend
+ * the period. If, after 30 days the update isn’t installed (through policy changes), the system
+ * prompts the user to install the update.
*
- * <p>After this policy expires, resetting it to any policy other than
- * {@link #TYPE_INSTALL_AUTOMATIC} will produce no effect, as the 30-day maximum delay has
- * already been used up.
- * The {@link #TYPE_INSTALL_AUTOMATIC} policy will still take effect to install the delayed
- * system update immediately.
- *
- * <p>Re-applying this policy or changing it to {@link #TYPE_INSTALL_WINDOWED} within the 30-day
- * period will <i>not</i> extend policy expiration.
- * However, the expiration will be recalculated when a new system update is made available.
+ * <p><strong>Note</strong>: Device manufacturers or carriers might choose to exempt important
+ * security updates from a postponement policy. Exempted updates notify the device user when
+ * they become available.
*/
public static final int TYPE_POSTPONE = 3;
@@ -303,16 +326,20 @@ public final class SystemUpdatePolicy implements Parcelable {
* Create a policy object and set it to: new system update will only be installed automatically
* when the system clock is inside a daily maintenance window. If the start and end times are
* the same, the window is considered to include the <i>whole 24 hours</i>. That is, updates can
- * install at any time. If the given window in invalid, an {@link IllegalArgumentException}
- * will be thrown. If start time is later than end time, the window is considered spanning
+ * install at any time. If start time is later than end time, the window is considered spanning
* midnight (i.e. the end time denotes a time on the next day). The maintenance window will last
- * for 30 days, after which the system will revert back to its normal behavior as if no policy
- * were set.
+ * for 30 days for any given update, after which the window will no longer be effective and
+ * the pending update will be made available for manual installation as if no system update
+ * policy were set on the device. See {@link #TYPE_INSTALL_WINDOWED} for the details of this
+ * policy's behavior.
*
* @param startTime the start of the maintenance window, measured as the number of minutes from
* midnight in the device's local time. Must be in the range of [0, 1440).
* @param endTime the end of the maintenance window, measured as the number of minutes from
* midnight in the device's local time. Must be in the range of [0, 1440).
+ * @throws IllegalArgumentException If the {@code startTime} or {@code endTime} isn't in the
+ * accepted range.
+ * @return The configured policy.
* @see #TYPE_INSTALL_WINDOWED
*/
public static SystemUpdatePolicy createWindowedInstallPolicy(int startTime, int endTime) {
@@ -329,8 +356,7 @@ public final class SystemUpdatePolicy implements Parcelable {
/**
* Create a policy object and set it to block installation for a maximum period of 30 days.
- * After expiration the system will revert back to its normal behavior as if no policy were
- * set.
+ * To learn more about this policy's behavior, see {@link #TYPE_POSTPONE}.
*
* <p><b>Note: </b> security updates (e.g. monthly security patches) will <i>not</i> be affected
* by this policy.
@@ -344,10 +370,9 @@ public final class SystemUpdatePolicy implements Parcelable {
}
/**
- * Returns the type of system update policy.
+ * Returns the type of system update policy, or -1 if no policy has been set.
*
- * @return an integer, either one of {@link #TYPE_INSTALL_AUTOMATIC},
- * {@link #TYPE_INSTALL_WINDOWED} and {@link #TYPE_POSTPONE}, or -1 if no policy has been set.
+ @return The policy type or -1 if the type isn't set.
*/
@SystemUpdatePolicyType
public int getPolicyType() {
@@ -423,24 +448,16 @@ public final class SystemUpdatePolicy implements Parcelable {
* be blocked and cannot be installed. When the device is outside the freeze periods, the normal
* policy behavior will apply.
* <p>
- * Each freeze period is defined by a starting and finishing date (both inclusive). Since the
- * freeze period repeats annually, both of these dates are simply represented by integers
- * counting the number of days since year start, similar to {@link LocalDate#getDayOfYear()}. We
- * do not consider leap year when handling freeze period so the valid range of the integer is
- * always [1,365] (see last section for more details on leap year). If the finishing date is
- * smaller than the starting date, the freeze period is considered to be spanning across
- * year-end.
- * <p>
* Each individual freeze period is allowed to be at most 90 days long, and adjacent freeze
* periods need to be at least 60 days apart. Also, the list of freeze periods should not
* contain duplicates or overlap with each other. If any of these conditions is not met, a
* {@link ValidationFailedException} will be thrown.
* <p>
- * Handling of leap year: we do not consider leap year when handling freeze period, in
- * particular,
+ * Handling of leap year: we ignore leap years in freeze period calculations, in particular,
* <ul>
- * <li>When a freeze period is defined by the day of year, February 29th does not count as one
- * day, so day 59 is February 28th while day 60 is March 1st.</li>
+ * <li>When a freeze period is defined, February 29th is disregarded so even though a freeze
+ * period can be specified to start or end on February 29th, it will be treated as if the period
+ * started or ended on February 28th.</li>
* <li>When applying freeze period behavior to the device, a system clock of February 29th is
* treated as if it were February 28th</li>
* <li>When calculating the number of days of a freeze period or separation between two freeze
diff --git a/core/java/android/app/backup/BackupManager.java b/core/java/android/app/backup/BackupManager.java
index debc32bd83eb..30f340c50e32 100644
--- a/core/java/android/app/backup/BackupManager.java
+++ b/core/java/android/app/backup/BackupManager.java
@@ -387,7 +387,7 @@ public class BackupManager {
@SystemApi
@RequiresPermission(android.Manifest.permission.BACKUP)
public boolean isBackupServiceActive(UserHandle user) {
- mContext.enforceCallingPermission(android.Manifest.permission.BACKUP,
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP,
"isBackupServiceActive");
checkServiceBinder();
if (sService != null) {
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index c5fc06751e0e..6b6e14fb7173 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -10775,6 +10775,7 @@ public final class Settings {
* track_cpu_active_cluster_time (boolean)
* read_binary_cpu_time (boolean)
* proc_state_cpu_times_read_delay_ms (long)
+ * external_stats_collection_rate_limit_ms (long)
* </pre>
*
* <p>
diff --git a/core/java/android/text/AndroidBidi.java b/core/java/android/text/AndroidBidi.java
index 179d545f8ccd..72383cf377e9 100644
--- a/core/java/android/text/AndroidBidi.java
+++ b/core/java/android/text/AndroidBidi.java
@@ -32,8 +32,12 @@ import com.android.internal.annotations.VisibleForTesting;
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
public class AndroidBidi {
- private static class EmojiBidiOverride extends BidiClassifier {
- EmojiBidiOverride() {
+ /**
+ * Overrides ICU {@link BidiClassifier} in order to correctly handle character directions for
+ * newest emoji that ICU is not aware of.
+ */
+ public static class EmojiBidiOverride extends BidiClassifier {
+ public EmojiBidiOverride() {
super(null /* No persisting object needed */);
}
diff --git a/core/java/android/text/BidiFormatter.java b/core/java/android/text/BidiFormatter.java
index f65f39762b75..77f17a7d2377 100644
--- a/core/java/android/text/BidiFormatter.java
+++ b/core/java/android/text/BidiFormatter.java
@@ -21,6 +21,8 @@ import static android.text.TextDirectionHeuristics.FIRSTSTRONG_LTR;
import android.annotation.Nullable;
import android.view.View;
+import com.android.internal.annotations.VisibleForTesting;
+
import java.util.Locale;
/**
@@ -570,8 +572,10 @@ public final class BidiFormatter {
/**
* An object that estimates the directionality of a given string by various methods.
*
+ * @hide
*/
- private static class DirectionalityEstimator {
+ @VisibleForTesting
+ public static class DirectionalityEstimator {
// Internal static variables and constants.
@@ -598,7 +602,11 @@ public final class BidiFormatter {
}
}
- private static byte getDirectionality(int codePoint) {
+ /**
+ * Return Character directionality. Same as {@link Character#getDirectionality(int)} except
+ * it overrides values for newest emoji that are not covered by ICU.
+ */
+ public static byte getDirectionality(int codePoint) {
if (Emoji.isNewEmoji(codePoint)) {
// TODO: Fix or remove once emoji-data.text 5.0 is in ICU or update to 6.0.
return Character.DIRECTIONALITY_OTHER_NEUTRALS;
diff --git a/core/java/android/text/Emoji.java b/core/java/android/text/Emoji.java
index d33aad99e1a5..876c64eebf84 100644
--- a/core/java/android/text/Emoji.java
+++ b/core/java/android/text/Emoji.java
@@ -46,44 +46,49 @@ public class Emoji {
return UCharacter.hasBinaryProperty(codePoint, UProperty.EMOJI_MODIFIER);
}
- // Returns true if the given code point is emoji modifier base.
- public static boolean isEmojiModifierBase(int codePoint) {
+ //
+
+ /**
+ * Returns true if the given code point is emoji modifier base.
+ * @param c codepoint to check
+ * @return true if is emoji modifier base
+ */
+ public static boolean isEmojiModifierBase(int c) {
// These two characters were removed from Emoji_Modifier_Base in Emoji 4.0, but we need to
// keep them as emoji modifier bases since there are fonts and user-generated text out there
// that treats these as potential emoji bases.
- if (codePoint == 0x1F91D || codePoint == 0x1F93C) {
+ if (c == 0x1F91D || c == 0x1F93C) {
return true;
}
- // Emoji Modifier Base characters new in Unicode emoji 5.0.
- // From http://www.unicode.org/Public/emoji/5.0/emoji-data.txt
- // TODO: Remove once emoji-data.text 5.0 is in ICU or update to 6.0.
- if (codePoint == 0x1F91F
- || (0x1F931 <= codePoint && codePoint <= 0x1F932)
- || (0x1F9D1 <= codePoint && codePoint <= 0x1F9DD)) {
+ // Emoji Modifier Base characters new in Unicode emoji 11
+ // From https://www.unicode.org/Public/emoji/11.0/emoji-data.txt
+ // TODO: Remove once emoji-data.text 11 is in ICU or update to 11.
+ if ((0x1F9B5 <= c && c <= 0x1F9B6) || (0x1F9B8 <= c && c <= 0x1F9B9)) {
return true;
}
- return UCharacter.hasBinaryProperty(codePoint, UProperty.EMOJI_MODIFIER_BASE);
+ return UCharacter.hasBinaryProperty(c, UProperty.EMOJI_MODIFIER_BASE);
}
/**
* Returns true if the character is a new emoji still not supported in our version of ICU.
*/
- public static boolean isNewEmoji(int codePoint) {
- // Emoji characters new in Unicode emoji 5.0.
- // From http://www.unicode.org/Public/emoji/5.0/emoji-data.txt
- // TODO: Remove once emoji-data.text 5.0 is in ICU or update to 6.0.
- if (codePoint < 0x1F6F7 || codePoint > 0x1F9E6) {
+ public static boolean isNewEmoji(int c) {
+ // Emoji characters new in Unicode emoji 11
+ // From https://www.unicode.org/Public/emoji/11.0/emoji-data.txt
+ // TODO: Remove once emoji-data.text 11 is in ICU or update to 11.
+ if (c < 0x1F6F9 || c > 0x1F9FF) {
// Optimization for characters outside the new emoji range.
return false;
}
- return (0x1F6F7 <= codePoint && codePoint <= 0x1F6F8)
- || codePoint == 0x1F91F
- || (0x1F928 <= codePoint && codePoint <= 0x1F92F)
- || (0x1F931 <= codePoint && codePoint <= 0x1F932)
- || codePoint == 0x1F94C
- || (0x1F95F <= codePoint && codePoint <= 0x1F96B)
- || (0x1F992 <= codePoint && codePoint <= 0x1F997)
- || (0x1F9D0 <= codePoint && codePoint <= 0x1F9E6);
+ return c == 0x265F || c == 0x267E || c == 0x1F6F9 || c == 0x1F97A
+ || (0x1F94D <= c && c <= 0x1F94F)
+ || (0x1F96C <= c && c <= 0x1F970)
+ || (0x1F973 <= c && c <= 0x1F976)
+ || (0x1F97C <= c && c <= 0x1F97F)
+ || (0x1F998 <= c && c <= 0x1F9A2)
+ || (0x1F9B0 <= c && c <= 0x1F9B9)
+ || (0x1F9C1 <= c && c <= 0x1F9C2)
+ || (0x1F9E7 <= c && c <= 0x1F9FF);
}
/**
diff --git a/core/java/android/util/apk/ApkSigningBlockUtils.java b/core/java/android/util/apk/ApkSigningBlockUtils.java
index 1c67434b2609..e247c87fdb4c 100644
--- a/core/java/android/util/apk/ApkSigningBlockUtils.java
+++ b/core/java/android/util/apk/ApkSigningBlockUtils.java
@@ -92,6 +92,8 @@ final class ApkSigningBlockUtils {
throw new SecurityException("No digests provided");
}
+ boolean neverVerified = true;
+
Map<Integer, byte[]> expected1MbChunkDigests = new ArrayMap<>();
if (expectedDigests.containsKey(CONTENT_DIGEST_CHUNKED_SHA256)) {
expected1MbChunkDigests.put(CONTENT_DIGEST_CHUNKED_SHA256,
@@ -101,18 +103,23 @@ final class ApkSigningBlockUtils {
expected1MbChunkDigests.put(CONTENT_DIGEST_CHUNKED_SHA512,
expectedDigests.get(CONTENT_DIGEST_CHUNKED_SHA512));
}
-
- if (expectedDigests.containsKey(CONTENT_DIGEST_VERITY_CHUNKED_SHA256)) {
- verifyIntegrityForVerityBasedAlgorithm(
- expectedDigests.get(CONTENT_DIGEST_VERITY_CHUNKED_SHA256), apk, signatureInfo);
- } else if (!expected1MbChunkDigests.isEmpty()) {
+ if (!expected1MbChunkDigests.isEmpty()) {
try {
verifyIntegrityFor1MbChunkBasedAlgorithm(expected1MbChunkDigests, apk.getFD(),
signatureInfo);
+ neverVerified = false;
} catch (IOException e) {
throw new SecurityException("Cannot get FD", e);
}
- } else {
+ }
+
+ if (expectedDigests.containsKey(CONTENT_DIGEST_VERITY_CHUNKED_SHA256)) {
+ verifyIntegrityForVerityBasedAlgorithm(
+ expectedDigests.get(CONTENT_DIGEST_VERITY_CHUNKED_SHA256), apk, signatureInfo);
+ neverVerified = false;
+ }
+
+ if (neverVerified) {
throw new SecurityException("No known digest exists for integrity check");
}
}
diff --git a/core/java/android/view/IRecentsAnimationController.aidl b/core/java/android/view/IRecentsAnimationController.aidl
index c0b40c8ceb3b..94b9bc099d56 100644
--- a/core/java/android/view/IRecentsAnimationController.aidl
+++ b/core/java/android/view/IRecentsAnimationController.aidl
@@ -64,4 +64,9 @@ interface IRecentsAnimationController {
* Informs the system that the primary split-screen stack should be minimized.
*/
void setSplitScreenMinimized(boolean minimized);
+
+ /**
+ * Hides the current input method if one is showing.
+ */
+ void hideCurrentInputMethod();
}
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 8395681f0139..131fe1395585 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -128,7 +128,10 @@ interface IWindowManager
void overridePendingAppTransitionRemote(in RemoteAnimationAdapter remoteAnimationAdapter);
void executeAppTransition();
- /** Used by system ui to report that recents has shown itself. */
+ /**
+ * Used by system ui to report that recents has shown itself.
+ * @deprecated to be removed once prebuilts are updated
+ */
void endProlongedAnimations();
// Re-evaluate the current orientation from the caller's state.
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 19ead600e2dc..4bd6fc8b665f 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -3272,7 +3272,8 @@ public final class ViewRootImpl implements ViewParent,
// eglTerminate() for instance.
if (mAttachInfo.mThreadedRenderer != null &&
!mAttachInfo.mThreadedRenderer.isEnabled() &&
- mAttachInfo.mThreadedRenderer.isRequested()) {
+ mAttachInfo.mThreadedRenderer.isRequested() &&
+ mSurface.isValid()) {
try {
mAttachInfo.mThreadedRenderer.initializeIfNeeded(
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index b6bd14ed5efd..5ecbf90a4eca 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -946,6 +946,7 @@ public class RemoteViews implements Parcelable, Filter {
}
};
}
+ target.setTagInternal(R.id.pending_intent_tag, pendingIntent);
target.setOnClickListener(listener);
}
@@ -1999,6 +2000,7 @@ public class RemoteViews implements Parcelable, Filter {
/** Set width */
public static final int LAYOUT_WIDTH = 2;
public static final int LAYOUT_MARGIN_BOTTOM_DIMEN = 3;
+ public static final int LAYOUT_MARGIN_END = 4;
final int mProperty;
final int mValue;
@@ -2036,11 +2038,14 @@ public class RemoteViews implements Parcelable, Filter {
if (layoutParams == null) {
return;
}
+ int value = mValue;
switch (mProperty) {
case LAYOUT_MARGIN_END_DIMEN:
+ value = resolveDimenPixelOffset(target, mValue);
+ // fall-through
+ case LAYOUT_MARGIN_END:
if (layoutParams instanceof ViewGroup.MarginLayoutParams) {
- int resolved = resolveDimenPixelOffset(target, mValue);
- ((ViewGroup.MarginLayoutParams) layoutParams).setMarginEnd(resolved);
+ ((ViewGroup.MarginLayoutParams) layoutParams).setMarginEnd(value);
target.setLayoutParams(layoutParams);
}
break;
@@ -2980,6 +2985,20 @@ public class RemoteViews implements Parcelable, Filter {
}
/**
+ * Equivalent to calling {@link android.view.ViewGroup.MarginLayoutParams#setMarginEnd(int)}.
+ * Only works if the {@link View#getLayoutParams()} supports margins.
+ * Hidden for now since we don't want to support this for all different layout margins yet.
+ *
+ * @param viewId The id of the view to change
+ * @param endMargin a value in pixels for the end margin.
+ * @hide
+ */
+ public void setViewLayoutMarginEnd(int viewId, @DimenRes int endMargin) {
+ addAction(new LayoutParamAction(viewId, LayoutParamAction.LAYOUT_MARGIN_END,
+ endMargin));
+ }
+
+ /**
* Equivalent to setting {@link android.view.ViewGroup.MarginLayoutParams#bottomMargin}.
*
* @param bottomMarginDimen a dimen resource to read the margin from or 0 to clear the margin.
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 5da3874dbcec..a4680cab4b56 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -196,6 +196,7 @@ public class BatteryStatsImpl extends BatteryStats {
static final int MSG_REPORT_CPU_UPDATE_NEEDED = 1;
static final int MSG_REPORT_POWER_CHANGE = 2;
static final int MSG_REPORT_CHARGING = 3;
+ static final int MSG_REPORT_RESET_STATS = 4;
static final long DELAY_UPDATE_WAKELOCKS = 5*1000;
private final KernelWakelockReader mKernelWakelockReader = new KernelWakelockReader();
@@ -319,6 +320,7 @@ public class BatteryStatsImpl extends BatteryStats {
public void batteryNeedsCpuUpdate();
public void batteryPowerChanged(boolean onBattery);
public void batterySendBroadcast(Intent intent);
+ public void batteryStatsReset();
}
public interface PlatformIdleStateCallback {
@@ -373,7 +375,11 @@ public class BatteryStatsImpl extends BatteryStats {
cb.batterySendBroadcast(intent);
}
break;
- }
+ case MSG_REPORT_RESET_STATS:
+ if (cb != null) {
+ cb.batteryStatsReset();
+ }
+ }
}
}
@@ -10939,6 +10945,7 @@ public class BatteryStatsImpl extends BatteryStats {
initDischarge();
clearHistoryLocked();
+ mHandler.sendEmptyMessage(MSG_REPORT_RESET_STATS);
}
private void initActiveHistoryEventsLocked(long elapsedRealtimeMs, long uptimeMs) {
@@ -13261,18 +13268,23 @@ public class BatteryStatsImpl extends BatteryStats {
= "kernel_uid_readers_throttle_time";
public static final String KEY_UID_REMOVE_DELAY_MS
= "uid_remove_delay_ms";
+ public static final String KEY_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS
+ = "external_stats_collection_rate_limit_ms";
private static final boolean DEFAULT_TRACK_CPU_TIMES_BY_PROC_STATE = true;
private static final boolean DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME = true;
private static final long DEFAULT_PROC_STATE_CPU_TIMES_READ_DELAY_MS = 5_000;
private static final long DEFAULT_KERNEL_UID_READERS_THROTTLE_TIME = 10_000;
private static final long DEFAULT_UID_REMOVE_DELAY_MS = 5L * 60L * 1000L;
+ private static final long DEFAULT_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS = 600_000;
public boolean TRACK_CPU_TIMES_BY_PROC_STATE = DEFAULT_TRACK_CPU_TIMES_BY_PROC_STATE;
public boolean TRACK_CPU_ACTIVE_CLUSTER_TIME = DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME;
public long PROC_STATE_CPU_TIMES_READ_DELAY_MS = DEFAULT_PROC_STATE_CPU_TIMES_READ_DELAY_MS;
public long KERNEL_UID_READERS_THROTTLE_TIME = DEFAULT_KERNEL_UID_READERS_THROTTLE_TIME;
public long UID_REMOVE_DELAY_MS = DEFAULT_UID_REMOVE_DELAY_MS;
+ public long EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS
+ = DEFAULT_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS;
private ContentResolver mResolver;
private final KeyValueListParser mParser = new KeyValueListParser(',');
@@ -13318,6 +13330,9 @@ public class BatteryStatsImpl extends BatteryStats {
DEFAULT_KERNEL_UID_READERS_THROTTLE_TIME));
updateUidRemoveDelay(
mParser.getLong(KEY_UID_REMOVE_DELAY_MS, DEFAULT_UID_REMOVE_DELAY_MS));
+ EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS = mParser.getLong(
+ KEY_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS,
+ DEFAULT_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS);
}
}
@@ -13367,6 +13382,14 @@ public class BatteryStatsImpl extends BatteryStats {
pw.println(PROC_STATE_CPU_TIMES_READ_DELAY_MS);
pw.print(KEY_KERNEL_UID_READERS_THROTTLE_TIME); pw.print("=");
pw.println(KERNEL_UID_READERS_THROTTLE_TIME);
+ pw.print(KEY_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS); pw.print("=");
+ pw.println(EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS);
+ }
+ }
+
+ public long getExternalStatsCollectionRateLimitMs() {
+ synchronized (this) {
+ return mConstants.EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS;
}
}
diff --git a/core/java/com/android/internal/os/BinderCallsStats.java b/core/java/com/android/internal/os/BinderCallsStats.java
index 2c48506494bc..3315cb15d4b4 100644
--- a/core/java/com/android/internal/os/BinderCallsStats.java
+++ b/core/java/com/android/internal/os/BinderCallsStats.java
@@ -18,9 +18,11 @@ package com.android.internal.os;
import android.os.Binder;
import android.os.SystemClock;
+import android.text.format.DateFormat;
import android.util.ArrayMap;
import android.util.SparseArray;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.Preconditions;
@@ -40,23 +42,22 @@ public class BinderCallsStats {
private static final int CALL_SESSIONS_POOL_SIZE = 100;
private static final BinderCallsStats sInstance = new BinderCallsStats();
- private volatile boolean mTrackingEnabled = false;
+ private volatile boolean mDetailedTracking = false;
+ @GuardedBy("mLock")
private final SparseArray<UidEntry> mUidEntries = new SparseArray<>();
private final Queue<CallSession> mCallSessionsPool = new ConcurrentLinkedQueue<>();
+ private final Object mLock = new Object();
+ private long mStartTime = System.currentTimeMillis();
private BinderCallsStats() {
}
@VisibleForTesting
- public BinderCallsStats(boolean trackingEnabled) {
- mTrackingEnabled = trackingEnabled;
+ public BinderCallsStats(boolean detailedTracking) {
+ mDetailedTracking = detailedTracking;
}
public CallSession callStarted(Binder binder, int code) {
- if (!mTrackingEnabled) {
- return null;
- }
-
return callStarted(binder.getClass().getName(), code);
}
@@ -73,32 +74,31 @@ public class BinderCallsStats {
}
public void callEnded(CallSession s) {
- if (!mTrackingEnabled) {
- return;
- }
Preconditions.checkNotNull(s);
- final long cpuTimeNow = getThreadTimeMicro();
- final long duration = cpuTimeNow - s.mStarted;
+ long duration = mDetailedTracking ? getThreadTimeMicro() - s.mStarted : 1;
s.mCallingUId = Binder.getCallingUid();
- synchronized (mUidEntries) {
+ synchronized (mLock) {
UidEntry uidEntry = mUidEntries.get(s.mCallingUId);
if (uidEntry == null) {
uidEntry = new UidEntry(s.mCallingUId);
mUidEntries.put(s.mCallingUId, uidEntry);
}
- // Find CallDesc entry and update its total time
- CallStat callStat = uidEntry.mCallStats.get(s.mCallStat);
- // Only create CallStat if it's a new entry, otherwise update existing instance
- if (callStat == null) {
- callStat = new CallStat(s.mCallStat.className, s.mCallStat.msg);
- uidEntry.mCallStats.put(callStat, callStat);
+ if (mDetailedTracking) {
+ // Find CallDesc entry and update its total time
+ CallStat callStat = uidEntry.mCallStats.get(s.mCallStat);
+ // Only create CallStat if it's a new entry, otherwise update existing instance
+ if (callStat == null) {
+ callStat = new CallStat(s.mCallStat.className, s.mCallStat.msg);
+ uidEntry.mCallStats.put(callStat, callStat);
+ }
+ callStat.callCount++;
+ callStat.time += duration;
}
+
uidEntry.time += duration;
uidEntry.callCount++;
- callStat.callCount++;
- callStat.time += duration;
}
if (mCallSessionsPool.size() < CALL_SESSIONS_POOL_SIZE) {
mCallSessionsPool.add(s);
@@ -110,9 +110,11 @@ public class BinderCallsStats {
Map<Integer, Long> uidCallCountMap = new HashMap<>();
long totalCallsCount = 0;
long totalCallsTime = 0;
+ pw.print("Start time: ");
+ pw.println(DateFormat.format("yyyy-MM-dd HH:mm:ss", mStartTime));
int uidEntriesSize = mUidEntries.size();
List<UidEntry> entries = new ArrayList<>();
- synchronized (mUidEntries) {
+ synchronized (mLock) {
for (int i = 0; i < uidEntriesSize; i++) {
UidEntry e = mUidEntries.valueAt(i);
entries.add(e);
@@ -127,20 +129,9 @@ public class BinderCallsStats {
totalCallsCount += e.callCount;
}
}
- pw.println("Binder call stats:");
- pw.println(" Raw data (uid,call_desc,time):");
- entries.sort((o1, o2) -> {
- if (o1.time < o2.time) {
- return 1;
- } else if (o1.time > o2.time) {
- return -1;
- }
- return 0;
- });
- StringBuilder sb = new StringBuilder();
- for (UidEntry uidEntry : entries) {
- List<CallStat> callStats = new ArrayList<>(uidEntry.mCallStats.keySet());
- callStats.sort((o1, o2) -> {
+ if (mDetailedTracking) {
+ pw.println("Raw data (uid,call_desc,time):");
+ entries.sort((o1, o2) -> {
if (o1.time < o2.time) {
return 1;
} else if (o1.time > o2.time) {
@@ -148,44 +139,73 @@ public class BinderCallsStats {
}
return 0;
});
- for (CallStat e : callStats) {
- sb.setLength(0);
- sb.append(" ")
- .append(uidEntry.uid).append(",").append(e).append(',').append(e.time);
- pw.println(sb);
+ StringBuilder sb = new StringBuilder();
+ for (UidEntry uidEntry : entries) {
+ List<CallStat> callStats = new ArrayList<>(uidEntry.mCallStats.keySet());
+ callStats.sort((o1, o2) -> {
+ if (o1.time < o2.time) {
+ return 1;
+ } else if (o1.time > o2.time) {
+ return -1;
+ }
+ return 0;
+ });
+ for (CallStat e : callStats) {
+ sb.setLength(0);
+ sb.append(" ")
+ .append(uidEntry.uid).append(",").append(e).append(',').append(e.time);
+ pw.println(sb);
+ }
+ }
+ pw.println();
+ pw.println("Per UID Summary(UID: time, % of total_time, calls_count):");
+ List<Map.Entry<Integer, Long>> uidTotals = new ArrayList<>(uidTimeMap.entrySet());
+ uidTotals.sort((o1, o2) -> o2.getValue().compareTo(o1.getValue()));
+ for (Map.Entry<Integer, Long> uidTotal : uidTotals) {
+ Long callCount = uidCallCountMap.get(uidTotal.getKey());
+ pw.println(String.format(" %7d: %11d %3.0f%% %8d",
+ uidTotal.getKey(), uidTotal.getValue(),
+ 100d * uidTotal.getValue() / totalCallsTime, callCount));
+ }
+ pw.println();
+ pw.println(String.format(" Summary: total_time=%d, "
+ + "calls_count=%d, avg_call_time=%.0f",
+ totalCallsTime, totalCallsCount,
+ (double)totalCallsTime / totalCallsCount));
+ } else {
+ pw.println("Per UID Summary(UID: calls_count, % of total calls_count):");
+ List<Map.Entry<Integer, Long>> uidTotals = new ArrayList<>(uidTimeMap.entrySet());
+ uidTotals.sort((o1, o2) -> o2.getValue().compareTo(o1.getValue()));
+ for (Map.Entry<Integer, Long> uidTotal : uidTotals) {
+ Long callCount = uidCallCountMap.get(uidTotal.getKey());
+ pw.println(String.format(" %7d: %8d %3.0f%%",
+ uidTotal.getKey(), callCount, 100d * uidTotal.getValue() / totalCallsTime));
}
}
- pw.println();
- pw.println(" Per UID Summary(UID: time, total_time_percentage, calls_count):");
- List<Map.Entry<Integer, Long>> uidTotals = new ArrayList<>(uidTimeMap.entrySet());
- uidTotals.sort((o1, o2) -> o2.getValue().compareTo(o1.getValue()));
- for (Map.Entry<Integer, Long> uidTotal : uidTotals) {
- Long callCount = uidCallCountMap.get(uidTotal.getKey());
- pw.println(String.format(" %5d: %11d %3.0f%% %8d",
- uidTotal.getKey(), uidTotal.getValue(),
- 100d * uidTotal.getValue() / totalCallsTime, callCount));
- }
- pw.println();
- pw.println(String.format(" Summary: total_time=%d, "
- + "calls_count=%d, avg_call_time=%.0f",
- totalCallsTime, totalCallsCount,
- (double)totalCallsTime / totalCallsCount));
}
- private static long getThreadTimeMicro() {
- return SystemClock.currentThreadTimeMicro();
+ private long getThreadTimeMicro() {
+ // currentThreadTimeMicro is expensive, so we measure cpu time only if detailed tracking is
+ // enabled
+ return mDetailedTracking ? SystemClock.currentThreadTimeMicro() : 0;
}
public static BinderCallsStats getInstance() {
return sInstance;
}
- public void setTrackingEnabled(boolean enabled) {
- mTrackingEnabled = enabled;
+ public void setDetailedTracking(boolean enabled) {
+ if (enabled != mDetailedTracking) {
+ reset();
+ mDetailedTracking = enabled;
+ }
}
- public boolean isTrackingEnabled() {
- return mTrackingEnabled;
+ public void reset() {
+ synchronized (mLock) {
+ mUidEntries.clear();
+ mStartTime = System.currentTimeMillis();
+ }
}
private static class CallStat {
@@ -210,7 +230,7 @@ public class BinderCallsStats {
CallStat callStat = (CallStat) o;
- return msg == callStat.msg && (className == callStat.className);
+ return msg == callStat.msg && (className.equals(callStat.className));
}
@Override
diff --git a/core/java/com/android/internal/widget/ILockSettings.aidl b/core/java/com/android/internal/widget/ILockSettings.aidl
index 7e63adc27c9e..591f15fd5676 100644
--- a/core/java/com/android/internal/widget/ILockSettings.aidl
+++ b/core/java/com/android/internal/widget/ILockSettings.aidl
@@ -45,6 +45,7 @@ interface ILockSettings {
boolean checkVoldPassword(int userId);
boolean havePattern(int userId);
boolean havePassword(int userId);
+ byte[] getHashFactor(String currentCredential, int userId);
void setSeparateProfileChallengeEnabled(int userId, boolean enabled, String managedUserPassword);
boolean getSeparateProfileChallengeEnabled(int userId);
void registerStrongAuthTracker(in IStrongAuthTracker tracker);
diff --git a/core/java/com/android/internal/widget/ImageFloatingTextView.java b/core/java/com/android/internal/widget/ImageFloatingTextView.java
index 09f7282f097a..1e7c11e75aec 100644
--- a/core/java/com/android/internal/widget/ImageFloatingTextView.java
+++ b/core/java/com/android/internal/widget/ImageFloatingTextView.java
@@ -47,6 +47,7 @@ public class ImageFloatingTextView extends TextView {
private boolean mFirstMeasure = true;
private int mLayoutMaxLines = -1;
private boolean mBlockLayouts;
+ private int mImageEndMargin;
public ImageFloatingTextView(Context context) {
this(context, null);
@@ -98,13 +99,11 @@ public class ImageFloatingTextView extends TextView {
}
// we set the endmargin on the requested number of lines.
- int endMargin = getContext().getResources().getDimensionPixelSize(
- R.dimen.notification_content_picture_margin);
int[] margins = null;
if (mIndentLines > 0) {
margins = new int[mIndentLines + 1];
for (int i = 0; i < mIndentLines; i++) {
- margins[i] = endMargin;
+ margins[i] = mImageEndMargin;
}
}
if (mResolvedDirection == LAYOUT_DIRECTION_RTL) {
@@ -116,6 +115,11 @@ public class ImageFloatingTextView extends TextView {
return builder.build();
}
+ @RemotableViewMethod
+ public void setImageEndMargin(int imageEndMargin) {
+ mImageEndMargin = imageEndMargin;
+ }
+
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int height = MeasureSpec.getSize(heightMeasureSpec);
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index d4ab4265b3fb..7c339fb6d6b1 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -66,8 +66,10 @@ import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.List;
+import java.util.StringJoiner;
/**
* Utilities for the lock pattern and its settings.
*/
@@ -165,6 +167,7 @@ public class LockPatternUtils {
public static final String SYNTHETIC_PASSWORD_HANDLE_KEY = "sp-handle";
public static final String SYNTHETIC_PASSWORD_ENABLED_KEY = "enable-sp";
+ private static final String HISTORY_DELIMITER = ",";
private final Context mContext;
private final ContentResolver mContentResolver;
@@ -507,31 +510,50 @@ public class LockPatternUtils {
}
/**
+ * Returns the password history hash factor, needed to check new password against password
+ * history with {@link #checkPasswordHistory(String, byte[], int)}
+ */
+ public byte[] getPasswordHistoryHashFactor(String currentPassword, int userId) {
+ try {
+ return getLockSettings().getHashFactor(currentPassword, userId);
+ } catch (RemoteException e) {
+ Log.e(TAG, "failed to get hash factor", e);
+ return null;
+ }
+ }
+
+ /**
* Check to see if a password matches any of the passwords stored in the
* password history.
*
- * @param password The password to check.
+ * @param passwordToCheck The password to check.
+ * @param hashFactor Hash factor of the current user returned from
+ * {@link ILockSettings#getHashFactor}
* @return Whether the password matches any in the history.
*/
- public boolean checkPasswordHistory(String password, int userId) {
- String passwordHashString = new String(
- passwordToHash(password, userId), StandardCharsets.UTF_8);
+ public boolean checkPasswordHistory(String passwordToCheck, byte[] hashFactor, int userId) {
+ if (TextUtils.isEmpty(passwordToCheck)) {
+ Log.e(TAG, "checkPasswordHistory: empty password");
+ return false;
+ }
String passwordHistory = getString(PASSWORD_HISTORY_KEY, userId);
- if (passwordHistory == null) {
+ if (TextUtils.isEmpty(passwordHistory)) {
return false;
}
- // Password History may be too long...
- int passwordHashLength = passwordHashString.length();
int passwordHistoryLength = getRequestedPasswordHistoryLength(userId);
if(passwordHistoryLength == 0) {
return false;
}
- int neededPasswordHistoryLength = passwordHashLength * passwordHistoryLength
- + passwordHistoryLength - 1;
- if (passwordHistory.length() > neededPasswordHistoryLength) {
- passwordHistory = passwordHistory.substring(0, neededPasswordHistoryLength);
+ String legacyHash = legacyPasswordToHash(passwordToCheck, userId);
+ String passwordHash = passwordToHistoryHash(passwordToCheck, hashFactor, userId);
+ String[] history = passwordHistory.split(HISTORY_DELIMITER);
+ // Password History may be too long...
+ for (int i = 0; i < Math.min(passwordHistoryLength, history.length); i++) {
+ if (history[i].equals(legacyHash) || history[i].equals(passwordHash)) {
+ return true;
+ }
}
- return passwordHistory.contains(passwordHashString);
+ return false;
}
/**
@@ -830,6 +852,7 @@ public class LockPatternUtils {
updateEncryptionPasswordIfNeeded(password,
PasswordMetrics.computeForPassword(password).quality, userHandle);
updatePasswordHistory(password, userHandle);
+ onAfterChangingPassword(userHandle);
}
/**
@@ -852,8 +875,15 @@ public class LockPatternUtils {
}
}
+ /**
+ * Store the hash of the *current* password in the password history list, if device policy
+ * enforces password history requirement.
+ */
private void updatePasswordHistory(String password, int userHandle) {
-
+ if (TextUtils.isEmpty(password)) {
+ Log.e(TAG, "checkPasswordHistory: empty password");
+ return;
+ }
// Add the password to the password history. We assume all
// password hashes have the same length for simplicity of implementation.
String passwordHistory = getString(PASSWORD_HISTORY_KEY, userHandle);
@@ -864,16 +894,25 @@ public class LockPatternUtils {
if (passwordHistoryLength == 0) {
passwordHistory = "";
} else {
- byte[] hash = passwordToHash(password, userHandle);
- passwordHistory = new String(hash, StandardCharsets.UTF_8) + "," + passwordHistory;
- // Cut it to contain passwordHistoryLength hashes
- // and passwordHistoryLength -1 commas.
- passwordHistory = passwordHistory.substring(0, Math.min(hash.length
- * passwordHistoryLength + passwordHistoryLength - 1, passwordHistory
- .length()));
+ final byte[] hashFactor = getPasswordHistoryHashFactor(password, userHandle);
+ String hash = passwordToHistoryHash(password, hashFactor, userHandle);
+ if (hash == null) {
+ Log.e(TAG, "Compute new style password hash failed, fallback to legacy style");
+ hash = legacyPasswordToHash(password, userHandle);
+ }
+ if (TextUtils.isEmpty(passwordHistory)) {
+ passwordHistory = hash;
+ } else {
+ String[] history = passwordHistory.split(HISTORY_DELIMITER);
+ StringJoiner joiner = new StringJoiner(HISTORY_DELIMITER);
+ joiner.add(hash);
+ for (int i = 0; i < passwordHistoryLength - 1 && i < history.length; i++) {
+ joiner.add(history[i]);
+ }
+ passwordHistory = joiner.toString();
+ }
}
setString(PASSWORD_HISTORY_KEY, passwordHistory, userHandle);
- onAfterChangingPassword(userHandle);
}
/**
@@ -1098,7 +1137,7 @@ public class LockPatternUtils {
return Long.toHexString(salt);
}
- /*
+ /**
* Generate a hash for the given password. To avoid brute force attacks, we use a salted hash.
* Not the most secure, but it is at least a second level of protection. First level is that
* the file is in a location only readable by the system process.
@@ -1107,7 +1146,7 @@ public class LockPatternUtils {
*
* @return the hash of the pattern in a byte array.
*/
- public byte[] passwordToHash(String password, int userId) {
+ public String legacyPasswordToHash(String password, int userId) {
if (password == null) {
return null;
}
@@ -1122,7 +1161,24 @@ public class LockPatternUtils {
System.arraycopy(md5, 0, combined, sha1.length, md5.length);
final char[] hexEncoded = HexEncoding.encode(combined);
- return new String(hexEncoded).getBytes(StandardCharsets.UTF_8);
+ return new String(hexEncoded);
+ } catch (NoSuchAlgorithmException e) {
+ throw new AssertionError("Missing digest algorithm: ", e);
+ }
+ }
+
+ /**
+ * Hash the password for password history check purpose.
+ */
+ private String passwordToHistoryHash(String passwordToHash, byte[] hashFactor, int userId) {
+ if (TextUtils.isEmpty(passwordToHash) || hashFactor == null) {
+ return null;
+ }
+ try {
+ MessageDigest sha256 = MessageDigest.getInstance("SHA-256");
+ sha256.update(hashFactor);
+ sha256.update((passwordToHash + getSalt(userId)).getBytes());
+ return new String(HexEncoding.encode(sha256.digest()));
} catch (NoSuchAlgorithmException e) {
throw new AssertionError("Missing digest algorithm: ", e);
}
@@ -1571,6 +1627,7 @@ public class LockPatternUtils {
updateEncryptionPasswordIfNeeded(credential, quality, userId);
updatePasswordHistory(credential, userId);
+ onAfterChangingPassword(userId);
} else {
if (!TextUtils.isEmpty(credential)) {
throw new IllegalArgumentException("password must be emtpy for NONE type");
diff --git a/core/java/com/android/internal/widget/MessagingGroup.java b/core/java/com/android/internal/widget/MessagingGroup.java
index 07d78fe2abda..3f73237da12b 100644
--- a/core/java/com/android/internal/widget/MessagingGroup.java
+++ b/core/java/com/android/internal/widget/MessagingGroup.java
@@ -22,6 +22,8 @@ import android.annotation.Nullable;
import android.annotation.StyleRes;
import android.app.Person;
import android.content.Context;
+import android.content.res.ColorStateList;
+import android.graphics.Color;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.Icon;
@@ -29,6 +31,7 @@ import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Pools;
+import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -36,6 +39,7 @@ import android.view.ViewParent;
import android.view.ViewTreeObserver;
import android.widget.ImageView;
import android.widget.LinearLayout;
+import android.widget.ProgressBar;
import android.widget.RemoteViews;
import com.android.internal.R;
@@ -58,6 +62,7 @@ public class MessagingGroup extends LinearLayout implements MessagingLinearLayou
private CharSequence mAvatarName = "";
private Icon mAvatarIcon;
private int mTextColor;
+ private int mSendingTextColor;
private List<MessagingMessage> mMessages;
private ArrayList<MessagingMessage> mAddedMessages = new ArrayList<>();
private boolean mFirstLayout;
@@ -69,6 +74,8 @@ public class MessagingGroup extends LinearLayout implements MessagingLinearLayou
private MessagingImageMessage mIsolatedMessage;
private boolean mTransformingImages;
private Point mDisplaySize = new Point();
+ private ProgressBar mSendingSpinner;
+ private View mSendingSpinnerContainer;
public MessagingGroup(@NonNull Context context) {
super(context);
@@ -96,6 +103,8 @@ public class MessagingGroup extends LinearLayout implements MessagingLinearLayou
mSenderName.addOnLayoutChangeListener(MessagingLayout.MESSAGING_PROPERTY_ANIMATOR);
mAvatarView = findViewById(R.id.message_icon);
mImageContainer = findViewById(R.id.messaging_group_icon_container);
+ mSendingSpinner = findViewById(R.id.messaging_group_sending_progress);
+ mSendingSpinnerContainer = findViewById(R.id.messaging_group_sending_progress_container);
DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
mDisplaySize.x = displayMetrics.widthPixels;
mDisplaySize.y = displayMetrics.heightPixels;
@@ -139,17 +148,37 @@ public class MessagingGroup extends LinearLayout implements MessagingLinearLayou
mAvatarView.setVisibility(VISIBLE);
mSenderName.setVisibility(VISIBLE);
mTextColor = getNormalTextColor();
+ mSendingTextColor = calculateSendingTextColor();
+ }
+
+ public void setSending(boolean sending) {
+ int visibility = sending ? View.VISIBLE : View.GONE;
+ if (mSendingSpinnerContainer.getVisibility() != visibility) {
+ mSendingSpinnerContainer.setVisibility(visibility);
+ updateMessageColor();
+ }
}
private int getNormalTextColor() {
return mContext.getColor(R.color.notification_secondary_text_color_light);
}
+ private int calculateSendingTextColor() {
+ TypedValue alphaValue = new TypedValue();
+ mContext.getResources().getValue(
+ R.dimen.notification_secondary_text_disabled_alpha, alphaValue, true);
+ float alpha = alphaValue.getFloat();
+ return Color.valueOf(
+ Color.red(mTextColor),
+ Color.green(mTextColor),
+ Color.blue(mTextColor),
+ alpha).toArgb();
+ }
+
public void setAvatar(Icon icon) {
mAvatarIcon = icon;
mAvatarView.setImageIcon(icon);
mAvatarSymbol = "";
- mLayoutColor = 0;
mAvatarName = "";
}
@@ -321,13 +350,26 @@ public class MessagingGroup extends LinearLayout implements MessagingLinearLayou
|| layoutColor != mLayoutColor) {
setAvatar(cachedIcon);
mAvatarSymbol = avatarSymbol;
- mLayoutColor = layoutColor;
+ setLayoutColor(layoutColor);
mAvatarName = avatarName;
}
}
public void setLayoutColor(int layoutColor) {
- mLayoutColor = layoutColor;
+ if (layoutColor != mLayoutColor){
+ mLayoutColor = layoutColor;
+ mSendingSpinner.setIndeterminateTintList(ColorStateList.valueOf(mLayoutColor));
+ }
+ }
+
+ private void updateMessageColor() {
+ if (mMessages != null) {
+ int color = mSendingSpinnerContainer.getVisibility() == View.VISIBLE
+ ? mSendingTextColor : mTextColor;
+ for (MessagingMessage message : mMessages) {
+ message.setColor(message.getMessage().isRemoteInputHistory() ? color : mTextColor);
+ }
+ }
}
public void setMessages(List<MessagingMessage> group) {
@@ -336,7 +378,6 @@ public class MessagingGroup extends LinearLayout implements MessagingLinearLayou
MessagingImageMessage isolatedMessage = null;
for (int messageIndex = 0; messageIndex < group.size(); messageIndex++) {
MessagingMessage message = group.get(messageIndex);
- message.setColor(mTextColor);
if (message.getGroup() != this) {
message.setMessagingGroup(this);
mAddedMessages.add(message);
@@ -375,7 +416,14 @@ public class MessagingGroup extends LinearLayout implements MessagingLinearLayou
mImageContainer.removeAllViews();
}
mIsolatedMessage = isolatedMessage;
+ updateImageContainerVisibility();
mMessages = group;
+ updateMessageColor();
+ }
+
+ private void updateImageContainerVisibility() {
+ mImageContainer.setVisibility(mIsolatedMessage != null && mImagesAtEnd
+ ? View.VISIBLE : View.GONE);
}
/**
@@ -477,7 +525,7 @@ public class MessagingGroup extends LinearLayout implements MessagingLinearLayou
public void setDisplayImagesAtEnd(boolean atEnd) {
if (mImagesAtEnd != atEnd) {
mImagesAtEnd = atEnd;
- mImageContainer.setVisibility(atEnd ? View.VISIBLE : View.GONE);
+ updateImageContainerVisibility();
}
}
diff --git a/core/java/com/android/internal/widget/MessagingLayout.java b/core/java/com/android/internal/widget/MessagingLayout.java
index f8236c78ac43..df20e639adf0 100644
--- a/core/java/com/android/internal/widget/MessagingLayout.java
+++ b/core/java/com/android/internal/widget/MessagingLayout.java
@@ -149,7 +149,9 @@ public class MessagingLayout extends FrameLayout {
}
addRemoteInputHistoryToMessages(newMessages,
extras.getCharSequenceArray(Notification.EXTRA_REMOTE_INPUT_HISTORY));
- bind(newMessages, newHistoricMessages);
+ boolean showSpinner =
+ extras.getBoolean(Notification.EXTRA_SHOW_REMOTE_INPUT_SPINNER, false);
+ bind(newMessages, newHistoricMessages, showSpinner);
}
private void addRemoteInputHistoryToMessages(
@@ -161,17 +163,18 @@ public class MessagingLayout extends FrameLayout {
for (int i = remoteInputHistory.length - 1; i >= 0; i--) {
CharSequence message = remoteInputHistory[i];
newMessages.add(new Notification.MessagingStyle.Message(
- message, 0, (Person) null));
+ message, 0, (Person) null, true /* remoteHistory */));
}
}
private void bind(List<Notification.MessagingStyle.Message> newMessages,
- List<Notification.MessagingStyle.Message> newHistoricMessages) {
+ List<Notification.MessagingStyle.Message> newHistoricMessages,
+ boolean showSpinner) {
List<MessagingMessage> historicMessages = createMessages(newHistoricMessages,
true /* isHistoric */);
List<MessagingMessage> messages = createMessages(newMessages, false /* isHistoric */);
- addMessagesToGroups(historicMessages, messages);
+ addMessagesToGroups(historicMessages, messages, showSpinner);
// Let's remove the remaining messages
mMessages.forEach(REMOVE_MESSAGE);
@@ -308,7 +311,7 @@ public class MessagingLayout extends FrameLayout {
}
private void addMessagesToGroups(List<MessagingMessage> historicMessages,
- List<MessagingMessage> messages) {
+ List<MessagingMessage> messages, boolean showSpinner) {
// Let's first find our groups!
List<List<MessagingMessage>> groups = new ArrayList<>();
List<Person> senders = new ArrayList<>();
@@ -317,11 +320,11 @@ public class MessagingLayout extends FrameLayout {
findGroups(historicMessages, messages, groups, senders);
// Let's now create the views and reorder them accordingly
- createGroupViews(groups, senders);
+ createGroupViews(groups, senders, showSpinner);
}
private void createGroupViews(List<List<MessagingMessage>> groups,
- List<Person> senders) {
+ List<Person> senders, boolean showSpinner) {
mGroups.clear();
for (int groupIndex = 0; groupIndex < groups.size(); groupIndex++) {
List<MessagingMessage> group = groups.get(groupIndex);
@@ -346,6 +349,7 @@ public class MessagingLayout extends FrameLayout {
nameOverride = mNameReplacement;
}
newGroup.setSender(sender, nameOverride);
+ newGroup.setSending(groupIndex == (groups.size() - 1) && showSpinner);
mGroups.add(newGroup);
if (mMessagingLinearLayout.indexOfChild(newGroup) != groupIndex) {
diff --git a/core/java/com/android/internal/widget/MessagingMessage.java b/core/java/com/android/internal/widget/MessagingMessage.java
index a2cc7cfb856c..f0b60685b70e 100644
--- a/core/java/com/android/internal/widget/MessagingMessage.java
+++ b/core/java/com/android/internal/widget/MessagingMessage.java
@@ -82,6 +82,9 @@ public interface MessagingMessage extends MessagingLinearLayout.MessagingChild {
if (!Objects.equals(message.getDataUri(), ownMessage.getDataUri())) {
return false;
}
+ if (message.isRemoteInputHistory() != ownMessage.isRemoteInputHistory()) {
+ return false;
+ }
return true;
}
diff --git a/core/jni/android_hardware_camera2_DngCreator.cpp b/core/jni/android_hardware_camera2_DngCreator.cpp
index 162822092af6..567bb075d746 100644
--- a/core/jni/android_hardware_camera2_DngCreator.cpp
+++ b/core/jni/android_hardware_camera2_DngCreator.cpp
@@ -1723,13 +1723,13 @@ static sp<TiffWriter> DngCreator_setup(JNIEnv* env, jobject thiz, uint32_t image
// Adjust the bad pixel coordinates to be relative to the origin of the active area DNG tag
std::vector<uint32_t> v;
- for (size_t i = 0; i < entry3.count; i+=2) {
+ for (size_t i = 0; i < entry3.count; i += 2) {
int32_t x = entry3.data.i32[i];
int32_t y = entry3.data.i32[i + 1];
x -= static_cast<int32_t>(xmin);
y -= static_cast<int32_t>(ymin);
if (x < 0 || y < 0 || static_cast<uint32_t>(x) >= width ||
- static_cast<uint32_t>(y) >= width) {
+ static_cast<uint32_t>(y) >= height) {
continue;
}
v.push_back(x);
diff --git a/core/res/res/drawable/ic_reply_notification.xml b/core/res/res/drawable/ic_reply_notification.xml
index 88b8c5b7ddef..a9864b09207a 100644
--- a/core/res/res/drawable/ic_reply_notification.xml
+++ b/core/res/res/drawable/ic_reply_notification.xml
@@ -13,15 +13,20 @@
~ See the License for the specific language governing permissions and
~ limitations under the License
-->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="10dp"
- android:height="10dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M10.0,9.0L10.0,5.0l-7.0,7.0 7.0,7.0l0.0,-4.1c5.0,0.0 8.5,1.6 11.0,5.1 -1.0,-5.0 -4.0,-10.0 -11.0,-11.0z"/>
- <path
- android:pathData="M0 0h24v24H0z"
- android:fillColor="#00000000"/>
-</vector>
+<inset xmlns:android="http://schemas.android.com/apk/res/android"
+ android:inset="@dimen/notification_reply_inset">
+ <vector android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+
+ <path
+ android:fillColor="#000000"
+ android:strokeWidth="1"
+ android:pathData="M16,10 L6.83,10 L9,7.83 L10.41,6.42 L9,5 L3,11 L9,17 L10.41,15.59 L9,14.17 L6.83,12 L16,12 C17.65,12 19,13.35 19,15 L19,19 L21,19 L21,15 C21,12.24 18.76,10 16,10 Z" />
+ <path
+ android:fillColor="#000000"
+ android:strokeWidth="1"
+ android:pathData="M16,10 L6.83,10 L9,7.83 L10.41,6.42 L9,5 L3,11 L9,17 L10.41,15.59 L9,14.17 L6.83,12 L16,12 C17.65,12 19,13.35 19,15 L19,19 L21,19 L21,15 C21,12.24 18.76,10 16,10 Z" />
+ </vector>
+</inset>
diff --git a/core/res/res/drawable/ic_reply_notification_large.xml b/core/res/res/drawable/ic_reply_notification_large.xml
deleted file mode 100644
index e75afddfead3..000000000000
--- a/core/res/res/drawable/ic_reply_notification_large.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<!--
- ~ Copyright (C) 2017 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License
- -->
-<inset xmlns:android="http://schemas.android.com/apk/res/android"
- android:inset="8dp">
- <vector android:width="24dp"
- android:height="24dp"
- android:viewportHeight="24.0"
- android:viewportWidth="24.0">
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M10.0,9.0L10.0,5.0l-7.0,7.0 7.0,7.0l0.0,-4.1c5.0,0.0 8.5,1.6 11.0,5.1 -1.0,-5.0 -4.0,-10.0 -11.0,-11.0z"/>
- <path
- android:fillColor="#00000000"
- android:pathData="M0 0h24v24H0z"/>
- </vector>
-</inset>
diff --git a/core/res/res/drawable/notification_reply_background.xml b/core/res/res/drawable/notification_reply_background.xml
deleted file mode 100644
index 08e22f2f9729..000000000000
--- a/core/res/res/drawable/notification_reply_background.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<!--
- ~ Copyright (C) 2017 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License
- -->
-
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
- <solid
- android:color="#ff757575"/>
- <size
- android:width="16dp"
- android:height="16dp"/>
-</shape>
diff --git a/core/res/res/layout/global_actions_item.xml b/core/res/res/layout/global_actions_item.xml
index e5a9854d50c7..6ac0b1756234 100644
--- a/core/res/res/layout/global_actions_item.xml
+++ b/core/res/res/layout/global_actions_item.xml
@@ -13,6 +13,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+<!-- Used with LegacyGlobalActions. -->
<!-- RelativeLayouts have an issue enforcing minimum heights, so just
work around this for now with LinearLayouts. -->
diff --git a/core/res/res/layout/notification_material_action_tombstone.xml b/core/res/res/layout/notification_material_action_tombstone.xml
index 817f298f0c6f..9fa7c6a28020 100644
--- a/core/res/res/layout/notification_material_action_tombstone.xml
+++ b/core/res/res/layout/notification_material_action_tombstone.xml
@@ -27,7 +27,7 @@
android:singleLine="true"
android:ellipsize="end"
android:textAlignment="viewStart"
- android:alpha="0.5"
+ android:alpha="@dimen/notification_action_disabled_alpha"
android:enabled="false"
android:background="@drawable/notification_material_action_background"
/>
diff --git a/core/res/res/layout/notification_material_reply_text.xml b/core/res/res/layout/notification_material_reply_text.xml
index 84603b06604e..dbf2dd008101 100644
--- a/core/res/res/layout/notification_material_reply_text.xml
+++ b/core/res/res/layout/notification_material_reply_text.xml
@@ -30,6 +30,7 @@
android:id="@+id/action_divider"
android:layout_marginTop="@dimen/notification_content_margin"
android:layout_marginBottom="@dimen/notification_content_margin"
+ android:layout_marginEnd="@dimen/notification_content_margin_end"
android:background="@drawable/notification_template_divider" />
<TextView
@@ -50,12 +51,31 @@
android:textAppearance="@style/TextAppearance.Material.Notification.Reply"
android:singleLine="true" />
- <TextView
- android:id="@+id/notification_material_reply_text_1"
+ <LinearLayout
+ android:id="@+id/notification_material_reply_text_1_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:layout_marginStart="@dimen/notification_content_margin_start"
+ android:layout_marginEnd="@dimen/notification_content_margin_end">
+ <TextView
+ android:id="@+id/notification_material_reply_text_1"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:layout_marginEnd="@dimen/notification_content_margin_end"
+ android:layout_gravity="center"
+ android:textAppearance="@style/TextAppearance.Material.Notification.Reply"
+ android:singleLine="true" />
+ <ProgressBar
+ android:id="@+id/notification_material_reply_progress"
+ android:layout_height="@dimen/messaging_group_sending_progress_size"
+ android:layout_width="@dimen/messaging_group_sending_progress_size"
+ android:layout_marginStart="@dimen/notification_content_margin_start"
android:layout_marginEnd="@dimen/notification_content_margin_end"
- android:textAppearance="@style/TextAppearance.Material.Notification.Reply"
- android:singleLine="true" />
+ android:layout_gravity="center"
+ android:indeterminate="true"
+ style="?android:attr/progressBarStyleSmall" />
+ </LinearLayout>
</LinearLayout>
diff --git a/core/res/res/layout/notification_template_material_messaging.xml b/core/res/res/layout/notification_template_material_messaging.xml
index 53514a341504..10c750972961 100644
--- a/core/res/res/layout/notification_template_material_messaging.xml
+++ b/core/res/res/layout/notification_template_material_messaging.xml
@@ -52,7 +52,9 @@
<include layout="@layout/notification_template_smart_reply_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginTop="@dimen/notification_content_margin" />
+ android:layout_marginTop="@dimen/notification_content_margin"
+ android:layout_marginStart="@dimen/notification_content_margin_start"
+ android:layout_marginEnd="@dimen/notification_content_margin_end" />
<include layout="@layout/notification_material_action_list" />
</com.android.internal.widget.RemeasuringLinearLayout>
<include layout="@layout/notification_template_right_icon"/>
diff --git a/core/res/res/layout/notification_template_messaging_group.xml b/core/res/res/layout/notification_template_messaging_group.xml
index bd1030ee14f5..d2fd467c3e00 100644
--- a/core/res/res/layout/notification_template_messaging_group.xml
+++ b/core/res/res/layout/notification_template_messaging_group.xml
@@ -50,4 +50,19 @@
android:layout_height="@dimen/messaging_avatar_size"
android:layout_marginStart="12dp"
android:visibility="gone"/>
+ <FrameLayout
+ android:id="@+id/messaging_group_sending_progress_container"
+ android:layout_width="@dimen/messaging_group_sending_progress_size"
+ android:layout_height="@dimen/messaging_avatar_size"
+ android:layout_marginStart="12dp"
+ android:layout_gravity="top"
+ android:visibility="gone">
+ <ProgressBar
+ android:id="@+id/messaging_group_sending_progress"
+ android:layout_height="@dimen/messaging_group_sending_progress_size"
+ android:layout_width="@dimen/messaging_group_sending_progress_size"
+ android:layout_gravity="center"
+ android:indeterminate="true"
+ style="?android:attr/progressBarStyleSmall" />
+ </FrameLayout>
</com.android.internal.widget.MessagingGroup>
diff --git a/core/res/res/layout/notification_template_right_icon.xml b/core/res/res/layout/notification_template_right_icon.xml
index 0b97e45b8eed..ee416ad36b8a 100644
--- a/core/res/res/layout/notification_template_right_icon.xml
+++ b/core/res/res/layout/notification_template_right_icon.xml
@@ -14,30 +14,29 @@
~ See the License for the specific language governing permissions and
~ limitations under the License
-->
-
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<!-- The view only has 8dp padding at the end instead of notification_content_margin_end,
+ since the reply icon has an inset of 8dp and we want it to visually start at the start of the
+ icon. -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/right_icon_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/notification_content_margin_top"
+ android:layout_marginEnd="8dp"
android:layout_gravity="top|end">
<ImageView android:id="@+id/right_icon"
android:layout_width="@dimen/notification_right_icon_size"
android:layout_height="@dimen/notification_right_icon_size"
android:layout_gravity="top|end"
- android:layout_marginEnd="@dimen/notification_content_margin_end"
+ android:layout_marginEnd="8dp"
android:scaleType="centerCrop"
android:importantForAccessibility="no" />
- <ImageButton android:id="@+id/reply_icon_action"
- android:layout_width="16dp"
- android:layout_height="16dp"
- android:layout_gravity="top|end"
- android:layout_marginTop="27dp"
- android:layout_marginEnd="16dp"
- android:background="@drawable/notification_reply_background"
- android:src="@drawable/ic_reply_notification"
- android:scaleType="center"
- android:contentDescription="@string/notification_reply_button_accessibility"
- visiblity="gone"/>
-</FrameLayout>
+ <ImageView android:id="@+id/reply_icon_action"
+ android:layout_width="@dimen/notification_right_icon_size"
+ android:layout_height="@dimen/notification_right_icon_size"
+ android:layout_gravity="top|end"
+ android:contentDescription="@string/notification_reply_button_accessibility"
+ android:scaleType="centerCrop"
+ android:src="@drawable/ic_reply_notification"/>
+</LinearLayout>
diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml
index da9fed080aed..095a632c4acd 100644
--- a/core/res/res/values/colors.xml
+++ b/core/res/res/values/colors.xml
@@ -137,6 +137,7 @@
<color name="notification_primary_text_color_light">@color/primary_text_default_material_light</color>
<color name="notification_primary_text_color_dark">@color/primary_text_default_material_dark</color>
<color name="notification_secondary_text_color_light">@color/primary_text_default_material_light</color>
+ <item name="notification_secondary_text_disabled_alpha" format="float" type="dimen">0.30</item>
<color name="notification_secondary_text_color_dark">@color/primary_text_default_material_dark</color>
<color name="notification_default_color_dark">@color/primary_text_default_material_light</color>
<color name="notification_default_color_light">#a3202124</color>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index a135b28c196a..84f23a9c07e9 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -162,19 +162,14 @@
<!-- The margin on the start of the content view -->
<dimen name="notification_content_margin_start">16dp</dimen>
- <!-- The margin on the end of the content view
- Keep in sync with notification_content_plus_picture_margin! -->
+ <!-- The margin on the end of the content view. -->
<dimen name="notification_content_margin_end">16dp</dimen>
- <!-- The margin on the end of the content view with a picture.
- Keep in sync with notification_content_plus_picture_margin! -->
- <dimen name="notification_content_picture_margin">56dp</dimen>
+ <!-- The inset of the reply icon. -->
+ <dimen name="notification_reply_inset">8dp</dimen>
- <!-- The margin on the end of the content view with a picture, plus the standard
- content end margin.
- Keep equal to (notification_content_picture_margin + notification_content_margin_end)!
- -->
- <dimen name="notification_content_plus_picture_margin_end">72dp</dimen>
+ <!-- The margin for text at the end of the image view for media notifications -->
+ <dimen name="notification_media_image_margin_end">72dp</dimen>
<!-- The additional margin on the sides of the ambient view. -->
<dimen name="notification_extra_margin_ambient">16dp</dimen>
@@ -616,7 +611,9 @@
<!-- The maximum width of a image in a media notification. The images will be reduced to that width in case they are bigger.-->
<dimen name="notification_media_image_max_width">280dp</dimen>
<!-- The size of the right icon -->
- <dimen name="notification_right_icon_size">38dp</dimen>
+ <dimen name="notification_right_icon_size">36dp</dimen>
+ <!-- The alpha of a disabled notification button -->
+ <item type="dimen" format="float" name="notification_action_disabled_alpha">0.5</item>
<!-- The maximum height of any image in a remote view. This is applied to all images in custom remoteviews. -->
<dimen name="notification_custom_view_max_image_height_low_ram">208dp</dimen>
@@ -631,10 +628,12 @@
<!-- The maximum width of a image in a media notification. The images will be reduced to that width in case they are bigger.-->
<dimen name="notification_media_image_max_width_low_ram">100dp</dimen>
<!-- The size of the right icon image when on low ram -->
- <dimen name="notification_right_icon_size_low_ram">40dp</dimen>
+ <dimen name="notification_right_icon_size_low_ram">@dimen/notification_right_icon_size_low_ram</dimen>
<dimen name="messaging_avatar_size">@dimen/notification_right_icon_size</dimen>
+ <dimen name="messaging_group_sending_progress_size">24dp</dimen>
+
<!-- Max width/height of the autofill data set picker as a fraction of the screen width/height -->
<dimen name="autofill_dataset_picker_max_width">90%</dimen>
<dimen name="autofill_dataset_picker_max_height">90%</dimen>
diff --git a/core/res/res/values/ids.xml b/core/res/res/values/ids.xml
index c90a0df5d7b1..47d04edfc281 100644
--- a/core/res/res/values/ids.xml
+++ b/core/res/res/values/ids.xml
@@ -128,6 +128,7 @@
<item type="id" name="accessibilityActionContextClick" />
<item type="id" name="remote_input_tag" />
+ <item type="id" name="pending_intent_tag" />
<item type="id" name="cross_task_transition" />
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 590f98800874..1785034783a7 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2615,6 +2615,7 @@
<java-symbol type="id" name="actions_container" />
<java-symbol type="id" name="smart_reply_container" />
<java-symbol type="id" name="remote_input_tag" />
+ <java-symbol type="id" name="pending_intent_tag" />
<java-symbol type="attr" name="seekBarDialogPreferenceStyle" />
<java-symbol type="string" name="ext_media_status_removed" />
@@ -2668,8 +2669,10 @@
<java-symbol type="id" name="notification_material_reply_container" />
<java-symbol type="id" name="notification_material_reply_text_1" />
+ <java-symbol type="id" name="notification_material_reply_text_1_container" />
<java-symbol type="id" name="notification_material_reply_text_2" />
<java-symbol type="id" name="notification_material_reply_text_3" />
+ <java-symbol type="id" name="notification_material_reply_progress" />
<java-symbol type="string" name="notification_hidden_text" />
<java-symbol type="id" name="app_name_text" />
@@ -2689,7 +2692,7 @@
<java-symbol type="dimen" name="notification_header_shrink_min_width" />
<java-symbol type="dimen" name="notification_content_margin_start" />
<java-symbol type="dimen" name="notification_content_margin_end" />
- <java-symbol type="dimen" name="notification_content_picture_margin" />
+ <java-symbol type="dimen" name="notification_reply_inset" />
<java-symbol type="dimen" name="notification_content_margin_top" />
<java-symbol type="dimen" name="notification_content_margin" />
<java-symbol type="dimen" name="notification_header_background_height" />
@@ -2873,8 +2876,9 @@
<java-symbol type="bool" name="config_supportPreRebootSecurityLogs" />
- <java-symbol type="dimen" name="notification_content_plus_picture_margin_end" />
+ <java-symbol type="dimen" name="notification_media_image_margin_end" />
<java-symbol type="id" name="notification_action_list_margin_target" />
+ <java-symbol type="dimen" name="notification_action_disabled_alpha" />
<!-- Pinner Service -->
<java-symbol type="array" name="config_defaultPinnerServiceFiles" />
@@ -2999,6 +3003,7 @@
<java-symbol type="color" name="notification_secondary_text_color_dark" />
<java-symbol type="color" name="notification_default_color_light" />
<java-symbol type="color" name="notification_default_color_dark" />
+ <java-symbol type="dimen" name="notification_secondary_text_disabled_alpha" />
<java-symbol type="string" name="app_category_game" />
<java-symbol type="string" name="app_category_audio" />
@@ -3252,13 +3257,15 @@
<java-symbol type="id" name="clip_children_set_tag" />
<java-symbol type="id" name="clip_to_padding_tag" />
<java-symbol type="id" name="clip_children_tag" />
- <java-symbol type="drawable" name="ic_reply_notification_large" />
<java-symbol type="dimen" name="messaging_avatar_size" />
+ <java-symbol type="dimen" name="messaging_group_sending_progress_size" />
<java-symbol type="dimen" name="messaging_image_rounding" />
<java-symbol type="dimen" name="messaging_image_min_size" />
<java-symbol type="dimen" name="messaging_image_max_height" />
<java-symbol type="dimen" name="messaging_image_extra_spacing" />
<java-symbol type="id" name="messaging_group_icon_container" />
+ <java-symbol type="id" name="messaging_group_sending_progress" />
+ <java-symbol type="id" name="messaging_group_sending_progress_container" />
<java-symbol type="integer" name="config_stableDeviceDisplayWidth" />
<java-symbol type="integer" name="config_stableDeviceDisplayHeight" />
diff --git a/core/tests/BroadcastRadioTests/src/android/hardware/radio/tests/functional/RadioTunerTest.java b/core/tests/BroadcastRadioTests/src/android/hardware/radio/tests/functional/RadioTunerTest.java
index 370659eb99d9..fdaba089490e 100644
--- a/core/tests/BroadcastRadioTests/src/android/hardware/radio/tests/functional/RadioTunerTest.java
+++ b/core/tests/BroadcastRadioTests/src/android/hardware/radio/tests/functional/RadioTunerTest.java
@@ -123,6 +123,7 @@ public class RadioTunerTest {
private void resetCallback() {
verify(mCallback, atLeast(0)).onMetadataChanged(any());
verify(mCallback, atLeast(0)).onProgramInfoChanged(any());
+ verify(mCallback, atLeast(0)).onProgramListChanged();
verifyNoMoreInteractions(mCallback);
Mockito.reset(mCallback);
}
diff --git a/core/tests/coretests/src/android/text/EmojiTest.java b/core/tests/coretests/src/android/text/EmojiTest.java
new file mode 100644
index 000000000000..313f1b6a6614
--- /dev/null
+++ b/core/tests/coretests/src/android/text/EmojiTest.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.text;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import android.icu.lang.UCharacterDirection;
+import android.icu.text.Bidi;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Emoji and ICU drops does not happen at the same time. Therefore there are almost always cases
+ * where the existing ICU version is not aware of the latest emoji that Android supports.
+ * This test covers Emoji and ICU related functions where other components such as
+ * {@link AndroidBidi}, {@link BidiFormatter} depend on. The tests are collected into the same
+ * class since the changes effect all those classes.
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class EmojiTest {
+
+ @Test
+ public void testIsNewEmoji_Emoji5() {
+ // each row in the data is the range of emoji
+ final int[][][] data = new int[][][]{
+ { // EMOJI 5
+ // range of emoji: i.e from 0x1F6F7 to 0x1F6F8 inclusive
+ {0x1F6F7, 0x1F6F8},
+ {0x1F91F, 0x1F91F},
+ {0x1F928, 0x1F92F},
+ {0x1F94C, 0x1F94C},
+ {0x1F95F, 0x1F96B},
+ {0x1F992, 0x1F997},
+ {0x1F9D0, 0x1F9E6},
+ },
+ { // EMOJI 11
+ {0x265F, 0x265F},
+ {0x267E, 0x267E},
+ {0x1F6F9, 0x1F6F9},
+ {0x1F94D, 0x1F94F},
+ {0x1F96C, 0x1F970},
+ {0x1F973, 0x1F976},
+ {0x1F97A, 0x1F97A},
+ {0x1F97C, 0x1F97F},
+ {0x1F998, 0x1F9A2},
+ {0x1F9B0, 0x1F9B9},
+ {0x1F9C1, 0x1F9C2},
+ {0x1F9E7, 0x1F9FF},
+ }
+ };
+
+ final Bidi icuBidi = new Bidi(0 /* maxLength */, 0 /* maxRunCount */);
+ icuBidi.setCustomClassifier(new AndroidBidi.EmojiBidiOverride());
+
+ for (int version = 0; version < data.length; version++) {
+ for (int row = 0; row < data[version].length; row++) {
+ for (int c = data[version][row][0]; c < data[version][row][1]; c++) {
+ assertTrue(Integer.toHexString(c) + " should be emoji", Emoji.isEmoji(c));
+
+ assertEquals(Integer.toHexString(c) + " should have neutral directionality",
+ Character.DIRECTIONALITY_OTHER_NEUTRALS,
+ BidiFormatter.DirectionalityEstimator.getDirectionality(c));
+
+ assertEquals(Integer.toHexString(c) + " shoud be OTHER_NEUTRAL for ICU Bidi",
+ UCharacterDirection.OTHER_NEUTRAL, icuBidi.getCustomizedClass(c));
+ }
+ }
+ }
+ }
+
+ @Test
+ public void testisEmojiModifierBase_LegacyCompat() {
+ assertTrue(Emoji.isEmojiModifierBase(0x1F91D));
+ assertTrue(Emoji.isEmojiModifierBase(0x1F93C));
+ }
+
+ @Test
+ public void testisEmojiModifierBase() {
+ // each row in the data is the range of emoji
+ final int[][][] data = new int[][][]{
+ { // EMOJI 5
+ // range of emoji: i.e from 0x1F91F to 0x1F91F inclusive
+ {0x1F91F, 0x1F91F},
+ {0x1F931, 0x1F932},
+ {0x1F9D1, 0x1F9DD},
+ },
+ { // EMOJI 11
+ {0x1F9B5, 0x1F9B6},
+ {0x1F9B8, 0x1F9B9}
+ }
+ };
+ for (int version = 0; version < data.length; version++) {
+ for (int row = 0; row < data[version].length; row++) {
+ for (int c = data[version][row][0]; c < data[version][row][1]; c++) {
+ assertTrue(Integer.toHexString(c) + " should be emoji modifier base",
+ Emoji.isEmojiModifierBase(c));
+ }
+ }
+ }
+ }
+}
diff --git a/location/java/android/location/GnssMeasurementsEvent.java b/location/java/android/location/GnssMeasurementsEvent.java
index 072a7fefb665..34c73549c5df 100644
--- a/location/java/android/location/GnssMeasurementsEvent.java
+++ b/location/java/android/location/GnssMeasurementsEvent.java
@@ -74,6 +74,13 @@ public final class GnssMeasurementsEvent implements Parcelable {
/**
* The client is not allowed to register for GNSS Measurements in general or in the
* requested mode.
+ *
+ * <p>Such a status is returned when a client tries to request a functionality from the GNSS
+ * chipset while another client has an ongoing request that does not allow such
+ * functionality to be performed.
+ *
+ * <p>If such a status is received, one would try again at a later time point where no
+ * other client is having a conflicting request.
*/
public static final int STATUS_NOT_ALLOWED = 3;
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index 000317e688da..16f6284b6031 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -1261,6 +1261,11 @@ static void android_media_MediaCodec_setInputSurface(
sp<PersistentSurface> persistentSurface =
android_media_MediaCodec_getPersistentInputSurface(env, object);
+ if (persistentSurface == NULL) {
+ throwExceptionAsNecessary(
+ env, BAD_VALUE, ACTION_CODE_FATAL, "input surface not valid");
+ return;
+ }
status_t err = codec->setInputSurface(persistentSurface);
if (err != NO_ERROR) {
throwExceptionAsNecessary(env, err);
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
index 50c6aac57e8f..3b1e4ce7e97a 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
@@ -27,8 +27,10 @@ import com.android.internal.annotations.VisibleForTesting;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.Objects;
/**
@@ -191,6 +193,7 @@ public class CachedBluetoothDeviceManager {
log("updateHearingAidsDevices: getHearingAidProfile() is null");
return;
}
+ final Set<Long> syncIdChangedSet = new HashSet<Long>();
for (CachedBluetoothDevice cachedDevice : mCachedDevices) {
if (cachedDevice.getHiSyncId() != BluetoothHearingAid.HI_SYNC_ID_INVALID) {
continue;
@@ -200,9 +203,12 @@ public class CachedBluetoothDeviceManager {
if (newHiSyncId != BluetoothHearingAid.HI_SYNC_ID_INVALID) {
cachedDevice.setHiSyncId(newHiSyncId);
- onHiSyncIdChanged(newHiSyncId);
+ syncIdChangedSet.add(newHiSyncId);
}
}
+ for (Long syncId : syncIdChangedSet) {
+ onHiSyncIdChanged(syncId);
+ }
}
/**
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java
index c3bd16195140..bab3cab3795c 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java
@@ -486,11 +486,14 @@ public class CachedBluetoothDeviceManagerTest {
doAnswer((invocation) -> mHearingAidProfile).when(mLocalProfileManager)
.getHearingAidProfile();
doAnswer((invocation) -> HISYNCID1).when(mHearingAidProfile).getHiSyncId(mDevice1);
+ doAnswer((invocation) -> HISYNCID1).when(mHearingAidProfile).getHiSyncId(mDevice2);
mCachedDeviceManager.mCachedDevices.add(mCachedDevice1);
+ mCachedDeviceManager.mCachedDevices.add(mCachedDevice2);
mCachedDeviceManager.updateHearingAidsDevices(mLocalProfileManager);
- // Assert that the mCachedDevice1 has an updated HiSyncId.
+ // Assert that the mCachedDevice1 and mCachedDevice2 have an updated HiSyncId.
assertThat(mCachedDevice1.getHiSyncId()).isEqualTo(HISYNCID1);
+ assertThat(mCachedDevice2.getHiSyncId()).isEqualTo(HISYNCID1);
}
/**
diff --git a/packages/SystemUI/res/layout/global_actions_item.xml b/packages/SystemUI/res/layout/global_actions_item.xml
index bf3aea8ab6dd..66a4b737d09b 100644
--- a/packages/SystemUI/res/layout/global_actions_item.xml
+++ b/packages/SystemUI/res/layout/global_actions_item.xml
@@ -25,8 +25,8 @@
android:minHeight="92dp"
android:gravity="center"
android:orientation="vertical"
- android:paddingEnd="0dip"
- android:paddingStart="0dip">
+ android:paddingEnd="4dip"
+ android:paddingStart="4dip">
<ImageView
android:id="@*android:id/icon"
diff --git a/packages/SystemUI/res/layout/global_actions_wrapped.xml b/packages/SystemUI/res/layout/global_actions_wrapped.xml
index 4a6af9e139d5..b715def73294 100644
--- a/packages/SystemUI/res/layout/global_actions_wrapped.xml
+++ b/packages/SystemUI/res/layout/global_actions_wrapped.xml
@@ -17,7 +17,7 @@
android:layout_gravity="top|right"
android:gravity="center"
android:orientation="vertical"
- android:padding="16dp"
+ android:padding="12dp"
android:translationZ="9dp" />
</com.android.systemui.HardwareUiLayout>
diff --git a/packages/SystemUI/res/layout/quick_qs_status_icons.xml b/packages/SystemUI/res/layout/quick_qs_status_icons.xml
index dcb8aaf2a6a8..5f73beff92e4 100644
--- a/packages/SystemUI/res/layout/quick_qs_status_icons.xml
+++ b/packages/SystemUI/res/layout/quick_qs_status_icons.xml
@@ -15,15 +15,28 @@
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:systemui="http://schemas.android.com/apk/res-auto"
android:id="@+id/quick_qs_status_icons"
android:layout_width="match_parent"
android:layout_height="20dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="14dp"
+ android:layout_marginStart="8dp"
android:layout_marginEnd="@dimen/notification_side_paddings"
android:layout_below="@id/quick_status_bar_system_icons"
android:paddingEnd="@dimen/status_bar_padding_end" >
+ <com.android.systemui.statusbar.policy.DateView
+ android:id="@+id/date"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="start"
+ android:gravity="center_vertical"
+ android:singleLine="true"
+ android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Date"
+ android:textSize="@dimen/qs_time_collapsed_size"
+ systemui:datePattern="@string/abbrev_wday_month_day_no_year_alarm" />
+
<com.android.systemui.statusbar.phone.StatusIconContainer
android:id="@+id/statusIcons"
android:layout_width="0dp"
diff --git a/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml b/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml
index 7b9cd2aee862..a9fe8620cf48 100644
--- a/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml
+++ b/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml
@@ -41,16 +41,6 @@
android:textAppearance="@style/TextAppearance.StatusBar.Clock"
systemui:showDark="false" />
- <com.android.systemui.statusbar.policy.DateView
- android:id="@+id/date"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:gravity="center_vertical"
- android:singleLine="true"
- android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Date"
- android:textSize="@dimen/qs_time_collapsed_size"
- systemui:datePattern="@string/abbrev_wday_month_day_no_year_alarm" />
-
<android.widget.Space
android:id="@+id/space"
android:layout_width="0dp"
diff --git a/packages/SystemUI/res/layout/smart_reply_view.xml b/packages/SystemUI/res/layout/smart_reply_view.xml
index 9b2dd95005bb..aa5549f35a34 100644
--- a/packages/SystemUI/res/layout/smart_reply_view.xml
+++ b/packages/SystemUI/res/layout/smart_reply_view.xml
@@ -23,7 +23,6 @@
android:id="@+id/smart_reply_view"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
- android:layout_marginStart="12dp"
systemui:spacing="@dimen/smart_reply_button_spacing"
systemui:singleLineButtonPaddingHorizontal="@dimen/smart_reply_button_padding_horizontal_single_line"
systemui:doubleLineButtonPaddingHorizontal="@dimen/smart_reply_button_padding_horizontal_double_line">
diff --git a/packages/SystemUI/res/layout/volume_dnd_icon.xml b/packages/SystemUI/res/layout/volume_dnd_icon.xml
index 215b2300992a..acf9aedd5a3c 100644
--- a/packages/SystemUI/res/layout/volume_dnd_icon.xml
+++ b/packages/SystemUI/res/layout/volume_dnd_icon.xml
@@ -15,16 +15,16 @@
-->
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="14dp"
- android:layout_height="14dp"
- android:layout_marginTop="6dp"
- android:layout_marginRight="6dp"
- android:layout_gravity="right|top">
+ android:layout_width="@dimen/volume_dialog_panel_width"
+ android:layout_height="wrap_content">
<ImageView
android:id="@+id/dnd_icon"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
+ android:layout_width="14dp"
+ android:layout_height="14dp"
+ android:layout_marginTop="6dp"
+ android:layout_marginRight="6dp"
+ android:layout_gravity="right|top"
android:src="@drawable/ic_dnd"
android:tint="?android:attr/textColorTertiary"/>
</FrameLayout>
diff --git a/packages/SystemUI/res/values-h320dp/config.xml b/packages/SystemUI/res/values-h320dp/config.xml
new file mode 100644
index 000000000000..a9c19db0f46f
--- /dev/null
+++ b/packages/SystemUI/res/values-h320dp/config.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (c) 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+-->
+
+<resources>
+ <!-- The number of rows in the QuickSettings -->
+ <integer name="quick_settings_num_rows">2</integer>
+</resources>
diff --git a/packages/SystemUI/res/values-h600dp/config.xml b/packages/SystemUI/res/values-h600dp/config.xml
new file mode 100644
index 000000000000..8616e3e62779
--- /dev/null
+++ b/packages/SystemUI/res/values-h600dp/config.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (c) 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+-->
+
+<resources>
+ <!-- The number of rows in the QuickSettings -->
+ <integer name="quick_settings_num_rows">3</integer>
+</resources>
diff --git a/packages/SystemUI/res/values-sw410dp/config.xml b/packages/SystemUI/res/values-sw410dp/config.xml
index 362c1d214b0e..8ace7bf13573 100644
--- a/packages/SystemUI/res/values-sw410dp/config.xml
+++ b/packages/SystemUI/res/values-sw410dp/config.xml
@@ -20,8 +20,5 @@
<!-- These resources are around just to allow their values to be customized
for different hardware and product builds. -->
<resources>
- <integer name="quick_settings_num_rows">2</integer>
- <integer name="quick_settings_num_rows_portrait">3</integer>
-
<bool name="quick_settings_show_full_alarm">true</bool>
</resources>
diff --git a/packages/SystemUI/res/values-sw540dp/config.xml b/packages/SystemUI/res/values-sw540dp/config.xml
deleted file mode 100644
index e554fc6dd4d1..000000000000
--- a/packages/SystemUI/res/values-sw540dp/config.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2016, 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.
-*/
--->
-
-<!-- These resources are around just to allow their values to be customized
- for different hardware and product builds. -->
-<resources>
- <integer name="quick_settings_num_rows">3</integer>
-</resources>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 7eb08c4c3582..88e3331ff76c 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -112,7 +112,6 @@
<!-- The number of rows in the QuickSettings -->
<integer name="quick_settings_num_rows">1</integer>
- <integer name="quick_settings_num_rows_portrait">2</integer>
<!-- The number of columns that the top level tiles span in the QuickSettings -->
<integer name="quick_settings_user_time_settings_tile_span">1</integer>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index a1e5b0e6e5e2..875000c84260 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -899,8 +899,6 @@
<dimen name="default_gear_space">18dp</dimen>
<dimen name="cell_overlay_padding">18dp</dimen>
- <dimen name="hwui_edge_margin">16dp</dimen>
-
<dimen name="global_actions_panel_width">120dp</dimen>
<dimen name="global_actions_top_padding">120dp</dimen>
@@ -916,7 +914,7 @@
<dimen name="corner_size">8dp</dimen>
<dimen name="top_padding">0dp</dimen>
<dimen name="bottom_padding">48dp</dimen>
- <dimen name="edge_margin">16dp</dimen>
+ <dimen name="edge_margin">8dp</dimen>
<dimen name="rounded_corner_radius">0dp</dimen>
<dimen name="rounded_corner_content_padding">0dp</dimen>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 6c507be44df3..d82b00c316a8 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -59,7 +59,7 @@
<string name="status_bar_latest_events_title">Notifications</string>
<!-- When the battery is low, this is displayed to the user in a dialog. The title of the low battery alert. [CHAR LIMIT=NONE]-->
- <string name="battery_low_title">Battery is low</string>
+ <string name="battery_low_title">Battery may run out soon</string>
<!-- A message that appears when the battery level is getting low in a dialog. This is
appended to the subtitle of the low battery alert. "percentage" is the percentage of battery
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 20d883435aef..804ca2cf1db7 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -173,7 +173,7 @@
<style name="TextAppearance.StatusBar.Expanded.Date">
<item name="android:textSize">@dimen/qs_time_expanded_size</item>
<item name="android:textStyle">normal</item>
- <item name="android:textColor">#ffffffff</item>
+ <item name="android:textColor">?android:attr/textColorPrimary</item>
<item name="android:fontFamily">sans-serif</item>
</style>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java
index 924e85dec37a..7429cb5c19d9 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java
@@ -17,6 +17,7 @@
package com.android.systemui.shared.recents.model;
import static android.content.res.Configuration.ORIENTATION_UNDEFINED;
+import static com.android.systemui.shared.system.WindowManagerWrapper.WINDOWING_MODE_UNDEFINED;
import android.app.ActivityManager.TaskSnapshot;
import android.graphics.Bitmap;
@@ -32,6 +33,7 @@ public class ThumbnailData {
public Rect insets;
public boolean reducedResolution;
public boolean isRealSnapshot;
+ public int windowingMode;
public float scale;
public ThumbnailData() {
@@ -41,6 +43,7 @@ public class ThumbnailData {
reducedResolution = false;
scale = 1f;
isRealSnapshot = true;
+ windowingMode = WINDOWING_MODE_UNDEFINED;
}
public ThumbnailData(TaskSnapshot snapshot) {
@@ -50,5 +53,6 @@ public class ThumbnailData {
reducedResolution = snapshot.isReducedResolution();
scale = snapshot.getScale();
isRealSnapshot = snapshot.isRealSnapshot();
+ windowingMode = snapshot.getWindowingMode();
}
}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java
index 80e226d929cd..9bebb14dabf0 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java
@@ -69,6 +69,14 @@ public class RecentsAnimationControllerCompat {
}
}
+ public void hideCurrentInputMethod() {
+ try {
+ mAnimationController.hideCurrentInputMethod();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to set hide input method", e);
+ }
+ }
+
public void finish(boolean toHome) {
try {
mAnimationController.finish(toHome);
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java
index 9355acf1db1d..07b980ef3f5e 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java
@@ -60,6 +60,16 @@ public class WindowManagerWrapper {
public static final int ACTIVITY_TYPE_STANDARD = WindowConfiguration.ACTIVITY_TYPE_STANDARD;
+ public static final int WINDOWING_MODE_UNDEFINED = WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+ public static final int WINDOWING_MODE_FULLSCREEN =
+ WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+ public static final int WINDOWING_MODE_PINNED = WindowConfiguration.WINDOWING_MODE_PINNED;
+ public static final int WINDOWING_MODE_SPLIT_SCREEN_PRIMARY =
+ WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
+ public static final int WINDOWING_MODE_SPLIT_SCREEN_SECONDARY =
+ WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
+ public static final int WINDOWING_MODE_FREEFORM = WindowConfiguration.WINDOWING_MODE_FREEFORM;
+
private static final WindowManagerWrapper sInstance = new WindowManagerWrapper();
public static WindowManagerWrapper getInstance() {
@@ -104,14 +114,6 @@ public class WindowManagerWrapper {
}
}
- public void endProlongedAnimations() {
- try {
- WindowManagerGlobal.getWindowManagerService().endProlongedAnimations();
- } catch (RemoteException e) {
- Log.w(TAG, "Failed to end prolonged animations: ", e);
- }
- }
-
/**
* Enable or disable haptic feedback on the navigation bar buttons.
*/
@@ -131,4 +133,12 @@ public class WindowManagerWrapper {
Log.w(TAG, "Failed to set shelf height");
}
}
+
+ public void setRecentsVisibility(boolean visible) {
+ try {
+ WindowManagerGlobal.getWindowManagerService().setRecentsVisibility(visible);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed to set recents visibility");
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index 5fce0a6d641c..7d19784aad03 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -21,6 +21,7 @@ import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Process;
+import android.os.ServiceManager;
import android.util.ArrayMap;
import android.view.IWindowManager;
import android.view.WindowManagerGlobal;
@@ -28,6 +29,7 @@ import android.view.WindowManagerGlobal;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.ColorDisplayController;
import com.android.internal.logging.MetricsLogger;
+import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.util.Preconditions;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.systemui.assist.AssistManager;
@@ -320,6 +322,9 @@ public class Dependency extends SystemUI {
mProviders.put(VibratorHelper.class, () -> new VibratorHelper(mContext));
+ mProviders.put(IStatusBarService.class, () -> IStatusBarService.Stub.asInterface(
+ ServiceManager.getService(Context.STATUS_BAR_SERVICE)));
+
// Put all dependencies above here so the factory can override them if it wants.
SystemUIFactory.getInstance().injectDependencies(mProviders, mContext);
}
diff --git a/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java b/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java
index 3bdb247b64c2..98dc3219acc6 100644
--- a/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java
@@ -89,7 +89,7 @@ public class HardwareUiLayout extends FrameLayout implements Tunable {
mEdgeBleed = Settings.Secure.getInt(getContext().getContentResolver(),
EDGE_BLEED, 0) != 0;
mRoundedDivider = Settings.Secure.getInt(getContext().getContentResolver(),
- ROUNDED_DIVIDER, 1) != 0;
+ ROUNDED_DIVIDER, 0) != 0;
updateEdgeMargin(mEdgeBleed ? 0 : getEdgePadding());
mBackground = new HardwareBgDrawable(mRoundedDivider, !mEdgeBleed, getContext());
if (mChild != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
index ac4da73a2a9a..721890f0aee9 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
@@ -20,7 +20,6 @@ import android.app.AlarmManager;
import android.content.Context;
import android.util.ArrayMap;
import android.util.Log;
-import android.view.View;
import android.view.ViewGroup;
import com.android.internal.logging.MetricsLogger;
@@ -43,12 +42,11 @@ import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.NotificationViewHierarchyManager;
import com.android.systemui.statusbar.ScrimView;
-import com.android.systemui.statusbar.SmartReplyLogger;
+import com.android.systemui.statusbar.SmartReplyController;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.phone.KeyguardBouncer;
import com.android.systemui.statusbar.phone.KeyguardDismissUtil;
-import com.android.systemui.statusbar.phone.LightBarController;
import com.android.systemui.statusbar.phone.LockIcon;
import com.android.systemui.statusbar.phone.LockscreenWallpaper;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
@@ -58,7 +56,6 @@ import com.android.systemui.statusbar.phone.ScrimState;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
-import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.SmartReplyConstants;
import java.util.function.Consumer;
@@ -150,6 +147,6 @@ public class SystemUIFactory {
() -> new NotificationViewHierarchyManager(context));
providers.put(NotificationEntryManager.class, () -> new NotificationEntryManager(context));
providers.put(KeyguardDismissUtil.class, KeyguardDismissUtil::new);
- providers.put(SmartReplyLogger.class, () -> new SmartReplyLogger(context));
+ providers.put(SmartReplyController.class, () -> new SmartReplyController());
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/AlwaysOnDisplayPolicy.java b/packages/SystemUI/src/com/android/systemui/doze/AlwaysOnDisplayPolicy.java
index 8515bf2e2968..4fea45c39d5d 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/AlwaysOnDisplayPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/AlwaysOnDisplayPolicy.java
@@ -116,6 +116,7 @@ public class AlwaysOnDisplayPolicy {
private SettingsObserver mSettingsObserver;
public AlwaysOnDisplayPolicy(Context context) {
+ context = context.getApplicationContext();
mContext = context;
mParser = new KeyValueListParser(',');
mSettingsObserver = new SettingsObserver(context.getMainThreadHandler());
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
index 5bf62f638235..e9d78d9b4fdf 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
@@ -61,13 +61,14 @@ public class DozeFactory {
DozeMachine machine = new DozeMachine(wrappedService, config, wakeLock);
machine.setParts(new DozeMachine.Part[]{
- new DozePauser(handler, machine, alarmManager, new AlwaysOnDisplayPolicy(context)),
+ new DozePauser(handler, machine, alarmManager, params.getPolicy()),
new DozeFalsingManagerAdapter(FalsingManager.getInstance(context)),
createDozeTriggers(context, sensorManager, host, alarmManager, config, params,
handler, wakeLock, machine),
createDozeUi(context, host, wakeLock, machine, handler, alarmManager, params),
new DozeScreenState(wrappedService, handler, params, wakeLock),
- createDozeScreenBrightness(context, wrappedService, sensorManager, host, handler),
+ createDozeScreenBrightness(context, wrappedService, sensorManager, host, params,
+ handler),
new DozeWallpaperState(context, params)
});
@@ -76,11 +77,11 @@ public class DozeFactory {
private DozeMachine.Part createDozeScreenBrightness(Context context,
DozeMachine.Service service, SensorManager sensorManager, DozeHost host,
- Handler handler) {
+ DozeParameters params, Handler handler) {
Sensor sensor = DozeSensors.findSensorWithType(sensorManager,
context.getString(R.string.doze_brightness_sensor_type));
return new DozeScreenBrightness(context, service, sensorManager, sensor, host, handler,
- new AlwaysOnDisplayPolicy(context));
+ params.getPolicy());
}
private DozeTriggers createDozeTriggers(Context context, SensorManager sensorManager,
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java
index f72bff5d651e..a0fdb9dc5b90 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java
@@ -21,6 +21,7 @@ import android.util.Log;
import android.view.Display;
import com.android.systemui.statusbar.phone.DozeParameters;
+import com.android.systemui.util.wakelock.SettableWakeLock;
import com.android.systemui.util.wakelock.WakeLock;
/**
@@ -43,15 +44,14 @@ public class DozeScreenState implements DozeMachine.Part {
private final DozeParameters mParameters;
private int mPendingScreenState = Display.STATE_UNKNOWN;
- private boolean mWakeLockHeld;
- private WakeLock mWakeLock;
+ private SettableWakeLock mWakeLock;
public DozeScreenState(DozeMachine.Service service, Handler handler,
DozeParameters parameters, WakeLock wakeLock) {
mDozeService = service;
mHandler = handler;
mParameters = parameters;
- mWakeLock = wakeLock;
+ mWakeLock = new SettableWakeLock(wakeLock);
}
@Override
@@ -64,6 +64,7 @@ public class DozeScreenState implements DozeMachine.Part {
mHandler.removeCallbacks(mApplyPendingScreenState);
applyScreenState(screenState);
+ mWakeLock.setAcquired(false);
return;
}
@@ -84,9 +85,8 @@ public class DozeScreenState implements DozeMachine.Part {
boolean shouldDelayTransition = newState == DozeMachine.State.DOZE_AOD
&& mParameters.shouldControlScreenOff();
- if (!mWakeLockHeld && shouldDelayTransition) {
- mWakeLockHeld = true;
- mWakeLock.acquire();
+ if (shouldDelayTransition) {
+ mWakeLock.setAcquired(true);
}
if (!messagePending) {
@@ -118,10 +118,7 @@ public class DozeScreenState implements DozeMachine.Part {
if (DEBUG) Log.d(TAG, "setDozeScreenState(" + screenState + ")");
mDozeService.setDozeScreenState(screenState);
mPendingScreenState = Display.STATE_UNKNOWN;
- if (mWakeLockHeld) {
- mWakeLockHeld = false;
- mWakeLock.release();
- }
+ mWakeLock.setAcquired(false);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
index aa264190f800..73393047cc45 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
@@ -62,6 +62,7 @@ public class DozeService extends DreamService
public void onDestroy() {
Dependency.get(PluginManager.class).removePluginListener(this);
super.onDestroy();
+ mDozeMachine = null;
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
index f7a258a2c959..be3e322f598f 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
@@ -85,7 +85,7 @@ public class DozeTriggers implements DozeMachine.Part {
mAllowPulseTriggers = allowPulseTriggers;
mDozeSensors = new DozeSensors(context, alarmManager, mSensorManager, dozeParameters,
config, wakeLock, this::onSensor, this::onProximityFar,
- new AlwaysOnDisplayPolicy(context));
+ dozeParameters.getPolicy());
mUiModeManager = mContext.getSystemService(UiModeManager.class);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
index 1fd60239ee98..8cfba2cc53d7 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
@@ -375,11 +375,7 @@ public class PagedTileLayout extends ViewPager implements QSTileLayout {
}
private int getRows() {
- final Resources res = getContext().getResources();
- if (res.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
- return res.getInteger(R.integer.quick_settings_num_rows_portrait);
- }
- return Math.max(1, res.getInteger(R.integer.quick_settings_num_rows));
+ return Math.max(1, getResources().getInteger(R.integer.quick_settings_num_rows));
}
public void setMaxRows(int maxRows) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java
index fd9ddb0fd0ac..b7907a605ca5 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java
@@ -284,6 +284,7 @@ public class QSFooterImpl extends FrameLayout implements QSFooter,
final boolean isDemo = UserManager.isDeviceInDemoMode(mContext);
mMultiUserSwitch.setVisibility(showUserSwitcher(isDemo) ? View.VISIBLE : View.INVISIBLE);
mEdit.setVisibility(isDemo || !mExpanded ? View.INVISIBLE : View.VISIBLE);
+ mSettingsButton.setVisibility(isDemo || !mExpanded ? View.INVISIBLE : View.VISIBLE);
}
private boolean showUserSwitcher(boolean isDemo) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index 5d7dcbbf08d1..f027c4bfb6d0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -98,7 +98,6 @@ public class QuickStatusBarHeader extends RelativeLayout implements
private View mSystemIconsView;
private View mQuickQsStatusIcons;
- private View mDate;
private View mHeaderTextContainerView;
/** View containing the next alarm and ringer mode info. */
private View mStatusContainer;
@@ -148,8 +147,6 @@ public class QuickStatusBarHeader extends RelativeLayout implements
super.onFinishInflate();
mHeaderQsPanel = findViewById(R.id.quick_qs_panel);
- mDate = findViewById(R.id.date);
- mDate.setOnClickListener(this);
mSystemIconsView = findViewById(R.id.quick_status_bar_system_icons);
mQuickQsStatusIcons = findViewById(R.id.quick_qs_status_icons);
StatusIconContainer iconContainer = findViewById(R.id.statusIcons);
@@ -183,6 +180,7 @@ public class QuickStatusBarHeader extends RelativeLayout implements
mBatteryMeterView.setForceShowPercent(true);
mClockView = findViewById(R.id.clock);
mDateView = findViewById(R.id.date);
+ mDateView.setOnClickListener(this);
}
private void updateStatusText() {
@@ -261,7 +259,6 @@ public class QuickStatusBarHeader extends RelativeLayout implements
newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE;
mBatteryMeterView.useWallpaperTextColor(shouldUseWallpaperTextColor);
mClockView.useWallpaperTextColor(shouldUseWallpaperTextColor);
- mDateView.useWallpaperTextColor(shouldUseWallpaperTextColor);
}
@Override
@@ -366,6 +363,7 @@ public class QuickStatusBarHeader extends RelativeLayout implements
@Override
public void onAttachedToWindow() {
+ super.onAttachedToWindow();
Dependency.get(StatusBarIconController.class).addIconGroup(mIconManager);
requestApplyInsets();
}
@@ -414,7 +412,7 @@ public class QuickStatusBarHeader extends RelativeLayout implements
@Override
public void onClick(View v) {
- if(v == mDate){
+ if(v == mDateView){
Dependency.get(ActivityStarter.class).postStartActivityDismissingKeyguard(new Intent(
AlarmClock.ACTION_SHOW_ALARMS),0);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
index 00d6bd0d307f..6bf0793a69cb 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
@@ -98,7 +98,8 @@ public class HotspotTile extends QSTileImpl<AirplaneBooleanState> {
@Override
protected void handleClick() {
final boolean isEnabled = mState.value;
- if (!isEnabled && mAirplaneMode.getValue() != 0) {
+ if (!isEnabled &&
+ (mAirplaneMode.getValue() != 0 || mDataSaverController.isDataSaverEnabled())) {
return;
}
// Immediately enter transient enabling state when turning hotspot on.
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index 95b311ff8e3e..36a12559d6b8 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -835,9 +835,6 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD
@Override
public boolean onPreDraw() {
mRecentsView.getViewTreeObserver().removeOnPreDrawListener(this);
- // We post to make sure that this information is delivered after this traversals is
- // finished.
- mRecentsView.post(() -> WindowManagerWrapper.getInstance().endProlongedAnimations());
return true;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
index e527be1a61f9..5477468505a4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
@@ -81,7 +81,7 @@ public class NotificationContentView extends FrameLayout {
private SmartReplyConstants mSmartReplyConstants;
private SmartReplyView mExpandedSmartReplyView;
- private SmartReplyLogger mSmartReplyLogger;
+ private SmartReplyController mSmartReplyController;
private NotificationViewWrapper mContractedWrapper;
private NotificationViewWrapper mExpandedWrapper;
@@ -154,7 +154,7 @@ public class NotificationContentView extends FrameLayout {
super(context, attrs);
mHybridGroupManager = new HybridGroupManager(getContext(), this);
mSmartReplyConstants = Dependency.get(SmartReplyConstants.class);
- mSmartReplyLogger = Dependency.get(SmartReplyLogger.class);
+ mSmartReplyController = Dependency.get(SmartReplyController.class);
initView();
}
@@ -1359,7 +1359,7 @@ public class NotificationContentView extends FrameLayout {
applySmartReplyView(mExpandedChild, remoteInput, pendingIntent, entry);
if (mExpandedSmartReplyView != null && remoteInput != null
&& remoteInput.getChoices() != null && remoteInput.getChoices().length > 0) {
- mSmartReplyLogger.smartRepliesAdded(entry, remoteInput.getChoices().length);
+ mSmartReplyController.smartRepliesAdded(entry, remoteInput.getChoices().length);
}
}
}
@@ -1377,6 +1377,13 @@ public class NotificationContentView extends FrameLayout {
smartReplyContainer.setVisibility(View.GONE);
return null;
}
+ // If we are showing the spinner we don't want to add the buttons.
+ boolean showingSpinner = entry.notification.getNotification()
+ .extras.getBoolean(Notification.EXTRA_SHOW_REMOTE_INPUT_SPINNER, false);
+ if (showingSpinner) {
+ smartReplyContainer.setVisibility(View.GONE);
+ return null;
+ }
SmartReplyView smartReplyView = null;
if (smartReplyContainer.getChildCount() == 0) {
smartReplyView = SmartReplyView.inflate(mContext, smartReplyContainer);
@@ -1389,7 +1396,7 @@ public class NotificationContentView extends FrameLayout {
}
if (smartReplyView != null) {
smartReplyView.setRepliesFromRemoteInput(remoteInput, pendingIntent,
- mSmartReplyLogger, entry);
+ mSmartReplyController, entry, smartReplyContainer);
smartReplyContainer.setVisibility(View.VISIBLE);
}
return smartReplyView;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationEntryManager.java
index 3a79e70bfc7d..7681530503a9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationEntryManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationEntryManager.java
@@ -474,37 +474,12 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater.
if (FORCE_REMOTE_INPUT_HISTORY
&& shouldKeepForRemoteInput(entry)
&& entry.row != null && !entry.row.isDismissed()) {
- StatusBarNotification sbn = entry.notification;
-
- Notification.Builder b = Notification.Builder
- .recoverBuilder(mContext, sbn.getNotification().clone());
- CharSequence[] oldHistory = sbn.getNotification().extras
- .getCharSequenceArray(Notification.EXTRA_REMOTE_INPUT_HISTORY);
- CharSequence[] newHistory;
- if (oldHistory == null) {
- newHistory = new CharSequence[1];
- } else {
- newHistory = new CharSequence[oldHistory.length + 1];
- System.arraycopy(oldHistory, 0, newHistory, 1, oldHistory.length);
- }
CharSequence remoteInputText = entry.remoteInputText;
if (TextUtils.isEmpty(remoteInputText)) {
remoteInputText = entry.remoteInputTextWhenReset;
}
- newHistory[0] = String.valueOf(remoteInputText);
- b.setRemoteInputHistory(newHistory);
-
- Notification newNotification = b.build();
-
- // Undo any compatibility view inflation
- newNotification.contentView = sbn.getNotification().contentView;
- newNotification.bigContentView = sbn.getNotification().bigContentView;
- newNotification.headsUpContentView = sbn.getNotification().headsUpContentView;
-
- StatusBarNotification newSbn = new StatusBarNotification(sbn.getPackageName(),
- sbn.getOpPkg(),
- sbn.getId(), sbn.getTag(), sbn.getUid(), sbn.getInitialPid(),
- newNotification, sbn.getUser(), sbn.getOverrideGroupKey(), sbn.getPostTime());
+ StatusBarNotification newSbn = rebuildNotificationWithRemoteInput(entry,
+ remoteInputText, false /* showSpinner */);
boolean updated = false;
entry.onRemoteInputInserted();
try {
@@ -554,6 +529,39 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater.
mCallback.onNotificationRemoved(key, old);
}
+ public StatusBarNotification rebuildNotificationWithRemoteInput(NotificationData.Entry entry,
+ CharSequence remoteInputText, boolean showSpinner) {
+ StatusBarNotification sbn = entry.notification;
+
+ Notification.Builder b = Notification.Builder
+ .recoverBuilder(mContext, sbn.getNotification().clone());
+ CharSequence[] oldHistory = sbn.getNotification().extras
+ .getCharSequenceArray(Notification.EXTRA_REMOTE_INPUT_HISTORY);
+ CharSequence[] newHistory;
+ if (oldHistory == null) {
+ newHistory = new CharSequence[1];
+ } else {
+ newHistory = new CharSequence[oldHistory.length + 1];
+ System.arraycopy(oldHistory, 0, newHistory, 1, oldHistory.length);
+ }
+ newHistory[0] = String.valueOf(remoteInputText);
+ b.setRemoteInputHistory(newHistory);
+ b.setShowRemoteInputSpinner(showSpinner);
+
+ Notification newNotification = b.build();
+
+ // Undo any compatibility view inflation
+ newNotification.contentView = sbn.getNotification().contentView;
+ newNotification.bigContentView = sbn.getNotification().bigContentView;
+ newNotification.headsUpContentView = sbn.getNotification().headsUpContentView;
+
+ StatusBarNotification newSbn = new StatusBarNotification(sbn.getPackageName(),
+ sbn.getOpPkg(),
+ sbn.getId(), sbn.getTag(), sbn.getUid(), sbn.getInitialPid(),
+ newNotification, sbn.getUser(), sbn.getOverrideGroupKey(), sbn.getPostTime());
+ return newSbn;
+ }
+
private boolean shouldKeepForRemoteInput(NotificationData.Entry entry) {
if (entry == null) {
return false;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
index abc261e6bbf6..f737a8cec4f0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
@@ -172,27 +172,28 @@ public class NotificationMediaManager implements Dumpable {
}
}
- if (mediaNotification != null) {
- mMediaNotificationKey = mediaNotification.notification.getKey();
- if (DEBUG_MEDIA) {
- Log.v(TAG, "DEBUG_MEDIA: Found new media notification: key="
- + mMediaNotificationKey + " controller=" + mMediaController);
- }
- }
-
if (controller != null && !sameSessions(mMediaController, controller)) {
// We have a new media session
- clearCurrentMediaNotification();
+ clearCurrentMediaNotificationSession();
mMediaController = controller;
mMediaController.registerCallback(mMediaListener);
mMediaMetadata = mMediaController.getMetadata();
if (DEBUG_MEDIA) {
- Log.v(TAG, "DEBUG_MEDIA: insert listener, receive metadata: "
- + mMediaMetadata);
+ Log.v(TAG, "DEBUG_MEDIA: insert listener, found new controller: "
+ + mMediaController + ", receive metadata: " + mMediaMetadata);
}
metaDataChanged = true;
}
+
+ if (mediaNotification != null
+ && !mediaNotification.notification.getKey().equals(mMediaNotificationKey)) {
+ mMediaNotificationKey = mediaNotification.notification.getKey();
+ if (DEBUG_MEDIA) {
+ Log.v(TAG, "DEBUG_MEDIA: Found new media notification: key="
+ + mMediaNotificationKey);
+ }
+ }
}
if (metaDataChanged) {
@@ -203,15 +204,7 @@ public class NotificationMediaManager implements Dumpable {
public void clearCurrentMediaNotification() {
mMediaNotificationKey = null;
- mMediaMetadata = null;
- if (mMediaController != null) {
- if (DEBUG_MEDIA) {
- Log.v(TAG, "DEBUG_MEDIA: Disconnecting from old controller: "
- + mMediaController.getPackageName());
- }
- mMediaController.unregisterCallback(mMediaListener);
- }
- mMediaController = null;
+ clearCurrentMediaNotificationSession();
}
@Override
@@ -265,4 +258,16 @@ public class NotificationMediaManager implements Dumpable {
entry.getExpandedContentView()
.findViewById(com.android.internal.R.id.media_actions) != null;
}
+
+ private void clearCurrentMediaNotificationSession() {
+ mMediaMetadata = null;
+ if (mMediaController != null) {
+ if (DEBUG_MEDIA) {
+ Log.v(TAG, "DEBUG_MEDIA: Disconnecting from old controller: "
+ + mMediaController.getPackageName());
+ }
+ mMediaController.unregisterCallback(mMediaListener);
+ }
+ mMediaController = null;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyLogger.java b/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java
index 75dd77d8ec3a..67da68cd9e92 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyLogger.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java
@@ -15,24 +15,32 @@
*/
package com.android.systemui.statusbar;
-import android.content.Context;
import android.os.RemoteException;
-import android.os.ServiceManager;
+import android.service.notification.StatusBarNotification;
+
import com.android.internal.statusbar.IStatusBarService;
+import com.android.systemui.Dependency;
+
/**
- * Handles reporting when smart replies are added to a notification
+ * Handles when smart replies are added to a notification
* and clicked upon.
*/
-public class SmartReplyLogger {
- protected IStatusBarService mBarService;
+public class SmartReplyController {
+ private IStatusBarService mBarService;
+ private NotificationEntryManager mNotificationEntryManager;
- public SmartReplyLogger(Context context) {
- mBarService = IStatusBarService.Stub.asInterface(
- ServiceManager.getService(Context.STATUS_BAR_SERVICE));
+ public SmartReplyController() {
+ mBarService = Dependency.get(IStatusBarService.class);
+ mNotificationEntryManager = Dependency.get(NotificationEntryManager.class);
}
- public void smartReplySent(NotificationData.Entry entry, int replyIndex) {
+ public void smartReplySent(NotificationData.Entry entry, int replyIndex, CharSequence reply) {
+ StatusBarNotification newSbn =
+ mNotificationEntryManager.rebuildNotificationWithRemoteInput(entry, reply,
+ true /* showSpinner */);
+ mNotificationEntryManager.updateNotification(newSbn, null /* ranking */);
+
try {
mBarService.onNotificationSmartReplySent(entry.notification.getKey(),
replyIndex);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java
index 5f7b638dc872..c9dcc5c688ec 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java
@@ -16,16 +16,25 @@
package com.android.systemui.statusbar.notification;
+import android.app.PendingIntent;
import android.content.Context;
+import android.content.res.ColorStateList;
import android.graphics.Color;
+import android.graphics.PorterDuffColorFilter;
import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
import android.service.notification.StatusBarNotification;
+import android.util.ArraySet;
import android.view.View;
+import android.widget.Button;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
+import com.android.internal.util.NotificationColorUtil;
import com.android.internal.widget.NotificationActionListLayout;
+import com.android.systemui.Dependency;
+import com.android.systemui.UiOffloadThread;
import com.android.systemui.statusbar.CrossFadeHelper;
import com.android.systemui.statusbar.ExpandableNotificationRow;
import com.android.systemui.statusbar.TransformableView;
@@ -43,12 +52,14 @@ public class NotificationTemplateViewWrapper extends NotificationHeaderViewWrapp
private TextView mTitle;
private TextView mText;
protected View mActionsContainer;
- private View mReplyAction;
+ private ImageView mReplyAction;
private Rect mTmpRect = new Rect();
private int mContentHeight;
private int mMinHeightHint;
private NotificationActionListLayout mActions;
+ private ArraySet<PendingIntent> mCancelledPendingIntents = new ArraySet<>();
+ private UiOffloadThread mUiOffloadThread;
protected NotificationTemplateViewWrapper(Context ctx, View view,
ExpandableNotificationRow row) {
@@ -137,6 +148,98 @@ public class NotificationTemplateViewWrapper extends NotificationHeaderViewWrapp
mActionsContainer = mView.findViewById(com.android.internal.R.id.actions_container);
mActions = mView.findViewById(com.android.internal.R.id.actions);
mReplyAction = mView.findViewById(com.android.internal.R.id.reply_icon_action);
+ updatePendingIntentCancellations();
+ }
+
+ private void updatePendingIntentCancellations() {
+ if (mActions != null) {
+ int numActions = mActions.getChildCount();
+ for (int i = 0; i < numActions; i++) {
+ Button action = (Button) mActions.getChildAt(i);
+ performOnPendingIntentCancellation(action, () -> {
+ if (action.isEnabled()) {
+ action.setEnabled(false);
+ // The visual appearance doesn't look disabled enough yet, let's add the
+ // alpha as well. Since Alpha doesn't play nicely right now with the
+ // transformation, we rather blend it manually with the background color.
+ ColorStateList textColors = action.getTextColors();
+ int[] colors = textColors.getColors();
+ int[] newColors = new int[colors.length];
+ float disabledAlpha = mView.getResources().getFloat(
+ com.android.internal.R.dimen.notification_action_disabled_alpha);
+ for (int j = 0; j < colors.length; j++) {
+ int color = colors[j];
+ color = blendColorWithBackground(color, disabledAlpha);
+ newColors[j] = color;
+ }
+ ColorStateList newColorStateList = new ColorStateList(
+ textColors.getStates(), newColors);
+ action.setTextColor(newColorStateList);
+ }
+ });
+ }
+ }
+ if (mReplyAction != null) {
+ performOnPendingIntentCancellation(mReplyAction, () -> {
+ if (mReplyAction != null && mReplyAction.isEnabled()) {
+ mReplyAction.setEnabled(false);
+ // The visual appearance doesn't look disabled enough yet, let's add the
+ // alpha as well. Since Alpha doesn't play nicely right now with the
+ // transformation, we rather blend it manually with the background color.
+ Drawable drawable = mReplyAction.getDrawable().mutate();
+ PorterDuffColorFilter colorFilter =
+ (PorterDuffColorFilter) drawable.getColorFilter();
+ float disabledAlpha = mView.getResources().getFloat(
+ com.android.internal.R.dimen.notification_action_disabled_alpha);
+ if (colorFilter != null) {
+ int color = colorFilter.getColor();
+ color = blendColorWithBackground(color, disabledAlpha);
+ drawable.mutate().setColorFilter(color, colorFilter.getMode());
+ } else {
+ mReplyAction.setAlpha(disabledAlpha);
+ }
+ }
+ });
+ }
+ }
+
+ private int blendColorWithBackground(int color, float alpha) {
+ // alpha doesn't go well for color filters, so let's blend it manually
+ return NotificationColorUtil.compositeColors(Color.argb((int) (alpha * 255),
+ Color.red(color), Color.green(color), Color.blue(color)), resolveBackgroundColor());
+ }
+
+ private void performOnPendingIntentCancellation(View view, Runnable cancellationRunnable) {
+ PendingIntent pendingIntent = (PendingIntent) view.getTag(
+ com.android.internal.R.id.pending_intent_tag);
+ if (pendingIntent == null) {
+ return;
+ }
+ if (mCancelledPendingIntents.contains(pendingIntent)) {
+ cancellationRunnable.run();
+ } else {
+ PendingIntent.CancelListener listener = (PendingIntent intent) -> {
+ mView.post(() -> {
+ mCancelledPendingIntents.add(pendingIntent);
+ cancellationRunnable.run();
+ });
+ };
+ if (mUiOffloadThread == null) {
+ mUiOffloadThread = Dependency.get(UiOffloadThread.class);
+ }
+ mUiOffloadThread.submit(() -> pendingIntent.registerCancelListener(listener));
+ view.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
+ @Override
+ public void onViewAttachedToWindow(View v) {
+ mUiOffloadThread.submit(() -> pendingIntent.registerCancelListener(listener));
+ }
+
+ @Override
+ public void onViewDetachedFromWindow(View v) {
+ mUiOffloadThread.submit(() -> pendingIntent.unregisterCancelListener(listener));
+ }
+ });
+ }
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java
index b09df158072c..93a9947a3c9b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java
@@ -175,6 +175,15 @@ public abstract class NotificationViewWrapper implements TransformableView {
return mRow.isSummaryWithChildren() ? 0 : mBackgroundColor;
}
+ protected int resolveBackgroundColor() {
+ int customBackgroundColor = getCustomBackgroundColor();
+ if (customBackgroundColor != 0) {
+ return customBackgroundColor;
+ }
+ return mView.getContext().getColor(
+ com.android.internal.R.color.notification_material_background_color);
+ }
+
public void setLegacy(boolean legacy) {
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
index 07b79a209b82..d2d9c4c9613b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
@@ -59,9 +59,9 @@ public class DozeParameters implements TunerService.Tunable {
@VisibleForTesting
protected DozeParameters(Context context) {
- mContext = context;
+ mContext = context.getApplicationContext();
mAmbientDisplayConfiguration = new AmbientDisplayConfiguration(mContext);
- mAlwaysOnPolicy = new AlwaysOnDisplayPolicy(context);
+ mAlwaysOnPolicy = new AlwaysOnDisplayPolicy(mContext);
mControlScreenOffAnimation = !getDisplayNeedsBlanking();
mPowerManager = mContext.getSystemService(PowerManager.class);
@@ -243,6 +243,10 @@ public class DozeParameters implements TunerService.Tunable {
mDozeAlwaysOn = mAmbientDisplayConfiguration.alwaysOnEnabled(UserHandle.USER_CURRENT);
}
+ public AlwaysOnDisplayPolicy getPolicy() {
+ return mAlwaysOnPolicy;
+ }
+
/**
* Parses a spec of the form `1,2,3,!5,*`. The resulting object will match numbers that are
* listed, will not match numbers that are listed with a ! prefix, and will match / not match
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java
index 94ac4f6286a2..669a8c83a6c5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java
@@ -82,6 +82,7 @@ public class StatusBarSignalPolicy implements NetworkControllerImpl.SignalCallba
mSlotWifi = mContext.getString(com.android.internal.R.string.status_bar_wifi);
mSlotEthernet = mContext.getString(com.android.internal.R.string.status_bar_ethernet);
mSlotVpn = mContext.getString(com.android.internal.R.string.status_bar_vpn);
+ mActivityEnabled = mContext.getResources().getBoolean(R.bool.config_showActivity);
mIconController = iconController;
mNetworkController = Dependency.get(NetworkController.class);
@@ -108,10 +109,6 @@ public class StatusBarSignalPolicy implements NetworkControllerImpl.SignalCallba
return isBranded ? R.drawable.stat_sys_branded_vpn : R.drawable.stat_sys_vpn_ic;
}
- private void updateActivityEnabled() {
- mActivityEnabled = mContext.getResources().getBoolean(R.bool.config_showActivity);
- }
-
/**
* From SecurityController
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java
index ef630c7205e1..dcce77c7c355 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java
@@ -43,17 +43,6 @@ public class DateView extends TextView {
private String mLastText;
private String mDatePattern;
- /**
- * Whether we should use colors that adapt based on wallpaper/the scrim behind quick settings
- * for text.
- */
- private boolean mUseWallpaperTextColor;
-
- /**
- * Color to be set on this {@link TextView}, when wallpaperTextColor is <b>not</b> utilized.
- */
- private int mNonAdaptedTextColor;
-
private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -74,7 +63,6 @@ public class DateView extends TextView {
public DateView(Context context, AttributeSet attrs) {
super(context, attrs);
- mNonAdaptedTextColor = getCurrentTextColor();
TypedArray a = context.getTheme().obtainStyledAttributes(
attrs,
R.styleable.DateView,
@@ -130,25 +118,6 @@ public class DateView extends TextView {
}
}
- /**
- * Sets whether the date view uses the wallpaperTextColor. If we're not using it, we'll revert
- * back to dark-mode-based/tinted colors.
- *
- * @param shouldUseWallpaperTextColor whether we should use wallpaperTextColor for text color
- */
- public void useWallpaperTextColor(boolean shouldUseWallpaperTextColor) {
- if (shouldUseWallpaperTextColor == mUseWallpaperTextColor) {
- return;
- }
- mUseWallpaperTextColor = shouldUseWallpaperTextColor;
-
- if (mUseWallpaperTextColor) {
- setTextColor(Utils.getColorAttr(mContext, R.attr.wallpaperTextColor));
- } else {
- setTextColor(mNonAdaptedTextColor);
- }
- }
-
public void setDatePattern(String pattern) {
if (TextUtils.equals(pattern, mDatePattern)) {
return;
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 143168210a51..b4fa2e8b16f8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
@@ -26,7 +26,7 @@ import com.android.keyguard.KeyguardHostView.OnDismissAction;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.statusbar.NotificationData;
-import com.android.systemui.statusbar.SmartReplyLogger;
+import com.android.systemui.statusbar.SmartReplyController;
import com.android.systemui.statusbar.notification.NotificationUtils;
import com.android.systemui.statusbar.phone.KeyguardDismissUtil;
@@ -73,6 +73,8 @@ public class SmartReplyView extends ViewGroup {
private PriorityQueue<Button> mCandidateButtonQueueForSqueezing;
+ private View mSmartReplyContainer;
+
public SmartReplyView(Context context, AttributeSet attrs) {
super(context, attrs);
mConstants = Dependency.get(SmartReplyConstants.class);
@@ -133,7 +135,9 @@ public class SmartReplyView extends ViewGroup {
}
public void setRepliesFromRemoteInput(RemoteInput remoteInput, PendingIntent pendingIntent,
- SmartReplyLogger smartReplyLogger, NotificationData.Entry entry) {
+ SmartReplyController smartReplyController, NotificationData.Entry entry,
+ View smartReplyContainer) {
+ mSmartReplyContainer = smartReplyContainer;
removeAllViews();
if (remoteInput != null && pendingIntent != null) {
CharSequence[] choices = remoteInput.getChoices();
@@ -141,7 +145,7 @@ public class SmartReplyView extends ViewGroup {
for (int i = 0; i < choices.length; ++i) {
Button replyButton = inflateReplyButton(
getContext(), this, i, choices[i], remoteInput, pendingIntent,
- smartReplyLogger, entry);
+ smartReplyController, entry);
addView(replyButton);
}
}
@@ -157,7 +161,7 @@ public class SmartReplyView extends ViewGroup {
@VisibleForTesting
Button inflateReplyButton(Context context, ViewGroup root, int replyIndex,
CharSequence choice, RemoteInput remoteInput, PendingIntent pendingIntent,
- SmartReplyLogger smartReplyLogger, NotificationData.Entry entry) {
+ SmartReplyController smartReplyController, NotificationData.Entry entry) {
Button b = (Button) LayoutInflater.from(context).inflate(
R.layout.smart_reply_button, root, false);
b.setText(choice);
@@ -173,7 +177,8 @@ public class SmartReplyView extends ViewGroup {
} catch (PendingIntent.CanceledException e) {
Log.w(TAG, "Unable to send smart reply", e);
}
- smartReplyLogger.smartReplySent(entry, replyIndex);
+ smartReplyController.smartReplySent(entry, replyIndex, b.getText());
+ mSmartReplyContainer.setVisibility(View.GONE);
return false; // do not defer
};
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
index 5a4478f072e0..611d4eb67824 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
@@ -16,21 +16,14 @@
package com.android.systemui.tuner;
import android.app.ActivityManager;
-import android.content.BroadcastReceiver;
-import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
-import android.content.DialogInterface;
-import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.UserInfo;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
-import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
import android.provider.Settings.Secure;
@@ -38,15 +31,12 @@ import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
+import com.android.internal.util.ArrayUtils;
import com.android.systemui.DemoMode;
import com.android.systemui.Dependency;
-import com.android.systemui.R;
-import com.android.systemui.SysUiServiceProvider;
-import com.android.systemui.SystemUI;
-import com.android.systemui.SystemUIApplication;
+import com.android.systemui.qs.QSTileHost;
import com.android.systemui.settings.CurrentUserTracker;
import com.android.systemui.statusbar.phone.StatusBarIconController;
-import com.android.systemui.statusbar.phone.SystemUIDialog;
import com.android.systemui.util.leak.LeakDetector;
import java.util.HashMap;
@@ -58,7 +48,13 @@ public class TunerServiceImpl extends TunerService {
private static final String TUNER_VERSION = "sysui_tuner_version";
- private static final int CURRENT_TUNER_VERSION = 2;
+ private static final int CURRENT_TUNER_VERSION = 4;
+
+ // Things that use the tunable infrastructure but are now real user settings and
+ // shouldn't be reset with tuner settings.
+ private static final String[] RESET_BLACKLIST = new String[] {
+ QSTileHost.TILES_SETTING,
+ };
private final Observer mObserver = new Observer();
// Map of Uris we listen on to their settings keys.
@@ -119,6 +115,11 @@ public class TunerServiceImpl extends TunerService {
if (oldVersion < 2) {
setTunerEnabled(mContext, false);
}
+ // 3 Removed because of a revert.
+ if (oldVersion < 4) {
+ // Delay this so that we can wait for everything to be registered first.
+ new Handler(Dependency.get(Dependency.BG_LOOPER)).postDelayed(() -> clearAll(), 5000);
+ }
setValue(TUNER_VERSION, newVersion);
}
@@ -226,6 +227,9 @@ public class TunerServiceImpl extends TunerService {
mContext.sendBroadcast(intent);
for (String key : mTunableLookup.keySet()) {
+ if (ArrayUtils.contains(RESET_BLACKLIST, key)) {
+ continue;
+ }
Settings.Secure.putString(mContentResolver, key, null);
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java
index 66836365705e..b6039b66e6cb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java
@@ -25,8 +25,10 @@ import static com.android.systemui.doze.DozeMachine.State.INITIALIZED;
import static com.android.systemui.doze.DozeMachine.State.UNINITIALIZED;
import static com.android.systemui.utils.os.FakeHandler.Mode.QUEUEING;
+import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
@@ -41,6 +43,7 @@ import android.view.Display;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.util.wakelock.WakeLock;
+import com.android.systemui.util.wakelock.WakeLockFake;
import com.android.systemui.utils.os.FakeHandler;
import org.junit.Before;
@@ -58,8 +61,7 @@ public class DozeScreenStateTest extends SysuiTestCase {
FakeHandler mHandlerFake;
@Mock
DozeParameters mDozeParameters;
- @Mock
- WakeLock mWakeLock;
+ WakeLockFake mWakeLock;
@Before
public void setUp() throws Exception {
@@ -68,6 +70,7 @@ public class DozeScreenStateTest extends SysuiTestCase {
when(mDozeParameters.getAlwaysOn()).thenReturn(true);
mServiceFake = new DozeServiceFake();
mHandlerFake = new FakeHandler(Looper.getMainLooper());
+ mWakeLock = new WakeLockFake();
mScreen = new DozeScreenState(mServiceFake, mHandlerFake, mDozeParameters, mWakeLock);
}
@@ -158,14 +161,29 @@ public class DozeScreenStateTest extends SysuiTestCase {
mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
mHandlerFake.dispatchQueuedMessages();
- reset(mWakeLock);
mScreen.transitionTo(INITIALIZED, DOZE_AOD);
- verify(mWakeLock).acquire();
- verify(mWakeLock, never()).release();
+ assertThat(mWakeLock.isHeld(), is(true));
mHandlerFake.dispatchQueuedMessages();
- verify(mWakeLock).release();
+ assertThat(mWakeLock.isHeld(), is(false));
+ }
+
+ @Test
+ public void test_releasesWakeLock_abortingLowPowerDelayed() {
+ // Transition to low power mode will be delayed to let
+ // animations play at 60 fps.
+ when(mDozeParameters.shouldControlScreenOff()).thenReturn(true);
+ mHandlerFake.setMode(QUEUEING);
+
+ mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
+ mHandlerFake.dispatchQueuedMessages();
+
+ mScreen.transitionTo(INITIALIZED, DOZE_AOD);
+ assertThat(mWakeLock.isHeld(), is(true));
+ mScreen.transitionTo(DOZE_AOD, FINISH);
+
+ assertThat(mWakeLock.isHeld(), is(false));
}
} \ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationEntryManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationEntryManagerTest.java
index 7cfd7a3d1822..8172626a4b5c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationEntryManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationEntryManagerTest.java
@@ -367,4 +367,44 @@ public class NotificationEntryManagerTest extends SysuiTestCase {
mEntryManager.tagForeground(mEntry.notification);
Assert.assertEquals(0, mEntry.mActiveAppOps.size());
}
+
+ @Test
+ public void testRebuildWithRemoteInput_noExistingInputNoSpinner() {
+ StatusBarNotification newSbn =
+ mEntryManager.rebuildNotificationWithRemoteInput(mEntry, "A Reply", false);
+ CharSequence[] messages = newSbn.getNotification().extras
+ .getCharSequenceArray(Notification.EXTRA_REMOTE_INPUT_HISTORY);
+ Assert.assertEquals(1, messages.length);
+ Assert.assertEquals("A Reply", messages[0]);
+ Assert.assertFalse(newSbn.getNotification().extras
+ .getBoolean(Notification.EXTRA_SHOW_REMOTE_INPUT_SPINNER, false));
+ }
+
+ @Test
+ public void testRebuildWithRemoteInput_noExistingInputWithSpinner() {
+ StatusBarNotification newSbn =
+ mEntryManager.rebuildNotificationWithRemoteInput(mEntry, "A Reply", true);
+ CharSequence[] messages = newSbn.getNotification().extras
+ .getCharSequenceArray(Notification.EXTRA_REMOTE_INPUT_HISTORY);
+ Assert.assertEquals(1, messages.length);
+ Assert.assertEquals("A Reply", messages[0]);
+ Assert.assertTrue(newSbn.getNotification().extras
+ .getBoolean(Notification.EXTRA_SHOW_REMOTE_INPUT_SPINNER, false));
+ }
+
+ @Test
+ public void testRebuildWithRemoteInput_withExistingInput() {
+ // Setup a notification entry with 1 remote input.
+ StatusBarNotification newSbn =
+ mEntryManager.rebuildNotificationWithRemoteInput(mEntry, "A Reply", false);
+ NotificationData.Entry entry = new NotificationData.Entry(newSbn);
+
+ // Try rebuilding to add another reply.
+ newSbn = mEntryManager.rebuildNotificationWithRemoteInput(entry, "Reply 2", true);
+ CharSequence[] messages = newSbn.getNotification().extras
+ .getCharSequenceArray(Notification.EXTRA_REMOTE_INPUT_HISTORY);
+ Assert.assertEquals(2, messages.length);
+ Assert.assertEquals("Reply 2", messages[0]);
+ Assert.assertEquals("A Reply", messages[1]);
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java
new file mode 100644
index 000000000000..84dceae0debf
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.statusbar;
+
+import static org.mockito.ArgumentMatchers.argThat;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.isNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.Notification;
+import android.os.RemoteException;
+import android.service.notification.StatusBarNotification;
+import android.support.test.filters.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+
+import com.android.internal.statusbar.IStatusBarService;
+import com.android.systemui.R;
+import com.android.systemui.SysuiTestCase;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+@SmallTest
+public class SmartReplyControllerTest extends SysuiTestCase {
+ private static final String TEST_NOTIFICATION_KEY = "akey";
+ private static final String TEST_CHOICE_TEXT = "A Reply";
+ private static final int TEST_CHOICE_INDEX = 2;
+ private static final int TEST_CHOICE_COUNT = 4;
+
+ private Notification mNotification;
+ private NotificationData.Entry mEntry;
+
+ @Mock
+ private NotificationEntryManager mNotificationEntryManager;
+ @Mock
+ private IStatusBarService mIStatusBarService;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ mDependency.injectTestDependency(NotificationEntryManager.class,
+ mNotificationEntryManager);
+ mDependency.injectTestDependency(IStatusBarService.class, mIStatusBarService);
+
+ mNotification = new Notification.Builder(mContext, "")
+ .setSmallIcon(R.drawable.ic_person)
+ .setContentTitle("Title")
+ .setContentText("Text").build();
+ StatusBarNotification sbn = mock(StatusBarNotification.class);
+ when(sbn.getNotification()).thenReturn(mNotification);
+ when(sbn.getKey()).thenReturn(TEST_NOTIFICATION_KEY);
+ mEntry = new NotificationData.Entry(sbn);
+ }
+
+ @Test
+ public void testSendSmartReply_updatesRemoteInput() throws RemoteException {
+ StatusBarNotification sbn = mock(StatusBarNotification.class);
+ when(sbn.getKey()).thenReturn(TEST_NOTIFICATION_KEY);
+ when(mNotificationEntryManager.rebuildNotificationWithRemoteInput(
+ argThat(entry -> entry.notification.getKey().equals(TEST_NOTIFICATION_KEY)),
+ eq(TEST_CHOICE_TEXT), eq(true))).thenReturn(sbn);
+
+ SmartReplyController controller = new SmartReplyController();
+ controller.smartReplySent(mEntry, TEST_CHOICE_INDEX, TEST_CHOICE_TEXT);
+
+ // Sending smart reply should make calls to NotificationEntryManager
+ // to update the notification with reply and spinner.
+ verify(mNotificationEntryManager).rebuildNotificationWithRemoteInput(
+ argThat(entry -> entry.notification.getKey().equals(TEST_NOTIFICATION_KEY)),
+ eq(TEST_CHOICE_TEXT), eq(true));
+ verify(mNotificationEntryManager).updateNotification(
+ argThat(sbn2 -> sbn2.getKey().equals(TEST_NOTIFICATION_KEY)), isNull());
+ }
+
+ @Test
+ public void testSendSmartReply_logsToStatusBar() throws RemoteException {
+ StatusBarNotification sbn = mock(StatusBarNotification.class);
+ when(sbn.getKey()).thenReturn(TEST_NOTIFICATION_KEY);
+ when(mNotificationEntryManager.rebuildNotificationWithRemoteInput(
+ argThat(entry -> entry.notification.getKey().equals(TEST_NOTIFICATION_KEY)),
+ eq(TEST_CHOICE_TEXT), eq(true))).thenReturn(sbn);
+
+ SmartReplyController controller = new SmartReplyController();
+ controller.smartReplySent(mEntry, TEST_CHOICE_INDEX, TEST_CHOICE_TEXT);
+
+ // Check we log the result to the status bar service.
+ verify(mIStatusBarService).onNotificationSmartReplySent(TEST_NOTIFICATION_KEY,
+ TEST_CHOICE_INDEX);
+ }
+
+ @Test
+ public void testShowSmartReply_logsToStatusBar() throws RemoteException {
+ SmartReplyController controller = new SmartReplyController();
+ controller.smartRepliesAdded(mEntry, TEST_CHOICE_COUNT);
+
+ // Check we log the result to the status bar service.
+ verify(mIStatusBarService).onNotificationSmartRepliesAdded(TEST_NOTIFICATION_KEY,
+ TEST_CHOICE_COUNT);
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java
index 2bb810665f3a..99c06e62d4bb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java
@@ -23,9 +23,10 @@ import static junit.framework.Assert.assertTrue;
import static junit.framework.Assert.fail;
import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import android.app.Notification;
import android.app.PendingIntent;
import android.app.RemoteInput;
import android.content.Intent;
@@ -44,7 +45,7 @@ import com.android.keyguard.KeyguardHostView.OnDismissAction;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.NotificationData;
-import com.android.systemui.statusbar.SmartReplyLogger;
+import com.android.systemui.statusbar.SmartReplyController;
import com.android.systemui.statusbar.phone.KeyguardDismissUtil;
import java.util.concurrent.atomic.AtomicReference;
@@ -64,19 +65,22 @@ public class SmartReplyViewTest extends SysuiTestCase {
private static final String TEST_ACTION = "com.android.SMART_REPLY_VIEW_ACTION";
private static final String[] TEST_CHOICES = new String[]{"Hello", "What's up?", "I'm here"};
+ private static final String TEST_NOTIFICATION_KEY = "akey";
private static final int WIDTH_SPEC = MeasureSpec.makeMeasureSpec(500, MeasureSpec.EXACTLY);
private static final int HEIGHT_SPEC = MeasureSpec.makeMeasureSpec(400, MeasureSpec.AT_MOST);
private BlockingQueueIntentReceiver mReceiver;
private SmartReplyView mView;
+ private View mContainer;
private int mSingleLinePaddingHorizontal;
private int mDoubleLinePaddingHorizontal;
private int mSpacing;
- @Mock private SmartReplyLogger mLogger;
+ @Mock private SmartReplyController mLogger;
private NotificationData.Entry mEntry;
+ private Notification mNotification;
@Before
public void setUp() {
@@ -86,6 +90,7 @@ public class SmartReplyViewTest extends SysuiTestCase {
mDependency.get(KeyguardDismissUtil.class).setDismissHandler(
(action, cancelAction, afterKeyguardGone) -> action.onDismiss());
+ mContainer = new View(mContext, null);
mView = SmartReplyView.inflate(mContext, null);
@@ -96,9 +101,14 @@ public class SmartReplyViewTest extends SysuiTestCase {
R.dimen.smart_reply_button_padding_horizontal_double_line);
mSpacing = res.getDimensionPixelSize(R.dimen.smart_reply_button_spacing);
- StatusBarNotification notification = mock(StatusBarNotification.class);
- when(notification.getKey()).thenReturn("akey");
- mEntry = new NotificationData.Entry(notification);
+ mNotification = new Notification.Builder(mContext, "")
+ .setSmallIcon(R.drawable.ic_person)
+ .setContentTitle("Title")
+ .setContentText("Text").build();
+ StatusBarNotification sbn = mock(StatusBarNotification.class);
+ when(sbn.getNotification()).thenReturn(mNotification);
+ when(sbn.getKey()).thenReturn(TEST_NOTIFICATION_KEY);
+ mEntry = new NotificationData.Entry(sbn);
}
@After
@@ -155,10 +165,18 @@ public class SmartReplyViewTest extends SysuiTestCase {
}
@Test
- public void testSendSmartReply_LoggerCall() {
+ public void testSendSmartReply_controllerCalled() {
setRepliesFromRemoteInput(TEST_CHOICES);
mView.getChildAt(2).performClick();
- verify(mLogger).smartReplySent(mEntry, 2);
+ verify(mLogger).smartReplySent(mEntry, 2, TEST_CHOICES[2]);
+ }
+
+ @Test
+ public void testSendSmartReply_hidesContainer() {
+ mContainer.setVisibility(View.VISIBLE);
+ setRepliesFromRemoteInput(TEST_CHOICES);
+ mView.getChildAt(0).performClick();
+ assertEquals(View.GONE, mContainer.getVisibility());
}
@Test
@@ -340,7 +358,7 @@ public class SmartReplyViewTest extends SysuiTestCase {
PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0,
new Intent(TEST_ACTION), 0);
RemoteInput input = new RemoteInput.Builder(TEST_RESULT_KEY).setChoices(choices).build();
- mView.setRepliesFromRemoteInput(input, pendingIntent, mLogger, mEntry);
+ mView.setRepliesFromRemoteInput(input, pendingIntent, mLogger, mEntry, mContainer);
}
/** Builds a {@link ViewGroup} whose measures and layout mirror a {@link SmartReplyView}. */
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index cd2e2a4a28d2..e33ef1fc8a6c 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -5697,6 +5697,26 @@ message MetricsEvent {
// internal platform metrics use.
NOTIFICATION_SHADE_COUNT = 1395;
+ // ACTION: DND Settings > What to block
+ // OS: P
+ ACTION_ZEN_SOUND_ONLY = 1396;
+
+ // ACTION: DND Settings > Notifications
+ // OS: P
+ ACTION_ZEN_SOUND_AND_VIS_EFFECTS = 1397;
+
+ // ACTION: DND Settings > Notifications
+ // OS: P
+ ACTION_ZEN_SHOW_CUSTOM = 1398;
+
+ // ACTION: DND Settings > Notifications
+ // OS: P
+ ACTION_ZEN_CUSTOM = 1399;
+
+ // Screen: DND Settings > Notifications
+ // OS: P
+ SETTINGS_ZEN_NOTIFICATIONS = 1400;
+
// ---- End P Constants, all P constants go above this line ----
// Add new aosp constants above this line.
// END OF AOSP CONSTANTS
diff --git a/proto/src/task_snapshot.proto b/proto/src/task_snapshot.proto
index 490a59e770ec..27febefc39dc 100644
--- a/proto/src/task_snapshot.proto
+++ b/proto/src/task_snapshot.proto
@@ -28,4 +28,5 @@
int32 inset_right = 4;
int32 inset_bottom = 5;
bool is_real_snapshot = 6;
+ int32 windowing_mode = 7;
} \ No newline at end of file
diff --git a/services/core/java/com/android/server/BinderCallsStatsService.java b/services/core/java/com/android/server/BinderCallsStatsService.java
index 2ed451610354..ae14dfaa4db1 100644
--- a/services/core/java/com/android/server/BinderCallsStatsService.java
+++ b/services/core/java/com/android/server/BinderCallsStatsService.java
@@ -30,26 +30,58 @@ public class BinderCallsStatsService extends Binder {
private static final String TAG = "BinderCallsStatsService";
- private static final String PERSIST_SYS_BINDER_CPU_STATS_TRACKING
- = "persist.sys.binder_cpu_stats_tracking";
+ private static final String PERSIST_SYS_BINDER_CALLS_DETAILED_TRACKING
+ = "persist.sys.binder_calls_detailed_tracking";
public static void start() {
BinderCallsStatsService service = new BinderCallsStatsService();
ServiceManager.addService("binder_calls_stats", service);
- // TODO Enable by default on eng/userdebug builds
- boolean trackingEnabledDefault = false;
- boolean trackingEnabled = SystemProperties.getBoolean(PERSIST_SYS_BINDER_CPU_STATS_TRACKING,
- trackingEnabledDefault);
+ boolean detailedTrackingEnabled = SystemProperties.getBoolean(
+ PERSIST_SYS_BINDER_CALLS_DETAILED_TRACKING, false);
- if (trackingEnabled) {
+ if (detailedTrackingEnabled) {
Slog.i(TAG, "Enabled CPU usage tracking for binder calls. Controlled by "
- + PERSIST_SYS_BINDER_CPU_STATS_TRACKING);
- BinderCallsStats.getInstance().setTrackingEnabled(true);
+ + PERSIST_SYS_BINDER_CALLS_DETAILED_TRACKING
+ + " or via dumpsys binder_calls_stats --enable-detailed-tracking");
+ BinderCallsStats.getInstance().setDetailedTracking(true);
}
}
+ public static void reset() {
+ Slog.i(TAG, "Resetting stats");
+ BinderCallsStats.getInstance().reset();
+ }
+
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ if (args != null) {
+ for (final String arg : args) {
+ if ("--reset".equals(arg)) {
+ reset();
+ pw.println("binder_calls_stats reset.");
+ return;
+ } else if ("--enable-detailed-tracking".equals(arg)) {
+ SystemProperties.set(PERSIST_SYS_BINDER_CALLS_DETAILED_TRACKING, "1");
+ BinderCallsStats.getInstance().setDetailedTracking(true);
+ pw.println("Detailed tracking enabled");
+ return;
+ } else if ("--disable-detailed-tracking".equals(arg)) {
+ SystemProperties.set(PERSIST_SYS_BINDER_CALLS_DETAILED_TRACKING, "");
+ BinderCallsStats.getInstance().setDetailedTracking(false);
+ pw.println("Detailed tracking disabled");
+ return;
+ } else if ("-h".equals(arg)) {
+ pw.println("binder_calls_stats commands:");
+ pw.println(" --reset: Reset stats");
+ pw.println(" --enable-detailed-tracking: Enables detailed tracking");
+ pw.println(" --disable-detailed-tracking: Disables detailed tracking");
+ return;
+ } else {
+ pw.println("Unknown option: " + arg);
+ return;
+ }
+ }
+ }
BinderCallsStats.getInstance().dump(pw);
}
}
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 5afb0a622208..9994462531b2 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -238,8 +238,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
private KeyStore mKeyStore;
+ @VisibleForTesting
@GuardedBy("mVpns")
- private final SparseArray<Vpn> mVpns = new SparseArray<Vpn>();
+ protected final SparseArray<Vpn> mVpns = new SparseArray<Vpn>();
// TODO: investigate if mLockdownEnabled can be removed and replaced everywhere by
// a direct call to LockdownVpnTracker.isEnabled().
@@ -929,6 +930,15 @@ public class ConnectivityService extends IConnectivityManager.Stub
deps);
}
+ private static NetworkCapabilities createDefaultNetworkCapabilitiesForUid(int uid) {
+ final NetworkCapabilities netCap = new NetworkCapabilities();
+ netCap.addCapability(NET_CAPABILITY_INTERNET);
+ netCap.addCapability(NET_CAPABILITY_NOT_RESTRICTED);
+ netCap.removeCapability(NET_CAPABILITY_NOT_VPN);
+ netCap.setSingleUid(uid);
+ return netCap;
+ }
+
private NetworkRequest createDefaultInternetRequestForTransport(
int transportType, NetworkRequest.Type type) {
NetworkCapabilities netCap = new NetworkCapabilities();
@@ -1181,12 +1191,20 @@ public class ConnectivityService extends IConnectivityManager.Stub
int vpnNetId = NETID_UNSET;
synchronized (mVpns) {
final Vpn vpn = mVpns.get(user);
+ // TODO : now that capabilities contain the UID, the appliesToUid test should
+ // be removed as the satisfying test below should be enough.
if (vpn != null && vpn.appliesToUid(uid)) vpnNetId = vpn.getNetId();
}
NetworkAgentInfo nai;
if (vpnNetId != NETID_UNSET) {
nai = getNetworkAgentInfoForNetId(vpnNetId);
- if (nai != null) return nai.network;
+ if (nai != null) {
+ final NetworkCapabilities requiredCaps =
+ createDefaultNetworkCapabilitiesForUid(uid);
+ if (requiredCaps.satisfiedByNetworkCapabilities(nai.networkCapabilities)) {
+ return nai.network;
+ }
+ }
}
nai = getDefaultNetwork();
if (nai != null
@@ -1401,8 +1419,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
private NetworkCapabilities networkCapabilitiesRestrictedForCallerPermissions(
NetworkCapabilities nc, int callerPid, int callerUid) {
final NetworkCapabilities newNc = new NetworkCapabilities(nc);
- if (!checkSettingsPermission(callerPid, callerUid)) newNc.setUids(null);
- if (!checkSettingsPermission(callerPid, callerUid)) newNc.setSSID(null);
+ if (!checkSettingsPermission(callerPid, callerUid)) {
+ newNc.setUids(null);
+ newNc.setSSID(null);
+ }
return newNc;
}
@@ -4304,8 +4324,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
// the default network request. This allows callers to keep track of
// the system default network.
if (type == NetworkRequest.Type.TRACK_DEFAULT) {
- networkCapabilities = new NetworkCapabilities(mDefaultRequest.networkCapabilities);
- networkCapabilities.removeCapability(NET_CAPABILITY_NOT_VPN);
+ networkCapabilities = createDefaultNetworkCapabilitiesForUid(Binder.getCallingUid());
enforceAccessPermission();
} else {
networkCapabilities = new NetworkCapabilities(networkCapabilities);
@@ -4562,7 +4581,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
// Note: if mDefaultRequest is changed, NetworkMonitor needs to be updated.
private final NetworkRequest mDefaultRequest;
-
+
// Request used to optionally keep mobile data active even when higher
// priority networks like Wi-Fi are active.
private final NetworkRequest mDefaultMobileDataRequest;
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java
index 2b3c5852ac8b..aaa42e575ae8 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/DeviceIdleController.java
@@ -327,13 +327,16 @@ public class DeviceIdleController extends SystemService
private final int[] mEventCmds = new int[EVENT_BUFFER_SIZE];
private final long[] mEventTimes = new long[EVENT_BUFFER_SIZE];
+ private final String[] mEventReasons = new String[EVENT_BUFFER_SIZE];
- private void addEvent(int cmd) {
+ private void addEvent(int cmd, String reason) {
if (mEventCmds[0] != cmd) {
System.arraycopy(mEventCmds, 0, mEventCmds, 1, EVENT_BUFFER_SIZE - 1);
System.arraycopy(mEventTimes, 0, mEventTimes, 1, EVENT_BUFFER_SIZE - 1);
+ System.arraycopy(mEventReasons, 0, mEventReasons, 1, EVENT_BUFFER_SIZE - 1);
mEventCmds[0] = cmd;
mEventTimes[0] = SystemClock.elapsedRealtime();
+ mEventReasons[0] = reason;
}
}
@@ -2061,7 +2064,7 @@ public class DeviceIdleController extends SystemService
mMaintenanceStartTime = 0;
resetIdleManagementLocked();
resetLightIdleManagementLocked();
- addEvent(EVENT_NORMAL);
+ addEvent(EVENT_NORMAL, activeReason);
}
}
@@ -2158,7 +2161,7 @@ public class DeviceIdleController extends SystemService
if (DEBUG) Slog.d(TAG, "Moved to LIGHT_STATE_IDLE.");
mLightState = LIGHT_STATE_IDLE;
EventLogTags.writeDeviceIdleLight(mLightState, reason);
- addEvent(EVENT_LIGHT_IDLE);
+ addEvent(EVENT_LIGHT_IDLE, null);
mGoingIdleWakeLock.acquire();
mHandler.sendEmptyMessage(MSG_REPORT_IDLE_ON_LIGHT);
break;
@@ -2179,7 +2182,7 @@ public class DeviceIdleController extends SystemService
"Moved from LIGHT_STATE_IDLE to LIGHT_STATE_IDLE_MAINTENANCE.");
mLightState = LIGHT_STATE_IDLE_MAINTENANCE;
EventLogTags.writeDeviceIdleLight(mLightState, reason);
- addEvent(EVENT_LIGHT_MAINTENANCE);
+ addEvent(EVENT_LIGHT_MAINTENANCE, null);
mHandler.sendEmptyMessage(MSG_REPORT_IDLE_OFF);
} else {
// We'd like to do maintenance, but currently don't have network
@@ -2284,7 +2287,7 @@ public class DeviceIdleController extends SystemService
cancelLightAlarmLocked();
}
EventLogTags.writeDeviceIdle(mState, reason);
- addEvent(EVENT_DEEP_IDLE);
+ addEvent(EVENT_DEEP_IDLE, null);
mGoingIdleWakeLock.acquire();
mHandler.sendEmptyMessage(MSG_REPORT_IDLE_ON);
break;
@@ -2303,7 +2306,7 @@ public class DeviceIdleController extends SystemService
}
mState = STATE_IDLE_MAINTENANCE;
EventLogTags.writeDeviceIdle(mState, reason);
- addEvent(EVENT_DEEP_MAINTENANCE);
+ addEvent(EVENT_DEEP_MAINTENANCE, null);
mHandler.sendEmptyMessage(MSG_REPORT_IDLE_OFF);
break;
}
@@ -2414,7 +2417,7 @@ public class DeviceIdleController extends SystemService
mCurIdleBudget = 0;
mMaintenanceStartTime = 0;
EventLogTags.writeDeviceIdle(mState, type);
- addEvent(EVENT_NORMAL);
+ addEvent(EVENT_NORMAL, type);
becomeInactive = true;
}
if (mLightState == LIGHT_STATE_OVERRIDE) {
@@ -3273,8 +3276,14 @@ public class DeviceIdleController extends SystemService
pw.print(" ");
pw.print(label);
pw.print(": ");
- TimeUtils.formatDuration(mEventTimes[i], now, pw);;
+ TimeUtils.formatDuration(mEventTimes[i], now, pw);
+ if (mEventReasons[i] != null) {
+ pw.print(" (");
+ pw.print(mEventReasons[i]);
+ pw.print(")");
+ }
pw.println();
+
}
}
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index 309a75a6a6de..7b02a4fb3fd8 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -86,6 +86,7 @@ import com.android.server.location.ActivityRecognitionProxy;
import com.android.server.location.GeocoderProxy;
import com.android.server.location.GeofenceManager;
import com.android.server.location.GeofenceProxy;
+import com.android.server.location.GnssBatchingProvider;
import com.android.server.location.GnssLocationProvider;
import com.android.server.location.GnssMeasurementsProvider;
import com.android.server.location.GnssNavigationMessageProvider;
@@ -244,7 +245,7 @@ public class LocationManagerService extends ILocationManager.Stub {
private GnssLocationProvider.GnssMetricsProvider mGnssMetricsProvider;
- private GnssLocationProvider.GnssBatchingProvider mGnssBatchingProvider;
+ private GnssBatchingProvider mGnssBatchingProvider;
private IBatchedLocationCallback mGnssBatchingCallback;
private LinkedCallback mGnssBatchingDeathCallback;
private boolean mGnssBatchingInProgress = false;
@@ -1176,7 +1177,7 @@ public class LocationManagerService extends ILocationManager.Stub {
"Location Hardware permission not granted to access hardware batching");
if (hasGnssPermissions(packageName) && mGnssBatchingProvider != null) {
- return mGnssBatchingProvider.getSize();
+ return mGnssBatchingProvider.getBatchSize();
} else {
return 0;
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index c9dbd45c5be4..6cd6a31c0f99 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -433,6 +433,7 @@ import com.android.internal.util.Preconditions;
import com.android.server.AlarmManagerInternal;
import com.android.server.AppOpsService;
import com.android.server.AttributeCache;
+import com.android.server.BinderCallsStatsService;
import com.android.server.DeviceIdleController;
import com.android.server.IntentResolver;
import com.android.server.IoThread;
@@ -3413,6 +3414,11 @@ public class ActivityManagerService extends IActivityManager.Stub
}
@Override
+ public void batteryStatsReset() {
+ BinderCallsStatsService.reset();
+ }
+
+ @Override
public void batterySendBroadcast(Intent intent) {
synchronized (this) {
broadcastIntentLocked(null, null, intent, null, null, 0, null, null, null,
@@ -8476,8 +8482,19 @@ public class ActivityManagerService extends IActivityManager.Stub
if (!(sender instanceof PendingIntentRecord)) {
return;
}
+ boolean isCancelled;
synchronized(this) {
- ((PendingIntentRecord)sender).registerCancelListenerLocked(receiver);
+ PendingIntentRecord pendingIntent = (PendingIntentRecord) sender;
+ isCancelled = pendingIntent.canceled;
+ if (!isCancelled) {
+ pendingIntent.registerCancelListenerLocked(receiver);
+ }
+ }
+ if (isCancelled) {
+ try {
+ receiver.send(Activity.RESULT_CANCELED, null);
+ } catch (RemoteException e) {
+ }
}
}
@@ -14542,6 +14559,10 @@ public class ActivityManagerService extends IActivityManager.Stub
}
void setRunningRemoteAnimation(int pid, boolean runningRemoteAnimation) {
+ if (pid == Process.myPid()) {
+ Slog.wtf(TAG, "system can't run remote animation");
+ return;
+ }
synchronized (ActivityManagerService.this) {
final ProcessRecord pr;
synchronized (mPidsSelfLocked) {
@@ -21961,54 +21982,6 @@ public class ActivityManagerService extends IActivityManager.Stub
// INSTRUMENTATION
// =========================================================
- private static String[] HIDDENAPI_EXEMPT_PACKAGES = {
- "com.android.bluetooth.tests",
- "com.android.managedprovisioning.tests",
- "com.android.frameworks.coretests",
- "com.android.frameworks.coretests.binderproxycountingtestapp",
- "com.android.frameworks.coretests.binderproxycountingtestservice",
- "com.android.frameworks.tests.net",
- "com.android.frameworks.tests.uiservices",
- "com.android.coretests.apps.bstatstestapp",
- "com.android.servicestests.apps.conntestapp",
- "com.android.frameworks.servicestests",
- "com.android.frameworks.utiltests",
- "com.android.mtp.tests",
- "android.mtp",
- "com.android.documentsui.tests",
- "com.android.shell.tests",
- "com.android.systemui.tests",
- "com.android.testables",
- "android.net.wifi.test",
- "com.android.server.wifi.test",
- "com.android.frameworks.telephonytests",
- "com.android.providers.contacts.tests",
- "com.android.providers.contacts.tests2",
- "com.android.settings.tests.unit",
- "com.android.server.telecom.tests",
- "com.android.vcard.tests",
- "com.android.providers.blockednumber.tests",
- "android.settings.functional",
- "com.android.notification.functional",
- "com.android.frameworks.dexloggertest",
- "com.android.server.usb",
- "com.android.providers.downloads.tests",
- "com.android.emergency.tests.unit",
- "com.android.providers.calendar.tests",
- "com.android.settingslib",
- "com.android.rs.test",
- "com.android.printspooler.outofprocess.tests",
- "com.android.cellbroadcastreceiver.tests.unit",
- "com.android.providers.telephony.tests",
- "com.android.carrierconfig.tests",
- "com.android.phone.tests",
- "com.android.service.ims.presence.tests",
- "com.android.providers.setting.test",
- "com.android.frameworks.locationtests",
- "com.android.frameworks.coretests.privacy",
- "com.android.settings.ui",
- };
-
public boolean startInstrumentation(ComponentName className,
String profileFile, int flags, Bundle arguments,
IInstrumentationWatcher watcher, IUiAutomationConnection uiAutomationConnection,
@@ -22096,12 +22069,6 @@ public class ActivityManagerService extends IActivityManager.Stub
mUsageStatsService.reportEvent(ii.targetPackage, userId,
UsageEvents.Event.SYSTEM_INTERACTION);
}
- // TODO: Temporary whitelist of packages which need to be exempt from hidden API
- // checks. Remove this as soon as the testing infrastructure allows to set
- // the flag in AndroidTest.xml.
- if (Arrays.asList(HIDDENAPI_EXEMPT_PACKAGES).contains(ai.packageName)) {
- disableHiddenApiChecks = true;
- }
ProcessRecord app = addAppLocked(ai, defProcess, false, disableHiddenApiChecks,
abiOverride);
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 95bae2eb24a8..9fb3e11446ce 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -3802,7 +3802,11 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
// and the resumed activity is not yet visible, then hold off on
// finishing until the resumed one becomes visible.
- final ActivityRecord next = mStackSupervisor.topRunningActivityLocked();
+ // The activity that we are finishing may be over the lock screen. In this case, we do not
+ // want to consider activities that cannot be shown on the lock screen as running and should
+ // proceed with finishing the activity if there is no valid next top running activity.
+ final ActivityRecord next = mStackSupervisor.topRunningActivityLocked(
+ true /* considerKeyguardState */);
if (mode == FINISH_AFTER_VISIBLE && (r.visible || r.nowVisible)
&& next != null && !next.nowVisible) {
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 0dc2445109ea..e5565dccc70e 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -1210,6 +1210,18 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
}
ActivityRecord topRunningActivityLocked() {
+ return topRunningActivityLocked(false /* considerKeyguardState */);
+ }
+
+ /**
+ * Returns the top running activity in the focused stack. In the case the focused stack has no
+ * such activity, the next focusable stack on top of a display is returned.
+ * @param considerKeyguardState Indicates whether the locked state should be considered. if
+ * {@code true} and the keyguard is locked, only activities that
+ * can be shown on top of the keyguard will be considered.
+ * @return The top running activity. {@code null} if none is available.
+ */
+ ActivityRecord topRunningActivityLocked(boolean considerKeyguardState) {
final ActivityStack focusedStack = mFocusedStack;
ActivityRecord r = focusedStack.topRunningActivityLocked();
if (r != null) {
@@ -1228,16 +1240,33 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
if (display == null) {
continue;
}
- for (int j = display.getChildCount() - 1; j >= 0; --j) {
- final ActivityStack stack = display.getChildAt(j);
- if (stack != focusedStack && stack.isTopStackOnDisplay() && stack.isFocusable()) {
- r = stack.topRunningActivityLocked();
- if (r != null) {
- return r;
- }
- }
+
+ // TODO: We probably want to consider the top fullscreen stack as we could have a pinned
+ // stack on top.
+ final ActivityStack topStack = display.getTopStack();
+
+ // Only consider focusable top stacks other than the current focused one.
+ if (topStack == null || !topStack.isFocusable() || topStack == focusedStack) {
+ continue;
+ }
+
+ final ActivityRecord topActivity = topStack.topRunningActivityLocked();
+
+ // Skip if no top activity.
+ if (topActivity == null) {
+ continue;
+ }
+
+ final boolean keyguardLocked = getKeyguardController().isKeyguardLocked();
+
+ // This activity can be considered the top running activity if we are not
+ // considering the locked state, the keyguard isn't locked, or we can show when
+ // locked.
+ if (!considerKeyguardState || !keyguardLocked || topActivity.canShowWhenLocked()) {
+ return topActivity;
}
}
+
return null;
}
diff --git a/services/core/java/com/android/server/am/ActivityStartController.java b/services/core/java/com/android/server/am/ActivityStartController.java
index 6c4554646e6e..31ccf3530fb9 100644
--- a/services/core/java/com/android/server/am/ActivityStartController.java
+++ b/services/core/java/com/android/server/am/ActivityStartController.java
@@ -350,7 +350,8 @@ public class ActivityStartController {
"FLAG_CANT_SAVE_STATE not supported here");
}
- final SafeActivityOptions checkedOptions = i == intents.length - 1
+ final boolean top = i == intents.length - 1;
+ final SafeActivityOptions checkedOptions = top
? options
: null;
final int res = obtainStarter(intent, reason)
@@ -367,6 +368,10 @@ public class ActivityStartController {
.setActivityOptions(checkedOptions)
.setComponentSpecified(componentSpecified)
.setOutActivity(outActivity)
+
+ // Top activity decides on animation being run, so we allow only for the
+ // top one as otherwise an activity below might consume it.
+ .setAllowPendingRemoteAnimationRegistryLookup(top /* allowLookup*/)
.execute();
if (res < 0) {
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index fb89e6711a18..7ff7d9a9b6c4 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -314,6 +314,12 @@ class ActivityStarter {
WaitResult waitResult;
/**
+ * If set to {@code true}, allows this activity start to look into
+ * {@link PendingRemoteAnimationRegistry}
+ */
+ boolean allowPendingRemoteAnimationRegistryLookup;
+
+ /**
* Indicates that we should wait for the result of the start request. This flag is set when
* {@link ActivityStarter#setMayWait(int)} is called.
* {@see ActivityStarter#startActivityMayWait}.
@@ -360,6 +366,7 @@ class ActivityStarter {
waitResult = null;
mayWait = false;
avoidMoveToFront = false;
+ allowPendingRemoteAnimationRegistryLookup = true;
}
/**
@@ -395,6 +402,8 @@ class ActivityStarter {
waitResult = request.waitResult;
mayWait = request.mayWait;
avoidMoveToFront = request.avoidMoveToFront;
+ allowPendingRemoteAnimationRegistryLookup
+ = request.allowPendingRemoteAnimationRegistryLookup;
}
}
@@ -477,7 +486,8 @@ class ActivityStarter {
mRequest.resultWho, mRequest.requestCode, mRequest.startFlags,
mRequest.profilerInfo, mRequest.waitResult, mRequest.globalConfig,
mRequest.activityOptions, mRequest.ignoreTargetSecurity, mRequest.userId,
- mRequest.inTask, mRequest.reason);
+ mRequest.inTask, mRequest.reason,
+ mRequest.allowPendingRemoteAnimationRegistryLookup);
} else {
return startActivity(mRequest.caller, mRequest.intent, mRequest.ephemeralIntent,
mRequest.resolvedType, mRequest.activityInfo, mRequest.resolveInfo,
@@ -486,7 +496,8 @@ class ActivityStarter {
mRequest.callingUid, mRequest.callingPackage, mRequest.realCallingPid,
mRequest.realCallingUid, mRequest.startFlags, mRequest.activityOptions,
mRequest.ignoreTargetSecurity, mRequest.componentSpecified,
- mRequest.outActivity, mRequest.inTask, mRequest.reason);
+ mRequest.outActivity, mRequest.inTask, mRequest.reason,
+ mRequest.allowPendingRemoteAnimationRegistryLookup);
}
} finally {
onExecutionComplete();
@@ -517,7 +528,8 @@ class ActivityStarter {
IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
SafeActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
- ActivityRecord[] outActivity, TaskRecord inTask, String reason) {
+ ActivityRecord[] outActivity, TaskRecord inTask, String reason,
+ boolean allowPendingRemoteAnimationRegistryLookup) {
if (TextUtils.isEmpty(reason)) {
throw new IllegalArgumentException("Need to specify a reason.");
@@ -530,7 +542,7 @@ class ActivityStarter {
aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode,
callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
options, ignoreTargetSecurity, componentSpecified, mLastStartActivityRecord,
- inTask);
+ inTask, allowPendingRemoteAnimationRegistryLookup);
if (outActivity != null) {
// mLastStartActivityRecord[0] is set in the call to startActivity above.
@@ -560,7 +572,7 @@ class ActivityStarter {
String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
SafeActivityOptions options,
boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity,
- TaskRecord inTask) {
+ TaskRecord inTask, boolean allowPendingRemoteAnimationRegistryLookup) {
int err = ActivityManager.START_SUCCESS;
// Pull the optional Ephemeral Installer-only bundle out of the options early.
final Bundle verificationBundle
@@ -709,8 +721,11 @@ class ActivityStarter {
ActivityOptions checkedOptions = options != null
? options.getOptions(intent, aInfo, callerApp, mSupervisor)
: null;
- checkedOptions = mService.getActivityStartController().getPendingRemoteAnimationRegistry()
- .overrideOptionsIfNeeded(callingPackage, checkedOptions);
+ if (allowPendingRemoteAnimationRegistryLookup) {
+ checkedOptions = mService.getActivityStartController()
+ .getPendingRemoteAnimationRegistry()
+ .overrideOptionsIfNeeded(callingPackage, checkedOptions);
+ }
if (mService.mController != null) {
try {
// The Intent we give to the watcher has the extra data
@@ -928,7 +943,8 @@ class ActivityStarter {
IBinder resultTo, String resultWho, int requestCode, int startFlags,
ProfilerInfo profilerInfo, WaitResult outResult,
Configuration globalConfig, SafeActivityOptions options, boolean ignoreTargetSecurity,
- int userId, TaskRecord inTask, String reason) {
+ int userId, TaskRecord inTask, String reason,
+ boolean allowPendingRemoteAnimationRegistryLookup) {
// Refuse possible leaked file descriptors
if (intent != null && intent.hasFileDescriptors()) {
throw new IllegalArgumentException("File descriptors passed in Intent");
@@ -1070,7 +1086,8 @@ class ActivityStarter {
int res = startActivity(caller, intent, ephemeralIntent, resolvedType, aInfo, rInfo,
voiceSession, voiceInteractor, resultTo, resultWho, requestCode, callingPid,
callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, options,
- ignoreTargetSecurity, componentSpecified, outRecord, inTask, reason);
+ ignoreTargetSecurity, componentSpecified, outRecord, inTask, reason,
+ allowPendingRemoteAnimationRegistryLookup);
Binder.restoreCallingIdentity(origId);
@@ -2567,6 +2584,11 @@ class ActivityStarter {
return this;
}
+ ActivityStarter setAllowPendingRemoteAnimationRegistryLookup(boolean allowLookup) {
+ mRequest.allowPendingRemoteAnimationRegistryLookup = allowLookup;
+ return this;
+ }
+
void dump(PrintWriter pw, String prefix) {
prefix = prefix + " ";
pw.print(prefix);
diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java
index 35b7f2b4fe86..a6dafbb1db36 100644
--- a/services/core/java/com/android/server/am/AppErrors.java
+++ b/services/core/java/com/android/server/am/AppErrors.java
@@ -476,7 +476,8 @@ class AppErrors {
} catch (IllegalArgumentException e) {
// Hmm, that didn't work, app might have crashed before creating a
// recents entry. Let's see if we have a safe-to-restart intent.
- final Set<String> cats = task.intent.getCategories();
+ final Set<String> cats = task.intent != null
+ ? task.intent.getCategories() : null;
if (cats != null && cats.contains(Intent.CATEGORY_LAUNCHER)) {
mService.getActivityStartController().startActivityInPackage(
task.mCallingUid, callingPid, callingUid, task.mCallingPackage,
diff --git a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
index 2291e44d9e06..87194bc8e771 100644
--- a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
+++ b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
@@ -117,6 +117,13 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync {
private WifiActivityEnergyInfo mLastInfo =
new WifiActivityEnergyInfo(0, 0, 0, new long[]{0}, 0, 0, 0, 0);
+ /**
+ * Timestamp at which all external stats were last collected in
+ * {@link SystemClock#elapsedRealtime()} time base.
+ */
+ @GuardedBy("this")
+ private long mLastCollectionTimeStamp;
+
BatteryExternalStatsWorker(Context context, BatteryStatsImpl stats) {
mContext = context;
mStats = stats;
@@ -259,6 +266,12 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync {
return mCurrentFuture;
}
+ long getLastCollectionTimeStamp() {
+ synchronized (this) {
+ return mLastCollectionTimeStamp;
+ }
+ }
+
private final Runnable mSyncTask = new Runnable() {
@Override
public void run() {
@@ -312,6 +325,10 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync {
} catch (Exception e) {
Slog.wtf(TAG, "Error updating external stats: ", e);
}
+
+ synchronized (BatteryExternalStatsWorker.this) {
+ mLastCollectionTimeStamp = SystemClock.elapsedRealtime();
+ }
}
};
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 9c2b1a5d17aa..0c328a89ef84 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -1541,7 +1541,9 @@ public final class BatteryStatsService extends IBatteryStats.Stub
}
long ident = Binder.clearCallingIdentity();
try {
- syncStats("get-health-stats-for-uids", BatteryExternalStatsWorker.UPDATE_ALL);
+ if (shouldCollectExternalStats()) {
+ syncStats("get-health-stats-for-uids", BatteryExternalStatsWorker.UPDATE_ALL);
+ }
synchronized (mStats) {
return getHealthStatsForUidLocked(requestUid);
}
@@ -1565,7 +1567,9 @@ public final class BatteryStatsService extends IBatteryStats.Stub
long ident = Binder.clearCallingIdentity();
int i=-1;
try {
- syncStats("get-health-stats-for-uids", BatteryExternalStatsWorker.UPDATE_ALL);
+ if (shouldCollectExternalStats()) {
+ syncStats("get-health-stats-for-uids", BatteryExternalStatsWorker.UPDATE_ALL);
+ }
synchronized (mStats) {
final int N = requestUids.length;
final HealthStatsParceler[] results = new HealthStatsParceler[N];
@@ -1583,6 +1587,11 @@ public final class BatteryStatsService extends IBatteryStats.Stub
}
}
+ private boolean shouldCollectExternalStats() {
+ return (SystemClock.elapsedRealtime() - mWorker.getLastCollectionTimeStamp())
+ > mStats.getExternalStatsCollectionRateLimitMs();
+ }
+
/**
* Returns whether the Binder.getCallingUid is the only thing in requestUids.
*/
diff --git a/services/core/java/com/android/server/am/DeprecatedTargetSdkVersionDialog.java b/services/core/java/com/android/server/am/DeprecatedTargetSdkVersionDialog.java
index 84dca7fe1c8a..d9878cd09fe4 100644
--- a/services/core/java/com/android/server/am/DeprecatedTargetSdkVersionDialog.java
+++ b/services/core/java/com/android/server/am/DeprecatedTargetSdkVersionDialog.java
@@ -16,6 +16,9 @@
package com.android.server.am;
+import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
+import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
+
import android.app.AlertDialog;
import android.content.Context;
import android.content.Intent;
@@ -23,6 +26,7 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.SystemPropertiesProto;
+import android.util.Log;
import android.view.Window;
import android.view.WindowManager;
import android.widget.CheckBox;
@@ -31,6 +35,8 @@ import com.android.internal.R;
import com.android.server.utils.AppInstallerUtil;
public class DeprecatedTargetSdkVersionDialog {
+ private static final String TAG = TAG_WITH_CLASS_NAME ? "DeprecatedTargetSdkVersionDialog" : TAG_AM;
+
private final AlertDialog mDialog;
private final String mPackageName;
@@ -74,6 +80,7 @@ public class DeprecatedTargetSdkVersionDialog {
}
public void show() {
+ Log.w(TAG, "Showing SDK deprecation warning for package " + mPackageName);
mDialog.show();
}
diff --git a/services/core/java/com/android/server/am/LockTaskController.java b/services/core/java/com/android/server/am/LockTaskController.java
index bef650b90f44..151ef4942432 100644
--- a/services/core/java/com/android/server/am/LockTaskController.java
+++ b/services/core/java/com/android/server/am/LockTaskController.java
@@ -555,11 +555,12 @@ public class LockTaskController {
return;
}
- if (mLockTaskModeTasks.isEmpty()) {
+ final Intent taskIntent = task.intent;
+ if (mLockTaskModeTasks.isEmpty() && taskIntent != null) {
mSupervisor.mRecentTasks.onLockTaskModeStateChanged(lockTaskModeState, task.userId);
// Start lock task on the handler thread
mHandler.post(() -> performStartLockTask(
- task.intent.getComponent().getPackageName(),
+ taskIntent.getComponent().getPackageName(),
task.userId,
lockTaskModeState));
}
diff --git a/services/core/java/com/android/server/am/RecentTasks.java b/services/core/java/com/android/server/am/RecentTasks.java
index a20452bb5074..c83bacbe7a1e 100644
--- a/services/core/java/com/android/server/am/RecentTasks.java
+++ b/services/core/java/com/android/server/am/RecentTasks.java
@@ -550,7 +550,7 @@ class RecentTasks {
continue;
}
- ComponentName cn = tr.intent.getComponent();
+ ComponentName cn = tr.intent != null ? tr.intent.getComponent() : null;
final boolean sameComponent = cn != null && cn.getPackageName().equals(packageName)
&& (filterByClasses == null || filterByClasses.contains(cn.getClassName()));
if (sameComponent) {
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index 0e418ad4cb88..1cd1dd6da529 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -203,7 +203,8 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
String rootAffinity; // Initial base affinity, or null; does not change from initial root.
final IVoiceInteractionSession voiceSession; // Voice interaction session driving task
final IVoiceInteractor voiceInteractor; // Associated interactor to provide to app
- Intent intent; // The original intent that started the task.
+ Intent intent; // The original intent that started the task. Note that this value can
+ // be null.
Intent affinityIntent; // Intent of affinity-moved activity that started this task.
int effectiveUid; // The current effective uid of the identity of this task.
ComponentName origActivity; // The non-alias activity component of the intent.
@@ -897,12 +898,12 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
// the real activity that will be launched not the alias, so we need to use an intent with
// the component name pointing to the real activity not the alias in the activity record.
intent.setComponent(r.realActivity);
- return this.intent.filterEquals(intent);
+ return intent.filterEquals(this.intent);
}
boolean returnsToHomeStack() {
final int returnHomeFlags = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME;
- return (intent.getFlags() & returnHomeFlags) == returnHomeFlags;
+ return intent != null && (intent.getFlags() & returnHomeFlags) == returnHomeFlags;
}
void setPrevAffiliate(TaskRecord prevAffiliate) {
@@ -2165,9 +2166,11 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
out.endTag(null, TAG_AFFINITYINTENT);
}
- out.startTag(null, TAG_INTENT);
- intent.saveToXml(out);
- out.endTag(null, TAG_INTENT);
+ if (intent != null) {
+ out.startTag(null, TAG_INTENT);
+ intent.saveToXml(out);
+ out.endTag(null, TAG_INTENT);
+ }
final ArrayList<ActivityRecord> activities = mActivities;
final int numActivities = activities.size();
diff --git a/services/core/java/com/android/server/location/GnssBatchingProvider.java b/services/core/java/com/android/server/location/GnssBatchingProvider.java
new file mode 100644
index 000000000000..f3918ee9e8ff
--- /dev/null
+++ b/services/core/java/com/android/server/location/GnssBatchingProvider.java
@@ -0,0 +1,145 @@
+package com.android.server.location;
+
+import android.util.Log;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+/**
+ * Manages GNSS Batching operations.
+ *
+ * <p>This class is not thread safe (It's client's responsibility to make sure calls happen on
+ * the same thread).
+ */
+public class GnssBatchingProvider {
+
+ private static final String TAG = "GnssBatchingProvider";
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
+ private final GnssBatchingProviderNative mNative;
+ private boolean mEnabled;
+ private boolean mStarted;
+ private long mPeriodNanos;
+ private boolean mWakeOnFifoFull;
+
+ GnssBatchingProvider() {
+ this(new GnssBatchingProviderNative());
+ }
+
+ @VisibleForTesting
+ GnssBatchingProvider(GnssBatchingProviderNative gnssBatchingProviderNative) {
+ mNative = gnssBatchingProviderNative;
+ }
+
+ /**
+ * Returns the GNSS batching size
+ */
+ public int getBatchSize() {
+ return mNative.getBatchSize();
+ }
+
+ /** Enable GNSS batching. */
+ public void enable() {
+ mEnabled = mNative.initBatching();
+ if (!mEnabled) {
+ Log.e(TAG, "Failed to initialize GNSS batching");
+ }
+ }
+
+ /**
+ * Starts the hardware batching operation
+ */
+ public boolean start(long periodNanos, boolean wakeOnFifoFull) {
+ if (!mEnabled) {
+ throw new IllegalStateException();
+ }
+ if (periodNanos <= 0) {
+ Log.e(TAG, "Invalid periodNanos " + periodNanos +
+ " in batching request, not started");
+ return false;
+ }
+ mStarted = mNative.startBatch(periodNanos, wakeOnFifoFull);
+ if (mStarted) {
+ mPeriodNanos = periodNanos;
+ mWakeOnFifoFull = wakeOnFifoFull;
+ }
+ return mStarted;
+ }
+
+ /**
+ * Forces a flush of existing locations from the hardware batching
+ */
+ public void flush() {
+ if (!mStarted) {
+ Log.w(TAG, "Cannot flush since GNSS batching has not started.");
+ return;
+ }
+ mNative.flushBatch();
+ }
+
+ /**
+ * Stops the batching operation
+ */
+ public boolean stop() {
+ boolean stopped = mNative.stopBatch();
+ if (stopped) {
+ mStarted = false;
+ }
+ return stopped;
+ }
+
+ /** Disable GNSS batching. */
+ public void disable() {
+ stop();
+ mNative.cleanupBatching();
+ mEnabled = false;
+ }
+
+ // TODO(b/37460011): Use this with death recovery logic.
+ void resumeIfStarted() {
+ if (DEBUG) {
+ Log.d(TAG, "resumeIfStarted");
+ }
+ if (mStarted) {
+ mNative.startBatch(mPeriodNanos, mWakeOnFifoFull);
+ }
+ }
+
+ @VisibleForTesting
+ static class GnssBatchingProviderNative {
+ public int getBatchSize() {
+ return native_get_batch_size();
+ }
+
+ public boolean startBatch(long periodNanos, boolean wakeOnFifoFull) {
+ return native_start_batch(periodNanos, wakeOnFifoFull);
+ }
+
+ public void flushBatch() {
+ native_flush_batch();
+ }
+
+ public boolean stopBatch() {
+ return native_stop_batch();
+ }
+
+ public boolean initBatching() {
+ return native_init_batching();
+ }
+
+ public void cleanupBatching() {
+ native_cleanup_batching();
+ }
+ }
+
+ private static native int native_get_batch_size();
+
+ private static native boolean native_start_batch(long periodNanos, boolean wakeOnFifoFull);
+
+ private static native void native_flush_batch();
+
+ private static native boolean native_stop_batch();
+
+ private static native boolean native_init_batching();
+
+ private static native void native_cleanup_batching();
+}
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index a8082986614c..756d06bc789d 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -418,6 +418,7 @@ public class GnssLocationProvider implements LocationProviderInterface, InjectNt
private final LocationChangeListener mNetworkLocationListener = new NetworkLocationListener();
private final LocationChangeListener mFusedLocationListener = new FusedLocationListener();
private final NtpTimeHelper mNtpTimeHelper;
+ private final GnssBatchingProvider mGnssBatchingProvider;
// Handler for processing events
private Handler mHandler;
@@ -885,6 +886,7 @@ public class GnssLocationProvider implements LocationProviderInterface, InjectNt
mGnssSatelliteBlacklistHelper = new GnssSatelliteBlacklistHelper(mContext,
looper, this);
mHandler.post(mGnssSatelliteBlacklistHelper::updateSatelliteBlacklist);
+ mGnssBatchingProvider = new GnssBatchingProvider();
}
/**
@@ -1061,6 +1063,12 @@ public class GnssLocationProvider implements LocationProviderInterface, InjectNt
locationListener = mFusedLocationListener;
}
+ if (!locationManager.isProviderEnabled(provider)) {
+ Log.w(TAG, "Unable to request location since " + provider
+ + " provider does not exist or is not enabled.");
+ return;
+ }
+
Log.i(TAG,
String.format(
"GNSS HAL Requesting location updates from %s provider for %d millis.",
@@ -1267,7 +1275,7 @@ public class GnssLocationProvider implements LocationProviderInterface, InjectNt
mGnssMeasurementsProvider.onGpsEnabledChanged();
mGnssNavigationMessageProvider.onGpsEnabledChanged();
- enableBatching();
+ mGnssBatchingProvider.enable();
} else {
synchronized (mLock) {
mEnabled = false;
@@ -1299,7 +1307,7 @@ public class GnssLocationProvider implements LocationProviderInterface, InjectNt
mAlarmManager.cancel(mWakeupIntent);
mAlarmManager.cancel(mTimeoutIntent);
- disableBatching();
+ mGnssBatchingProvider.disable();
// do this before releasing wakelock
native_cleanup();
@@ -2001,58 +2009,11 @@ public class GnssLocationProvider implements LocationProviderInterface, InjectNt
};
}
- public interface GnssBatchingProvider {
- /**
- * Returns the GNSS batching size
- */
- int getSize();
-
- /**
- * Starts the hardware batching operation
- */
- boolean start(long periodNanos, boolean wakeOnFifoFull);
-
- /**
- * Forces a flush of existing locations from the hardware batching
- */
- void flush();
-
- /**
- * Stops the batching operation
- */
- boolean stop();
- }
-
/**
* @hide
*/
public GnssBatchingProvider getGnssBatchingProvider() {
- return new GnssBatchingProvider() {
- @Override
- public int getSize() {
- return native_get_batch_size();
- }
-
- @Override
- public boolean start(long periodNanos, boolean wakeOnFifoFull) {
- if (periodNanos <= 0) {
- Log.e(TAG, "Invalid periodNanos " + periodNanos +
- "in batching request, not started");
- return false;
- }
- return native_start_batch(periodNanos, wakeOnFifoFull);
- }
-
- @Override
- public void flush() {
- native_flush_batch();
- }
-
- @Override
- public boolean stop() {
- return native_stop_batch();
- }
- };
+ return mGnssBatchingProvider;
}
public interface GnssMetricsProvider {
@@ -2075,23 +2036,6 @@ public class GnssLocationProvider implements LocationProviderInterface, InjectNt
}
/**
- * Initialize Batching if enabled
- */
- private void enableBatching() {
- if (!native_init_batching()) {
- Log.e(TAG, "Failed to initialize GNSS batching");
- }
- }
-
- /**
- * Disable batching
- */
- private void disableBatching() {
- native_stop_batch();
- native_cleanup_batching();
- }
-
- /**
* called from native code - GNSS location batch callback
*/
private void reportLocationBatch(Location[] locationArray) {
@@ -2912,19 +2856,5 @@ public class GnssLocationProvider implements LocationProviderInterface, InjectNt
private static native boolean native_set_emergency_supl_pdn(int emergencySuplPdn);
private static native boolean native_set_satellite_blacklist(int[] constellations, int[] svIds);
-
- // GNSS Batching
- private static native int native_get_batch_size();
-
- private static native boolean native_start_batch(long periodNanos, boolean wakeOnFifoFull);
-
- private static native void native_flush_batch();
-
- private static native boolean native_stop_batch();
-
- private static native boolean native_init_batching();
-
- private static native void native_cleanup_batching();
-
}
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index f1fd00b4ea2a..1078f6eefa76 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -1742,7 +1742,8 @@ public class LockSettingsService extends ILockSettings.Stub {
if (storedHash.type == LockPatternUtils.CREDENTIAL_TYPE_PATTERN) {
hash = LockPatternUtils.patternToHash(LockPatternUtils.stringToPattern(credential));
} else {
- hash = mLockPatternUtils.passwordToHash(credential, userId);
+ hash = mLockPatternUtils.legacyPasswordToHash(credential, userId)
+ .getBytes(StandardCharsets.UTF_8);
}
if (Arrays.equals(hash, storedHash.hash)) {
if (storedHash.type == LockPatternUtils.CREDENTIAL_TYPE_PATTERN) {
@@ -2532,6 +2533,33 @@ public class LockSettingsService extends ILockSettings.Stub {
mRecoverableKeyStoreManager.lockScreenSecretChanged(credentialType, credential, userId);
}
+ /**
+ * Returns a fixed pseudorandom byte string derived from the user's synthetic password.
+ * This is used to salt the password history hash to protect the hash against offline
+ * bruteforcing, since rederiving this value requires a successful authentication.
+ */
+ @Override
+ public byte[] getHashFactor(String currentCredential, int userId) throws RemoteException {
+ checkPasswordReadPermission(userId);
+ if (TextUtils.isEmpty(currentCredential)) {
+ currentCredential = null;
+ }
+ synchronized (mSpManager) {
+ if (!isSyntheticPasswordBasedCredentialLocked(userId)) {
+ Slog.w(TAG, "Synthetic password not enabled");
+ return null;
+ }
+ long handle = getSyntheticPasswordHandleLocked(userId);
+ AuthenticationResult auth = mSpManager.unwrapPasswordBasedSyntheticPassword(
+ getGateKeeperService(), handle, currentCredential, userId, null);
+ if (auth.authToken == null) {
+ Slog.w(TAG, "Current credential is incorrect");
+ return null;
+ }
+ return auth.authToken.derivePasswordHashFactor();
+ }
+ }
+
private long addEscrowToken(byte[] token, int userId) throws RemoteException {
if (DEBUG) Slog.d(TAG, "addEscrowToken: user=" + userId);
synchronized (mSpManager) {
diff --git a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
index 0700ab35df1b..596daeb1427b 100644
--- a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
+++ b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
@@ -123,6 +123,7 @@ public class SyntheticPasswordManager {
private static final byte[] PERSONALIZATION_FBE_KEY = "fbe-key".getBytes();
private static final byte[] PERSONALIZATION_AUTHSECRET_KEY = "authsecret-hal".getBytes();
private static final byte[] PERSONALIZATION_SP_SPLIT = "sp-split".getBytes();
+ private static final byte[] PERSONALIZATION_PASSWORD_HASH = "pw-hash".getBytes();
private static final byte[] PERSONALIZATION_E0 = "e0-encryption".getBytes();
private static final byte[] PERSONALISATION_WEAVER_PASSWORD = "weaver-pwd".getBytes();
private static final byte[] PERSONALISATION_WEAVER_KEY = "weaver-key".getBytes();
@@ -165,6 +166,11 @@ public class SyntheticPasswordManager {
syntheticPassword.getBytes());
}
+ public byte[] derivePasswordHashFactor() {
+ return SyntheticPasswordCrypto.personalisedHash(PERSONALIZATION_PASSWORD_HASH,
+ syntheticPassword.getBytes());
+ }
+
private void initialize(byte[] P0, byte[] P1) {
this.P1 = P1;
this.syntheticPassword = String.valueOf(HexEncoding.encode(
diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java
index 477b062ac90f..269a0dac41ab 100644
--- a/services/core/java/com/android/server/notification/ManagedServices.java
+++ b/services/core/java/com/android/server/notification/ManagedServices.java
@@ -71,9 +71,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
-import java.util.Objects;
import java.util.Set;
-import java.util.stream.Collectors;
/**
* Manages the lifecycle of application-provided services bound by system server.
@@ -401,15 +399,20 @@ abstract public class ManagedServices {
approvedByType = new ArrayMap<>();
mApproved.put(userId, approvedByType);
}
+
+ ArraySet<String> approvedList = approvedByType.get(isPrimary);
+ if (approvedList == null) {
+ approvedList = new ArraySet<>();
+ approvedByType.put(isPrimary, approvedList);
+ }
+
String[] approvedArray = approved.split(ENABLED_SERVICES_SEPARATOR);
- final ArraySet<String> approvedList = new ArraySet<>();
for (String pkgOrComponent : approvedArray) {
String approvedItem = getApprovedValue(pkgOrComponent);
if (approvedItem != null) {
approvedList.add(approvedItem);
}
}
- approvedByType.put(isPrimary, approvedList);
}
protected boolean isComponentEnabledForPackage(String pkg) {
diff --git a/services/core/java/com/android/server/os/SchedulingPolicyService.java b/services/core/java/com/android/server/os/SchedulingPolicyService.java
index c64e745a3ac2..5cbe1a1e9816 100644
--- a/services/core/java/com/android/server/os/SchedulingPolicyService.java
+++ b/services/core/java/com/android/server/os/SchedulingPolicyService.java
@@ -24,6 +24,8 @@ import android.os.Process;
import android.os.RemoteException;
import android.util.Log;
+import com.android.server.SystemServerInitThreadPool;
+
/**
* The implementation of the scheduling policy service interface.
*
@@ -62,11 +64,18 @@ public class SchedulingPolicyService extends ISchedulingPolicyService.Stub {
// (Note that if mediaserver thinks we're in boosted state before the crash,
// the state could go out of sync temporarily until mediaserver enables/disable
// boost next time, but this won't be a big issue.)
- int[] nativePids = Process.getPidsForCommands(MEDIA_PROCESS_NAMES);
- if (nativePids != null && nativePids.length == 1) {
- mBoostedPid = nativePids[0];
- disableCpusetBoost(nativePids[0]);
- }
+ SystemServerInitThreadPool.get().submit(() -> {
+ synchronized (mDeathRecipient) {
+ // only do this if we haven't already got a request to boost.
+ if (mBoostedPid == -1) {
+ int[] nativePids = Process.getPidsForCommands(MEDIA_PROCESS_NAMES);
+ if (nativePids != null && nativePids.length == 1) {
+ mBoostedPid = nativePids[0];
+ disableCpusetBoost(nativePids[0]);
+ }
+ }
+ }
+ }, TAG + ".<init>");
}
// TODO(b/35196900) We should pass the period in time units, rather
@@ -107,7 +116,9 @@ public class SchedulingPolicyService extends ISchedulingPolicyService.Stub {
// Request to move media.codec process between SP_FOREGROUND and SP_TOP_APP.
public int requestCpusetBoost(boolean enable, IBinder client) {
- if (!isPermitted()) {
+ // Can only allow mediaserver to call this.
+ if (Binder.getCallingPid() != Process.myPid() &&
+ Binder.getCallingUid() != Process.MEDIA_UID) {
return PackageManager.PERMISSION_DENIED;
}
@@ -201,7 +212,6 @@ public class SchedulingPolicyService extends ISchedulingPolicyService.Stub {
switch (Binder.getCallingUid()) {
case Process.AUDIOSERVER_UID: // fastcapture, fastmixer
- case Process.MEDIA_UID: // mediaserver
case Process.CAMERASERVER_UID: // camera high frame rate recording
case Process.BLUETOOTH_UID: // Bluetooth audio playback
return true;
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index a20023128ff5..866de76d10e4 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -13625,25 +13625,15 @@ public class PackageManagerService extends IPackageManager.Stub
// install reason correctly.
return installReason;
}
-
- final IDevicePolicyManager dpm = IDevicePolicyManager.Stub.asInterface(
- ServiceManager.getService(Context.DEVICE_POLICY_SERVICE));
- if (dpm != null) {
- ComponentName owner = null;
- try {
- owner = dpm.getDeviceOwnerComponent(true /* callingUserOnly */);
- if (owner == null) {
- owner = dpm.getProfileOwner(UserHandle.getUserId(installerUid));
- }
- } catch (RemoteException e) {
- }
- if (owner != null && owner.getPackageName().equals(installerPackageName)) {
- // If the install is being performed by a device or profile owner, the install
- // reason should be enterprise policy.
- return PackageManager.INSTALL_REASON_POLICY;
- }
+ final String ownerPackage = mProtectedPackages.getDeviceOwnerOrProfileOwnerPackage(
+ UserHandle.getUserId(installerUid));
+ if (ownerPackage != null && ownerPackage.equals(installerPackageName)) {
+ // If the install is being performed by a device or profile owner, the install
+ // reason should be enterprise policy.
+ return PackageManager.INSTALL_REASON_POLICY;
}
+
if (installReason == PackageManager.INSTALL_REASON_POLICY) {
// If the install is being performed by a regular app (i.e. neither system app nor
// device or profile owner), we have no reason to believe that the app is acting on
@@ -14040,7 +14030,11 @@ public class PackageManagerService extends IPackageManager.Stub
throw new IllegalArgumentException("CallingPackage " + callingPackage + " does not"
+ " belong to calling app id " + UserHandle.getAppId(callingUid));
}
-
+ if (!PLATFORM_PACKAGE_NAME.equals(callingPackage)
+ && mProtectedPackages.getDeviceOwnerOrProfileOwnerPackage(userId) != null) {
+ throw new UnsupportedOperationException("Cannot suspend/unsuspend packages. User "
+ + userId + " has an active DO or PO");
+ }
if (ArrayUtils.isEmpty(packageNames)) {
return packageNames;
}
@@ -17425,6 +17419,7 @@ public class PackageManagerService extends IPackageManager.Stub
// 1) it is not forward locked.
// 2) it is not on on an external ASEC container.
// 3) it is not an instant app or if it is then dexopt is enabled via gservices.
+ // 4) it is not debuggable.
//
// Note that we do not dexopt instant apps by default. dexopt can take some time to
// complete, so we skip this step during installation. Instead, we'll take extra time
@@ -17436,7 +17431,8 @@ public class PackageManagerService extends IPackageManager.Stub
&& !forwardLocked
&& !pkg.applicationInfo.isExternalAsec()
&& (!instantApp || Global.getInt(mContext.getContentResolver(),
- Global.INSTANT_APP_DEXOPT_ENABLED, 0) != 0);
+ Global.INSTANT_APP_DEXOPT_ENABLED, 0) != 0)
+ && ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) == 0);
if (performDexopt) {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt");
diff --git a/services/core/java/com/android/server/pm/ProtectedPackages.java b/services/core/java/com/android/server/pm/ProtectedPackages.java
index e67364a26e5c..a374e1484b28 100644
--- a/services/core/java/com/android/server/pm/ProtectedPackages.java
+++ b/services/core/java/com/android/server/pm/ProtectedPackages.java
@@ -88,6 +88,13 @@ public class ProtectedPackages {
return false;
}
+ public synchronized String getDeviceOwnerOrProfileOwnerPackage(int userId) {
+ if (mDeviceOwnerUserId == userId) {
+ return mDeviceOwnerPackage;
+ }
+ return mProfileOwnerPackages.get(userId);
+ }
+
/**
* Returns {@code true} if a given package is protected. Otherwise, returns {@code false}.
*
diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java
index 61e82cd2d339..20283a792cfb 100644
--- a/services/core/java/com/android/server/power/Notifier.java
+++ b/services/core/java/com/android/server/power/Notifier.java
@@ -16,6 +16,7 @@
package com.android.server.power;
+import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.ActivityManagerInternal;
import android.app.AppOpsManager;
@@ -97,7 +98,7 @@ final class Notifier {
private final ActivityManagerInternal mActivityManagerInternal;
private final InputManagerInternal mInputManagerInternal;
private final InputMethodManagerInternal mInputMethodManagerInternal;
- private final StatusBarManagerInternal mStatusBarManagerInternal;
+ @Nullable private final StatusBarManagerInternal mStatusBarManagerInternal;
private final TrustManager mTrustManager;
private final NotifierHandler mHandler;
@@ -738,7 +739,9 @@ final class Notifier {
private void showWirelessChargingStarted(int batteryLevel) {
playChargingStartedSound();
- mStatusBarManagerInternal.showChargingAnimation(batteryLevel);
+ if (mStatusBarManagerInternal != null) {
+ mStatusBarManagerInternal.showChargingAnimation(batteryLevel);
+ }
mSuspendBlocker.release();
}
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index 0dc06b27a605..c7617546780d 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -82,6 +82,7 @@ import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.res.Configuration;
+import android.content.res.ResourceId;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
@@ -245,7 +246,6 @@ public class AppTransition implements Dump {
private int mLastClipRevealMaxTranslation;
private boolean mLastHadClipReveal;
- private boolean mProlongedAnimationsEnded;
private final boolean mGridLayoutRecentsEnabled;
private final boolean mLowRamRecentsEnabled;
@@ -423,27 +423,12 @@ public class AppTransition implements Dump {
mService.getDefaultDisplayContentLocked().getDockedDividerController()
.notifyAppTransitionStarting(openingApps, transit);
- // Prolong the start for the transition when docking a task from recents, unless recents
- // ended it already then we don't need to wait.
- if (transit == TRANSIT_DOCK_TASK_FROM_RECENTS && !mProlongedAnimationsEnded) {
- for (int i = openingApps.size() - 1; i >= 0; i--) {
- final AppWindowToken app = openingApps.valueAt(i);
- app.startDelayingAnimationStart();
- }
- }
if (mRemoteAnimationController != null) {
mRemoteAnimationController.goodToGo();
}
return redoLayout;
}
- /**
- * Let the transitions manager know that the somebody wanted to end the prolonged animations.
- */
- void notifyProlongedAnimationsEnded() {
- mProlongedAnimationsEnded = true;
- }
-
void clear() {
mNextAppTransitionType = NEXT_TRANSIT_TYPE_NONE;
mNextAppTransitionPackage = null;
@@ -452,7 +437,6 @@ public class AppTransition implements Dump {
mNextAppTransitionAnimationsSpecsFuture = null;
mDefaultNextAppTransitionAnimationSpec = null;
mAnimationFinishedCallback = null;
- mProlongedAnimationsEnded = false;
}
void freeze() {
@@ -555,25 +539,25 @@ public class AppTransition implements Dump {
}
Animation loadAnimationAttr(LayoutParams lp, int animAttr, int transit) {
- int anim = 0;
+ int resId = ResourceId.ID_NULL;
Context context = mContext;
if (animAttr >= 0) {
AttributeCache.Entry ent = getCachedAnimations(lp);
if (ent != null) {
context = ent.context;
- anim = ent.array.getResourceId(animAttr, 0);
+ resId = ent.array.getResourceId(animAttr, 0);
}
}
- anim = updateToTranslucentAnimIfNeeded(anim, transit);
- if (anim != 0) {
- return AnimationUtils.loadAnimation(context, anim);
+ resId = updateToTranslucentAnimIfNeeded(resId, transit);
+ if (ResourceId.isValid(resId)) {
+ return AnimationUtils.loadAnimation(context, resId);
}
return null;
}
Animation loadAnimationRes(LayoutParams lp, int resId) {
Context context = mContext;
- if (resId >= 0) {
+ if (ResourceId.isValid(resId)) {
AttributeCache.Entry ent = getCachedAnimations(lp);
if (ent != null) {
context = ent.context;
@@ -584,18 +568,12 @@ public class AppTransition implements Dump {
}
private Animation loadAnimationRes(String packageName, int resId) {
- int anim = 0;
- Context context = mContext;
- if (resId >= 0) {
+ if (ResourceId.isValid(resId)) {
AttributeCache.Entry ent = getCachedAnimations(packageName, resId);
if (ent != null) {
- context = ent.context;
- anim = resId;
+ return AnimationUtils.loadAnimation(ent.context, resId);
}
}
- if (anim != 0) {
- return AnimationUtils.loadAnimation(context, anim);
- }
return null;
}
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index 79b230d45110..b057b1d8fb52 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -47,7 +47,9 @@ import android.view.IRecentsAnimationRunner;
import android.view.RemoteAnimationTarget;
import android.view.SurfaceControl;
import android.view.SurfaceControl.Transaction;
+import android.view.inputmethod.InputMethodManagerInternal;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.LocalServices;
import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
import com.android.server.wm.utils.InsetUtils;
import com.google.android.collect.Sets;
@@ -220,6 +222,20 @@ public class RecentsAnimationController implements DeathRecipient {
Binder.restoreCallingIdentity(token);
}
}
+
+ @Override
+ public void hideCurrentInputMethod() {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ final InputMethodManagerInternal inputMethodManagerInternal =
+ LocalServices.getService(InputMethodManagerInternal.class);
+ if (inputMethodManagerInternal != null) {
+ inputMethodManagerInternal.hideCurrentInputMethod();
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
};
/**
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index 5f9d679d7f07..6b13edd072cd 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -273,9 +273,8 @@ class TaskSnapshotController {
return null;
}
return new TaskSnapshot(buffer, top.getConfiguration().orientation,
- getInsets(mainWindow),
- isLowRamDevice /* reduced */, scaleFraction /* scale */,
- true /* isRealSnapshot */);
+ getInsets(mainWindow), isLowRamDevice /* reduced */, scaleFraction /* scale */,
+ true /* isRealSnapshot */, task.getWindowingMode());
}
private boolean shouldDisableSnapshots() {
@@ -365,7 +364,7 @@ class TaskSnapshotController {
return new TaskSnapshot(hwBitmap.createGraphicBufferHandle(),
topChild.getConfiguration().orientation, mainWindow.mStableInsets,
ActivityManager.isLowRamDeviceStatic() /* reduced */, 1.0f /* scale */,
- false /* isRealSnapshot */);
+ false /* isRealSnapshot */, task.getWindowingMode());
}
/**
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotLoader.java b/services/core/java/com/android/server/wm/TaskSnapshotLoader.java
index 31da5f3ff1c8..b682a3262da1 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotLoader.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotLoader.java
@@ -90,7 +90,7 @@ class TaskSnapshotLoader {
return new TaskSnapshot(buffer, proto.orientation,
new Rect(proto.insetLeft, proto.insetTop, proto.insetRight, proto.insetBottom),
reducedResolution, reducedResolution ? REDUCED_SCALE : 1f,
- proto.isRealSnapshot);
+ proto.isRealSnapshot, proto.windowingMode);
} catch (IOException e) {
Slog.w(TAG, "Unable to load task snapshot data for taskId=" + taskId);
return null;
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
index 086fffa9d621..408fb3ce36c9 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
@@ -24,9 +24,7 @@ import android.annotation.TestApi;
import android.app.ActivityManager;
import android.app.ActivityManager.TaskSnapshot;
import android.graphics.Bitmap;
-import android.graphics.Bitmap.CompressFormat;
import android.graphics.Bitmap.Config;
-import android.graphics.GraphicBuffer;
import android.os.Process;
import android.os.SystemClock;
import android.util.ArraySet;
@@ -41,7 +39,6 @@ import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayDeque;
-import java.util.ArrayList;
/**
* Persists {@link TaskSnapshot}s to disk.
@@ -319,6 +316,7 @@ class TaskSnapshotPersister {
proto.insetRight = mSnapshot.getContentInsets().right;
proto.insetBottom = mSnapshot.getContentInsets().bottom;
proto.isRealSnapshot = mSnapshot.isRealSnapshot();
+ proto.windowingMode = mSnapshot.getWindowingMode();
final byte[] bytes = TaskSnapshotProto.toByteArray(proto);
final File file = getProtoFile(mTaskId, mUserId);
final AtomicFile atomicFile = new AtomicFile(file);
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index ae9e80268741..7d4d7cb9c71c 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -751,8 +751,9 @@ public class TaskStack extends WindowContainer<Task> implements
* Used to make room for shadows in the pinned windowing mode.
*/
int getStackOutset() {
- if (inPinnedWindowingMode()) {
- final DisplayMetrics displayMetrics = getDisplayContent().getDisplayMetrics();
+ DisplayContent displayContent = getDisplayContent();
+ if (inPinnedWindowingMode() && displayContent != null) {
+ final DisplayMetrics displayMetrics = displayContent.getDisplayMetrics();
// We multiply by two to match the client logic for converting view elevation
// to insets, as in {@link WindowManager.LayoutParams#setSurfaceInsets}
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 331a0bd3da11..eab391ed74ce 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -183,6 +183,7 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
// build a surface.
mSurfaceControl = makeSurface().build();
getPendingTransaction().show(mSurfaceControl);
+ updateSurfacePosition();
} else {
// If we have a surface but a new parent, we just need to perform a reparent. Go through
// surface animator such that hierarchy is preserved when animating, i.e.
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 09e43f843983..06e8d4718cd2 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2204,7 +2204,7 @@ public class WindowManagerService extends IWindowManager.Stub
if (mInputMethodWindow == win) {
setInputMethodWindowLocked(null);
}
- boolean stopped = win.mAppToken != null ? win.mAppToken.mAppStopped : false;
+ boolean stopped = win.mAppToken != null ? win.mAppToken.mAppStopped : true;
// We set mDestroying=true so AppWindowToken#notifyAppStopped in-to destroy surfaces
// will later actually destroy the surface if we do not do so here. Normally we leave
// this to the exit animation.
@@ -2677,15 +2677,7 @@ public class WindowManagerService extends IWindowManager.Stub
@Override
public void endProlongedAnimations() {
- synchronized (mWindowMap) {
- for (final WindowState win : mWindowMap.values()) {
- final AppWindowToken appToken = win.mAppToken;
- if (appToken != null) {
- appToken.endDelayingAnimationStart();
- }
- }
- mAppTransition.notifyProlongedAnimationsEnded();
- }
+ // TODO: Remove once clients are updated.
}
@Override
@@ -5816,6 +5808,7 @@ public class WindowManagerService extends IWindowManager.Stub
final int displayId = mFrozenDisplayId;
mFrozenDisplayId = INVALID_DISPLAY;
mDisplayFrozen = false;
+ mInputMonitor.thawInputDispatchingLw();
mLastDisplayFreezeDuration = (int)(SystemClock.elapsedRealtime() - mDisplayFreezeTime);
StringBuilder sb = new StringBuilder(128);
sb.append("Screen frozen for ");
@@ -5862,8 +5855,6 @@ public class WindowManagerService extends IWindowManager.Stub
updateRotation = true;
}
- mInputMonitor.thawInputDispatchingLw();
-
boolean configChanged;
// While the display is frozen we don't re-compute the orientation
@@ -5952,12 +5943,8 @@ public class WindowManagerService extends IWindowManager.Stub
@Override
public void setRecentsVisibility(boolean visible) {
- if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR)
- != PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException("Caller does not hold permission "
- + android.Manifest.permission.STATUS_BAR);
- }
-
+ mAmInternal.enforceCallerIsRecentsOrHasPermission(android.Manifest.permission.STATUS_BAR,
+ "setRecentsVisibility()");
synchronized (mWindowMap) {
mPolicy.setRecentsVisibilityLw(visible);
}
diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
index e18eee267610..92ef9f16ca93 100644
--- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
@@ -2050,7 +2050,7 @@ static jboolean android_location_GnssLocationProvider_set_satellite_blacklist(
}
-static jint android_location_GnssLocationProvider_get_batch_size(JNIEnv*, jclass) {
+static jint android_location_GnssBatchingProvider_get_batch_size(JNIEnv*, jclass) {
if (gnssBatchingIface == nullptr) {
return 0; // batching not supported, size = 0
}
@@ -2062,7 +2062,7 @@ static jint android_location_GnssLocationProvider_get_batch_size(JNIEnv*, jclass
}
}
-static jboolean android_location_GnssLocationProvider_init_batching(JNIEnv*, jclass) {
+static jboolean android_location_GnssBatchingProvider_init_batching(JNIEnv*, jclass) {
if (gnssBatchingIface == nullptr) {
return JNI_FALSE; // batching not supported
}
@@ -2071,14 +2071,14 @@ static jboolean android_location_GnssLocationProvider_init_batching(JNIEnv*, jcl
return static_cast<jboolean>(gnssBatchingIface->init(gnssBatchingCbIface));
}
-static void android_location_GnssLocationProvider_cleanup_batching(JNIEnv*, jclass) {
+static void android_location_GnssBatchingProvider_cleanup_batching(JNIEnv*, jclass) {
if (gnssBatchingIface == nullptr) {
return; // batching not supported
}
gnssBatchingIface->cleanup();
}
-static jboolean android_location_GnssLocationProvider_start_batch(JNIEnv*, jclass,
+static jboolean android_location_GnssBatchingProvider_start_batch(JNIEnv*, jclass,
jlong periodNanos, jboolean wakeOnFifoFull) {
if (gnssBatchingIface == nullptr) {
return JNI_FALSE; // batching not supported
@@ -2095,7 +2095,7 @@ static jboolean android_location_GnssLocationProvider_start_batch(JNIEnv*, jclas
return static_cast<jboolean>(gnssBatchingIface->start(options));
}
-static void android_location_GnssLocationProvider_flush_batch(JNIEnv*, jclass) {
+static void android_location_GnssBatchingProvider_flush_batch(JNIEnv*, jclass) {
if (gnssBatchingIface == nullptr) {
return; // batching not supported
}
@@ -2103,7 +2103,7 @@ static void android_location_GnssLocationProvider_flush_batch(JNIEnv*, jclass) {
gnssBatchingIface->flush();
}
-static jboolean android_location_GnssLocationProvider_stop_batch(JNIEnv*, jclass) {
+static jboolean android_location_GnssBatchingProvider_stop_batch(JNIEnv*, jclass) {
if (gnssBatchingIface == nullptr) {
return JNI_FALSE; // batching not supported
}
@@ -2241,30 +2241,36 @@ static const JNINativeMethod sMethods[] = {
{"native_set_satellite_blacklist",
"([I[I)Z",
reinterpret_cast<void *>(android_location_GnssLocationProvider_set_satellite_blacklist)},
+};
+
+static const JNINativeMethod sMethodsBatching[] = {
+ /* name, signature, funcPtr */
{"native_get_batch_size",
"()I",
- reinterpret_cast<void *>(android_location_GnssLocationProvider_get_batch_size)},
- {"native_init_batching",
- "()Z",
- reinterpret_cast<void *>(android_location_GnssLocationProvider_init_batching)},
+ reinterpret_cast<void *>(android_location_GnssBatchingProvider_get_batch_size)},
{"native_start_batch",
"(JZ)Z",
- reinterpret_cast<void *>(android_location_GnssLocationProvider_start_batch)},
+ reinterpret_cast<void *>(android_location_GnssBatchingProvider_start_batch)},
{"native_flush_batch",
"()V",
- reinterpret_cast<void *>(android_location_GnssLocationProvider_flush_batch)},
+ reinterpret_cast<void *>(android_location_GnssBatchingProvider_flush_batch)},
{"native_stop_batch",
"()Z",
- reinterpret_cast<void *>(android_location_GnssLocationProvider_stop_batch)},
+ reinterpret_cast<void *>(android_location_GnssBatchingProvider_stop_batch)},
{"native_init_batching",
"()Z",
- reinterpret_cast<void *>(android_location_GnssLocationProvider_init_batching)},
+ reinterpret_cast<void *>(android_location_GnssBatchingProvider_init_batching)},
{"native_cleanup_batching",
"()V",
- reinterpret_cast<void *>(android_location_GnssLocationProvider_cleanup_batching)},
+ reinterpret_cast<void *>(android_location_GnssBatchingProvider_cleanup_batching)},
};
int register_android_server_location_GnssLocationProvider(JNIEnv* env) {
+ jniRegisterNativeMethods(
+ env,
+ "com/android/server/location/GnssBatchingProvider",
+ sMethodsBatching,
+ NELEM(sMethodsBatching));
return jniRegisterNativeMethods(
env,
"com/android/server/location/GnssLocationProvider",
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index e07b89f232b1..51ce7c20dd5e 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -73,6 +73,9 @@ import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker
import static com.android.server.devicepolicy.TransferOwnershipMetadataManager.ADMIN_TYPE_DEVICE_OWNER;
import static com.android.server.devicepolicy.TransferOwnershipMetadataManager.ADMIN_TYPE_PROFILE_OWNER;
+
+import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
+
import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
import static org.xmlpull.v1.XmlPullParser.END_TAG;
import static org.xmlpull.v1.XmlPullParser.TEXT;
@@ -9193,8 +9196,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
long id = mInjector.binderClearCallingIdentity();
try {
- return mIPackageManager.setPackagesSuspendedAsUser(
- packageNames, suspended, null, null, null, "android", callingUserId);
+ return mIPackageManager.setPackagesSuspendedAsUser(packageNames, suspended,
+ null, null, null, PLATFORM_PACKAGE_NAME, callingUserId);
} catch (RemoteException re) {
// Shouldn't happen.
Slog.e(LOG_TAG, "Failed talking to the package manager", re);
diff --git a/services/robotests/src/com/android/server/location/GnssBatchingProviderTest.java b/services/robotests/src/com/android/server/location/GnssBatchingProviderTest.java
new file mode 100644
index 000000000000..504609472fa6
--- /dev/null
+++ b/services/robotests/src/com/android/server/location/GnssBatchingProviderTest.java
@@ -0,0 +1,91 @@
+package com.android.server.location;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Matchers.anyBoolean;
+import static org.mockito.Matchers.anyLong;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.platform.test.annotations.Presubmit;
+
+import com.android.server.location.GnssBatchingProvider.GnssBatchingProviderNative;
+import com.android.server.testing.FrameworkRobolectricTestRunner;
+import com.android.server.testing.SystemLoaderPackages;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.annotation.Config;
+
+/**
+ * Unit tests for {@link GnssBatchingProvider}.
+ */
+@RunWith(FrameworkRobolectricTestRunner.class)
+@Config(
+ manifest = Config.NONE,
+ shadows = {
+ },
+ sdk = 27
+)
+@SystemLoaderPackages({"com.android.server.location"})
+@Presubmit
+public class GnssBatchingProviderTest {
+
+ private static final long PERIOD_NANOS = (long) 1e9;
+ private static final boolean WAKE_ON_FIFO_FULL = true;
+ private static final int BATCH_SIZE = 3;
+ @Mock
+ private GnssBatchingProviderNative mMockNative;
+ private GnssBatchingProvider mTestProvider;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ when(mMockNative.initBatching()).thenReturn(true);
+ when(mMockNative.startBatch(anyLong(), anyBoolean())).thenReturn(true);
+ when(mMockNative.stopBatch()).thenReturn(true);
+ when(mMockNative.getBatchSize()).thenReturn(BATCH_SIZE);
+ mTestProvider = new GnssBatchingProvider(mMockNative);
+ mTestProvider.enable();
+ mTestProvider.start(PERIOD_NANOS, WAKE_ON_FIFO_FULL);
+ }
+
+ @Test
+ public void start_nativeStarted() {
+ verify(mMockNative).startBatch(eq(PERIOD_NANOS), eq(WAKE_ON_FIFO_FULL));
+ }
+
+ @Test
+ public void stop_nativeStopped() {
+ mTestProvider.stop();
+ verify(mMockNative).stopBatch();
+ }
+
+ @Test
+ public void flush_nativeFlushed() {
+ mTestProvider.flush();
+ verify(mMockNative).flushBatch();
+ }
+
+ @Test
+ public void getBatchSize_nativeGetBatchSize() {
+ assertThat(mTestProvider.getBatchSize()).isEqualTo(BATCH_SIZE);
+ }
+
+ @Test
+ public void started_resume_started() {
+ mTestProvider.resumeIfStarted();
+ verify(mMockNative, times(2)).startBatch(eq(PERIOD_NANOS), eq(WAKE_ON_FIFO_FULL));
+ }
+
+ @Test
+ public void stopped_resume_notStarted() {
+ mTestProvider.stop();
+ mTestProvider.resumeIfStarted();
+ verify(mMockNative, times(1)).startBatch(eq(PERIOD_NANOS), eq(WAKE_ON_FIFO_FULL));
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java
index 08b8af289bd8..9daea1afc505 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java
@@ -25,6 +25,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.content.pm.ActivityInfo.FLAG_ALWAYS_FOCUSABLE;
+import static android.content.pm.ActivityInfo.FLAG_SHOW_WHEN_LOCKED;
import static com.android.server.am.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
@@ -329,4 +330,52 @@ public class ActivityStackSupervisorTests extends ActivityTestsBase {
REMOVE_TASK_MODE_DESTROYING);
assertFalse(pinnedStack.isFocusable());
}
+
+ /**
+ * Verifies the correct activity is returned when querying the top running activity with an
+ * empty focused stack.
+ */
+ @Test
+ public void testNonFocusedTopRunningActivity() throws Exception {
+ // Create stack to hold focus
+ final ActivityStack focusedStack = mService.mStackSupervisor.getDefaultDisplay()
+ .createStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
+
+ final KeyguardController keyguard = mSupervisor.getKeyguardController();
+ final ActivityStack stack = mService.mStackSupervisor.getDefaultDisplay().createStack(
+ WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
+ final ActivityRecord activity = new ActivityBuilder(mService).setCreateTask(true)
+ .setStack(stack).build();
+
+ mSupervisor.mFocusedStack = focusedStack;
+
+ doAnswer((InvocationOnMock invocationOnMock) -> {
+ final SparseIntArray displayIds = invocationOnMock.<SparseIntArray>getArgument(0);
+ displayIds.put(0, mSupervisor.getDefaultDisplay().mDisplayId);
+ return null;
+ }).when(mSupervisor.mWindowManager).getDisplaysInFocusOrder(any());
+
+ // Make sure the top running activity is not affected when keyguard is not locked
+ assertEquals(activity, mService.mStackSupervisor.topRunningActivityLocked());
+ assertEquals(activity, mService.mStackSupervisor.topRunningActivityLocked(
+ true /* considerKeyguardState */));
+
+ // Check to make sure activity not reported when it cannot show on lock and lock is on.
+ doReturn(true).when(keyguard).isKeyguardLocked();
+ assertEquals(activity, mService.mStackSupervisor.topRunningActivityLocked());
+ assertEquals(null, mService.mStackSupervisor.topRunningActivityLocked(
+ true /* considerKeyguardState */));
+
+ // Add activity that should be shown on the keyguard.
+ final ActivityRecord showWhenLockedActivity = new ActivityBuilder(mService)
+ .setCreateTask(true)
+ .setStack(stack)
+ .setActivityFlags(FLAG_SHOW_WHEN_LOCKED)
+ .build();
+
+ // Ensure the show when locked activity is returned.
+ assertEquals(showWhenLockedActivity, mService.mStackSupervisor.topRunningActivityLocked());
+ assertEquals(showWhenLockedActivity, mService.mStackSupervisor.topRunningActivityLocked(
+ true /* considerKeyguardState */));
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
index f5e61a1db341..1cd111fce0ec 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
@@ -132,6 +132,7 @@ public class ActivityTestsBase {
private int mUid;
private boolean mCreateTask;
private ActivityStack mStack;
+ private int mActivityFlags;
ActivityBuilder(ActivityManagerService service) {
mService = service;
@@ -152,6 +153,11 @@ public class ActivityTestsBase {
return this;
}
+ ActivityBuilder setActivityFlags(int flags) {
+ mActivityFlags = flags;
+ return this;
+ }
+
ActivityBuilder setStack(ActivityStack stack) {
mStack = stack;
return this;
@@ -186,6 +192,8 @@ public class ActivityTestsBase {
aInfo.applicationInfo = new ApplicationInfo();
aInfo.applicationInfo.packageName = mComponent.getPackageName();
aInfo.applicationInfo.uid = mUid;
+ aInfo.flags |= mActivityFlags;
+
final ActivityRecord activity = new ActivityRecord(mService, null /* caller */,
0 /* launchedFromPid */, 0, null, intent, null,
aInfo /*aInfo*/, new Configuration(), null /* resultTo */, null /* resultWho */,
diff --git a/services/tests/servicestests/src/com/android/server/am/TaskRecordTests.java b/services/tests/servicestests/src/com/android/server/am/TaskRecordTests.java
index c91e22f84a07..057fdc8c10bb 100644
--- a/services/tests/servicestests/src/com/android/server/am/TaskRecordTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/TaskRecordTests.java
@@ -17,6 +17,9 @@
package com.android.server.am;
+import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
+import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
@@ -62,7 +65,7 @@ import java.util.Comparator;
* Tests for exercising {@link TaskRecord}.
*
* Build/Install/Run:
- * bit FrameworksServicesTests:com.android.server.am.TaskRecordTests
+ * atest FrameworksServicesTests:com.android.server.am.TaskRecordTests
*/
@MediumTest
@Presubmit
@@ -113,6 +116,18 @@ public class TaskRecordTests extends ActivityTestsBase {
assertTrue(factory.mCreated);
}
+ @Test
+ public void testReturnsToHomeStack() throws Exception {
+ final TaskRecord task = createTaskRecord(1);
+ assertFalse(task.returnsToHomeStack());
+ task.intent = null;
+ assertFalse(task.returnsToHomeStack());
+ task.intent = new Intent();
+ assertFalse(task.returnsToHomeStack());
+ task.intent.addFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME);
+ assertTrue(task.returnsToHomeStack());
+ }
+
private File serializeToFile(TaskRecord r) throws IOException, XmlPullParserException {
final File tmpFile = File.createTempFile(r.taskId + "_task_", "xml");
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java
index 80cbf2aae3f0..13478dfded34 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java
@@ -16,6 +16,8 @@
package com.android.server.wm;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
@@ -164,8 +166,10 @@ public class TaskSnapshotPersisterLoaderTest extends TaskSnapshotPersisterTestBa
@Test
public void testIsRealSnapshotPersistAndLoadSnapshot() {
- TaskSnapshot a = createSnapshot(1f /* scale */, true /* isRealSnapshot */);
- TaskSnapshot b = createSnapshot(1f /* scale */, false /* isRealSnapshot */);
+ TaskSnapshot a = createSnapshot(1f /* scale */, true /* isRealSnapshot */,
+ WINDOWING_MODE_FULLSCREEN);
+ TaskSnapshot b = createSnapshot(1f /* scale */, false /* isRealSnapshot */,
+ WINDOWING_MODE_FULLSCREEN);
assertTrue(a.isRealSnapshot());
assertFalse(b.isRealSnapshot());
mPersister.persistSnapshot(1, mTestUserId, a);
@@ -180,6 +184,25 @@ public class TaskSnapshotPersisterLoaderTest extends TaskSnapshotPersisterTestBa
}
@Test
+ public void testWindowingModePersistAndLoadSnapshot() {
+ TaskSnapshot a = createSnapshot(1f /* scale */, true /* isRealSnapshot */,
+ WINDOWING_MODE_FULLSCREEN);
+ TaskSnapshot b = createSnapshot(1f /* scale */, true /* isRealSnapshot */,
+ WINDOWING_MODE_PINNED);
+ assertTrue(a.getWindowingMode() == WINDOWING_MODE_FULLSCREEN);
+ assertTrue(b.getWindowingMode() == WINDOWING_MODE_PINNED);
+ mPersister.persistSnapshot(1, mTestUserId, a);
+ mPersister.persistSnapshot(2, mTestUserId, b);
+ mPersister.waitForQueueEmpty();
+ final TaskSnapshot snapshotA = mLoader.loadTask(1, mTestUserId, false /* reduced */);
+ final TaskSnapshot snapshotB = mLoader.loadTask(2, mTestUserId, false /* reduced */);
+ assertNotNull(snapshotA);
+ assertNotNull(snapshotB);
+ assertTrue(snapshotA.getWindowingMode() == WINDOWING_MODE_FULLSCREEN);
+ assertTrue(snapshotB.getWindowingMode() == WINDOWING_MODE_PINNED);
+ }
+
+ @Test
public void testRemoveObsoleteFiles() {
mPersister.persistSnapshot(1, mTestUserId, createSnapshot());
mPersister.persistSnapshot(2, mTestUserId, createSnapshot());
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java
index 2ad5bf404052..6a4acbe47beb 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java
@@ -16,6 +16,7 @@
package com.android.server.wm;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.graphics.GraphicBuffer.USAGE_HW_TEXTURE;
import static android.graphics.GraphicBuffer.USAGE_SW_READ_RARELY;
@@ -84,16 +85,16 @@ class TaskSnapshotPersisterTestBase extends WindowTestsBase {
}
TaskSnapshot createSnapshot(float scale) {
- return createSnapshot(scale, true /* isRealSnapshot */);
+ return createSnapshot(scale, true /* isRealSnapshot */, WINDOWING_MODE_FULLSCREEN);
}
- TaskSnapshot createSnapshot(float scale, boolean isRealSnapshot) {
+ TaskSnapshot createSnapshot(float scale, boolean isRealSnapshot, int windowingMode) {
final GraphicBuffer buffer = GraphicBuffer.create(100, 100, PixelFormat.RGBA_8888,
USAGE_HW_TEXTURE | USAGE_SW_READ_RARELY | USAGE_SW_READ_RARELY);
Canvas c = buffer.lockCanvas();
c.drawColor(Color.RED);
buffer.unlockCanvasAndPost(c);
return new TaskSnapshot(buffer, ORIENTATION_PORTRAIT, TEST_INSETS,
- scale < 1f /* reducedResolution */, scale, isRealSnapshot);
+ scale < 1f /* reducedResolution */, scale, isRealSnapshot, windowingMode);
}
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
index d5334babc1a6..54d02d4f2ad2 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
@@ -16,6 +16,7 @@
package com.android.server.wm;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
import static org.junit.Assert.assertEquals;
@@ -60,7 +61,8 @@ public class TaskSnapshotSurfaceTest extends WindowTestsBase {
final GraphicBuffer buffer = GraphicBuffer.create(width, height, PixelFormat.RGBA_8888,
GraphicBuffer.USAGE_SW_READ_NEVER | GraphicBuffer.USAGE_SW_WRITE_NEVER);
final TaskSnapshot snapshot = new TaskSnapshot(buffer,
- ORIENTATION_PORTRAIT, contentInsets, false, 1.0f, true /* isRealSnapshot */);
+ ORIENTATION_PORTRAIT, contentInsets, false, 1.0f, true /* isRealSnapshot */,
+ WINDOWING_MODE_FULLSCREEN);
mSurface = new TaskSnapshotSurface(sWm, new Window(), new Surface(), snapshot, "Test",
Color.WHITE, Color.RED, Color.BLUE, sysuiVis, windowFlags, 0, taskBounds,
ORIENTATION_PORTRAIT);
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowContainerTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowContainerTests.java
index 8446d252323f..6c7830e5cf79 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowContainerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowContainerTests.java
@@ -17,6 +17,8 @@
package com.android.server.wm;
import android.support.test.filters.FlakyTest;
+import android.view.SurfaceControl;
+import android.view.SurfaceSession;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -43,6 +45,9 @@ import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.anyFloat;
+import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
@@ -108,6 +113,21 @@ public class WindowContainerTests extends WindowTestsBase {
}
@Test
+ public void testAddChildSetsSurfacePosition() throws Exception {
+ MockSurfaceBuildingContainer top = new MockSurfaceBuildingContainer();
+
+ final SurfaceControl.Transaction transaction = mock(SurfaceControl.Transaction.class);
+ sWm.mTransactionFactory = () -> transaction;
+
+ WindowContainer child = new WindowContainer(sWm);
+ child.setBounds(1, 1, 10, 10);
+
+ verify(transaction, never()).setPosition(any(), anyFloat(), anyFloat());
+ top.addChild(child, 0);
+ verify(transaction, times(1)).setPosition(any(), eq(1.f), eq(1.f));
+ }
+
+ @Test
public void testAdd_AlreadyHasParent() throws Exception {
final TestWindowContainerBuilder builder = new TestWindowContainerBuilder();
final TestWindowContainer root = builder.setLayer(0).build();
@@ -825,4 +845,28 @@ public class WindowContainerTests extends WindowTestsBase {
return new TestWindowContainer(mLayer, mIsAnimating, mIsVisible, mOrientation);
}
}
+
+ private class MockSurfaceBuildingContainer extends WindowContainer<WindowContainer> {
+ final SurfaceSession mSession = new SurfaceSession();
+
+ MockSurfaceBuildingContainer() {
+ super(sWm);
+ }
+
+ class MockSurfaceBuilder extends SurfaceControl.Builder {
+ MockSurfaceBuilder(SurfaceSession ss) {
+ super(ss);
+ }
+
+ @Override
+ public SurfaceControl build() {
+ return mock(SurfaceControl.class);
+ }
+ }
+
+ @Override
+ SurfaceControl.Builder makeChildSurface(WindowContainer child) {
+ return new MockSurfaceBuilder(mSession);
+ }
+ }
}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java
index 9ef0ec7ac99b..4668ed42b11e 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java
@@ -267,6 +267,32 @@ public class ManagedServicesTest extends UiServiceTestCase {
}
@Test
+ public void testReadXml_appendsListOfApprovedComponents() throws Exception {
+ for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) {
+ ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles,
+ mIpm, approvalLevel);
+
+ String preApprovedPackage = "some.random.package";
+ String preApprovedComponent = "some.random.package/C1";
+
+ List<String> packages = new ArrayList<>();
+ packages.add(preApprovedPackage);
+ addExpectedServices(service, packages, 0);
+
+ service.setPackageOrComponentEnabled(preApprovedComponent, 0, true, true);
+
+ loadXml(service);
+
+ verifyExpectedApprovedEntries(service);
+
+ String verifyValue = (approvalLevel == APPROVAL_BY_COMPONENT)
+ ? preApprovedComponent
+ : preApprovedPackage;
+ assertTrue(service.isPackageOrComponentAllowed(verifyValue, 0));
+ }
+ }
+
+ @Test
public void testWriteXml_trimsMissingServices() throws Exception {
for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) {
ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles,
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 19061f94a6b9..c850004a54d8 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -1124,6 +1124,41 @@ public class TelephonyManager {
*/
public static final String EXTRA_SUBSCRIPTION_ID = "android.telephony.extra.SUBSCRIPTION_ID";
+ /**
+ * Broadcast intent action indicating that when data stall recovery is attempted by Telephony,
+ * intended for report every data stall recovery step attempted.
+ *
+ * <p>
+ * The {@link #EXTRA_RECOVERY_ACTION} extra indicates the action associated with the data
+ * stall recovery.
+ * The phone id where the data stall recovery is attempted.
+ *
+ * <p class="note">
+ * Requires the READ_PHONE_STATE permission.
+ *
+ * <p class="note">
+ * This is a protected intent that can only be sent by the system.
+ *
+ * @see #EXTRA_RECOVERY_ACTION
+ *
+ * @hide
+ */
+ // TODO(b/78370030) : Restrict this to system applications only
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+ public static final String ACTION_DATA_STALL_DETECTED =
+ "android.intent.action.DATA_STALL_DETECTED";
+
+ /**
+ * An int extra used with {@link #ACTION_DATA_STALL_DETECTED} to indicate the
+ * action associated with the data stall recovery.
+ *
+ * @see #ACTION_DATA_STALL_DETECTED
+ *
+ * @hide
+ */
+ public static final String EXTRA_RECOVERY_ACTION = "recoveryAction";
+
//
//
// Device Info
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 482d6e1fdb31..5b73bbaa1c73 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -84,6 +84,7 @@ import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.net.CaptivePortal;
import android.net.ConnectivityManager;
@@ -201,6 +202,7 @@ public class ConnectivityServiceTest {
@Mock DefaultNetworkMetrics mDefaultNetworkMetrics;
@Mock INetworkManagementService mNetworkManagementService;
@Mock INetworkStatsService mStatsService;
+ @Mock Vpn mMockVpn;
private ArgumentCaptor<String[]> mStringArrayCaptor = ArgumentCaptor.forClass(String[].class);
@@ -505,6 +507,7 @@ public class ConnectivityServiceTest {
mWrappedNetworkMonitor.gen204ProbeResult = 204;
NetworkRequest request = new NetworkRequest.Builder()
.addTransportType(mNetworkCapabilities.getTransportTypes()[0])
+ .clearCapabilities()
.build();
callback = new NetworkCallback() {
public void onCapabilitiesChanged(Network network,
@@ -888,6 +891,15 @@ public class ConnectivityServiceTest {
return mLastCreatedNetworkMonitor;
}
+ public void mockVpn(int uid) {
+ synchronized (mVpns) {
+ // This has no effect unless the VPN is actually connected, because things like
+ // getActiveNetworkForUidInternal call getNetworkAgentInfoForNetId on the VPN
+ // netId, and check if that network is actually connected.
+ mVpns.put(UserHandle.getUserId(Process.myUid()), mMockVpn);
+ }
+ }
+
public void waitForIdle(int timeoutMs) {
waitForIdleHandler(mHandlerThread, timeoutMs);
}
@@ -914,6 +926,7 @@ public class ConnectivityServiceTest {
MockitoAnnotations.initMocks(this);
when(mMetricsService.defaultNetworkMetrics()).thenReturn(mDefaultNetworkMetrics);
+ when(mMockVpn.appliesToUid(Process.myUid())).thenReturn(true);
// InstrumentationTestRunner prepares a looper, but AndroidJUnitRunner does not.
// http://b/25897652 .
@@ -935,6 +948,7 @@ public class ConnectivityServiceTest {
// getSystemService() correctly.
mCm = new WrappedConnectivityManager(InstrumentationRegistry.getContext(), mService);
mService.systemReady();
+ mService.mockVpn(Process.myUid());
mCm.bindProcessToNetwork(null);
// Ensure that the default setting for Captive Portals is used for most tests
@@ -1347,6 +1361,7 @@ public class ConnectivityServiceTest {
private final static int TIMEOUT_MS = 100;
private final LinkedBlockingQueue<CallbackInfo> mCallbacks = new LinkedBlockingQueue<>();
+ private Network mLastAvailableNetwork;
protected void setLastCallback(CallbackState state, Network network, Object o) {
mCallbacks.offer(new CallbackInfo(state, network, o));
@@ -1354,6 +1369,7 @@ public class ConnectivityServiceTest {
@Override
public void onAvailable(Network network) {
+ mLastAvailableNetwork = network;
setLastCallback(CallbackState.AVAILABLE, network, null);
}
@@ -1389,9 +1405,14 @@ public class ConnectivityServiceTest {
@Override
public void onLost(Network network) {
+ mLastAvailableNetwork = null;
setLastCallback(CallbackState.LOST, network, null);
}
+ public Network getLastAvailableNetwork() {
+ return mLastAvailableNetwork;
+ }
+
CallbackInfo nextCallback(int timeoutMs) {
CallbackInfo cb = null;
try {
@@ -1658,6 +1679,7 @@ public class ConnectivityServiceTest {
callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+ assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
mWiFiNetworkAgent.connect(true);
// We get AVAILABLE on wifi when wifi connects and satisfies our unmetered request.
@@ -1668,6 +1690,7 @@ public class ConnectivityServiceTest {
callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+ assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
mEthernetNetworkAgent.connect(true);
callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent);
@@ -1676,11 +1699,13 @@ public class ConnectivityServiceTest {
callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+ assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
mEthernetNetworkAgent.disconnect();
callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
defaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
+ assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
for (int i = 0; i < 4; i++) {
MockNetworkAgent oldNetwork, newNetwork;
@@ -1709,6 +1734,7 @@ public class ConnectivityServiceTest {
defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED, mWiFiNetworkAgent);
defaultCallback.assertNoCallback();
callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
+ assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
// Wifi no longer satisfies our listen, which is for an unmetered network.
// But because its score is 55, it's still up (and the default network).
@@ -1718,8 +1744,11 @@ public class ConnectivityServiceTest {
mWiFiNetworkAgent.disconnect();
defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
+ assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
mCellNetworkAgent.disconnect();
defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
+ waitForIdle();
+ assertEquals(null, mCm.getActiveNetwork());
mCm.unregisterNetworkCallback(callback);
waitForIdle();
@@ -1736,6 +1765,7 @@ public class ConnectivityServiceTest {
callback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+ assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
// Bring up wifi with a score of 20.
// Cell stays up because it would satisfy the default request if it validated.
@@ -1744,12 +1774,14 @@ public class ConnectivityServiceTest {
callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+ assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
mWiFiNetworkAgent.disconnect();
callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+ assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
// Bring up wifi with a score of 70.
// Cell is lingered because it would not satisfy any request, even if it validated.
@@ -1760,6 +1792,7 @@ public class ConnectivityServiceTest {
callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+ assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
// Tear down wifi.
mWiFiNetworkAgent.disconnect();
@@ -1767,6 +1800,7 @@ public class ConnectivityServiceTest {
defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+ assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
// Bring up wifi, then validate it. Previous versions would immediately tear down cell, but
// it's arguably correct to linger it, since it was the default network before it validated.
@@ -1778,6 +1812,7 @@ public class ConnectivityServiceTest {
callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+ assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
mWiFiNetworkAgent.disconnect();
callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
@@ -1786,12 +1821,15 @@ public class ConnectivityServiceTest {
mCellNetworkAgent.disconnect();
callback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
+ waitForIdle();
+ assertEquals(null, mCm.getActiveNetwork());
// If a network is lingering, and we add and remove a request from it, resume lingering.
mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
mCellNetworkAgent.connect(true);
callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
+ assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(true);
defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
@@ -1799,6 +1837,7 @@ public class ConnectivityServiceTest {
// TODO: Investigate sending validated before losing.
callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
+ assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
NetworkRequest cellRequest = new NetworkRequest.Builder()
.addTransportType(TRANSPORT_CELLULAR).build();
@@ -1815,6 +1854,7 @@ public class ConnectivityServiceTest {
callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
+ assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
// Cell is now the default network. Pin it with a cell-specific request.
noopCallback = new NetworkCallback(); // Can't reuse NetworkCallbacks. http://b/20701525
@@ -1825,6 +1865,7 @@ public class ConnectivityServiceTest {
mWiFiNetworkAgent.connect(true);
callback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
+ assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
// The default request is lingering on cell, but nothing happens to cell, and we send no
// callbacks for it, because it's kept up by cellRequest.
callback.assertNoCallback();
@@ -1848,6 +1889,7 @@ public class ConnectivityServiceTest {
callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
trackDefaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
+ assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
// Let linger run its course.
callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent, lingerTimeoutMs);
@@ -2496,23 +2538,27 @@ public class ConnectivityServiceTest {
mCellNetworkAgent.connect(true);
cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
+ assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
// Bring up wifi and expect CALLBACK_AVAILABLE.
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(true);
cellNetworkCallback.assertNoCallback();
defaultNetworkCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
+ assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
// Bring down cell. Expect no default network callback, since it wasn't the default.
mCellNetworkAgent.disconnect();
cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
defaultNetworkCallback.assertNoCallback();
+ assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
// Bring up cell. Expect no default network callback, since it won't be the default.
mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
mCellNetworkAgent.connect(true);
cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
defaultNetworkCallback.assertNoCallback();
+ assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
// Bring down wifi. Expect the default network callback to notified of LOST wifi
// followed by AVAILABLE cell.
@@ -2523,6 +2569,23 @@ public class ConnectivityServiceTest {
mCellNetworkAgent.disconnect();
cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
defaultNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
+ waitForIdle();
+ assertEquals(null, mCm.getActiveNetwork());
+
+ final int uid = Process.myUid();
+ final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
+ final ArraySet<UidRange> ranges = new ArraySet<>();
+ ranges.add(new UidRange(uid, uid));
+ when(mMockVpn.getNetId()).thenReturn(vpnNetworkAgent.getNetwork().netId);
+ vpnNetworkAgent.setUids(ranges);
+ vpnNetworkAgent.connect(true);
+ defaultNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
+ assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
+
+ vpnNetworkAgent.disconnect();
+ defaultNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
+ waitForIdle();
+ assertEquals(null, mCm.getActiveNetwork());
}
@Test
@@ -4015,6 +4078,7 @@ public class ConnectivityServiceTest {
final TestNetworkCallback genericNotVpnNetworkCallback = new TestNetworkCallback();
final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
+ final TestNetworkCallback defaultCallback = new TestNetworkCallback();
final NetworkRequest genericNotVpnRequest = new NetworkRequest.Builder().build();
final NetworkRequest genericRequest = new NetworkRequest.Builder()
.removeCapability(NET_CAPABILITY_NOT_VPN).build();
@@ -4027,6 +4091,8 @@ public class ConnectivityServiceTest {
mCm.registerNetworkCallback(genericNotVpnRequest, genericNotVpnNetworkCallback);
mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
+ mCm.registerDefaultNetworkCallback(defaultCallback);
+ defaultCallback.assertNoCallback();
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(false);
@@ -4034,15 +4100,14 @@ public class ConnectivityServiceTest {
genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
genericNotVpnNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+ defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
vpnNetworkCallback.assertNoCallback();
-
- // TODO : check callbacks agree with the return value of mCm.getActiveNetwork().
- // Right now this is not possible because establish() is not adequately instrumented
- // in this test.
+ assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
final ArraySet<UidRange> ranges = new ArraySet<>();
ranges.add(new UidRange(uid, uid));
+ when(mMockVpn.getNetId()).thenReturn(vpnNetworkAgent.getNetwork().netId);
vpnNetworkAgent.setUids(ranges);
vpnNetworkAgent.connect(false);
@@ -4050,10 +4115,14 @@ public class ConnectivityServiceTest {
genericNotVpnNetworkCallback.assertNoCallback();
wifiNetworkCallback.assertNoCallback();
vpnNetworkCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
+ defaultCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
+ assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
genericNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
genericNotVpnNetworkCallback.assertNoCallback();
vpnNetworkCallback.expectCapabilitiesLike(nc -> null == nc.getUids(), vpnNetworkAgent);
+ defaultCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
+ assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
ranges.clear();
vpnNetworkAgent.setUids(ranges);
@@ -4063,6 +4132,14 @@ public class ConnectivityServiceTest {
wifiNetworkCallback.assertNoCallback();
vpnNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
+ // TODO : The default network callback should actually get a LOST call here (also see the
+ // comment below for AVAILABLE). This is because ConnectivityService does not look at UID
+ // ranges at all when determining whether a network should be rematched. In practice, VPNs
+ // can't currently update their UIDs without disconnecting, so this does not matter too
+ // much, but that is the reason the test here has to check for an update to the
+ // capabilities instead of the expected LOST then AVAILABLE.
+ defaultCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
+
ranges.add(new UidRange(uid, uid));
vpnNetworkAgent.setUids(ranges);
@@ -4070,6 +4147,9 @@ public class ConnectivityServiceTest {
genericNotVpnNetworkCallback.assertNoCallback();
wifiNetworkCallback.assertNoCallback();
vpnNetworkCallback.expectAvailableCallbacksValidated(vpnNetworkAgent);
+ // TODO : Here like above, AVAILABLE would be correct, but because this can't actually
+ // happen outside of the test, ConnectivityService does not rematch callbacks.
+ defaultCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
mWiFiNetworkAgent.disconnect();
@@ -4077,6 +4157,7 @@ public class ConnectivityServiceTest {
genericNotVpnNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
vpnNetworkCallback.assertNoCallback();
+ defaultCallback.assertNoCallback();
vpnNetworkAgent.disconnect();
@@ -4084,9 +4165,61 @@ public class ConnectivityServiceTest {
genericNotVpnNetworkCallback.assertNoCallback();
wifiNetworkCallback.assertNoCallback();
vpnNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
+ defaultCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
+ assertEquals(null, mCm.getActiveNetwork());
mCm.unregisterNetworkCallback(genericNetworkCallback);
mCm.unregisterNetworkCallback(wifiNetworkCallback);
mCm.unregisterNetworkCallback(vpnNetworkCallback);
+ mCm.unregisterNetworkCallback(defaultCallback);
+ }
+
+ @Test
+ public void testVpnWithAndWithoutInternet() {
+ final int uid = Process.myUid();
+
+ final TestNetworkCallback defaultCallback = new TestNetworkCallback();
+ mCm.registerDefaultNetworkCallback(defaultCallback);
+ defaultCallback.assertNoCallback();
+
+ mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent.connect(true);
+
+ defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
+ assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
+
+ MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
+ final ArraySet<UidRange> ranges = new ArraySet<>();
+ ranges.add(new UidRange(uid, uid));
+ when(mMockVpn.getNetId()).thenReturn(vpnNetworkAgent.getNetwork().netId);
+ vpnNetworkAgent.setUids(ranges);
+ vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */);
+
+ defaultCallback.assertNoCallback();
+ assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
+
+ vpnNetworkAgent.disconnect();
+ defaultCallback.assertNoCallback();
+
+ vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
+ when(mMockVpn.getNetId()).thenReturn(vpnNetworkAgent.getNetwork().netId);
+ vpnNetworkAgent.setUids(ranges);
+ vpnNetworkAgent.connect(true /* validated */, true /* hasInternet */);
+ defaultCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
+ assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
+
+ vpnNetworkAgent.disconnect();
+ defaultCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
+ defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
+
+ vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
+ when(mMockVpn.getNetId()).thenReturn(vpnNetworkAgent.getNetwork().netId);
+ ranges.clear();
+ vpnNetworkAgent.setUids(ranges);
+
+ vpnNetworkAgent.connect(false /* validated */, true /* hasInternet */);
+ defaultCallback.assertNoCallback();
+
+ mCm.unregisterNetworkCallback(defaultCallback);
}
}
diff --git a/tools/aapt2/cmd/Link.cpp b/tools/aapt2/cmd/Link.cpp
index a3b766481887..b90e7b3042f9 100644
--- a/tools/aapt2/cmd/Link.cpp
+++ b/tools/aapt2/cmd/Link.cpp
@@ -798,35 +798,39 @@ class LinkCommand {
return;
}
- xml::Attribute* attr = manifest_xml->root->FindAttribute(xml::kSchemaAndroid, "versionCode");
- if (attr != nullptr) {
- Maybe<std::string>& compile_sdk_version = options_.manifest_fixer_options.compile_sdk_version;
- if (BinaryPrimitive* prim = ValueCast<BinaryPrimitive>(attr->compiled_value.get())) {
- switch (prim->value.dataType) {
- case Res_value::TYPE_INT_DEC:
- compile_sdk_version = StringPrintf("%" PRId32, static_cast<int32_t>(prim->value.data));
- break;
- case Res_value::TYPE_INT_HEX:
- compile_sdk_version = StringPrintf("%" PRIx32, prim->value.data);
- break;
- default:
- break;
+ if (!options_.manifest_fixer_options.compile_sdk_version) {
+ xml::Attribute* attr = manifest_xml->root->FindAttribute(xml::kSchemaAndroid, "versionCode");
+ if (attr != nullptr) {
+ Maybe<std::string>& compile_sdk_version = options_.manifest_fixer_options.compile_sdk_version;
+ if (BinaryPrimitive* prim = ValueCast<BinaryPrimitive>(attr->compiled_value.get())) {
+ switch (prim->value.dataType) {
+ case Res_value::TYPE_INT_DEC:
+ compile_sdk_version = StringPrintf("%" PRId32, static_cast<int32_t>(prim->value.data));
+ break;
+ case Res_value::TYPE_INT_HEX:
+ compile_sdk_version = StringPrintf("%" PRIx32, prim->value.data);
+ break;
+ default:
+ break;
+ }
+ } else if (String* str = ValueCast<String>(attr->compiled_value.get())) {
+ compile_sdk_version = *str->value;
+ } else {
+ compile_sdk_version = attr->value;
}
- } else if (String* str = ValueCast<String>(attr->compiled_value.get())) {
- compile_sdk_version = *str->value;
- } else {
- compile_sdk_version = attr->value;
}
}
- attr = manifest_xml->root->FindAttribute(xml::kSchemaAndroid, "versionName");
- if (attr != nullptr) {
- Maybe<std::string>& compile_sdk_version_codename =
- options_.manifest_fixer_options.compile_sdk_version_codename;
- if (String* str = ValueCast<String>(attr->compiled_value.get())) {
- compile_sdk_version_codename = *str->value;
- } else {
- compile_sdk_version_codename = attr->value;
+ if (!options_.manifest_fixer_options.compile_sdk_version_codename) {
+ xml::Attribute* attr = manifest_xml->root->FindAttribute(xml::kSchemaAndroid, "versionName");
+ if (attr != nullptr) {
+ Maybe<std::string>& compile_sdk_version_codename =
+ options_.manifest_fixer_options.compile_sdk_version_codename;
+ if (String* str = ValueCast<String>(attr->compiled_value.get())) {
+ compile_sdk_version_codename = *str->value;
+ } else {
+ compile_sdk_version_codename = attr->value;
+ }
}
}
}
@@ -2102,6 +2106,13 @@ int Link(const std::vector<StringPiece>& args, IDiagnostics* diagnostics) {
.OptionalFlag("--version-name",
"Version name to inject into the AndroidManifest.xml if none is present.",
&options.manifest_fixer_options.version_name_default)
+ .OptionalFlag("--compile-sdk-version-code",
+ "Version code (integer) to inject into the AndroidManifest.xml if none is\n"
+ "present.",
+ &options.manifest_fixer_options.compile_sdk_version)
+ .OptionalFlag("--compile-sdk-version-name",
+ "Version name to inject into the AndroidManifest.xml if none is present.",
+ &options.manifest_fixer_options.compile_sdk_version_codename)
.OptionalSwitch("--shared-lib", "Generates a shared Android runtime library.",
&shared_lib)
.OptionalSwitch("--static-lib", "Generate a static Android library.", &static_lib)
diff --git a/tools/fonts/fontchain_linter.py b/tools/fonts/fontchain_linter.py
index ec40a2229c33..ffca46696a7c 100755
--- a/tools/fonts/fontchain_linter.py
+++ b/tools/fonts/fontchain_linter.py
@@ -471,11 +471,20 @@ def parse_ucd(ucd_path):
_emoji_zwj_sequences.update(parse_unicode_datafile(
path.join(ucd_path, 'additions', 'emoji-zwj-sequences.txt')))
+ exclusions = parse_unicode_datafile(path.join(ucd_path, 'additions', 'emoji-exclusions.txt'))
+ _emoji_sequences = remove_emoji_exclude(_emoji_sequences, exclusions)
+ _emoji_zwj_sequences = remove_emoji_exclude(_emoji_zwj_sequences, exclusions)
+ _emoji_variation_sequences = remove_emoji_variation_exclude(_emoji_variation_sequences, exclusions)
+
+def remove_emoji_variation_exclude(source, items):
+ return source.difference(items.keys())
+
+def remove_emoji_exclude(source, items):
+ return {k: v for k, v in source.items() if k not in items}
def flag_sequence(territory_code):
return tuple(0x1F1E6 + ord(ch) - ord('A') for ch in territory_code)
-
UNSUPPORTED_FLAGS = frozenset({
flag_sequence('BL'), flag_sequence('BQ'), flag_sequence('DG'),
flag_sequence('EA'), flag_sequence('EH'), flag_sequence('FK'),
@@ -522,8 +531,6 @@ LEGACY_ANDROID_EMOJI = {
ZWJ_IDENTICALS = {
# KISS
(0x1F469, 0x200D, 0x2764, 0x200D, 0x1F48B, 0x200D, 0x1F468): 0x1F48F,
- # COUPLE WITH HEART
- (0x1F469, 0x200D, 0x2764, 0x200D, 0x1F468): 0x1F491,
# FAMILY
(0x1F468, 0x200D, 0x1F469, 0x200D, 0x1F466): 0x1F46A,
}
@@ -576,6 +583,8 @@ GENDER_DEFAULTS = [
(0x1F9DD, FEMALE_SIGN), # ELF
(0x1F9DE, FEMALE_SIGN), # GENIE
(0x1F9DF, FEMALE_SIGN), # ZOMBIE
+ (0X1F9B8, FEMALE_SIGN), # SUPERVILLAIN
+ (0x1F9B9, FEMALE_SIGN), # SUPERHERO
]
def is_fitzpatrick_modifier(cp):
diff --git a/wifi/tests/runtests.sh b/wifi/tests/runtests.sh
index ebcc2a2f34a2..4e52b8f23399 100755
--- a/wifi/tests/runtests.sh
+++ b/wifi/tests/runtests.sh
@@ -21,4 +21,5 @@ adb wait-for-device
adb install -r -g "$OUT/data/app/FrameworksWifiApiTests/FrameworksWifiApiTests.apk"
-adb shell am instrument -w "$@" 'android.net.wifi.test/android.support.test.runner.AndroidJUnitRunner'
+adb shell am instrument --no-hidden-api-checks -w "$@" \
+ 'android.net.wifi.test/android.support.test.runner.AndroidJUnitRunner'