summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.txt9
-rw-r--r--api/system-current.txt9
-rw-r--r--api/test-current.txt9
-rw-r--r--core/java/android/app/ActivityManager.java10
-rw-r--r--core/java/android/app/ActivityOptions.java8
-rw-r--r--core/java/android/app/ResourcesManager.java43
-rw-r--r--core/java/android/content/pm/PackageManager.java8
-rw-r--r--core/java/android/service/autofill/SaveInfo.java57
-rw-r--r--core/java/android/view/accessibility/AccessibilityNodeInfo.java23
-rw-r--r--core/java/com/android/internal/os/ZygoteInit.java20
-rw-r--r--core/res/res/values/strings.xml8
-rw-r--r--core/res/res/values/symbols.xml2
-rw-r--r--media/java/android/media/MediaPlayer.java12
-rw-r--r--packages/PrintRecommendationService/res/values/strings.xml1
-rw-r--r--packages/PrintRecommendationService/src/com/android/printservice/recommendation/RecommendationServiceImpl.java9
-rw-r--r--packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/google/CloudPrintPlugin.java168
-rw-r--r--services/autofill/java/com/android/server/autofill/Session.java3
-rw-r--r--services/autofill/java/com/android/server/autofill/ui/SaveUi.java57
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java4
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerShellCommand.java13
-rw-r--r--services/core/java/com/android/server/am/ActivityStack.java33
-rw-r--r--services/core/java/com/android/server/am/ActivityStackSupervisor.java56
-rw-r--r--services/core/java/com/android/server/am/ActivityStarter.java20
-rw-r--r--services/core/java/com/android/server/fingerprint/FingerprintService.java19
-rw-r--r--services/core/java/com/android/server/wm/BoundsAnimationController.java4
25 files changed, 446 insertions, 159 deletions
diff --git a/api/current.txt b/api/current.txt
index 2723f4dfd106..cbe4195e4c26 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -10616,6 +10616,7 @@ package android.content.pm {
field public static final int DONT_KILL_APP = 1; // 0x1
field public static final java.lang.String EXTRA_VERIFICATION_ID = "android.content.pm.extra.VERIFICATION_ID";
field public static final java.lang.String EXTRA_VERIFICATION_RESULT = "android.content.pm.extra.VERIFICATION_RESULT";
+ field public static final java.lang.String FEATURE_ACTIVITIES_ON_SECONDARY_DISPLAYS = "android.software.activities_on_secondary_displays";
field public static final java.lang.String FEATURE_APP_WIDGETS = "android.software.app_widgets";
field public static final java.lang.String FEATURE_AUDIO_LOW_LATENCY = "android.hardware.audio.low_latency";
field public static final java.lang.String FEATURE_AUDIO_OUTPUT = "android.hardware.audio.output";
@@ -22857,6 +22858,7 @@ package android.media {
field public static final int MEDIA_ERROR_TIMED_OUT = -110; // 0xffffff92
field public static final int MEDIA_ERROR_UNKNOWN = 1; // 0x1
field public static final int MEDIA_ERROR_UNSUPPORTED = -1010; // 0xfffffc0e
+ field public static final int MEDIA_INFO_AUDIO_NOT_PLAYING = 804; // 0x324
field public static final int MEDIA_INFO_BAD_INTERLEAVING = 800; // 0x320
field public static final int MEDIA_INFO_BUFFERING_END = 702; // 0x2be
field public static final int MEDIA_INFO_BUFFERING_START = 701; // 0x2bd
@@ -22865,6 +22867,7 @@ package android.media {
field public static final int MEDIA_INFO_SUBTITLE_TIMED_OUT = 902; // 0x386
field public static final int MEDIA_INFO_UNKNOWN = 1; // 0x1
field public static final int MEDIA_INFO_UNSUPPORTED_SUBTITLE = 901; // 0x385
+ field public static final int MEDIA_INFO_VIDEO_NOT_PLAYING = 805; // 0x325
field public static final int MEDIA_INFO_VIDEO_RENDERING_START = 3; // 0x3
field public static final int MEDIA_INFO_VIDEO_TRACK_LAGGING = 700; // 0x2bc
field public static final java.lang.String MEDIA_MIMETYPE_TEXT_SUBRIP = "application/x-subrip";
@@ -37038,11 +37041,11 @@ package android.service.autofill {
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.service.autofill.SaveInfo> CREATOR;
field public static final int SAVE_DATA_TYPE_ADDRESS = 2; // 0x2
- field public static final int SAVE_DATA_TYPE_CREDIT_CARD = 3; // 0x3
- field public static final int SAVE_DATA_TYPE_EMAIL_ADDRESS = 5; // 0x5
+ field public static final int SAVE_DATA_TYPE_CREDIT_CARD = 4; // 0x4
+ field public static final int SAVE_DATA_TYPE_EMAIL_ADDRESS = 16; // 0x10
field public static final int SAVE_DATA_TYPE_GENERIC = 0; // 0x0
field public static final int SAVE_DATA_TYPE_PASSWORD = 1; // 0x1
- field public static final int SAVE_DATA_TYPE_USERNAME = 4; // 0x4
+ field public static final int SAVE_DATA_TYPE_USERNAME = 8; // 0x8
}
public static final class SaveInfo.Builder {
diff --git a/api/system-current.txt b/api/system-current.txt
index 895a5d4daccf..34f05da5b367 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -11300,6 +11300,7 @@ package android.content.pm {
field public static final java.lang.String EXTRA_REQUEST_PERMISSIONS_RESULTS = "android.content.pm.extra.REQUEST_PERMISSIONS_RESULTS";
field public static final java.lang.String EXTRA_VERIFICATION_ID = "android.content.pm.extra.VERIFICATION_ID";
field public static final java.lang.String EXTRA_VERIFICATION_RESULT = "android.content.pm.extra.VERIFICATION_RESULT";
+ field public static final java.lang.String FEATURE_ACTIVITIES_ON_SECONDARY_DISPLAYS = "android.software.activities_on_secondary_displays";
field public static final java.lang.String FEATURE_APP_WIDGETS = "android.software.app_widgets";
field public static final java.lang.String FEATURE_AUDIO_LOW_LATENCY = "android.hardware.audio.low_latency";
field public static final java.lang.String FEATURE_AUDIO_OUTPUT = "android.hardware.audio.output";
@@ -24682,6 +24683,7 @@ package android.media {
field public static final int MEDIA_ERROR_TIMED_OUT = -110; // 0xffffff92
field public static final int MEDIA_ERROR_UNKNOWN = 1; // 0x1
field public static final int MEDIA_ERROR_UNSUPPORTED = -1010; // 0xfffffc0e
+ field public static final int MEDIA_INFO_AUDIO_NOT_PLAYING = 804; // 0x324
field public static final int MEDIA_INFO_BAD_INTERLEAVING = 800; // 0x320
field public static final int MEDIA_INFO_BUFFERING_END = 702; // 0x2be
field public static final int MEDIA_INFO_BUFFERING_START = 701; // 0x2bd
@@ -24690,6 +24692,7 @@ package android.media {
field public static final int MEDIA_INFO_SUBTITLE_TIMED_OUT = 902; // 0x386
field public static final int MEDIA_INFO_UNKNOWN = 1; // 0x1
field public static final int MEDIA_INFO_UNSUPPORTED_SUBTITLE = 901; // 0x385
+ field public static final int MEDIA_INFO_VIDEO_NOT_PLAYING = 805; // 0x325
field public static final int MEDIA_INFO_VIDEO_RENDERING_START = 3; // 0x3
field public static final int MEDIA_INFO_VIDEO_TRACK_LAGGING = 700; // 0x2bc
field public static final java.lang.String MEDIA_MIMETYPE_TEXT_SUBRIP = "application/x-subrip";
@@ -40134,11 +40137,11 @@ package android.service.autofill {
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.service.autofill.SaveInfo> CREATOR;
field public static final int SAVE_DATA_TYPE_ADDRESS = 2; // 0x2
- field public static final int SAVE_DATA_TYPE_CREDIT_CARD = 3; // 0x3
- field public static final int SAVE_DATA_TYPE_EMAIL_ADDRESS = 5; // 0x5
+ field public static final int SAVE_DATA_TYPE_CREDIT_CARD = 4; // 0x4
+ field public static final int SAVE_DATA_TYPE_EMAIL_ADDRESS = 16; // 0x10
field public static final int SAVE_DATA_TYPE_GENERIC = 0; // 0x0
field public static final int SAVE_DATA_TYPE_PASSWORD = 1; // 0x1
- field public static final int SAVE_DATA_TYPE_USERNAME = 4; // 0x4
+ field public static final int SAVE_DATA_TYPE_USERNAME = 8; // 0x8
}
public static final class SaveInfo.Builder {
diff --git a/api/test-current.txt b/api/test-current.txt
index 67416fba10cf..ac49a9bc720f 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -10655,6 +10655,7 @@ package android.content.pm {
field public static final int DONT_KILL_APP = 1; // 0x1
field public static final java.lang.String EXTRA_VERIFICATION_ID = "android.content.pm.extra.VERIFICATION_ID";
field public static final java.lang.String EXTRA_VERIFICATION_RESULT = "android.content.pm.extra.VERIFICATION_RESULT";
+ field public static final java.lang.String FEATURE_ACTIVITIES_ON_SECONDARY_DISPLAYS = "android.software.activities_on_secondary_displays";
field public static final java.lang.String FEATURE_APP_WIDGETS = "android.software.app_widgets";
field public static final java.lang.String FEATURE_AUDIO_LOW_LATENCY = "android.hardware.audio.low_latency";
field public static final java.lang.String FEATURE_AUDIO_OUTPUT = "android.hardware.audio.output";
@@ -22970,6 +22971,7 @@ package android.media {
field public static final int MEDIA_ERROR_TIMED_OUT = -110; // 0xffffff92
field public static final int MEDIA_ERROR_UNKNOWN = 1; // 0x1
field public static final int MEDIA_ERROR_UNSUPPORTED = -1010; // 0xfffffc0e
+ field public static final int MEDIA_INFO_AUDIO_NOT_PLAYING = 804; // 0x324
field public static final int MEDIA_INFO_BAD_INTERLEAVING = 800; // 0x320
field public static final int MEDIA_INFO_BUFFERING_END = 702; // 0x2be
field public static final int MEDIA_INFO_BUFFERING_START = 701; // 0x2bd
@@ -22978,6 +22980,7 @@ package android.media {
field public static final int MEDIA_INFO_SUBTITLE_TIMED_OUT = 902; // 0x386
field public static final int MEDIA_INFO_UNKNOWN = 1; // 0x1
field public static final int MEDIA_INFO_UNSUPPORTED_SUBTITLE = 901; // 0x385
+ field public static final int MEDIA_INFO_VIDEO_NOT_PLAYING = 805; // 0x325
field public static final int MEDIA_INFO_VIDEO_RENDERING_START = 3; // 0x3
field public static final int MEDIA_INFO_VIDEO_TRACK_LAGGING = 700; // 0x2bc
field public static final java.lang.String MEDIA_MIMETYPE_TEXT_SUBRIP = "application/x-subrip";
@@ -37196,11 +37199,11 @@ package android.service.autofill {
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.service.autofill.SaveInfo> CREATOR;
field public static final int SAVE_DATA_TYPE_ADDRESS = 2; // 0x2
- field public static final int SAVE_DATA_TYPE_CREDIT_CARD = 3; // 0x3
- field public static final int SAVE_DATA_TYPE_EMAIL_ADDRESS = 5; // 0x5
+ field public static final int SAVE_DATA_TYPE_CREDIT_CARD = 4; // 0x4
+ field public static final int SAVE_DATA_TYPE_EMAIL_ADDRESS = 16; // 0x10
field public static final int SAVE_DATA_TYPE_GENERIC = 0; // 0x0
field public static final int SAVE_DATA_TYPE_PASSWORD = 1; // 0x1
- field public static final int SAVE_DATA_TYPE_USERNAME = 4; // 0x4
+ field public static final int SAVE_DATA_TYPE_USERNAME = 8; // 0x8
}
public static final class SaveInfo.Builder {
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index e2883873752c..4004bd6686b1 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -1118,16 +1118,6 @@ public class ActivityManager {
}
/**
- * Returns true if the system supports running activities on secondary displays.
- * @hide
- */
- static public boolean supportsMultiDisplay() {
- return !isLowRamDeviceStatic()
- && Resources.getSystem().getBoolean(
- com.android.internal.R.bool.config_supportsMultiDisplay);
- }
-
- /**
* Return the maximum number of actions that will be displayed in the picture-in-picture UI when
* the user interacts with the activity currently in picture-in-picture mode.
*/
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index aa7cdf7b475e..02d18841f489 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -155,6 +155,7 @@ public class ActivityOptions {
/**
* The display id the activity should be launched into.
+ * @see #setLaunchDisplayId(int)
* @hide
*/
private static final String KEY_LAUNCH_DISPLAY_ID = "android.activity.launchDisplayId";
@@ -1038,6 +1039,7 @@ public class ActivityOptions {
* Gets the id of the display where activity should be launched.
* @return The id of the display where activity should be launched,
* {@link android.view.Display#INVALID_DISPLAY} if not set.
+ * @see #setLaunchDisplayId(int)
*/
public int getLaunchDisplayId() {
return mLaunchDisplayId;
@@ -1045,6 +1047,12 @@ public class ActivityOptions {
/**
* Sets the id of the display where activity should be launched.
+ * An app can launch activities on public displays or private displays that are owned by the app
+ * or where an app already has activities. Otherwise, trying to launch on a private display
+ * or providing an invalid display id will result in an exception.
+ * <p>
+ * Setting launch display id will be ignored on devices that don't have
+ * {@link android.content.pm.PackageManager#FEATURE_ACTIVITIES_ON_SECONDARY_DISPLAYS}.
* @param launchDisplayId The id of the display where the activity should be launched.
* @return {@code this} {@link ActivityOptions} instance.
*/
diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java
index d620a81e985b..3191eec03ffa 100644
--- a/core/java/android/app/ResourcesManager.java
+++ b/core/java/android/app/ResourcesManager.java
@@ -44,6 +44,8 @@ import com.android.internal.util.ArrayUtils;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.Map;
import java.util.Objects;
import java.util.WeakHashMap;
import java.util.function.Predicate;
@@ -114,7 +116,7 @@ public class ResourcesManager {
* A cache of DisplayId, Resources to Display. These display adjustments associated with these
* {@link Display}s will change as the resources change.
*/
- private final ArrayMap<Pair<Integer, Resources>, WeakReference<Display>> mResourceDisplays =
+ private final ArrayMap<Pair<Integer, ResourcesKey>, WeakReference<Display>> mResourceDisplays =
new ArrayMap<>();
public static ResourcesManager getInstance() {
@@ -137,10 +139,7 @@ public class ResourcesManager {
for (int i = 0; i < mResourceImpls.size();) {
final ResourcesKey key = mResourceImpls.keyAt(i);
if (key.isPathReferenced(path)) {
- final ResourcesImpl res = mResourceImpls.removeAt(i).get();
- if (res != null) {
- res.flushLayoutCache();
- }
+ cleanupResourceImpl(key);
count++;
} else {
i++;
@@ -251,8 +250,14 @@ public class ResourcesManager {
* @param resources The {@link Resources} backing the display adjustments.
*/
public Display getAdjustedDisplay(final int displayId, Resources resources) {
- final Pair<Integer, Resources> key = Pair.create(displayId, resources);
synchronized (this) {
+ // Note that the ResourcesKey might be {@code null} in the case that the
+ // {@link Resources} is actually from {@link Resources#getSystem}. In this case, it is
+ // not managed by {@link ResourcesManager}, but we still want to cache the display
+ // object.
+ final Pair<Integer, ResourcesKey> key = Pair.create(displayId,
+ findKeyForResourceImplLocked(resources.getImpl()));
+
WeakReference<Display> wd = mResourceDisplays.get(key);
if (wd != null) {
final Display display = wd.get();
@@ -273,6 +278,32 @@ public class ResourcesManager {
}
}
+ private void cleanupResourceImpl(ResourcesKey removedKey) {
+ // Remove any resource to display mapping based on this key.
+ final Iterator<Map.Entry<Pair<Integer, ResourcesKey>, WeakReference<Display>>> iter =
+ mResourceDisplays.entrySet().iterator();
+ while (iter.hasNext()) {
+ final Map.Entry<Pair<Integer, ResourcesKey>, WeakReference<Display>> entry =
+ iter.next();
+ final ResourcesKey key = entry.getKey().second;
+
+ // Do not touch system resource displays (indicated by a {@code null} key) or
+ // non-matching keys.
+ if (key == null || !key.equals(removedKey)) {
+ continue;
+ }
+
+ iter.remove();
+ }
+
+ // Remove resource key to resource impl mapping and flush cache
+ final ResourcesImpl res = mResourceImpls.remove(removedKey).get();
+
+ if (res != null) {
+ res.flushLayoutCache();
+ }
+ }
+
/**
* Creates an AssetManager from the paths within the ResourcesKey.
*
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 50e3e6863d4f..fa3e4e98b551 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -2285,6 +2285,14 @@ public abstract class PackageManager {
/**
* Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}:
+ * The device supports running activities on secondary displays.
+ */
+ @SdkConstant(SdkConstantType.FEATURE)
+ public static final String FEATURE_ACTIVITIES_ON_SECONDARY_DISPLAYS
+ = "android.software.activities_on_secondary_displays";
+
+ /**
+ * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}:
* The device supports creating secondary users and managed profiles via
* {@link DevicePolicyManager}.
*/
diff --git a/core/java/android/service/autofill/SaveInfo.java b/core/java/android/service/autofill/SaveInfo.java
index f75b7afe4c46..4ad0f086691a 100644
--- a/core/java/android/service/autofill/SaveInfo.java
+++ b/core/java/android/service/autofill/SaveInfo.java
@@ -25,6 +25,7 @@ import android.content.IntentSender;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
+import android.util.DebugUtils;
import android.view.autofill.AutofillId;
import android.view.autofill.AutofillManager;
import android.view.autofill.AutofillValue;
@@ -111,52 +112,41 @@ public final class SaveInfo implements Parcelable {
* Type used on when the service can save the contents of an activity, but cannot describe what
* the content is for.
*/
- public static final int SAVE_DATA_TYPE_GENERIC = 0;
+ public static final int SAVE_DATA_TYPE_GENERIC = 0x0;
/**
* Type used when the {@link FillResponse} represents user credentials that have a password.
*/
- public static final int SAVE_DATA_TYPE_PASSWORD = 1;
+ public static final int SAVE_DATA_TYPE_PASSWORD = 0x01;
/**
* Type used on when the {@link FillResponse} represents a physical address (such as street,
* city, state, etc).
*/
- public static final int SAVE_DATA_TYPE_ADDRESS = 2;
+ public static final int SAVE_DATA_TYPE_ADDRESS = 0x02;
/**
* Type used when the {@link FillResponse} represents a credit card.
*/
- public static final int SAVE_DATA_TYPE_CREDIT_CARD = 3;
+ public static final int SAVE_DATA_TYPE_CREDIT_CARD = 0x04;
/**
* Type used when the {@link FillResponse} represents just an username, without a password.
*/
- public static final int SAVE_DATA_TYPE_USERNAME = 4;
+ public static final int SAVE_DATA_TYPE_USERNAME = 0x08;
/**
* Type used when the {@link FillResponse} represents just an email address, without a password.
*/
- public static final int SAVE_DATA_TYPE_EMAIL_ADDRESS = 5;
+ public static final int SAVE_DATA_TYPE_EMAIL_ADDRESS = 0x10;
- private final @SaveDataType int mType;
+ private final int mType;
private final CharSequence mNegativeActionTitle;
private final IntentSender mNegativeActionListener;
private final AutofillId[] mRequiredIds;
private final AutofillId[] mOptionalIds;
private final CharSequence mDescription;
- /** @hide */
- @IntDef({
- SAVE_DATA_TYPE_GENERIC,
- SAVE_DATA_TYPE_PASSWORD,
- SAVE_DATA_TYPE_ADDRESS,
- SAVE_DATA_TYPE_CREDIT_CARD
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface SaveDataType {
- }
-
private SaveInfo(Builder builder) {
mType = builder.mType;
mNegativeActionTitle = builder.mNegativeActionTitle;
@@ -201,7 +191,7 @@ public final class SaveInfo implements Parcelable {
*/
public static final class Builder {
- private final @SaveDataType int mType;
+ private final int mType;
private CharSequence mNegativeActionTitle;
private IntentSender mNegativeActionListener;
// TODO(b/33197203): make mRequiredIds final once addSavableIds() is gone
@@ -213,32 +203,24 @@ public final class SaveInfo implements Parcelable {
/**
* Creates a new builder.
*
- * @param type the type of information the associated {@link FillResponse} represents. Must
- * be {@link SaveInfo#SAVE_DATA_TYPE_GENERIC}, {@link SaveInfo#SAVE_DATA_TYPE_PASSWORD},
- * {@link SaveInfo#SAVE_DATA_TYPE_ADDRESS}, or {@link SaveInfo#SAVE_DATA_TYPE_CREDIT_CARD};
- * otherwise it will assume {@link SaveInfo#SAVE_DATA_TYPE_GENERIC}.
+ * @param type the type of information the associated {@link FillResponse} represents, can
+ * be any combination of {@link SaveInfo#SAVE_DATA_TYPE_GENERIC},
+ * {@link SaveInfo#SAVE_DATA_TYPE_PASSWORD},
+ * {@link SaveInfo#SAVE_DATA_TYPE_ADDRESS}, {@link SaveInfo#SAVE_DATA_TYPE_CREDIT_CARD},
+ * {@link SaveInfo#SAVE_DATA_TYPE_USERNAME}, or
+ * {@link SaveInfo#SAVE_DATA_TYPE_EMAIL_ADDRESS}.
* @param requiredIds ids of all required views that will trigger a save request.
*
* <p>See {@link SaveInfo} for more info.
*
* @throws IllegalArgumentException if {@code requiredIds} is {@code null} or empty.
*/
- public Builder(@SaveDataType int type, @NonNull AutofillId[] requiredIds) {
+ public Builder(int type, @NonNull AutofillId[] requiredIds) {
if (false) {// TODO(b/33197203): re-move when clients use it
Preconditions.checkArgument(requiredIds != null && requiredIds.length > 0,
"must have at least one required id: " + Arrays.toString(requiredIds));
}
- switch (type) {
- case SAVE_DATA_TYPE_PASSWORD:
- case SAVE_DATA_TYPE_ADDRESS:
- case SAVE_DATA_TYPE_CREDIT_CARD:
- case SAVE_DATA_TYPE_USERNAME:
- case SAVE_DATA_TYPE_EMAIL_ADDRESS:
- mType = type;
- break;
- default:
- mType = SAVE_DATA_TYPE_GENERIC;
- }
+ mType = type;
mRequiredIds = requiredIds;
}
@@ -248,7 +230,7 @@ public final class SaveInfo implements Parcelable {
* // TODO(b/33197203): make sure is removed when clients migrated
*/
@Deprecated
- public Builder(@SaveDataType int type) {
+ public Builder(int type) {
this(type, null);
}
@@ -355,7 +337,8 @@ public final class SaveInfo implements Parcelable {
public String toString() {
if (!DEBUG) return super.toString();
- return new StringBuilder("SaveInfo: [type=").append(mType)
+ return new StringBuilder("SaveInfo: [type=")
+ .append(DebugUtils.flagsToString(SaveInfo.class, "SAVE_DATA_TYPE_", mType))
.append(", requiredIds=").append(Arrays.toString(mRequiredIds))
.append(", optionalIds=").append(Arrays.toString(mOptionalIds))
.append(", description=").append(mDescription)
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index 50f17e089585..255574f8cee7 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -3073,16 +3073,19 @@ public class AccessibilityNodeInfo implements Parcelable {
if (mActions != null && !mActions.isEmpty()) {
final int actionCount = mActions.size();
- parcel.writeInt(actionCount);
+ int nonLegacyActionCount = 0;
int defaultLegacyStandardActions = 0;
for (int i = 0; i < actionCount; i++) {
AccessibilityAction action = mActions.get(i);
if (isDefaultLegacyStandardAction(action)) {
defaultLegacyStandardActions |= action.getId();
+ } else {
+ nonLegacyActionCount++;
}
}
parcel.writeInt(defaultLegacyStandardActions);
+ parcel.writeInt(nonLegacyActionCount);
for (int i = 0; i < actionCount; i++) {
AccessibilityAction action = mActions.get(i);
@@ -3093,6 +3096,7 @@ public class AccessibilityNodeInfo implements Parcelable {
}
} else {
parcel.writeInt(0);
+ parcel.writeInt(0);
}
parcel.writeInt(mMaxTextLength);
@@ -3270,16 +3274,13 @@ public class AccessibilityNodeInfo implements Parcelable {
mBoundsInScreen.left = parcel.readInt();
mBoundsInScreen.right = parcel.readInt();
- final int actionCount = parcel.readInt();
- if (actionCount > 0) {
- final int legacyStandardActions = parcel.readInt();
- addLegacyStandardActions(legacyStandardActions);
- final int nonLegacyActionCount = actionCount - Integer.bitCount(legacyStandardActions);
- for (int i = 0; i < nonLegacyActionCount; i++) {
- final AccessibilityAction action = new AccessibilityAction(
- parcel.readInt(), parcel.readCharSequence());
- addActionUnchecked(action);
- }
+ final int legacyStandardActions = parcel.readInt();
+ addLegacyStandardActions(legacyStandardActions);
+ final int nonLegacyActionCount = parcel.readInt();
+ for (int i = 0; i < nonLegacyActionCount; i++) {
+ final AccessibilityAction action = new AccessibilityAction(
+ parcel.readInt(), parcel.readCharSequence());
+ addActionUnchecked(action);
}
mMaxTextLength = parcel.readInt();
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 67bce8c59309..44fa99df7b73 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -26,7 +26,9 @@ import android.icu.text.DecimalFormatSymbols;
import android.icu.util.ULocale;
import android.net.LocalServerSocket;
import android.opengl.EGL14;
+import android.os.Build;
import android.os.IInstalld;
+import android.os.Environment;
import android.os.Process;
import android.os.RemoteException;
import android.os.Seccomp;
@@ -60,6 +62,7 @@ import dalvik.system.ZygoteHooks;
import libcore.io.IoUtils;
import java.io.BufferedReader;
+import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
@@ -457,6 +460,23 @@ public class ZygoteInit {
final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
if (systemServerClasspath != null) {
performSystemServerDexOpt(systemServerClasspath);
+ // Capturing profiles is only supported for debug or eng builds since selinux normally
+ // prevents it.
+ boolean profileSystemServer = SystemProperties.getBoolean(
+ "dalvik.vm.profilesystemserver", false);
+ if (profileSystemServer && (Build.IS_USERDEBUG || Build.IS_ENG)) {
+ try {
+ File profileDir = Environment.getDataProfilesDePackageDirectory(
+ Process.SYSTEM_UID, "system_server");
+ File profile = new File(profileDir, "primary.prof");
+ profile.getParentFile().mkdirs();
+ profile.createNewFile();
+ String[] codePaths = systemServerClasspath.split(":");
+ VMRuntime.registerAppInfo(profile.getPath(), codePaths);
+ } catch (Exception e) {
+ Log.wtf(TAG, "Failed to set up system server profile", e);
+ }
+ }
}
if (parsedArgs.invokeWith != null) {
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index ae28797c32aa..75de4dad3390 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -4594,6 +4594,14 @@
<!-- Title for the autofill save dialog shown when the the contents of the activity can be saved
by an autofill service, and the service does knows what the activity represents (for example, credit card info) [CHAR LIMIT=NONE] -->
<string name="autofill_save_title_with_type">Save <xliff:g id="type" example="Credit Card">%1$s</xliff:g> to <xliff:g id="label" example="MyPass">%2$s</xliff:g>?</string>
+ <!-- Title for the autofill save dialog shown when the the contents of the activity can be saved
+ by an autofill service, and the service does knows what the activity represents, and it represents 2 types of
+ data (for example, password and credit card info) [CHAR LIMIT=NONE] -->
+ <string name="autofill_save_title_with_2types">Save <xliff:g id="type" example="Password">%1$s</xliff:g>, <xliff:g id="type" example="Credit Card">%2$s</xliff:g> to <xliff:g id="label" example="MyPass">%3$s</xliff:g>?</string>
+ <!-- Title for the autofill save dialog shown when the the contents of the activity can be saved
+ by an autofill service, and the service does knows what the activity represents, and it represents 3 types of
+ data (for example, username, password and credit card info) [CHAR LIMIT=NONE] -->
+ <string name="autofill_save_title_with_3types">Save <xliff:g id="type" example="Username">%1$s</xliff:g>, <xliff:g id="type" example="Password">%2$s</xliff:g>, <xliff:g id="type" example="Credit Card">%3$s</xliff:g> to <xliff:g id="label" example="MyPass">%4$s</xliff:g>?</string>
<!-- Label for the autofill save button [CHAR LIMIT=NONE] -->
<string name="autofill_save_yes">Save</string>
<!-- Label for the autofill cancel button [CHAR LIMIT=NONE] -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 89c39430bd23..7cb9ba8cd64b 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2881,6 +2881,8 @@
<java-symbol type="string" name="autofill_picker_accessibility_title " />
<java-symbol type="string" name="autofill_save_title" />
<java-symbol type="string" name="autofill_save_title_with_type" />
+ <java-symbol type="string" name="autofill_save_title_with_2types" />
+ <java-symbol type="string" name="autofill_save_title_with_3types" />
<java-symbol type="string" name="autofill_save_yes" />
<java-symbol type="string" name="autofill_save_no" />
<java-symbol type="string" name="autofill_save_type_password" />
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index e6f3cfbb07d2..71a968b4d4b5 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -3822,6 +3822,18 @@ public class MediaPlayer extends PlayerBase
*/
public static final int MEDIA_INFO_EXTERNAL_METADATA_UPDATE = 803;
+ /** Informs that audio is not playing. Note that playback of the video
+ * is not interrupted.
+ * @see android.media.MediaPlayer.OnInfoListener
+ */
+ public static final int MEDIA_INFO_AUDIO_NOT_PLAYING = 804;
+
+ /** Informs that video is not playing. Note that playback of the audio
+ * is not interrupted.
+ * @see android.media.MediaPlayer.OnInfoListener
+ */
+ public static final int MEDIA_INFO_VIDEO_NOT_PLAYING = 805;
+
/** Failed to handle timed text track properly.
* @see android.media.MediaPlayer.OnInfoListener
*
diff --git a/packages/PrintRecommendationService/res/values/strings.xml b/packages/PrintRecommendationService/res/values/strings.xml
index b6c45b7a23c8..2bab1b65529b 100644
--- a/packages/PrintRecommendationService/res/values/strings.xml
+++ b/packages/PrintRecommendationService/res/values/strings.xml
@@ -18,6 +18,7 @@
-->
<resources>
+ <string name="plugin_vendor_google_cloud_print">Cloud Print</string>
<string name="plugin_vendor_hp">HP</string>
<string name="plugin_vendor_lexmark">Lexmark</string>
<string name="plugin_vendor_brother">Brother</string>
diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/RecommendationServiceImpl.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/RecommendationServiceImpl.java
index e18ee90d39d7..128ed5085529 100644
--- a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/RecommendationServiceImpl.java
+++ b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/RecommendationServiceImpl.java
@@ -22,6 +22,7 @@ import android.printservice.recommendation.RecommendationInfo;
import android.printservice.recommendation.RecommendationService;
import android.util.Log;
+import com.android.printservice.recommendation.plugin.google.CloudPrintPlugin;
import com.android.printservice.recommendation.plugin.hp.HPRecommendationPlugin;
import com.android.printservice.recommendation.plugin.mdnsFilter.MDNSFilterPlugin;
import com.android.printservice.recommendation.plugin.mdnsFilter.VendorConfig;
@@ -65,6 +66,14 @@ public class RecommendationServiceImpl extends RecommendationService
}
try {
+ mPlugins.add(new RemotePrintServicePlugin(new CloudPrintPlugin(this), this,
+ true));
+ } catch (Exception e) {
+ Log.e(LOG_TAG, "Could not initiate "
+ + getString(R.string.plugin_vendor_google_cloud_print) + " plugin", e);
+ }
+
+ try {
mPlugins.add(new RemotePrintServicePlugin(new HPRecommendationPlugin(this), this,
false));
} catch (Exception e) {
diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/google/CloudPrintPlugin.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/google/CloudPrintPlugin.java
new file mode 100644
index 000000000000..05b0c862ebd5
--- /dev/null
+++ b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/google/CloudPrintPlugin.java
@@ -0,0 +1,168 @@
+/*
+ * 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.printservice.recommendation.plugin.google;
+
+import static com.android.printservice.recommendation.util.MDNSUtils.ATTRIBUTE_TY;
+
+import android.annotation.NonNull;
+import android.annotation.StringRes;
+import android.content.Context;
+import android.util.ArrayMap;
+import android.util.Log;
+
+import com.android.printservice.recommendation.PrintServicePlugin;
+import com.android.printservice.recommendation.R;
+import com.android.printservice.recommendation.util.MDNSFilteredDiscovery;
+
+import java.net.Inet4Address;
+import java.net.InetAddress;
+import java.nio.charset.StandardCharsets;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Plugin detecting <a href="https://developers.google.com/cloud-print/docs/privet">Google Cloud
+ * Print</a> printers.
+ */
+public class CloudPrintPlugin implements PrintServicePlugin {
+ private static final String LOG_TAG = CloudPrintPlugin.class.getSimpleName();
+ private static final boolean DEBUG = false;
+
+ private static final String ATTRIBUTE_TXTVERS = "txtvers";
+ private static final String ATTRIBUTE_URL = "url";
+ private static final String ATTRIBUTE_TYPE = "type";
+ private static final String ATTRIBUTE_ID = "id";
+ private static final String ATTRIBUTE_CS = "cs";
+
+ private static final String TYPE = "printer";
+
+ private static final String PRIVET_SERVICE = "_privet._tcp";
+
+ /** The required mDNS service types */
+ private static final Set<String> PRINTER_SERVICE_TYPE = new HashSet<String>() {{
+ // Not checking _printer_._sub
+ add(PRIVET_SERVICE);
+ }};
+
+ /** All possible connection states */
+ private static final Set<String> POSSIBLE_CONNECTION_STATES = new HashSet<String>() {{
+ add("online");
+ add("offline");
+ add("connecting");
+ add("not-configured");
+ }};
+
+ private static final byte SUPPORTED_TXTVERS = '1';
+
+ /** The mDNS filtered discovery */
+ private final MDNSFilteredDiscovery mMDNSFilteredDiscovery;
+
+ /**
+ * Create a plugin detecting Google Cloud Print printers.
+ *
+ * @param context The context the plugin runs in
+ */
+ public CloudPrintPlugin(@NonNull Context context) {
+ mMDNSFilteredDiscovery = new MDNSFilteredDiscovery(context, PRINTER_SERVICE_TYPE,
+ nsdServiceInfo -> {
+ // The attributes are case insensitive. For faster searching create a clone of
+ // the map with the attribute-keys all in lower case.
+ ArrayMap<String, byte[]> caseInsensitiveAttributes =
+ new ArrayMap<>(nsdServiceInfo.getAttributes().size());
+ for (Map.Entry<String, byte[]> entry : nsdServiceInfo.getAttributes()
+ .entrySet()) {
+ caseInsensitiveAttributes.put(entry.getKey().toLowerCase(),
+ entry.getValue());
+ }
+
+ if (DEBUG) {
+ Log.i(LOG_TAG, nsdServiceInfo.getServiceName() + ":");
+ Log.i(LOG_TAG, "type: " + nsdServiceInfo.getServiceType());
+ Log.i(LOG_TAG, "host: " + nsdServiceInfo.getHost());
+ for (Map.Entry<String, byte[]> entry : caseInsensitiveAttributes.entrySet()) {
+ if (entry.getValue() == null) {
+ Log.i(LOG_TAG, entry.getKey() + "= null");
+ } else {
+ Log.i(LOG_TAG, entry.getKey() + "=" + new String(entry.getValue(),
+ StandardCharsets.UTF_8));
+ }
+ }
+ }
+
+ byte[] txtvers = caseInsensitiveAttributes.get(ATTRIBUTE_TXTVERS);
+ if (txtvers == null || txtvers.length != 1 || txtvers[0] != SUPPORTED_TXTVERS) {
+ // The spec requires this to be the first attribute, but at this time we
+ // lost the order of the attributes
+ return false;
+ }
+
+ if (caseInsensitiveAttributes.get(ATTRIBUTE_TY) == null) {
+ return false;
+ }
+
+ byte[] url = caseInsensitiveAttributes.get(ATTRIBUTE_URL);
+ if (url == null || url.length == 0) {
+ return false;
+ }
+
+ byte[] type = caseInsensitiveAttributes.get(ATTRIBUTE_TYPE);
+ if (type == null || !TYPE.equals(
+ new String(type, StandardCharsets.UTF_8).toLowerCase())) {
+ return false;
+ }
+
+ if (caseInsensitiveAttributes.get(ATTRIBUTE_ID) == null) {
+ return false;
+ }
+
+ byte[] cs = caseInsensitiveAttributes.get(ATTRIBUTE_CS);
+ if (cs == null || !POSSIBLE_CONNECTION_STATES.contains(
+ new String(cs, StandardCharsets.UTF_8).toLowerCase())) {
+ return false;
+ }
+
+ InetAddress address = nsdServiceInfo.getHost();
+ if (!(address instanceof Inet4Address)) {
+ // Not checking for link local address
+ return false;
+ }
+
+ return true;
+ });
+ }
+
+ @Override
+ @NonNull public CharSequence getPackageName() {
+ return "com.google.android.apps.cloudprint";
+ }
+
+ @Override
+ public void start(@NonNull PrinterDiscoveryCallback callback) throws Exception {
+ mMDNSFilteredDiscovery.start(callback);
+ }
+
+ @Override
+ @StringRes public int getName() {
+ return R.string.plugin_vendor_google_cloud_print;
+ }
+
+ @Override
+ public void stop() throws Exception {
+ mMDNSFilteredDiscovery.stop();
+ }
+}
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 9092bdb4e999..c3cbf18135fc 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -398,8 +398,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
return true;
}
- // TODO(b/33197203 , b/35707731): must iterate over all responses
- final FillResponse response = mResponses.get(0);
+ final FillResponse response = mResponses.get(mResponses.size() - 1);
final SaveInfo saveInfo = response.getSaveInfo();
if (DEBUG) {
diff --git a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
index d35cc95e6d26..f94d456cb47f 100644
--- a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
@@ -24,7 +24,7 @@ import android.content.Context;
import android.content.IntentSender;
import android.os.Handler;
import android.service.autofill.SaveInfo;
-import android.text.format.DateUtils;
+import android.util.ArraySet;
import android.util.Slog;
import android.view.Gravity;
import android.view.Window;
@@ -105,32 +105,45 @@ final class SaveUi {
final View view = inflater.inflate(R.layout.autofill_save, null);
final TextView titleView = (TextView) view.findViewById(R.id.autofill_save_title);
- final String type;
- switch(info.getType()) {
- case SaveInfo.SAVE_DATA_TYPE_PASSWORD:
- type = context.getString(R.string.autofill_save_type_password);
- break;
- case SaveInfo.SAVE_DATA_TYPE_ADDRESS:
- type = context.getString(R.string.autofill_save_type_address);
- break;
- case SaveInfo.SAVE_DATA_TYPE_CREDIT_CARD:
- type = context.getString(R.string.autofill_save_type_credit_card);
+ final ArraySet<String> types = new ArraySet<>(3);
+ final int type = info.getType();
+
+ if ((type & SaveInfo.SAVE_DATA_TYPE_PASSWORD) != 0) {
+ types.add(context.getString(R.string.autofill_save_type_password));
+ }
+ if ((type & SaveInfo.SAVE_DATA_TYPE_ADDRESS) != 0) {
+ types.add(context.getString(R.string.autofill_save_type_address));
+ }
+ if ((type & SaveInfo.SAVE_DATA_TYPE_CREDIT_CARD) != 0) {
+ types.add(context.getString(R.string.autofill_save_type_credit_card));
+ }
+ if ((type & SaveInfo.SAVE_DATA_TYPE_USERNAME) != 0) {
+ types.add(context.getString(R.string.autofill_save_type_username));
+ }
+ if ((type & SaveInfo.SAVE_DATA_TYPE_EMAIL_ADDRESS) != 0) {
+ types.add(context.getString(R.string.autofill_save_type_email_address));
+ }
+
+ final String title;
+ switch (types.size()) {
+ case 1:
+ title = context.getString(R.string.autofill_save_title_with_type,
+ types.valueAt(0), providerLabel);
break;
- case SaveInfo.SAVE_DATA_TYPE_USERNAME:
- type = context.getString(R.string.autofill_save_type_username);
+ case 2:
+ title = context.getString(R.string.autofill_save_title_with_2types,
+ types.valueAt(0), types.valueAt(1), providerLabel);
break;
- case SaveInfo.SAVE_DATA_TYPE_EMAIL_ADDRESS:
- type = context.getString(R.string.autofill_save_type_email_address);
+ case 3:
+ title = context.getString(R.string.autofill_save_title_with_3types,
+ types.valueAt(0), types.valueAt(1), types.valueAt(2), providerLabel);
break;
default:
- type = null;
+ // Use generic if more than 3 or invalid type (size 0).
+ title = context.getString(R.string.autofill_save_title, providerLabel);
}
- final String title = (type == null)
- ? context.getString(R.string.autofill_save_title, providerLabel)
- : context.getString(R.string.autofill_save_title_with_type, type, providerLabel);
-
titleView.setText(title);
final CharSequence subTitle = info.getDescription();
if (subTitle != null) {
@@ -139,6 +152,10 @@ final class SaveUi {
subTitleView.setVisibility(View.VISIBLE);
}
+ if (DEBUG) {
+ Slog.d(TAG, "Title: " + title + " SubTitle: " + subTitle);
+ }
+
final TextView noButton = view.findViewById(R.id.autofill_save_no);
if (info.getNegativeActionTitle() != null) {
noButton.setText(info.getNegativeActionTitle());
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index f4e3b313e98a..35654d76dee5 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -30,6 +30,7 @@ import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
+import static android.content.pm.PackageManager.FEATURE_ACTIVITIES_ON_SECONDARY_DISPLAYS;
import static android.content.pm.PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT;
import static android.content.pm.PackageManager.FEATURE_LEANBACK_ONLY;
import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE;
@@ -13766,7 +13767,8 @@ public class ActivityManagerService extends IActivityManager.Stub
final boolean supportsMultiWindow = ActivityManager.supportsMultiWindow();
final boolean supportsSplitScreenMultiWindow =
ActivityManager.supportsSplitScreenMultiWindow();
- final boolean supportsMultiDisplay = ActivityManager.supportsMultiDisplay();
+ final boolean supportsMultiDisplay = mContext.getPackageManager()
+ .hasSystemFeature(FEATURE_ACTIVITIES_ON_SECONDARY_DISPLAYS);
final String debugApp = Settings.Global.getString(resolver, DEBUG_APP);
final boolean waitForDebugger = Settings.Global.getInt(resolver, WAIT_FOR_DEBUGGER, 0) != 0;
final boolean alwaysFinishActivities =
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 2b3a19a83e55..04c2af5af339 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -247,8 +247,6 @@ final class ActivityManagerShellCommand extends ShellCommand {
return runSupportsMultiwindow(pw);
case "supports-split-screen-multi-window":
return runSupportsSplitScreenMultiwindow(pw);
- case "supports-multi-display":
- return runSupportsMultiDisplay(pw);
case "update-appinfo":
return runUpdateApplicationInfo(pw);
case "no-home-screen":
@@ -2399,15 +2397,6 @@ final class ActivityManagerShellCommand extends ShellCommand {
return 0;
}
- int runSupportsMultiDisplay(PrintWriter pw) throws RemoteException {
- final Resources res = getResources(pw);
- if (res == null) {
- return -1;
- }
- pw.println(ActivityManager.supportsMultiDisplay());
- return 0;
- }
-
int runUpdateApplicationInfo(PrintWriter pw) throws RemoteException {
int userid = UserHandle.parseUserArg(getNextArgRequired());
ArrayList<String> packages = new ArrayList<>();
@@ -2637,8 +2626,6 @@ final class ActivityManagerShellCommand extends ShellCommand {
pw.println(" Returns true if the device supports multiwindow.");
pw.println(" supports-split-screen-multi-window");
pw.println(" Returns true if the device supports split screen multiwindow.");
- pw.println(" supports-multi-display");
- pw.println(" Returns true if the device supports multi-display.");
pw.println(" suppress-resize-config-changes <true|false>");
pw.println(" Suppresses configuration changes due to user resizing an activity/task.");
pw.println(" set-inactive [--user <USER_ID>] <PACKAGE> true|false");
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 4ee1a207a341..51011b586743 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -312,6 +312,11 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
*/
boolean mConfigWillChange;
+ /**
+ * When set, will force the stack to report as invisible.
+ */
+ boolean mForceHidden = false;
+
// Whether or not this stack covers the entire screen; by default stacks are fullscreen
boolean mFullscreen = true;
// Current bounds of the stack or null if fullscreen.
@@ -1561,7 +1566,8 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
/** Returns true if the stack is currently considered visible. */
boolean isVisible() {
- return mWindowContainerController != null && mWindowContainerController.isVisible();
+ return mWindowContainerController != null && mWindowContainerController.isVisible()
+ && !mForceHidden;
}
/**
@@ -1571,7 +1577,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
* @param starting The currently starting activity or null if there is none.
*/
int shouldBeVisible(ActivityRecord starting) {
- if (!isAttached()) {
+ if (!isAttached() || mForceHidden) {
return STACK_INVISIBLE;
}
@@ -3220,8 +3226,25 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
r.addResultLocked(null, resultWho, requestCode, resultCode, data);
}
+ /** Returns true if the task is one of the task finishing on-top of the top running task. */
+ boolean isATopFinishingTask(TaskRecord task) {
+ for (int i = mTaskHistory.size() - 1; i >= 0; --i) {
+ final TaskRecord current = mTaskHistory.get(i);
+ final ActivityRecord r = current.topRunningActivityLocked();
+ if (r != null) {
+ // We got a top running activity, so there isn't a top finishing task...
+ return false;
+ }
+ if (current == task) {
+ return true;
+ }
+ }
+ return false;
+ }
+
private void adjustFocusedActivityStackLocked(ActivityRecord r, String reason) {
- if (!mStackSupervisor.isFocusedStack(this) || mResumedActivity != r) {
+ if (!mStackSupervisor.isFocusedStack(this) ||
+ ((mResumedActivity != r) && (mResumedActivity != null))) {
return;
}
@@ -3236,8 +3259,8 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
final TaskRecord task = r.getTask();
final boolean isAssistantOrOverAssistant = task.getStack().isAssistantStack() ||
task.isOverAssistantStack();
- if (r.frontOfTask && task == topTask() &&
- (task.isOverHomeStack() || isAssistantOrOverAssistant)) {
+ if (r.frontOfTask && isATopFinishingTask(task)
+ && (task.isOverHomeStack() || isAssistantOrOverAssistant)) {
// For non-fullscreen or assistant stack, we want to move the focus to the next
// visible stack to prevent the home screen from moving to the top and obscuring
// other visible stacks.
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 0ea834abffed..c9bb9e547693 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -42,6 +42,7 @@ import static android.view.Display.FLAG_PRIVATE;
import static android.view.Display.INVALID_DISPLAY;
import static android.view.Display.REMOVE_MODE_DESTROY_CONTENT;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.ACTION_PICTURE_IN_PICTURE_EXPANDED_TO_FULLSCREEN;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ALL;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONTAINERS;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_FOCUS;
@@ -167,7 +168,6 @@ import android.view.Surface;
import com.android.internal.content.ReferrerIntent;
import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.os.TransferPipe;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.util.ArrayUtils;
@@ -2343,7 +2343,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
mWindowManager.deferSurfaceLayout();
try {
if (fromStackId == DOCKED_STACK_ID) {
-
// We are moving all tasks from the docked stack to the fullscreen stack,
// which is dismissing the docked stack, so resize all other stacks to
// fullscreen here already so we don't end up with resize trashing.
@@ -2362,13 +2361,19 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
// resize when we remove task from it below and it is detached from the
// display because it no longer contains any tasks.
mAllowDockedStackResize = false;
+ } else if (fromStackId == PINNED_STACK_ID) {
+ if (onTop) {
+ // Log if we are expanding the PiP to fullscreen
+ MetricsLogger.action(mService.mContext,
+ ACTION_PICTURE_IN_PICTURE_EXPANDED_TO_FULLSCREEN);
+ }
}
ActivityStack fullscreenStack = getStack(FULLSCREEN_WORKSPACE_STACK_ID);
final boolean isFullscreenStackVisible = fullscreenStack != null &&
fullscreenStack.shouldBeVisible(null) == STACK_VISIBLE;
// If we are moving from the pinned stack, then the animation takes care of updating
// the picture-in-picture mode.
- final boolean schedulePictureInPictureModeChange = (fromStackId != PINNED_STACK_ID);
+ final boolean schedulePictureInPictureModeChange = (fromStackId == PINNED_STACK_ID);
final ArrayList<TaskRecord> tasks = stack.getAllTasks();
final int size = tasks.size();
if (onTop) {
@@ -2381,8 +2386,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
// pinned stack is recreated. See moveActivityToPinnedStackLocked().
task.setTaskToReturnTo(isFullscreenStackVisible && onTop ?
APPLICATION_ACTIVITY_TYPE : HOME_ACTIVITY_TYPE);
- MetricsLogger.action(mService.mContext,
- MetricsEvent.ACTION_PICTURE_IN_PICTURE_EXPANDED_TO_FULLSCREEN);
}
// Defer resume until all the tasks have been moved to the fullscreen stack
task.reparent(FULLSCREEN_WORKSPACE_STACK_ID, ON_TOP,
@@ -2537,27 +2540,24 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
final ArrayList<TaskRecord> tasks = stack.getAllTasks();
if (stack.getStackId() == PINNED_STACK_ID) {
- final ActivityStack fullscreenStack = getStack(FULLSCREEN_WORKSPACE_STACK_ID);
- if (fullscreenStack != null) {
- final boolean isFullscreenStackVisible =
- fullscreenStack.shouldBeVisible(null) == STACK_VISIBLE;
- for (int i = 0; i < tasks.size(); i++) {
- // Insert the task either at the top of the fullscreen stack if it is hidden,
- // or to the bottom if it is currently visible
- final int insertPosition = isFullscreenStackVisible ? 0
- : fullscreenStack.getChildCount();
- final TaskRecord task = tasks.get(i);
- // Defer resume until we remove all the tasks
- task.reparent(FULLSCREEN_WORKSPACE_STACK_ID, insertPosition,
- REPARENT_LEAVE_STACK_IN_PLACE, !ANIMATE, DEFER_RESUME, "removeStack");
- }
- ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
- resumeFocusedStackTopActivityLocked();
- } else {
- // If there is no fullscreen stack, then create the stack and move all the tasks
- // onto the stack
- moveTasksToFullscreenStackLocked(PINNED_STACK_ID, !ON_TOP);
- }
+ /**
+ * Workaround: Force-stop all the activities in the pinned stack before we reparent them
+ * to the fullscreen stack. This is to guarantee that when we are removing a stack,
+ * that the client receives onStop() before it is reparented. We do this by detaching
+ * the stack from the display so that it will be considered invisible when
+ * ensureActivitiesVisibleLocked() is called, and all of its activitys will be marked
+ * invisible as well and added to the stopping list. After which we process the
+ * stopping list by handling the idle.
+ */
+ final PinnedActivityStack pinnedStack = (PinnedActivityStack) stack;
+ pinnedStack.mForceHidden = true;
+ pinnedStack.ensureActivitiesVisibleLocked(null, 0, PRESERVE_WINDOWS);
+ pinnedStack.mForceHidden = false;
+ activityIdleInternalLocked(null, false /* fromTimeout */,
+ true /* processPausingActivites */, null /* configuration */);
+
+ // Move all the tasks to the bottom of the fullscreen stack
+ moveTasksToFullscreenStackLocked(PINNED_STACK_ID, !ON_TOP);
} else {
for (int i = tasks.size() - 1; i >= 0; i--) {
removeTaskByIdLocked(tasks.get(i).taskId, true /* killProcess */,
@@ -2935,6 +2935,10 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
resumeFocusedStackTopActivityLocked();
+ // TODO(b/36099777): Schedule the PiP mode change here immediately until we can defer all
+ // callbacks until after the bounds animation
+ scheduleUpdatePictureInPictureModeIfNeeded(r.getTask(), destBounds, true /* immediate */);
+
stack.animateResizePinnedStack(sourceBounds, destBounds, -1 /* animationDuration */);
mService.mTaskChangeNotificationController.notifyActivityPinned(r.packageName);
}
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index a30591b7b9f2..59f6098684eb 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -1457,17 +1457,11 @@ class ActivityStarter {
}
/**
- * Returns the ID of the display to use for a new activity. If the source activity has
- * a explicit display ID set, use that to launch the activity. If not and the device is in VR
- * mode, then return the Vr mode's virtual display ID.
+ * Returns the ID of the display to use for a new activity. If the device is in VR mode,
+ * then return the Vr mode's virtual display ID. If not, if the source activity has
+ * a explicit display ID set, use that to launch the activity.
*/
private int getSourceDisplayId(ActivityRecord sourceRecord, ActivityRecord startingActivity) {
- int displayId = sourceRecord != null ? sourceRecord.getDisplayId() : INVALID_DISPLAY;
- // If the activity has a displayId set explicitly, launch it on the same displayId.
- if (displayId != INVALID_DISPLAY) {
- return displayId;
- }
-
// Check if the Activity is a VR activity. If so, the activity should be launched in
// main display.
if (startingActivity != null && startingActivity.requestedVrComponent != null) {
@@ -1475,7 +1469,7 @@ class ActivityStarter {
}
// Get the virtual display id from ActivityManagerService.
- displayId = mService.mVrCompatibilityDisplayId;
+ int displayId = mService.mVrCompatibilityDisplayId;
if (displayId != INVALID_DISPLAY) {
if (DEBUG_STACK) {
Slog.d(TAG, "getSourceDisplayId :" + displayId);
@@ -1483,6 +1477,12 @@ class ActivityStarter {
mUsingVrCompatibilityDisplay = true;
return displayId;
}
+
+ displayId = sourceRecord != null ? sourceRecord.getDisplayId() : INVALID_DISPLAY;
+ // If the activity has a displayId set explicitly, launch it on the same displayId.
+ if (displayId != INVALID_DISPLAY) {
+ return displayId;
+ }
return DEFAULT_DISPLAY;
}
diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java
index 656e01a1ab52..85f7056ba1ad 100644
--- a/services/core/java/com/android/server/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java
@@ -570,12 +570,12 @@ public class FingerprintService extends SystemService implements IHwBinder.Death
* @return true if caller can use fingerprint API
*/
private boolean canUseFingerprint(String opPackageName, boolean requireForeground, int uid,
- int pid) {
+ int pid, int userId) {
checkPermission(USE_FINGERPRINT);
if (isKeyguard(opPackageName)) {
return true; // Keyguard is always allowed
}
- if (!isCurrentUserOrProfile(UserHandle.getCallingUserId())) {
+ if (!isCurrentUserOrProfile(userId)) {
Slog.w(TAG,"Rejecting " + opPackageName + " ; not a current user or profile");
return false;
}
@@ -906,7 +906,7 @@ public class FingerprintService extends SystemService implements IHwBinder.Death
@Override
public void run() {
if (!canUseFingerprint(opPackageName, true /* foregroundOnly */,
- callingUid, pid)) {
+ callingUid, pid, callingUserId)) {
if (DEBUG) Slog.v(TAG, "authenticate(): reject " + opPackageName);
return;
}
@@ -933,10 +933,12 @@ public class FingerprintService extends SystemService implements IHwBinder.Death
public void cancelAuthentication(final IBinder token, final String opPackageName) {
final int uid = Binder.getCallingUid();
final int pid = Binder.getCallingPid();
+ final int callingUserId = UserHandle.getCallingUserId();
mHandler.post(new Runnable() {
@Override
public void run() {
- if (!canUseFingerprint(opPackageName, true /* foregroundOnly */, uid, pid)) {
+ if (!canUseFingerprint(opPackageName, true /* foregroundOnly */, uid, pid,
+ callingUserId)) {
if (DEBUG) Slog.v(TAG, "cancelAuthentication(): reject " + opPackageName);
} else {
ClientMonitor client = mCurrentClient;
@@ -996,7 +998,8 @@ public class FingerprintService extends SystemService implements IHwBinder.Death
@Override // Binder call
public boolean isHardwareDetected(long deviceId, String opPackageName) {
if (!canUseFingerprint(opPackageName, false /* foregroundOnly */,
- Binder.getCallingUid(), Binder.getCallingPid())) {
+ Binder.getCallingUid(), Binder.getCallingPid(),
+ UserHandle.getCallingUserId())) {
return false;
}
@@ -1027,7 +1030,8 @@ public class FingerprintService extends SystemService implements IHwBinder.Death
@Override // Binder call
public List<Fingerprint> getEnrolledFingerprints(int userId, String opPackageName) {
if (!canUseFingerprint(opPackageName, false /* foregroundOnly */,
- Binder.getCallingUid(), Binder.getCallingPid())) {
+ Binder.getCallingUid(), Binder.getCallingPid(),
+ UserHandle.getCallingUserId())) {
return Collections.emptyList();
}
@@ -1037,7 +1041,8 @@ public class FingerprintService extends SystemService implements IHwBinder.Death
@Override // Binder call
public boolean hasEnrolledFingerprints(int userId, String opPackageName) {
if (!canUseFingerprint(opPackageName, false /* foregroundOnly */,
- Binder.getCallingUid(), Binder.getCallingPid())) {
+ Binder.getCallingUid(), Binder.getCallingPid(),
+ UserHandle.getCallingUserId())) {
return false;
}
diff --git a/services/core/java/com/android/server/wm/BoundsAnimationController.java b/services/core/java/com/android/server/wm/BoundsAnimationController.java
index 7b8057cafbb4..2811145bcf5f 100644
--- a/services/core/java/com/android/server/wm/BoundsAnimationController.java
+++ b/services/core/java/com/android/server/wm/BoundsAnimationController.java
@@ -170,8 +170,8 @@ public class BoundsAnimationController {
// If we are animating to a new fullscreen state (either to/from fullscreen), then
// notify the target of the change with the new frozen task bounds
- if (mAnimatingToNewFullscreenState) {
- mTarget.updatePictureInPictureMode(mMoveToFullScreen ? null : mTo);
+ if (mAnimatingToNewFullscreenState && mMoveToFullScreen) {
+ mTarget.updatePictureInPictureMode(null);
}
// Immediately update the task bounds if they have to become larger, but preserve