summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.txt2
-rw-r--r--api/system-current.txt2
-rw-r--r--api/test-current.txt2
-rw-r--r--cmds/vr/src/com/android/commands/vr/Vr.java16
-rw-r--r--core/java/android/app/ActivityManagerInternal.java6
-rw-r--r--core/java/android/app/ITaskStackListener.aidl5
-rw-r--r--core/java/android/app/Notification.java3
-rw-r--r--core/java/android/app/TaskStackListener.java2
-rw-r--r--core/java/android/app/Vr2dDisplayProperties.aidl (renamed from core/java/android/app/CompatibilityDisplayProperties.aidl)2
-rw-r--r--core/java/android/app/Vr2dDisplayProperties.java (renamed from core/java/android/app/CompatibilityDisplayProperties.java)24
-rw-r--r--core/java/android/app/VrManager.java12
-rw-r--r--core/java/android/app/assist/AssistStructure.java11
-rw-r--r--core/java/android/bluetooth/BluetoothA2dp.java114
-rw-r--r--core/java/android/bluetooth/IBluetoothA2dp.aidl3
-rw-r--r--core/java/android/net/INetworkScoreService.aidl2
-rw-r--r--core/java/android/net/NetworkScoreManager.java42
-rw-r--r--core/java/android/os/Build.java2
-rw-r--r--core/java/android/os/VintfObject.java22
-rwxr-xr-xcore/java/android/provider/Settings.java46
-rw-r--r--core/java/android/service/vr/IVrManager.aidl12
-rw-r--r--core/java/android/text/TextUtils.java16
-rw-r--r--core/java/android/view/ViewStructure.java7
-rw-r--r--core/java/android/view/autofill/AutofillValue.java4
-rw-r--r--core/java/android/view/textclassifier/TextClassifierImpl.java4
-rw-r--r--core/java/android/widget/Editor.java44
-rw-r--r--core/java/android/widget/ListView.java11
-rw-r--r--core/java/android/widget/SelectionActionModeHelper.java14
-rw-r--r--core/java/android/widget/TextView.java2
-rw-r--r--core/jni/android_os_VintfObject.cpp64
-rw-r--r--core/proto/android/providers/settings.proto2
-rw-r--r--core/res/res/values/config.xml8
-rw-r--r--core/res/res/values/symbols.xml1
-rw-r--r--core/tests/coretests/src/android/os/VintfObjectTest.java3
-rw-r--r--core/tests/coretests/src/android/provider/SettingsBackupTest.java2
-rw-r--r--core/tests/coretests/src/android/view/textclassifier/TextClassificationManagerTest.java16
-rw-r--r--libs/hwui/tests/unit/FrameBuilderTests.cpp24
-rw-r--r--obex/javax/obex/ServerSession.java1
-rw-r--r--packages/CarrierDefaultApp/AndroidManifest.xml1
-rw-r--r--packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierActionUtils.java37
-rw-r--r--packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierDefaultBroadcastReceiver.java4
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java3
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java14
-rw-r--r--packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java4
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java6
-rw-r--r--packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeLog.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java45
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeUi.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSPanel.java17
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java1
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java53
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java24
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/utils/hardware/FakeSensorManager.java (renamed from packages/SystemUI/tests/src/com/android/systemui/doze/SensorManagerFake.java)83
-rw-r--r--preloaded-classes1
-rw-r--r--services/autofill/java/com/android/server/autofill/Helper.java10
-rw-r--r--services/autofill/java/com/android/server/autofill/Session.java73
-rw-r--r--services/autofill/java/com/android/server/autofill/ViewState.java20
-rw-r--r--services/backup/java/com/android/server/backup/BackupManagerService.java31
-rw-r--r--services/backup/java/com/android/server/backup/Trampoline.java8
-rw-r--r--services/backup/java/com/android/server/backup/TransportManager.java4
-rw-r--r--services/core/java/com/android/server/AlarmManagerService.java1
-rw-r--r--services/core/java/com/android/server/NetworkScoreService.java9
-rw-r--r--services/core/java/com/android/server/NetworkScorerAppManager.java23
-rw-r--r--services/core/java/com/android/server/Vr2dDisplay.java (renamed from services/core/java/com/android/server/vr/CompatibilityDisplay.java)26
-rw-r--r--services/core/java/com/android/server/am/ActiveServices.java75
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java41
-rw-r--r--services/core/java/com/android/server/am/ActivityStarter.java27
-rw-r--r--services/core/java/com/android/server/am/ProcessRecord.java6
-rw-r--r--services/core/java/com/android/server/am/TaskChangeNotificationController.java7
-rw-r--r--services/core/java/com/android/server/am/UidRecord.java5
-rw-r--r--services/core/java/com/android/server/display/NightDisplayService.java95
-rw-r--r--services/core/java/com/android/server/location/GnssLocationProvider.java25
-rw-r--r--services/core/java/com/android/server/notification/NotificationIntrusivenessExtractor.java6
-rw-r--r--services/core/java/com/android/server/notification/NotificationManagerService.java18
-rw-r--r--services/core/java/com/android/server/notification/NotificationRecord.java42
-rw-r--r--services/core/java/com/android/server/notification/RankingConfig.java2
-rw-r--r--services/core/java/com/android/server/notification/RankingHelper.java59
-rw-r--r--services/core/java/com/android/server/pm/EphemeralResolverConnection.java5
-rw-r--r--services/core/java/com/android/server/pm/PackageDexOptimizer.java65
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java2
-rw-r--r--services/core/java/com/android/server/pm/dex/DexManager.java42
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java96
-rw-r--r--services/core/java/com/android/server/trust/TrustManagerService.java7
-rw-r--r--services/core/java/com/android/server/twilight/TwilightState.java2
-rw-r--r--services/core/java/com/android/server/vr/VrManagerInternal.java12
-rw-r--r--services/core/java/com/android/server/vr/VrManagerService.java46
-rw-r--r--services/core/java/com/android/server/wm/AppWindowContainerController.java3
-rw-r--r--services/core/java/com/android/server/wm/AppWindowToken.java20
-rw-r--r--services/core/java/com/android/server/wm/DimLayerController.java13
-rw-r--r--services/core/java/com/android/server/wm/TaskSnapshotController.java11
-rw-r--r--services/core/java/com/android/server/wm/TaskSnapshotPersister.java6
-rw-r--r--services/core/java/com/android/server/wm/TaskSnapshotSurface.java144
-rw-r--r--services/tests/notification/src/com/android/server/notification/BadgeExtractorTest.java2
-rw-r--r--services/tests/notification/src/com/android/server/notification/BuzzBeepBlinkTest.java4
-rw-r--r--services/tests/notification/src/com/android/server/notification/GlobalSortKeyComparatorTest.java14
-rw-r--r--services/tests/notification/src/com/android/server/notification/ImportanceExtractorTest.java2
-rw-r--r--services/tests/notification/src/com/android/server/notification/NotificationComparatorTest.java22
-rw-r--r--services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java4
-rw-r--r--services/tests/notification/src/com/android/server/notification/NotificationRecordTest.java98
-rw-r--r--services/tests/notification/src/com/android/server/notification/RankingHelperTest.java116
-rw-r--r--services/tests/notification/src/com/android/server/notification/SnoozeHelperTest.java2
-rw-r--r--services/tests/servicestests/AndroidManifest.xml1
-rw-r--r--services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java4
-rw-r--r--services/tests/servicestests/src/com/android/server/NetworkScorerAppManagerTest.java56
-rw-r--r--services/tests/servicestests/src/com/android/server/NightDisplayServiceTest.java620
-rw-r--r--services/tests/servicestests/src/com/android/server/wm/TaskSnapshotCacheTest.java4
-rw-r--r--services/tests/servicestests/src/com/android/server/wm/TaskSnapshotControllerTest.java10
-rw-r--r--services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java6
-rw-r--r--services/tests/servicestests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java25
-rw-r--r--telephony/java/android/telephony/ims/ImsServiceProxy.java58
-rw-r--r--telephony/java/android/telephony/ims/feature/ImsFeature.java2
-rw-r--r--wifi/java/android/net/wifi/RttManager.java10
-rw-r--r--wifi/java/android/net/wifi/WifiConfiguration.java4
120 files changed, 2281 insertions, 766 deletions
diff --git a/api/current.txt b/api/current.txt
index 157a72c47f05..899381bec02d 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -30508,7 +30508,7 @@ package android.os {
field public static final int M = 23; // 0x17
field public static final int N = 24; // 0x18
field public static final int N_MR1 = 25; // 0x19
- field public static final int O = 26; // 0x1a
+ field public static final int O = 10000; // 0x2710
}
public final class Bundle extends android.os.BaseBundle implements java.lang.Cloneable android.os.Parcelable {
diff --git a/api/system-current.txt b/api/system-current.txt
index 110d1dd59661..8aa6c362480d 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -33218,7 +33218,7 @@ package android.os {
field public static final int M = 23; // 0x17
field public static final int N = 24; // 0x18
field public static final int N_MR1 = 25; // 0x19
- field public static final int O = 26; // 0x1a
+ field public static final int O = 10000; // 0x2710
}
public final class Bundle extends android.os.BaseBundle implements java.lang.Cloneable android.os.Parcelable {
diff --git a/api/test-current.txt b/api/test-current.txt
index ef2fce7afc82..944a35078e51 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -30617,7 +30617,7 @@ package android.os {
field public static final int M = 23; // 0x17
field public static final int N = 24; // 0x18
field public static final int N_MR1 = 25; // 0x19
- field public static final int O = 26; // 0x1a
+ field public static final int O = 10000; // 0x2710
}
public final class Bundle extends android.os.BaseBundle implements java.lang.Cloneable android.os.Parcelable {
diff --git a/cmds/vr/src/com/android/commands/vr/Vr.java b/cmds/vr/src/com/android/commands/vr/Vr.java
index bf97bbaa019b..b765866faef9 100644
--- a/cmds/vr/src/com/android/commands/vr/Vr.java
+++ b/cmds/vr/src/com/android/commands/vr/Vr.java
@@ -16,7 +16,7 @@
package com.android.commands.vr;
-import android.app.CompatibilityDisplayProperties;
+import android.app.Vr2dDisplayProperties;
import android.content.Context;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -39,7 +39,7 @@ public final class Vr extends BaseCommand {
private static final String COMMAND_SET_PERSISTENT_VR_MODE_ENABLED =
"set-persistent-vr-mode-enabled";
- private static final String COMMAND_SET_COMPATIBILITY_DISPLAY_PROPERTIES =
+ private static final String COMMAND_SET_VR2D_DISPLAY_PROPERTIES =
"set-display-props";
private IVrManager mVrService;
@@ -63,8 +63,8 @@ public final class Vr extends BaseCommand {
String command = nextArgRequired();
switch (command) {
- case COMMAND_SET_COMPATIBILITY_DISPLAY_PROPERTIES:
- runSetCompatibilityDisplayProperties();
+ case COMMAND_SET_VR2D_DISPLAY_PROPERTIES:
+ runSetVr2dDisplayProperties();
break;
case COMMAND_SET_PERSISTENT_VR_MODE_ENABLED:
runSetPersistentVrModeEnabled();
@@ -74,7 +74,7 @@ public final class Vr extends BaseCommand {
}
}
- private void runSetCompatibilityDisplayProperties() throws RemoteException {
+ private void runSetVr2dDisplayProperties() throws RemoteException {
String widthStr = nextArgRequired();
int width = Integer.parseInt(widthStr);
@@ -84,11 +84,11 @@ public final class Vr extends BaseCommand {
String dpiStr = nextArgRequired();
int dpi = Integer.parseInt(dpiStr);
- CompatibilityDisplayProperties compatDisplayProperties =
- new CompatibilityDisplayProperties(width, height, dpi);
+ Vr2dDisplayProperties vr2dDisplayProperties =
+ new Vr2dDisplayProperties(width, height, dpi);
try {
- mVrService.setCompatibilityDisplayProperties(compatDisplayProperties);
+ mVrService.setVr2dDisplayProperties(vr2dDisplayProperties);
} catch (RemoteException re) {
System.err.println("Error: Can't set persistent mode " + re);
}
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index 65cb5f492285..0dfaf6a0da3a 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -244,8 +244,8 @@ public abstract class ActivityManagerInternal {
/**
* Called after virtual display Id is updated by
- * {@link com.android.server.vr.CompatibilityDisplay} with a specific
- * {@param compatibilityDisplayId}.
+ * {@link com.android.server.vr.Vr2dDisplay} with a specific
+ * {@param vr2dDisplayId}.
*/
- public abstract void setVrCompatibilityDisplayId(int vrCompatibilityDisplayId);
+ public abstract void setVr2dDisplayId(int vr2dDisplayId);
}
diff --git a/core/java/android/app/ITaskStackListener.aidl b/core/java/android/app/ITaskStackListener.aidl
index f369955cdc31..4994fbb0da3a 100644
--- a/core/java/android/app/ITaskStackListener.aidl
+++ b/core/java/android/app/ITaskStackListener.aidl
@@ -39,8 +39,11 @@ oneway interface ITaskStackListener {
* Called whenever IActivityManager.startActivity is called on an activity that is already
* running in the pinned stack and the activity is not actually started, but the task is either
* brought to the front or a new Intent is delivered to it.
+ *
+ * @param clearedTask whether or not the launch activity also cleared the task as a part of
+ * starting
*/
- void onPinnedActivityRestartAttempt();
+ void onPinnedActivityRestartAttempt(boolean clearedTask);
/**
* Called whenever the pinned stack is starting animating a resize.
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index c8b8c6c1b262..2e56bcf8a3de 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -4358,6 +4358,8 @@ public class Notification implements Parcelable
mN.mLargeIcon = null;
Bitmap largeIconLegacy = mN.largeIcon;
mN.largeIcon = null;
+ ArrayList<Action> actions = mActions;
+ mActions = new ArrayList<>();
Bundle publicExtras = new Bundle();
publicExtras.putBoolean(EXTRA_SHOW_WHEN,
savedBundle.getBoolean(EXTRA_SHOW_WHEN));
@@ -4373,6 +4375,7 @@ public class Notification implements Parcelable
mN.extras = savedBundle;
mN.mLargeIcon = largeIcon;
mN.largeIcon = largeIconLegacy;
+ mActions = actions;
mStyle = style;
return view;
}
diff --git a/core/java/android/app/TaskStackListener.java b/core/java/android/app/TaskStackListener.java
index 307fc9128ed2..2df011fb856e 100644
--- a/core/java/android/app/TaskStackListener.java
+++ b/core/java/android/app/TaskStackListener.java
@@ -39,7 +39,7 @@ public abstract class TaskStackListener extends ITaskStackListener.Stub {
}
@Override
- public void onPinnedActivityRestartAttempt() throws RemoteException {
+ public void onPinnedActivityRestartAttempt(boolean clearedTask) throws RemoteException {
}
@Override
diff --git a/core/java/android/app/CompatibilityDisplayProperties.aidl b/core/java/android/app/Vr2dDisplayProperties.aidl
index 626a63e05819..1e049433c052 100644
--- a/core/java/android/app/CompatibilityDisplayProperties.aidl
+++ b/core/java/android/app/Vr2dDisplayProperties.aidl
@@ -17,4 +17,4 @@
package android.app;
/** @hide */
-parcelable CompatibilityDisplayProperties;
+parcelable Vr2dDisplayProperties;
diff --git a/core/java/android/app/CompatibilityDisplayProperties.java b/core/java/android/app/Vr2dDisplayProperties.java
index 9a9bc2c40d94..a608bb08836f 100644
--- a/core/java/android/app/CompatibilityDisplayProperties.java
+++ b/core/java/android/app/Vr2dDisplayProperties.java
@@ -27,7 +27,7 @@ import java.io.PrintWriter;
*
* @hide
*/
-public class CompatibilityDisplayProperties implements Parcelable {
+public class Vr2dDisplayProperties implements Parcelable {
/**
* The actual width, height and dpi.
@@ -36,7 +36,7 @@ public class CompatibilityDisplayProperties implements Parcelable {
private final int mHeight;
private final int mDpi;
- public CompatibilityDisplayProperties(int width, int height, int dpi) {
+ public Vr2dDisplayProperties(int width, int height, int dpi) {
mWidth = width;
mHeight = height;
mDpi = dpi;
@@ -52,7 +52,7 @@ public class CompatibilityDisplayProperties implements Parcelable {
@Override
public String toString() {
- return "CompatibilityDisplayProperties{" +
+ return "Vr2dDisplayProperties{" +
"mWidth=" + mWidth +
", mHeight=" + mHeight +
", mDpi=" + mDpi +
@@ -64,7 +64,7 @@ public class CompatibilityDisplayProperties implements Parcelable {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
- CompatibilityDisplayProperties that = (CompatibilityDisplayProperties) o;
+ Vr2dDisplayProperties that = (Vr2dDisplayProperties) o;
if (getWidth() != that.getWidth()) return false;
if (getHeight() != that.getHeight()) return false;
@@ -83,27 +83,27 @@ public class CompatibilityDisplayProperties implements Parcelable {
dest.writeInt(mDpi);
}
- public static final Parcelable.Creator<CompatibilityDisplayProperties> CREATOR
- = new Parcelable.Creator<CompatibilityDisplayProperties>() {
+ public static final Parcelable.Creator<Vr2dDisplayProperties> CREATOR
+ = new Parcelable.Creator<Vr2dDisplayProperties>() {
@Override
- public CompatibilityDisplayProperties createFromParcel(Parcel source) {
- return new CompatibilityDisplayProperties(source);
+ public Vr2dDisplayProperties createFromParcel(Parcel source) {
+ return new Vr2dDisplayProperties(source);
}
@Override
- public CompatibilityDisplayProperties[] newArray(int size) {
- return new CompatibilityDisplayProperties[size];
+ public Vr2dDisplayProperties[] newArray(int size) {
+ return new Vr2dDisplayProperties[size];
}
};
- private CompatibilityDisplayProperties(Parcel source) {
+ private Vr2dDisplayProperties(Parcel source) {
mWidth = source.readInt();
mHeight = source.readInt();
mDpi = source.readInt();
}
public void dump(PrintWriter pw, String prefix) {
- pw.println(prefix + "CompatibilityDisplayProperties:");
+ pw.println(prefix + "Vr2dDisplayProperties:");
pw.println(prefix + " width=" + mWidth);
pw.println(prefix + " height=" + mHeight);
pw.println(prefix + " dpi=" + mDpi);
diff --git a/core/java/android/app/VrManager.java b/core/java/android/app/VrManager.java
index 878c8c38516d..040b330c2f30 100644
--- a/core/java/android/app/VrManager.java
+++ b/core/java/android/app/VrManager.java
@@ -45,20 +45,20 @@ public class VrManager {
}
/**
- * Sets the resolution and DPI of the compatibility virtual display used to display 2D
+ * Sets the resolution and DPI of the vr2d virtual display used to display 2D
* applications in VR mode.
*
* <p>Requires {@link android.Manifest.permission#ACCESS_VR_MANAGER} permission.</p>
*
- * @param {@link android.app.CompatibilityDisplayProperties} properties to be set to the
- * virtual display for 2D applications in VR mode.
+ * @param vr2dDisplayProp properties to be set to the virtual display for
+ * 2D applications in VR mode.
*
* {@hide}
*/
- public void setCompatibilityDisplayProperties(
- CompatibilityDisplayProperties compatDisplayProp) {
+ public void setVr2dDisplayProperties(
+ Vr2dDisplayProperties vr2dDisplayProp) {
try {
- mService.setCompatibilityDisplayProperties(compatDisplayProp);
+ mService.setVr2dDisplayProperties(vr2dDisplayProp);
} catch (RemoteException e) {
e.rethrowFromSystemServer();
}
diff --git a/core/java/android/app/assist/AssistStructure.java b/core/java/android/app/assist/AssistStructure.java
index 33535302bd5c..7261dfa09bb4 100644
--- a/core/java/android/app/assist/AssistStructure.java
+++ b/core/java/android/app/assist/AssistStructure.java
@@ -1559,14 +1559,14 @@ public class AssistStructure implements Parcelable {
@Override
public void setText(CharSequence text) {
ViewNodeText t = getNodeText();
- t.mText = text;
+ t.mText = TextUtils.trimNoCopySpans(text);
t.mTextSelectionStart = t.mTextSelectionEnd = -1;
}
@Override
public void setText(CharSequence text, int selectionStart, int selectionEnd) {
ViewNodeText t = getNodeText();
- t.mText = text;
+ t.mText = TextUtils.trimNoCopySpans(text);
t.mTextSelectionStart = selectionStart;
t.mTextSelectionEnd = selectionEnd;
}
@@ -1737,13 +1737,6 @@ public class AssistStructure implements Parcelable {
}
@Override
- public void setUrl(String url) {
- if (url == null) return;
-
- setWebDomain(url);
- }
-
- @Override
public void setWebDomain(@Nullable String domain) {
if (domain == null) {
mNode.mWebDomain = null;
diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java
index d1ad8de0b113..c58eaa14ed82 100644
--- a/core/java/android/bluetooth/BluetoothA2dp.java
+++ b/core/java/android/bluetooth/BluetoothA2dp.java
@@ -136,6 +136,38 @@ public final class BluetoothA2dp implements BluetoothProfile {
*/
public static final int STATE_NOT_PLAYING = 11;
+ /**
+ * We don't have a stored preference for whether or not the given A2DP sink device supports
+ * optional codecs.
+ * @hide */
+ public static final int OPTIONAL_CODECS_SUPPORT_UNKNOWN = -1;
+
+ /**
+ * The given A2DP sink device does not support optional codecs.
+ * @hide */
+ public static final int OPTIONAL_CODECS_NOT_SUPPORTED = 0;
+
+ /**
+ * The given A2DP sink device does support optional codecs.
+ * @hide */
+ public static final int OPTIONAL_CODECS_SUPPORTED = 1;
+
+ /**
+ * We don't have a stored preference for whether optional codecs should be enabled or disabled
+ * for the given A2DP device.
+ * @hide */
+ public static final int OPTIONAL_CODECS_PREF_UNKNOWN = -1;
+
+ /**
+ * Optional codecs should be disabled for the given A2DP device.
+ * @hide */
+ public static final int OPTIONAL_CODECS_PREF_DISABLED = 0;
+
+ /**
+ * Optional codecs should be enabled for the given A2DP device.
+ * @hide */
+ public static final int OPTIONAL_CODECS_PREF_ENABLED = 1;
+
private Context mContext;
private ServiceListener mServiceListener;
private final ReentrantReadWriteLock mServiceLock = new ReentrantReadWriteLock();
@@ -655,6 +687,88 @@ public final class BluetoothA2dp implements BluetoothProfile {
}
/**
+ * Returns whether this device supports optional codecs.
+ *
+ * @param device The device to check
+ * @return one of OPTIONAL_CODECS_SUPPORT_UNKNOWN, OPTIONAL_CODECS_NOT_SUPPORTED, or
+ * OPTIONAL_CODECS_SUPPORTED.
+ *
+ * @hide
+ */
+ public int supportsOptionalCodecs(BluetoothDevice device) {
+ try {
+ mServiceLock.readLock().lock();
+ if (mService != null && isEnabled() && isValidDevice(device)) {
+ return mService.supportsOptionalCodecs(device);
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return OPTIONAL_CODECS_SUPPORT_UNKNOWN;
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error talking to BT service in getSupportsOptionalCodecs()", e);
+ return OPTIONAL_CODECS_SUPPORT_UNKNOWN;
+ } finally {
+ mServiceLock.readLock().unlock();
+ }
+ }
+
+ /**
+ * Returns whether this device should have optional codecs enabled.
+ *
+ * @param device The device in question.
+ * @return one of OPTIONAL_CODECS_PREF_UNKNOWN, OPTIONAL_CODECS_PREF_ENABLED, or
+ * OPTIONAL_CODECS_PREF_DISABLED.
+ *
+ * @hide
+ */
+ public int getOptionalCodecsEnabled(BluetoothDevice device) {
+ try {
+ mServiceLock.readLock().lock();
+ if (mService != null && isEnabled() && isValidDevice(device)) {
+ return mService.getOptionalCodecsEnabled(device);
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return OPTIONAL_CODECS_PREF_UNKNOWN;
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error talking to BT service in getSupportsOptionalCodecs()", e);
+ return OPTIONAL_CODECS_PREF_UNKNOWN;
+ } finally {
+ mServiceLock.readLock().unlock();
+ }
+ }
+
+ /**
+ * Sets a persistent preference for whether a given device should have optional codecs enabled.
+ *
+ * @param device The device to set this preference for.
+ * @param value Whether the optional codecs should be enabled for this device. This should be
+ * one of OPTIONAL_CODECS_PREF_UNKNOWN, OPTIONAL_CODECS_PREF_ENABLED, or
+ * OPTIONAL_CODECS_PREF_DISABLED.
+ * @hide
+ */
+ public void setOptionalCodecsEnabled(BluetoothDevice device, int value) {
+ try {
+ if (value != BluetoothA2dp.OPTIONAL_CODECS_PREF_UNKNOWN &&
+ value != BluetoothA2dp.OPTIONAL_CODECS_PREF_DISABLED &&
+ value != BluetoothA2dp.OPTIONAL_CODECS_PREF_ENABLED) {
+ Log.e(TAG, "Invalid value passed to setOptionalCodecsEnabled: " + value);
+ return;
+ }
+ mServiceLock.readLock().lock();
+ if (mService != null && isEnabled()
+ && isValidDevice(device)) {
+ mService.setOptionalCodecsEnabled(device, value);
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return;
+ } catch (RemoteException e) {
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+ return;
+ } finally {
+ mServiceLock.readLock().unlock();
+ }
+ }
+
+ /**
* Helper for converting a state to a string.
*
* For debug use only - strings are not internationalized.
diff --git a/core/java/android/bluetooth/IBluetoothA2dp.aidl b/core/java/android/bluetooth/IBluetoothA2dp.aidl
index a775a1f90b8e..1b533cba3d2a 100644
--- a/core/java/android/bluetooth/IBluetoothA2dp.aidl
+++ b/core/java/android/bluetooth/IBluetoothA2dp.aidl
@@ -42,4 +42,7 @@ interface IBluetoothA2dp {
oneway void setCodecConfigPreference(in BluetoothCodecConfig codecConfig);
oneway void enableOptionalCodecs();
oneway void disableOptionalCodecs();
+ int supportsOptionalCodecs(in BluetoothDevice device);
+ int getOptionalCodecsEnabled(in BluetoothDevice device);
+ oneway void setOptionalCodecsEnabled(in BluetoothDevice device, int value);
}
diff --git a/core/java/android/net/INetworkScoreService.aidl b/core/java/android/net/INetworkScoreService.aidl
index 73e52c89dcc4..d163a4441097 100644
--- a/core/java/android/net/INetworkScoreService.aidl
+++ b/core/java/android/net/INetworkScoreService.aidl
@@ -45,7 +45,7 @@ interface INetworkScoreService
* Set the active scorer and clear existing scores.
* @param packageName the package name of the new scorer to use.
* @return true if the operation succeeded, or false if the new package is not a valid scorer.
- * @throws SecurityException if the caller is not the system.
+ * @throws SecurityException if the caller is not the system or a network scorer.
*/
boolean setActiveScorer(in String packageName);
diff --git a/core/java/android/net/NetworkScoreManager.java b/core/java/android/net/NetworkScoreManager.java
index eeb426a4bcf9..9f6e45ca6fb5 100644
--- a/core/java/android/net/NetworkScoreManager.java
+++ b/core/java/android/net/NetworkScoreManager.java
@@ -16,27 +16,20 @@
package android.net;
-import static android.net.NetworkRecommendationProvider.EXTRA_RECOMMENDATION_RESULT;
-
+import android.Manifest.permission;
import android.annotation.IntDef;
-import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
import android.content.Context;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.RemoteCallback;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.ServiceManager.ServiceNotFoundException;
-import com.android.internal.util.Preconditions;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.List;
-import java.util.concurrent.CompletableFuture;
/**
* Class that manages communication between network subsystems and a network scorer.
@@ -49,9 +42,9 @@ import java.util.concurrent.CompletableFuture;
*
* <p>A network scorer is any application which:
* <ul>
- * <li>Declares the {@link android.Manifest.permission#SCORE_NETWORKS} permission.
+ * <li>Declares the {@link permission#SCORE_NETWORKS} permission.
* <li>Include a Service for the {@link #ACTION_RECOMMEND_NETWORKS} action
- * protected by the {@link android.Manifest.permission#BIND_NETWORK_RECOMMENDATION_SERVICE}
+ * protected by the {@link permission#BIND_NETWORK_RECOMMENDATION_SERVICE}
* permission.
* </ul>
*
@@ -319,7 +312,7 @@ public class NetworkScoreManager {
*
* @return true if the operation succeeded, or false if the new package is not a valid scorer.
* @throws SecurityException if the caller is not a system process or does not hold the
- * {@link android.Manifest.permission#REQUEST_NETWORK_SCORES} permission
+ * {@link permission#SCORE_NETWORKS} permission
* @hide
*/
@SystemApi
@@ -351,7 +344,7 @@ public class NetworkScoreManager {
*
* @return true if the broadcast was sent, or false if there is no active scorer.
* @throws SecurityException if the caller does not hold the
- * {@link android.Manifest.permission#REQUEST_NETWORK_SCORES} permission.
+ * {@link permission#REQUEST_NETWORK_SCORES} permission.
* @hide
*/
public boolean requestScores(NetworkKey[] networks) throws SecurityException {
@@ -368,7 +361,7 @@ public class NetworkScoreManager {
* @param networkType the type of network this cache can handle. See {@link NetworkKey#type}.
* @param scoreCache implementation of {@link INetworkScoreCache} to store the scores.
* @throws SecurityException if the caller does not hold the
- * {@link android.Manifest.permission#REQUEST_NETWORK_SCORES} permission.
+ * {@link permission#REQUEST_NETWORK_SCORES} permission.
* @throws IllegalArgumentException if a score cache is already registered for this type.
* @deprecated equivalent to registering for cache updates with CACHE_FILTER_NONE.
* @hide
@@ -385,7 +378,7 @@ public class NetworkScoreManager {
* @param scoreCache implementation of {@link INetworkScoreCache} to store the scores
* @param filterType the {@link CacheUpdateFilter} to apply
* @throws SecurityException if the caller does not hold the
- * {@link android.Manifest.permission#REQUEST_NETWORK_SCORES} permission.
+ * {@link permission#REQUEST_NETWORK_SCORES} permission.
* @throws IllegalArgumentException if a score cache is already registered for this type.
* @hide
*/
@@ -404,7 +397,7 @@ public class NetworkScoreManager {
* @param networkType the type of network this cache can handle. See {@link NetworkKey#type}.
* @param scoreCache implementation of {@link INetworkScoreCache} to store the scores.
* @throws SecurityException if the caller does not hold the
- * {@link android.Manifest.permission#REQUEST_NETWORK_SCORES} permission.
+ * {@link permission#REQUEST_NETWORK_SCORES} permission.
* @throws IllegalArgumentException if a score cache is already registered for this type.
* @hide
*/
@@ -417,25 +410,6 @@ public class NetworkScoreManager {
}
/**
- * Request a recommendation for which network to connect to.
- *
- * <p>It is not safe to call this method from the main thread.
- *
- * @param request a {@link RecommendationRequest} instance containing additional
- * request details
- * @return a {@link RecommendationResult} instance containing the recommended network
- * to connect to
- * @throws SecurityException if the caller does not hold the
- * {@link android.Manifest.permission#REQUEST_NETWORK_SCORES} permission.
- * @hide
- * @deprecated to be removed.
- */
- public RecommendationResult requestRecommendation(RecommendationRequest request)
- throws SecurityException {
- return null;
- }
-
- /**
* Determine whether the application with the given UID is the enabled scorer.
*
* @param callingUid the UID to check
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 4bad7ab76be6..86fcfc8fb961 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -758,7 +758,7 @@ public class Build {
/**
* O.
*/
- public static final int O = 26;
+ public static final int O = CUR_DEVELOPMENT; // STOPSHIP Replace with the real version.
}
/** The type of build, like "user" or "eng". */
diff --git a/core/java/android/os/VintfObject.java b/core/java/android/os/VintfObject.java
index 1ef3916a743f..8302eceb772a 100644
--- a/core/java/android/os/VintfObject.java
+++ b/core/java/android/os/VintfObject.java
@@ -26,17 +26,12 @@ public class VintfObject {
private static final String LOG_TAG = "VintfObject";
/**
- * Slurps all device information (both manifests)
- * and report it.
+ * Slurps all device information (both manifests and both matrices)
+ * and report them.
* If any error in getting one of the manifests, it is not included in
* the list.
*/
- public static String[] report() {
- ArrayList<String> ret = new ArrayList<>();
- put(ret, getDeviceManifest(), "device manifest");
- put(ret, getFrameworkManifest(), "framework manifest");
- return ret.toArray(new String[0]);
- }
+ public static native String[] report();
/**
* Verify that the given metadata for an OTA package is compatible with
@@ -50,15 +45,4 @@ public class VintfObject {
*/
public static native int verify(String[] packageInfo);
- // return null if any error, otherwise XML string.
- private static native String getDeviceManifest();
- private static native String getFrameworkManifest();
-
- private static void put(ArrayList<String> list, String content, String message) {
- if (content == null || content.length() == 0) {
- Log.e(LOG_TAG, "Cannot get;" + message + "; check native logs for details.");
- return;
- }
- list.add(content);
- }
}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index f215ae7ce405..1f423ea66063 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -6789,7 +6789,8 @@ public final class Settings {
* Represented as milliseconds from midnight (e.g. 79200000 == 10pm).
* @hide
*/
- public static final String NIGHT_DISPLAY_CUSTOM_START_TIME = "night_display_custom_start_time";
+ public static final String NIGHT_DISPLAY_CUSTOM_START_TIME =
+ "night_display_custom_start_time";
/**
* Custom time when Night display is scheduled to deactivate.
@@ -6799,6 +6800,14 @@ public final class Settings {
public static final String NIGHT_DISPLAY_CUSTOM_END_TIME = "night_display_custom_end_time";
/**
+ * Time in milliseconds (since epoch) when Night display was last activated. Use to decide
+ * whether to apply the current activated state after a reboot or user change.
+ * @hide
+ */
+ public static final String NIGHT_DISPLAY_LAST_ACTIVATED_TIME =
+ "night_display_last_activated_time";
+
+ /**
* Names of the service components that the current user has explicitly allowed to
* be a VR mode listener, separated by ':'.
*
@@ -7024,6 +7033,7 @@ public final class Settings {
NIGHT_DISPLAY_CUSTOM_END_TIME,
NIGHT_DISPLAY_COLOR_TEMPERATURE,
NIGHT_DISPLAY_AUTO_MODE,
+ NIGHT_DISPLAY_LAST_ACTIVATED_TIME,
NIGHT_DISPLAY_ACTIVATED,
SYNC_PARENT_SOUNDS,
CAMERA_DOUBLE_TWIST_TO_FLIP_ENABLED,
@@ -8971,6 +8981,12 @@ public final class Settings {
public static final String
BLUETOOTH_A2DP_SRC_PRIORITY_PREFIX = "bluetooth_a2dp_src_priority_";
/** {@hide} */
+ public static final String BLUETOOTH_A2DP_SUPPORTS_OPTIONAL_CODECS_PREFIX =
+ "bluetooth_a2dp_supports_optional_codecs_";
+ /** {@hide} */
+ public static final String BLUETOOTH_A2DP_OPTIONAL_CODECS_ENABLED_PREFIX =
+ "bluetooth_a2dp_optional_codecs_enabled_";
+ /** {@hide} */
public static final String
BLUETOOTH_INPUT_DEVICE_PRIORITY_PREFIX = "bluetooth_input_device_priority_";
/** {@hide} */
@@ -9237,6 +9253,25 @@ public final class Settings {
}
/**
+ * Get the key that retrieves a bluetooth a2dp device's ability to support optional codecs.
+ * @hide
+ */
+ public static final String getBluetoothA2dpSupportsOptionalCodecsKey(String address) {
+ return BLUETOOTH_A2DP_SUPPORTS_OPTIONAL_CODECS_PREFIX +
+ address.toUpperCase(Locale.ROOT);
+ }
+
+ /**
+ * Get the key that retrieves whether a bluetooth a2dp device should have optional codecs
+ * enabled.
+ * @hide
+ */
+ public static final String getBluetoothA2dpOptionalCodecsEnabledKey(String address) {
+ return BLUETOOTH_A2DP_OPTIONAL_CODECS_ENABLED_PREFIX +
+ address.toUpperCase(Locale.ROOT);
+ }
+
+ /**
* Get the key that retrieves a bluetooth Input Device's priority.
* @hide
*/
@@ -10379,6 +10414,15 @@ public final class Settings {
public static final String MAX_NOTIFICATION_ENQUEUE_RATE = "max_notification_enqueue_rate";
/**
+ * Displays toasts when an app posts a notification that does not specify a valid channel.
+ *
+ * The value 1 - enable, 0 - disable
+ * @hide
+ */
+ public static final String SHOW_NOTIFICATION_CHANNEL_WARNINGS =
+ "show_notification_channel_warnings";
+
+ /**
* Whether cell is enabled/disabled
* @hide
*/
diff --git a/core/java/android/service/vr/IVrManager.aidl b/core/java/android/service/vr/IVrManager.aidl
index 8b2d0c6293e8..fc8afe9131b1 100644
--- a/core/java/android/service/vr/IVrManager.aidl
+++ b/core/java/android/service/vr/IVrManager.aidl
@@ -16,7 +16,7 @@
package android.service.vr;
-import android.app.CompatibilityDisplayProperties;
+import android.app.Vr2dDisplayProperties;
import android.service.vr.IVrStateCallbacks;
import android.service.vr.IPersistentVrStateCallbacks;
@@ -68,16 +68,16 @@ interface IVrManager {
void setPersistentVrModeEnabled(in boolean enabled);
/**
- * Sets the resolution and DPI of the compatibility virtual display used to display
+ * Sets the resolution and DPI of the vr2d virtual display used to display
* 2D applications in VR mode.
*
* <p>Requires {@link android.Manifest.permission#ACCESS_VR_MANAGER} permission.</p>
*
- * @param compatDisplayProperties Compatibitlity display properties to be set for
+ * @param vr2dDisplayProperties Vr2d display properties to be set for
* the VR virtual display
*/
- void setCompatibilityDisplayProperties(
- in CompatibilityDisplayProperties compatDisplayProperties);
+ void setVr2dDisplayProperties(
+ in Vr2dDisplayProperties vr2dDisplayProperties);
/**
* Return current virtual display id.
@@ -85,7 +85,7 @@ interface IVrManager {
* @return {@link android.view.Display.INVALID_DISPLAY} if there is no virtual display
* currently, else return the display id of the virtual display
*/
- int getCompatibilityDisplayId();
+ int getVr2dDisplayId();
/**
* Initiate connection for system controller data.
diff --git a/core/java/android/text/TextUtils.java b/core/java/android/text/TextUtils.java
index 081deebaed77..91f43d632dfd 100644
--- a/core/java/android/text/TextUtils.java
+++ b/core/java/android/text/TextUtils.java
@@ -1921,6 +1921,22 @@ public class TextUtils {
return false;
}
+ /**
+ * If the {@code charSequence} is instance of {@link Spanned}, creates a new copy and
+ * {@link NoCopySpan}'s are removed from the copy. Otherwise the given {@code charSequence} is
+ * returned as it is.
+ *
+ * @hide
+ */
+ @Nullable
+ public static CharSequence trimNoCopySpans(@Nullable CharSequence charSequence) {
+ if (charSequence != null && charSequence instanceof Spanned) {
+ // SpannableStringBuilder copy constructor trims NoCopySpans.
+ return new SpannableStringBuilder(charSequence);
+ }
+ return charSequence;
+ }
+
private static Object sLock = new Object();
private static char[] sTemp = null;
diff --git a/core/java/android/view/ViewStructure.java b/core/java/android/view/ViewStructure.java
index f71589c6c5ef..6bdc9ff5d0fa 100644
--- a/core/java/android/view/ViewStructure.java
+++ b/core/java/android/view/ViewStructure.java
@@ -374,13 +374,6 @@ public abstract class ViewStructure {
public abstract Rect getTempRect();
/**
- * @deprecated - use {@link #setWebDomain(String)} instead.
- * @hide
- */
- @Deprecated
- public abstract void setUrl(String url);
-
- /**
* Sets the Web domain represented by this node.
*
* <p>Typically used when the view is a container for an HTML document.
diff --git a/core/java/android/view/autofill/AutofillValue.java b/core/java/android/view/autofill/AutofillValue.java
index b57dab56318e..3beae11cf38c 100644
--- a/core/java/android/view/autofill/AutofillValue.java
+++ b/core/java/android/view/autofill/AutofillValue.java
@@ -26,6 +26,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Parcel;
import android.os.Parcelable;
+import android.text.TextUtils;
import android.view.View;
import com.android.internal.util.Preconditions;
@@ -257,7 +258,8 @@ public final class AutofillValue implements Parcelable {
* <p>See {@link View#AUTOFILL_TYPE_TEXT} for more info.
*/
public static AutofillValue forText(@Nullable CharSequence value) {
- return value == null ? null : new AutofillValue(AUTOFILL_TYPE_TEXT, value);
+ return value == null ? null : new AutofillValue(AUTOFILL_TYPE_TEXT,
+ TextUtils.trimNoCopySpans(value));
}
/**
diff --git a/core/java/android/view/textclassifier/TextClassifierImpl.java b/core/java/android/view/textclassifier/TextClassifierImpl.java
index ebf1c0189b15..209ff097f9e6 100644
--- a/core/java/android/view/textclassifier/TextClassifierImpl.java
+++ b/core/java/android/view/textclassifier/TextClassifierImpl.java
@@ -607,6 +607,7 @@ final class TextClassifierImpl implements TextClassifier {
@Nullable
public static Intent create(Context context, String type, String text) {
type = type.trim().toLowerCase(Locale.ENGLISH);
+ text = text.trim();
switch (type) {
case TextClassifier.TYPE_EMAIL:
return new Intent(Intent.ACTION_SENDTO)
@@ -618,6 +619,9 @@ final class TextClassifierImpl implements TextClassifier {
return new Intent(Intent.ACTION_VIEW)
.setData(Uri.parse(String.format("geo:0,0?q=%s", text)));
case TextClassifier.TYPE_URL:
+ if (!text.startsWith("https://") && !text.startsWith("http://")) {
+ text = "http://" + text;
+ }
return new Intent(Intent.ACTION_VIEW, Uri.parse(text))
.putExtra(Browser.EXTRA_APPLICATION_ID, context.getPackageName());
default:
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index ad3a99d3610f..b0d63951971b 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -1404,6 +1404,11 @@ public class Editor {
// or double-clicks that could "dismiss" the floating toolbar.
int delay = ViewConfiguration.getDoubleTapTimeout();
mTextView.postDelayed(mShowFloatingToolbar, delay);
+
+ // This classifies the text and most likely returns before the toolbar is actually
+ // shown. If not, it will update the toolbar with the result when classification
+ // returns. We would rather not wait for a long running classification process.
+ invalidateActionModeAsync();
}
}
@@ -1853,7 +1858,7 @@ public class Editor {
mInsertionPointCursorController.invalidateHandle();
}
if (mTextActionMode != null) {
- invalidateActionModeAsync();
+ invalidateActionMode();
}
}
@@ -1945,12 +1950,12 @@ public class Editor {
if (mRestartActionModeOnNextRefresh) {
// To avoid distraction, newly start action mode only when selection action
// mode is being restarted.
- startSelectionActionMode();
+ startSelectionActionModeAsync(false);
}
} else if (selectionController == null || !selectionController.isActive()) {
// Insertion action mode is active. Avoid dismissing the selection.
stopTextActionModeWithPreservingSelection();
- startSelectionActionMode();
+ startSelectionActionModeAsync(false);
} else {
mTextActionMode.invalidateContentRect();
}
@@ -2004,22 +2009,24 @@ public class Editor {
/**
* Asynchronously starts a selection action mode using the TextClassifier.
*/
- void startSelectionActionModeAsync() {
- getSelectionActionModeHelper().startActionModeAsync();
+ void startSelectionActionModeAsync(boolean adjustSelection) {
+ getSelectionActionModeHelper().startActionModeAsync(adjustSelection);
}
/**
- * Synchronously starts a selection action mode without the TextClassifier.
+ * Asynchronously invalidates an action mode using the TextClassifier.
*/
- void startSelectionActionMode() {
- getSelectionActionModeHelper().startActionMode();
+ private void invalidateActionModeAsync() {
+ getSelectionActionModeHelper().invalidateActionModeAsync();
}
/**
- * Asynchronously invalidates an action mode using the TextClassifier.
+ * Synchronously invalidates an action mode without the TextClassifier.
*/
- private void invalidateActionModeAsync() {
- getSelectionActionModeHelper().invalidateActionModeAsync();
+ private void invalidateActionMode() {
+ if (mTextActionMode != null) {
+ mTextActionMode.invalidate();
+ }
}
private SelectionActionModeHelper getSelectionActionModeHelper() {
@@ -2075,7 +2082,7 @@ public class Editor {
}
if (mTextActionMode != null) {
// Text action mode is already started
- invalidateActionModeAsync();
+ invalidateActionMode();
return false;
}
@@ -4703,7 +4710,7 @@ public class Editor {
}
positionAtCursorOffset(offset, false);
if (mTextActionMode != null) {
- invalidateActionModeAsync();
+ invalidateActionMode();
}
}
@@ -4787,7 +4794,7 @@ public class Editor {
}
updateDrawable();
if (mTextActionMode != null) {
- invalidateActionModeAsync();
+ invalidateActionMode();
}
}
@@ -5414,13 +5421,8 @@ public class Editor {
resetDragAcceleratorState();
if (mTextView.hasSelection()) {
- // Do not invoke the text assistant if this was a drag selection.
- if (mHaventMovedEnoughToStartDrag) {
- startSelectionActionModeAsync();
- } else {
- startSelectionActionMode();
- }
-
+ // Drag selection should not be adjusted by the text classifier.
+ startSelectionActionModeAsync(mHaventMovedEnoughToStartDrag);
}
break;
}
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index 1457d026ea39..569fe017ac86 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -49,7 +49,6 @@ import android.view.accessibility.AccessibilityNodeProvider;
import android.widget.RemoteViews.RemoteView;
import com.android.internal.R;
-import com.android.internal.util.Preconditions;
import com.google.android.collect.Lists;
@@ -336,11 +335,6 @@ public class ListView extends AbsListView {
* @param isSelectable whether the item is selectable
*/
public void addHeaderView(View v, Object data, boolean isSelectable) {
- Preconditions.checkState(
- v.getParent() == null,
- "The specified child already has a parent. "
- + "You must call removeView() on the child's parent first.");
-
final FixedViewInfo info = new FixedViewInfo();
info.view = v;
info.data = data;
@@ -435,11 +429,6 @@ public class ListView extends AbsListView {
* @param isSelectable true if the footer view can be selected
*/
public void addFooterView(View v, Object data, boolean isSelectable) {
- Preconditions.checkState(
- v.getParent() == null,
- "The specified child already has a parent. "
- + "You must call removeView() on the child's parent first.");
-
final FixedViewInfo info = new FixedViewInfo();
info.view = v;
info.data = data;
diff --git a/core/java/android/widget/SelectionActionModeHelper.java b/core/java/android/widget/SelectionActionModeHelper.java
index c9d172fa78b5..16a1087510d3 100644
--- a/core/java/android/widget/SelectionActionModeHelper.java
+++ b/core/java/android/widget/SelectionActionModeHelper.java
@@ -65,7 +65,7 @@ final class SelectionActionModeHelper {
textView.getTextClassifier(), textView.getText(), 0, 1, textView.getTextLocales());
}
- public void startActionModeAsync() {
+ public void startActionModeAsync(boolean adjustSelection) {
cancelAsyncTask();
if (isNoOpTextClassifier() || !hasSelection()) {
// No need to make an async call for a no-op TextClassifier.
@@ -74,16 +74,16 @@ final class SelectionActionModeHelper {
} else {
resetTextClassificationHelper();
mTextClassificationAsyncTask = new TextClassificationAsyncTask(
- mEditor.getTextView(), TIMEOUT_DURATION,
- mTextClassificationHelper::suggestSelection, this::startActionMode)
+ mEditor.getTextView(),
+ TIMEOUT_DURATION,
+ adjustSelection
+ ? mTextClassificationHelper::suggestSelection
+ : mTextClassificationHelper::classifyText,
+ this::startActionMode)
.execute();
}
}
- public void startActionMode() {
- startActionMode(null);
- }
-
public void invalidateActionModeAsync() {
cancelAsyncTask();
if (isNoOpTextClassifier() || !hasSelection()) {
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 242dcf535d32..eaf111521574 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -10579,7 +10579,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
Selection.setSelection((Spannable) text, start, end);
// Make sure selection mode is engaged.
if (mEditor != null) {
- mEditor.startSelectionActionMode();
+ mEditor.startSelectionActionModeAsync(false);
}
return true;
}
diff --git a/core/jni/android_os_VintfObject.cpp b/core/jni/android_os_VintfObject.cpp
index 9491a1ecdad3..033f2dfe5173 100644
--- a/core/jni/android_os_VintfObject.cpp
+++ b/core/jni/android_os_VintfObject.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 The Android Open Source Project
+ * 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.
@@ -16,6 +16,10 @@
#define LOG_TAG "VintfObject"
//#define LOG_NDEBUG 0
+#include <android-base/logging.h>
+
+#include <vector>
+#include <string>
#include <JNIHelp.h>
#include <vintf/VintfObject.h>
@@ -23,31 +27,48 @@
#include "core_jni_helpers.h"
+static jclass gString;
+
namespace android {
-using vintf::HalManifest;
-using vintf::RuntimeInfo;
using vintf::VintfObject;
using vintf::gHalManifestConverter;
+using vintf::gCompatibilityMatrixConverter;
+using vintf::XmlConverter;
-static jstring android_os_VintfObject_getDeviceManifest(JNIEnv* env, jclass clazz)
-{
- const HalManifest *manifest = VintfObject::GetDeviceHalManifest();
- if (manifest == nullptr) {
- return nullptr;
+static inline jobjectArray toJavaStringArray(JNIEnv* env, const std::vector<std::string>& v) {
+ jobjectArray ret = env->NewObjectArray(v.size(), gString, NULL /* init element */);
+ for (size_t i = 0; i < v.size(); ++i) {
+ env->SetObjectArrayElement(ret, i, env->NewStringUTF(v[i].c_str()));
}
- std::string xml = gHalManifestConverter(*manifest);
- return env->NewStringUTF(xml.c_str());
+ return ret;
}
-static jstring android_os_VintfObject_getFrameworkManifest(JNIEnv* env, jclass clazz)
-{
- const HalManifest *manifest = VintfObject::GetFrameworkHalManifest();
- if (manifest == nullptr) {
- return nullptr;
+template<typename T>
+static void tryAddSchema(const T* object, const XmlConverter<T>& converter,
+ const std::string& description,
+ std::vector<std::string>* cStrings) {
+ if (object == nullptr) {
+ LOG(WARNING) << __FUNCTION__ << "Cannot get " << description;
+ } else {
+ cStrings->push_back(converter(*object));
}
- std::string xml = gHalManifestConverter(*manifest);
- return env->NewStringUTF(xml.c_str());
+}
+
+static jobjectArray android_os_VintfObject_report(JNIEnv* env, jclass clazz)
+{
+ std::vector<std::string> cStrings;
+
+ tryAddSchema(VintfObject::GetDeviceHalManifest(), gHalManifestConverter,
+ "device manifest", &cStrings);
+ tryAddSchema(VintfObject::GetFrameworkHalManifest(), gHalManifestConverter,
+ "framework manifest", &cStrings);
+ tryAddSchema(VintfObject::GetDeviceCompatibilityMatrix(), gCompatibilityMatrixConverter,
+ "device compatibility matrix", &cStrings);
+ tryAddSchema(VintfObject::GetFrameworkCompatibilityMatrix(), gCompatibilityMatrixConverter,
+ "framework compatibility matrix", &cStrings);
+
+ return toJavaStringArray(env, cStrings);
}
static jint android_os_VintfObject_verify(JNIEnv *env, jclass clazz, jobjectArray packageInfo) {
@@ -66,15 +87,18 @@ static jint android_os_VintfObject_verify(JNIEnv *env, jclass clazz, jobjectArra
// ----------------------------------------------------------------------------
static const JNINativeMethod gVintfObjectMethods[] = {
- {"getDeviceManifest", "()Ljava/lang/String;", (void*)android_os_VintfObject_getDeviceManifest},
- {"getFrameworkManifest", "()Ljava/lang/String;", (void*)android_os_VintfObject_getFrameworkManifest},
- {"verify", "([Ljava/lang/String;)I", (void*)android_os_VintfObject_verify},
+ {"report", "()[Ljava/lang/String;", (void*)android_os_VintfObject_report},
+ {"verify", "([Ljava/lang/String;)I", (void*)android_os_VintfObject_verify},
};
+
const char* const kVintfObjectPathName = "android/os/VintfObject";
int register_android_os_VintfObject(JNIEnv* env)
{
+
+ gString = MakeGlobalRefOrDie(env, FindClassOrDie(env, "java/lang/String"));
+
return RegisterMethodsOrDie(env, kVintfObjectPathName, gVintfObjectMethods,
NELEM(gVintfObjectMethods));
}
diff --git a/core/proto/android/providers/settings.proto b/core/proto/android/providers/settings.proto
index ce951defadbc..ea40fd5bb472 100644
--- a/core/proto/android/providers/settings.proto
+++ b/core/proto/android/providers/settings.proto
@@ -329,6 +329,8 @@ message GlobalSettingsProto {
SettingProto max_notification_enqueue_rate = 284;
SettingProto cell_on = 285;
SettingProto network_recommendations_package = 286;
+ SettingProto bluetooth_a2dp_supports_optional_codecs_prefix = 287;
+ SettingProto bluetooth_a2dp_optional_codecs_enabled_prefix = 288;
}
message SecureSettingsProto {
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index a921fd740b7e..aeb564b49ea8 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1299,9 +1299,9 @@
* Include a Service for the android.net.scoring.RECOMMEND_NETWORKS action
protected by the BIND_NETWORK_RECOMMENDATION_SERVICE permission.
- This must be set to a valid network recommendation app.
+ This must be set to a valid network recommendation app or empty.
-->
- <string name="config_defaultNetworkRecommendationProviderPackage" translatable="false">com.android.networkrecommendation</string>
+ <string name="config_defaultNetworkRecommendationProviderPackage" translatable="false"></string>
<!-- Whether to enable Hardware FLP overlay which allows Hardware FLP to be
replaced by an app at run-time. When disabled, only the
@@ -2872,4 +2872,8 @@
<!-- Additional non-platform defined secure settings exposed to Instant Apps -->
<string-array name="config_allowedSecureInstantAppSettings"></string-array>
+
+ <!-- Handle volume keys directly in Window Manager without passing them to the foreground app -->
+ <bool name="config_handleVolumeKeysInWindowManager">false</bool>
+
</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 1966f6a89412..cff6eb198473 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3010,4 +3010,5 @@
<java-symbol type="array" name="config_allowedSystemInstantAppSettings" />
<java-symbol type="array" name="config_allowedSecureInstantAppSettings" />
+ <java-symbol type="bool" name="config_handleVolumeKeysInWindowManager" />
</resources>
diff --git a/core/tests/coretests/src/android/os/VintfObjectTest.java b/core/tests/coretests/src/android/os/VintfObjectTest.java
index aaaf55ccf799..821ee806743d 100644
--- a/core/tests/coretests/src/android/os/VintfObjectTest.java
+++ b/core/tests/coretests/src/android/os/VintfObjectTest.java
@@ -26,5 +26,8 @@ public class VintfObjectTest extends TestCase {
// From /system/manifest.xml
assertTrue(String.join("", xmls).contains(
"<manifest version=\"1.0\" type=\"framework\">"));
+ // From /system/compatibility-matrix.xml
+ assertTrue(String.join("", xmls).contains(
+ "<compatibility-matrix version=\"1.0\" type=\"framework\">"));
}
}
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 99909acb9c0a..aeed20e211a2 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -109,6 +109,8 @@ public class SettingsBackupTest {
Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE,
Settings.Global.BLUETOOTH_A2DP_SINK_PRIORITY_PREFIX,
Settings.Global.BLUETOOTH_A2DP_SRC_PRIORITY_PREFIX,
+ Settings.Global.BLUETOOTH_A2DP_SUPPORTS_OPTIONAL_CODECS_PREFIX,
+ Settings.Global.BLUETOOTH_A2DP_OPTIONAL_CODECS_ENABLED_PREFIX,
Settings.Global.BLUETOOTH_DISABLED_PROFILES,
Settings.Global.BLUETOOTH_HEADSET_PRIORITY_PREFIX,
Settings.Global.BLUETOOTH_INPUT_DEVICE_PRIORITY_PREFIX,
diff --git a/core/tests/coretests/src/android/view/textclassifier/TextClassificationManagerTest.java b/core/tests/coretests/src/android/view/textclassifier/TextClassificationManagerTest.java
index f59e4fc188d4..742fd60e25f7 100644
--- a/core/tests/coretests/src/android/view/textclassifier/TextClassificationManagerTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/TextClassificationManagerTest.java
@@ -118,7 +118,7 @@ public class TextClassificationManagerTest {
if (isTextClassifierDisabled()) return;
String text = "Visit http://www.android.com for more information";
- String classifiedText = "http://www.android.com";
+ String classifiedText = "www.android.com";
int startIndex = text.indexOf(classifiedText);
int endIndex = startIndex + classifiedText.length();
assertThat(mClassifier.classifyText(text, startIndex, endIndex, LOCALES),
@@ -193,7 +193,19 @@ public class TextClassificationManagerTest {
public boolean matches(Object o) {
if (o instanceof TextClassification) {
TextClassification result = (TextClassification) o;
- return text.equals(result.getText())
+ final boolean typeRequirementSatisfied;
+ switch (type) {
+ case TextClassifier.TYPE_URL:
+ String scheme = result.getIntent().getData().getScheme();
+ typeRequirementSatisfied = "http".equalsIgnoreCase(scheme)
+ || "https".equalsIgnoreCase(scheme);
+ break;
+ default:
+ typeRequirementSatisfied = true;
+ }
+
+ return typeRequirementSatisfied
+ && text.equals(result.getText())
&& result.getEntityCount() > 0
&& type.equals(result.getEntity(0));
// TODO: Include other properties.
diff --git a/libs/hwui/tests/unit/FrameBuilderTests.cpp b/libs/hwui/tests/unit/FrameBuilderTests.cpp
index bd798e8dc688..fcdd814bb63e 100644
--- a/libs/hwui/tests/unit/FrameBuilderTests.cpp
+++ b/libs/hwui/tests/unit/FrameBuilderTests.cpp
@@ -819,7 +819,7 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, deferColorOp_unbounded) {
EXPECT_EQ(1, renderer.getIndex()) << "ColorOp should not be rejected";
}
-OPENGL_PIPELINE_TEST(FrameBuilder, renderNode) {
+RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, renderNode) {
class RenderNodeTestRenderer : public TestRendererBase {
public:
void onRectOp(const RectOp& op, const BakedOpState& state) override {
@@ -2321,7 +2321,7 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, clip_replace) {
EXPECT_EQ(1, renderer.getIndex());
}
-OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderProjectedInMiddle) {
+RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderProjectedInMiddle) {
/* R is backward projected on B
A
/ \
@@ -2351,7 +2351,7 @@ OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderProjectedInMiddle) {
EXPECT_EQ(3, renderer.getIndex());
}
-OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderProjectLast) {
+RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderProjectLast) {
/* R is backward projected on E
A
/ | \
@@ -2383,7 +2383,7 @@ OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderProjectLast) {
EXPECT_EQ(4, renderer.getIndex());
}
-OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderNoReceivable) {
+RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderNoReceivable) {
/* R is backward projected without receiver
A
/ \
@@ -2412,7 +2412,7 @@ OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderNoReceivable) {
EXPECT_EQ(2, renderer.getIndex());
}
-OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderParentReceivable) {
+RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderParentReceivable) {
/* R is backward projected on C
A
/ \
@@ -2441,7 +2441,7 @@ OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderParentReceivable) {
EXPECT_EQ(3, renderer.getIndex());
}
-OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderSameNodeReceivable) {
+RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderSameNodeReceivable) {
auto nodeA = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
[](RenderProperties& props, RecordingCanvas& canvas) {
drawOrderedNode(&canvas, 0, nullptr); //nodeB
@@ -2464,7 +2464,7 @@ OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderSameNodeReceivable) {
EXPECT_EQ(2, renderer.getIndex());
}
-OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderProjectedSibling) {
+RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderProjectedSibling) {
//TODO: this test together with the next "projectionReorderProjectedSibling2" likely expose a
//bug in HWUI. First test draws R, while the second test does not draw R for a nearly identical
//tree setup. The correct behaviour is to not draw R, because the receiver cannot be a sibling
@@ -2497,7 +2497,7 @@ OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderProjectedSibling) {
EXPECT_EQ(3, renderer.getIndex());
}
-OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderProjectedSibling2) {
+RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderProjectedSibling2) {
/* R is set to project on B, but R is not drawn because projecting on a sibling is not allowed.
A
|
@@ -2530,7 +2530,7 @@ OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderProjectedSibling2) {
EXPECT_EQ(3, renderer.getIndex());
}
-OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderGrandparentReceivable) {
+RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderGrandparentReceivable) {
/* R is backward projected on B
A
|
@@ -2562,7 +2562,7 @@ OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderGrandparentReceivable) {
EXPECT_EQ(3, renderer.getIndex());
}
-OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderTwoReceivables) {
+RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderTwoReceivables) {
/* B and G are receivables, R is backward projected
A
/ \
@@ -2595,7 +2595,7 @@ OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderTwoReceivables) {
EXPECT_EQ(4, renderer.getIndex());
}
-OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderTwoReceivablesLikelyScenario) {
+RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderTwoReceivablesLikelyScenario) {
/* B and G are receivables, G is backward projected
A
/ \
@@ -2628,7 +2628,7 @@ OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderTwoReceivablesLikelyScenario
EXPECT_EQ(4, renderer.getIndex());
}
-OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderTwoReceivablesDeeper) {
+RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderTwoReceivablesDeeper) {
/* B and G are receivables, R is backward projected
A
/ \
diff --git a/obex/javax/obex/ServerSession.java b/obex/javax/obex/ServerSession.java
index 3831cf7285da..dbfeefdfb037 100644
--- a/obex/javax/obex/ServerSession.java
+++ b/obex/javax/obex/ServerSession.java
@@ -104,7 +104,6 @@ public final class ServerSession extends ObexSession implements Runnable {
case ObexHelper.OBEX_OPCODE_DISCONNECT:
handleDisconnectRequest();
- done = true;
break;
case ObexHelper.OBEX_OPCODE_GET:
diff --git a/packages/CarrierDefaultApp/AndroidManifest.xml b/packages/CarrierDefaultApp/AndroidManifest.xml
index 2ef1cf59ffc5..c30913393075 100644
--- a/packages/CarrierDefaultApp/AndroidManifest.xml
+++ b/packages/CarrierDefaultApp/AndroidManifest.xml
@@ -34,6 +34,7 @@
<intent-filter>
<action android:name="com.android.internal.telephony.CARRIER_SIGNAL_REDIRECTED" />
<action android:name="com.android.internal.telephony.CARRIER_SIGNAL_RESET" />
+ <action android:name="android.intent.action.LOCALE_CHANGED" />
</intent-filter>
</receiver>
<service android:name="com.android.carrierdefaultapp.ProvisionObserver"
diff --git a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierActionUtils.java b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierActionUtils.java
index 7fd16019267e..021330650975 100644
--- a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierActionUtils.java
+++ b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierActionUtils.java
@@ -112,8 +112,6 @@ public class CarrierActionUtils {
private static void onShowCaptivePortalNotification(Intent intent, Context context) {
logd("onShowCaptivePortalNotification");
- final NotificationManager notificationMgr = context.getSystemService(
- NotificationManager.class);
Intent portalIntent = new Intent(context, CaptivePortalLoginActivity.class);
portalIntent.putExtras(intent);
portalIntent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT
@@ -123,7 +121,8 @@ public class CarrierActionUtils {
Notification notification = getNotification(context, R.string.portal_notification_id,
R.string.portal_notification_detail, pendingIntent);
try {
- notificationMgr.notify(PORTAL_NOTIFICATION_TAG, PORTAL_NOTIFICATION_ID, notification);
+ context.getSystemService(NotificationManager.class)
+ .notify(PORTAL_NOTIFICATION_TAG, PORTAL_NOTIFICATION_ID, notification);
} catch (NullPointerException npe) {
loge("setNotificationVisible: " + npe);
}
@@ -131,12 +130,11 @@ public class CarrierActionUtils {
private static void onShowNoDataServiceNotification(Context context) {
logd("onShowNoDataServiceNotification");
- final NotificationManager notificationMgr = context.getSystemService(
- NotificationManager.class);
Notification notification = getNotification(context, R.string.no_data_notification_id,
R.string.no_data_notification_detail, null);
try {
- notificationMgr.notify(NO_DATA_NOTIFICATION_TAG, NO_DATA_NOTIFICATION_ID, notification);
+ context.getSystemService(NotificationManager.class)
+ .notify(NO_DATA_NOTIFICATION_TAG, NO_DATA_NOTIFICATION_ID, notification);
} catch (NullPointerException npe) {
loge("setNotificationVisible: " + npe);
}
@@ -144,26 +142,16 @@ public class CarrierActionUtils {
private static void onCancelAllNotifications(Context context) {
logd("onCancelAllNotifications");
- final NotificationManager notificationMgr = context.getSystemService(
- NotificationManager.class);
- notificationMgr.cancelAll();
+ context.getSystemService(NotificationManager.class).cancelAll();
}
private static Notification getNotification(Context context, int titleId, int textId,
PendingIntent pendingIntent) {
final TelephonyManager telephonyMgr = context.getSystemService(TelephonyManager.class);
- final NotificationManager notificationManager = context.getSystemService(
- NotificationManager.class);
final Resources resources = context.getResources();
final Bundle extras = Bundle.forPair(Notification.EXTRA_SUBSTITUTE_APP_NAME,
resources.getString(R.string.android_system_label));
- /* Creates the notification channel and registers it with NotificationManager. If a channel
- * with the same ID is already registered, NotificationManager will ignore this call.
- */
- notificationManager.createNotificationChannel(new NotificationChannel(
- NOTIFICATION_CHANNEL_ID_MOBILE_DATA_STATUS,
- resources.getString(R.string.mobile_data_status_notification_channel_name),
- NotificationManager.IMPORTANCE_DEFAULT));
+ createNotificationChannels(context);
Notification.Builder builder = new Notification.Builder(context)
.setContentTitle(resources.getString(titleId))
.setContentText(String.format(resources.getString(textId),
@@ -187,6 +175,19 @@ public class CarrierActionUtils {
return builder.build();
}
+ /**
+ * Creates the notification channel and registers it with NotificationManager. Also used to
+ * update an existing channel's name.
+ */
+ static void createNotificationChannels(Context context) {
+ context.getSystemService(NotificationManager.class)
+ .createNotificationChannel(new NotificationChannel(
+ NOTIFICATION_CHANNEL_ID_MOBILE_DATA_STATUS,
+ context.getResources().getString(
+ R.string.mobile_data_status_notification_channel_name),
+ NotificationManager.IMPORTANCE_DEFAULT));
+ }
+
private static void logd(String s) {
Log.d(TAG, s);
}
diff --git a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierDefaultBroadcastReceiver.java b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierDefaultBroadcastReceiver.java
index 3fd89d97617e..3f55ff514913 100644
--- a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierDefaultBroadcastReceiver.java
+++ b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierDefaultBroadcastReceiver.java
@@ -32,6 +32,10 @@ public class CarrierDefaultBroadcastReceiver extends BroadcastReceiver{
Log.d(TAG, "skip carrier actions during provisioning");
return;
}
+ if (Intent.ACTION_LOCALE_CHANGED.equals(intent.getAction())) {
+ CarrierActionUtils.createNotificationChannels(context);
+ return;
+ }
List<Integer> actionList = CustomConfigLoader.loadCarrierActionList(context, intent);
for (int actionIdx : actionList) {
Log.d(TAG, "apply carrier action idx: " + actionIdx);
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index 5a178a50408b..eb513e170286 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -998,7 +998,8 @@ public class AccessPoint implements Comparable<AccessPoint> {
if (mRssi != info.getRssi()) {
mRssi = info.getRssi();
updated = true;
- } else if (mNetworkInfo.getDetailedState() != networkInfo.getDetailedState()) {
+ } else if (mNetworkInfo != null && networkInfo != null
+ && mNetworkInfo.getDetailedState() != networkInfo.getDetailedState()) {
updated = true;
}
mInfo = info;
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
index 646b6ba84ebb..be15e657d1c3 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
@@ -124,7 +124,8 @@ public class WifiTracker {
*/
private final Object mLock = new Object();
- //visible to both worker and main thread. Guarded by #mInternalAccessPoints
+ //visible to both worker and main thread.
+ @GuardedBy("mLock")
private final AccessPointListenerAdapter mAccessPointListenerAdapter
= new AccessPointListenerAdapter();
@@ -1005,12 +1006,13 @@ public class WifiTracker {
if (DBG) {
Log.d(TAG, "Starting to copy AP items on the MainHandler");
}
- if (notifyListeners) {
- notificationMap = mAccessPointListenerAdapter.mPendingNotifications.clone();
- }
-
- mAccessPointListenerAdapter.mPendingNotifications.clear();
synchronized (mLock) {
+ if (notifyListeners) {
+ notificationMap = mAccessPointListenerAdapter.mPendingNotifications.clone();
+ }
+
+ mAccessPointListenerAdapter.mPendingNotifications.clear();
+
for (AccessPoint internalAccessPoint : mInternalAccessPoints) {
AccessPoint accessPoint = oldAccessPoints.get(internalAccessPoint.mId);
if (accessPoint == null) {
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
index f519a906eab5..d4ce40c7c0a8 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
@@ -465,9 +465,9 @@ public class WifiTrackerTest {
private void updateScoresAndWaitForAccessPointsChangedCallback() throws InterruptedException {
// Updating scores can happen together or one after the other, so the latch countdown is set
// to 2.
- mAccessPointsChangedLatch = new CountDownLatch(3);
+ mAccessPointsChangedLatch = new CountDownLatch(2);
updateScores();
- assertTrue("onAccessPointChanged was not called three times",
+ assertTrue("onAccessPointChanged was not called twice",
mAccessPointsChangedLatch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS));
}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index 885573e86ac6..c7c2222f8230 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -696,6 +696,12 @@ class SettingsProtoDumpUtil {
Settings.Global.BLUETOOTH_A2DP_SRC_PRIORITY_PREFIX,
GlobalSettingsProto.BLUETOOTH_A2DP_SRC_PRIORITY_PREFIX);
dumpSetting(s, p,
+ Settings.Global.BLUETOOTH_A2DP_SUPPORTS_OPTIONAL_CODECS_PREFIX,
+ GlobalSettingsProto.BLUETOOTH_A2DP_SUPPORTS_OPTIONAL_CODECS_PREFIX);
+ dumpSetting(s, p,
+ Settings.Global.BLUETOOTH_A2DP_OPTIONAL_CODECS_ENABLED_PREFIX,
+ GlobalSettingsProto.BLUETOOTH_A2DP_OPTIONAL_CODECS_ENABLED_PREFIX);
+ dumpSetting(s, p,
Settings.Global.BLUETOOTH_INPUT_DEVICE_PRIORITY_PREFIX,
GlobalSettingsProto.BLUETOOTH_INPUT_DEVICE_PRIORITY_PREFIX);
dumpSetting(s, p,
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java
index 7d78c089b089..9ef05c5d4125 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java
@@ -16,6 +16,7 @@ package com.android.systemui.plugins.qs;
import android.content.Context;
import android.graphics.drawable.Drawable;
+import android.metrics.LogMaker;
import android.service.quicksettings.Tile;
import com.android.systemui.plugins.annotations.DependsOn;
@@ -66,6 +67,10 @@ public interface QSTile {
State getState();
+ default LogMaker populate(LogMaker logMaker) {
+ return logMaker;
+ }
+
@ProvidesInterface(version = Callback.VERSION)
public interface Callback {
public static final int VERSION = 1;
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java b/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java
index 7139d59c6eef..af02e5beca92 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java
@@ -37,6 +37,7 @@ public class DozeLog {
private static final int PULSE_REASONS = 5;
+ public static final int PULSE_REASON_NONE = -1;
public static final int PULSE_REASON_INTENT = 0;
public static final int PULSE_REASON_NOTIFICATION = 1;
public static final int PULSE_REASON_SENSOR_SIGMOTION = 2;
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
index 38b32e950225..44bb33aee2df 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
@@ -106,6 +106,7 @@ public class DozeMachine {
private final ArrayList<State> mQueuedRequests = new ArrayList<>();
private State mState = State.UNINITIALIZED;
+ private int mPulseReason;
private boolean mWakeLockHeldForCurrentState = false;
public DozeMachine(Service service, AmbientDisplayConfiguration config,
@@ -133,6 +134,20 @@ public class DozeMachine {
*/
@MainThread
public void requestState(State requestedState) {
+ Preconditions.checkArgument(requestedState != State.DOZE_REQUEST_PULSE);
+ requestState(requestedState, DozeLog.PULSE_REASON_NONE);
+ }
+
+ @MainThread
+ public void requestPulse(int pulseReason) {
+ // Must not be called during a transition. There's no inherent problem with that,
+ // but there's currently no need to execute from a transition and it simplifies the
+ // code to not have to worry about keeping the pulseReason in mQueuedRequests.
+ Preconditions.checkState(!isExecutingTransition());
+ requestState(State.DOZE_REQUEST_PULSE, pulseReason);
+ }
+
+ private void requestState(State requestedState, int pulseReason) {
Assert.isMainThread();
if (DEBUG) {
Log.i(TAG, "request: current=" + mState + " req=" + requestedState,
@@ -146,7 +161,7 @@ public class DozeMachine {
for (int i = 0; i < mQueuedRequests.size(); i++) {
// Transitions in Parts can call back into requestState, which will
// cause mQueuedRequests to grow.
- transitionTo(mQueuedRequests.get(i));
+ transitionTo(mQueuedRequests.get(i), pulseReason);
}
mQueuedRequests.clear();
mWakeLock.release();
@@ -165,6 +180,20 @@ public class DozeMachine {
return mState;
}
+ /**
+ * @return the current pulse reason.
+ *
+ * This is only valid if the machine is currently in one of the pulse states.
+ */
+ @MainThread
+ public int getPulseReason() {
+ Assert.isMainThread();
+ Preconditions.checkState(mState == State.DOZE_REQUEST_PULSE
+ || mState == State.DOZE_PULSING
+ || mState == State.DOZE_PULSE_DONE, "must be in pulsing state, but is " + mState);
+ return mPulseReason;
+ }
+
/** Requests the PowerManager to wake up now. */
public void wakeUp() {
mDozeService.requestWakeUp();
@@ -174,7 +203,7 @@ public class DozeMachine {
return !mQueuedRequests.isEmpty();
}
- private void transitionTo(State requestedState) {
+ private void transitionTo(State requestedState, int pulseReason) {
State newState = transitionPolicy(requestedState);
if (DEBUG) {
@@ -190,6 +219,7 @@ public class DozeMachine {
State oldState = mState;
mState = newState;
+ updatePulseReason(newState, oldState, pulseReason);
performTransitionOnComponents(oldState, newState);
updateScreenState(newState);
updateWakeLockState(newState);
@@ -197,6 +227,14 @@ public class DozeMachine {
resolveIntermediateState(newState);
}
+ private void updatePulseReason(State newState, State oldState, int pulseReason) {
+ if (newState == State.DOZE_REQUEST_PULSE) {
+ mPulseReason = pulseReason;
+ } else if (oldState == State.DOZE_PULSE_DONE) {
+ mPulseReason = DozeLog.PULSE_REASON_NONE;
+ }
+ }
+
private void performTransitionOnComponents(State oldState, State newState) {
for (Part p : mParts) {
p.transitionTo(oldState, newState);
@@ -280,7 +318,8 @@ public class DozeMachine {
case INITIALIZED:
case DOZE_PULSE_DONE:
transitionTo(mConfig.alwaysOnEnabled(UserHandle.USER_CURRENT)
- ? DozeMachine.State.DOZE_AOD : DozeMachine.State.DOZE);
+ ? DozeMachine.State.DOZE_AOD : DozeMachine.State.DOZE,
+ DozeLog.PULSE_REASON_NONE);
break;
default:
break;
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
index 2096956e8c8f..563b8fe35401 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
@@ -227,7 +227,7 @@ public class DozeTriggers implements DozeMachine.Part {
mDozeHost.isPulsingBlocked());
return;
}
- mMachine.requestState(DozeMachine.State.DOZE_REQUEST_PULSE);
+ mMachine.requestPulse(reason);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
index 03076cc4b7a8..64a152e1ac15 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
@@ -83,7 +83,7 @@ public class DozeUi implements DozeMachine.Part {
unscheduleTimeTick();
break;
case DOZE_REQUEST_PULSE:
- pulseWhileDozing(DozeLog.PULSE_REASON_NOTIFICATION /* TODO */);
+ pulseWhileDozing(mMachine.getPulseReason());
break;
case DOZE_PULSE_DONE:
mHost.abortPulsing();
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
index df03fdc46d06..bdc08718d37f 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
@@ -107,12 +107,12 @@ public class PipManager implements BasePipManager {
}
@Override
- public void onPinnedActivityRestartAttempt() {
+ public void onPinnedActivityRestartAttempt(boolean clearedTask) {
if (!checkCurrentUserId(false /* debug */)) {
return;
}
- mTouchHandler.getMotionHelper().expandPip();
+ mTouchHandler.getMotionHelper().expandPip(clearedTask /* skipAnimation */);
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
index fc52a2ec5994..5121c8d0a375 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
@@ -140,14 +140,25 @@ public class PipMotionHelper {
* Resizes the pinned stack back to fullscreen.
*/
void expandPip() {
+ expandPip(false /* skipAnimation */);
+ }
+
+ /**
+ * Resizes the pinned stack back to fullscreen.
+ */
+ void expandPip(boolean skipAnimation) {
cancelAnimations();
mHandler.post(() -> {
try {
- mActivityManager.resizeStack(PINNED_STACK_ID, null /* bounds */,
- true /* allowResizeInDockedMode */, true /* preserveWindows */,
- true /* animate */, EXPAND_STACK_TO_FULLSCREEN_DURATION);
+ if (skipAnimation) {
+ mActivityManager.moveTasksToFullscreenStack(PINNED_STACK_ID, true /* onTop */);
+ } else {
+ mActivityManager.resizeStack(PINNED_STACK_ID, null /* bounds */,
+ true /* allowResizeInDockedMode */, true /* preserveWindows */,
+ true /* animate */, EXPAND_STACK_TO_FULLSCREEN_DURATION);
+ }
} catch (RemoteException e) {
- Log.e(TAG, "Error showing PiP menu activity", e);
+ Log.e(TAG, "Error expanding PiP activity", e);
}
});
}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
index 657f08be8b52..9735bfc666d7 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
@@ -625,7 +625,7 @@ public class PipManager implements BasePipManager {
}
@Override
- public void onPinnedActivityRestartAttempt() {
+ public void onPinnedActivityRestartAttempt(boolean clearedTask) {
if (DEBUG) Log.d(TAG, "onPinnedActivityRestartAttempt()");
if (!checkCurrentUserId(DEBUG)) {
return;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index f5e096ebbbef..c4d88aec7b8c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -22,6 +22,7 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
+import android.metrics.LogMaker;
import android.os.Handler;
import android.os.Message;
import android.service.quicksettings.Tile;
@@ -30,6 +31,7 @@ import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
+
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settingslib.Utils;
@@ -179,7 +181,7 @@ public class QSPanel extends LinearLayout implements Tunable, Callback {
public void openDetails(String subPanel) {
QSTile tile = getTile(subPanel);
- showDetailAdapter(true, tile.getDetailAdapter(), new int[] {getWidth() / 2, 0});
+ showDetailAdapter(true, tile.getDetailAdapter(), new int[]{getWidth() / 2, 0});
}
private QSTile getTile(String subPanel) {
@@ -485,8 +487,9 @@ public class QSPanel extends LinearLayout implements Tunable, Callback {
private void logTiles() {
for (int i = 0; i < mRecords.size(); i++) {
- TileRecord tileRecord = mRecords.get(i);
- mMetricsLogger.visible(tileRecord.tile.getMetricsCategory());
+ QSTile tile = mRecords.get(i).tile;
+ mMetricsLogger.write(tile.populate(new LogMaker(tile.getMetricsCategory())
+ .setType(MetricsEvent.TYPE_OPEN)));
}
}
@@ -544,12 +547,13 @@ public class QSPanel extends LinearLayout implements Tunable, Callback {
private static final int SHOW_DETAIL = 1;
private static final int SET_TILE_VISIBILITY = 2;
private static final int ANNOUNCE_FOR_ACCESSIBILITY = 3;
+
@Override
public void handleMessage(Message msg) {
if (msg.what == SHOW_DETAIL) {
- handleShowDetail((Record)msg.obj, msg.arg1 != 0);
+ handleShowDetail((Record) msg.obj, msg.arg1 != 0);
} else if (msg.what == ANNOUNCE_FOR_ACCESSIBILITY) {
- announceForAccessibility((CharSequence)msg.obj);
+ announceForAccessibility((CharSequence) msg.obj);
}
}
}
@@ -569,8 +573,11 @@ public class QSPanel extends LinearLayout implements Tunable, Callback {
public interface QSTileLayout {
void addTile(TileRecord tile);
+
void removeTile(TileRecord tile);
+
int getOffsetTop(TileRecord tile);
+
boolean updateResources();
void setListening(boolean listening);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
index dc9176f66bb2..017365f6c64d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
@@ -157,7 +157,7 @@ public class CustomTile extends QSTileImpl<State> implements TileChangeListener
}
@Override
- protected LogMaker populate(LogMaker logMaker) {
+ public LogMaker populate(LogMaker logMaker) {
return super.populate(logMaker).setComponentName(mComponent);
}
@@ -275,7 +275,6 @@ public class CustomTile extends QSTileImpl<State> implements TileChangeListener
} catch (RemoteException e) {
// Called through wrapper, won't happen here.
}
- MetricsLogger.action(mContext, getMetricsCategory(), mComponent.getPackageName());
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
index 976efb2c289b..32af2305062e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
@@ -175,7 +175,7 @@ public abstract class QSTileImpl<TState extends State> implements QSTile {
mHandler.sendEmptyMessage(H.LONG_CLICK);
}
- protected LogMaker populate(LogMaker logMaker) {
+ public LogMaker populate(LogMaker logMaker) {
if (mState instanceof BooleanState) {
logMaker.addTaggedData(FIELD_QS_VALUE, ((BooleanState) mState).value ? 1 : 0);
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
index a9e1f61b7d47..f431517cfe77 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -158,7 +158,7 @@ public class SystemServicesProxy {
public void onTaskSnapshotChanged(int taskId, TaskSnapshot snapshot) { }
public void onActivityPinned(String packageName) { }
public void onActivityUnpinned() { }
- public void onPinnedActivityRestartAttempt() { }
+ public void onPinnedActivityRestartAttempt(boolean clearedTask) { }
public void onPinnedStackAnimationStarted() { }
public void onPinnedStackAnimationEnded() { }
public void onActivityForcedResizable(String packageName, int taskId, int reason) { }
@@ -223,10 +223,11 @@ public class SystemServicesProxy {
}
@Override
- public void onPinnedActivityRestartAttempt()
+ public void onPinnedActivityRestartAttempt(boolean clearedTask)
throws RemoteException{
mHandler.removeMessages(H.ON_PINNED_ACTIVITY_RESTART_ATTEMPT);
- mHandler.sendEmptyMessage(H.ON_PINNED_ACTIVITY_RESTART_ATTEMPT);
+ mHandler.obtainMessage(H.ON_PINNED_ACTIVITY_RESTART_ATTEMPT, clearedTask ? 1 : 0, 0)
+ .sendToTarget();
}
@Override
@@ -1294,7 +1295,8 @@ public class SystemServicesProxy {
}
case ON_PINNED_ACTIVITY_RESTART_ATTEMPT: {
for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
- mTaskStackListeners.get(i).onPinnedActivityRestartAttempt();
+ mTaskStackListeners.get(i).onPinnedActivityRestartAttempt(
+ msg.arg1 != 0);
}
break;
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
index 5817e9252c73..36be49deef35 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
@@ -279,6 +279,7 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback {
}
MetricsLogger.action(mSv.getContext(), MetricsEvent.OVERVIEW_SCROLL);
+ mLastY = mDownY = y;
}
}
if (mIsScrolling) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java
index cdbde5e8b0e1..d20360234c74 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java
@@ -106,7 +106,7 @@ public class DozeMachineTest {
public void testPulseDone_goesToDoze() {
when(mConfigMock.alwaysOnEnabled(anyInt())).thenReturn(false);
mMachine.requestState(INITIALIZED);
- mMachine.requestState(DOZE_REQUEST_PULSE);
+ mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION);
mMachine.requestState(DOZE_PULSING);
mMachine.requestState(DOZE_PULSE_DONE);
@@ -119,7 +119,7 @@ public class DozeMachineTest {
public void testPulseDone_goesToAoD() {
when(mConfigMock.alwaysOnEnabled(anyInt())).thenReturn(true);
mMachine.requestState(INITIALIZED);
- mMachine.requestState(DOZE_REQUEST_PULSE);
+ mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION);
mMachine.requestState(DOZE_PULSING);
mMachine.requestState(DOZE_PULSE_DONE);
@@ -163,7 +163,7 @@ public class DozeMachineTest {
public void testWakeLock_heldInPulseStates() {
mMachine.requestState(INITIALIZED);
- mMachine.requestState(DOZE_REQUEST_PULSE);
+ mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION);
assertTrue(mWakeLockFake.isHeld());
mMachine.requestState(DOZE_PULSING);
@@ -186,7 +186,7 @@ public class DozeMachineTest {
mMachine.requestState(INITIALIZED);
mMachine.requestState(DOZE);
- mMachine.requestState(DOZE_REQUEST_PULSE);
+ mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION);
mMachine.requestState(DOZE_PULSING);
mMachine.requestState(DOZE_PULSE_DONE);
@@ -198,9 +198,9 @@ public class DozeMachineTest {
mMachine.requestState(INITIALIZED);
mMachine.requestState(DOZE);
- mMachine.requestState(DOZE_REQUEST_PULSE);
+ mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION);
mMachine.requestState(DOZE_PULSING);
- mMachine.requestState(DOZE_REQUEST_PULSE);
+ mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION);
mMachine.requestState(DOZE_PULSE_DONE);
}
@@ -209,7 +209,7 @@ public class DozeMachineTest {
mMachine.requestState(INITIALIZED);
mMachine.requestState(DOZE);
- mMachine.requestState(DOZE_REQUEST_PULSE);
+ mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION);
mMachine.requestState(DOZE_PULSE_DONE);
}
@@ -235,7 +235,7 @@ public class DozeMachineTest {
public void testScreen_onInPulse() {
mMachine.requestState(INITIALIZED);
- mMachine.requestState(DOZE_REQUEST_PULSE);
+ mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION);
mMachine.requestState(DOZE_PULSING);
assertEquals(Display.STATE_DOZE, mServiceFake.screenState);
@@ -246,7 +246,7 @@ public class DozeMachineTest {
mMachine.requestState(INITIALIZED);
mMachine.requestState(DOZE);
- mMachine.requestState(DOZE_REQUEST_PULSE);
+ mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION);
assertEquals(Display.STATE_OFF, mServiceFake.screenState);
}
@@ -256,7 +256,7 @@ public class DozeMachineTest {
mMachine.requestState(INITIALIZED);
mMachine.requestState(DOZE_AOD);
- mMachine.requestState(DOZE_REQUEST_PULSE);
+ mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION);
assertEquals(Display.STATE_DOZE, mServiceFake.screenState);
}
@@ -270,12 +270,43 @@ public class DozeMachineTest {
return null;
}).when(mPartMock).transitionTo(any(), eq(DOZE_REQUEST_PULSE));
- mMachine.requestState(DOZE_REQUEST_PULSE);
+ mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION);
assertEquals(DOZE_PULSING, mMachine.getState());
}
@Test
+ public void testPulseReason_getMatchesRequest() {
+ mMachine.requestState(INITIALIZED);
+ mMachine.requestState(DOZE);
+ mMachine.requestPulse(DozeLog.PULSE_REASON_SENSOR_DOUBLE_TAP);
+
+ assertEquals(DozeLog.PULSE_REASON_SENSOR_DOUBLE_TAP, mMachine.getPulseReason());
+ }
+
+ @Test
+ public void testPulseReason_getFromTransition() {
+ mMachine.requestState(INITIALIZED);
+ mMachine.requestState(DOZE);
+ doAnswer(inv -> {
+ DozeMachine.State newState = inv.getArgument(1);
+ if (newState == DOZE_REQUEST_PULSE
+ || newState == DOZE_PULSING
+ || newState == DOZE_PULSE_DONE) {
+ assertEquals(DozeLog.PULSE_REASON_NOTIFICATION, mMachine.getPulseReason());
+ } else {
+ assertTrue("unexpected state " + newState,
+ newState == DOZE || newState == DOZE_AOD);
+ }
+ return null;
+ }).when(mPartMock).transitionTo(any(), any());
+
+ mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION);
+ mMachine.requestState(DOZE_PULSING);
+ mMachine.requestState(DOZE_PULSE_DONE);
+ }
+
+ @Test
public void testWakeUp_wakesUp() {
mMachine.wakeUp();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
index 12e75a14ba2b..8934460c380e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
@@ -22,26 +22,28 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import static org.mockito.Mockito.withSettings;
import android.app.Instrumentation;
import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
import com.android.internal.hardware.AmbientDisplayConfiguration;
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.hardware.FakeSensorManager;
import org.junit.Before;
import org.junit.BeforeClass;
-import org.junit.Ignore;
import org.junit.Test;
-import org.mockito.Answers;
-import org.mockito.MockSettings;
+import org.junit.runner.RunWith;
+@SmallTest
+@RunWith(AndroidJUnit4.class)
public class DozeTriggersTest {
private Context mContext;
private DozeTriggers mTriggers;
@@ -49,7 +51,7 @@ public class DozeTriggersTest {
private DozeHostFake mHost;
private AmbientDisplayConfiguration mConfig;
private DozeParameters mParameters;
- private SensorManagerFake mSensors;
+ private FakeSensorManager mSensors;
private Handler mHandler;
private WakeLock mWakeLock;
private Instrumentation mInstrumentation;
@@ -68,7 +70,7 @@ public class DozeTriggersTest {
mHost = new DozeHostFake();
mConfig = DozeConfigurationUtil.createMockConfig();
mParameters = DozeConfigurationUtil.createMockParameters();
- mSensors = new SensorManagerFake(mContext);
+ mSensors = new FakeSensorManager(mContext);
mHandler = new Handler(Looper.getMainLooper());
mWakeLock = new WakeLockFake();
@@ -79,32 +81,32 @@ public class DozeTriggersTest {
}
@Test
- @Ignore("setup crashes on virtual devices")
public void testOnNotification_stillWorksAfterOneFailedProxCheck() throws Exception {
when(mMachine.getState()).thenReturn(DozeMachine.State.DOZE);
mInstrumentation.runOnMainSync(()->{
mTriggers.transitionTo(DozeMachine.State.UNINITIALIZED, DozeMachine.State.INITIALIZED);
- mTriggers.transitionTo(DozeMachine.State.UNINITIALIZED, DozeMachine.State.DOZE);
+ mTriggers.transitionTo(DozeMachine.State.INITIALIZED, DozeMachine.State.DOZE);
mHost.callback.onNotificationHeadsUp();
});
mInstrumentation.runOnMainSync(() -> {
- mSensors.PROXIMITY.sendProximityResult(false); /* Near */
+ mSensors.getMockProximitySensor().sendProximityResult(false); /* Near */
});
verify(mMachine, never()).requestState(any());
+ verify(mMachine, never()).requestPulse(anyInt());
mInstrumentation.runOnMainSync(()->{
mHost.callback.onNotificationHeadsUp();
});
mInstrumentation.runOnMainSync(() -> {
- mSensors.PROXIMITY.sendProximityResult(true); /* Far */
+ mSensors.getMockProximitySensor().sendProximityResult(true); /* Far */
});
- verify(mMachine).requestState(DozeMachine.State.DOZE_REQUEST_PULSE);
+ verify(mMachine).requestPulse(anyInt());
}
} \ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/SensorManagerFake.java b/packages/SystemUI/tests/src/com/android/systemui/utils/hardware/FakeSensorManager.java
index 5b4b8917d8d1..30be6658d4b6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/SensorManagerFake.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/hardware/FakeSensorManager.java
@@ -11,10 +11,10 @@
* 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.
+ * limitations under the License
*/
-package com.android.systemui.doze;
+package com.android.systemui.utils.hardware;
import android.content.Context;
import android.hardware.HardwareBuffer;
@@ -33,6 +33,8 @@ import android.util.ArraySet;
import com.google.android.collect.Lists;
import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
@@ -44,18 +46,38 @@ import java.util.List;
* Note that this class ignores the "Handler" argument, so the test is responsible for calling the
* listener on the right thread.
*/
-public class SensorManagerFake extends SensorManager {
+public class FakeSensorManager extends SensorManager {
- public MockSensor PROXIMITY;
+ private final MockProximitySensor mMockProximitySensor;
- public SensorManagerFake(Context context) {
- PROXIMITY = new MockSensor(context.getSystemService(SensorManager.class)
- .getDefaultSensor(Sensor.TYPE_PROXIMITY));
+ public FakeSensorManager(Context context) throws Exception {
+ Sensor proxSensor = context.getSystemService(SensorManager.class)
+ .getDefaultSensor(Sensor.TYPE_PROXIMITY);
+ if (proxSensor == null) {
+ // No prox? Let's create a fake one!
+ proxSensor = createSensor(Sensor.TYPE_PROXIMITY);
+ }
+ mMockProximitySensor = new MockProximitySensor(proxSensor);
+ }
+
+ public MockProximitySensor getMockProximitySensor() {
+ return mMockProximitySensor;
+ }
+
+ @Override
+ public Sensor getDefaultSensor(int type) {
+ Sensor s = super.getDefaultSensor(type);
+ if (s != null) {
+ return s;
+ }
+ // Our mock sensors aren't wakeup, and it's a pain to create them that way. Instead, just
+ // return non-wakeup sensors if we can't find a wakeup sensor.
+ return getDefaultSensor(type, false /* wakeup */);
}
@Override
protected List<Sensor> getFullSensorList() {
- return Lists.newArrayList(PROXIMITY.sensor);
+ return Lists.newArrayList(mMockProximitySensor.sensor);
}
@Override
@@ -65,8 +87,8 @@ public class SensorManagerFake extends SensorManager {
@Override
protected void unregisterListenerImpl(SensorEventListener listener, Sensor sensor) {
- if (sensor == PROXIMITY.sensor || sensor == null) {
- PROXIMITY.listeners.remove(listener);
+ if (sensor == mMockProximitySensor.sensor || sensor == null) {
+ mMockProximitySensor.listeners.remove(listener);
}
}
@@ -74,8 +96,8 @@ public class SensorManagerFake extends SensorManager {
protected boolean registerListenerImpl(SensorEventListener listener, Sensor sensor,
int delayUs,
Handler handler, int maxReportLatencyUs, int reservedFlags) {
- if (sensor == PROXIMITY.sensor) {
- PROXIMITY.listeners.add(listener);
+ if (sensor == mMockProximitySensor.sensor) {
+ mMockProximitySensor.listeners.add(listener);
return true;
}
return false;
@@ -141,11 +163,44 @@ public class SensorManagerFake extends SensorManager {
return false;
}
- public class MockSensor {
+ private Sensor createSensor(int type) throws Exception {
+ Constructor<Sensor> constr = Sensor.class.getDeclaredConstructor();
+ constr.setAccessible(true);
+ Sensor sensor = constr.newInstance();
+
+ setSensorType(sensor, type);
+ setSensorField(sensor, "mName", "Mock " + sensor.getStringType() + "/" + type);
+ setSensorField(sensor, "mVendor", "Mock Vendor");
+ setSensorField(sensor, "mVersion", 1);
+ setSensorField(sensor, "mHandle", -1);
+ setSensorField(sensor, "mMaxRange", 10);
+ setSensorField(sensor, "mResolution", 1);
+ setSensorField(sensor, "mPower", 1);
+ setSensorField(sensor, "mMinDelay", 1000);
+ setSensorField(sensor, "mMaxDelay", 1000000000);
+ setSensorField(sensor, "mFlags", 0);
+ setSensorField(sensor, "mId", -1);
+
+ return sensor;
+ }
+
+ private void setSensorField(Sensor sensor, String fieldName, Object value) throws Exception {
+ Field field = Sensor.class.getDeclaredField(fieldName);
+ field.setAccessible(true);
+ field.set(sensor, value);
+ }
+
+ private void setSensorType(Sensor sensor, int type) throws Exception {
+ Method setter = Sensor.class.getDeclaredMethod("setType", Integer.TYPE);
+ setter.setAccessible(true);
+ setter.invoke(sensor, type);
+ }
+
+ public class MockProximitySensor {
final Sensor sensor;
final ArraySet<SensorEventListener> listeners = new ArraySet<>();
- private MockSensor(Sensor sensor) {
+ private MockProximitySensor(Sensor sensor) {
this.sensor = sensor;
}
diff --git a/preloaded-classes b/preloaded-classes
index 892c59394855..493e9803d81e 100644
--- a/preloaded-classes
+++ b/preloaded-classes
@@ -1820,6 +1820,7 @@ android.text.FontConfig$Font$1
android.text.GetChars
android.text.GraphicsOperations
android.text.Html
+android.text.Html$HtmlParser
android.text.Hyphenator
android.text.InputFilter
android.text.InputType
diff --git a/services/autofill/java/com/android/server/autofill/Helper.java b/services/autofill/java/com/android/server/autofill/Helper.java
index 68ade63ac516..cbf97ddc8abb 100644
--- a/services/autofill/java/com/android/server/autofill/Helper.java
+++ b/services/autofill/java/com/android/server/autofill/Helper.java
@@ -20,7 +20,9 @@ import android.annotation.NonNull;
import android.app.assist.AssistStructure;
import android.app.assist.AssistStructure.ViewNode;
import android.os.Bundle;
+import android.util.DebugUtils;
import android.view.autofill.AutofillId;
+import android.view.autofill.AutofillManager;
import java.util.Arrays;
import java.util.Objects;
@@ -40,6 +42,10 @@ public final class Helper {
*/
public static boolean sVerbose = false;
+ private Helper() {
+ throw new UnsupportedOperationException("contains static members only");
+ }
+
static void append(StringBuilder builder, Bundle bundle) {
if (bundle == null || !sVerbose) {
builder.append("null");
@@ -62,8 +68,8 @@ public final class Helper {
return builder.toString();
}
- private Helper() {
- throw new UnsupportedOperationException("contains static members only");
+ static String getUpdateActionAsString(int action) {
+ return DebugUtils.flagsToString(AutofillManager.class, "ACTION_", action);
}
static ViewNode findViewNodeById(@NonNull AssistStructure structure, @NonNull AutofillId id) {
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 018fb6886cd9..23b734adaa9a 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -25,9 +25,13 @@ import static android.view.autofill.AutofillManager.ACTION_VALUE_CHANGED;
import static android.view.autofill.AutofillManager.ACTION_VIEW_ENTERED;
import static android.view.autofill.AutofillManager.ACTION_VIEW_EXITED;
+import static com.android.server.autofill.Helper.findViewNodeById;
+import static com.android.server.autofill.Helper.getUpdateActionAsString;
import static com.android.server.autofill.Helper.sDebug;
import static com.android.server.autofill.Helper.sVerbose;
-import static com.android.server.autofill.Helper.findViewNodeById;
+import static com.android.server.autofill.ViewState.STATE_AUTOFILLED;
+import static com.android.server.autofill.ViewState.STATE_FILLABLE;
+import static com.android.server.autofill.ViewState.STATE_RESTARTED_SESSION;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -221,7 +225,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
final int numContexts = mContexts.size();
for (int i = 0; i < numContexts; i++) {
- fillStructureWithAllowedValues(mContexts.get(i).getStructure());
+ fillStructureWithAllowedValues(mContexts.get(i).getStructure(), flags);
}
request = new FillRequest(requestId, mContexts, mClientState, flags);
@@ -235,10 +239,12 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
* Updates values of the nodes in the structure so that:
* - proper node is focused
* - autofillValue is sent back to service when it was previously autofilled
+ * - autofillValue is sent in the view used to force a request
*
* @param structure The structure to be filled
+ * @param flags The flags that started the session
*/
- private void fillStructureWithAllowedValues(@NonNull AssistStructure structure) {
+ private void fillStructureWithAllowedValues(@NonNull AssistStructure structure, int flags) {
final int numViewStates = mViewStates.size();
for (int i = 0; i < numViewStates; i++) {
final ViewState viewState = mViewStates.valueAt(i);
@@ -249,16 +255,23 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
continue;
}
- final AutofillValue initialValue = viewState.getInitialValue();
+ final AutofillValue currentValue = viewState.getCurrentValue();
final AutofillValue filledValue = viewState.getAutofilledValue();
final AutofillOverlay overlay = new AutofillOverlay();
- if (filledValue != null && !filledValue.equals(initialValue)) {
- overlay.value = filledValue;
+
+ // Sanitizes the value if the current value matches what the service sent.
+ if (filledValue != null && filledValue.equals(currentValue)) {
+ overlay.value = currentValue;
}
+
if (mCurrentViewId != null) {
+ // Updates the focus value.
overlay.focused = mCurrentViewId.equals(viewState.id);
+ // Sanitizes the value of the focused field in a manual request.
+ if (overlay.focused && (flags & FLAG_MANUAL_REQUEST) != 0) {
+ overlay.value = currentValue;
+ }
}
-
node.setAutofillOverlay(overlay);
}
}
@@ -883,6 +896,40 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
}
/**
+ * Starts (if necessary) a new fill request upon entering a view.
+ *
+ * <p>A new request will be started in 2 scenarios:
+ * <ol>
+ * <li>If the user manually requested autofill after the view was already filled.
+ * <li>If the view is part of a new partition.
+ * </ol>
+ *
+ * @param id The id of the view that is entered.
+ * @param viewState The view that is entered.
+ * @param flags The flag that was passed by the AutofillManager.
+ */
+ private void requestNewFillResponseIfNecessaryLocked(@NonNull AutofillId id,
+ @NonNull ViewState viewState, int flags) {
+ // First check if this is a manual request after view was autofilled.
+ final int state = viewState.getState();
+ final boolean restart = (state & STATE_AUTOFILLED) != 0
+ && (flags & FLAG_MANUAL_REQUEST) != 0;
+ if (restart) {
+ if (sDebug) Slog.d(TAG, "Re-starting session on view " + id);
+ viewState.setState(STATE_RESTARTED_SESSION);
+ requestNewFillResponseLocked(flags);
+ return;
+ }
+
+ // If it's not, then check if it it should start a partition.
+ if (shouldStartNewPartitionLocked(id)) {
+ if (sDebug) Slog.d(TAG, "Starting partition for view id " + id);
+ viewState.setState(ViewState.STATE_STARTED_PARTITION);
+ requestNewFillResponseLocked(flags);
+ }
+ }
+
+ /**
* Determines if a new partition should be started for an id.
*
* @param id The id of the view that is entered
@@ -938,6 +985,10 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
+ id + " destroyed");
return;
}
+ if (sVerbose) {
+ Slog.v(TAG, "updateLocked(): id=" + id + ", action=" + getUpdateActionAsString(action)
+ + ", flags=" + flags);
+ }
ViewState viewState = mViewStates.get(id);
if (viewState == null) {
@@ -992,13 +1043,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
}
break;
case ACTION_VIEW_ENTERED:
- if (shouldStartNewPartitionLocked(id)) {
- if (sDebug) {
- Slog.d(TAG, "Starting partition for view id " + viewState.id);
- }
- viewState.setState(ViewState.STATE_STARTED_PARTITION);
- requestNewFillResponseLocked(flags);
- }
+ requestNewFillResponseIfNecessaryLocked(id, viewState, flags);
// Remove the UI if the ViewState has changed.
if (mCurrentViewId != viewState.id) {
diff --git a/services/autofill/java/com/android/server/autofill/ViewState.java b/services/autofill/java/com/android/server/autofill/ViewState.java
index d114e1452373..561c603ea3b0 100644
--- a/services/autofill/java/com/android/server/autofill/ViewState.java
+++ b/services/autofill/java/com/android/server/autofill/ViewState.java
@@ -47,23 +47,25 @@ final class ViewState {
private static final String TAG = "ViewState";
// NOTE: state constants must be public because of flagstoString().
- public static final int STATE_UNKNOWN = 0x00;
+ public static final int STATE_UNKNOWN = 0x000;
/** Initial state. */
- public static final int STATE_INITIAL = 0x01;
+ public static final int STATE_INITIAL = 0x001;
/** View id is present in a dataset returned by the service. */
- public static final int STATE_FILLABLE = 0x02;
+ public static final int STATE_FILLABLE = 0x002;
/** View was autofilled after user selected a dataset. */
- public static final int STATE_AUTOFILLED = 0x04;
+ public static final int STATE_AUTOFILLED = 0x004;
/** View value was changed, but not by the service. */
- public static final int STATE_CHANGED = 0x08;
+ public static final int STATE_CHANGED = 0x008;
/** Set only in the View that started a session. */
- public static final int STATE_STARTED_SESSION = 0x10;
+ public static final int STATE_STARTED_SESSION = 0x010;
/** View that started a new partition when focused on. */
- public static final int STATE_STARTED_PARTITION = 0x20;
+ public static final int STATE_STARTED_PARTITION = 0x020;
/** User select a dataset in this view, but service must authenticate first. */
- public static final int STATE_WAITING_DATASET_AUTH = 0x40;
+ public static final int STATE_WAITING_DATASET_AUTH = 0x040;
/** Service does not care about this view. */
- public static final int STATE_IGNORED = 0x80;
+ public static final int STATE_IGNORED = 0x080;
+ /** User manually request autofill in this view, after it was already autofilled. */
+ public static final int STATE_RESTARTED_SESSION = 0x100;
public final AutofillId id;
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index dc2dfa8ff289..a68a7ddd6f9c 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -2387,7 +2387,7 @@ public class BackupManagerService {
long token = mAncestralToken;
synchronized (mQueueLock) {
- if (mEverStoredApps.contains(packageName)) {
+ if (mCurrentToken != 0 && mEverStoredApps.contains(packageName)) {
if (MORE_DEBUG) {
Slog.i(TAG, "App in ever-stored, so using current token");
}
@@ -10464,8 +10464,7 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
final long oldId = Binder.clearCallingIdentity();
try {
String prevTransport = mTransportManager.selectTransport(transport);
- Settings.Secure.putString(mContext.getContentResolver(),
- Settings.Secure.BACKUP_TRANSPORT, transport);
+ updateStateForTransport(transport);
Slog.v(TAG, "selectBackupTransport() set " + mTransportManager.getCurrentTransportName()
+ " returning " + prevTransport);
return prevTransport;
@@ -10488,9 +10487,7 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
@Override
public void onSuccess(String transportName) {
mTransportManager.selectTransport(transportName);
- Settings.Secure.putString(mContext.getContentResolver(),
- Settings.Secure.BACKUP_TRANSPORT,
- mTransportManager.getCurrentTransportName());
+ updateStateForTransport(mTransportManager.getCurrentTransportName());
Slog.v(TAG, "Transport successfully selected: " + transport.flattenToShortString());
try {
listener.onSuccess(transportName);
@@ -10513,6 +10510,28 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
Binder.restoreCallingIdentity(oldId);
}
+ private void updateStateForTransport(String newTransportName) {
+ // Publish the name change
+ Settings.Secure.putString(mContext.getContentResolver(),
+ Settings.Secure.BACKUP_TRANSPORT, newTransportName);
+
+ // And update our current-dataset bookkeeping
+ IBackupTransport transport = mTransportManager.getTransportBinder(newTransportName);
+ if (transport != null) {
+ try {
+ mCurrentToken = transport.getCurrentRestoreSet();
+ } catch (Exception e) {
+ // Oops. We can't know the current dataset token, so reset and figure it out
+ // when we do the next k/v backup operation on this transport.
+ mCurrentToken = 0;
+ }
+ } else {
+ // The named transport isn't bound at this particular moment, so we can't
+ // know yet what its current dataset token is. Reset as above.
+ mCurrentToken = 0;
+ }
+ }
+
// Supply the configuration Intent for the given transport. If the name is not one
// of the available transports, or if the transport does not supply any configuration
// UI, the method returns null.
diff --git a/services/backup/java/com/android/server/backup/Trampoline.java b/services/backup/java/com/android/server/backup/Trampoline.java
index 2c14a7cd030e..aafa88a8eae5 100644
--- a/services/backup/java/com/android/server/backup/Trampoline.java
+++ b/services/backup/java/com/android/server/backup/Trampoline.java
@@ -304,6 +304,14 @@ public class Trampoline extends IBackupManager.Stub {
BackupManagerService svc = mService;
if (svc != null) {
svc.selectBackupTransportAsync(transport, listener);
+ } else {
+ if (listener != null) {
+ try {
+ listener.onFailure(BackupManager.ERROR_BACKUP_NOT_ALLOWED);
+ } catch (RemoteException ex) {
+ // Ignore
+ }
+ }
}
}
diff --git a/services/backup/java/com/android/server/backup/TransportManager.java b/services/backup/java/com/android/server/backup/TransportManager.java
index 67f105e503d3..da1f32c9d203 100644
--- a/services/backup/java/com/android/server/backup/TransportManager.java
+++ b/services/backup/java/com/android/server/backup/TransportManager.java
@@ -182,13 +182,13 @@ class TransportManager {
String[] getBoundTransportNames() {
synchronized (mTransportLock) {
- return mBoundTransports.keySet().toArray(new String[0]);
+ return mBoundTransports.keySet().toArray(new String[mBoundTransports.size()]);
}
}
ComponentName[] getAllTransportCompenents() {
synchronized (mTransportLock) {
- return mValidTransports.keySet().toArray(new ComponentName[0]);
+ return mValidTransports.keySet().toArray(new ComponentName[mValidTransports.size()]);
}
}
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index 05ffcf071268..550774a1df58 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -1049,6 +1049,7 @@ class AlarmManagerService extends SystemService {
if (timeZoneWasChanged) {
Intent intent = new Intent(Intent.ACTION_TIMEZONE_CHANGED);
intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
+ | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND
| Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
intent.putExtra("time-zone", zone.getID());
getContext().sendBroadcastAsUser(intent, UserHandle.ALL);
diff --git a/services/core/java/com/android/server/NetworkScoreService.java b/services/core/java/com/android/server/NetworkScoreService.java
index 114d7619a024..fdc0bba09a52 100644
--- a/services/core/java/com/android/server/NetworkScoreService.java
+++ b/services/core/java/com/android/server/NetworkScoreService.java
@@ -631,6 +631,11 @@ public class NetworkScoreService extends INetworkScoreService.Stub {
PackageManager.PERMISSION_GRANTED;
}
+ private boolean callerCanScoreNetworks() {
+ return mContext.checkCallingOrSelfPermission(permission.SCORE_NETWORKS) ==
+ PackageManager.PERMISSION_GRANTED;
+ }
+
@Override
public boolean clearScores() {
// Only the active scorer or the system should be allowed to flush all scores.
@@ -651,9 +656,9 @@ public class NetworkScoreService extends INetworkScoreService.Stub {
@Override
public boolean setActiveScorer(String packageName) {
// Only the system can set the active scorer
- if (!isCallerSystemProcess(getCallingUid()) && !callerCanRequestScores()) {
+ if (!isCallerSystemProcess(getCallingUid()) && !callerCanScoreNetworks()) {
throw new SecurityException(
- "Caller is neither the system process nor a score requester.");
+ "Caller is neither the system process or a network scorer.");
}
return mNetworkScorerAppManager.setActiveScorer(packageName);
diff --git a/services/core/java/com/android/server/NetworkScorerAppManager.java b/services/core/java/com/android/server/NetworkScorerAppManager.java
index 8404025e6726..42777bf33bd3 100644
--- a/services/core/java/com/android/server/NetworkScorerAppManager.java
+++ b/services/core/java/com/android/server/NetworkScorerAppManager.java
@@ -208,11 +208,11 @@ public class NetworkScorerAppManager {
*
* <p>The caller must have permission to write to {@link Settings.Global}.
*
- * @param packageName the packageName of the new scorer to use. If null, the scoring app will
- * revert back to the configured default. Otherwise, the scorer will only
- * be set if it is a valid scorer application.
- * @return true if the scorer was changed, or false if the package is not a valid scorer or
- * a valid network recommendation provider exists.
+ * @param packageName the packageName of the new scorer to use. If null, scoring will be forced
+ * off, otherwise the scorer will only be set if it is a valid scorer
+ * application.
+ * @return true if the package was a valid scorer (including <code>null</code>) and now
+ * represents the active scorer, false otherwise.
*/
@VisibleForTesting
public boolean setActiveScorer(String packageName) {
@@ -223,16 +223,19 @@ public class NetworkScorerAppManager {
return true;
}
- if (packageName == null) {
- // revert to the default setting.
- packageName = getDefaultPackageSetting();
+ if (TextUtils.isEmpty(packageName)) {
+ Log.i(TAG, "Network scorer forced off, was: " + oldPackageName);
+ setNetworkRecommendationsPackage(null);
+ setNetworkRecommendationsEnabledSetting(
+ NetworkScoreManager.RECOMMENDATIONS_ENABLED_FORCED_OFF);
+ return true;
}
- Log.i(TAG, "Changing network scorer from " + oldPackageName + " to " + packageName);
-
// We only make the change if the new package is valid.
if (getScorer(packageName) != null) {
+ Log.i(TAG, "Changing network scorer from " + oldPackageName + " to " + packageName);
setNetworkRecommendationsPackage(packageName);
+ setNetworkRecommendationsEnabledSetting(NetworkScoreManager.RECOMMENDATIONS_ENABLED_ON);
return true;
} else {
Log.w(TAG, "Requested network scorer is not valid: " + packageName);
diff --git a/services/core/java/com/android/server/vr/CompatibilityDisplay.java b/services/core/java/com/android/server/Vr2dDisplay.java
index d7cdf085bfb7..1116e4e2c3fc 100644
--- a/services/core/java/com/android/server/vr/CompatibilityDisplay.java
+++ b/services/core/java/com/android/server/Vr2dDisplay.java
@@ -3,7 +3,7 @@ package com.android.server.vr;
import static android.view.Display.INVALID_DISPLAY;
import android.app.ActivityManagerInternal;
-import android.app.CompatibilityDisplayProperties;
+import android.app.Vr2dDisplayProperties;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -31,8 +31,8 @@ import com.android.server.vr.VrManagerService;
* Creates a 2D Virtual Display while VR Mode is enabled. This display will be used to run and
* render 2D app within a VR experience. For example, bringing up the 2D calculator app in VR.
*/
-class CompatibilityDisplay {
- private final static String TAG = "CompatDisplay";
+class Vr2dDisplay {
+ private final static String TAG = "Vr2dDisplay";
private final static boolean DEBUG = false;
// TODO: Go over these values and figure out what is best
@@ -42,13 +42,13 @@ class CompatibilityDisplay {
private final static int STOP_VIRTUAL_DISPLAY_DELAY_MILLIS = 2000;
private final static String DEBUG_ACTION_SET_MODE =
- "com.android.server.vr.CompatibilityDisplay.SET_MODE";
+ "com.android.server.vr.Vr2dDisplay.SET_MODE";
private final static String DEBUG_EXTRA_MODE_ON =
- "com.android.server.vr.CompatibilityDisplay.EXTRA_MODE_ON";
+ "com.android.server.vr.Vr2dDisplay.EXTRA_MODE_ON";
private final static String DEBUG_ACTION_SET_SURFACE =
- "com.android.server.vr.CompatibilityDisplay.SET_SURFACE";
+ "com.android.server.vr.Vr2dDisplay.SET_SURFACE";
private final static String DEBUG_EXTRA_SURFACE =
- "com.android.server.vr.CompatibilityDisplay.EXTRA_SURFACE";
+ "com.android.server.vr.Vr2dDisplay.EXTRA_SURFACE";
/**
* The default width of the VR virtual display
@@ -99,7 +99,7 @@ class CompatibilityDisplay {
private boolean mIsVrModeOverrideEnabled;
private boolean mIsVrModeEnabled;
- public CompatibilityDisplay(DisplayManager displayManager,
+ public Vr2dDisplay(DisplayManager displayManager,
ActivityManagerInternal activityManagerInternal, IVrManager vrManager) {
mDisplayManager = displayManager;
mActivityManagerInternal = activityManagerInternal;
@@ -190,7 +190,7 @@ class CompatibilityDisplay {
}
/**
- * Sets the resolution and DPI of the compatibility virtual display used to display
+ * Sets the resolution and DPI of the Vr2d virtual display used to display
* 2D applications in VR mode.
*
* <p>Requires {@link android.Manifest.permission#ACCESS_VR_MANAGER} permission.</p>
@@ -198,7 +198,7 @@ class CompatibilityDisplay {
* @param compatDisplayProperties Properties of the virtual display for 2D applications
* in VR mode.
*/
- public void setVirtualDisplayProperties(CompatibilityDisplayProperties compatDisplayProperties) {
+ public void setVirtualDisplayProperties(Vr2dDisplayProperties compatDisplayProperties) {
synchronized(mVdLock) {
if (DEBUG) {
Log.i(TAG, "VD setVirtualDisplayProperties: res = " +
@@ -273,13 +273,13 @@ class CompatibilityDisplay {
null /* Surface */, 0 /* flags */);
if (mVirtualDisplay != null) {
- mActivityManagerInternal.setVrCompatibilityDisplayId(
+ mActivityManagerInternal.setVr2dDisplayId(
mVirtualDisplay.getDisplay().getDisplayId());
// Now create the ImageReader to supply a Surface to the new virtual display.
startImageReader();
} else {
Log.w(TAG, "Virtual display id is null after createVirtualDisplay");
- mActivityManagerInternal.setVrCompatibilityDisplayId(INVALID_DISPLAY);
+ mActivityManagerInternal.setVr2dDisplayId(INVALID_DISPLAY);
return;
}
}
@@ -302,7 +302,7 @@ class CompatibilityDisplay {
} else {
Log.i(TAG, "Stopping Virtual Display");
synchronized (mVdLock) {
- mActivityManagerInternal.setVrCompatibilityDisplayId(INVALID_DISPLAY);
+ mActivityManagerInternal.setVr2dDisplayId(INVALID_DISPLAY);
setSurfaceLocked(null); // clean up and release the surface first.
if (mVirtualDisplay != null) {
mVirtualDisplay.release();
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index e0fc531eb326..a5615a9c56fe 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -166,8 +166,11 @@ public final class ActiveServices {
*/
static final class ActiveForegroundApp {
String mPackageName;
+ int mUid;
CharSequence mLabel;
boolean mShownWhileScreenOn;
+ boolean mAppOnTop;
+ boolean mShownWhileTop;
long mStartTime;
long mStartVisibleTime;
long mEndTime;
@@ -728,11 +731,12 @@ public final class ActiveServices {
synchronized (mAm) {
final long now = SystemClock.elapsedRealtime();
final long nowPlusMin = now + mAm.mConstants.FOREGROUND_SERVICE_UI_MIN_TIME;
+ long nextUpdateTime = Long.MAX_VALUE;
if (smap != null) {
for (int i = smap.mActiveForegroundApps.size()-1; i >= 0; i--) {
ActiveForegroundApp aa = smap.mActiveForegroundApps.valueAt(i);
if (aa.mEndTime != 0 && (mScreenOn || aa.mShownWhileScreenOn)) {
- if (aa.mEndTime < (aa.mStartVisibleTime
+ if (!aa.mShownWhileTop && aa.mEndTime < (aa.mStartVisibleTime
+ mAm.mConstants.FOREGROUND_SERVICE_UI_MIN_TIME)) {
// Check to see if this should still be displayed... we continue
// until it has been shown for at least the timeout duration.
@@ -741,6 +745,12 @@ public final class ActiveServices {
smap.mActiveForegroundApps.removeAt(i);
smap.mActiveForegroundAppsChanged = true;
continue;
+ } else {
+ long hideTime = aa.mStartVisibleTime
+ + mAm.mConstants.FOREGROUND_SERVICE_UI_MIN_TIME;
+ if (hideTime < nextUpdateTime) {
+ nextUpdateTime = hideTime;
+ }
}
} else {
// This was up for longer than the timeout, so just remove immediately.
@@ -749,10 +759,17 @@ public final class ActiveServices {
continue;
}
}
- if (active == null) {
- active = new ArrayList<>();
+ if (!aa.mAppOnTop) {
+ if (active == null) {
+ active = new ArrayList<>();
+ }
+ active.add(aa);
}
- active.add(aa);
+ }
+ smap.removeMessages(ServiceMap.MSG_UPDATE_FOREGROUND_APPS);
+ if (nextUpdateTime < Long.MAX_VALUE) {
+ Message msg = smap.obtainMessage();
+ smap.sendMessageAtTime(msg, nextUpdateTime);
}
}
if (!smap.mActiveForegroundAppsChanged) {
@@ -842,7 +859,7 @@ public final class ActiveServices {
active.mNumActive--;
if (active.mNumActive <= 0) {
active.mEndTime = SystemClock.elapsedRealtime();
- if (active.mEndTime >= (active.mStartVisibleTime
+ if (active.mShownWhileTop || active.mEndTime >= (active.mStartVisibleTime
+ mAm.mConstants.FOREGROUND_SERVICE_UI_MIN_TIME)) {
// Have been active for long enough that we will remove it immediately.
smap.mActiveForegroundApps.remove(r.packageName);
@@ -887,6 +904,31 @@ public final class ActiveServices {
}
}
+ void foregroundServiceProcStateChangedLocked(UidRecord uidRec) {
+ ServiceMap smap = mServiceMap.get(UserHandle.getUserId(uidRec.uid));
+ if (smap != null) {
+ boolean changed = false;
+ for (int j = smap.mActiveForegroundApps.size()-1; j >= 0; j--) {
+ ActiveForegroundApp active = smap.mActiveForegroundApps.valueAt(j);
+ if (active.mUid == uidRec.uid) {
+ if (uidRec.curProcState <= ActivityManager.PROCESS_STATE_TOP) {
+ if (!active.mAppOnTop) {
+ active.mAppOnTop = true;
+ changed = true;
+ }
+ active.mShownWhileTop = true;
+ } else if (active.mAppOnTop) {
+ active.mAppOnTop = false;
+ changed = true;
+ }
+ }
+ }
+ if (changed) {
+ requestUpdateActiveForegroundAppsLocked(smap, 0);
+ }
+ }
+ }
+
private void setServiceForegroundInnerLocked(ServiceRecord r, int id,
Notification notification, int flags) {
if (id != 0) {
@@ -948,7 +990,13 @@ public final class ActiveServices {
if (active == null) {
active = new ActiveForegroundApp();
active.mPackageName = r.packageName;
+ active.mUid = r.appInfo.uid;
active.mShownWhileScreenOn = mScreenOn;
+ if (r.app != null) {
+ active.mAppOnTop = active.mShownWhileTop =
+ r.app.uidRecord.curProcState
+ <= ActivityManager.PROCESS_STATE_TOP;
+ }
active.mStartTime = active.mStartVisibleTime
= SystemClock.elapsedRealtime();
smap.mActiveForegroundApps.put(r.packageName, active);
@@ -1258,6 +1306,10 @@ public final class ActiveServices {
mAm.startAssociationLocked(callerApp.uid, callerApp.processName, callerApp.curProcState,
s.appInfo.uid, s.name, s.processName);
+ // Once the apps have become associated, if one of them is caller is ephemeral
+ // the target app should now be able to see the calling app
+ mAm.grantEphemeralAccessLocked(callerApp.userId, service,
+ s.appInfo.uid, UserHandle.getAppId(callerApp.uid));
AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
ConnectionRecord c = new ConnectionRecord(b, activity,
@@ -2786,6 +2838,9 @@ public final class ActiveServices {
if (!doit && didSomething) {
return true;
}
+ if (doit && filterByClasses == null) {
+ forceStopPackageLocked(packageName, mServiceMap.valueAt(i).mUserId);
+ }
}
} else {
ServiceMap smap = mServiceMap.get(userId);
@@ -2794,6 +2849,9 @@ public final class ActiveServices {
didSomething = collectPackageServicesLocked(packageName, filterByClasses,
evenPersistent, doit, killProcess, items);
}
+ if (doit && filterByClasses == null) {
+ forceStopPackageLocked(packageName, userId);
+ }
}
if (mTmpCollectionResults != null) {
@@ -2802,10 +2860,11 @@ public final class ActiveServices {
}
mTmpCollectionResults.clear();
}
+
return didSomething;
}
- void removeUninstalledPackageLocked(String packageName, int userId) {
+ void forceStopPackageLocked(String packageName, int userId) {
ServiceMap smap = mServiceMap.get(userId);
if (smap != null && smap.mActiveForegroundApps.size() > 0) {
for (int i = smap.mActiveForegroundApps.size()-1; i >= 0; i--) {
@@ -3636,6 +3695,10 @@ public final class ActiveServices {
}
pw.print(" mNumActive=");
pw.print(aa.mNumActive);
+ pw.print(" mAppOnTop=");
+ pw.print(aa.mAppOnTop);
+ pw.print(" mShownWhileTop=");
+ pw.print(aa.mShownWhileTop);
pw.print(" mShownWhileScreenOn=");
pw.println(aa.mShownWhileScreenOn);
pw.print(" mStartTime=");
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index d46a24bec6cb..c65aac4eb2d1 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -120,7 +120,6 @@ import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_NETWORK;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_OOM_ADJ;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PERMISSIONS_REVIEW;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_POWER;
-import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_POWER_QUICK;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PROCESSES;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PROCESS_OBSERVERS;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PROVIDER;
@@ -572,11 +571,10 @@ public class ActivityManagerService extends IActivityManager.Stub
// Determines whether to take full screen screenshots
static final boolean TAKE_FULLSCREEN_SCREENSHOTS = true;
- // STOPSHIP: Update default to a smaller value.
/**
* Default value for {@link Settings.Global#NETWORK_ACCESS_TIMEOUT_MS}.
*/
- private static final long NETWORK_ACCESS_TIMEOUT_DEFAULT_MS = 2000; // 2 sec
+ private static final long NETWORK_ACCESS_TIMEOUT_DEFAULT_MS = 200; // 0.2 sec
/**
* State indicating that there is no need for any blocking for network.
@@ -627,8 +625,8 @@ public class ActivityManagerService extends IActivityManager.Stub
private final VrController mVrController;
- // VR Compatibility Display Id.
- int mVrCompatibilityDisplayId = INVALID_DISPLAY;
+ // VR Vr2d Display Id.
+ int mVr2dDisplayId = INVALID_DISPLAY;
// Whether we should use SCHED_FIFO for UI and RenderThreads.
private boolean mUseFifoUiScheduling = false;
@@ -4332,6 +4330,7 @@ public class ActivityManagerService extends IActivityManager.Stub
validateUid.idle = false;
}
validateUid.curProcState = validateUid.setProcState = item.processState;
+ validateUid.lastDispatchedProcStateSeq = item.procStateSeq;
}
}
}
@@ -19007,7 +19006,7 @@ public class ActivityManagerService extends IActivityManager.Stub
removeTasksByPackageNameLocked(ssp, userId);
- mServices.removeUninstalledPackageLocked(ssp, userId);
+ mServices.forceStopPackageLocked(ssp, userId);
// Hide the "unsupported display" dialog if necessary.
if (mUnsupportedDisplaySizeDialog != null && ssp.equals(
@@ -19890,8 +19889,9 @@ public class ActivityManagerService extends IActivityManager.Stub
}
/**
- * NOTE: For the pinned stack, this method is only called after the bounds animation has
- * animated the stack to the fullscreen.
+ * NOTE: For the pinned stack, this method is usually called after the bounds animation has
+ * animated the stack to the fullscreen, but can also be called if we are relaunching an
+ * activity and clearing the task at the same time.
*/
@Override
public void moveTasksToFullscreenStack(int fromStackId, boolean onTop) {
@@ -22277,6 +22277,9 @@ public class ActivityManagerService extends IActivityManager.Stub
if (uidRec.curProcState > app.curProcState) {
uidRec.curProcState = app.curProcState;
}
+ if (app.foregroundServices) {
+ uidRec.foregroundServices = true;
+ }
}
}
@@ -22518,6 +22521,9 @@ public class ActivityManagerService extends IActivityManager.Stub
uidRec.setWhitelist = uidRec.curWhitelist;
enqueueUidChangeLocked(uidRec, -1, uidChange);
noteUidProcessState(uidRec.uid, uidRec.curProcState);
+ if (uidRec.foregroundServices) {
+ mServices.foregroundServiceProcStateChangedLocked(uidRec);
+ }
}
}
if (mLocalPowerManager != null) {
@@ -23726,17 +23732,17 @@ public class ActivityManagerService extends IActivityManager.Stub
/**
* Called after virtual display Id is updated by
- * {@link com.android.server.vr.CompatibilityDisplay} with a specific
- * {@param vrCompatibilityDisplayId}.
+ * {@link com.android.server.vr.Vr2dDisplay} with a specific
+ * {@param vrVr2dDisplayId}.
*/
@Override
- public void setVrCompatibilityDisplayId(int vrCompatibilityDisplayId) {
+ public void setVr2dDisplayId(int vr2dDisplayId) {
if (DEBUG_STACK) {
- Slog.d(TAG, "setVrCompatibilityDisplayId called for: " +
- vrCompatibilityDisplayId);
+ Slog.d(TAG, "setVr2dDisplayId called for: " +
+ vr2dDisplayId);
}
synchronized (ActivityManagerService.this) {
- mVrCompatibilityDisplayId = vrCompatibilityDisplayId;
+ mVr2dDisplayId = vr2dDisplayId;
}
}
}
@@ -23800,11 +23806,8 @@ public class ActivityManagerService extends IActivityManager.Stub
if (totalTime >= mWaitForNetworkTimeoutMs) {
Slog.wtf(TAG_NETWORK, "Total time waited for network rules to get updated: "
+ totalTime + ". Uid: " + callingUid + " procStateSeq: "
- + procStateSeq);
- } else if (DEBUG_NETWORK || totalTime >= mWaitForNetworkTimeoutMs / 2) {
- Slog.d(TAG_NETWORK, "Total time waited for network rules to get updated: "
- + totalTime + ". Uid: " + callingUid + " procStateSeq: "
- + procStateSeq);
+ + procStateSeq + " UidRec: " + record
+ + " validateUidRec: " + mValidateUids.get(callingUid));
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index 19b9b452df7e..1f1aa8e8cdd9 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -186,7 +186,7 @@ class ActivityStarter {
private IVoiceInteractionSession mVoiceSession;
private IVoiceInteractor mVoiceInteractor;
- private boolean mUsingVrCompatibilityDisplay;
+ private boolean mUsingVr2dDisplay;
private void reset() {
mStartActivity = null;
@@ -226,14 +226,14 @@ class ActivityStarter {
mVoiceSession = null;
mVoiceInteractor = null;
- mUsingVrCompatibilityDisplay = false;
+ mUsingVr2dDisplay = false;
}
ActivityStarter(ActivityManagerService service, ActivityStackSupervisor supervisor) {
mService = service;
mSupervisor = supervisor;
mInterceptor = new ActivityStartInterceptor(mService, mSupervisor);
- mUsingVrCompatibilityDisplay = false;
+ mUsingVr2dDisplay = false;
}
final int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
@@ -575,12 +575,15 @@ class ActivityStarter {
return;
}
- if (startedActivityStackId == PINNED_STACK_ID
- && (result == START_TASK_TO_FRONT || result == START_DELIVERED_TO_TOP)) {
+ boolean clearedTask = (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
+ == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
+ if (startedActivityStackId == PINNED_STACK_ID && (result == START_TASK_TO_FRONT
+ || result == START_DELIVERED_TO_TOP || clearedTask)) {
// The activity was already running in the pinned stack so it wasn't started, but either
// brought to the front or the new intent was delivered to it since it was already in
// front. Notify anyone interested in this piece of information.
- mService.mTaskChangeNotificationController.notifyPinnedActivityRestartAttempt();
+ mService.mTaskChangeNotificationController.notifyPinnedActivityRestartAttempt(
+ clearedTask);
return;
}
}
@@ -953,7 +956,7 @@ class ActivityStarter {
// If we are not able to proceed, disassociate the activity from the task. Leaving an
// activity in an incomplete state can lead to issues, such as performing operations
// without a window container.
- if (result != START_SUCCESS && mStartActivity.getTask() != null) {
+ if (result < START_SUCCESS && mStartActivity.getTask() != null) {
mStartActivity.getTask().removeActivity(mStartActivity);
}
mService.mWindowManager.continueSurfaceLayout();
@@ -1059,7 +1062,7 @@ class ActivityStarter {
// We didn't do anything... but it was needed (a.k.a., client don't use that
// intent!) And for paranoia, make sure we have correctly resumed the top activity.
resumeTargetStackIfNeeded();
- if (outActivity.length > 0) {
+ if (outActivity != null && outActivity.length > 0) {
outActivity[0] = reusedActivity;
}
return START_TASK_TO_FRONT;
@@ -1476,12 +1479,12 @@ class ActivityStarter {
}
// Get the virtual display id from ActivityManagerService.
- int displayId = mService.mVrCompatibilityDisplayId;
+ int displayId = mService.mVr2dDisplayId;
if (displayId != INVALID_DISPLAY) {
if (DEBUG_STACK) {
Slog.d(TAG, "getSourceDisplayId :" + displayId);
}
- mUsingVrCompatibilityDisplay = true;
+ mUsingVr2dDisplay = true;
return displayId;
}
@@ -2105,8 +2108,8 @@ class ActivityStarter {
return mSupervisor.getValidLaunchStackOnDisplay(launchDisplayId, r);
}
- // If we are using Vr compatibility display, find the virtual display stack.
- if (mUsingVrCompatibilityDisplay) {
+ // If we are using Vr2d display, find the virtual display stack.
+ if (mUsingVr2dDisplay) {
ActivityStack as = mSupervisor.getValidLaunchStackOnDisplay(mSourceDisplayId, r);
if (DEBUG_STACK) {
Slog.v(TAG, "Launch stack for app: " + r.toString() +
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index b025385413ea..fbc2bd270a75 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -103,7 +103,6 @@ final class ProcessRecord {
int renderThreadTid; // TID for RenderThread
boolean serviceb; // Process currently is on the service B list
boolean serviceHighRam; // We are forcing to service B list due to its RAM use
- boolean setIsForeground; // Running foreground UI when last set?
boolean notCachedSinceIdle; // Has this process not been in a cached state since last idle?
boolean hasClientActivities; // Are there any client services with activities?
boolean hasStartedServices; // Are there any started services running in this process?
@@ -303,9 +302,8 @@ final class ProcessRecord {
pw.print(" hasAboveClient="); pw.print(hasAboveClient);
pw.print(" treatLikeActivity="); pw.println(treatLikeActivity);
}
- if (setIsForeground || foregroundServices || forcingToForeground != null) {
- pw.print(prefix); pw.print("setIsForeground="); pw.print(setIsForeground);
- pw.print(" foregroundServices="); pw.print(foregroundServices);
+ if (foregroundServices || forcingToForeground != null) {
+ pw.print(prefix); pw.print("foregroundServices="); pw.print(foregroundServices);
pw.print(" forcingToForeground="); pw.println(forcingToForeground);
}
if (reportedInteraction || fgInteractionTime != 0) {
diff --git a/services/core/java/com/android/server/am/TaskChangeNotificationController.java b/services/core/java/com/android/server/am/TaskChangeNotificationController.java
index 7d2bc5b51c2e..f5d7b6858b83 100644
--- a/services/core/java/com/android/server/am/TaskChangeNotificationController.java
+++ b/services/core/java/com/android/server/am/TaskChangeNotificationController.java
@@ -104,7 +104,7 @@ class TaskChangeNotificationController {
};
private final TaskStackConsumer mNotifyPinnedActivityRestartAttempt = (l, m) -> {
- l.onPinnedActivityRestartAttempt();
+ l.onPinnedActivityRestartAttempt(m.arg1 != 0);
};
private final TaskStackConsumer mNotifyPinnedStackAnimationStarted = (l, m) -> {
@@ -300,10 +300,11 @@ class TaskChangeNotificationController {
* running in the pinned stack and the activity was not actually started, but the task is
* either brought to the front or a new Intent is delivered to it.
*/
- void notifyPinnedActivityRestartAttempt() {
+ void notifyPinnedActivityRestartAttempt(boolean clearedTask) {
mHandler.removeMessages(NOTIFY_PINNED_ACTIVITY_RESTART_ATTEMPT_LISTENERS_MSG);
final Message msg =
- mHandler.obtainMessage(NOTIFY_PINNED_ACTIVITY_RESTART_ATTEMPT_LISTENERS_MSG);
+ mHandler.obtainMessage(NOTIFY_PINNED_ACTIVITY_RESTART_ATTEMPT_LISTENERS_MSG,
+ clearedTask ? 1 : 0, 0);
forAllLocalListeners(mNotifyPinnedActivityRestartAttempt, msg);
msg.sendToTarget();
}
diff --git a/services/core/java/com/android/server/am/UidRecord.java b/services/core/java/com/android/server/am/UidRecord.java
index c0fb77f08647..c411bcec4540 100644
--- a/services/core/java/com/android/server/am/UidRecord.java
+++ b/services/core/java/com/android/server/am/UidRecord.java
@@ -35,6 +35,7 @@ public final class UidRecord {
int setProcState = ActivityManager.PROCESS_STATE_NONEXISTENT;
long lastBackgroundTime;
boolean ephemeral;
+ boolean foregroundServices;
boolean curWhitelist;
boolean setWhitelist;
boolean idle;
@@ -102,6 +103,7 @@ public final class UidRecord {
public void reset() {
curProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
+ foregroundServices = false;
}
public void updateHasInternetPermission() {
@@ -131,6 +133,9 @@ public final class UidRecord {
if (ephemeral) {
sb.append(" ephemeral");
}
+ if (foregroundServices) {
+ sb.append(" fgServices");
+ }
if (curWhitelist) {
sb.append(" whitelist");
}
diff --git a/services/core/java/com/android/server/display/NightDisplayService.java b/services/core/java/com/android/server/display/NightDisplayService.java
index d1275bb2224a..78498967b344 100644
--- a/services/core/java/com/android/server/display/NightDisplayService.java
+++ b/services/core/java/com/android/server/display/NightDisplayService.java
@@ -47,7 +47,6 @@ import com.android.server.SystemService;
import com.android.server.twilight.TwilightListener;
import com.android.server.twilight.TwilightManager;
import com.android.server.twilight.TwilightState;
-import com.android.server.vr.VrManagerService;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.Calendar;
@@ -62,7 +61,6 @@ public final class NightDisplayService extends SystemService
implements NightDisplayController.Callback {
private static final String TAG = "NightDisplayService";
- private static final boolean DEBUG = false;
/**
* The transition time, in milliseconds, for Night Display to turn on/off.
@@ -151,8 +149,9 @@ public final class NightDisplayService extends SystemService
@Override
public void onBootPhase(int phase) {
- if (phase == PHASE_SYSTEM_SERVICES_READY) {
- IVrManager vrManager = (IVrManager) getBinderService(Context.VR_SERVICE);
+ if (phase >= PHASE_SYSTEM_SERVICES_READY) {
+ final IVrManager vrManager = IVrManager.Stub.asInterface(
+ getBinderService(Context.VR_SERVICE));
if (vrManager != null) {
try {
vrManager.registerListener(mVrStateCallbacks);
@@ -160,7 +159,9 @@ public final class NightDisplayService extends SystemService
Slog.e(TAG, "Failed to register VR mode state listener: " + e);
}
}
- } else if (phase == PHASE_BOOT_COMPLETED) {
+ }
+
+ if (phase >= PHASE_BOOT_COMPLETED) {
mBootCompleted = true;
// Register listeners now that boot is complete.
@@ -284,12 +285,18 @@ public final class NightDisplayService extends SystemService
if (mIsActivated == null || mIsActivated != activated) {
Slog.i(TAG, activated ? "Turning on night display" : "Turning off night display");
- if (mAutoMode != null) {
- mAutoMode.onActivated(activated);
+ if (mIsActivated != null) {
+ Secure.putLongForUser(getContext().getContentResolver(),
+ Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME, System.currentTimeMillis(),
+ mCurrentUser);
}
mIsActivated = activated;
+ if (mAutoMode != null) {
+ mAutoMode.onActivated(activated);
+ }
+
applyTint(false);
}
}
@@ -401,7 +408,7 @@ public final class NightDisplayService extends SystemService
* Set the color transformation {@code MATRIX_NIGHT} to the given color temperature.
*
* @param colorTemperature color temperature in Kelvin
- * @param outTemp the 4x4 display transformation matrix for that color temperature
+ * @param outTemp the 4x4 display transformation matrix for that color temperature
*/
private void setMatrix(int colorTemperature, float[] outTemp) {
if (outTemp.length != 16) {
@@ -423,8 +430,22 @@ public final class NightDisplayService extends SystemService
outTemp[10] = blue;
}
+ private Calendar getLastActivatedTime() {
+ final ContentResolver cr = getContext().getContentResolver();
+ final long lastActivatedTimeMillis = Secure.getLongForUser(
+ cr, Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME, -1, mCurrentUser);
+ if (lastActivatedTimeMillis < 0) {
+ return null;
+ }
+
+ final Calendar lastActivatedTime = Calendar.getInstance();
+ lastActivatedTime.setTimeInMillis(lastActivatedTimeMillis);
+ return lastActivatedTime;
+ }
+
private abstract class AutoMode implements NightDisplayController.Callback {
public abstract void onStart();
+
public abstract void onStop();
}
@@ -438,7 +459,7 @@ public final class NightDisplayService extends SystemService
private Calendar mLastActivatedTime;
- public CustomAutoMode() {
+ CustomAutoMode() {
mAlarmManager = (AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE);
mTimeChangedReceiver = new BroadcastReceiver() {
@Override
@@ -452,10 +473,10 @@ public final class NightDisplayService extends SystemService
final Calendar now = Calendar.getInstance();
final Calendar startTime = mStartTime.getDateTimeBefore(now);
final Calendar endTime = mEndTime.getDateTimeAfter(startTime);
- final boolean activated = now.before(endTime);
- boolean setActivated = mIsActivated == null || mLastActivatedTime == null;
- if (!setActivated && mIsActivated != activated) {
+ boolean activate = now.before(endTime);
+ if (mLastActivatedTime != null) {
+ // Convert mLastActivatedTime to the current timezone if needed.
final TimeZone currentTimeZone = now.getTimeZone();
if (!currentTimeZone.equals(mLastActivatedTime.getTimeZone())) {
final int year = mLastActivatedTime.get(Calendar.YEAR);
@@ -470,17 +491,16 @@ public final class NightDisplayService extends SystemService
mLastActivatedTime.set(Calendar.MINUTE, minute);
}
- if (mIsActivated) {
- setActivated = now.before(mStartTime.getDateTimeBefore(mLastActivatedTime))
- || now.after(mEndTime.getDateTimeAfter(mLastActivatedTime));
- } else {
- setActivated = now.before(mEndTime.getDateTimeBefore(mLastActivatedTime))
- || now.after(mStartTime.getDateTimeAfter(mLastActivatedTime));
+ // Maintain the existing activated state if within the current period.
+ if (mLastActivatedTime.before(now)
+ && mLastActivatedTime.after(startTime)
+ && (mLastActivatedTime.after(endTime) || now.before(endTime))) {
+ activate = mController.isActivated();
}
}
- if (setActivated) {
- mController.setActivated(activated);
+ if (mIsActivated == null || mIsActivated != activate) {
+ mController.setActivated(activate);
}
updateNextAlarm(mIsActivated, now);
}
@@ -502,6 +522,8 @@ public final class NightDisplayService extends SystemService
mStartTime = mController.getCustomStartTime();
mEndTime = mController.getCustomEndTime();
+ mLastActivatedTime = getLastActivatedTime();
+
// Force an update to initialize state.
updateActivated();
}
@@ -516,11 +538,8 @@ public final class NightDisplayService extends SystemService
@Override
public void onActivated(boolean activated) {
- final Calendar now = Calendar.getInstance();
- if (mIsActivated != null) {
- mLastActivatedTime = now;
- }
- updateNextAlarm(activated, now);
+ mLastActivatedTime = getLastActivatedTime();
+ updateNextAlarm(activated, Calendar.getInstance());
}
@Override
@@ -550,33 +569,33 @@ public final class NightDisplayService extends SystemService
private Calendar mLastActivatedTime;
- public TwilightAutoMode() {
+ TwilightAutoMode() {
mTwilightManager = getLocalService(TwilightManager.class);
}
private void updateActivated(TwilightState state) {
- final boolean isNight = state != null && state.isNight();
- boolean setActivated = mIsActivated == null || mIsActivated != isNight;
- if (setActivated && state != null && mLastActivatedTime != null) {
+ boolean activate = state != null && state.isNight();
+ if (state != null && mLastActivatedTime != null) {
+ final Calendar now = Calendar.getInstance();
final Calendar sunrise = state.sunrise();
final Calendar sunset = state.sunset();
- if (sunrise.before(sunset)) {
- setActivated = mLastActivatedTime.before(sunrise)
- || mLastActivatedTime.after(sunset);
- } else {
- setActivated = mLastActivatedTime.before(sunset)
- || mLastActivatedTime.after(sunrise);
+
+ // Maintain the existing activated state if within the current period.
+ if (mLastActivatedTime.before(now)
+ && (mLastActivatedTime.after(sunrise) ^ mLastActivatedTime.after(sunset))) {
+ activate = mController.isActivated();
}
}
- if (setActivated) {
- mController.setActivated(isNight);
+ if (mIsActivated == null || mIsActivated != activate) {
+ mController.setActivated(activate);
}
}
@Override
public void onStart() {
mTwilightManager.registerListener(this, mHandler);
+ mLastActivatedTime = getLastActivatedTime();
// Force an update to initialize state.
updateActivated(mTwilightManager.getLastTwilightState());
@@ -591,7 +610,7 @@ public final class NightDisplayService extends SystemService
@Override
public void onActivated(boolean activated) {
if (mIsActivated != null) {
- mLastActivatedTime = Calendar.getInstance();
+ mLastActivatedTime = getLastActivatedTime();
}
}
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index 91c32e48d802..51bebb0963c9 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -382,6 +382,8 @@ public class GnssLocationProvider implements LocationProviderInterface {
// Wakelocks
private final static String WAKELOCK_KEY = "GnssLocationProvider";
private final PowerManager.WakeLock mWakeLock;
+ private static final String DOWNLOAD_EXTRA_WAKELOCK_KEY = "GnssLocationProviderXtraDownload";
+ private final PowerManager.WakeLock mDownloadXtraWakeLock;
// Alarms
private final static String ALARM_WAKEUP = "com.android.internal.location.ALARM_WAKEUP";
@@ -686,6 +688,11 @@ public class GnssLocationProvider implements LocationProviderInterface {
mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
mWakeLock.setReferenceCounted(true);
+ // Create a separate wake lock for xtra downloader as it may be released due to timeout.
+ mDownloadXtraWakeLock = mPowerManager.newWakeLock(
+ PowerManager.PARTIAL_WAKE_LOCK, DOWNLOAD_EXTRA_WAKELOCK_KEY);
+ mDownloadXtraWakeLock.setReferenceCounted(true);
+
mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
mWakeupIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_WAKEUP), 0);
mTimeoutIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_TIMEOUT), 0);
@@ -989,7 +996,7 @@ public class GnssLocationProvider implements LocationProviderInterface {
mDownloadXtraDataPending = STATE_DOWNLOADING;
// hold wake lock while task runs
- mWakeLock.acquire(DOWNLOAD_XTRA_DATA_TIMEOUT_MS);
+ mDownloadXtraWakeLock.acquire(DOWNLOAD_XTRA_DATA_TIMEOUT_MS);
Log.i(TAG, "WakeLock acquired by handleDownloadXtraData()");
AsyncTask.THREAD_POOL_EXECUTOR.execute(new Runnable() {
@Override
@@ -1011,13 +1018,17 @@ public class GnssLocationProvider implements LocationProviderInterface {
mXtraBackOff.nextBackoffMillis());
}
- // release wake lock held by task
- if (mWakeLock.isHeld()) {
- mWakeLock.release();
- } else {
- Log.e(TAG, "WakeLock expired before release in handleDownloadXtraData()");
+ // Release wake lock held by task, synchronize on mLock in case multiple
+ // download tasks overrun.
+ synchronized (mLock) {
+ if (mDownloadXtraWakeLock.isHeld()) {
+ mDownloadXtraWakeLock.release();
+ if (DEBUG) Log.d(TAG, "WakeLock released by handleDownloadXtraData()");
+ } else {
+ Log.e(TAG, "WakeLock expired before release in "
+ + "handleDownloadXtraData()");
+ }
}
- Log.i(TAG, "WakeLock released by handleDownloadXtraData()");
}
});
}
diff --git a/services/core/java/com/android/server/notification/NotificationIntrusivenessExtractor.java b/services/core/java/com/android/server/notification/NotificationIntrusivenessExtractor.java
index f92bf3dd4427..4981d5c5731f 100644
--- a/services/core/java/com/android/server/notification/NotificationIntrusivenessExtractor.java
+++ b/services/core/java/com/android/server/notification/NotificationIntrusivenessExtractor.java
@@ -66,7 +66,11 @@ public class NotificationIntrusivenessExtractor implements NotificationSignalExt
@Override
public void applyChangesLocked(NotificationRecord record) {
- record.setRecentlyIntrusive(false);
+ // there will be another reconsideration in the message queue HANG_TIME_MS
+ // from each time this record alerts, which can finally clear this flag.
+ if ((System.currentTimeMillis() - record.getLastIntrusive()) >= HANG_TIME_MS) {
+ record.setRecentlyIntrusive(false);
+ }
}
};
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index a8959c56ae22..1d843c1cabf8 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -884,6 +884,8 @@ public class NotificationManagerService extends SystemService {
} else if (action.equals(Intent.ACTION_USER_REMOVED)) {
final int user = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
mZenModeHelper.onUserRemoved(user);
+ mRankingHelper.onUserRemoved(user);
+ savePolicyFile();
} else if (action.equals(Intent.ACTION_USER_UNLOCKED)) {
final int user = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
mConditionProviders.onUserUnlocked(user);
@@ -2869,7 +2871,8 @@ public class NotificationManagerService extends SystemService {
adjustedSbn.getUser(), GroupHelper.AUTOGROUP_KEY,
System.currentTimeMillis());
summaryRecord = new NotificationRecord(getContext(), summarySbn,
- notificationRecord.getChannel());
+ notificationRecord.getChannel(), mRankingHelper.supportsChannels(
+ summarySbn.getPackageName(), summarySbn.getUid()));
summaries.put(pkg, summarySbn.getKey());
}
}
@@ -3198,10 +3201,8 @@ public class NotificationManagerService extends SystemService {
+ ", incomingUserId=" + incomingUserId
+ ", notificationUid=" + notificationUid
+ ", notification=" + notification;
- // STOPSHIP TODO: should throw instead of logging or toasting.
- // throw new IllegalArgumentException(noChannelStr);
Log.e(TAG, noChannelStr);
- doDebugOnlyToast("Developer warning for package \"" + pkg + "\"\n" +
+ doChannelWarningToast("Developer warning for package \"" + pkg + "\"\n" +
"Failed to post notification on channel \"" + channelId + "\"\n" +
"See log for more details");
return;
@@ -3210,7 +3211,8 @@ public class NotificationManagerService extends SystemService {
final StatusBarNotification n = new StatusBarNotification(
pkg, opPkg, id, tag, notificationUid, callingPid, notification,
user, null, System.currentTimeMillis());
- final NotificationRecord r = new NotificationRecord(getContext(), n, channel);
+ final NotificationRecord r = new NotificationRecord(getContext(), n, channel,
+ mRankingHelper.supportsChannels(pkg, notificationUid));
if (!checkDisqualifyingFeatures(userId, notificationUid, id,tag, r)) {
return;
@@ -3236,8 +3238,10 @@ public class NotificationManagerService extends SystemService {
mHandler.post(new EnqueueNotificationRunnable(userId, r));
}
- private void doDebugOnlyToast(CharSequence toastText) {
- if (Build.IS_DEBUGGABLE) {
+ private void doChannelWarningToast(CharSequence toastText) {
+ final boolean warningEnabled = Settings.System.getInt(getContext().getContentResolver(),
+ Settings.Global.SHOW_NOTIFICATION_CHANNEL_WARNINGS, 0) != 0;
+ if (warningEnabled || Build.IS_DEBUGGABLE) {
try {
Toast toast = Toast.makeText(getContext(), toastText, Toast.LENGTH_LONG);
toast.show();
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index b51a4d10a053..f019a5ce00ea 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -85,6 +85,7 @@ public final class NotificationRecord {
// to communicate with the ranking module.
private float mContactAffinity;
private boolean mRecentlyIntrusive;
+ private long mLastIntrusive;
// is this notification currently being intercepted by Zen Mode?
private boolean mIntercept;
@@ -115,7 +116,7 @@ public final class NotificationRecord {
private int mSuppressedVisualEffects = 0;
private String mUserExplanation;
private String mPeopleExplanation;
- private boolean mPreChannelsNotification = true;
+ private boolean mSupportsChannels = false;
private Uri mSound;
private long[] mVibration;
private AudioAttributes mAttributes;
@@ -128,7 +129,7 @@ public final class NotificationRecord {
@VisibleForTesting
public NotificationRecord(Context context, StatusBarNotification sbn,
- NotificationChannel channel)
+ NotificationChannel channel, boolean supportsChannels)
{
this.sbn = sbn;
mOriginalFlags = sbn.getNotification().flags;
@@ -138,7 +139,7 @@ public final class NotificationRecord {
mContext = context;
stats = new NotificationUsageStats.SingleNotificationStats();
mChannel = channel;
- mPreChannelsNotification = isPreChannelsNotification();
+ mSupportsChannels = supportsChannels;
mSound = calculateSound();
mVibration = calculateVibration();
mAttributes = calculateAttributes();
@@ -146,27 +147,11 @@ public final class NotificationRecord {
mLight = calculateLights();
}
- private boolean isPreChannelsNotification() {
- try {
- if (NotificationChannel.DEFAULT_CHANNEL_ID.equals(getChannel().getId())) {
- final ApplicationInfo applicationInfo =
- mContext.getPackageManager().getApplicationInfoAsUser(sbn.getPackageName(),
- 0, UserHandle.getUserId(sbn.getUid()));
- if (applicationInfo.targetSdkVersion <= Build.VERSION_CODES.N_MR1) {
- return true;
- }
- }
- } catch (NameNotFoundException e) {
- Slog.e(TAG, "Can't find package", e);
- }
- return false;
- }
-
private Uri calculateSound() {
final Notification n = sbn.getNotification();
Uri sound = mChannel.getSound();
- if (mPreChannelsNotification && (getChannel().getUserLockedFields()
+ if (!mSupportsChannels && (getChannel().getUserLockedFields()
& NotificationChannel.USER_LOCKED_SOUND) == 0) {
final boolean useDefaultSound = (n.defaults & Notification.DEFAULT_SOUND) != 0;
@@ -191,7 +176,7 @@ public final class NotificationRecord {
: defaultLightColor;
Light light = getChannel().shouldShowLights() ? new Light(channelLightColor,
defaultLightOn, defaultLightOff) : null;
- if (mPreChannelsNotification
+ if (!mSupportsChannels
&& (getChannel().getUserLockedFields()
& NotificationChannel.USER_LOCKED_LIGHTS) == 0) {
final Notification notification = sbn.getNotification();
@@ -222,7 +207,7 @@ public final class NotificationRecord {
} else {
vibration = null;
}
- if (mPreChannelsNotification
+ if (!mSupportsChannels
&& (getChannel().getUserLockedFields()
& NotificationChannel.USER_LOCKED_VIBRATION) == 0) {
final Notification notification = sbn.getNotification();
@@ -244,7 +229,7 @@ public final class NotificationRecord {
attributes = Notification.AUDIO_ATTRIBUTES_DEFAULT;
}
- if (mPreChannelsNotification
+ if (!mSupportsChannels
&& (getChannel().getUserLockedFields()
& NotificationChannel.USER_LOCKED_SOUND) == 0) {
if (n.audioAttributes != null) {
@@ -293,7 +278,7 @@ public final class NotificationRecord {
stats.requestedImportance = requestedImportance;
stats.isNoisy = mSound != null || mVibration != null;
- if (mPreChannelsNotification
+ if (!mSupportsChannels
&& (importance == IMPORTANCE_UNSPECIFIED
|| (getChannel().getUserLockedFields()
& NotificationChannel.USER_LOCKED_IMPORTANCE) == 0)) {
@@ -460,7 +445,7 @@ public final class NotificationRecord {
pw.println(prefix + "mVisibleSinceMs=" + mVisibleSinceMs);
pw.println(prefix + "mUpdateTimeMs=" + mUpdateTimeMs);
pw.println(prefix + "mSuppressedVisualEffects= " + mSuppressedVisualEffects);
- if (mPreChannelsNotification) {
+ if (!mSupportsChannels) {
pw.println(prefix + String.format("defaults=0x%08x flags=0x%08x",
notification.defaults, notification.flags));
pw.println(prefix + "n.sound=" + notification.sound);
@@ -531,12 +516,19 @@ public final class NotificationRecord {
public void setRecentlyIntrusive(boolean recentlyIntrusive) {
mRecentlyIntrusive = recentlyIntrusive;
+ if (recentlyIntrusive) {
+ mLastIntrusive = System.currentTimeMillis();
+ }
}
public boolean isRecentlyIntrusive() {
return mRecentlyIntrusive;
}
+ public long getLastIntrusive() {
+ return mLastIntrusive;
+ }
+
public void setPackagePriority(int packagePriority) {
mPackagePriority = packagePriority;
}
diff --git a/services/core/java/com/android/server/notification/RankingConfig.java b/services/core/java/com/android/server/notification/RankingConfig.java
index 4d19b52c327a..14d796f59c37 100644
--- a/services/core/java/com/android/server/notification/RankingConfig.java
+++ b/services/core/java/com/android/server/notification/RankingConfig.java
@@ -42,4 +42,6 @@ public interface RankingConfig {
void permanentlyDeleteNotificationChannel(String pkg, int uid, String channelId);
void permanentlyDeleteNotificationChannels(String pkg, int uid);
ParceledListSlice<NotificationChannel> getNotificationChannels(String pkg, int uid, boolean includeDeleted);
+
+ boolean supportsChannels(String pkg, int uid);
}
diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java
index 850b730f3dff..1e741de5f269 100644
--- a/services/core/java/com/android/server/notification/RankingHelper.java
+++ b/services/core/java/com/android/server/notification/RankingHelper.java
@@ -273,8 +273,14 @@ public class RankingHelper implements RankingConfig {
}
private boolean shouldHaveDefaultChannel(Record r) throws NameNotFoundException {
+ if (supportsChannels(r)) {
+ return false;
+ }
+
final int userId = UserHandle.getUserId(r.uid);
- final ApplicationInfo applicationInfo = mPm.getApplicationInfoAsUser(r.pkg, 0, userId);
+ final ApplicationInfo applicationInfo = mPm.getApplicationInfoAsUser(r.pkg,
+ PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
+ userId);
if (applicationInfo.targetSdkVersion > Build.VERSION_CODES.N_MR1) {
// O apps should not have the default channel.
return false;
@@ -500,6 +506,31 @@ public class RankingHelper implements RankingConfig {
}
@Override
+ public boolean supportsChannels(String pkg, int uid) {
+ Record r = getOrCreateRecord(pkg, uid);
+
+ if (r == null) {
+ return false;
+ }
+
+ if (r.channels.size() == 1
+ && r.channels.containsKey(NotificationChannel.DEFAULT_CHANNEL_ID)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ private boolean supportsChannels(Record r) {
+ if (r.channels.size() == 1
+ && r.channels.containsKey(NotificationChannel.DEFAULT_CHANNEL_ID)) {
+ return false;
+ }
+
+ return (r.channels.size() > 0);
+ }
+
+ @Override
public void createNotificationChannelGroup(String pkg, int uid, NotificationChannelGroup group,
boolean fromTargetApp) {
Preconditions.checkNotNull(pkg);
@@ -571,6 +602,10 @@ public class RankingHelper implements RankingConfig {
r.channels.put(channel.getId(), channel);
MetricsLogger.action(getChannelLog(channel, pkg).setType(
MetricsProto.MetricsEvent.TYPE_OPEN));
+
+ // Remove Default Channel.
+ r.channels.remove(NotificationChannel.DEFAULT_CHANNEL_ID);
+
updateConfig();
}
@@ -667,13 +702,7 @@ public class RankingHelper implements RankingConfig {
if (r == null) {
return;
}
- int N = r.channels.size() - 1;
- for (int i = N; i >= 0; i--) {
- String key = r.channels.keyAt(i);
- if (!NotificationChannel.DEFAULT_CHANNEL_ID.equals(key)) {
- r.channels.remove(key);
- }
- }
+ r.channels.clear();
updateConfig();
}
@@ -1011,6 +1040,18 @@ public class RankingHelper implements RankingConfig {
return packageChannels;
}
+ public void onUserRemoved(int userId) {
+ synchronized (mRecords) {
+ int N = mRecords.size();
+ for (int i = N - 1; i >= 0 ; i--) {
+ Record record = mRecords.valueAt(i);
+ if (UserHandle.getUserId(record.uid) == userId) {
+ mRecords.removeAt(i);
+ }
+ }
+ }
+ }
+
public void onPackagesChanged(boolean removingPackage, int changeUserId, String[] pkgList,
int[] uidList) {
if (pkgList == null || pkgList.length == 0) {
@@ -1025,6 +1066,8 @@ public class RankingHelper implements RankingConfig {
final int uid = uidList[i];
synchronized (mRecords) {
mRecords.remove(recordKey(pkg, uid));
+ // reset to default settings and re-add misc channel for pre-O apps
+ getOrCreateRecord(pkg, uid);
}
mRestoredWithoutUids.remove(pkg);
updated = true;
diff --git a/services/core/java/com/android/server/pm/EphemeralResolverConnection.java b/services/core/java/com/android/server/pm/EphemeralResolverConnection.java
index 9d08004c579a..09e9433c9a02 100644
--- a/services/core/java/com/android/server/pm/EphemeralResolverConnection.java
+++ b/services/core/java/com/android/server/pm/EphemeralResolverConnection.java
@@ -43,6 +43,7 @@ import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
+import java.util.NoSuchElementException;
import java.util.concurrent.TimeoutException;
/**
@@ -206,7 +207,9 @@ final class EphemeralResolverConnection implements DeathRecipient {
private void handleBinderDiedLocked() {
if (mRemoteInstance != null) {
- mRemoteInstance.asBinder().unlinkToDeath(this, 0 /*flags*/);
+ try {
+ mRemoteInstance.asBinder().unlinkToDeath(this, 0 /*flags*/);
+ } catch (NoSuchElementException ignore) { }
}
mRemoteInstance = null;
}
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index 4c0d9da52f37..f94a56f15fe0 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -24,6 +24,7 @@ import android.content.pm.PackageParser;
import android.os.Environment;
import android.os.FileUtils;
import android.os.PowerManager;
+import android.os.SystemClock;
import android.os.UserHandle;
import android.os.WorkSource;
import android.util.Log;
@@ -54,6 +55,7 @@ import static com.android.server.pm.Installer.DEXOPT_STORAGE_DE;
import static com.android.server.pm.InstructionSets.getAppDexInstructionSets;
import static com.android.server.pm.InstructionSets.getDexCodeInstructionSets;
+import static com.android.server.pm.PackageManagerService.WATCHDOG_TIMEOUT;
import static com.android.server.pm.PackageManagerServiceCompilerMapping.getNonProfileGuidedCompilerFilter;
import static dalvik.system.DexFile.isProfileGuidedCompilerFilter;
@@ -67,13 +69,17 @@ public class PackageDexOptimizer {
public static final int DEX_OPT_SKIPPED = 0;
public static final int DEX_OPT_PERFORMED = 1;
public static final int DEX_OPT_FAILED = -1;
+ // One minute over PM WATCHDOG_TIMEOUT
+ private static final long WAKELOCK_TIMEOUT_MS = WATCHDOG_TIMEOUT + 1000 * 60;
/** Special library name that skips shared libraries check during compilation. */
public static final String SKIP_SHARED_LIBRARY_CHECK = "&";
+ @GuardedBy("mInstallLock")
private final Installer mInstaller;
private final Object mInstallLock;
+ @GuardedBy("mInstallLock")
private final PowerManager.WakeLock mDexoptWakeLock;
private volatile boolean mSystemReady;
@@ -111,21 +117,12 @@ public class PackageDexOptimizer {
return DEX_OPT_SKIPPED;
}
synchronized (mInstallLock) {
- // During boot the system doesn't need to instantiate and obtain a wake lock.
- // PowerManager might not be ready, but that doesn't mean that we can't proceed with
- // dexopt.
- final boolean useLock = mSystemReady;
- if (useLock) {
- mDexoptWakeLock.setWorkSource(new WorkSource(pkg.applicationInfo.uid));
- mDexoptWakeLock.acquire();
- }
+ final long acquireTime = acquireWakeLockLI(pkg.applicationInfo.uid);
try {
return performDexOptLI(pkg, sharedLibraries, instructionSets, checkProfiles,
targetCompilationFilter, packageStats, isUsedByOtherApps);
} finally {
- if (useLock) {
- mDexoptWakeLock.release();
- }
+ releaseWakeLockLI(acquireTime);
}
}
}
@@ -250,22 +247,46 @@ public class PackageDexOptimizer {
public int dexOptSecondaryDexPath(ApplicationInfo info, String path, Set<String> isas,
String compilerFilter, boolean isUsedByOtherApps) {
synchronized (mInstallLock) {
- // During boot the system doesn't need to instantiate and obtain a wake lock.
- // PowerManager might not be ready, but that doesn't mean that we can't proceed with
- // dexopt.
- final boolean useLock = mSystemReady;
- if (useLock) {
- mDexoptWakeLock.setWorkSource(new WorkSource(info.uid));
- mDexoptWakeLock.acquire();
- }
+ final long acquireTime = acquireWakeLockLI(info.uid);
try {
return dexOptSecondaryDexPathLI(info, path, isas, compilerFilter,
isUsedByOtherApps);
} finally {
- if (useLock) {
- mDexoptWakeLock.release();
- }
+ releaseWakeLockLI(acquireTime);
+ }
+ }
+ }
+
+ @GuardedBy("mInstallLock")
+ private long acquireWakeLockLI(final int uid) {
+ // During boot the system doesn't need to instantiate and obtain a wake lock.
+ // PowerManager might not be ready, but that doesn't mean that we can't proceed with
+ // dexopt.
+ if (!mSystemReady) {
+ return -1;
+ }
+ mDexoptWakeLock.setWorkSource(new WorkSource(uid));
+ mDexoptWakeLock.acquire(WAKELOCK_TIMEOUT_MS);
+ return SystemClock.elapsedRealtime();
+ }
+
+ @GuardedBy("mInstallLock")
+ private void releaseWakeLockLI(final long acquireTime) {
+ if (acquireTime < 0) {
+ return;
+ }
+ try {
+ if (mDexoptWakeLock.isHeld()) {
+ mDexoptWakeLock.release();
+ }
+ final long duration = SystemClock.elapsedRealtime() - acquireTime;
+ if (duration >= WAKELOCK_TIMEOUT_MS) {
+ Slog.wtf(TAG, "WakeLock " + mDexoptWakeLock.getTag()
+ + " time out. Operation took " + duration + " ms. Thread: "
+ + Thread.currentThread().getName());
}
+ } catch (Exception e) {
+ Slog.wtf(TAG, "Error while releasing " + mDexoptWakeLock.getTag() + " lock", e);
}
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 2686fcb866c1..cfcd0a51a328 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -444,7 +444,7 @@ public class PackageManagerService extends IPackageManager.Stub
* minute but we sometimes do very lengthy I/O operations on this thread,
* such as installing multi-gigabyte applications, so ours needs to be longer.
*/
- private static final long WATCHDOG_TIMEOUT = 1000*60*10; // ten minutes
+ static final long WATCHDOG_TIMEOUT = 1000*60*10; // ten minutes
/**
* Wall-clock timeout (in milliseconds) after which we *require* that an fstrim
diff --git a/services/core/java/com/android/server/pm/dex/DexManager.java b/services/core/java/com/android/server/pm/dex/DexManager.java
index 3d7cedce522a..9b44646efc0a 100644
--- a/services/core/java/com/android/server/pm/dex/DexManager.java
+++ b/services/core/java/com/android/server/pm/dex/DexManager.java
@@ -60,6 +60,7 @@ public class DexManager {
// Maps package name to code locations.
// It caches the code locations for the installed packages. This allows for
// faster lookups (no locks) when finding what package owns the dex file.
+ @GuardedBy("mPackageCodeLocationsCache")
private final Map<String, PackageCodeLocations> mPackageCodeLocationsCache;
// PackageDexUsage handles the actual I/O operations. It is responsible to
@@ -204,7 +205,7 @@ public class DexManager {
// In case there was an update, write the package use info to disk async.
// Note that we do the writing here and not in PackageDexUsage in order to be
// consistent with other methods in DexManager (e.g. reconcileSecondaryDexFiles performs
- // multiple updates in PackaeDexUsage before writing it).
+ // multiple updates in PackageDexUsage before writing it).
if (mPackageDexUsage.clearUsedByOtherApps(packageName)) {
mPackageDexUsage.maybeWriteAsync();
}
@@ -224,7 +225,7 @@ public class DexManager {
// In case there was an update, write the package use info to disk async.
// Note that we do the writing here and not in PackageDexUsage in order to be
// consistent with other methods in DexManager (e.g. reconcileSecondaryDexFiles performs
- // multiple updates in PackaeDexUsage before writing it).
+ // multiple updates in PackageDexUsage before writing it).
if (updated) {
mPackageDexUsage.maybeWriteAsync();
}
@@ -243,17 +244,22 @@ public class DexManager {
private void cachePackageCodeLocation(String packageName, String baseCodePath,
String[] splitCodePaths, String[] dataDirs, int userId) {
- PackageCodeLocations pcl = putIfAbsent(mPackageCodeLocationsCache, packageName,
- new PackageCodeLocations(packageName, baseCodePath, splitCodePaths));
- pcl.updateCodeLocation(baseCodePath, splitCodePaths);
- if (dataDirs != null) {
- for (String dataDir : dataDirs) {
- // The set of data dirs includes deviceProtectedDataDir and
- // credentialProtectedDataDir which might be null for shared
- // libraries. Currently we don't track these but be lenient
- // and check in case we ever decide to store their usage data.
- if (dataDir != null) {
- pcl.mergeAppDataDirs(dataDir, userId);
+ synchronized (mPackageCodeLocationsCache) {
+ PackageCodeLocations pcl = putIfAbsent(mPackageCodeLocationsCache, packageName,
+ new PackageCodeLocations(packageName, baseCodePath, splitCodePaths));
+ // TODO(calin): We are forced to extend the scope of this synchronization because
+ // the values of the cache (PackageCodeLocations) are updated in place.
+ // Make PackageCodeLocations immutable to simplify the synchronization reasoning.
+ pcl.updateCodeLocation(baseCodePath, splitCodePaths);
+ if (dataDirs != null) {
+ for (String dataDir : dataDirs) {
+ // The set of data dirs includes deviceProtectedDataDir and
+ // credentialProtectedDataDir which might be null for shared
+ // libraries. Currently we don't track these but be lenient
+ // and check in case we ever decide to store their usage data.
+ if (dataDir != null) {
+ pcl.mergeAppDataDirs(dataDir, userId);
+ }
}
}
}
@@ -479,10 +485,12 @@ public class DexManager {
// The loadingPackage does not own the dex file.
// Perform a reverse look-up in the cache to detect if any package has ownership.
// Note that we can have false negatives if the cache falls out of date.
- for (PackageCodeLocations pcl : mPackageCodeLocationsCache.values()) {
- outcome = pcl.searchDex(dexPath, userId);
- if (outcome != DEX_SEARCH_NOT_FOUND) {
- return new DexSearchResult(pcl.mPackageName, outcome);
+ synchronized (mPackageCodeLocationsCache) {
+ for (PackageCodeLocations pcl : mPackageCodeLocationsCache.values()) {
+ outcome = pcl.searchDex(dexPath, userId);
+ if (outcome != DEX_SEARCH_NOT_FOUND) {
+ return new DexSearchResult(pcl.mPackageName, outcome);
+ }
}
}
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 7e03d80d33a6..f0ae1a735443 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -184,6 +184,7 @@ import android.provider.Settings;
import android.service.dreams.DreamManagerInternal;
import android.service.dreams.DreamService;
import android.service.dreams.IDreamManager;
+import android.service.vr.IPersistentVrStateCallbacks;
import android.speech.RecognizerIntent;
import android.telecom.TelecomManager;
import android.util.DisplayMetrics;
@@ -512,6 +513,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
volatile boolean mGoingToSleep;
volatile boolean mRecentsVisible;
volatile boolean mPictureInPictureVisible;
+ // Written by vr manager thread, only read in this class.
+ volatile private boolean mPersistentVrModeEnabled;
volatile private boolean mDismissImeOnBackKeyPressed;
// Used to hold the last user key used to wake the device. This helps us prevent up events
@@ -581,6 +584,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
boolean mTranslucentDecorEnabled = true;
boolean mUseTvRouting;
+ private boolean mHandleVolumeKeysInWM;
+
int mPointerLocationMode = 0; // guarded by mLock
// The last window we were told about in focusChanged.
@@ -777,6 +782,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
private boolean mBugreportTvKey2Pressed;
private boolean mBugreportTvScheduled;
+ private boolean mAccessibilityTvKey1Pressed;
+ private boolean mAccessibilityTvKey2Pressed;
+ private boolean mAccessibilityTvScheduled;
+
/* The number of steps between min and max brightness */
private static final int BRIGHTNESS_STEPS = 10;
@@ -821,6 +830,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
private static final int MSG_BACK_DELAYED_PRESS = 20;
private static final int MSG_ACCESSIBILITY_SHORTCUT = 21;
private static final int MSG_BUGREPORT_TV = 22;
+ private static final int MSG_ACCESSIBILITY_TV = 23;
private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS = 0;
private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_NAVIGATION = 1;
@@ -902,6 +912,11 @@ public class PhoneWindowManager implements WindowManagerPolicy {
case MSG_BUGREPORT_TV:
takeBugreport();
break;
+ case MSG_ACCESSIBILITY_TV:
+ if (mAccessibilityShortcutController.isAccessibilityShortcutAvailable(false)) {
+ accessibilityShortcutActivated();
+ }
+ break;
}
}
}
@@ -1002,6 +1017,14 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
MyOrientationListener mOrientationListener;
+ final IPersistentVrStateCallbacks mPersistentVrModeListener =
+ new IPersistentVrStateCallbacks.Stub() {
+ @Override
+ public void onPersistentVrStateChanged(boolean enabled) {
+ mPersistentVrModeEnabled = enabled;
+ }
+ };
+
private final StatusBarController mStatusBarController = new StatusBarController();
private final BarController mNavigationBarController = new BarController("NavigationBar",
@@ -1917,6 +1940,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mUseTvRouting = AudioSystem.getPlatformType(mContext) == AudioSystem.PLATFORM_TELEVISION;
+ mHandleVolumeKeysInWM = mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_handleVolumeKeysInWindowManager);
+
readConfigurationDependentBehaviors();
mAccessibilityManager = (AccessibilityManager) context.getSystemService(
@@ -3308,6 +3334,11 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (!down) {
cancelPreloadRecentApps();
+ if (mHasFeatureLeanback) {
+ // Clear flags
+ mAccessibilityTvKey2Pressed = down;
+ }
+
mHomePressed = false;
if (mHomeConsumed) {
mHomeConsumed = false;
@@ -3362,6 +3393,13 @@ public class PhoneWindowManager implements WindowManagerPolicy {
preloadRecentApps();
}
} else if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) {
+ if (mHasFeatureLeanback) {
+ mAccessibilityTvKey2Pressed = down;
+ if (interceptAccessibilityGestureTv()) {
+ return -1;
+ }
+ }
+
if (!keyguardOn) {
handleLongPressOnHome(event.getDeviceId());
}
@@ -3511,16 +3549,28 @@ public class PhoneWindowManager implements WindowManagerPolicy {
} else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP
|| keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
|| keyCode == KeyEvent.KEYCODE_VOLUME_MUTE) {
- if (mUseTvRouting) {
- // On TVs volume keys never go to the foreground app.
+ if (mUseTvRouting || mHandleVolumeKeysInWM) {
+ // On TVs or when the configuration is enabled, volume keys never
+ // go to the foreground app.
dispatchDirectAudioEvent(event);
return -1;
}
+
+ // If the device is in Vr mode, drop the volume keys and don't
+ // forward it to the application/dispatch the audio event.
+ if (mPersistentVrModeEnabled) {
+ return -1;
+ }
} else if (keyCode == KeyEvent.KEYCODE_TAB && event.isMetaPressed()) {
// Pass through keyboard navigation keys.
return 0;
} else if (mHasFeatureLeanback && interceptBugreportGestureTv(keyCode, down)) {
return -1;
+ } else if (mHasFeatureLeanback && keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
+ mAccessibilityTvKey1Pressed = down;
+ if (interceptAccessibilityGestureTv()) {
+ return -1;
+ }
}
// Toggle Caps Lock on META-ALT.
@@ -3739,6 +3789,25 @@ public class PhoneWindowManager implements WindowManagerPolicy {
return mBugreportTvScheduled;
}
+ /**
+ * TV only: recognizes a remote control gesture as Accessibility shortcut.
+ * Shortcut: Long press (HOME + DPAD_CENTER)
+ */
+ private boolean interceptAccessibilityGestureTv() {
+ if (mAccessibilityTvKey1Pressed && mAccessibilityTvKey2Pressed) {
+ if (!mAccessibilityTvScheduled) {
+ mAccessibilityTvScheduled = true;
+ Message msg = Message.obtain(mHandler, MSG_ACCESSIBILITY_TV);
+ msg.setAsynchronous(true);
+ mHandler.sendMessage(msg);
+ }
+ } else if (mAccessibilityTvScheduled) {
+ mHandler.removeMessages(MSG_ACCESSIBILITY_TV);
+ mAccessibilityTvScheduled = false;
+ }
+ return mAccessibilityTvScheduled;
+ }
+
private void takeBugreport() {
if ("1".equals(SystemProperties.get("ro.debuggable"))
|| Settings.Global.getInt(mContext.getContentResolver(),
@@ -5900,8 +5969,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
}
}
- if (mUseTvRouting) {
- // On TVs, defer special key handlings to
+ if (mUseTvRouting || mHandleVolumeKeysInWM) {
+ // Defer special key handlings to
// {@link interceptKeyBeforeDispatching()}.
result |= ACTION_PASS_TO_USER;
} else if ((result & ACTION_PASS_TO_USER) == 0) {
@@ -6909,7 +6978,13 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|| mAllowAllRotations == 1
|| orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
|| orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER) {
- preferredRotation = sensorRotation;
+ // In VrMode, we report the sensor as always being in default orientation so:
+ // 1) The orientation doesn't change as the user moves their head.
+ // 2) 2D apps within VR show in the device's default orientation.
+ // This only overwrites the sensor-provided orientation and does not affect any
+ // explicit orientation preferences specified by any activities.
+ preferredRotation =
+ mPersistentVrModeEnabled ? Surface.ROTATION_0 : sensorRotation;
} else {
preferredRotation = lastRotation;
}
@@ -7083,6 +7158,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mKeyguardDelegate.onSystemReady();
mVrManagerInternal = LocalServices.getService(VrManagerInternal.class);
+ if (mVrManagerInternal != null) {
+ mVrManagerInternal.addPersistentVrModeStateListener(mPersistentVrModeListener);
+ }
readCameraLensCoverState();
updateUiMode();
@@ -8215,6 +8293,14 @@ public class PhoneWindowManager implements WindowManagerPolicy {
pw.print(prefix); pw.print("mDemoHdmiRotation="); pw.print(mDemoHdmiRotation);
pw.print(" mDemoHdmiRotationLock="); pw.println(mDemoHdmiRotationLock);
pw.print(prefix); pw.print("mUndockedHdmiRotation="); pw.println(mUndockedHdmiRotation);
+ if (mHasFeatureLeanback) {
+ pw.print(prefix);
+ pw.print("mAccessibilityTvKey1Pressed="); pw.println(mAccessibilityTvKey1Pressed);
+ pw.print(prefix);
+ pw.print("mAccessibilityTvKey2Pressed="); pw.println(mAccessibilityTvKey2Pressed);
+ pw.print(prefix);
+ pw.print("mAccessibilityTvScheduled="); pw.println(mAccessibilityTvScheduled);
+ }
mGlobalKeyManager.dump(prefix, pw);
mStatusBarController.dump(pw, prefix);
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index f4f7e2403f0c..8e06a51238ee 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -325,8 +325,6 @@ public class TrustManagerService extends SystemService {
agentInfo.label = resolveInfo.loadLabel(pm);
agentInfo.icon = resolveInfo.loadIcon(pm);
agentInfo.settings = getSettingsAttrs(pm, resolveInfo);
- agentInfo.agent = new TrustAgentWrapper(mContext, this,
- new Intent().setComponent(name), userInfo.getUserHandle());
} else {
int index = mActiveAgents.indexOf(agentInfo);
agentInfo = mActiveAgents.valueAt(index);
@@ -363,6 +361,11 @@ public class TrustManagerService extends SystemService {
}
}
+ if (agentInfo.agent == null) {
+ agentInfo.agent = new TrustAgentWrapper(mContext, this,
+ new Intent().setComponent(name), userInfo.getUserHandle());
+ }
+
if (!mActiveAgents.contains(agentInfo)) {
mActiveAgents.add(agentInfo);
} else {
diff --git a/services/core/java/com/android/server/twilight/TwilightState.java b/services/core/java/com/android/server/twilight/TwilightState.java
index a12965df11c0..30a8cccb6ad5 100644
--- a/services/core/java/com/android/server/twilight/TwilightState.java
+++ b/services/core/java/com/android/server/twilight/TwilightState.java
@@ -31,7 +31,7 @@ public final class TwilightState {
private final long mSunriseTimeMillis;
private final long mSunsetTimeMillis;
- TwilightState(long sunriseTimeMillis, long sunsetTimeMillis) {
+ public TwilightState(long sunriseTimeMillis, long sunsetTimeMillis) {
mSunriseTimeMillis = sunriseTimeMillis;
mSunsetTimeMillis = sunsetTimeMillis;
}
diff --git a/services/core/java/com/android/server/vr/VrManagerInternal.java b/services/core/java/com/android/server/vr/VrManagerInternal.java
index 63c61955bcd7..1f7564027166 100644
--- a/services/core/java/com/android/server/vr/VrManagerInternal.java
+++ b/services/core/java/com/android/server/vr/VrManagerInternal.java
@@ -16,7 +16,7 @@
package com.android.server.vr;
import android.annotation.NonNull;
-import android.app.CompatibilityDisplayProperties;
+import android.app.Vr2dDisplayProperties;
import android.content.ComponentName;
import android.service.vr.IPersistentVrStateCallbacks;
@@ -83,16 +83,16 @@ public abstract class VrManagerInternal {
public abstract int hasVrPackage(@NonNull ComponentName packageName, int userId);
/**
- * Sets the resolution and DPI of the compatibility virtual display used to display
+ * Sets the resolution and DPI of the vr2d virtual display used to display
* 2D applications in VR mode.
*
* <p>Requires {@link android.Manifest.permission#ACCESS_VR_MANAGER} permission.</p>
*
- * @param compatDisplayProp Properties of the virtual display for 2D applications
+ * @param vr2dDisplayProp Properties of the virtual display for 2D applications
* in VR mode.
*/
- public abstract void setCompatibilityDisplayProperties(
- CompatibilityDisplayProperties compatDisplayProp);
+ public abstract void setVr2dDisplayProperties(
+ Vr2dDisplayProperties vr2dDisplayProp);
/**
* Sets the persistent VR mode state of a device. When a device is in persistent VR mode it will
@@ -110,7 +110,7 @@ public abstract class VrManagerInternal {
* @return {@link android.view.Display.INVALID_DISPLAY} if there is no virtual display
* currently, else return the display id of the virtual display
*/
- public abstract int getCompatibilityDisplayId();
+ public abstract int getVr2dDisplayId();
/**
* Adds listener that reports state changes to persistent VR mode.
diff --git a/services/core/java/com/android/server/vr/VrManagerService.java b/services/core/java/com/android/server/vr/VrManagerService.java
index 860b2419327a..0e183f0a50b8 100644
--- a/services/core/java/com/android/server/vr/VrManagerService.java
+++ b/services/core/java/com/android/server/vr/VrManagerService.java
@@ -21,7 +21,7 @@ import android.Manifest;
import android.app.ActivityManagerInternal;
import android.app.ActivityManager;
import android.app.AppOpsManager;
-import android.app.CompatibilityDisplayProperties;
+import android.app.Vr2dDisplayProperties;
import android.app.NotificationManager;
import android.annotation.NonNull;
import android.content.ComponentName;
@@ -141,7 +141,7 @@ public class VrManagerService extends SystemService implements EnabledComponentC
private final NotificationAccessManager mNotifAccessManager = new NotificationAccessManager();
/** Tracks the state of the screen and keyguard UI.*/
private int mSystemSleepFlags = FLAG_AWAKE;
- private CompatibilityDisplay mCompatibilityDisplay;
+ private Vr2dDisplay mVr2dDisplay;
private static final int MSG_VR_STATE_CHANGE = 0;
private static final int MSG_PENDING_VR_STATE_CHANGE = 1;
@@ -428,15 +428,15 @@ public class VrManagerService extends SystemService implements EnabledComponentC
}
@Override
- public void setCompatibilityDisplayProperties(
- CompatibilityDisplayProperties compatDisplayProp) {
+ public void setVr2dDisplayProperties(
+ Vr2dDisplayProperties vr2dDisplayProp) {
enforceCallerPermission(Manifest.permission.RESTRICTED_VR_ACCESS);
- VrManagerService.this.setCompatibilityDisplayProperties(compatDisplayProp);
+ VrManagerService.this.setVr2dDisplayProperties(vr2dDisplayProp);
}
@Override
- public int getCompatibilityDisplayId() {
- return VrManagerService.this.getCompatibilityDisplayId();
+ public int getVr2dDisplayId() {
+ return VrManagerService.this.getVr2dDisplayId();
}
@Override
@@ -549,14 +549,14 @@ public class VrManagerService extends SystemService implements EnabledComponentC
}
@Override
- public void setCompatibilityDisplayProperties(
- CompatibilityDisplayProperties compatDisplayProp) {
- VrManagerService.this.setCompatibilityDisplayProperties(compatDisplayProp);
+ public void setVr2dDisplayProperties(
+ Vr2dDisplayProperties compatDisplayProp) {
+ VrManagerService.this.setVr2dDisplayProperties(compatDisplayProp);
}
@Override
- public int getCompatibilityDisplayId() {
- return VrManagerService.this.getCompatibilityDisplayId();
+ public int getVr2dDisplayId() {
+ return VrManagerService.this.getVr2dDisplayId();
}
@Override
@@ -608,8 +608,8 @@ public class VrManagerService extends SystemService implements EnabledComponentC
DisplayManager dm =
(DisplayManager) getContext().getSystemService(Context.DISPLAY_SERVICE);
ActivityManagerInternal ami = LocalServices.getService(ActivityManagerInternal.class);
- mCompatibilityDisplay = new CompatibilityDisplay(dm, ami, mVrManager);
- mCompatibilityDisplay.init(getContext());
+ mVr2dDisplay = new Vr2dDisplay(dm, ami, mVrManager);
+ mVr2dDisplay.init(getContext());
} else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
synchronized (mLock) {
mVrModeAllowed = true;
@@ -1116,20 +1116,20 @@ public class VrManagerService extends SystemService implements EnabledComponentC
}
}
- public void setCompatibilityDisplayProperties(
- CompatibilityDisplayProperties compatDisplayProp) {
- if (mCompatibilityDisplay != null) {
- mCompatibilityDisplay.setVirtualDisplayProperties(compatDisplayProp);
+ public void setVr2dDisplayProperties(
+ Vr2dDisplayProperties compatDisplayProp) {
+ if (mVr2dDisplay != null) {
+ mVr2dDisplay.setVirtualDisplayProperties(compatDisplayProp);
return;
}
- Slog.w(TAG, "CompatibilityDisplay is null!");
+ Slog.w(TAG, "Vr2dDisplay is null!");
}
- private int getCompatibilityDisplayId() {
- if (mCompatibilityDisplay != null) {
- return mCompatibilityDisplay.getVirtualDisplayId();
+ private int getVr2dDisplayId() {
+ if (mVr2dDisplay != null) {
+ return mVr2dDisplay.getVirtualDisplayId();
}
- Slog.w(TAG, "CompatibilityDisplay is null!");
+ Slog.w(TAG, "Vr2dDisplay is null!");
return INVALID_DISPLAY;
}
diff --git a/services/core/java/com/android/server/wm/AppWindowContainerController.java b/services/core/java/com/android/server/wm/AppWindowContainerController.java
index c625cbea1fa4..b5e194b4b93b 100644
--- a/services/core/java/com/android/server/wm/AppWindowContainerController.java
+++ b/services/core/java/com/android/server/wm/AppWindowContainerController.java
@@ -36,7 +36,6 @@ import android.graphics.Rect;
import android.os.Debug;
import android.os.Handler;
import android.os.IBinder;
-import android.os.Looper;
import android.os.Trace;
import android.util.Slog;
import android.view.IApplicationToken;
@@ -319,7 +318,7 @@ public class AppWindowContainerController
+ " token: " + mToken);
return;
}
- mContainer.setDisablePreviewSnapshots(disable);
+ mContainer.setDisablePreviewScreenshots(disable);
}
}
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 36418bea1940..640bac28efdf 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -23,6 +23,7 @@ import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
+import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
@@ -48,6 +49,7 @@ import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE
import static com.android.server.wm.WindowManagerService.logWithStack;
import android.annotation.NonNull;
+import android.app.Activity;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.Binder;
@@ -1528,12 +1530,24 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
return candidate;
}
- void setDisablePreviewSnapshots(boolean disable) {
+ /**
+ * See {@link Activity#setDisablePreviewScreenshots}.
+ */
+ void setDisablePreviewScreenshots(boolean disable) {
mDisbalePreviewScreenshots = disable;
}
- boolean shouldDisablePreviewScreenshots() {
- return mDisbalePreviewScreenshots;
+ /**
+ * Retrieves whether we'd like to generate a snapshot that's based solely on the theme. This is
+ * the case when preview screenshots are disabled {@link #setDisablePreviewScreenshots} or when
+ * we can't take a snapshot for other reasons, for example, if we have a secure window.
+ *
+ * @return True if we need to generate an app theme snapshot, false if we'd like to take a real
+ * screenshot.
+ */
+ boolean shouldUseAppThemeSnapshot() {
+ return mDisbalePreviewScreenshots || forAllWindows(w -> (w.mAttrs.flags & FLAG_SECURE) != 0,
+ true /* topToBottom */);
}
@Override
diff --git a/services/core/java/com/android/server/wm/DimLayerController.java b/services/core/java/com/android/server/wm/DimLayerController.java
index 410044633215..d44cd13f8ed5 100644
--- a/services/core/java/com/android/server/wm/DimLayerController.java
+++ b/services/core/java/com/android/server/wm/DimLayerController.java
@@ -188,6 +188,7 @@ class DimLayerController {
boolean animateDimLayers() {
int fullScreen = -1;
int fullScreenAndDimming = -1;
+ int topFullScreenUserLayer = 0;
boolean result = false;
for (int i = mState.size() - 1; i >= 0; i--) {
@@ -213,8 +214,18 @@ class DimLayerController {
// and we have to make sure we always animate the layer.
if (user.dimFullscreen() && state.dimLayer == mSharedFullScreenDimLayer) {
fullScreen = i;
- if (mState.valueAt(i).continueDimming) {
+ if (!state.continueDimming) {
+ continue;
+ }
+
+ // When choosing which user to assign the shared fullscreen layer to
+ // we need to look at Z-order.
+ if (topFullScreenUserLayer == 0 ||
+ (state.animator != null && state.animator.mAnimLayer > topFullScreenUserLayer)) {
fullScreenAndDimming = i;
+ if (state.animator != null) {
+ topFullScreenUserLayer = state.animator.mAnimLayer;
+ }
}
} else {
// We always want to animate the non fullscreen windows, they don't share their
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index fbb826d5cb48..b79173cf77e5 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -31,11 +31,13 @@ import android.graphics.GraphicBuffer;
import android.graphics.Rect;
import android.os.Environment;
import android.util.ArraySet;
+import android.view.WindowManager.LayoutParams;
import android.view.WindowManagerPolicy.StartingSurface;
import com.google.android.collect.Sets;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.wm.TaskSnapshotSurface.SystemBarBackgroundPainter;
import java.io.PrintWriter;
@@ -206,7 +208,7 @@ class TaskSnapshotController {
final AppWindowToken topChild = task.getTopChild();
if (StackId.isHomeOrRecentsStack(task.mStack.mStackId)) {
return SNAPSHOT_MODE_NONE;
- } else if (topChild != null && topChild.shouldDisablePreviewScreenshots()) {
+ } else if (topChild != null && topChild.shouldUseAppThemeSnapshot()) {
return SNAPSHOT_MODE_APP_THEME;
} else {
return SNAPSHOT_MODE_REAL;
@@ -227,6 +229,8 @@ class TaskSnapshotController {
return null;
}
final int color = task.getTaskDescription().getBackgroundColor();
+ final int statusBarColor = task.getTaskDescription().getStatusBarColor();
+ final int navigationBarColor = task.getTaskDescription().getNavigationBarColor();
final GraphicBuffer buffer = GraphicBuffer.create(mainWindow.getFrameLw().width(),
mainWindow.getFrameLw().height(),
RGBA_8888, USAGE_HW_TEXTURE | USAGE_SW_WRITE_RARELY | USAGE_SW_READ_NEVER);
@@ -235,6 +239,11 @@ class TaskSnapshotController {
}
final Canvas c = buffer.lockCanvas();
c.drawColor(color);
+ final LayoutParams attrs = mainWindow.getAttrs();
+ final SystemBarBackgroundPainter decorPainter = new SystemBarBackgroundPainter(attrs.flags,
+ attrs.privateFlags, attrs.systemUiVisibility, statusBarColor, navigationBarColor);
+ decorPainter.setInsets(mainWindow.mContentInsets, mainWindow.mStableInsets);
+ decorPainter.drawDecors(c, null /* statusBarExcludeFrame */);
buffer.unlockCanvasAndPost(c);
return new TaskSnapshot(buffer, topChild.getConfiguration().orientation,
mainWindow.mStableInsets, false /* reduced */, 1.0f /* scale */);
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
index f2a92df2b820..e5c7a72c78bc 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
@@ -24,6 +24,7 @@ import android.annotation.TestApi;
import android.app.ActivityManager.TaskSnapshot;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
+import android.graphics.Bitmap.Config;
import android.os.Process;
import android.os.SystemClock;
import android.util.ArraySet;
@@ -266,12 +267,13 @@ class TaskSnapshotPersister {
final File file = getBitmapFile(mTaskId, mUserId);
final File reducedFile = getReducedResolutionBitmapFile(mTaskId, mUserId);
final Bitmap bitmap = Bitmap.createHardwareBitmap(mSnapshot.getSnapshot());
- final Bitmap reduced = Bitmap.createScaledBitmap(bitmap,
+ final Bitmap swBitmap = bitmap.copy(Config.ARGB_8888, false /* isMutable */);
+ final Bitmap reduced = Bitmap.createScaledBitmap(swBitmap,
(int) (bitmap.getWidth() * REDUCED_SCALE),
(int) (bitmap.getHeight() * REDUCED_SCALE), true /* filter */);
try {
FileOutputStream fos = new FileOutputStream(file);
- bitmap.compress(JPEG, QUALITY, fos);
+ swBitmap.compress(JPEG, QUALITY, fos);
fos.close();
FileOutputStream reducedFos = new FileOutputStream(reducedFile);
reduced.compress(JPEG, QUALITY, reducedFos);
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
index c816ba3fa796..2b9e800fd854 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
@@ -42,8 +42,11 @@ import static com.android.internal.policy.DecorView.getNavigationBarRect;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+import android.annotation.Nullable;
import android.app.ActivityManager.TaskDescription;
import android.app.ActivityManager.TaskSnapshot;
+import android.app.ActivityThread;
+import android.content.Context;
import android.graphics.Canvas;
import android.graphics.GraphicBuffer;
import android.graphics.Paint;
@@ -118,13 +121,8 @@ class TaskSnapshotSurface implements StartingSurface {
private final Handler mHandler;
private boolean mSizeMismatch;
private final Paint mBackgroundPaint = new Paint();
- private final Paint mStatusBarPaint = new Paint();
- private final Paint mNavigationBarPaint = new Paint();
private final int mStatusBarColor;
- private final int mNavigationBarColor;
- private final int mSysUiVis;
- private final int mWindowFlags;
- private final int mWindowPrivateFlags;
+ @VisibleForTesting final SystemBarBackgroundPainter mSystemBarBackgroundPainter;
static TaskSnapshotSurface create(WindowManagerService service, AppWindowToken token,
TaskSnapshot snapshot) {
@@ -224,15 +222,9 @@ class TaskSnapshotSurface implements StartingSurface {
mTitle = title;
mBackgroundPaint.setColor(backgroundColor != 0 ? backgroundColor : WHITE);
mTaskBounds = taskBounds;
- mSysUiVis = sysUiVis;
- mWindowFlags = windowFlags;
- mWindowPrivateFlags = windowPrivateFlags;
- mStatusBarColor = DecorView.calculateStatusBarColor(windowFlags,
- service.mContext.getColor(R.color.system_bar_background_semi_transparent),
- statusBarColor);
- mNavigationBarColor = navigationBarColor;
- mStatusBarPaint.setColor(mStatusBarColor);
- mNavigationBarPaint.setColor(navigationBarColor);
+ mSystemBarBackgroundPainter = new SystemBarBackgroundPainter(windowFlags,
+ windowPrivateFlags, sysUiVis, statusBarColor, navigationBarColor);
+ mStatusBarColor = statusBarColor;
}
@Override
@@ -258,6 +250,7 @@ class TaskSnapshotSurface implements StartingSurface {
mStableInsets.set(stableInsets);
mSizeMismatch = (mFrame.width() != mSnapshot.getSnapshot().getWidth()
|| mFrame.height() != mSnapshot.getSnapshot().getHeight());
+ mSystemBarBackgroundPainter.setInsets(contentInsets, stableInsets);
}
private void drawSnapshot() {
@@ -346,7 +339,7 @@ class TaskSnapshotSurface implements StartingSurface {
@VisibleForTesting
void drawBackgroundAndBars(Canvas c, Rect frame) {
- final int statusBarHeight = getStatusBarColorViewHeight();
+ final int statusBarHeight = mSystemBarBackgroundPainter.getStatusBarColorViewHeight();
final boolean fillHorizontally = c.getWidth() > frame.right;
final boolean fillVertically = c.getHeight() > frame.bottom;
if (fillHorizontally) {
@@ -359,44 +352,7 @@ class TaskSnapshotSurface implements StartingSurface {
if (fillVertically) {
c.drawRect(0, frame.bottom, c.getWidth(), c.getHeight(), mBackgroundPaint);
}
- drawStatusBarBackground(c, frame, statusBarHeight);
- drawNavigationBarBackground(c);
- }
-
- private int getStatusBarColorViewHeight() {
- final boolean forceStatusBarBackground =
- (mWindowPrivateFlags & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) != 0;
- if (STATUS_BAR_COLOR_VIEW_ATTRIBUTES.isVisible(
- mSysUiVis, mStatusBarColor, mWindowFlags, forceStatusBarBackground)) {
- return getColorViewTopInset(mStableInsets.top, mContentInsets.top);
- } else {
- return 0;
- }
- }
-
- private boolean isNavigationBarColorViewVisible() {
- return NAVIGATION_BAR_COLOR_VIEW_ATTRIBUTES.isVisible(
- mSysUiVis, mNavigationBarColor, mWindowFlags, false /* force */);
- }
-
- @VisibleForTesting
- void drawStatusBarBackground(Canvas c, Rect frame, int statusBarHeight) {
- if (statusBarHeight > 0 && c.getWidth() > frame.right) {
- final int rightInset = DecorView.getColorViewRightInset(mStableInsets.right,
- mContentInsets.right);
- c.drawRect(frame.right, 0, c.getWidth() - rightInset, statusBarHeight, mStatusBarPaint);
- }
- }
-
- @VisibleForTesting
- void drawNavigationBarBackground(Canvas c) {
- final Rect navigationBarRect = new Rect();
- getNavigationBarRect(c.getWidth(), c.getHeight(), mStableInsets, mContentInsets,
- navigationBarRect);
- final boolean visible = isNavigationBarColorViewVisible();
- if (visible && !navigationBarRect.isEmpty()) {
- c.drawRect(navigationBarRect, mNavigationBarPaint);
- }
+ mSystemBarBackgroundPainter.drawDecors(c, frame);
}
private void reportDrawn() {
@@ -450,4 +406,84 @@ class TaskSnapshotSurface implements StartingSurface {
}
}
}
+
+ /**
+ * Helper class to draw the background of the system bars in regions the task snapshot isn't
+ * filling the window.
+ */
+ static class SystemBarBackgroundPainter {
+
+ private final Rect mContentInsets = new Rect();
+ private final Rect mStableInsets = new Rect();
+ private final Paint mStatusBarPaint = new Paint();
+ private final Paint mNavigationBarPaint = new Paint();
+ private final int mStatusBarColor;
+ private final int mNavigationBarColor;
+ private final int mWindowFlags;
+ private final int mWindowPrivateFlags;
+ private final int mSysUiVis;
+
+ SystemBarBackgroundPainter( int windowFlags, int windowPrivateFlags, int sysUiVis,
+ int statusBarColor, int navigationBarColor) {
+ mWindowFlags = windowFlags;
+ mWindowPrivateFlags = windowPrivateFlags;
+ mSysUiVis = sysUiVis;
+ final Context context = ActivityThread.currentActivityThread().getSystemUiContext();
+ mStatusBarColor = DecorView.calculateStatusBarColor(windowFlags,
+ context.getColor(R.color.system_bar_background_semi_transparent),
+ statusBarColor);
+ mNavigationBarColor = navigationBarColor;
+ mStatusBarPaint.setColor(mStatusBarColor);
+ mNavigationBarPaint.setColor(navigationBarColor);
+ }
+
+ void setInsets(Rect contentInsets, Rect stableInsets) {
+ mContentInsets.set(contentInsets);
+ mStableInsets.set(stableInsets);
+ }
+
+ int getStatusBarColorViewHeight() {
+ final boolean forceStatusBarBackground =
+ (mWindowPrivateFlags & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) != 0;
+ if (STATUS_BAR_COLOR_VIEW_ATTRIBUTES.isVisible(
+ mSysUiVis, mStatusBarColor, mWindowFlags, forceStatusBarBackground)) {
+ return getColorViewTopInset(mStableInsets.top, mContentInsets.top);
+ } else {
+ return 0;
+ }
+ }
+
+ private boolean isNavigationBarColorViewVisible() {
+ return NAVIGATION_BAR_COLOR_VIEW_ATTRIBUTES.isVisible(
+ mSysUiVis, mNavigationBarColor, mWindowFlags, false /* force */);
+ }
+
+ void drawDecors(Canvas c, @Nullable Rect alreadyDrawnFrame) {
+ drawStatusBarBackground(c, alreadyDrawnFrame, getStatusBarColorViewHeight());
+ drawNavigationBarBackground(c);
+ }
+
+ @VisibleForTesting
+ void drawStatusBarBackground(Canvas c, @Nullable Rect alreadyDrawnFrame,
+ int statusBarHeight) {
+ if (statusBarHeight > 0
+ && (alreadyDrawnFrame == null || c.getWidth() > alreadyDrawnFrame.right)) {
+ final int rightInset = DecorView.getColorViewRightInset(mStableInsets.right,
+ mContentInsets.right);
+ final int left = alreadyDrawnFrame != null ? alreadyDrawnFrame.right : 0;
+ c.drawRect(left, 0, c.getWidth() - rightInset, statusBarHeight, mStatusBarPaint);
+ }
+ }
+
+ @VisibleForTesting
+ void drawNavigationBarBackground(Canvas c) {
+ final Rect navigationBarRect = new Rect();
+ getNavigationBarRect(c.getWidth(), c.getHeight(), mStableInsets, mContentInsets,
+ navigationBarRect);
+ final boolean visible = isNavigationBarColorViewVisible();
+ if (visible && !navigationBarRect.isEmpty()) {
+ c.drawRect(navigationBarRect, mNavigationBarPaint);
+ }
+ }
+ }
}
diff --git a/services/tests/notification/src/com/android/server/notification/BadgeExtractorTest.java b/services/tests/notification/src/com/android/server/notification/BadgeExtractorTest.java
index 0cf4994ebbce..2e8b0682f53d 100644
--- a/services/tests/notification/src/com/android/server/notification/BadgeExtractorTest.java
+++ b/services/tests/notification/src/com/android/server/notification/BadgeExtractorTest.java
@@ -69,7 +69,7 @@ public class BadgeExtractorTest {
Notification n = builder.build();
StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, mId, mTag, mUid,
mPid, n, mUser, null, System.currentTimeMillis());
- NotificationRecord r = new NotificationRecord(getContext(), sbn, channel);
+ NotificationRecord r = new NotificationRecord(getContext(), sbn, channel, true);
return r;
}
diff --git a/services/tests/notification/src/com/android/server/notification/BuzzBeepBlinkTest.java b/services/tests/notification/src/com/android/server/notification/BuzzBeepBlinkTest.java
index d4904f5aecf7..5e8b3d43682b 100644
--- a/services/tests/notification/src/com/android/server/notification/BuzzBeepBlinkTest.java
+++ b/services/tests/notification/src/com/android/server/notification/BuzzBeepBlinkTest.java
@@ -259,7 +259,7 @@ public class BuzzBeepBlinkTest {
StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, id, mTag, mUid,
mPid, n, mUser, null, System.currentTimeMillis());
- NotificationRecord r = new NotificationRecord(getContext(), sbn, channel);
+ NotificationRecord r = new NotificationRecord(getContext(), sbn, channel, true);
mService.addNotification(r);
return r;
}
@@ -769,7 +769,7 @@ public class BuzzBeepBlinkTest {
StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, 0, mTag, mUid,
mPid, n, mUser, null, System.currentTimeMillis());
- NotificationRecord r = new NotificationRecord(getContext(), sbn, channel);
+ NotificationRecord r = new NotificationRecord(getContext(), sbn, channel, true);
mService.addNotification(r);
mService.buzzBeepBlinkLocked(r);
diff --git a/services/tests/notification/src/com/android/server/notification/GlobalSortKeyComparatorTest.java b/services/tests/notification/src/com/android/server/notification/GlobalSortKeyComparatorTest.java
index 24cb72e8b0fb..33d2d079d87e 100644
--- a/services/tests/notification/src/com/android/server/notification/GlobalSortKeyComparatorTest.java
+++ b/services/tests/notification/src/com/android/server/notification/GlobalSortKeyComparatorTest.java
@@ -53,21 +53,21 @@ public class GlobalSortKeyComparatorTest {
new StatusBarNotification(PKG,
PKG, 1, "media", UID, UID, n,
new UserHandle(UserHandle.myUserId()),
- "", 1499), getDefaultChannel());
+ "", 1499), getDefaultChannel(), true);
left.setGlobalSortKey("first");
NotificationRecord right = new NotificationRecord(InstrumentationRegistry.getContext(),
new StatusBarNotification(PKG,
PKG, 1, "media", UID, UID, n,
new UserHandle(UserHandle.myUserId()),
- "", 1499), getDefaultChannel());
+ "", 1499), getDefaultChannel(), true);
right.setGlobalSortKey("second");
NotificationRecord last = new NotificationRecord(InstrumentationRegistry.getContext(),
new StatusBarNotification(PKG,
PKG, 1, "media", UID, UID, n,
new UserHandle(UserHandle.myUserId()),
- "", 1499), getDefaultChannel());
+ "", 1499), getDefaultChannel(), true);
final List<NotificationRecord> expected = new ArrayList<>();
@@ -93,13 +93,13 @@ public class GlobalSortKeyComparatorTest {
new StatusBarNotification(PKG,
PKG, 1, "media", UID, UID, n,
new UserHandle(UserHandle.myUserId()),
- "", 1499), getDefaultChannel());
+ "", 1499), getDefaultChannel(), true);
NotificationRecord right = new NotificationRecord(InstrumentationRegistry.getContext(),
new StatusBarNotification(PKG,
PKG, 1, "media", UID, UID, n,
new UserHandle(UserHandle.myUserId()),
- "", 1499), getDefaultChannel());
+ "", 1499), getDefaultChannel(), true);
right.setGlobalSortKey("not null");
final List<NotificationRecord> expected = new ArrayList<>();
@@ -124,14 +124,14 @@ public class GlobalSortKeyComparatorTest {
new StatusBarNotification(PKG,
PKG, 1, "media", UID, UID, n,
new UserHandle(UserHandle.myUserId()),
- "", 1499), getDefaultChannel());
+ "", 1499), getDefaultChannel(), true);
left.setGlobalSortKey("not null");
NotificationRecord right = new NotificationRecord(InstrumentationRegistry.getContext(),
new StatusBarNotification(PKG,
PKG, 1, "media", UID, UID, n,
new UserHandle(UserHandle.myUserId()),
- "", 1499), getDefaultChannel());
+ "", 1499), getDefaultChannel(), true);
final List<NotificationRecord> expected = new ArrayList<>();
expected.add(left);
diff --git a/services/tests/notification/src/com/android/server/notification/ImportanceExtractorTest.java b/services/tests/notification/src/com/android/server/notification/ImportanceExtractorTest.java
index 3dbd803e0a76..7a2dbaf98692 100644
--- a/services/tests/notification/src/com/android/server/notification/ImportanceExtractorTest.java
+++ b/services/tests/notification/src/com/android/server/notification/ImportanceExtractorTest.java
@@ -71,7 +71,7 @@ public class ImportanceExtractorTest {
Notification n = builder.build();
StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, mId, mTag, mUid,
mPid, n, mUser, null, System.currentTimeMillis());
- NotificationRecord r = new NotificationRecord(getContext(), sbn, channel);
+ NotificationRecord r = new NotificationRecord(getContext(), sbn, channel, true);
return r;
}
diff --git a/services/tests/notification/src/com/android/server/notification/NotificationComparatorTest.java b/services/tests/notification/src/com/android/server/notification/NotificationComparatorTest.java
index 84945ab5acd3..ccd2db0ebf2c 100644
--- a/services/tests/notification/src/com/android/server/notification/NotificationComparatorTest.java
+++ b/services/tests/notification/src/com/android/server/notification/NotificationComparatorTest.java
@@ -108,7 +108,7 @@ public class NotificationComparatorTest {
.build();
mRecordMinCall = new NotificationRecord(mContext, new StatusBarNotification(callPkg,
callPkg, 1, "minCall", callUid, callUid, n1,
- new UserHandle(userId), "", 2000), getDefaultChannel());
+ new UserHandle(userId), "", 2000), getDefaultChannel(), false);
mRecordMinCall.setUserImportance(NotificationManager.IMPORTANCE_MIN);
Notification n2 = new Notification.Builder(mContext, TEST_CHANNEL_ID)
@@ -118,7 +118,7 @@ public class NotificationComparatorTest {
.build();
mRecordHighCall = new NotificationRecord(mContext, new StatusBarNotification(callPkg,
callPkg, 1, "highcall", callUid, callUid, n2,
- new UserHandle(userId), "", 1999), getDefaultChannel());
+ new UserHandle(userId), "", 1999), getDefaultChannel(), false);
mRecordHighCall.setUserImportance(NotificationManager.IMPORTANCE_HIGH);
Notification n3 = new Notification.Builder(mContext, TEST_CHANNEL_ID)
@@ -128,14 +128,14 @@ public class NotificationComparatorTest {
.build();
mRecordDefaultMedia = new NotificationRecord(mContext, new StatusBarNotification(pkg2,
pkg2, 1, "media", uid2, uid2, n3, new UserHandle(userId),
- "", 1499), getDefaultChannel());
+ "", 1499), getDefaultChannel(), false);
mRecordDefaultMedia.setUserImportance(NotificationManager.IMPORTANCE_DEFAULT);
Notification n4 = new Notification.Builder(mContext, TEST_CHANNEL_ID)
.setStyle(new Notification.MessagingStyle("sender!")).build();
mRecordInlineReply = new NotificationRecord(mContext, new StatusBarNotification(pkg2,
pkg2, 1, "inlinereply", uid2, uid2, n4, new UserHandle(userId),
- "", 1599), getDefaultChannel());
+ "", 1599), getDefaultChannel(), false);
mRecordInlineReply.setUserImportance(NotificationManager.IMPORTANCE_HIGH);
mRecordInlineReply.setPackagePriority(Notification.PRIORITY_MAX);
@@ -143,27 +143,27 @@ public class NotificationComparatorTest {
.setCategory(Notification.CATEGORY_MESSAGE).build();
mRecordSms = new NotificationRecord(mContext, new StatusBarNotification(smsPkg,
smsPkg, 1, "sms", smsUid, smsUid, n5, new UserHandle(userId),
- "", 1299), getDefaultChannel());
+ "", 1299), getDefaultChannel(), false);
mRecordSms.setUserImportance(NotificationManager.IMPORTANCE_DEFAULT);
Notification n6 = new Notification.Builder(mContext, TEST_CHANNEL_ID).build();
mRecordStarredContact = new NotificationRecord(mContext, new StatusBarNotification(pkg2,
pkg2, 1, "starred", uid2, uid2, n6, new UserHandle(userId),
- "", 1259), getDefaultChannel());
+ "", 1259), getDefaultChannel(), false);
mRecordStarredContact.setContactAffinity(ValidateNotificationPeople.STARRED_CONTACT);
mRecordStarredContact.setUserImportance(NotificationManager.IMPORTANCE_DEFAULT);
Notification n7 = new Notification.Builder(mContext, TEST_CHANNEL_ID).build();
mRecordContact = new NotificationRecord(mContext, new StatusBarNotification(pkg2,
pkg2, 1, "contact", uid2, uid2, n7, new UserHandle(userId),
- "", 1259), getDefaultChannel());
+ "", 1259), getDefaultChannel(), false);
mRecordContact.setContactAffinity(ValidateNotificationPeople.VALID_CONTACT);
mRecordContact.setUserImportance(NotificationManager.IMPORTANCE_DEFAULT);
Notification n8 = new Notification.Builder(mContext, TEST_CHANNEL_ID).build();
mRecordUrgent = new NotificationRecord(mContext, new StatusBarNotification(pkg2,
pkg2, 1, "urgent", uid2, uid2, n8, new UserHandle(userId),
- "", 1258), getDefaultChannel());
+ "", 1258), getDefaultChannel(), false);
mRecordUrgent.setUserImportance(NotificationManager.IMPORTANCE_HIGH);
Notification n9 = new Notification.Builder(mContext, TEST_CHANNEL_ID)
@@ -173,7 +173,7 @@ public class NotificationComparatorTest {
.build();
mRecordCheater = new NotificationRecord(mContext, new StatusBarNotification(pkg2,
pkg2, 1, "cheater", uid2, uid2, n9, new UserHandle(userId),
- "", 9258), getDefaultChannel());
+ "", 9258), getDefaultChannel(), false);
mRecordCheater.setUserImportance(NotificationManager.IMPORTANCE_LOW);
mRecordCheater.setPackagePriority(Notification.PRIORITY_MAX);
@@ -181,7 +181,7 @@ public class NotificationComparatorTest {
.setStyle(new Notification.InboxStyle().setSummaryText("message!")).build();
mRecordEmail = new NotificationRecord(mContext, new StatusBarNotification(pkg2,
pkg2, 1, "email", uid2, uid2, n10, new UserHandle(userId),
- "", 1599), getDefaultChannel());
+ "", 1599), getDefaultChannel(), false);
mRecordEmail.setUserImportance(NotificationManager.IMPORTANCE_HIGH);
Notification n11 = new Notification.Builder(mContext, TEST_CHANNEL_ID)
@@ -190,7 +190,7 @@ public class NotificationComparatorTest {
.build();
mRecordCheaterColorized = new NotificationRecord(mContext, new StatusBarNotification(pkg2,
pkg2, 1, "cheater", uid2, uid2, n11, new UserHandle(userId),
- "", 9258), getDefaultChannel());
+ "", 9258), getDefaultChannel(), false);
mRecordCheaterColorized.setUserImportance(NotificationManager.IMPORTANCE_LOW);
}
diff --git a/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java
index 177c02d63280..f3eb4f817262 100644
--- a/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -165,7 +165,7 @@ public class NotificationManagerServiceTest {
StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, id, "tag", uid, 0,
nb.build(), new UserHandle(uid), null, 0);
- return new NotificationRecord(mContext, sbn, channel);
+ return new NotificationRecord(mContext, sbn, channel, true);
}
private NotificationRecord generateNotificationRecord(NotificationChannel channel) {
return generateNotificationRecord(channel, null);
@@ -184,7 +184,7 @@ public class NotificationManagerServiceTest {
}
StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, "tag", uid, 0,
nb.build(), new UserHandle(uid), null, 0);
- return new NotificationRecord(mContext, sbn, channel);
+ return new NotificationRecord(mContext, sbn, channel, true);
}
@Test
diff --git a/services/tests/notification/src/com/android/server/notification/NotificationRecordTest.java b/services/tests/notification/src/com/android/server/notification/NotificationRecordTest.java
index 1c8ca84815d3..66f379970d5a 100644
--- a/services/tests/notification/src/com/android/server/notification/NotificationRecordTest.java
+++ b/services/tests/notification/src/com/android/server/notification/NotificationRecordTest.java
@@ -21,7 +21,6 @@ import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.assertTrue;
-import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.when;
@@ -61,6 +60,10 @@ public class NotificationRecordTest {
private final Context mMockContext = Mockito.mock(Context.class);
@Mock PackageManager mPm;
+ // constants for targetSdk version. N is pre channels, O is post.
+ private final boolean N = false;
+ private final boolean O = true;
+
private final String pkg = "com.android.server.notification";
private final int uid = 9583;
private final String pkg2 = "pkg2";
@@ -76,7 +79,6 @@ public class NotificationRecordTest {
new NotificationChannel(NotificationChannel.DEFAULT_CHANNEL_ID, "test",
NotificationManager.IMPORTANCE_UNSPECIFIED);
private android.os.UserHandle mUser = UserHandle.of(ActivityManager.getCurrentUser());
- final ApplicationInfo legacy = new ApplicationInfo();
final ApplicationInfo upgrade = new ApplicationInfo();
private static final long[] CUSTOM_VIBRATION = new long[] {
@@ -100,17 +102,13 @@ public class NotificationRecordTest {
InstrumentationRegistry.getContext().getResources());
when(mMockContext.getPackageManager()).thenReturn(mPm);
- legacy.targetSdkVersion = Build.VERSION_CODES.N_MR1;
upgrade.targetSdkVersion = Build.VERSION_CODES.N_MR1 + 1;
- try {
- when(mPm.getApplicationInfoAsUser(eq(pkg), anyInt(), anyInt())).thenReturn(legacy);
- when(mPm.getApplicationInfoAsUser(eq(pkg2), anyInt(), anyInt())).thenReturn(upgrade);
- } catch (PackageManager.NameNotFoundException e) {}
+ when(mMockContext.getApplicationInfo()).thenReturn(upgrade);
}
- private StatusBarNotification getNotification(boolean preO, boolean noisy, boolean defaultSound,
- boolean buzzy, boolean defaultVibration, boolean lights, boolean defaultLights) {
- when(mMockContext.getApplicationInfo()).thenReturn(preO ? legacy : upgrade);
+ private StatusBarNotification getNotification(boolean supportsChannels, boolean noisy,
+ boolean defaultSound, boolean buzzy, boolean defaultVibration, boolean lights,
+ boolean defaultLights) {
final Builder builder = new Builder(mMockContext)
.setContentTitle("foo")
.setSmallIcon(android.R.drawable.sym_def_app_icon)
@@ -149,13 +147,13 @@ public class NotificationRecordTest {
}
builder.setDefaults(defaults);
- if (!preO) {
+ if (supportsChannels) {
builder.setChannelId(channelId);
}
Notification n = builder.build();
- if (preO) {
+ if (!supportsChannels) {
return new StatusBarNotification(pkg, pkg, id1, tag1, uid, uid, n,
mUser, null, uid);
} else {
@@ -172,11 +170,11 @@ public class NotificationRecordTest {
public void testSound_default_preUpgradeUsesNotification() throws Exception {
defaultChannel.setSound(null, null);
// pre upgrade, default sound.
- StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
+ StatusBarNotification sbn = getNotification(N, true /* noisy */,
true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
false /* lights */, false /*defaultLights */);
- NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
+ NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel, N);
assertEquals(Settings.System.DEFAULT_NOTIFICATION_URI, record.getSound());
assertEquals(Notification.AUDIO_ATTRIBUTES_DEFAULT, record.getAudioAttributes());
}
@@ -185,11 +183,11 @@ public class NotificationRecordTest {
public void testSound_custom_preUpgradeUsesNotification() throws Exception {
defaultChannel.setSound(null, null);
// pre upgrade, custom sound.
- StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
+ StatusBarNotification sbn = getNotification(N, true /* noisy */,
false /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
false /* lights */, false /*defaultLights */);
- NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
+ NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel, N);
assertEquals(CUSTOM_SOUND, record.getSound());
assertEquals(CUSTOM_ATTRIBUTES, record.getAudioAttributes());
}
@@ -199,11 +197,11 @@ public class NotificationRecordTest {
defaultChannel.setSound(CUSTOM_SOUND, CUSTOM_ATTRIBUTES);
defaultChannel.lockFields(NotificationChannel.USER_LOCKED_SOUND);
// pre upgrade, default sound.
- StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
+ StatusBarNotification sbn = getNotification(N, true /* noisy */,
true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
false /* lights */, false /*defaultLights */);
- NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
+ NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel, N);
assertEquals(CUSTOM_SOUND, record.getSound());
assertEquals(CUSTOM_ATTRIBUTES, record.getAudioAttributes());
}
@@ -211,11 +209,11 @@ public class NotificationRecordTest {
@Test
public void testSound_noSound_preUpgrade() throws Exception {
// pre upgrade, default sound.
- StatusBarNotification sbn = getNotification(true /*preO */, false /* noisy */,
+ StatusBarNotification sbn = getNotification(N, false /* noisy */,
false /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
false /* lights */, false /*defaultLights */);
- NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
+ NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel, N);
assertEquals(null, record.getSound());
assertEquals(Notification.AUDIO_ATTRIBUTES_DEFAULT, record.getAudioAttributes());
}
@@ -224,11 +222,11 @@ public class NotificationRecordTest {
public void testSound_default_upgradeUsesChannel() throws Exception {
channel.setSound(CUSTOM_SOUND, CUSTOM_ATTRIBUTES);
// post upgrade, default sound.
- StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
+ StatusBarNotification sbn = getNotification(O, true /* noisy */,
true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
false /* lights */, false /*defaultLights */);
- NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
+ NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel, O);
assertEquals(CUSTOM_SOUND, record.getSound());
assertEquals(CUSTOM_ATTRIBUTES, record.getAudioAttributes());
}
@@ -237,11 +235,11 @@ public class NotificationRecordTest {
public void testVibration_default_preUpgradeUsesNotification() throws Exception {
defaultChannel.enableVibration(false);
// pre upgrade, default vibration.
- StatusBarNotification sbn = getNotification(true /*preO */, false /* noisy */,
+ StatusBarNotification sbn = getNotification(N, false /* noisy */,
false /* defaultSound */, true /* buzzy */, true /* defaultBuzz */,
false /* lights */, false /*defaultLights */);
- NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
+ NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel, N);
assertNotNull(record.getVibration());
}
@@ -249,11 +247,11 @@ public class NotificationRecordTest {
public void testVibration_custom_preUpgradeUsesNotification() throws Exception {
defaultChannel.enableVibration(false);
// pre upgrade, custom vibration.
- StatusBarNotification sbn = getNotification(true /*preO */, false /* noisy */,
+ StatusBarNotification sbn = getNotification(N, false /* noisy */,
false /* defaultSound */, true /* buzzy */, false /* defaultBuzz */,
false /* lights */, false /*defaultLights */);
- NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
+ NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel, N);
assertEquals(CUSTOM_VIBRATION, record.getVibration());
}
@@ -262,11 +260,11 @@ public class NotificationRecordTest {
defaultChannel.enableVibration(true);
defaultChannel.lockFields(NotificationChannel.USER_LOCKED_VIBRATION);
// pre upgrade, custom vibration.
- StatusBarNotification sbn = getNotification(true /*preO */, false /* noisy */,
+ StatusBarNotification sbn = getNotification(N, false /* noisy */,
false /* defaultSound */, true /* buzzy */, false /* defaultBuzz */,
false /* lights */, false /*defaultLights */);
- NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
+ NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel, N);
assertTrue(!Objects.equals(CUSTOM_VIBRATION, record.getVibration()));
}
@@ -274,20 +272,20 @@ public class NotificationRecordTest {
public void testVibration_custom_upgradeUsesChannel() throws Exception {
channel.enableVibration(true);
// post upgrade, custom vibration.
- StatusBarNotification sbn = getNotification(false /*preO */, false /* noisy */,
+ StatusBarNotification sbn = getNotification(O, false /* noisy */,
false /* defaultSound */, true /* buzzy */, false /* defaultBuzz */,
false /* lights */, false /*defaultLights */);
- NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
+ NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel, O);
assertEquals(CUSTOM_CHANNEL_VIBRATION, record.getVibration());
}
@Test
public void testImportance_preUpgrade() throws Exception {
- StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
+ StatusBarNotification sbn = getNotification(N, true /* noisy */,
true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
false /* lights */, false /*defaultLights */);
- NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
+ NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel, N);
assertEquals(NotificationManager.IMPORTANCE_HIGH, record.getImportance());
}
@@ -295,11 +293,11 @@ public class NotificationRecordTest {
public void testImportance_locked_preUpgrade() throws Exception {
defaultChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
defaultChannel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);
- StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
+ StatusBarNotification sbn = getNotification(N, true /* noisy */,
true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
false /* lights */, false /*defaultLights */);
- NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
+ NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel, N);
assertEquals(NotificationManager.IMPORTANCE_LOW, record.getImportance());
}
@@ -307,39 +305,39 @@ public class NotificationRecordTest {
public void testImportance_locked_unspecified_preUpgrade() throws Exception {
defaultChannel.setImportance(NotificationManager.IMPORTANCE_UNSPECIFIED);
defaultChannel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);
- StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
+ StatusBarNotification sbn = getNotification(N, true /* noisy */,
true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
false /* lights */, false /*defaultLights */);
- NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
+ NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel, N);
assertEquals(NotificationManager.IMPORTANCE_HIGH, record.getImportance());
}
@Test
public void testImportance_upgrade() throws Exception {
- StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
+ StatusBarNotification sbn = getNotification(O, true /* noisy */,
true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
false /* lights */, false /*defaultLights */);
- NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
+ NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel, O);
assertEquals(NotificationManager.IMPORTANCE_DEFAULT, record.getImportance());
}
@Test
public void testLights_preUpgrade_noLight() throws Exception {
- StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
+ StatusBarNotification sbn = getNotification(N, true /* noisy */,
true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
false /* lights */, false /*defaultLights */);
- NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
+ NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel, N);
assertNull(record.getLight());
}
@Test
public void testLights_preUpgrade() throws Exception {
- StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
+ StatusBarNotification sbn = getNotification(N, true /* noisy */,
true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
true /* lights */, false /*defaultLights */);
- NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
+ NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel, N);
assertEquals(CUSTOM_LIGHT, record.getLight());
}
@@ -347,11 +345,11 @@ public class NotificationRecordTest {
public void testLights_locked_preUpgrade() throws Exception {
defaultChannel.enableLights(true);
defaultChannel.lockFields(NotificationChannel.USER_LOCKED_LIGHTS);
- StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
+ StatusBarNotification sbn = getNotification(N, true /* noisy */,
true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
true /* lights */, false /*defaultLights */);
- NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
+ NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel, N);
assertFalse(CUSTOM_LIGHT.equals(record.getLight()));
}
@@ -366,10 +364,10 @@ public class NotificationRecordTest {
NotificationRecord.Light expected = new NotificationRecord.Light(
defaultLightColor, defaultLightOn, defaultLightOff);
- StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
+ StatusBarNotification sbn = getNotification(O, true /* noisy */,
true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
true /* lights */, true /*defaultLights */);
- NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
+ NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel, O);
assertEquals(expected, record.getLight());
}
@@ -382,19 +380,19 @@ public class NotificationRecordTest {
NotificationRecord.Light expected = new NotificationRecord.Light(
Color.BLUE, defaultLightOn, defaultLightOff);
- StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
+ StatusBarNotification sbn = getNotification(O, true /* noisy */,
true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
true /* lights */, false /*defaultLights */);
- NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
+ NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel, O);
assertEquals(expected, record.getLight());
}
@Test
public void testLights_upgrade_noLight() throws Exception {
- StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
+ StatusBarNotification sbn = getNotification(O, true /* noisy */,
true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
false /* lights */, false /*defaultLights */);
- NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
+ NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel, O);
assertNull(record.getLight());
}
}
diff --git a/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java b/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java
index c48e73879b13..8ab6d08c3e4f 100644
--- a/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java
+++ b/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java
@@ -124,7 +124,7 @@ public class RankingHelperTest {
.build();
mRecordGroupGSortA = new NotificationRecord(getContext(), new StatusBarNotification(
"package", "package", 1, null, 0, 0, mNotiGroupGSortA, user,
- null, System.currentTimeMillis()), getDefaultChannel());
+ null, System.currentTimeMillis()), getDefaultChannel(), false);
mNotiGroupGSortB = new Notification.Builder(getContext(), TEST_CHANNEL_ID)
.setContentTitle("B")
@@ -134,7 +134,7 @@ public class RankingHelperTest {
.build();
mRecordGroupGSortB = new NotificationRecord(getContext(), new StatusBarNotification(
"package", "package", 1, null, 0, 0, mNotiGroupGSortB, user,
- null, System.currentTimeMillis()), getDefaultChannel());
+ null, System.currentTimeMillis()), getDefaultChannel(), false);
mNotiNoGroup = new Notification.Builder(getContext(), TEST_CHANNEL_ID)
.setContentTitle("C")
@@ -142,7 +142,7 @@ public class RankingHelperTest {
.build();
mRecordNoGroup = new NotificationRecord(getContext(), new StatusBarNotification(
"package", "package", 1, null, 0, 0, mNotiNoGroup, user,
- null, System.currentTimeMillis()), getDefaultChannel());
+ null, System.currentTimeMillis()), getDefaultChannel(), false);
mNotiNoGroup2 = new Notification.Builder(getContext(), TEST_CHANNEL_ID)
.setContentTitle("D")
@@ -150,7 +150,7 @@ public class RankingHelperTest {
.build();
mRecordNoGroup2 = new NotificationRecord(getContext(), new StatusBarNotification(
"package", "package", 1, null, 0, 0, mNotiNoGroup2, user,
- null, System.currentTimeMillis()), getDefaultChannel());
+ null, System.currentTimeMillis()), getDefaultChannel(), false);
mNotiNoGroupSortA = new Notification.Builder(getContext(), TEST_CHANNEL_ID)
.setContentTitle("E")
@@ -159,7 +159,7 @@ public class RankingHelperTest {
.build();
mRecordNoGroupSortA = new NotificationRecord(getContext(), new StatusBarNotification(
"package", "package", 1, null, 0, 0, mNotiNoGroupSortA, user,
- null, System.currentTimeMillis()), getDefaultChannel());
+ null, System.currentTimeMillis()), getDefaultChannel(), false);
mAudioAttributes = new AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_UNKNOWN)
@@ -373,7 +373,7 @@ public class RankingHelperTest {
assertNull(mHelper.getNotificationChannel(PKG, UID, channel1.getId(), false));
assertNull(mHelper.getNotificationChannel(PKG, UID, channel3.getId(), false));
assertNull(mHelper.getNotificationChannelGroup(ncg.getId(), PKG, UID));
- //assertEquals(ncg2, mHelper.getNotificationChannelGroup(ncg2.getId(), PKG, UID));
+ assertEquals(ncg2, mHelper.getNotificationChannelGroup(ncg2.getId(), PKG, UID));
assertEquals(channel2, mHelper.getNotificationChannel(PKG, UID, channel2.getId(), false));
}
@@ -696,20 +696,14 @@ public class RankingHelperTest {
// Returns only non-deleted channels
List<NotificationChannel> channels =
mHelper.getNotificationChannels(PKG, UID, false).getList();
- assertEquals(2, channels.size()); // Default channel + non-deleted channel
- for (NotificationChannel nc : channels) {
- if (!NotificationChannel.DEFAULT_CHANNEL_ID.equals(nc.getId())) {
- compareChannels(channel2, nc);
- }
- }
+ assertEquals(1, channels.size());
+ compareChannels(channel2, channels.get(0));
// Returns deleted channels too
channels = mHelper.getNotificationChannels(PKG, UID, true).getList();
- assertEquals(3, channels.size()); // Includes default channel
+ assertEquals(2, channels.size());
for (NotificationChannel nc : channels) {
- if (!NotificationChannel.DEFAULT_CHANNEL_ID.equals(nc.getId())) {
- compareChannels(channelMap.get(nc.getId()), nc);
- }
+ compareChannels(channelMap.get(nc.getId()), nc);
}
}
@@ -807,8 +801,8 @@ public class RankingHelperTest {
mHelper.permanentlyDeleteNotificationChannels(PKG, UID);
- // Only default channel remains
- assertEquals(1, mHelper.getNotificationChannels(PKG, UID, true).getList().size());
+ // No channels remain
+ assertEquals(0, mHelper.getNotificationChannels(PKG, UID, true).getList().size());
}
@Test
@@ -849,6 +843,36 @@ public class RankingHelperTest {
}
@Test
+ public void testOnUserRemoved() throws Exception {
+ int[] user0Uids = {98, 235, 16, 3782};
+ int[] user1Uids = new int[user0Uids.length];
+ for (int i = 0; i < user0Uids.length; i++) {
+ user1Uids[i] = UserHandle.PER_USER_RANGE + user0Uids[i];
+
+ final ApplicationInfo legacy = new ApplicationInfo();
+ legacy.targetSdkVersion = Build.VERSION_CODES.N_MR1;
+ when(mPm.getApplicationInfoAsUser(eq(PKG), anyInt(), anyInt())).thenReturn(legacy);
+
+ // create records with the default channel for all user 0 and user 1 uids
+ mHelper.getImportance(PKG, user0Uids[i]);
+ mHelper.getImportance(PKG, user1Uids[i]);
+ }
+
+ mHelper.onUserRemoved(1);
+
+ // user 0 records remain
+ for (int i = 0; i < user0Uids.length; i++) {
+ assertEquals(1,
+ mHelper.getNotificationChannels(PKG, user0Uids[i], false).getList().size());
+ }
+ // user 1 records are gone
+ for (int i = 0; i < user1Uids.length; i++) {
+ assertEquals(0,
+ mHelper.getNotificationChannels(PKG, user1Uids[i], false).getList().size());
+ }
+ }
+
+ @Test
public void testOnPackageChanged_packageRemoval() throws Exception {
// Deleted
NotificationChannel channel1 =
@@ -857,13 +881,32 @@ public class RankingHelperTest {
mHelper.onPackagesChanged(true, UserHandle.USER_SYSTEM, new String[]{PKG}, new int[]{UID});
- assertEquals(0, mHelper.getNotificationChannels(PKG, UID, true).getList().size());
+ // since this is a pre upgrade app, clearing data should restore the default channel
+ assertEquals(1, mHelper.getNotificationChannels(PKG, UID, true).getList().size());
+ assertEquals(NotificationChannel.DEFAULT_CHANNEL_ID,
+ mHelper.getNotificationChannels(PKG, UID, true).getList().get(0).getId());
// Not deleted
mHelper.createNotificationChannel(PKG, UID, channel1, true);
-
mHelper.onPackagesChanged(false, UserHandle.USER_SYSTEM, new String[]{PKG}, new int[]{UID});
- assertEquals(2, mHelper.getNotificationChannels(PKG, UID, false).getList().size());
+ assertEquals(1, mHelper.getNotificationChannels(PKG, UID, false).getList().size());
+ }
+
+ @Test
+ public void testOnPackageChanged_packageRemoval_updatedPackage() throws Exception {
+ // Deleted
+ NotificationChannel channel1 =
+ new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH);
+ mHelper.createNotificationChannel(UPDATED_PKG, UID2, channel1, true);
+ mHelper.onPackagesChanged(
+ true, UserHandle.USER_SYSTEM, new String[]{UPDATED_PKG}, new int[]{UID2});
+ assertEquals(0, mHelper.getNotificationChannels(UPDATED_PKG, UID2, true).getList().size());
+
+ // Not deleted
+ mHelper.createNotificationChannel(UPDATED_PKG, UID2, channel1, true);
+ mHelper.onPackagesChanged(
+ false, UserHandle.USER_SYSTEM, new String[]{UPDATED_PKG}, new int[]{UID2});
+ assertEquals(1, mHelper.getNotificationChannels(UPDATED_PKG, UID2, false).getList().size());
}
@Test
@@ -884,7 +927,23 @@ public class RankingHelperTest {
mHelper.onPackagesChanged(true, UserHandle.USER_SYSTEM, new String[]{PKG}, new int[]{UID});
- assertEquals(0, mHelper.getNotificationChannelGroups(PKG, UID, true).getList().size());
+ // default channel restored
+ assertEquals(1, mHelper.getNotificationChannelGroups(PKG, UID, true).getList().size());
+ assertNull(mHelper.getNotificationChannelGroups(PKG, UID, true).getList().get(0).getId());
+ }
+
+ @Test
+ public void testOnPackageChanged_packageRemoval_groups_upgraded() throws Exception {
+ NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1");
+ mHelper.createNotificationChannelGroup(UPDATED_PKG, UID2, ncg, true);
+ NotificationChannelGroup ncg2 = new NotificationChannelGroup("group2", "name2");
+ mHelper.createNotificationChannelGroup(UPDATED_PKG, UID2, ncg2, true);
+
+ mHelper.onPackagesChanged(
+ true, UserHandle.USER_SYSTEM, new String[]{UPDATED_PKG}, new int[]{UID2});
+
+ assertEquals(0,
+ mHelper.getNotificationChannelGroups(UPDATED_PKG, UID2, true).getList().size());
}
@Test
@@ -958,9 +1017,8 @@ public class RankingHelperTest {
assertEquals(3, actual.size());
for (NotificationChannelGroup group : actual) {
if (group.getId() == null) {
- assertEquals(2, group.getChannels().size()); // misc channel too
- assertTrue(channel3.getId().equals(group.getChannels().get(0).getId())
- || channel3.getId().equals(group.getChannels().get(1).getId()));
+ assertEquals(1, group.getChannels().size());
+ assertTrue(channel3.getId().equals(group.getChannels().get(0).getId()));
} else if (group.getId().equals(ncg.getId())) {
assertEquals(2, group.getChannels().size());
if (group.getChannels().get(0).getId().equals(channel1.getId())) {
@@ -994,12 +1052,8 @@ public class RankingHelperTest {
List<NotificationChannelGroup> actual =
mHelper.getNotificationChannelGroups(PKG, UID, true).getList();
- assertEquals(2, actual.size());
- for (NotificationChannelGroup group : actual) {
- if (Objects.equals(group.getId(), ncg.getId())) {
- assertEquals(1, group.getChannels().size());
- }
- }
+ assertEquals(1, actual.size());
+ assertEquals(1, actual.get(0).getChannels().size());
}
@Test
diff --git a/services/tests/notification/src/com/android/server/notification/SnoozeHelperTest.java b/services/tests/notification/src/com/android/server/notification/SnoozeHelperTest.java
index bc25860e8e92..b1cb4d7d4e67 100644
--- a/services/tests/notification/src/com/android/server/notification/SnoozeHelperTest.java
+++ b/services/tests/notification/src/com/android/server/notification/SnoozeHelperTest.java
@@ -312,7 +312,7 @@ public class SnoozeHelperTest {
TEST_CHANNEL_ID, "name", NotificationManager.IMPORTANCE_LOW);
return new NotificationRecord(getContext(), new StatusBarNotification(
pkg, pkg, id, tag, 0, 0, n, user, null,
- System.currentTimeMillis()), notificationChannel);
+ System.currentTimeMillis()), notificationChannel, true);
}
private NotificationRecord getNotificationRecord(String pkg, int id, String tag,
diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml
index cc682c4ee985..fa72416edd16 100644
--- a/services/tests/servicestests/AndroidManifest.xml
+++ b/services/tests/servicestests/AndroidManifest.xml
@@ -18,6 +18,7 @@
package="com.android.frameworks.servicestests">
<uses-permission android:name="android.permission.READ_LOGS" />
+ <uses-permission android:name="android.permission.ACCESS_VR_MANAGER" />
<uses-permission android:name="android.permission.ACCOUNT_MANAGER" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
diff --git a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
index c78488f9d8d9..bb7e20bcb9c3 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
@@ -368,8 +368,8 @@ public class NetworkScoreServiceTest {
}
@Test
- public void testSetActiveScorer_noRequestNetworkScoresPermission() {
- when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
+ public void testSetActiveScorer_noScoreNetworksPermission() {
+ when(mContext.checkCallingOrSelfPermission(permission.SCORE_NETWORKS))
.thenReturn(PackageManager.PERMISSION_DENIED);
try {
diff --git a/services/tests/servicestests/src/com/android/server/NetworkScorerAppManagerTest.java b/services/tests/servicestests/src/com/android/server/NetworkScorerAppManagerTest.java
index 0694eaefd288..ceb92dece764 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkScorerAppManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkScorerAppManagerTest.java
@@ -228,30 +228,23 @@ public class NetworkScorerAppManagerTest {
}
@Test
- public void testSetActiveScorer_nullPackage_validDefault() throws Exception {
- String packageName = "package";
- String defaultPackage = "defaultPackage";
- setNetworkRecoPackageSetting(packageName);
- setDefaultNetworkRecommendationPackage(defaultPackage);
- final ComponentName recoComponent = new ComponentName(defaultPackage, "class1");
- mockScoreNetworksGranted(recoComponent.getPackageName());
- mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */, null);
+ public void testSetActiveScorer_nullPackage_currentIsSet() throws Exception {
+ setNetworkRecoPackageSetting("package");
assertTrue(mNetworkScorerAppManager.setActiveScorer(null));
verify(mSettingsFacade).putString(mMockContext,
- Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE, defaultPackage);
+ Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE, null);
+ verify(mSettingsFacade).putInt(mMockContext,
+ Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED,
+ NetworkScoreManager.RECOMMENDATIONS_ENABLED_FORCED_OFF);
}
@Test
- public void testSetActiveScorer_nullPackage_invalidDefault() throws Exception {
- String packageName = "package";
- String defaultPackage = "defaultPackage";
- setNetworkRecoPackageSetting(packageName);
- setDefaultNetworkRecommendationPackage(defaultPackage);
+ public void testSetActiveScorer_nullPackage_currentIsNull() throws Exception {
+ setNetworkRecoPackageSetting(null);
- assertFalse(mNetworkScorerAppManager.setActiveScorer(null));
- verify(mSettingsFacade, never()).putString(any(),
- eq(Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE), any());
+ assertTrue(mNetworkScorerAppManager.setActiveScorer(null));
+ verify(mSettingsFacade, never()).putString(any(), any(), any());
}
@Test
@@ -266,6 +259,9 @@ public class NetworkScorerAppManagerTest {
assertTrue(mNetworkScorerAppManager.setActiveScorer(newPackage));
verify(mSettingsFacade).putString(mMockContext,
Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE, newPackage);
+ verify(mSettingsFacade).putInt(mMockContext,
+ Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED,
+ NetworkScoreManager.RECOMMENDATIONS_ENABLED_ON);
}
@Test
@@ -341,6 +337,32 @@ public class NetworkScorerAppManagerTest {
}
@Test
+ public void testUpdateState_currentPackageNull_defaultNull() throws Exception {
+ setDefaultNetworkRecommendationPackage(null);
+ setNetworkRecoPackageSetting(null);
+
+ mNetworkScorerAppManager.updateState();
+
+ verify(mSettingsFacade, never()).putString(any(),
+ eq(Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE), anyString());
+ verify(mSettingsFacade, never()).putInt(any(),
+ eq(Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED), anyInt());
+ }
+
+ @Test
+ public void testUpdateState_currentPackageEmpty_defaultEmpty() throws Exception {
+ setDefaultNetworkRecommendationPackage("");
+ setNetworkRecoPackageSetting("");
+
+ mNetworkScorerAppManager.updateState();
+
+ verify(mSettingsFacade, never()).putString(any(),
+ eq(Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE), anyString());
+ verify(mSettingsFacade, never()).putInt(any(),
+ eq(Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED), anyInt());
+ }
+
+ @Test
public void testUpdateState_currentPackageNotValid_sameAsDefault() throws Exception {
String defaultPackage = "defaultPackage";
setDefaultNetworkRecommendationPackage(defaultPackage);
diff --git a/services/tests/servicestests/src/com/android/server/NightDisplayServiceTest.java b/services/tests/servicestests/src/com/android/server/NightDisplayServiceTest.java
new file mode 100644
index 000000000000..9a9c243023eb
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/NightDisplayServiceTest.java
@@ -0,0 +1,620 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+import android.app.ActivityManager;
+import android.app.AlarmManager;
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.provider.Settings.Secure;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+import android.test.mock.MockContentResolver;
+
+import com.android.internal.app.NightDisplayController;
+import com.android.internal.app.NightDisplayController.LocalTime;
+import com.android.internal.util.test.FakeSettingsProvider;
+import com.android.server.display.DisplayTransformManager;
+import com.android.server.display.NightDisplayService;
+import com.android.server.twilight.TwilightManager;
+import com.android.server.twilight.TwilightState;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+
+import java.util.Calendar;
+
+import static com.google.common.truth.Truth.assertWithMessage;
+import static org.mockito.Mockito.doReturn;
+
+@RunWith(AndroidJUnit4.class)
+public class NightDisplayServiceTest {
+
+ private Context mContext;
+ private int mUserId;
+
+ private TwilightManager mTwilightManager;
+
+ private NightDisplayController mNightDisplayController;
+ private NightDisplayService mNightDisplayService;
+
+ @Before
+ public void setUp() {
+ mContext = Mockito.spy(new ContextWrapper(InstrumentationRegistry.getTargetContext()));
+ mUserId = ActivityManager.getCurrentUser();
+
+ doReturn(mContext).when(mContext).getApplicationContext();
+
+ final MockContentResolver cr = new MockContentResolver(mContext);
+ cr.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
+ doReturn(cr).when(mContext).getContentResolver();
+
+ final AlarmManager am = Mockito.mock(AlarmManager.class);
+ doReturn(am).when(mContext).getSystemService(Context.ALARM_SERVICE);
+
+ final DisplayTransformManager dtm = Mockito.mock(DisplayTransformManager.class);
+ LocalServices.addService(DisplayTransformManager.class, dtm);
+
+ mTwilightManager = Mockito.mock(TwilightManager.class);
+ LocalServices.addService(TwilightManager.class, mTwilightManager);
+
+ mNightDisplayController = new NightDisplayController(mContext, mUserId);
+ mNightDisplayService = new NightDisplayService(mContext);
+ }
+
+ @After
+ public void tearDown() {
+ LocalServices.removeServiceForTest(DisplayTransformManager.class);
+ LocalServices.removeServiceForTest(TwilightManager.class);
+
+ mNightDisplayService = null;
+ mNightDisplayController = null;
+
+ mTwilightManager = null;
+
+ mUserId = UserHandle.USER_NULL;
+ mContext = null;
+ }
+
+ @Test
+ public void customSchedule_whenStartedAfterNight_ifOffAfterNight_turnsOff() {
+ setAutoModeCustom(-120 /* startTimeOffset */, -60 /* endTimeOffset */);
+ setActivated(false /* activated */, -30 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(false /* activated */);
+ }
+
+ @Test
+ public void customSchedule_whenStartedAfterNight_ifOffBeforeNight_turnsOff() {
+ setAutoModeCustom(-120 /* startTimeOffset */, -60 /* endTimeOffset */);
+ setActivated(false /* activated */, -180 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(false /* activated */);
+ }
+
+ @Test
+ public void customSchedule_whenStartedAfterNight_ifOffDuringNight_turnsOff() {
+ setAutoModeCustom(-120 /* startTimeOffset */, -60 /* endTimeOffset */);
+ setActivated(false /* activated */, -90 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(false /* activated */);
+ }
+
+ @Test
+ public void customSchedule_whenStartedAfterNight_ifOffInFuture_turnsOff() {
+ setAutoModeCustom(-120 /* startTimeOffset */, -60 /* endTimeOffset */);
+ setActivated(false /* activated */, 30 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(false /* activated */);
+ }
+
+ @Test
+ public void customSchedule_whenStartedAfterNight_ifOnAfterNight_turnsOn() {
+ setAutoModeCustom(-120 /* startTimeOffset */, -60 /* endTimeOffset */);
+ setActivated(true /* activated */, -30 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(true /* activated */);
+ }
+
+ @Test
+ public void customSchedule_whenStartedAfterNight_ifOnBeforeNight_turnsOff() {
+ setAutoModeCustom(-120 /* startTimeOffset */, -60 /* endTimeOffset */);
+ setActivated(true /* activated */, -180 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(false /* activated */);
+ }
+
+ @Test
+ public void customSchedule_whenStartedAfterNight_ifOnDuringNight_turnsOff() {
+ setAutoModeCustom(-120 /* startTimeOffset */, -60 /* endTimeOffset */);
+ setActivated(true /* activated */, -90 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(false /* activated */);
+ }
+
+ @Test
+ public void customSchedule_whenStartedAfterNight_ifOnInFuture_turnsOff() {
+ setAutoModeCustom(-120 /* startTimeOffset */, -60 /* endTimeOffset */);
+ setActivated(true /* activated */, 30 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(false /* activated */);
+ }
+
+ @Test
+ public void customSchedule_whenStartedBeforeNight_ifOffAfterNight_turnsOff() {
+ setAutoModeCustom(60 /* startTimeOffset */, 120 /* endTimeOffset */);
+ setActivated(false /* activated */, 180 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(false /* activated */);
+ }
+
+ @Test
+ public void customSchedule_whenStartedBeforeNight_ifOffBeforeNight_turnsOff() {
+ setAutoModeCustom(60 /* startTimeOffset */, 120 /* endTimeOffset */);
+ setActivated(false /* activated */, 30 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(false /* activated */);
+ }
+
+ @Test
+ public void customSchedule_whenStartedBeforeNight_ifOffDuringNight_turnsOff() {
+ setAutoModeCustom(60 /* startTimeOffset */, 120 /* endTimeOffset */);
+ setActivated(false /* activated */, 90 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(false /* activated */);
+ }
+
+ @Test
+ public void customSchedule_whenStartedBeforeNight_ifOffInPast_turnsOff() {
+ setAutoModeCustom(60 /* startTimeOffset */, 120 /* endTimeOffset */);
+ setActivated(false /* activated */, -30 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(false /* activated */);
+ }
+
+ @Test
+ public void customSchedule_whenStartedBeforeNight_ifOnAfterNight_turnsOff() {
+ setAutoModeCustom(60 /* startTimeOffset */, 120 /* endTimeOffset */);
+ setActivated(true /* activated */, 180 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(false /* activated */);
+ }
+
+ @Test
+ public void customSchedule_whenStartedBeforeNight_ifOnBeforeNight_turnsOff() {
+ setAutoModeCustom(60 /* startTimeOffset */, 120 /* endTimeOffset */);
+ setActivated(true /* activated */, 30 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(false /* activated */);
+ }
+
+ @Test
+ public void customSchedule_whenStartedBeforeNight_ifOnDuringNight_turnsOff() {
+ setAutoModeCustom(60 /* startTimeOffset */, 120 /* endTimeOffset */);
+ setActivated(true /* activated */, 90 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(false /* activated */);
+ }
+
+ @Test
+ public void customSchedule_whenStartedBeforeNight_ifOnInPast_turnsOn() {
+ setAutoModeCustom(60 /* startTimeOffset */, 120 /* endTimeOffset */);
+ setActivated(true /* activated */, -30 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(true /* activated */);
+ }
+
+ @Test
+ public void customSchedule_whenStartedDuringNight_ifOffAfterNight_turnsOn() {
+ setAutoModeCustom(-60 /* startTimeOffset */, 60 /* endTimeOffset */);
+ setActivated(false /* activated */, 90 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(true /* activated */);
+ }
+
+ @Test
+ public void customSchedule_whenStartedDuringNight_ifOffBeforeNight_turnsOn() {
+ setAutoModeCustom(-60 /* startTimeOffset */, 60 /* endTimeOffset */);
+ setActivated(false /* activated */, -90 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(true /* activated */);
+ }
+
+ @Test
+ public void customSchedule_whenStartedDuringNight_ifOffDuringNightInFuture_turnsOn() {
+ setAutoModeCustom(-60 /* startTimeOffset */, 60 /* endTimeOffset */);
+ setActivated(false /* activated */, 30 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(true /* activated */);
+ }
+
+ @Test
+ public void customSchedule_whenStartedDuringNight_ifOffDuringNightInPast_turnsOff() {
+ setAutoModeCustom(-60 /* startTimeOffset */, 60 /* endTimeOffset */);
+ setActivated(false /* activated */, -30 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(false /* activated */);
+ }
+
+ @Test
+ public void customSchedule_whenStartedDuringNight_ifOnAfterNight_turnsOn() {
+ setAutoModeCustom(-60 /* startTimeOffset */, 60 /* endTimeOffset */);
+ setActivated(true /* activated */, 90 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(true /* activated */);
+ }
+
+ @Test
+ public void customSchedule_whenStartedDuringNight_ifOnBeforeNight_turnsOn() {
+ setAutoModeCustom(-60 /* startTimeOffset */, 60 /* endTimeOffset */);
+ setActivated(true /* activated */, -90 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(true /* activated */);
+ }
+
+ @Test
+ public void customSchedule_whenStartedDuringNight_ifOnDuringNightInFuture_turnsOn() {
+ setAutoModeCustom(-60 /* startTimeOffset */, 60 /* endTimeOffset */);
+ setActivated(true /* activated */, 30 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(true /* activated */);
+ }
+
+ @Test
+ public void customSchedule_whenStartedDuringNight_ifOnDuringNightInPast_turnsOn() {
+ setAutoModeCustom(-60 /* startTimeOffset */, 60 /* endTimeOffset */);
+ setActivated(true /* activated */, -30 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(true /* activated */);
+ }
+
+ @Test
+ public void twilightSchedule_whenStartedAfterNight_ifOffAfterNight_turnsOff() {
+ setAutoModeTwilight(-120 /* sunsetOffset */, -60 /* sunriseOffset */);
+ setActivated(false /* activated */, -30 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(false /* activated */);
+ }
+
+ @Test
+ public void twilightSchedule_whenStartedAfterNight_ifOffBeforeNight_turnsOff() {
+ setAutoModeTwilight(-120 /* sunsetOffset */, -60 /* sunriseOffset */);
+ setActivated(false /* activated */, -180 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(false /* activated */);
+ }
+
+ @Test
+ public void twilightSchedule_whenStartedAfterNight_ifOffDuringNight_turnsOff() {
+ setAutoModeTwilight(-120 /* sunsetOffset */, -60 /* sunriseOffset */);
+ setActivated(false /* activated */, -90 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(false /* activated */);
+ }
+
+ @Test
+ public void twilightSchedule_whenStartedAfterNight_ifOffInFuture_turnsOff() {
+ setAutoModeTwilight(-120 /* sunsetOffset */, -60 /* sunriseOffset */);
+ setActivated(false /* activated */, 30 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(false /* activated */);
+ }
+
+ @Test
+ public void twilightSchedule_whenStartedAfterNight_ifOnAfterNight_turnsOn() {
+ setAutoModeTwilight(-120 /* sunsetOffset */, -60 /* sunriseOffset */);
+ setActivated(true /* activated */, -30 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(true /* activated */);
+ }
+
+ @Test
+ public void twilightSchedule_whenStartedAfterNight_ifOnBeforeNight_turnsOff() {
+ setAutoModeTwilight(-120 /* sunsetOffset */, -60 /* sunriseOffset */);
+ setActivated(true /* activated */, -180 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(false /* activated */);
+ }
+
+ @Test
+ public void twilightSchedule_whenStartedAfterNight_ifOnDuringNight_turnsOff() {
+ setAutoModeTwilight(-120 /* sunsetOffset */, -60 /* sunriseOffset */);
+ setActivated(true /* activated */, -90 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(false /* activated */);
+ }
+
+ @Test
+ public void twilightSchedule_whenStartedAfterNight_ifOnInFuture_turnsOff() {
+ setAutoModeTwilight(-120 /* sunsetOffset */, -60 /* sunriseOffset */);
+ setActivated(true /* activated */, 30 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(false /* activated */);
+ }
+
+ @Test
+ public void twilightSchedule_whenStartedBeforeNight_ifOffAfterNight_turnsOff() {
+ setAutoModeTwilight(60 /* sunsetOffset */, 120 /* sunriseOffset */);
+ setActivated(false /* activated */, 180 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(false /* activated */);
+ }
+
+ @Test
+ public void twilightSchedule_whenStartedBeforeNight_ifOffBeforeNight_turnsOff() {
+ setAutoModeTwilight(60 /* sunsetOffset */, 120 /* sunriseOffset */);
+ setActivated(false /* activated */, 30 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(false /* activated */);
+ }
+
+ @Test
+ public void twilightSchedule_whenStartedBeforeNight_ifOffDuringNight_turnsOff() {
+ setAutoModeTwilight(60 /* sunsetOffset */, 120 /* sunriseOffset */);
+ setActivated(false /* activated */, 90 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(false /* activated */);
+ }
+
+ @Test
+ public void twilightSchedule_whenStartedBeforeNight_ifOffInPast_turnsOff() {
+ setAutoModeTwilight(60 /* sunsetOffset */, 120 /* sunriseOffset */);
+ setActivated(false /* activated */, -30 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(false /* activated */);
+ }
+
+ @Test
+ public void twilightSchedule_whenStartedBeforeNight_ifOnAfterNight_turnsOff() {
+ setAutoModeTwilight(60 /* sunsetOffset */, 120 /* sunriseOffset */);
+ setActivated(true /* activated */, 180 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(false /* activated */);
+ }
+
+ @Test
+ public void twilightSchedule_whenStartedBeforeNight_ifOnBeforeNight_turnsOff() {
+ setAutoModeTwilight(60 /* sunsetOffset */, 120 /* sunriseOffset */);
+ setActivated(true /* activated */, 30 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(false /* activated */);
+ }
+
+ @Test
+ public void twilightSchedule_whenStartedBeforeNight_ifOnDuringNight_turnsOff() {
+ setAutoModeTwilight(60 /* sunsetOffset */, 120 /* sunriseOffset */);
+ setActivated(true /* activated */, 90 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(false /* activated */);
+ }
+
+ @Test
+ public void twilightSchedule_whenStartedBeforeNight_ifOnInPast_turnsOn() {
+ setAutoModeTwilight(60 /* sunsetOffset */, 120 /* sunriseOffset */);
+ setActivated(true /* activated */, -30 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(true /* activated */);
+ }
+
+ @Test
+ public void twilightSchedule_whenStartedDuringNight_ifOffAfterNight_turnsOn() {
+ setAutoModeTwilight(-60 /* sunsetOffset */, 60 /* sunriseOffset */);
+ setActivated(false /* activated */, 90 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(true /* activated */);
+ }
+
+ @Test
+ public void twilightSchedule_whenStartedDuringNight_ifOffBeforeNight_turnsOn() {
+ setAutoModeTwilight(-60 /* sunsetOffset */, 60 /* sunriseOffset */);
+ setActivated(false /* activated */, -90 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(true /* activated */);
+ }
+
+ @Test
+ public void twilightSchedule_whenStartedDuringNight_ifOffDuringNightInFuture_turnsOn() {
+ setAutoModeTwilight(-60 /* sunsetOffset */, 60 /* sunriseOffset */);
+ setActivated(false /* activated */, 30 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(true /* activated */);
+ }
+
+ @Test
+ public void twilightSchedule_whenStartedDuringNight_ifOffDuringNightInPast_turnsOff() {
+ setAutoModeTwilight(-60 /* sunsetOffset */, 60 /* sunriseOffset */);
+ setActivated(false /* activated */, -30 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(false /* activated */);
+ }
+
+ @Test
+ public void twilightSchedule_whenStartedDuringNight_ifOnAfterNight_turnsOn() {
+ setAutoModeTwilight(-60 /* sunsetOffset */, 60 /* sunriseOffset */);
+ setActivated(true /* activated */, 90 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(true /* activated */);
+ }
+
+ @Test
+ public void twilightSchedule_whenStartedDuringNight_ifOnBeforeNight_turnsOn() {
+ setAutoModeTwilight(-60 /* sunsetOffset */, 60 /* sunriseOffset */);
+ setActivated(true /* activated */, -90 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(true /* activated */);
+ }
+
+ @Test
+ public void twilightSchedule_whenStartedDuringNight_ifOnDuringNightInFuture_turnsOn() {
+ setAutoModeTwilight(-60 /* sunsetOffset */, 60 /* sunriseOffset */);
+ setActivated(true /* activated */, 30 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(true /* activated */);
+ }
+
+ @Test
+ public void twilightSchedule_whenStartedDuringNight_ifOnDuringNightInPast_turnsOn() {
+ setAutoModeTwilight(-60 /* sunsetOffset */, 60 /* sunriseOffset */);
+ setActivated(true /* activated */, -30 /* lastActivatedTimeOffset */);
+
+ startService();
+ assertActivated(true /* activated */);
+ }
+
+ /**
+ * Convenience for making a {@link LocalTime} instance with an offset relative to now.
+ *
+ * @param offsetMinutes the offset relative to now (in minutes)
+ * @return the LocalTime instance
+ */
+ private LocalTime getLocalTimeRelativeToNow(int offsetMinutes) {
+ final Calendar c = Calendar.getInstance();
+ c.add(Calendar.MINUTE, offsetMinutes);
+ return new LocalTime(c.get(Calendar.HOUR_OF_DAY), c.get(Calendar.MINUTE));
+ }
+
+ /**
+ * Configures Night display to use a custom schedule.
+ *
+ * @param startTimeOffset the offset relative to now to activate Night display (in minutes)
+ * @param endTimeOffset the offset relative to now to deactivate Night display (in minutes)
+ */
+ private void setAutoModeCustom(int startTimeOffset, int endTimeOffset) {
+ mNightDisplayController.setAutoMode(NightDisplayController.AUTO_MODE_CUSTOM);
+ mNightDisplayController.setCustomStartTime(getLocalTimeRelativeToNow(startTimeOffset));
+ mNightDisplayController.setCustomEndTime(getLocalTimeRelativeToNow(endTimeOffset));
+ }
+
+ /**
+ * Configures Night display to use the twilight schedule.
+ *
+ * @param sunsetOffset the offset relative to now for sunset (in minutes)
+ * @param sunriseOffset the offset relative to now for sunrise (in minutes)
+ */
+ private void setAutoModeTwilight(int sunsetOffset, int sunriseOffset) {
+ mNightDisplayController.setAutoMode(NightDisplayController.AUTO_MODE_TWILIGHT);
+
+ final LocalTime sunset = getLocalTimeRelativeToNow(sunsetOffset);
+ final LocalTime sunrise = getLocalTimeRelativeToNow(sunriseOffset);
+
+ final Calendar now = Calendar.getInstance();
+ long sunsetMillis = sunset.getDateTimeBefore(now).getTimeInMillis();
+ long sunriseMillis = sunrise.getDateTimeBefore(now).getTimeInMillis();
+ if (sunsetMillis < sunriseMillis) {
+ sunsetMillis = sunset.getDateTimeAfter(now).getTimeInMillis();
+ } else {
+ sunriseMillis = sunrise.getDateTimeAfter(now).getTimeInMillis();
+ }
+
+ final TwilightState state = new TwilightState(sunriseMillis, sunsetMillis);
+ doReturn(state).when(mTwilightManager).getLastTwilightState();
+ }
+
+ /**
+ * Configures the Night display activated state.
+ *
+ * @param activated {@code true} if Night display should be activated
+ * @param lastActivatedTimeOffset the offset relative to now to record that Night display was
+ activated (in minutes)
+ */
+ private void setActivated(boolean activated, int lastActivatedTimeOffset) {
+ mNightDisplayController.setActivated(activated);
+
+ final Calendar c = Calendar.getInstance();
+ c.add(Calendar.MINUTE, lastActivatedTimeOffset);
+ Secure.putLongForUser(mContext.getContentResolver(),
+ Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME, c.getTimeInMillis(), mUserId);
+ }
+
+ /**
+ * Convenience method to start {@link #mNightDisplayService}.
+ */
+ private void startService() {
+ Secure.putIntForUser(mContext.getContentResolver(), Secure.USER_SETUP_COMPLETE, 1, mUserId);
+
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ mNightDisplayService.onStart();
+ mNightDisplayService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED);
+ mNightDisplayService.onStartUser(mUserId);
+ }
+ });
+ }
+
+ /**
+ * Convenience method for asserting whether Night display should be activated.
+ *
+ * @param activated the expected activated state of Night display
+ */
+ private void assertActivated(boolean activated) {
+ assertWithMessage("Invalid Night display activated state")
+ .that(mNightDisplayController.isActivated())
+ .isEqualTo(activated);
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotCacheTest.java b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotCacheTest.java
index a23a6b22d9e8..649de4a783fa 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotCacheTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotCacheTest.java
@@ -20,6 +20,7 @@ import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertNull;
+import android.platform.test.annotations.Presubmit;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
@@ -33,8 +34,7 @@ import org.junit.runner.RunWith;
* runtest frameworks-services -c com.android.server.wm.TaskSnapshotCacheTest
*/
@SmallTest
-// TODO(b/35196891): Add back to presubmit once the bug is fixed.
-//@Presubmit
+@Presubmit
@RunWith(AndroidJUnit4.class)
public class TaskSnapshotCacheTest extends TaskSnapshotPersisterTestBase {
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotControllerTest.java b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotControllerTest.java
index 2b4d9fb4800a..f253632a1765 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotControllerTest.java
@@ -17,6 +17,7 @@
package com.android.server.wm;
import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
+import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
import static com.android.server.wm.AppTransition.TRANSIT_UNSET;
import static com.android.server.wm.TaskSnapshotController.*;
import static junit.framework.Assert.assertEquals;
@@ -76,12 +77,19 @@ public class TaskSnapshotControllerTest extends WindowTestsBase {
public void testGetSnapshotMode() throws Exception {
final WindowState disabledWindow = createWindow(null,
FIRST_APPLICATION_WINDOW, mDisplayContent, "disabledWindow");
- disabledWindow.mAppToken.setDisablePreviewSnapshots(true);
+ disabledWindow.mAppToken.setDisablePreviewScreenshots(true);
assertEquals(SNAPSHOT_MODE_APP_THEME,
sWm.mTaskSnapshotController.getSnapshotMode(disabledWindow.getTask()));
+
final WindowState normalWindow = createWindow(null,
FIRST_APPLICATION_WINDOW, mDisplayContent, "normalWindow");
assertEquals(SNAPSHOT_MODE_REAL,
sWm.mTaskSnapshotController.getSnapshotMode(normalWindow.getTask()));
+
+ final WindowState secureWindow = createWindow(null,
+ FIRST_APPLICATION_WINDOW, mDisplayContent, "secureWindow");
+ secureWindow.mAttrs.flags |= FLAG_SECURE;
+ assertEquals(SNAPSHOT_MODE_APP_THEME,
+ sWm.mTaskSnapshotController.getSnapshotMode(secureWindow.getTask()));
}
}
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 18d0c321d181..8146763ae871 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java
@@ -68,7 +68,11 @@ class TaskSnapshotPersisterTestBase extends WindowTestsBase {
}
private void cleanDirectory() {
- for (File file : new File(sFilesDir, "snapshots").listFiles()) {
+ final File[] files = new File(sFilesDir, "snapshots").listFiles();
+ if (files == null) {
+ return;
+ }
+ for (File file : files) {
if (!file.isDirectory()) {
file.delete();
}
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 717ddf26eb2f..e2868d7056b0 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
@@ -171,11 +171,25 @@ public class TaskSnapshotSurfaceTest extends WindowTestsBase {
final Canvas mockCanvas = mock(Canvas.class);
when(mockCanvas.getWidth()).thenReturn(100);
when(mockCanvas.getHeight()).thenReturn(100);
- mSurface.drawStatusBarBackground(mockCanvas, new Rect(0, 0, 50, 100), 10);
+ mSurface.mSystemBarBackgroundPainter.drawStatusBarBackground(
+ mockCanvas, new Rect(0, 0, 50, 100), 10);
verify(mockCanvas).drawRect(eq(50.0f), eq(0.0f), eq(90.0f), eq(10.0f), any());
}
@Test
+ public void testDrawStatusBarBackground_nullFrame() {
+ setupSurface(100, 100);
+ final Rect insets = new Rect(0, 10, 10, 0);
+ mSurface.setFrames(new Rect(0, 0, 100, 100), insets, insets);
+ final Canvas mockCanvas = mock(Canvas.class);
+ when(mockCanvas.getWidth()).thenReturn(100);
+ when(mockCanvas.getHeight()).thenReturn(100);
+ mSurface.mSystemBarBackgroundPainter.drawStatusBarBackground(
+ mockCanvas, null, 10);
+ verify(mockCanvas).drawRect(eq(0.0f), eq(0.0f), eq(90.0f), eq(10.0f), any());
+ }
+
+ @Test
public void testDrawStatusBarBackground_nope() {
setupSurface(100, 100);
final Rect insets = new Rect(0, 10, 10, 0);
@@ -183,7 +197,8 @@ public class TaskSnapshotSurfaceTest extends WindowTestsBase {
final Canvas mockCanvas = mock(Canvas.class);
when(mockCanvas.getWidth()).thenReturn(100);
when(mockCanvas.getHeight()).thenReturn(100);
- mSurface.drawStatusBarBackground(mockCanvas, new Rect(0, 0, 100, 100), 10);
+ mSurface.mSystemBarBackgroundPainter.drawStatusBarBackground(
+ mockCanvas, new Rect(0, 0, 100, 100), 10);
verify(mockCanvas, never()).drawRect(anyInt(), anyInt(), anyInt(), anyInt(), any());
}
@@ -196,7 +211,7 @@ public class TaskSnapshotSurfaceTest extends WindowTestsBase {
final Canvas mockCanvas = mock(Canvas.class);
when(mockCanvas.getWidth()).thenReturn(100);
when(mockCanvas.getHeight()).thenReturn(100);
- mSurface.drawNavigationBarBackground(mockCanvas);
+ mSurface.mSystemBarBackgroundPainter.drawNavigationBarBackground(mockCanvas);
verify(mockCanvas).drawRect(eq(new Rect(0, 90, 100, 100)), any());
}
@@ -209,7 +224,7 @@ public class TaskSnapshotSurfaceTest extends WindowTestsBase {
final Canvas mockCanvas = mock(Canvas.class);
when(mockCanvas.getWidth()).thenReturn(100);
when(mockCanvas.getHeight()).thenReturn(100);
- mSurface.drawNavigationBarBackground(mockCanvas);
+ mSurface.mSystemBarBackgroundPainter.drawNavigationBarBackground(mockCanvas);
verify(mockCanvas).drawRect(eq(new Rect(0, 0, 10, 100)), any());
}
@@ -222,7 +237,7 @@ public class TaskSnapshotSurfaceTest extends WindowTestsBase {
final Canvas mockCanvas = mock(Canvas.class);
when(mockCanvas.getWidth()).thenReturn(100);
when(mockCanvas.getHeight()).thenReturn(100);
- mSurface.drawNavigationBarBackground(mockCanvas);
+ mSurface.mSystemBarBackgroundPainter.drawNavigationBarBackground(mockCanvas);
verify(mockCanvas).drawRect(eq(new Rect(90, 0, 100, 100)), any());
}
}
diff --git a/telephony/java/android/telephony/ims/ImsServiceProxy.java b/telephony/java/android/telephony/ims/ImsServiceProxy.java
index 38ea6e6ff9a0..a75cd86dcf07 100644
--- a/telephony/java/android/telephony/ims/ImsServiceProxy.java
+++ b/telephony/java/android/telephony/ims/ImsServiceProxy.java
@@ -120,7 +120,7 @@ public class ImsServiceProxy extends ImsServiceProxyCompat implements IRcsFeatur
public int startSession(PendingIntent incomingCallIntent, IImsRegistrationListener listener)
throws RemoteException {
synchronized (mLock) {
- checkBinderConnection();
+ checkServiceIsReady();
return getServiceInterface(mBinder).startSession(mSlotId, mSupportedFeature,
incomingCallIntent, listener);
}
@@ -129,7 +129,7 @@ public class ImsServiceProxy extends ImsServiceProxyCompat implements IRcsFeatur
@Override
public void endSession(int sessionId) throws RemoteException {
synchronized (mLock) {
- checkBinderConnection();
+ checkServiceIsReady();
getServiceInterface(mBinder).endSession(mSlotId, mSupportedFeature, sessionId);
}
}
@@ -138,7 +138,7 @@ public class ImsServiceProxy extends ImsServiceProxyCompat implements IRcsFeatur
public boolean isConnected(int callServiceType, int callType)
throws RemoteException {
synchronized (mLock) {
- checkBinderConnection();
+ checkServiceIsReady();
return getServiceInterface(mBinder).isConnected(mSlotId, mSupportedFeature,
callServiceType, callType);
}
@@ -147,7 +147,7 @@ public class ImsServiceProxy extends ImsServiceProxyCompat implements IRcsFeatur
@Override
public boolean isOpened() throws RemoteException {
synchronized (mLock) {
- checkBinderConnection();
+ checkServiceIsReady();
return getServiceInterface(mBinder).isOpened(mSlotId, mSupportedFeature);
}
}
@@ -156,7 +156,7 @@ public class ImsServiceProxy extends ImsServiceProxyCompat implements IRcsFeatur
public void addRegistrationListener(IImsRegistrationListener listener)
throws RemoteException {
synchronized (mLock) {
- checkBinderConnection();
+ checkServiceIsReady();
getServiceInterface(mBinder).addRegistrationListener(mSlotId, mSupportedFeature,
listener);
}
@@ -166,7 +166,7 @@ public class ImsServiceProxy extends ImsServiceProxyCompat implements IRcsFeatur
public void removeRegistrationListener(IImsRegistrationListener listener)
throws RemoteException {
synchronized (mLock) {
- checkBinderConnection();
+ checkServiceIsReady();
getServiceInterface(mBinder).removeRegistrationListener(mSlotId, mSupportedFeature,
listener);
}
@@ -176,7 +176,7 @@ public class ImsServiceProxy extends ImsServiceProxyCompat implements IRcsFeatur
public ImsCallProfile createCallProfile(int sessionId, int callServiceType, int callType)
throws RemoteException {
synchronized (mLock) {
- checkBinderConnection();
+ checkServiceIsReady();
return getServiceInterface(mBinder).createCallProfile(mSlotId, mSupportedFeature,
sessionId, callServiceType, callType);
}
@@ -186,7 +186,7 @@ public class ImsServiceProxy extends ImsServiceProxyCompat implements IRcsFeatur
public IImsCallSession createCallSession(int sessionId, ImsCallProfile profile,
IImsCallSessionListener listener) throws RemoteException {
synchronized (mLock) {
- checkBinderConnection();
+ checkServiceIsReady();
return getServiceInterface(mBinder).createCallSession(mSlotId, mSupportedFeature,
sessionId, profile, listener);
}
@@ -196,7 +196,7 @@ public class ImsServiceProxy extends ImsServiceProxyCompat implements IRcsFeatur
public IImsCallSession getPendingCallSession(int sessionId, String callId)
throws RemoteException {
synchronized (mLock) {
- checkBinderConnection();
+ checkServiceIsReady();
return getServiceInterface(mBinder).getPendingCallSession(mSlotId, mSupportedFeature,
sessionId, callId);
}
@@ -205,7 +205,7 @@ public class ImsServiceProxy extends ImsServiceProxyCompat implements IRcsFeatur
@Override
public IImsUt getUtInterface() throws RemoteException {
synchronized (mLock) {
- checkBinderConnection();
+ checkServiceIsReady();
return getServiceInterface(mBinder).getUtInterface(mSlotId, mSupportedFeature);
}
}
@@ -213,7 +213,7 @@ public class ImsServiceProxy extends ImsServiceProxyCompat implements IRcsFeatur
@Override
public IImsConfig getConfigInterface() throws RemoteException {
synchronized (mLock) {
- checkBinderConnection();
+ checkServiceIsReady();
return getServiceInterface(mBinder).getConfigInterface(mSlotId, mSupportedFeature);
}
}
@@ -221,7 +221,7 @@ public class ImsServiceProxy extends ImsServiceProxyCompat implements IRcsFeatur
@Override
public void turnOnIms() throws RemoteException {
synchronized (mLock) {
- checkBinderConnection();
+ checkServiceIsReady();
getServiceInterface(mBinder).turnOnIms(mSlotId, mSupportedFeature);
}
}
@@ -229,7 +229,7 @@ public class ImsServiceProxy extends ImsServiceProxyCompat implements IRcsFeatur
@Override
public void turnOffIms() throws RemoteException {
synchronized (mLock) {
- checkBinderConnection();
+ checkServiceIsReady();
getServiceInterface(mBinder).turnOffIms(mSlotId, mSupportedFeature);
}
}
@@ -237,7 +237,7 @@ public class ImsServiceProxy extends ImsServiceProxyCompat implements IRcsFeatur
@Override
public IImsEcbm getEcbmInterface() throws RemoteException {
synchronized (mLock) {
- checkBinderConnection();
+ checkServiceIsReady();
return getServiceInterface(mBinder).getEcbmInterface(mSlotId, mSupportedFeature);
}
}
@@ -246,7 +246,7 @@ public class ImsServiceProxy extends ImsServiceProxyCompat implements IRcsFeatur
public void setUiTTYMode(int uiTtyMode, Message onComplete)
throws RemoteException {
synchronized (mLock) {
- checkBinderConnection();
+ checkServiceIsReady();
getServiceInterface(mBinder).setUiTTYMode(mSlotId, mSupportedFeature, uiTtyMode,
onComplete);
}
@@ -255,7 +255,7 @@ public class ImsServiceProxy extends ImsServiceProxyCompat implements IRcsFeatur
@Override
public IImsMultiEndpoint getMultiEndpointInterface() throws RemoteException {
synchronized (mLock) {
- checkBinderConnection();
+ checkServiceIsReady();
return getServiceInterface(mBinder).getMultiEndpointInterface(mSlotId,
mSupportedFeature);
}
@@ -264,7 +264,8 @@ public class ImsServiceProxy extends ImsServiceProxyCompat implements IRcsFeatur
@Override
public int getFeatureStatus() {
synchronized (mLock) {
- if (mFeatureStatusCached != null) {
+ if (isBinderAlive() && mFeatureStatusCached != null) {
+ Log.i(LOG_TAG, "getFeatureStatus - returning cached: " + mFeatureStatusCached);
return mFeatureStatusCached;
}
}
@@ -277,6 +278,7 @@ public class ImsServiceProxy extends ImsServiceProxyCompat implements IRcsFeatur
// Cache only non-null value for feature status.
mFeatureStatusCached = status;
}
+ Log.i(LOG_TAG, "getFeatureStatus - returning " + status);
return status;
}
@@ -301,10 +303,28 @@ public class ImsServiceProxy extends ImsServiceProxyCompat implements IRcsFeatur
mStatusCallback = c;
}
+ /**
+ * @return Returns true if the ImsService is ready to take commands, false otherwise. If this
+ * method returns false, it doesn't mean that the Binder connection is not available (use
+ * {@link #isBinderReady()} to check that), but that the ImsService is not accepting commands
+ * at this time.
+ *
+ * For example, for DSDS devices, only one slot can be {@link ImsFeature#STATE_READY} to take
+ * commands at a time, so the other slot must stay at {@link ImsFeature#STATE_NOT_AVAILABLE}.
+ */
+ public boolean isBinderReady() {
+ return isBinderAlive() && getFeatureStatus() == ImsFeature.STATE_READY;
+ }
+
@Override
public boolean isBinderAlive() {
- return mIsAvailable && getFeatureStatus() == ImsFeature.STATE_READY && mBinder != null &&
- mBinder.isBinderAlive();
+ return mIsAvailable && mBinder != null && mBinder.isBinderAlive();
+ }
+
+ protected void checkServiceIsReady() throws RemoteException {
+ if (!isBinderReady()) {
+ throw new RemoteException("ImsServiceProxy is not ready to accept commands.");
+ }
}
private IImsServiceController getServiceInterface(IBinder b) {
diff --git a/telephony/java/android/telephony/ims/feature/ImsFeature.java b/telephony/java/android/telephony/ims/feature/ImsFeature.java
index 988dd588ecad..395f1ccc7a29 100644
--- a/telephony/java/android/telephony/ims/feature/ImsFeature.java
+++ b/telephony/java/android/telephony/ims/feature/ImsFeature.java
@@ -150,7 +150,7 @@ public abstract class ImsFeature {
private void notifyFeatureState(@ImsState int state) {
if (mStatusCallback != null) {
try {
- Log.i(LOG_TAG, "notifying ImsFeatureState");
+ Log.i(LOG_TAG, "notifying ImsFeatureState=" + state);
mStatusCallback.notifyImsFeatureStatus(state);
} catch (RemoteException e) {
mStatusCallback = null;
diff --git a/wifi/java/android/net/wifi/RttManager.java b/wifi/java/android/net/wifi/RttManager.java
index ff632a5cdc7c..b133a44d0117 100644
--- a/wifi/java/android/net/wifi/RttManager.java
+++ b/wifi/java/android/net/wifi/RttManager.java
@@ -660,10 +660,10 @@ public class RttManager {
@Deprecated
public int tx_rate;
- /** average transmit rate. Unit (100kbps). */
+ /** average transmit rate. Unit (kbps). */
public int txRate;
- /** average receiving rate Unit (100kbps). */
+ /** average receiving rate Unit (kbps). */
public int rxRate;
/**
@@ -673,7 +673,7 @@ public class RttManager {
@Deprecated
public long rtt_ns;
- /** average round trip time in 0.1 nano second. */
+ /** average round trip time in picoseconds. */
public long rtt;
/**
@@ -683,7 +683,7 @@ public class RttManager {
@Deprecated
public long rtt_sd_ns;
- /** standard deviation of RTT in 0.1 ns. */
+ /** standard deviation of RTT in picoseconds. */
public long rttStandardDeviation;
/**
@@ -693,7 +693,7 @@ public class RttManager {
@Deprecated
public long rtt_spread_ns;
- /** spread (i.e. max - min) RTT in 0.1 ns. */
+ /** spread (i.e. max - min) RTT in picoseconds. */
public long rttSpread;
/**
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index e31a74b42b14..f7333e281982 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -839,6 +839,10 @@ public class WifiConfiguration implements Parcelable {
*/
public static final int NETWORK_SELECTION_ENABLE = 0;
/**
+ * The starting index for network selection disabled reasons
+ */
+ public static final int NETWORK_SELECTION_DISABLED_STARTING_INDEX = 1;
+ /**
* @deprecated it is not used any more.
* This network is disabled because higher layer (>2) network is bad
*/