Merge "Allow setImeWindowStatus with null startInputToken"
diff --git a/Android.mk b/Android.mk
index 28adbca..7a8b1b7 100644
--- a/Android.mk
+++ b/Android.mk
@@ -295,9 +295,9 @@
core/java/android/printservice/IPrintService.aidl \
core/java/android/printservice/IPrintServiceClient.aidl \
core/java/android/companion/ICompanionDeviceManager.aidl \
- core/java/android/companion/ICompanionDeviceManagerService.aidl \
- core/java/android/companion/ICompanionDeviceManagerServiceCallback.aidl \
- core/java/android/companion/IOnAssociateCallback.aidl \
+ core/java/android/companion/ICompanionDeviceDiscoveryService.aidl \
+ core/java/android/companion/ICompanionDeviceDiscoveryServiceCallback.aidl \
+ core/java/android/companion/IFindDeviceCallback.aidl \
core/java/android/service/dreams/IDreamManager.aidl \
core/java/android/service/dreams/IDreamService.aidl \
core/java/android/service/persistentdata/IPersistentDataBlockService.aidl \
diff --git a/api/current.txt b/api/current.txt
index a03ef38..7465c4d 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -121,6 +121,7 @@
field public static final java.lang.String REQUEST_INSTALL_PACKAGES = "android.permission.REQUEST_INSTALL_PACKAGES";
field public static final deprecated java.lang.String RESTART_PACKAGES = "android.permission.RESTART_PACKAGES";
field public static final java.lang.String RESTRICTED_VR_ACCESS = "android.permission.RESTRICTED_VR_ACCESS";
+ field public static final java.lang.String RUN_IN_BACKGROUND = "android.permission.RUN_IN_BACKGROUND";
field public static final java.lang.String SEND_RESPOND_VIA_MESSAGE = "android.permission.SEND_RESPOND_VIA_MESSAGE";
field public static final java.lang.String SEND_SMS = "android.permission.SEND_SMS";
field public static final java.lang.String SET_ALARM = "com.android.alarm.permission.SET_ALARM";
@@ -139,6 +140,7 @@
field public static final java.lang.String TRANSMIT_IR = "android.permission.TRANSMIT_IR";
field public static final java.lang.String UNINSTALL_SHORTCUT = "com.android.launcher.permission.UNINSTALL_SHORTCUT";
field public static final java.lang.String UPDATE_DEVICE_STATS = "android.permission.UPDATE_DEVICE_STATS";
+ field public static final java.lang.String USE_DATA_IN_BACKGROUND = "android.permission.USE_DATA_IN_BACKGROUND";
field public static final java.lang.String USE_FINGERPRINT = "android.permission.USE_FINGERPRINT";
field public static final java.lang.String USE_SIP = "android.permission.USE_SIP";
field public static final java.lang.String VIBRATE = "android.permission.VIBRATE";
@@ -6572,6 +6574,7 @@
method public int getTextStyle();
method public int getTop();
method public android.graphics.Matrix getTransformation();
+ method public java.lang.String getUrl();
method public int getVisibility();
method public int getWidth();
method public boolean isAccessibilityFocused();
@@ -9224,7 +9227,7 @@
field public static final java.lang.String EXTRA_PHONE_NUMBER = "android.intent.extra.PHONE_NUMBER";
field public static final java.lang.String EXTRA_PROCESS_TEXT = "android.intent.extra.PROCESS_TEXT";
field public static final java.lang.String EXTRA_PROCESS_TEXT_READONLY = "android.intent.extra.PROCESS_TEXT_READONLY";
- field public static final java.lang.String EXTRA_QUICK_VIEW_PLAIN = "android.intent.extra.QUICK_VIEW_PLAIN";
+ field public static final java.lang.String EXTRA_QUICK_VIEW_ADVANCED = "android.intent.extra.QUICK_VIEW_ADVANCED";
field public static final java.lang.String EXTRA_QUIET_MODE = "android.intent.extra.QUIET_MODE";
field public static final java.lang.String EXTRA_REFERRER = "android.intent.extra.REFERRER";
field public static final java.lang.String EXTRA_REFERRER_NAME = "android.intent.extra.REFERRER_NAME";
@@ -22320,7 +22323,7 @@
method public void pause() throws java.lang.IllegalStateException;
method public void prepare() throws java.io.IOException, java.lang.IllegalStateException;
method public void prepareAsync() throws java.lang.IllegalStateException;
- method public void prepareDrm(java.util.UUID, android.media.MediaPlayer.OnDrmConfigCallback) throws android.media.MediaPlayer.ProvisioningErrorException, android.media.ResourceBusyException, android.media.UnsupportedSchemeException;
+ method public void prepareDrm(java.util.UUID) throws android.media.MediaPlayer.ProvisioningErrorException, android.media.ResourceBusyException, android.media.UnsupportedSchemeException;
method public byte[] provideKeyResponse(byte[], byte[]) throws android.media.DeniedByServerException, android.media.MediaPlayer.NoDrmSchemeException;
method public void release();
method public void releaseDrm() throws android.media.MediaPlayer.NoDrmSchemeException;
@@ -22348,6 +22351,7 @@
method public void setNextMediaPlayer(android.media.MediaPlayer);
method public void setOnBufferingUpdateListener(android.media.MediaPlayer.OnBufferingUpdateListener);
method public void setOnCompletionListener(android.media.MediaPlayer.OnCompletionListener);
+ method public void setOnDrmConfigListener(android.media.MediaPlayer.OnDrmConfigListener);
method public void setOnDrmInfoListener(android.media.MediaPlayer.OnDrmInfoListener);
method public void setOnDrmInfoListener(android.media.MediaPlayer.OnDrmInfoListener, android.os.Handler);
method public void setOnDrmPreparedListener(android.media.MediaPlayer.OnDrmPreparedListener);
@@ -22412,9 +22416,8 @@
method public abstract void onCompletion(android.media.MediaPlayer);
}
- public static abstract class MediaPlayer.OnDrmConfigCallback {
- ctor public MediaPlayer.OnDrmConfigCallback();
- method public void onDrmConfig(android.media.MediaPlayer);
+ public static abstract interface MediaPlayer.OnDrmConfigListener {
+ method public abstract void onDrmConfig(android.media.MediaPlayer);
}
public static abstract interface MediaPlayer.OnDrmInfoListener {
@@ -44111,6 +44114,7 @@
field public static final int AXIS_RX = 12; // 0xc
field public static final int AXIS_RY = 13; // 0xd
field public static final int AXIS_RZ = 14; // 0xe
+ field public static final int AXIS_SCROLL = 26; // 0x1a
field public static final int AXIS_SIZE = 3; // 0x3
field public static final int AXIS_THROTTLE = 19; // 0x13
field public static final int AXIS_TILT = 25; // 0x19
@@ -45661,6 +45665,7 @@
method public abstract void setTextLines(int[], int[]);
method public abstract void setTextStyle(float, int, int, int);
method public abstract void setTransformation(android.graphics.Matrix);
+ method public abstract void setUrl(java.lang.String);
method public abstract void setVisibility(int);
field public static final int AUTO_FILL_FLAG_SANITIZED = 1; // 0x1
}
@@ -47337,7 +47342,7 @@
public final class TextClassificationManager {
method public java.util.List<android.view.textclassifier.TextLanguage> detectLanguages(java.lang.CharSequence);
- method public synchronized android.view.textclassifier.TextClassifier getDefaultTextClassifier();
+ method public android.view.textclassifier.TextClassifier getDefaultTextClassifier();
}
public final class TextClassificationResult {
diff --git a/api/system-current.txt b/api/system-current.txt
index 406d51c..25b393c 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -211,6 +211,7 @@
field public static final java.lang.String RESTRICTED_VR_ACCESS = "android.permission.RESTRICTED_VR_ACCESS";
field public static final java.lang.String RETRIEVE_WINDOW_CONTENT = "android.permission.RETRIEVE_WINDOW_CONTENT";
field public static final java.lang.String REVOKE_RUNTIME_PERMISSIONS = "android.permission.REVOKE_RUNTIME_PERMISSIONS";
+ field public static final java.lang.String RUN_IN_BACKGROUND = "android.permission.RUN_IN_BACKGROUND";
field public static final java.lang.String SCORE_NETWORKS = "android.permission.SCORE_NETWORKS";
field public static final java.lang.String SEND_RESPOND_VIA_MESSAGE = "android.permission.SEND_RESPOND_VIA_MESSAGE";
field public static final java.lang.String SEND_SMS = "android.permission.SEND_SMS";
@@ -248,6 +249,7 @@
field public static final java.lang.String UPDATE_DEVICE_STATS = "android.permission.UPDATE_DEVICE_STATS";
field public static final java.lang.String UPDATE_LOCK = "android.permission.UPDATE_LOCK";
field public static final java.lang.String USER_ACTIVITY = "android.permission.USER_ACTIVITY";
+ field public static final java.lang.String USE_DATA_IN_BACKGROUND = "android.permission.USE_DATA_IN_BACKGROUND";
field public static final java.lang.String USE_FINGERPRINT = "android.permission.USE_FINGERPRINT";
field public static final java.lang.String USE_SIP = "android.permission.USE_SIP";
field public static final java.lang.String VIBRATE = "android.permission.VIBRATE";
@@ -6809,6 +6811,7 @@
method public int getTextStyle();
method public int getTop();
method public android.graphics.Matrix getTransformation();
+ method public java.lang.String getUrl();
method public int getVisibility();
method public int getWidth();
method public boolean isAccessibilityFocused();
@@ -9668,7 +9671,7 @@
field public static final java.lang.String EXTRA_PHONE_NUMBER = "android.intent.extra.PHONE_NUMBER";
field public static final java.lang.String EXTRA_PROCESS_TEXT = "android.intent.extra.PROCESS_TEXT";
field public static final java.lang.String EXTRA_PROCESS_TEXT_READONLY = "android.intent.extra.PROCESS_TEXT_READONLY";
- field public static final java.lang.String EXTRA_QUICK_VIEW_PLAIN = "android.intent.extra.QUICK_VIEW_PLAIN";
+ field public static final java.lang.String EXTRA_QUICK_VIEW_ADVANCED = "android.intent.extra.QUICK_VIEW_ADVANCED";
field public static final java.lang.String EXTRA_QUIET_MODE = "android.intent.extra.QUIET_MODE";
field public static final java.lang.String EXTRA_REFERRER = "android.intent.extra.REFERRER";
field public static final java.lang.String EXTRA_REFERRER_NAME = "android.intent.extra.REFERRER_NAME";
@@ -23963,7 +23966,7 @@
method public void pause() throws java.lang.IllegalStateException;
method public void prepare() throws java.io.IOException, java.lang.IllegalStateException;
method public void prepareAsync() throws java.lang.IllegalStateException;
- method public void prepareDrm(java.util.UUID, android.media.MediaPlayer.OnDrmConfigCallback) throws android.media.MediaPlayer.ProvisioningErrorException, android.media.ResourceBusyException, android.media.UnsupportedSchemeException;
+ method public void prepareDrm(java.util.UUID) throws android.media.MediaPlayer.ProvisioningErrorException, android.media.ResourceBusyException, android.media.UnsupportedSchemeException;
method public byte[] provideKeyResponse(byte[], byte[]) throws android.media.DeniedByServerException, android.media.MediaPlayer.NoDrmSchemeException;
method public void release();
method public void releaseDrm() throws android.media.MediaPlayer.NoDrmSchemeException;
@@ -23991,6 +23994,7 @@
method public void setNextMediaPlayer(android.media.MediaPlayer);
method public void setOnBufferingUpdateListener(android.media.MediaPlayer.OnBufferingUpdateListener);
method public void setOnCompletionListener(android.media.MediaPlayer.OnCompletionListener);
+ method public void setOnDrmConfigListener(android.media.MediaPlayer.OnDrmConfigListener);
method public void setOnDrmInfoListener(android.media.MediaPlayer.OnDrmInfoListener);
method public void setOnDrmInfoListener(android.media.MediaPlayer.OnDrmInfoListener, android.os.Handler);
method public void setOnDrmPreparedListener(android.media.MediaPlayer.OnDrmPreparedListener);
@@ -24055,9 +24059,8 @@
method public abstract void onCompletion(android.media.MediaPlayer);
}
- public static abstract class MediaPlayer.OnDrmConfigCallback {
- ctor public MediaPlayer.OnDrmConfigCallback();
- method public void onDrmConfig(android.media.MediaPlayer);
+ public static abstract interface MediaPlayer.OnDrmConfigListener {
+ method public abstract void onDrmConfig(android.media.MediaPlayer);
}
public static abstract interface MediaPlayer.OnDrmInfoListener {
@@ -47549,6 +47552,7 @@
field public static final int AXIS_RX = 12; // 0xc
field public static final int AXIS_RY = 13; // 0xd
field public static final int AXIS_RZ = 14; // 0xe
+ field public static final int AXIS_SCROLL = 26; // 0x1a
field public static final int AXIS_SIZE = 3; // 0x3
field public static final int AXIS_THROTTLE = 19; // 0x13
field public static final int AXIS_TILT = 25; // 0x19
@@ -49099,6 +49103,7 @@
method public abstract void setTextLines(int[], int[]);
method public abstract void setTextStyle(float, int, int, int);
method public abstract void setTransformation(android.graphics.Matrix);
+ method public abstract void setUrl(java.lang.String);
method public abstract void setVisibility(int);
field public static final int AUTO_FILL_FLAG_SANITIZED = 1; // 0x1
}
@@ -50778,7 +50783,7 @@
public final class TextClassificationManager {
method public java.util.List<android.view.textclassifier.TextLanguage> detectLanguages(java.lang.CharSequence);
- method public synchronized android.view.textclassifier.TextClassifier getDefaultTextClassifier();
+ method public android.view.textclassifier.TextClassifier getDefaultTextClassifier();
}
public final class TextClassificationResult {
diff --git a/api/test-current.txt b/api/test-current.txt
index 1be19ed..2c2831f 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -121,6 +121,7 @@
field public static final java.lang.String REQUEST_INSTALL_PACKAGES = "android.permission.REQUEST_INSTALL_PACKAGES";
field public static final deprecated java.lang.String RESTART_PACKAGES = "android.permission.RESTART_PACKAGES";
field public static final java.lang.String RESTRICTED_VR_ACCESS = "android.permission.RESTRICTED_VR_ACCESS";
+ field public static final java.lang.String RUN_IN_BACKGROUND = "android.permission.RUN_IN_BACKGROUND";
field public static final java.lang.String SEND_RESPOND_VIA_MESSAGE = "android.permission.SEND_RESPOND_VIA_MESSAGE";
field public static final java.lang.String SEND_SMS = "android.permission.SEND_SMS";
field public static final java.lang.String SET_ALARM = "com.android.alarm.permission.SET_ALARM";
@@ -139,6 +140,7 @@
field public static final java.lang.String TRANSMIT_IR = "android.permission.TRANSMIT_IR";
field public static final java.lang.String UNINSTALL_SHORTCUT = "com.android.launcher.permission.UNINSTALL_SHORTCUT";
field public static final java.lang.String UPDATE_DEVICE_STATS = "android.permission.UPDATE_DEVICE_STATS";
+ field public static final java.lang.String USE_DATA_IN_BACKGROUND = "android.permission.USE_DATA_IN_BACKGROUND";
field public static final java.lang.String USE_FINGERPRINT = "android.permission.USE_FINGERPRINT";
field public static final java.lang.String USE_SIP = "android.permission.USE_SIP";
field public static final java.lang.String VIBRATE = "android.permission.VIBRATE";
@@ -6595,6 +6597,7 @@
method public int getTextStyle();
method public int getTop();
method public android.graphics.Matrix getTransformation();
+ method public java.lang.String getUrl();
method public int getVisibility();
method public int getWidth();
method public boolean isAccessibilityFocused();
@@ -9250,7 +9253,7 @@
field public static final java.lang.String EXTRA_PHONE_NUMBER = "android.intent.extra.PHONE_NUMBER";
field public static final java.lang.String EXTRA_PROCESS_TEXT = "android.intent.extra.PROCESS_TEXT";
field public static final java.lang.String EXTRA_PROCESS_TEXT_READONLY = "android.intent.extra.PROCESS_TEXT_READONLY";
- field public static final java.lang.String EXTRA_QUICK_VIEW_PLAIN = "android.intent.extra.QUICK_VIEW_PLAIN";
+ field public static final java.lang.String EXTRA_QUICK_VIEW_ADVANCED = "android.intent.extra.QUICK_VIEW_ADVANCED";
field public static final java.lang.String EXTRA_QUIET_MODE = "android.intent.extra.QUIET_MODE";
field public static final java.lang.String EXTRA_REFERRER = "android.intent.extra.REFERRER";
field public static final java.lang.String EXTRA_REFERRER_NAME = "android.intent.extra.REFERRER_NAME";
@@ -22413,7 +22416,7 @@
method public void pause() throws java.lang.IllegalStateException;
method public void prepare() throws java.io.IOException, java.lang.IllegalStateException;
method public void prepareAsync() throws java.lang.IllegalStateException;
- method public void prepareDrm(java.util.UUID, android.media.MediaPlayer.OnDrmConfigCallback) throws android.media.MediaPlayer.ProvisioningErrorException, android.media.ResourceBusyException, android.media.UnsupportedSchemeException;
+ method public void prepareDrm(java.util.UUID) throws android.media.MediaPlayer.ProvisioningErrorException, android.media.ResourceBusyException, android.media.UnsupportedSchemeException;
method public byte[] provideKeyResponse(byte[], byte[]) throws android.media.DeniedByServerException, android.media.MediaPlayer.NoDrmSchemeException;
method public void release();
method public void releaseDrm() throws android.media.MediaPlayer.NoDrmSchemeException;
@@ -22441,6 +22444,7 @@
method public void setNextMediaPlayer(android.media.MediaPlayer);
method public void setOnBufferingUpdateListener(android.media.MediaPlayer.OnBufferingUpdateListener);
method public void setOnCompletionListener(android.media.MediaPlayer.OnCompletionListener);
+ method public void setOnDrmConfigListener(android.media.MediaPlayer.OnDrmConfigListener);
method public void setOnDrmInfoListener(android.media.MediaPlayer.OnDrmInfoListener);
method public void setOnDrmInfoListener(android.media.MediaPlayer.OnDrmInfoListener, android.os.Handler);
method public void setOnDrmPreparedListener(android.media.MediaPlayer.OnDrmPreparedListener);
@@ -22505,9 +22509,8 @@
method public abstract void onCompletion(android.media.MediaPlayer);
}
- public static abstract class MediaPlayer.OnDrmConfigCallback {
- ctor public MediaPlayer.OnDrmConfigCallback();
- method public void onDrmConfig(android.media.MediaPlayer);
+ public static abstract interface MediaPlayer.OnDrmConfigListener {
+ method public abstract void onDrmConfig(android.media.MediaPlayer);
}
public static abstract interface MediaPlayer.OnDrmInfoListener {
@@ -44418,6 +44421,7 @@
field public static final int AXIS_RX = 12; // 0xc
field public static final int AXIS_RY = 13; // 0xd
field public static final int AXIS_RZ = 14; // 0xe
+ field public static final int AXIS_SCROLL = 26; // 0x1a
field public static final int AXIS_SIZE = 3; // 0x3
field public static final int AXIS_THROTTLE = 19; // 0x13
field public static final int AXIS_TILT = 25; // 0x19
@@ -45973,6 +45977,7 @@
method public abstract void setTextLines(int[], int[]);
method public abstract void setTextStyle(float, int, int, int);
method public abstract void setTransformation(android.graphics.Matrix);
+ method public abstract void setUrl(java.lang.String);
method public abstract void setVisibility(int);
field public static final int AUTO_FILL_FLAG_SANITIZED = 1; // 0x1
}
@@ -47651,7 +47656,7 @@
public final class TextClassificationManager {
method public java.util.List<android.view.textclassifier.TextLanguage> detectLanguages(java.lang.CharSequence);
- method public synchronized android.view.textclassifier.TextClassifier getDefaultTextClassifier();
+ method public android.view.textclassifier.TextClassifier getDefaultTextClassifier();
}
public final class TextClassificationResult {
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index fb927e9..6dd31a8 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -357,7 +357,8 @@
public static final String OPSTR_INSTANT_APP_START_FOREGROUND
= "android:instant_app_start_foreground";
- private static final int[] RUNTIME_PERMISSIONS_OPS = {
+ private static final int[] RUNTIME_AND_APPOP_PERMISSIONS_OPS = {
+ // RUNTIME PERMISSIONS
// Contacts
OP_READ_CONTACTS,
OP_WRITE_CONTACTS,
@@ -392,7 +393,13 @@
// Camera
OP_CAMERA,
// Body sensors
- OP_BODY_SENSORS
+ OP_BODY_SENSORS,
+
+ // APPOP PERMISSIONS
+ OP_ACCESS_NOTIFICATIONS,
+ OP_SYSTEM_ALERT_WINDOW,
+ OP_WRITE_SETTINGS,
+ OP_REQUEST_INSTALL_PACKAGES,
};
/**
@@ -926,9 +933,9 @@
AppOpsManager.MODE_ALLOWED, // OP_RUN_IN_BACKGROUND
AppOpsManager.MODE_ALLOWED, // OP_AUDIO_ACCESSIBILITY_VOLUME
AppOpsManager.MODE_ALLOWED,
- AppOpsManager.MODE_DEFAULT, // OP_REQUEST_INSTALL_PACKAGES
+ AppOpsManager.MODE_DEFAULT, // OP_REQUEST_INSTALL_PACKAGES
AppOpsManager.MODE_ALLOWED, // OP_ENTER_PICTURE_IN_PICTURE_ON_HIDE
- AppOpsManager.MODE_DEFAULT, // OP_INSTANT_APP_START_FOREGROUND
+ AppOpsManager.MODE_DEFAULT, // OP_INSTANT_APP_START_FOREGROUND
};
/**
@@ -1018,7 +1025,7 @@
/**
* Mapping from a permission to the corresponding app op.
*/
- private static HashMap<String, Integer> sRuntimePermToOp = new HashMap<>();
+ private static HashMap<String, Integer> sPermToOp = new HashMap<>();
static {
if (sOpToSwitch.length != _NUM_OP) {
@@ -1058,9 +1065,9 @@
sOpStrToOp.put(sOpToString[i], i);
}
}
- for (int op : RUNTIME_PERMISSIONS_OPS) {
+ for (int op : RUNTIME_AND_APPOP_PERMISSIONS_OPS) {
if (sOpPerms[op] != null) {
- sRuntimePermToOp.put(sOpPerms[op], op);
+ sPermToOp.put(sOpPerms[op], op);
}
}
}
@@ -1112,12 +1119,12 @@
/**
* Retrieve the app op code for a permission, or null if there is not one.
- * This API is intended to be used for mapping runtime permissions to the
- * corresponding app op.
+ * This API is intended to be used for mapping runtime or appop permissions
+ * to the corresponding app op.
* @hide
*/
public static int permissionToOpCode(String permission) {
- Integer boxedOpCode = sRuntimePermToOp.get(permission);
+ Integer boxedOpCode = sPermToOp.get(permission);
return boxedOpCode != null ? boxedOpCode : OP_NONE;
}
@@ -1462,7 +1469,7 @@
* @return The app op associated with the permission or null.
*/
public static String permissionToOp(String permission) {
- final Integer opCode = sRuntimePermToOp.get(permission);
+ final Integer opCode = sPermToOp.get(permission);
if (opCode == null) {
return null;
}
diff --git a/core/java/android/app/assist/AssistStructure.java b/core/java/android/app/assist/AssistStructure.java
index 6591fc9..8d385db 100644
--- a/core/java/android/app/assist/AssistStructure.java
+++ b/core/java/android/app/assist/AssistStructure.java
@@ -17,13 +17,13 @@
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
-import android.view.ViewStructure;
import android.view.ViewRootImpl;
+import android.view.ViewStructure;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
+import android.view.autofill.AutoFillId;
import android.view.autofill.AutoFillType;
import android.view.autofill.AutoFillValue;
-import android.view.autofill.AutoFillId;
import java.util.ArrayList;
@@ -579,6 +579,7 @@
static final int FLAGS_HAS_EXTRAS = 0x00400000;
static final int FLAGS_HAS_ID = 0x00200000;
static final int FLAGS_HAS_CHILDREN = 0x00100000;
+ static final int FLAGS_HAS_URL = 0x00080000;
static final int FLAGS_ALL_CONTROL = 0xfff00000;
int mFlags;
@@ -587,6 +588,7 @@
CharSequence mContentDescription;
ViewNodeText mText;
+ String mUrl;
Bundle mExtras;
ViewNode[] mChildren;
@@ -651,6 +653,9 @@
if ((flags&FLAGS_HAS_TEXT) != 0) {
mText = new ViewNodeText(in, (flags&FLAGS_HAS_COMPLEX_TEXT) == 0);
}
+ if ((flags&FLAGS_HAS_URL) != 0) {
+ mUrl = in.readString();
+ }
if ((flags&FLAGS_HAS_EXTRAS) != 0) {
mExtras = in.readBundle();
}
@@ -704,6 +709,9 @@
flags |= FLAGS_HAS_COMPLEX_TEXT;
}
}
+ if (mUrl != null) {
+ flags |= FLAGS_HAS_URL;
+ }
if (mExtras != null) {
flags |= FLAGS_HAS_EXTRAS;
}
@@ -760,6 +768,9 @@
if ((flags&FLAGS_HAS_TEXT) != 0) {
mText.writeToParcel(out, (flags&FLAGS_HAS_COMPLEX_TEXT) == 0, writeSensitive);
}
+ if ((flags&FLAGS_HAS_URL) != 0) {
+ out.writeString(mUrl);
+ }
if ((flags&FLAGS_HAS_EXTRAS) != 0) {
out.writeBundle(mExtras);
}
@@ -1040,6 +1051,20 @@
}
/**
+ * Returns the URL represented by this node.
+ *
+ * <p>Typically used in 2 categories of nodes:
+ *
+ * <ol>
+ * <li>Root node (containing the URL of the HTML page)
+ * <li>Child nodes that represent hyperlinks (contains the hyperlink URL).
+ * </ol>
+ */
+ public String getUrl() {
+ return mUrl;
+ }
+
+ /**
* Returns any text associated with the node that is displayed to the user, or null
* if there is none.
*/
@@ -1486,6 +1511,11 @@
public void setSanitized(boolean sanitized) {
mNode.mSanitized = sanitized;
}
+
+ @Override
+ public void setUrl(String url) {
+ mNode.mUrl = url;
+ }
}
/** @hide */
@@ -1583,6 +1613,10 @@
Log.i(TAG, prefix + " Text color fg: #" + Integer.toHexString(node.getTextColor())
+ ", bg: #" + Integer.toHexString(node.getTextBackgroundColor()));
}
+ CharSequence url = node.getUrl();
+ if (url != null) {
+ Log.i(TAG, prefix + " URL: " + url);
+ }
String hint = node.getHint();
if (hint != null) {
Log.i(TAG, prefix + " Hint: " + hint);
diff --git a/core/java/android/companion/CompanionDeviceManager.java b/core/java/android/companion/CompanionDeviceManager.java
index b379c7c..c0c1a4d 100644
--- a/core/java/android/companion/CompanionDeviceManager.java
+++ b/core/java/android/companion/CompanionDeviceManager.java
@@ -29,12 +29,10 @@
/**
* System level service for managing companion devices
*
- * Usage:
- * To obtain an instance call
- * {@link Context#getSystemService}({@link Context#COMPANION_DEVICE_SERVICE})
- *
- * Then, call {@link #associate} to initiate the flow of associating current package
- * with a device selected by user
+ * <p>To obtain an instance call {@link Context#getSystemService}({@link
+ * Context#COMPANION_DEVICE_SERVICE}) Then, call {@link #associate(AssociationRequest,
+ * Callback, Handler)} to initiate the flow of associating current package with a
+ * device selected by user.</p>
*
* @see AssociationRequest
*/
@@ -47,6 +45,14 @@
public static final String EXTRA_DEVICE = "android.companion.extra.DEVICE";
/**
+ * The package name of the companion device discovery component.
+ *
+ * @hide
+ */
+ public static final String COMPANION_DEVICE_DISCOVERY_PACKAGE_NAME =
+ "com.android.companiondevicemanager";
+
+ /**
* A callback to receive once at least one suitable device is found, or the search failed
* (e.g. timed out)
*/
@@ -81,13 +87,20 @@
/**
* Associate this app with a companion device, selected by user
*
- * Once at least one appropriate device is found, {@code callback} will be called with a
+ * <p>Once at least one appropriate device is found, {@code callback} will be called with a
* {@link PendingIntent} that can be used to show the list of available devices for the user
* to select.
* It should be started for result (i.e. using
* {@link android.app.Activity#startIntentSenderForResult}), as the resulting
* {@link android.content.Intent} will contain extra {@link #EXTRA_DEVICE}, with the selected
- * device. (e.g. {@link android.bluetooth.BluetoothDevice})
+ * device. (e.g. {@link android.bluetooth.BluetoothDevice})</p>
+ *
+ * <p>If your app needs to be excluded from battery optimizations (run in the background)
+ * or to have unrestricted data access (use data in the background) you can declare that
+ * you use the {@link android.Manifest.permission#RUN_IN_BACKGROUND} and {@link
+ * android.Manifest.permission#USE_DATA_IN_BACKGROUND} respectively. Note that these
+ * special capabilities have a negative effect on the device's battery and user's data
+ * usage, therefore you should requested them when absolutely necessary.</p>
*
* @param request specific details about this request
* @param callback will be called once there's at least one device found for user to choose from
@@ -106,17 +119,16 @@
try {
mService.associate(
request,
- new IOnAssociateCallback.Stub() {
-
+ new IFindDeviceCallback.Stub() {
@Override
- public void onSuccess(PendingIntent launcher) throws RemoteException {
+ public void onSuccess(PendingIntent launcher) {
finalHandler.post(() -> {
callback.onDeviceFound(launcher.getIntentSender());
});
}
@Override
- public void onFailure(CharSequence reason) throws RemoteException {
+ public void onFailure(CharSequence reason) {
finalHandler.post(() -> callback.onFailure(reason));
}
},
diff --git a/core/java/android/companion/ICompanionDeviceManagerService.aidl b/core/java/android/companion/ICompanionDeviceDiscoveryService.aidl
similarity index 71%
rename from core/java/android/companion/ICompanionDeviceManagerService.aidl
rename to core/java/android/companion/ICompanionDeviceDiscoveryService.aidl
index ff2a7eb..4d77963 100644
--- a/core/java/android/companion/ICompanionDeviceManagerService.aidl
+++ b/core/java/android/companion/ICompanionDeviceDiscoveryService.aidl
@@ -17,13 +17,14 @@
package android.companion;
import android.companion.AssociationRequest;
-import android.companion.IOnAssociateCallback;
-
+import android.companion.ICompanionDeviceDiscoveryServiceCallback;
+import android.companion.IFindDeviceCallback;
/** @hide */
-interface ICompanionDeviceManagerService {
+interface ICompanionDeviceDiscoveryService {
void startDiscovery(
in AssociationRequest request,
- in IOnAssociateCallback callback,
- in String callingPackage);
+ in String callingPackage,
+ in IFindDeviceCallback findCallback,
+ in ICompanionDeviceDiscoveryServiceCallback serviceCallback);
}
diff --git a/core/java/android/companion/ICompanionDeviceManagerServiceCallback.aidl b/core/java/android/companion/ICompanionDeviceDiscoveryServiceCallback.aidl
similarity index 81%
rename from core/java/android/companion/ICompanionDeviceManagerServiceCallback.aidl
rename to core/java/android/companion/ICompanionDeviceDiscoveryServiceCallback.aidl
index c9dd345..7af708e 100644
--- a/core/java/android/companion/ICompanionDeviceManagerServiceCallback.aidl
+++ b/core/java/android/companion/ICompanionDeviceDiscoveryServiceCallback.aidl
@@ -16,9 +16,7 @@
package android.companion;
-import android.bluetooth.BluetoothDevice;
-
/** @hide */
-interface ICompanionDeviceManagerServiceCallback {
- void onDeviceSelected(in BluetoothDevice device);
+interface ICompanionDeviceDiscoveryServiceCallback {
+ void onDeviceSelected(String packageName, int userId);
}
diff --git a/core/java/android/companion/ICompanionDeviceManager.aidl b/core/java/android/companion/ICompanionDeviceManager.aidl
index 065e31b..1d30ada 100644
--- a/core/java/android/companion/ICompanionDeviceManager.aidl
+++ b/core/java/android/companion/ICompanionDeviceManager.aidl
@@ -16,7 +16,7 @@
package android.companion;
-import android.companion.IOnAssociateCallback;
+import android.companion.IFindDeviceCallback;
import android.companion.AssociationRequest;
/**
@@ -26,8 +26,8 @@
*/
interface ICompanionDeviceManager {
void associate(in AssociationRequest request,
- in IOnAssociateCallback callback,
- in String callingPackage); //TODO int userId?
+ in IFindDeviceCallback callback,
+ in String callingPackage);
//TODO add these
// boolean haveNotificationAccess(String packageName);
diff --git a/core/java/android/companion/IOnAssociateCallback.aidl b/core/java/android/companion/IFindDeviceCallback.aidl
similarity index 95%
rename from core/java/android/companion/IOnAssociateCallback.aidl
rename to core/java/android/companion/IFindDeviceCallback.aidl
index 4867eadd..919e1519 100644
--- a/core/java/android/companion/IOnAssociateCallback.aidl
+++ b/core/java/android/companion/IFindDeviceCallback.aidl
@@ -19,7 +19,7 @@
import android.app.PendingIntent;
/** @hide */
-interface IOnAssociateCallback {
+interface IFindDeviceCallback {
void onSuccess(in PendingIntent launcher);
void onFailure(in CharSequence reason);
}
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 028a7bcf..b0505ac 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -669,13 +669,14 @@
* preview. {@link #getClipData} contains an optional list of content URIs
* if there is more than one item to preview. {@link #EXTRA_INDEX} is an
* optional index of the URI in the clip data to show first.
- * If {@link #EXTRA_QUICK_VIEW_PLAIN} is true, then the quick viewer should show
- * basic UI without any extra features other than quick viewing the passed items.
- * Especially, the quick viewer should not let users open the passed files
- * in other apps, which includes sharing, opening, editing, printing, etc in the
- * plain mode.
+ * <p>By default quick viewers are supposed to be lightweight and focus on
+ * previewing the content only. They should not expose features such as printing,
+ * opening in an external app, deleting, rotating, casting, etc.
+ * However, if {@link #EXTRA_QUICK_VIEW_ADVANCED} is true, then the quick viewer
+ * may show advanced UI which includes convenience actions suitable for the passed
+ * Uris.
* <p>Output: nothing.
- * @see #EXTRA_QUICK_VIEW_HIDE_DEFAULT_ACTIONS
+ * @see #EXTRA_QUICK_VIEW_ADVANCED
* @see #EXTRA_INDEX
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
@@ -4413,19 +4414,15 @@
public static final String EXTRA_INDEX = "android.intent.extra.INDEX";
/**
- * Shows a plain quick viewer UI which doesn't provide any extra features other than
- * quick viewing the items.
- *
- * <p>Especially, the quick viewer should not let users open the quick viewed files
- * in other apps, which includes sharing, opening, editing, printing, etc.
- *
- * <p>This feature is optional, and may not be handled by all quick viewers.
+ * Tells the quick viewer to show additional UI actions suitable for the passed Uris,
+ * such as opening in other apps, sharing, opening, editing, printing, deleting,
+ * casting, etc.
*
* <p>The value is boolean. By default false.
* @see ACTION_QUICK_VIEW
*/
- public static final String EXTRA_QUICK_VIEW_PLAIN =
- "android.intent.extra.QUICK_VIEW_PLAIN";
+ public static final String EXTRA_QUICK_VIEW_ADVANCED =
+ "android.intent.extra.QUICK_VIEW_ADVANCED";
/**
* Optional boolean extra indicating whether quiet mode has been switched on or off.
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index acb1d07..719a957 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -2998,8 +2998,8 @@
*
* This function behaves identically to the non-timedout version, but if a suitable
* network is not found within the given time (in milliseconds) the
- * {@link NetworkCallback#unavailable} callback is called. The request must
- * still be released normally by calling {@link unregisterNetworkCallback(NetworkCallback)}.
+ * {@link NetworkCallback#onUnavailable()} callback is called. The request must
+ * still be released normally by calling {@link #unregisterNetworkCallback(NetworkCallback)}.
*
* <p>This method requires the caller to hold either the
* {@link android.Manifest.permission#CHANGE_NETWORK_STATE} permission
@@ -3011,10 +3011,7 @@
* the callbacks must not be shared - they uniquely specify
* this request.
* @param timeoutMs The time in milliseconds to attempt looking for a suitable network
- * before {@link NetworkCallback#unavailable} is called.
- *
- * TODO: Make timeouts work and then unhide this method.
- *
+ * before {@link NetworkCallback#onUnavailable()} is called.
* @hide
*/
public void requestNetwork(NetworkRequest request, NetworkCallback networkCallback,
@@ -3024,13 +3021,6 @@
}
/**
- * The maximum number of milliseconds the framework will look for a suitable network
- * during a timeout-equiped call to {@link requestNetwork}.
- * {@hide}
- */
- public final static int MAX_NETWORK_REQUEST_TIMEOUT_MS = 100 * 60 * 1000;
-
- /**
* The lookup key for a {@link Network} object included with the intent after
* successfully finding a network for the applications request. Retrieve it with
* {@link android.content.Intent#getParcelableExtra(String)}.
diff --git a/core/java/android/preference/SeekBarVolumizer.java b/core/java/android/preference/SeekBarVolumizer.java
index 11b9606..ee8eed1 100644
--- a/core/java/android/preference/SeekBarVolumizer.java
+++ b/core/java/android/preference/SeekBarVolumizer.java
@@ -348,8 +348,8 @@
if (msg.what == UPDATE_SLIDER) {
if (mSeekBar != null) {
mLastProgress = msg.arg1;
- mLastAudibleStreamVolume = Math.abs(msg.arg2);
- final boolean muted = msg.arg2 < 0;
+ mLastAudibleStreamVolume = msg.arg2;
+ final boolean muted = ((Boolean)msg.obj).booleanValue();
if (muted != mMuted) {
mMuted = muted;
if (mCallback != null) {
@@ -362,8 +362,7 @@
}
public void postUpdateSlider(int volume, int lastAudibleVolume, boolean mute) {
- final int arg2 = lastAudibleVolume * (mute ? -1 : 1);
- obtainMessage(UPDATE_SLIDER, volume, arg2).sendToTarget();
+ obtainMessage(UPDATE_SLIDER, volume, lastAudibleVolume, new Boolean(mute)).sendToTarget();
}
}
diff --git a/core/java/android/text/Emoji.java b/core/java/android/text/Emoji.java
index b6d720d..83810b0 100644
--- a/core/java/android/text/Emoji.java
+++ b/core/java/android/text/Emoji.java
@@ -164,6 +164,8 @@
public static int VARIATION_SELECTOR_16 = 0xFE0F;
+ public static int CANCEL_TAG = 0xE007F;
+
// Returns true if the given code point is regional indicator symbol.
public static boolean isRegionalIndicatorSymbol(int codepoint) {
return 0x1F1E6 <= codepoint && codepoint <= 0x1F1FF;
@@ -188,4 +190,13 @@
public static boolean isKeycapBase(int codePoint) {
return ('0' <= codePoint && codePoint <= '9') || codePoint == '#' || codePoint == '*';
}
+
+ /**
+ * Returns true if the character can be a part of tag_spec in emoji tag sequence.
+ *
+ * Note that 0xE007F (CANCEL TAG) is not included.
+ */
+ public static boolean isTagSpecChar(int codePoint) {
+ return 0xE0020 <= codePoint && codePoint <= 0xE007E;
+ }
}
diff --git a/core/java/android/text/method/BaseKeyListener.java b/core/java/android/text/method/BaseKeyListener.java
index 90559dc..5f0a46d 100644
--- a/core/java/android/text/method/BaseKeyListener.java
+++ b/core/java/android/text/method/BaseKeyListener.java
@@ -145,8 +145,11 @@
// The number of following RIS code points is even.
final int STATE_EVEN_NUMBERED_RIS = 11;
+ // The offset is in emoji tag sequence.
+ final int STATE_IN_TAG_SEQUENCE = 12;
+
// The state machine has been stopped.
- final int STATE_FINISHED = 12;
+ final int STATE_FINISHED = 13;
int deleteCharCount = 0; // Char count to be deleted by backspace.
int lastSeenVSCharCount = 0; // Char count of previous variation selector.
@@ -173,6 +176,8 @@
state = STATE_BEFORE_KEYCAP;
} else if (Emoji.isEmoji(codePoint)) {
state = STATE_BEFORE_EMOJI;
+ } else if (codePoint == Emoji.CANCEL_TAG) {
+ state = STATE_IN_TAG_SEQUENCE;
} else {
state = STATE_FINISHED;
}
@@ -275,6 +280,20 @@
state = STATE_FINISHED;
}
break;
+ case STATE_IN_TAG_SEQUENCE:
+ if (Emoji.isTagSpecChar(codePoint)) {
+ deleteCharCount += 2; /* Char count of emoji tag spec character. */
+ // Keep the same state.
+ } else if (Emoji.isEmoji(codePoint)) {
+ deleteCharCount += Character.charCount(codePoint);
+ state = STATE_FINISHED;
+ } else {
+ // Couldn't find tag_base character. Delete the last tag_term character.
+ deleteCharCount = 2; // for U+E007F
+ state = STATE_FINISHED;
+ }
+ // TODO: Need handle emoji variation selectors. Issue 35224297
+ break;
default:
throw new IllegalArgumentException("state " + state + " is unknown");
}
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index 2129039..5f55bdc 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -1008,7 +1008,6 @@
* </p>
*
* @see #getAxisValue(int, int)
- * {@hide}
*/
public static final int AXIS_SCROLL = 26;
diff --git a/core/java/android/view/ViewStructure.java b/core/java/android/view/ViewStructure.java
index cc19539..9ce23e6 100644
--- a/core/java/android/view/ViewStructure.java
+++ b/core/java/android/view/ViewStructure.java
@@ -25,7 +25,8 @@
/**
* Container for storing additional per-view data generated by {@link View#onProvideStructure
- * View.onProvideStructure}.
+ * View.onProvideStructure} and {@link View#onProvideAutoFillStructure
+ * View.onProvideAutoFillStructure}.
*/
public abstract class ViewStructure {
@@ -33,7 +34,9 @@
* Flag used when adding virtual views for auto-fill, it indicates the contents of the view
* (such as * {@link android.app.assist.AssistStructure.ViewNode#getText()} and
* {@link android.app.assist.AssistStructure.ViewNode#getAutoFillValue()})
- * can be passed to the {@link android.service.autofill.AutoFillService}.
+ * can be passed to the {@link
+ * android.service.autofill.AutoFillService#onFillRequest(android.app.assist.AssistStructure,
+ * Bundle, android.os.CancellationSignal, android.service.autofill.FillCallback)} call.
*/
public static final int AUTO_FILL_FLAG_SANITIZED = 0x1;
@@ -275,7 +278,7 @@
*
* @param index child index
* @param virtualId id identifying the virtual child inside the custom view.
- * @param flags currently {@code 0}.
+ * @param flags currently {@code 0} or {@link #AUTO_FILL_FLAG_SANITIZED}.
*/
// TODO(b/33197203, b/33802548): add CTS/unit test
public abstract ViewStructure newChild(int index, int virtualId, int flags);
@@ -296,7 +299,7 @@
*
* @param index child index
* @param virtualId id identifying the virtual child inside the custom view.
- * @param flags currently {@code 0}.
+ * @param flags currently {@code 0} or {@link #AUTO_FILL_FLAG_SANITIZED}.
*/
// TODO(b/33197203, b/33802548): add CTS/unit test
public abstract ViewStructure asyncNewChild(int index, int virtualId, int flags);
@@ -335,4 +338,17 @@
/** @hide */
public abstract AutoFillId getAutoFillId();
+
+ /**
+ * Sets the URL represented by this node.
+ *
+ * <p>Typically used in the following situations:
+ *
+ * <ol>
+ * <li>In a {@link android.app.assist.AssistStructure.WindowNode#getRootViewNode()}, to set up
+ * the main URL of an HTML page.
+ * <li>On child nodes represening hyperlinks.
+ * </ol>
+ */
+ public abstract void setUrl(String url);
}
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 0b5a1b7..310cbc7 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -584,6 +584,7 @@
OsConstants.CAP_NET_RAW,
OsConstants.CAP_SYS_MODULE,
OsConstants.CAP_SYS_NICE,
+ OsConstants.CAP_SYS_PTRACE,
OsConstants.CAP_SYS_RESOURCE,
OsConstants.CAP_SYS_TIME,
OsConstants.CAP_SYS_TTY_CONFIG,
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index cd02fbb..97fbfa5 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1813,6 +1813,22 @@
android:description="@string/permdesc_systemAlertWindow"
android:protectionLevel="signature|preinstalled|appop|pre23|development" />
+ <!-- Allows an app to run in the background.
+ <p>Protection level: signature
+ -->
+ <permission android:name="android.permission.RUN_IN_BACKGROUND"
+ android:label="@string/permlab_runInBackground"
+ android:description="@string/permdesc_runInBackground"
+ android:protectionLevel="signature" />
+
+ <!-- Allows an app to use data in the background.
+ <p>Protection level: signature
+ -->
+ <permission android:name="android.permission.USE_DATA_IN_BACKGROUND"
+ android:label="@string/permlab_useDataInBackground"
+ android:description="@string/permdesc_useDataInBackground"
+ android:protectionLevel="signature" />
+
<!-- ================================== -->
<!-- Permissions affecting the system wallpaper -->
<!-- ================================== -->
@@ -2996,7 +3012,7 @@
any metadata and intents attached.
@hide -->
<permission android:name="android.permission.ACCESS_NOTIFICATIONS"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged|appop" />
<!-- Marker permission for applications that wish to access notification policy.
<p>Protection level: normal
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 72a2e43..fcb0e08 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1286,6 +1286,16 @@
<item>com.android.networkrecommendation</item>
</string-array>
+ <!-- The package name of the default network recommendation app.
+ A network recommendation provider must:
+ * Be granted the SCORE_NETWORKS permission.
+ * 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.
+ -->
+ <string name="config_defaultNetworkRecommendationProviderPackage" translatable="false">com.android.networkrecommendation</string>
+
<!-- Whether to enable Hardware FLP overlay which allows Hardware FLP to be
replaced by an app at run-time. When disabled, only the
config_hardwareFlpPackageName package will be searched for Hardware Flp,
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 2309866..8faa76c 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -816,6 +816,16 @@
<string name="permdesc_systemAlertWindow">This app can appear on top of other apps or other parts of the screen. This may interfere with normal app usage and change the way that other apps appear.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permlab_runInBackground">run in the background</string>
+ <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permdesc_runInBackground">This app can run in the background. This may drain battery faster.</string>
+
+ <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permlab_useDataInBackground">use data in the background</string>
+ <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permdesc_useDataInBackground">This app can use data in the background. This may increase data usage.</string>
+
+ <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permlab_persistentActivity">make app always run</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_persistentActivity" product="tablet">Allows the app to make parts of itself persistent in memory. This can limit memory available to other apps slowing down the tablet.</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 1324e38..0d63a1e 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2790,6 +2790,7 @@
<!-- Network Recommendation -->
<java-symbol type="array" name="config_networkRecommendationPackageNames" />
+ <java-symbol type="string" name="config_defaultNetworkRecommendationProviderPackage" />
<!-- Whether allow 3rd party apps on internal storage. -->
<java-symbol type="bool" name="config_allow3rdPartyAppOnInternal" />
diff --git a/core/tests/coretests/src/android/text/method/BackspaceTest.java b/core/tests/coretests/src/android/text/method/BackspaceTest.java
index a260e94..864b48a 100644
--- a/core/tests/coretests/src/android/text/method/BackspaceTest.java
+++ b/core/tests/coretests/src/android/text/method/BackspaceTest.java
@@ -37,23 +37,12 @@
// Sync the state to the TextView and call onKeyDown with KEYCODE_DEL key event.
// Then update the state to the result of TextView.
private void backspace(final EditorState state, int modifiers) {
- mActivity.runOnUiThread(new Runnable() {
- public void run() {
- mTextView.setText(state.mText, BufferType.EDITABLE);
- mTextView.setKeyListener(mKeyListener);
- mTextView.setSelection(state.mSelectionStart, state.mSelectionEnd);
- }
- });
- mInstrumentation.waitForIdleSync();
- assertTrue(mTextView.hasWindowFocus());
+ mTextView.setText(state.mText, BufferType.EDITABLE);
+ mTextView.setKeyListener(mKeyListener);
+ mTextView.setSelection(state.mSelectionStart, state.mSelectionEnd);
final KeyEvent keyEvent = getKey(KeyEvent.KEYCODE_DEL, modifiers);
- mActivity.runOnUiThread(new Runnable() {
- public void run() {
- mTextView.onKeyDown(keyEvent.getKeyCode(), keyEvent);
- }
- });
- mInstrumentation.waitForIdleSync();
+ mTextView.onKeyDown(keyEvent.getKeyCode(), keyEvent);
state.mText = mTextView.getText();
state.mSelectionStart = mTextView.getSelectionStart();
@@ -247,6 +236,51 @@
state.assertEquals("U+1F1FA U+1F1F8 |");
backspace(state, 0);
state.assertEquals("|");
+
+ // Incomplete sequence. (no tag_term: U+E007E)
+ state.setByString("'a' U+1F3F4 U+E0067 'b' |");
+ backspace(state, 0);
+ state.assertEquals("'a' U+1F3F4 U+E0067 |");
+ backspace(state, 0);
+ state.assertEquals("'a' U+1F3F4 |");
+ backspace(state, 0);
+ state.assertEquals("'a' |");
+
+ // No tag_base
+ state.setByString("'a' U+E0067 U+E007F 'b' |");
+ backspace(state, 0);
+ state.assertEquals("'a' U+E0067 U+E007F |");
+ backspace(state, 0);
+ state.assertEquals("'a' U+E0067 |");
+ backspace(state, 0);
+ state.assertEquals("'a' |");
+
+ // Isolated tag chars
+ state.setByString("'a' U+E0067 U+E0067 'b' |");
+ backspace(state, 0);
+ state.assertEquals("'a' U+E0067 U+E0067 |");
+ backspace(state, 0);
+ state.assertEquals("'a' U+E0067 |");
+ backspace(state, 0);
+ state.assertEquals("'a' |");
+
+ // Isolated tab term.
+ state.setByString("'a' U+E007F U+E007F 'b' |");
+ backspace(state, 0);
+ state.assertEquals("'a' U+E007F U+E007F |");
+ backspace(state, 0);
+ state.assertEquals("'a' U+E007F |");
+ backspace(state, 0);
+ state.assertEquals("'a' |");
+
+ // Immediate tag_term after tag_base
+ state.setByString("'a' U+1F3F4 U+E007F U+1F3F4 U+E007F 'b' |");
+ backspace(state, 0);
+ state.assertEquals("'a' U+1F3F4 U+E007F U+1F3F4 U+E007F |");
+ backspace(state, 0);
+ state.assertEquals("'a' U+1F3F4 U+E007F |");
+ backspace(state, 0);
+ state.assertEquals("'a' |");
}
@SmallTest
diff --git a/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java b/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java
index 1990fd0..839d380 100644
--- a/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java
+++ b/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java
@@ -37,23 +37,12 @@
// Sync the state to the TextView and call onKeyDown with KEYCODE_FORWARD_DEL key event.
// Then update the state to the result of TextView.
private void forwardDelete(final EditorState state, int modifiers) {
- mActivity.runOnUiThread(new Runnable() {
- public void run() {
- mTextView.setText(state.mText, BufferType.EDITABLE);
- mTextView.setKeyListener(mKeyListener);
- mTextView.setSelection(state.mSelectionStart, state.mSelectionEnd);
- }
- });
- mInstrumentation.waitForIdleSync();
- assertTrue(mTextView.hasWindowFocus());
+ mTextView.setText(state.mText, BufferType.EDITABLE);
+ mTextView.setKeyListener(mKeyListener);
+ mTextView.setSelection(state.mSelectionStart, state.mSelectionEnd);
final KeyEvent keyEvent = getKey(KeyEvent.KEYCODE_FORWARD_DEL, modifiers);
- mActivity.runOnUiThread(new Runnable() {
- public void run() {
- mTextView.onKeyDown(keyEvent.getKeyCode(), keyEvent);
- }
- });
- mInstrumentation.waitForIdleSync();
+ mTextView.onKeyDown(keyEvent.getKeyCode(), keyEvent);
state.mText = mTextView.getText();
state.mSelectionStart = mTextView.getSelectionStart();
@@ -186,6 +175,46 @@
state.assertEquals("| U+1F1FA");
forwardDelete(state, 0);
state.assertEquals("|");
+
+ // Incomplete sequence. (no tag_term:U+E007E)
+ state.setByString("| 'a' U+1F3F4 U+E0067 'b'");
+ forwardDelete(state, 0);
+ state.assertEquals("| U+1F3F4 U+E0067 'b'");
+ forwardDelete(state, 0);
+ state.assertEquals("| 'b'");
+
+ // No tag_base
+ state.setByString("| 'a' U+E0067 U+E007F 'b'");
+ forwardDelete(state, 0);
+ state.assertEquals("| 'b'");
+
+ // Isolated tag chars
+ state.setByString("| 'a' U+E0067 U+E0067 'b'");
+ forwardDelete(state, 0);
+ state.assertEquals("| 'b'");
+
+ // Isolated tag base.
+ state.setByString("| 'a' U+1F3F4 U+1F3F4 'b'");
+ forwardDelete(state, 0);
+ state.assertEquals("| U+1F3F4 U+1F3F4 'b'");
+ forwardDelete(state, 0);
+ state.assertEquals("| U+1F3F4 'b'");
+ forwardDelete(state, 0);
+ state.assertEquals("| 'b'");
+
+ // Isolated tab term.
+ state.setByString("| 'a' U+E007F U+E007F 'b'");
+ forwardDelete(state, 0);
+ state.assertEquals("| 'b'");
+
+ // Immediate tag_term after tag_base
+ state.setByString("| 'a' U+1F3F4 U+E007F U+1F3F4 U+E007F 'b'");
+ forwardDelete(state, 0);
+ state.assertEquals("| U+1F3F4 U+E007F U+1F3F4 U+E007F 'b'");
+ forwardDelete(state, 0);
+ state.assertEquals("| U+1F3F4 U+E007F 'b'");
+ forwardDelete(state, 0);
+ state.assertEquals("| 'b'");
}
@SmallTest
diff --git a/core/tests/coretests/src/android/text/method/KeyListenerTestCase.java b/core/tests/coretests/src/android/text/method/KeyListenerTestCase.java
index 4b4e7af..f005d7b 100644
--- a/core/tests/coretests/src/android/text/method/KeyListenerTestCase.java
+++ b/core/tests/coretests/src/android/text/method/KeyListenerTestCase.java
@@ -17,41 +17,26 @@
package android.text.method;
import android.app.Instrumentation;
-import android.test.ActivityInstrumentationTestCase2;
-import android.text.format.DateUtils;
+import android.test.InstrumentationTestCase;
import android.view.KeyEvent;
import android.widget.EditText;
-import android.widget.TextViewActivity;
import com.android.frameworks.coretests.R;
-public abstract class KeyListenerTestCase extends
- ActivityInstrumentationTestCase2<TextViewActivity> {
+public abstract class KeyListenerTestCase extends InstrumentationTestCase {
- protected TextViewActivity mActivity;
protected Instrumentation mInstrumentation;
protected EditText mTextView;
public KeyListenerTestCase() {
- super(TextViewActivity.class);
}
@Override
protected void setUp() throws Exception {
super.setUp();
- mActivity = getActivity();
mInstrumentation = getInstrumentation();
- mTextView = (EditText) mActivity.findViewById(R.id.textview);
-
- mActivity.runOnUiThread(new Runnable() {
- public void run() {
- // Ensure that the screen is on for this test.
- mTextView.setKeepScreenOn(true);
- }
- });
-
- assertTrue(mActivity.waitForWindowFocus(5 * DateUtils.SECOND_IN_MILLIS));
+ mTextView = new EditText(mInstrumentation.getContext());
}
protected static KeyEvent getKey(int keycode, int metaState) {
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 85c3c1c..5008a5f 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -640,6 +640,8 @@
private UUID mDrmUUID;
private final Object mDrmLock = new Object();
private DrmInfo mDrmInfo;
+ private MediaDrm mDrmObj;
+ private byte[] mDrmSessionId;
private boolean mDrmInfoResolved;
private boolean mActiveDrmScheme;
private boolean mDrmConfigAllowed;
@@ -1960,6 +1962,7 @@
mOnSubtitleDataListener = null;
// Modular DRM clean up
+ mOnDrmConfigListener = null;
mOnDrmInfoHandlerDelegate = null;
mOnDrmPreparedHandlerDelegate = null;
resetDrmState();
@@ -3171,7 +3174,7 @@
onDrmInfoHandlerDelegate.notifyClient(drmInfo);
}
} else {
- Log.w(TAG, "MEDIA_DRM_INFO msg.obj NONE; UNEXPECTED" + msg.obj);
+ Log.w(TAG, "MEDIA_DRM_INFO msg.obj of unexpected type " + msg.obj);
}
return;
@@ -3846,17 +3849,34 @@
* and setDrmPropertyString.
*
*/
- public static abstract class OnDrmConfigCallback
+ public interface OnDrmConfigListener
{
/**
* Called to give the app the opportunity to configure DRM before the session is created
*
* @param mp the {@code MediaPlayer} associated with this callback
*/
- public void onDrmConfig(MediaPlayer mp) {}
+ public void onDrmConfig(MediaPlayer mp);
}
/**
+ * Register a callback to be invoked for configuration of the DRM object before
+ * the session is created.
+ * The callback will be invoked synchronously half-way into the execution
+ * of {@link #prepareDrm(UUID uuid)}.
+ *
+ * @param listener the callback that will be run
+ */
+ public void setOnDrmConfigListener(OnDrmConfigListener listener)
+ {
+ synchronized (mDrmLock) {
+ mOnDrmConfigListener = listener;
+ } // synchronized
+ }
+
+ private OnDrmConfigListener mOnDrmConfigListener;
+
+ /**
* Interface definition of a callback to be invoked when the
* DRM info becomes available
*/
@@ -4053,13 +4073,11 @@
return drmInfo;
}
- private native void _prepareDrm(@NonNull byte[] uuid, int mode)
- throws UnsupportedSchemeException, ResourceBusyException, NotProvisionedException;
/**
* Prepares the DRM for the current source
* <p>
- * If {@code OnDrmConfigCallback} is registered, it will be called half-way into
+ * If {@code OnDrmConfigListener} is registered, it will be called half-way into
* preparation to allow configuration of the DRM properties before opening the
* DRM session. Note that the callback is called synchronously in the thread that called
* {@code prepareDrm}. It should be used only for a series of {@code getDrmPropertyString}
@@ -4087,10 +4105,12 @@
* @throws ResourceBusyException if required DRM resources are in use
* @throws ProvisioningErrorException if provisioning is required but an attempt failed
*/
- public void prepareDrm(@NonNull UUID uuid, OnDrmConfigCallback configCallback)
+ public void prepareDrm(@NonNull UUID uuid)
throws UnsupportedSchemeException,
ResourceBusyException, ProvisioningErrorException
{
+ Log.v(TAG, "prepareDrm: uuid: " + uuid + " mOnDrmConfigListener: " + mOnDrmConfigListener);
+
boolean allDoneWithoutProvisioning = false;
// get a snapshot as we'll use them outside the lock
OnDrmPreparedHandlerDelegate onDrmPreparedHandlerDelegate = null;
@@ -4099,58 +4119,46 @@
// only allowing if tied to a protected source; might releax for releasing offline keys
if (mDrmInfo == null) {
- final String msg = String.format("prepareDrm(%s): Wrong usage: " +
- "The player must be prepared and DRM " +
- "info be retrieved before this call.", uuid);
+ final String msg = "prepareDrm(): Wrong usage: The player must be prepared and " +
+ "DRM info be retrieved before this call.";
Log.e(TAG, msg);
throw new IllegalStateException(msg);
}
if (mActiveDrmScheme) {
- final String msg = String.format("prepareDrm(%s): Wrong usage: There is already " +
- "an active DRM scheme with %s.", uuid, mDrmUUID);
+ final String msg = "prepareDrm(): Wrong usage: There is already " +
+ "an active DRM scheme with " + mDrmUUID;
Log.e(TAG, msg);
throw new IllegalStateException(msg);
}
if (mPrepareDrmInProgress) {
- final String msg = String.format("prepareDrm(%s): Wrong usage: There is already " +
- "a pending prepareDrm call.", uuid);
+ final String msg = "prepareDrm(): Wrong usage: There is already " +
+ "a pending prepareDrm call.";
Log.e(TAG, msg);
throw new IllegalStateException(msg);
}
if (mDrmProvisioningInProgress) {
- final String msg = String.format("prepareDrm(%s): Unexpectd: Provisioning is " +
- "already in progress.", uuid);
+ final String msg = "prepareDrm(): Unexpectd: Provisioning is already in progress.";
Log.e(TAG, msg);
throw new IllegalStateException(msg);
}
+ // shouldn't need this; just for safeguard
+ cleanDrmObj();
+
mPrepareDrmInProgress = true;
// local copy while the lock is held
onDrmPreparedHandlerDelegate = mOnDrmPreparedHandlerDelegate;
- if (configCallback != null) {
- try {
- boolean allowOpenSession = false; // just pre-openSession
- _prepareDrm(getByteArrayFromUUID(uuid), allowOpenSession ? 1 : 0);
- } catch (IllegalStateException e) {
- final String msg = String.format("prepareDrm(): Wrong usage: The player must " +
- "be in prepared state to call prepareDrm().");
- Log.e(TAG, msg);
- throw new IllegalStateException(msg);
- } catch (NotProvisionedException e) { // the pre-config step won't raise this
- final String msg = String.format("prepareDrm: Unexpected " +
- "NotProvisionedException here.");
- Log.e(TAG, msg);
- throw new ProvisioningErrorException(msg);
- } catch (Exception e) {
- Log.w(TAG, String.format("prepareDrm: Exception %s", e));
- throw e;
- } finally {
- mPrepareDrmInProgress = false;
- }
+ try {
+ // only creating the DRM object to allow pre-openSession configuration
+ prepareDrm_createDrmStep(uuid);
+ } catch (Exception e) {
+ Log.w(TAG, "prepareDrm(): Exception ", e);
+ mPrepareDrmInProgress = false;
+ throw e;
}
mDrmConfigAllowed = true;
@@ -4158,51 +4166,55 @@
// call the callback outside the lock
- if (configCallback != null) {
- configCallback.onDrmConfig(this);
+ if (mOnDrmConfigListener != null) {
+ mOnDrmConfigListener.onDrmConfig(this);
}
synchronized (mDrmLock) {
mDrmConfigAllowed = false;
+ boolean earlyExit = false;
try {
- boolean allowOpenSession = true; // all in
- _prepareDrm(getByteArrayFromUUID(uuid), allowOpenSession ? 1 : 0);
+ prepareDrm_openSessionStep(uuid);
mDrmUUID = uuid;
mActiveDrmScheme = true;
- mPrepareDrmInProgress = false;
-
allDoneWithoutProvisioning = true;
} catch (IllegalStateException e) {
- final String msg = String.format("prepareDrm(%s): Wrong usage: The player must be" +
- " in prepared state to call prepareDrm().", uuid);
+ final String msg = "prepareDrm(): Wrong usage: The player must be " +
+ "in the prepared state to call prepareDrm().";
Log.e(TAG, msg);
+ earlyExit = true;
throw new IllegalStateException(msg);
} catch (NotProvisionedException e) {
- Log.w(TAG, String.format("prepareDrm: NotProvisionedException"));
+ Log.w(TAG, "prepareDrm: NotProvisionedException");
- // handle provisioning internally
+ // handle provisioning internally; it'll reset mPrepareDrmInProgress
boolean result = HandleProvisioninig(uuid);
// if blocking mode, we're already done;
// if non-blocking mode, we attempted to launch background provisioning
if (result == false) {
- final String msg =
- String.format("prepareDrm: Provisioning was required but failed.");
+ final String msg = "prepareDrm: Provisioning was required but failed.";
Log.e(TAG, msg);
+ earlyExit = true;
throw new ProvisioningErrorException(msg);
}
-
// nothing else to do;
// if blocking or non-blocking, HandleProvisioninig does the re-attempt & cleanup
} catch (Exception e) {
- Log.w(TAG, String.format("prepareDrm: Exception %s", e));
+ Log.e(TAG, "prepareDrm: Exception " + e);
+ earlyExit = true;
throw e;
} finally {
- mPrepareDrmInProgress = false;
- }
+ if (!mDrmProvisioningInProgress) {// if early exit other than provisioning exception
+ mPrepareDrmInProgress = false;
+ }
+ if (earlyExit) { // cleaning up object if didn't succeed
+ cleanDrmObj();
+ }
+ } // finally
} // synchronized
@@ -4225,25 +4237,33 @@
public void releaseDrm()
throws NoDrmSchemeException
{
+ Log.v(TAG, "releaseDrm:");
+
synchronized (mDrmLock) {
if (!mActiveDrmScheme) {
- Log.e(TAG, String.format("releaseDrm(%s): No active DRM scheme to release."));
+ Log.e(TAG, "releaseDrm(): No active DRM scheme to release.");
throw new NoDrmSchemeException("releaseDrm: No active DRM scheme to release.");
- } else {
+ }
+
+ try {
+ // we don't have the player's state in this layer. The below call raises
+ // exception if we're in a non-stopped/idle state.
+
+ // for cleaning native/mediaserver crypto object
_releaseDrm();
+ // for cleaning client-side MediaDrm object; only called if above has succeeded
+ cleanDrmObj();
+
mActiveDrmScheme = false;
+ } catch (Exception e) {
+ Log.w(TAG, "releaseDrm: Exception ", e);
+ throw e;
}
} // synchronized
}
- @NonNull
- private native MediaDrm.KeyRequest _getKeyRequest(@NonNull byte[] scope,
- @Nullable String mimeType, @MediaDrm.KeyType int keyType,
- @Nullable Map<String, String> optionalParameters)
- throws NotProvisionedException;
-
/**
* A key request/response exchange occurs between the app and a license server
* to obtain or release keys used to decrypt encrypted content.
@@ -4284,20 +4304,42 @@
@MediaDrm.KeyType int keyType, @Nullable Map<String, String> optionalParameters)
throws NoDrmSchemeException
{
+ Log.v(TAG, "getKeyRequest: " +
+ " scope: " + scope + " mimeType: " + mimeType +
+ " keyType: " + keyType + " optionalParameters: " + optionalParameters);
+
synchronized (mDrmLock) {
if (!mActiveDrmScheme) {
- Log.e(TAG, String.format("getKeyRequest NoDrmSchemeException"));
+ Log.e(TAG, "getKeyRequest NoDrmSchemeException");
throw new NoDrmSchemeException("getKeyRequest: Has to set a DRM scheme first.");
}
try {
- return _getKeyRequest(scope, mimeType, keyType, optionalParameters);
+ byte[] scopeOut = (keyType != MediaDrm.KEY_TYPE_RELEASE) ?
+ mDrmSessionId : // sessionId for KEY_TYPE_STREAMING/OFFLINE
+ scope; // keySetId for KEY_TYPE_RELEASE
+
+ byte[] initData = (keyType != MediaDrm.KEY_TYPE_RELEASE) ?
+ scope : // initData for KEY_TYPE_STREAMING/OFFLINE
+ null; // not used for KEY_TYPE_RELEASE
+
+ HashMap<String, String> hmapOptionalParameters =
+ (optionalParameters != null) ?
+ new HashMap<String, String>(optionalParameters) :
+ null;
+
+ MediaDrm.KeyRequest request = mDrmObj.getKeyRequest(scopeOut, initData, mimeType,
+ keyType, hmapOptionalParameters);
+ Log.v(TAG, "getKeyRequest: --> request: " + request);
+
+ return request;
+
} catch (NotProvisionedException e) {
- Log.w(TAG, String.format("getKeyRequest NotProvisionedException: " +
- "Unexpected. Shouldn't have reached here."));
+ Log.w(TAG, "getKeyRequest NotProvisionedException: " +
+ "Unexpected. Shouldn't have reached here.");
throw new IllegalStateException("getKeyRequest: Unexpected provisioning error.");
} catch (Exception e) {
- Log.w(TAG, String.format("getKeyRequest Exception %s", e));
+ Log.w(TAG, "getKeyRequest Exception " + e);
throw e;
}
@@ -4305,10 +4347,6 @@
}
- @Nullable
- private native byte[] _provideKeyResponse(@Nullable byte[] keySetId, @NonNull byte[] response)
- throws DeniedByServerException;
-
/**
* A key response is received from the license server by the app, then it is
* provided to the DRM engine plugin using provideKeyResponse. When the
@@ -4331,25 +4369,41 @@
public byte[] provideKeyResponse(@Nullable byte[] keySetId, @NonNull byte[] response)
throws NoDrmSchemeException, DeniedByServerException
{
+ Log.v(TAG, "provideKeyResponse: keySetId: " + keySetId + " response: " + response);
+
synchronized (mDrmLock) {
if (!mActiveDrmScheme) {
- Log.e(TAG, String.format("getKeyRequest NoDrmSchemeException"));
+ Log.e(TAG, "getKeyRequest NoDrmSchemeException");
throw new NoDrmSchemeException("getKeyRequest: Has to set a DRM scheme first.");
}
try {
- return _provideKeyResponse(keySetId, response);
+ byte[] scope = (keySetId == null) ?
+ mDrmSessionId : // sessionId for KEY_TYPE_STREAMING/OFFLINE
+ keySetId; // keySetId for KEY_TYPE_RELEASE
+
+ byte[] keySetResult = mDrmObj.provideKeyResponse(scope, response);
+
+ Log.v(TAG, "provideKeyResponse: keySetId: " + keySetId + " response: " + response +
+ " --> " + keySetResult);
+
+
+ return keySetResult;
+
+ } catch (NotProvisionedException e) {
+ Log.w(TAG, "provideKeyResponse NotProvisionedException: " +
+ "Unexpected. Shouldn't have reached here.");
+ throw new IllegalStateException("provideKeyResponse: " +
+ "Unexpected provisioning error.");
} catch (Exception e) {
- Log.w(TAG, String.format("provideKeyResponse Exception %s", e));
+ Log.w(TAG, "provideKeyResponse Exception " + e);
throw e;
}
} // synchronized
}
- private native void _restoreKeys(@NonNull byte[] keySetId);
-
/**
* Restore persisted offline keys into a new session. keySetId identifies the
* keys to load, obtained from a prior call to {@link #provideKeyResponse}.
@@ -4359,17 +4413,19 @@
public void restoreKeys(@NonNull byte[] keySetId)
throws NoDrmSchemeException
{
+ Log.v(TAG, "restoreKeys: keySetId: " + keySetId);
+
synchronized (mDrmLock) {
if (!mActiveDrmScheme) {
- Log.w(TAG, String.format("restoreKeys NoDrmSchemeException"));
+ Log.w(TAG, "restoreKeys NoDrmSchemeException");
throw new NoDrmSchemeException("restoreKeys: Has to set a DRM scheme first.");
}
try {
- _restoreKeys(keySetId);
+ mDrmObj.restoreKeys(mDrmSessionId, keySetId);
} catch (Exception e) {
- Log.w(TAG, String.format("restoreKeys Exception %s", e));
+ Log.w(TAG, "restoreKeys Exception " + e);
throw e;
}
@@ -4377,9 +4433,6 @@
}
- @NonNull
- private native String _getDrmPropertyString(@NonNull String propertyName);
-
/**
* Read a DRM engine plugin String property value, given the property name string.
* <p>
@@ -4393,26 +4446,29 @@
public String getDrmPropertyString(@NonNull @MediaDrm.StringProperty String propertyName)
throws NoDrmSchemeException
{
+ Log.v(TAG, "getDrmPropertyString: propertyName: " + propertyName);
+
String value;
synchronized (mDrmLock) {
if (!mActiveDrmScheme && !mDrmConfigAllowed) {
- Log.w(TAG, String.format("getDrmPropertyString NoDrmSchemeException"));
+ Log.w(TAG, "getDrmPropertyString NoDrmSchemeException");
throw new NoDrmSchemeException("getDrmPropertyString: Has to prepareDrm() first.");
}
try {
- value = _getDrmPropertyString(propertyName);
+ value = mDrmObj.getPropertyString(propertyName);
} catch (Exception e) {
- Log.w(TAG, String.format("getDrmPropertyString Exception %s", e));
+ Log.w(TAG, "getDrmPropertyString Exception " + e);
throw e;
}
} // synchronized
+ Log.v(TAG, "getDrmPropertyString: propertyName: " + propertyName + " --> value: " + value);
+
return value;
}
- private native void _setDrmPropertyString(@NonNull String propertyName, @NonNull String value);
/**
* Set a DRM engine plugin String property value.
@@ -4428,17 +4484,19 @@
@NonNull String value)
throws NoDrmSchemeException
{
+ Log.v(TAG, "setDrmPropertyString: propertyName: " + propertyName + " value: " + value);
+
synchronized (mDrmLock) {
if ( !mActiveDrmScheme && !mDrmConfigAllowed ) {
- Log.w(TAG, String.format("setDrmPropertyString NoDrmSchemeException"));
+ Log.w(TAG, "setDrmPropertyString NoDrmSchemeException");
throw new NoDrmSchemeException("setDrmPropertyString: Has to prepareDrm() first.");
}
try {
- _setDrmPropertyString(propertyName, value);
+ mDrmObj.setPropertyString(propertyName, value);
} catch ( Exception e ) {
- Log.w(TAG, String.format("setDrmPropertyString Exception %s", e));
+ Log.w(TAG, "setDrmPropertyString Exception " + e);
throw e;
}
} // synchronized
@@ -4605,8 +4663,47 @@
}
}
+
+ private native void _prepareDrm(@NonNull byte[] uuid, @NonNull byte[] drmSessionId);
+
// Modular DRM helpers
+ private void prepareDrm_createDrmStep(@NonNull UUID uuid)
+ throws UnsupportedSchemeException {
+ Log.v(TAG, "prepareDrm_createDrmStep: UUID: " + uuid);
+
+ try {
+ mDrmObj = new MediaDrm(uuid);
+ Log.v(TAG, "prepareDrm_createDrmStep: Created mDrmObj=" + mDrmObj);
+ } catch (Exception e) { // UnsupportedSchemeException
+ Log.e(TAG, "prepareDrm_createDrmStep: MediaDrm failed with " + e);
+ throw e;
+ }
+ }
+
+ private void prepareDrm_openSessionStep(@NonNull UUID uuid)
+ throws NotProvisionedException, ResourceBusyException {
+ Log.v(TAG, "prepareDrm_openSessionStep: uuid: " + uuid);
+
+ // TODO: don't need an open session for a future specialKeyReleaseDrm mode but we should do
+ // it anyway so it raises provisioning error if needed. We'd rather handle provisioning
+ // at prepareDrm/openSession rather than getKeyRequest/provideKeyResponse
+ try {
+ mDrmSessionId = mDrmObj.openSession();
+ Log.v(TAG, "prepareDrm_openSessionStep: mDrmSessionId=" + mDrmSessionId);
+
+ // Sending it down to native/mediaserver to create the crypto object
+ // This call could simply fail due to bad player state, e.g., after start().
+ _prepareDrm(getByteArrayFromUUID(uuid), mDrmSessionId);
+ Log.v(TAG, "prepareDrm_openSessionStep: _prepareDrm/Crypto succeeded");
+
+ } catch (Exception e) { //ResourceBusyException, NotProvisionedException
+ Log.e(TAG, "prepareDrm_openSessionStep: open/crypto failed with " + e);
+ throw e;
+ }
+
+ }
+
private class ProvisioningThread extends Thread
{
public static final int TIMEOUT_MS = 60000;
@@ -4633,7 +4730,7 @@
urlStr = request.getDefaultUrl() + "&signedRequest=" + new String(request.getData());
this.uuid = uuid;
- Log.v(TAG, String.format("HandleProvisioninig: Thread is initialised url: %s", urlStr));
+ Log.v(TAG, "HandleProvisioninig: Thread is initialised url: " + urlStr);
return this;
}
@@ -4653,30 +4750,27 @@
connection.connect();
response = Streams.readFully(connection.getInputStream());
- Log.v(TAG, String.format("HandleProvisioninig: Thread run response %d %s",
- response.length, response));
+ Log.v(TAG, "HandleProvisioninig: Thread run: response " +
+ response.length + " " + response);
} catch (Exception e) {
- Log.w(TAG, String.format("HandleProvisioninig: Thread run connect %s url: %s",
- e, url));
+ Log.w(TAG, "HandleProvisioninig: Thread run: connect " + e + " url: " + url);
} finally {
connection.disconnect();
}
} catch (Exception e) {
- Log.w(TAG, String.format("HandleProvisioninig: Thread run openConnection %s", e));
+ Log.w(TAG, "HandleProvisioninig: Thread run: openConnection " + e);
}
if (response != null) {
try {
- MediaDrm drm = new MediaDrm(uuid);
- drm.provideProvisionResponse(response);
- drm.release();
- Log.v(TAG, String.format("HandleProvisioninig: Thread run " +
- "newDrm+provideProvisionResponse SUCCEEDED!"));
+ mDrmObj.provideProvisionResponse(response);
+ Log.v(TAG, "HandleProvisioninig: Thread run: " +
+ "provideProvisionResponse SUCCEEDED!");
provisioningSucceeded = true;
} catch (Exception e) {
- Log.w(TAG, String.format("HandleProvisioninig: Thread run " +
- "newDrm+provideProvisionResponse %s", e));
+ Log.w(TAG, "HandleProvisioninig: Thread run: " +
+ "provideProvisionResponse " + e);
}
}
@@ -4690,7 +4784,10 @@
}
mediaPlayer.mDrmProvisioningInProgress = false;
mediaPlayer.mPrepareDrmInProgress = false;
- }
+ if (!succeeded) {
+ cleanDrmObj(); // cleaning up if it hasn't gone through while in the lock
+ }
+ } // synchronized
// calling the callback outside the lock
onDrmPreparedHandlerDelegate.notifyClient(succeeded);
@@ -4702,6 +4799,9 @@
}
mediaPlayer.mDrmProvisioningInProgress = false;
mediaPlayer.mPrepareDrmInProgress = false;
+ if (!succeeded) {
+ cleanDrmObj(); // cleaning up if it hasn't gone through
+ }
}
finished = true;
@@ -4714,24 +4814,18 @@
// the lock is already held by the caller
if (mDrmProvisioningInProgress) {
- Log.e(TAG, String.format("HandleProvisioninig: Unexpected mDrmProvisioningInProgress"));
+ Log.e(TAG, "HandleProvisioninig: Unexpected mDrmProvisioningInProgress");
return false;
}
- MediaDrm.ProvisionRequest provReq = null;
- try {
- MediaDrm drm = new MediaDrm(uuid);
- provReq = drm.getProvisionRequest();
- drm.release();
- } catch (Exception e) {
- Log.e(TAG, String.format("HandleProvisioninig: getProvisionRequest failed with %s", e));
+ MediaDrm.ProvisionRequest provReq = mDrmObj.getProvisionRequest();
+ if (provReq == null) {
+ Log.e(TAG, "HandleProvisioninig: getProvisionRequest returned null.");
return false;
}
- Log.v(TAG, String.format("HandleProvisioninig provReq: data %s url %s",
- (provReq != null) ? provReq.getData() : "-",
- (provReq != null) ? provReq.getDefaultUrl() : "://")
- );
+ Log.v(TAG, "HandleProvisioninig provReq " +
+ " data: " + provReq.getData() + " url: " + provReq.getDefaultUrl());
// networking in a background thread
mDrmProvisioningInProgress = true;
@@ -4749,7 +4843,7 @@
try {
mDrmProvisioningThread.join();
} catch (Exception e) {
- Log.w(TAG, String.format("HandleProvisioninig: Thread.join Exception %s", e));
+ Log.w(TAG, "HandleProvisioninig: Thread.join Exception " + e);
}
result = mDrmProvisioningThread.succeeded();
// no longer need the thread
@@ -4761,19 +4855,21 @@
private boolean resumePrepareDrm(UUID uuid)
{
+ Log.v(TAG, "resumePrepareDrm: uuid: " + uuid);
+
// mDrmLock is guaranteed to be held
boolean success = false;
try {
- boolean allowOpenSession = true; // resuming
- _prepareDrm(getByteArrayFromUUID(uuid), allowOpenSession ? 1 : 0);
+ // resuming
+ prepareDrm_openSessionStep(uuid);
mDrmUUID = uuid;
mActiveDrmScheme = true;
success = true;
} catch (Exception e) {
- Log.w(TAG, String.format("HandleProvisioninig: " +
- "Thread run _prepareDrm resume failed with %s", e));
+ Log.w(TAG, "HandleProvisioninig: Thread run _prepareDrm resume failed with " + e);
+ // mDrmObj clean up is done by the caller
}
return success;
@@ -4782,6 +4878,12 @@
private void resetDrmState()
{
synchronized (mDrmLock) {
+ Log.v(TAG, "resetDrmState: " +
+ " mDrmInfo=" + mDrmInfo +
+ " mDrmProvisioningThread=" + mDrmProvisioningThread +
+ " mPrepareDrmInProgress=" + mPrepareDrmInProgress +
+ " mActiveDrmScheme=" + mActiveDrmScheme);
+
mDrmInfoResolved = false;
mDrmInfo = null;
@@ -4791,15 +4893,33 @@
mDrmProvisioningThread.join();
}
catch (InterruptedException e) {
- Log.w(TAG, String.format("resetDrmState: ProvThread.join Exception %s", e));
+ Log.w(TAG, "resetDrmState: ProvThread.join Exception " + e);
}
mDrmProvisioningThread = null;
}
mPrepareDrmInProgress = false;
+ mActiveDrmScheme = false;
+
+ cleanDrmObj();
} // synchronized
}
+ private void cleanDrmObj()
+ {
+ // the caller holds mDrmLock
+ Log.v(TAG, "cleanDrmObj: mDrmObj=" + mDrmObj + " mDrmSessionId=" + mDrmSessionId);
+
+ if (mDrmSessionId != null) {
+ mDrmObj.closeSession(mDrmSessionId);
+ mDrmSessionId = null;
+ }
+ if (mDrmObj != null) {
+ mDrmObj.release();
+ mDrmObj = null;
+ }
+ }
+
private static final byte[] getByteArrayFromUUID(@NonNull UUID uuid) {
long msb = uuid.getMostSignificantBits();
long lsb = uuid.getLeastSignificantBits();
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index c941766..636727e 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -58,86 +58,20 @@
#include "android_util_Binder.h"
// Modular DRM begin
-#include <media/drm/DrmAPI.h>
-
#define FIND_CLASS(var, className) \
var = env->FindClass(className); \
LOG_FATAL_IF(! (var), "Unable to find class " className);
-#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
-var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
-LOG_FATAL_IF(! (var), "Unable to find field " fieldName);
-
#define GET_METHOD_ID(var, clazz, fieldName, fieldDescriptor) \
var = env->GetMethodID(clazz, fieldName, fieldDescriptor); \
LOG_FATAL_IF(! (var), "Unable to find method " fieldName);
-#define GET_STATIC_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
-var = env->GetStaticFieldID(clazz, fieldName, fieldDescriptor); \
-LOG_FATAL_IF(! (var), "Unable to find field " fieldName);
-
-
-// TODO: investigate if these can be shared with their MediaDrm counterparts
-struct RequestFields {
- jfieldID data;
- jfieldID defaultUrl;
- jfieldID requestType;
-};
-
-struct HashmapFields {
- jmethodID init;
- jmethodID get;
- jmethodID put;
- jmethodID entrySet;
-};
-
-struct SetFields {
- jmethodID iterator;
-};
-
-struct IteratorFields {
- jmethodID next;
- jmethodID hasNext;
-};
-
-struct EntryFields {
- jmethodID getKey;
- jmethodID getValue;
-};
-
-struct KeyTypes {
- jint kKeyTypeStreaming;
- jint kKeyTypeOffline;
- jint kKeyTypeRelease;
-};
-
-static KeyTypes gKeyTypes;
-
-struct KeyRequestTypes {
- jint kKeyRequestTypeInitial;
- jint kKeyRequestTypeRenewal;
- jint kKeyRequestTypeRelease;
-};
-
-static KeyRequestTypes gKeyRequestTypes;
-
struct StateExceptionFields {
jmethodID init;
jclass classId;
};
-struct drm_fields_t {
- RequestFields keyRequest;
- HashmapFields hashmap;
- SetFields set;
- IteratorFields iterator;
- EntryFields entry;
- StateExceptionFields stateException;
- jclass stringClassId;
-};
-
-static drm_fields_t gFields;
-
+static StateExceptionFields gStateExceptionFields;
// Modular DRM end
// ----------------------------------------------------------------------------
@@ -1041,50 +975,14 @@
gBufferingParamsFields.init(env);
// Modular DRM
- FIND_CLASS(clazz, "android/media/MediaDrm");
- if (clazz) {
- jfieldID field;
- GET_STATIC_FIELD_ID(field, clazz, "KEY_TYPE_STREAMING", "I");
- gKeyTypes.kKeyTypeStreaming = env->GetStaticIntField(clazz, field);
- GET_STATIC_FIELD_ID(field, clazz, "KEY_TYPE_OFFLINE", "I");
- gKeyTypes.kKeyTypeOffline = env->GetStaticIntField(clazz, field);
- GET_STATIC_FIELD_ID(field, clazz, "KEY_TYPE_RELEASE", "I");
- gKeyTypes.kKeyTypeRelease = env->GetStaticIntField(clazz, field);
-
- env->DeleteLocalRef(clazz);
- } else {
- ALOGE("JNI getKeyRequest android_media_MediaPlayer_native_init couldn't "
- "get clazz android/media/MediaDrm");
- }
-
- FIND_CLASS(clazz, "android/media/MediaDrm$KeyRequest");
- if (clazz) {
- GET_FIELD_ID(gFields.keyRequest.data, clazz, "mData", "[B");
- GET_FIELD_ID(gFields.keyRequest.defaultUrl, clazz, "mDefaultUrl", "Ljava/lang/String;");
- GET_FIELD_ID(gFields.keyRequest.requestType, clazz, "mRequestType", "I");
-
- jfieldID field;
- GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_INITIAL", "I");
- gKeyRequestTypes.kKeyRequestTypeInitial = env->GetStaticIntField(clazz, field);
- GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_RENEWAL", "I");
- gKeyRequestTypes.kKeyRequestTypeRenewal = env->GetStaticIntField(clazz, field);
- GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_RELEASE", "I");
- gKeyRequestTypes.kKeyRequestTypeRelease = env->GetStaticIntField(clazz, field);
-
- env->DeleteLocalRef(clazz);
- } else {
- ALOGE("JNI getKeyRequest android_media_MediaPlayer_native_init couldn't "
- "get clazz android/media/MediaDrm$KeyRequest");
- }
-
FIND_CLASS(clazz, "android/media/MediaDrm$MediaDrmStateException");
if (clazz) {
- GET_METHOD_ID(gFields.stateException.init, clazz, "<init>", "(ILjava/lang/String;)V");
- gFields.stateException.classId = static_cast<jclass>(env->NewGlobalRef(clazz));
+ GET_METHOD_ID(gStateExceptionFields.init, clazz, "<init>", "(ILjava/lang/String;)V");
+ gStateExceptionFields.classId = static_cast<jclass>(env->NewGlobalRef(clazz));
env->DeleteLocalRef(clazz);
} else {
- ALOGE("JNI getKeyRequest android_media_MediaPlayer_native_init couldn't "
+ ALOGE("JNI android_media_MediaPlayer_native_init couldn't "
"get clazz android/media/MediaDrm$MediaDrmStateException");
}
@@ -1315,8 +1213,8 @@
{
ALOGE("Illegal DRM state exception: %s (%d)", msg, err);
- jobject exception = env->NewObject(gFields.stateException.classId,
- gFields.stateException.init, static_cast<int>(err),
+ jobject exception = env->NewObject(gStateExceptionFields.classId,
+ gStateExceptionFields.init, static_cast<int>(err),
env->NewStringUTF(msg));
env->Throw(static_cast<jthrowable>(exception));
}
@@ -1393,18 +1291,6 @@
return false;
}
-// TODO: investigate if these can be shared with their MediaDrm counterparts
-static jbyteArray VectorToJByteArray(JNIEnv *env, Vector<uint8_t> const &vector)
-{
- size_t length = vector.size();
- jbyteArray result = env->NewByteArray(length);
- if (result != NULL) {
- env->SetByteArrayRegion(result, 0, length, (jbyte *)vector.array());
- }
- return result;
-}
-
-// TODO: investigate if these can be shared with their MediaDrm counterparts
static Vector<uint8_t> JByteArrayToVector(JNIEnv *env, jbyteArray const &byteArray)
{
Vector<uint8_t> vector;
@@ -1414,74 +1300,8 @@
return vector;
}
-// TODO: investigate if these can be shared with their MediaDrm counterparts
-static String8 JStringToString8(JNIEnv *env, jstring const &jstr)
-{
- String8 result;
-
- const char *s = env->GetStringUTFChars(jstr, NULL);
- if (s) {
- result = s;
- env->ReleaseStringUTFChars(jstr, s);
- }
- return result;
-}
-
-// TODO: investigate if these can be shared with their MediaDrm counterparts
-static KeyedVector<String8, String8> HashMapToKeyedVector(JNIEnv *env,
- jobject &hashMap, bool* pIsOK)
-{
- jclass clazz = gFields.stringClassId;
- KeyedVector<String8, String8> keyedVector;
- *pIsOK = true;
-
- jobject entrySet = env->CallObjectMethod(hashMap, gFields.hashmap.entrySet);
- if (entrySet) {
- jobject iterator = env->CallObjectMethod(entrySet, gFields.set.iterator);
- if (iterator) {
- jboolean hasNext = env->CallBooleanMethod(iterator, gFields.iterator.hasNext);
- while (hasNext) {
- jobject entry = env->CallObjectMethod(iterator, gFields.iterator.next);
- if (entry) {
- jobject obj = env->CallObjectMethod(entry, gFields.entry.getKey);
- if (obj == NULL || !env->IsInstanceOf(obj, clazz)) {
- jniThrowException(env, "java/lang/IllegalArgumentException",
- "HashMap key is not a String");
- env->DeleteLocalRef(entry);
- *pIsOK = false;
- break;
- }
- jstring jkey = static_cast<jstring>(obj);
-
- obj = env->CallObjectMethod(entry, gFields.entry.getValue);
- if (obj == NULL || !env->IsInstanceOf(obj, clazz)) {
- jniThrowException(env, "java/lang/IllegalArgumentException",
- "HashMap value is not a String");
- env->DeleteLocalRef(entry);
- *pIsOK = false;
- break;
- }
- jstring jvalue = static_cast<jstring>(obj);
-
- String8 key = JStringToString8(env, jkey);
- String8 value = JStringToString8(env, jvalue);
- keyedVector.add(key, value);
-
- env->DeleteLocalRef(jkey);
- env->DeleteLocalRef(jvalue);
- hasNext = env->CallBooleanMethod(iterator, gFields.iterator.hasNext);
- }
- env->DeleteLocalRef(entry);
- }
- env->DeleteLocalRef(iterator);
- }
- env->DeleteLocalRef(entrySet);
- }
- return keyedVector;
-}
-
static void android_media_MediaPlayer_prepareDrm(JNIEnv *env, jobject thiz,
- jbyteArray uuidObj, jint mode)
+ jbyteArray uuidObj, jbyteArray drmSessionIdObj)
{
sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
if (mp == NULL) {
@@ -1504,13 +1324,23 @@
return;
}
- status_t err = mp->prepareDrm(uuid.array(), mode);
+ Vector<uint8_t> drmSessionId = JByteArrayToVector(env, drmSessionIdObj);
+
+ if (drmSessionId.size() == 0) {
+ jniThrowException(
+ env,
+ "java/lang/IllegalArgumentException",
+ "empty drmSessionId");
+ return;
+ }
+
+ status_t err = mp->prepareDrm(uuid.array(), drmSessionId);
if (err != OK) {
if (err == INVALID_OPERATION) {
jniThrowException(
env,
"java/lang/IllegalStateException",
- "The player is not prepared yet.");
+ "The player must be in prepared state.");
} else if (err == ERROR_DRM_CANNOT_HANDLE) {
jniThrowException(
env,
@@ -1536,211 +1366,10 @@
jniThrowException(
env,
"java/lang/IllegalStateException",
- "The player is not prepared yet.");
+ "Can not release DRM in an active player state.");
}
}
}
-
-static jobject android_media_MediaPlayer_getKeyRequest(JNIEnv *env, jobject thiz, jbyteArray jscope,
- jstring jmimeType, jint jkeyType, jobject joptParams)
-{
- sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
- if (mp == NULL) {
- jniThrowException(env, "java/lang/IllegalStateException", NULL);
- return NULL;
- }
-
- Vector<uint8_t> scope;
- if (jscope != NULL) {
- scope = JByteArrayToVector(env, jscope);
- }
-
- String8 mimeType;
- if (jmimeType != NULL) {
- mimeType = JStringToString8(env, jmimeType);
- }
-
- DrmPlugin::KeyType keyType;
- if (jkeyType == gKeyTypes.kKeyTypeStreaming) {
- keyType = DrmPlugin::kKeyType_Streaming;
- } else if (jkeyType == gKeyTypes.kKeyTypeOffline) {
- keyType = DrmPlugin::kKeyType_Offline;
- } else if (jkeyType == gKeyTypes.kKeyTypeRelease) {
- keyType = DrmPlugin::kKeyType_Release;
- } else {
- jniThrowException(env, "java/lang/IllegalArgumentException", "invalid keyType");
- return NULL;
- }
-
- KeyedVector<String8, String8> optParams;
- if (joptParams != NULL) {
- bool isOK;
- optParams = HashMapToKeyedVector(env, joptParams, &isOK);
- if (!isOK) {
- return NULL;
- }
- }
-
- Vector<uint8_t> request;
- String8 defaultUrl;
- DrmPlugin::KeyRequestType keyRequestType;
- status_t err = mp->getKeyRequest(scope, mimeType, keyType, optParams, request, defaultUrl,
- keyRequestType);
-
- if (throwDrmExceptionAsNecessary(env, err, "Failed to get key request")) {
- return NULL;
- }
-
- ALOGV("JNI getKeyRequest err %d request %d url %s keyReqType %d",
- err, (int)request.size(), defaultUrl.string(), (int)keyRequestType);
-
- // Fill out return obj
- jclass clazz;
- FIND_CLASS(clazz, "android/media/MediaDrm$KeyRequest");
-
- jobject keyObj = NULL;
-
- if (clazz) {
- keyObj = env->AllocObject(clazz);
- jbyteArray jrequest = VectorToJByteArray(env, request);
- env->SetObjectField(keyObj, gFields.keyRequest.data, jrequest);
-
- jstring jdefaultUrl = env->NewStringUTF(defaultUrl.string());
- env->SetObjectField(keyObj, gFields.keyRequest.defaultUrl, jdefaultUrl);
-
- switch (keyRequestType) {
- case DrmPlugin::kKeyRequestType_Initial:
- env->SetIntField(keyObj, gFields.keyRequest.requestType,
- gKeyRequestTypes.kKeyRequestTypeInitial);
- break;
- case DrmPlugin::kKeyRequestType_Renewal:
- env->SetIntField(keyObj, gFields.keyRequest.requestType,
- gKeyRequestTypes.kKeyRequestTypeRenewal);
- break;
- case DrmPlugin::kKeyRequestType_Release:
- env->SetIntField(keyObj, gFields.keyRequest.requestType,
- gKeyRequestTypes.kKeyRequestTypeRelease);
- break;
- default:
- throwDrmStateException(env, "MediaPlayer/DRM plugin failure: unknown "
- "key request type", ERROR_DRM_UNKNOWN);
- break;
- }
- }
-
- return keyObj;
-}
-
-static jbyteArray android_media_MediaPlayer_provideKeyResponse(JNIEnv *env, jobject thiz,
- jbyteArray jreleaseKeySetId, jbyteArray jresponse)
-{
- sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
- if (mp == NULL ) {
- jniThrowException(env, "java/lang/IllegalStateException", NULL);
- return NULL;
- }
-
- if (jresponse == NULL) {
- jniThrowException(env, "java/lang/IllegalArgumentException", "key response is null");
- return NULL;
- }
-
- Vector<uint8_t> releaseKeySetId;
- if (jreleaseKeySetId != NULL) {
- releaseKeySetId = JByteArrayToVector(env, jreleaseKeySetId);
- }
-
- Vector<uint8_t> response(JByteArrayToVector(env, jresponse));
- Vector<uint8_t> keySetId;
-
- status_t err = mp->provideKeyResponse(releaseKeySetId, response, keySetId);
-
- if (throwDrmExceptionAsNecessary(env, err, "Failed to handle key response")) {
- return NULL;
- }
- return VectorToJByteArray(env, keySetId);
-}
-
-static void android_media_MediaPlayer_restoreKeys(JNIEnv *env, jobject thiz, jbyteArray jkeySetId)
-{
- sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
- if (mp == NULL) {
- jniThrowException(env, "java/lang/IllegalStateException", NULL);
- return;
- }
-
- if (jkeySetId == NULL) {
- jniThrowException(env, "java/lang/IllegalArgumentException", "invalid keyType");
- return;
- }
-
- Vector<uint8_t> keySetId;
- keySetId = JByteArrayToVector(env, jkeySetId);
-
- status_t err = mp->restoreKeys(keySetId);
-
- ALOGV("JNI restoreKeys err %d ", err);
- throwDrmExceptionAsNecessary(env, err, "Failed to restore keys");
-}
-
-static jstring android_media_MediaPlayer_getDrmPropertyString(JNIEnv *env, jobject thiz,
- jstring jname)
-{
- sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
- if (mp == NULL) {
- jniThrowException(env, "java/lang/IllegalStateException", NULL);
- return NULL;
- }
-
- if (jname == NULL) {
- jniThrowException(env, "java/lang/IllegalArgumentException",
- "property name String is null");
- return NULL;
- }
-
- String8 name = JStringToString8(env, jname);
- String8 value;
-
- status_t err = mp->getDrmPropertyString(name, value);
-
- ALOGV("JNI getPropertyString err %d", err);
-
- if (throwDrmExceptionAsNecessary(env, err, "Failed to get property")) {
- return NULL;
- }
-
- return env->NewStringUTF(value.string());
-}
-
-static void android_media_MediaPlayer_setDrmPropertyString(JNIEnv *env, jobject thiz,
- jstring jname, jstring jvalue)
-{
- sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
- if (mp == NULL) {
- jniThrowException(env, "java/lang/IllegalStateException", NULL);
- return;
- }
-
- if (jname == NULL) {
- jniThrowException(env, "java/lang/IllegalArgumentException",
- "property name String is null");
- return;
- }
-
- if (jvalue == NULL) {
- jniThrowException(env, "java/lang/IllegalArgumentException",
- "property value String is null");
- return;
- }
-
- String8 name = JStringToString8(env, jname);
- String8 value = JStringToString8(env, jvalue);
-
- status_t err = mp->setDrmPropertyString(name, value);
-
- ALOGV("JNI setPropertyString err %d", err);
- throwDrmExceptionAsNecessary(env, err, "Failed to set property");
-}
// Modular DRM end
// ----------------------------------------------------------------------------
@@ -1802,14 +1431,8 @@
"(I)Landroid/media/VolumeShaper$State;",
(void *)android_media_MediaPlayer_getVolumeShaperState},
// Modular DRM
- { "_prepareDrm", "([BI)V", (void *)android_media_MediaPlayer_prepareDrm },
+ { "_prepareDrm", "([B[B)V", (void *)android_media_MediaPlayer_prepareDrm },
{ "_releaseDrm", "()V", (void *)android_media_MediaPlayer_releaseDrm },
- { "_getKeyRequest", "([BLjava/lang/String;ILjava/util/Map;)" "Landroid/media/MediaDrm$KeyRequest;",
- (void *)android_media_MediaPlayer_getKeyRequest },
- { "_provideKeyResponse", "([B[B)[B", (void *)android_media_MediaPlayer_provideKeyResponse },
- { "_getDrmPropertyString", "(Ljava/lang/String;)Ljava/lang/String;", (void *)android_media_MediaPlayer_getDrmPropertyString },
- { "_setDrmPropertyString", "(Ljava/lang/String;Ljava/lang/String;)V",(void *)android_media_MediaPlayer_setDrmPropertyString },
- { "_restoreKeys", "([B)V", (void *)android_media_MediaPlayer_restoreKeys },
};
// This function only registers the native methods
diff --git a/obex/javax/obex/ServerSession.java b/obex/javax/obex/ServerSession.java
index acee5dd..3831cf7 100644
--- a/obex/javax/obex/ServerSession.java
+++ b/obex/javax/obex/ServerSession.java
@@ -658,6 +658,11 @@
*/
byte[] sendData = new byte[totalLength];
int maxRxLength = ObexHelper.getMaxRxPacketSize(mTransport);
+ if (maxRxLength > mMaxPacketLength) {
+ if(V) Log.v(TAG,"Set maxRxLength to min of maxRxServrLen:" + maxRxLength +
+ " and MaxNegotiated from Client: " + mMaxPacketLength);
+ maxRxLength = mMaxPacketLength;
+ }
sendData[0] = (byte)code;
sendData[1] = length[2];
sendData[2] = length[3];
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java
index 8a970da..25127ef 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java
@@ -33,7 +33,6 @@
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
-import android.widget.Toast;
public class DeviceChooserActivity extends Activity {
@@ -129,12 +128,9 @@
}
protected void onPairTapped(BluetoothDevice selectedDevice) {
+ getService().onDeviceSelected();
setResult(RESULT_OK,
new Intent().putExtra(CompanionDeviceManager.EXTRA_DEVICE, selectedDevice));
finish();
}
-
- private void toast(String msg) {
- Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
- }
}
\ No newline at end of file
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
index ccbee2a..11c722d 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
@@ -32,16 +32,15 @@
import android.bluetooth.le.ScanResult;
import android.bluetooth.le.ScanSettings;
import android.companion.AssociationRequest;
-import android.companion.BluetoothDeviceFilterUtils;
import android.companion.BluetoothLEDeviceFilter;
-import android.companion.ICompanionDeviceManagerService;
-import android.companion.IOnAssociateCallback;
+import android.companion.ICompanionDeviceDiscoveryService;
+import android.companion.ICompanionDeviceDiscoveryServiceCallback;
+import android.companion.IFindDeviceCallback;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Color;
-import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.os.IBinder;
import android.os.RemoteException;
@@ -70,21 +69,25 @@
List<BluetoothDevice> mDevicesFound;
BluetoothDevice mSelectedDevice;
DevicesAdapter mDevicesAdapter;
- IOnAssociateCallback mCallback;
+ IFindDeviceCallback mFindCallback;
+ ICompanionDeviceDiscoveryServiceCallback mServiceCallback;
String mCallingPackage;
- private final ICompanionDeviceManagerService mBinder =
- new ICompanionDeviceManagerService.Stub() {
+ private final ICompanionDeviceDiscoveryService mBinder =
+ new ICompanionDeviceDiscoveryService.Stub() {
@Override
public void startDiscovery(AssociationRequest request,
- IOnAssociateCallback callback,
- String callingPackage) throws RemoteException {
+ String callingPackage,
+ IFindDeviceCallback findCallback,
+ ICompanionDeviceDiscoveryServiceCallback serviceCallback) {
if (DEBUG) {
Log.i(LOG_TAG,
- "startDiscovery() called with: filter = [" + request + "], callback = ["
- + callback + "]");
+ "startDiscovery() called with: filter = [" + request
+ + "], findCallback = [" + findCallback + "]"
+ + "], serviceCallback = [" + serviceCallback + "]");
}
- mCallback = callback;
+ mFindCallback = findCallback;
+ mServiceCallback = serviceCallback;
mCallingPackage = callingPackage;
DeviceDiscoveryService.this.startDiscovery(request);
}
@@ -171,6 +174,14 @@
return super.onUnbind(intent);
}
+ public void onDeviceSelected() {
+ try {
+ mServiceCallback.onDeviceSelected(mCallingPackage, getUserId());
+ } catch (RemoteException e) {
+ Log.e(LOG_TAG, "Error reporting selected device");
+ }
+ }
+
private void stopScan() {
if (DEBUG) Log.i(LOG_TAG, "stopScan() called");
mBluetoothAdapter.cancelDiscovery();
@@ -205,7 +216,7 @@
//TODO also, on timeout -> call onFailure
private void onReadyToShowUI() {
try {
- mCallback.onSuccess(PendingIntent.getActivity(
+ mFindCallback.onSuccess(PendingIntent.getActivity(
this, 0,
new Intent(this, DeviceChooserActivity.class),
PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_CANCEL_CURRENT
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index 499b6ae..136f17e 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -227,7 +227,4 @@
<!-- default setting for Settings.System.END_BUTTON_BEHAVIOR : END_BUTTON_BEHAVIOR_SLEEP -->
<integer name="def_end_button_behavior">0x2</integer>
-
- <!--Default settings for network recommendations. -->
- <string name="def_network_recommendations_package" translatable="false">com.android.networkrecommendation</string>
</resources>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index edcb9b5..d5787e6 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -3182,24 +3182,7 @@
}
if (currentVersion == 138) {
- // Version 139: Applying the default to NETWORK_RECOMMENDATIONS_PACKAGE
- if (userId == UserHandle.USER_SYSTEM) {
- final SettingsState globalSettings = getGlobalSettingsLocked();
- final String defaultAppPackage = getContext().getResources()
- .getString(R.string.def_network_recommendations_package);
-
- // Set the network recommendations package name
- globalSettings.insertSettingLocked(
- Global.NETWORK_RECOMMENDATIONS_PACKAGE,
- defaultAppPackage, null, true,
- SettingsState.SYSTEM_PACKAGE_NAME);
-
- // Clear the scorer setting since it's no longer needed.
- globalSettings.insertSettingLocked(
- Global.NETWORK_SCORER_APP,
- null, null, true,
- SettingsState.SYSTEM_PACKAGE_NAME);
- }
+ // Version 139: Removed.
currentVersion = 139;
}
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index d4c7c7a..2e115ab 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -154,8 +154,8 @@
android:name=".BugreportReceiver"
android:permission="android.permission.DUMP">
<intent-filter>
- <action android:name="android.intent.action.BUGREPORT_STARTED" />
- <action android:name="android.intent.action.BUGREPORT_FINISHED" />
+ <action android:name="com.android.internal.intent.action.BUGREPORT_STARTED" />
+ <action android:name="com.android.internal.intent.action.BUGREPORT_FINISHED" />
</intent-filter>
</receiver>
@@ -163,7 +163,7 @@
android:name=".RemoteBugreportReceiver"
android:permission="android.permission.DUMP">
<intent-filter>
- <action android:name="android.intent.action.REMOTE_BUGREPORT_FINISHED" />
+ <action android:name="com.android.internal.intent.action.REMOTE_BUGREPORT_FINISHED" />
</intent-filter>
</receiver>
diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java
index 17d0a09..12d0c03 100644
--- a/packages/Shell/src/com/android/shell/BugreportProgressService.java
+++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java
@@ -133,10 +133,12 @@
private static final String AUTHORITY = "com.android.shell";
// External intents sent by dumpstate.
- static final String INTENT_BUGREPORT_STARTED = "android.intent.action.BUGREPORT_STARTED";
- static final String INTENT_BUGREPORT_FINISHED = "android.intent.action.BUGREPORT_FINISHED";
+ static final String INTENT_BUGREPORT_STARTED =
+ "com.android.internal.intent.action.BUGREPORT_STARTED";
+ static final String INTENT_BUGREPORT_FINISHED =
+ "com.android.internal.intent.action.BUGREPORT_FINISHED";
static final String INTENT_REMOTE_BUGREPORT_FINISHED =
- "android.intent.action.REMOTE_BUGREPORT_FINISHED";
+ "com.android.internal.intent.action.REMOTE_BUGREPORT_FINISHED";
// Internal intents used on notification actions.
static final String INTENT_BUGREPORT_CANCEL = "android.intent.action.BUGREPORT_CANCEL";
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index 3648a06..cb4306f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -462,6 +462,7 @@
updateBackgroundForGroupState();
updateClickAndFocus();
if (mNotificationParent != null) {
+ setOverrideTintColor(NO_COLOR, 0.0f);
mNotificationParent.updateBackgroundForGroupState();
}
updateIconVisibilities();
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index 36dee49..8d2f0c3 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -3416,6 +3416,19 @@
// ACTION: Settings advanced button is expanded
ACTION_SETTINGS_ADVANCED_BUTTON_EXPAND = 834;
+ // ACTION: Logs the number of times the saved network evaluator was used to
+ // recommend a wifi network
+ WIFI_NETWORK_RECOMMENDATION_SAVED_NETWORK_EVALUATOR = 835;
+
+ // ACTION: Logs the number of times the recommended network evaluator was
+ // used to recommend a wifi network
+ WIFI_NETWORK_RECOMMENDATION_RECOMMENDED_NETWORK_EVALUATOR = 836;
+
+ // ACTION: Logs the number of times a recommended network was resulted in a
+ // successful connection
+ // VALUE: true if the connection was successful, false if the connection failed
+ WIFI_NETWORK_RECOMMENDATION_CONNECTION_SUCCESS = 837;
+
// ---- End O Constants, all O constants go above this line ----
// Add new aosp constants above this line.
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 13e6ae0..8fbc520 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -2400,14 +2400,19 @@
}
final long oldToken = Binder.clearCallingIdentity();
try {
+ List<Integer> operationsToCancel = new ArrayList<>();
synchronized (mCurrentOpLock) {
for (int i = 0; i < mCurrentOperations.size(); i++) {
Operation op = mCurrentOperations.valueAt(i);
int token = mCurrentOperations.keyAt(i);
if (op.type == OP_TYPE_BACKUP) {
- handleCancel(token, true /* cancelAll */);
+ operationsToCancel.add(token);
}
}
+
+ for (Integer token : operationsToCancel) {
+ handleCancel(token, true /* cancelAll */);
+ }
}
// We don't want the backup jobs to kick in any time soon.
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 719a64e..fe0b840 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -4166,7 +4166,7 @@
}
ensureRequestableCapabilities(networkCapabilities);
- if (timeoutMs < 0 || timeoutMs > ConnectivityManager.MAX_NETWORK_REQUEST_TIMEOUT_MS) {
+ if (timeoutMs < 0) {
throw new IllegalArgumentException("Bad timeout specified");
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index a73eb18..c2c24b3 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -556,7 +556,7 @@
// Intent sent when remote bugreport collection has been completed
private static final String INTENT_REMOTE_BUGREPORT_FINISHED =
- "android.intent.action.REMOTE_BUGREPORT_FINISHED";
+ "com.android.internal.intent.action.REMOTE_BUGREPORT_FINISHED";
// Used to indicate that an app transition should be animated.
static final boolean ANIMATE = true;
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 1b19382..082b6b5 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -22,7 +22,6 @@
import static android.app.ActivityManager.StackId.ASSISTANT_STACK_ID;
import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
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.HOME_STACK_ID;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.app.AppOpsManager.MODE_ALLOWED;
@@ -47,7 +46,6 @@
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
-import static android.content.res.Configuration.UI_MODE_TYPE_MASK;
import static android.content.res.Configuration.UI_MODE_TYPE_VR_HEADSET;
import static android.os.Build.VERSION_CODES.HONEYCOMB;
import static android.os.Build.VERSION_CODES.O;
@@ -85,7 +83,6 @@
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.Rect;
-import android.os.Build;
import android.os.Bundle;
import android.os.Debug;
import android.os.IBinder;
@@ -290,8 +287,8 @@
/**
* Temp configs used in {@link #ensureActivityConfigurationLocked(int, boolean)}
*/
- private final Configuration mTmpGlobalConfig = new Configuration();
- private final Configuration mTmpTaskConfig = new Configuration();
+ private final Configuration mTmpConfig1 = new Configuration();
+ private final Configuration mTmpConfig2 = new Configuration();
private static String startingWindowStateToString(int state) {
switch (state) {
@@ -1975,13 +1972,13 @@
if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
"Ensuring correct configuration: " + this);
- // Short circuit: if the two configurations are equal (the common case), then there is
- // nothing to do.
- final Configuration newGlobalConfig = service.getGlobalConfiguration();
- final Configuration newTaskMergedOverrideConfig = task.getMergedOverrideConfiguration();
- if (mLastReportedConfiguration.equals(newGlobalConfig)
- && mLastReportedOverrideConfiguration.equals(newTaskMergedOverrideConfig)
- && !forceNewConfig) {
+ // Short circuit: if the two full configurations are equal (the common case), then there is
+ // nothing to do. We test the full configuration instead of the global and merged override
+ // configurations because there are cases (like moving a task to the pinned stack) where
+ // the combine configurations are equal, but would otherwise differ in the override config
+ mTmpConfig1.setTo(mLastReportedConfiguration);
+ mTmpConfig1.updateFrom(mLastReportedOverrideConfiguration);
+ if (task.getConfiguration().equals(mTmpConfig1) && !forceNewConfig) {
if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
"Configuration unchanged in " + this);
return true;
@@ -1997,14 +1994,16 @@
// Okay we now are going to make this activity have the new config.
// But then we need to figure out how it needs to deal with that.
- mTmpGlobalConfig.setTo(mLastReportedConfiguration);
- mTmpTaskConfig.setTo(mLastReportedOverrideConfiguration);
+ final Configuration newGlobalConfig = service.getGlobalConfiguration();
+ final Configuration newTaskMergedOverrideConfig = task.getMergedOverrideConfiguration();
+ mTmpConfig1.setTo(mLastReportedConfiguration);
+ mTmpConfig2.setTo(mLastReportedOverrideConfiguration);
mLastReportedConfiguration.setTo(newGlobalConfig);
mLastReportedOverrideConfiguration.setTo(newTaskMergedOverrideConfig);
int taskChanges = getTaskConfigurationChanges(this, newTaskMergedOverrideConfig,
- mTmpTaskConfig);
- final int changes = mTmpGlobalConfig.diff(newGlobalConfig) | taskChanges;
+ mTmpConfig2);
+ final int changes = mTmpConfig1.diff(newGlobalConfig) | taskChanges;
if (changes == 0 && !forceNewConfig) {
if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
"Configuration no differences in " + this);
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 7c24604..f75ce25 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -2507,7 +2507,7 @@
if (!next.hasBeenLaunched) {
next.hasBeenLaunched = true;
} else if (SHOW_APP_STARTING_PREVIEW && lastStack != null &&
- mStackSupervisor.isFrontStack(lastStack)) {
+ mStackSupervisor.isFrontStackOnDisplay(lastStack)) {
next.showStartingWindow(null /* prev */, false /* newTask */,
false /* taskSwitch */);
}
@@ -4354,7 +4354,7 @@
// If we have a watcher, preflight the move before committing to it. First check
// for *other* available tasks, but if none are available, then try again allowing the
// current task to be selected.
- if (mStackSupervisor.isFrontStack(this) && mService.mController != null) {
+ if (mStackSupervisor.isFrontStackOnDisplay(this) && mService.mController != null) {
ActivityRecord next = topRunningActivityLocked(null, taskId);
if (next == null) {
next = topRunningActivityLocked(null, 0);
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 95734a4..4a29872 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -624,11 +624,6 @@
return stack == mFocusedStack;
}
- /** The top most stack. */
- boolean isFrontStack(ActivityStack stack) {
- return isFrontOfStackList(stack, mHomeStack.mStacks);
- }
-
/** The top most stack on its display. */
boolean isFrontStackOnDisplay(ActivityStack stack) {
return isFrontOfStackList(stack, stack.mActivityContainer.mActivityDisplay.mStacks);
@@ -1103,13 +1098,21 @@
}
// Look in other non-focused and non-home stacks.
- final ArrayList<ActivityStack> stacks = mHomeStack.mStacks;
- for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = stacks.get(stackNdx);
- if (stack != focusedStack && isFrontStack(stack) && stack.isFocusable()) {
- r = stack.topRunningActivityLocked();
- if (r != null) {
- return r;
+ mWindowManager.getDisplaysInFocusOrder(mTmpOrderedDisplayIds);
+
+ for (int i = mTmpOrderedDisplayIds.size() - 1; i >= 0; --i) {
+ final int displayId = mTmpOrderedDisplayIds.get(i);
+ final List<ActivityStack> stacks = mActivityDisplays.get(displayId).mStacks;
+ if (stacks == null) {
+ continue;
+ }
+ for (int j = stacks.size() - 1; j >= 0; --j) {
+ final ActivityStack stack = stacks.get(j);
+ if (stack != focusedStack && isFrontStackOnDisplay(stack) && stack.isFocusable()) {
+ r = stack.topRunningActivityLocked();
+ if (r != null) {
+ return r;
+ }
}
}
}
@@ -2676,7 +2679,7 @@
// In some cases the focused stack isn't the front stack. E.g. pinned stack.
// Whenever we are moving the top activity from the front stack we want to make sure to move
// the stack to the front.
- final boolean wasFront = isFrontStack(prevStack)
+ final boolean wasFront = isFrontStackOnDisplay(prevStack)
&& (prevStack.topRunningActivityLocked() == r);
if (stackId == DOCKED_STACK_ID && !task.isResizeable()) {
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index 520d4ee..f8645d6 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -35,7 +35,6 @@
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.graphics.Bitmap;
-import android.graphics.GraphicBuffer;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.Debug;
@@ -52,6 +51,7 @@
import com.android.internal.util.XmlUtils;
import com.android.server.wm.AppWindowContainerController;
+import com.android.server.wm.StackWindowController;
import com.android.server.wm.TaskWindowContainerController;
import com.android.server.wm.TaskWindowContainerListener;
@@ -278,7 +278,6 @@
private final Rect mTmpStableBounds = new Rect();
private final Rect mTmpNonDecorBounds = new Rect();
private final Rect mTmpRect = new Rect();
- private final Rect mTmpRect2 = new Rect();
// Last non-fullscreen bounds the task was launched in or resized to.
// The information is persisted and used to determine the appropriate stack to launch the
@@ -1838,66 +1837,38 @@
return !mTmpConfig.equals(newConfig);
}
- private void subtractNonDecorInsets(Rect inOutBounds, Rect inInsetBounds,
- boolean overrideWidth, boolean overrideHeight) {
- mTmpRect2.set(inInsetBounds);
- mService.mWindowManager.subtractNonDecorInsets(mTmpRect2);
- int leftInset = mTmpRect2.left - inInsetBounds.left;
- int topInset = mTmpRect2.top - inInsetBounds.top;
- int rightInset = overrideWidth ? 0 : inInsetBounds.right - mTmpRect2.right;
- int bottomInset = overrideHeight ? 0 : inInsetBounds.bottom - mTmpRect2.bottom;
- inOutBounds.inset(leftInset, topInset, rightInset, bottomInset);
- }
-
- private void subtractStableInsets(Rect inOutBounds, Rect inInsetBounds,
- boolean overrideWidth, boolean overrideHeight) {
- mTmpRect2.set(inInsetBounds);
- mService.mWindowManager.subtractStableInsets(mTmpRect2);
- int leftInset = mTmpRect2.left - inInsetBounds.left;
- int topInset = mTmpRect2.top - inInsetBounds.top;
- int rightInset = overrideWidth ? 0 : inInsetBounds.right - mTmpRect2.right;
- int bottomInset = overrideHeight ? 0 : inInsetBounds.bottom - mTmpRect2.bottom;
- inOutBounds.inset(leftInset, topInset, rightInset, bottomInset);
- }
-
/** Clears passed config and fills it with new override values. */
private void calculateOverrideConfig(Configuration config, Rect bounds, Rect insetBounds,
boolean overrideWidth, boolean overrideHeight) {
mTmpNonDecorBounds.set(bounds);
mTmpStableBounds.set(bounds);
- final Configuration parentConfig = getParent().getConfiguration();
config.unset();
+ final Configuration parentConfig = getParent().getConfiguration();
final float density = parentConfig.densityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE;
- final boolean isFloatingTask = mStack != null && StackId.tasksAreFloating(mStack.mStackId);
- if (isFloatingTask) {
- // Floating tasks should not be resized to the screen's bounds.
- config.screenWidthDp = (int) (mTmpStableBounds.width() / density);
- config.screenHeightDp = (int) (mTmpStableBounds.height() / density);
- } else {
- // For calculating screenWidthDp, screenWidthDp, we use the stable inset screen area,
- // i.e. the screen area without the system bars.
- // Additionally task dimensions should not be bigger than its parents dimensions.
- subtractNonDecorInsets(mTmpNonDecorBounds, insetBounds != null ? insetBounds : bounds,
- overrideWidth, overrideHeight);
- subtractStableInsets(mTmpStableBounds, insetBounds != null ? insetBounds : bounds,
- overrideWidth, overrideHeight);
- config.screenWidthDp = Math.min(
- (int) (mTmpStableBounds.width() / density), parentConfig.screenWidthDp);
- config.screenHeightDp = Math.min(
- (int) (mTmpStableBounds.height() / density), parentConfig.screenHeightDp);
- }
// TODO: Orientation?
config.orientation = (config.screenWidthDp <= config.screenHeightDp)
? Configuration.ORIENTATION_PORTRAIT
: Configuration.ORIENTATION_LANDSCAPE;
+ if (mStack != null) {
+ final StackWindowController stackController = mStack.getWindowContainerController();
+ stackController.adjustConfigurationForBounds(bounds, insetBounds,
+ mTmpNonDecorBounds, mTmpStableBounds, overrideWidth, overrideHeight, density,
+ config, parentConfig);
+ } else {
+ // No stack, give some default values
+ config.smallestScreenWidthDp =
+ mService.mStackSupervisor.mDefaultMinSizeOfResizeableTask;
+ config.screenWidthDp = config.screenHeightDp = config.smallestScreenWidthDp;
+ Slog.wtf(TAG, "Expected stack when caclulating override config");
+ }
// For calculating screen layout, we need to use the non-decor inset screen area for the
// calculation for compatibility reasons, i.e. screen area without system bars that could
// never go away in Honeycomb.
- final int compatScreenWidthDp = (int)(mTmpNonDecorBounds.width() / density);
- final int compatScreenHeightDp = (int)(mTmpNonDecorBounds.height() / density);
+ final int compatScreenWidthDp = (int) (mTmpNonDecorBounds.width() / density);
+ final int compatScreenHeightDp = (int) (mTmpNonDecorBounds.height() / density);
// We're only overriding LONG, SIZE and COMPAT parts of screenLayout, so we start override
// calculation with partial default.
final int sl = Configuration.SCREENLAYOUT_LONG_YES | Configuration.SCREENLAYOUT_SIZE_XLARGE;
@@ -1905,8 +1876,6 @@
final int shortSize = Math.min(compatScreenHeightDp, compatScreenWidthDp);
config.screenLayout = Configuration.reduceScreenLayout(sl, longSize, shortSize);
- config.smallestScreenWidthDp = mService.mWindowManager.getSmallestWidthForTaskBounds(
- insetBounds != null ? insetBounds : bounds);
}
/**
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index 17b005d..8bc72de 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -481,12 +481,6 @@
public void onLost(Network network) {
releaseSuplConnection(GPS_RELEASE_AGPS_DATA_CONN);
}
-
- @Override
- public void onUnavailable() {
- // timeout, it was not possible to establish the required connection
- releaseSuplConnection(GPS_AGPS_DATA_CONN_FAILED);
- }
};
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@@ -877,8 +871,7 @@
NetworkRequest request = requestBuilder.build();
mConnMgr.requestNetwork(
request,
- mSuplConnectivityCallback,
- ConnectivityManager.MAX_NETWORK_REQUEST_TIMEOUT_MS);
+ mSuplConnectivityCallback);
}
private void handleReleaseSuplConnection(int agpsDataConnStatus) {
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index 98177fe..407262b 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -93,7 +93,6 @@
private final SessionManagerImpl mSessionManagerImpl;
private final MediaSessionStack mPriorityStack;
- private final ArrayList<MediaSessionRecord> mAllSessions = new ArrayList<MediaSessionRecord>();
private final SparseArray<UserRecord> mUserRecords = new SparseArray<UserRecord>();
private final ArrayList<SessionsListenerRecord> mSessionsListeners
= new ArrayList<SessionsListenerRecord>();
@@ -145,7 +144,8 @@
public void updateSession(MediaSessionRecord record) {
synchronized (mLock) {
- if (!mAllSessions.contains(record)) {
+ UserRecord user = mUserRecords.get(record.getUserId());
+ if (user == null || !user.mSessions.contains(record)) {
Log.d(TAG, "Unknown session updated. Ignoring.");
return;
}
@@ -171,7 +171,8 @@
public void onSessionPlaystateChange(MediaSessionRecord record, int oldState, int newState) {
boolean updateSessions = false;
synchronized (mLock) {
- if (!mAllSessions.contains(record)) {
+ UserRecord user = mUserRecords.get(record.getUserId());
+ if (user == null || !user.mSessions.contains(record)) {
Log.d(TAG, "Unknown session changed playback state. Ignoring.");
return;
}
@@ -184,7 +185,8 @@
public void onSessionPlaybackTypeChanged(MediaSessionRecord record) {
synchronized (mLock) {
- if (!mAllSessions.contains(record)) {
+ UserRecord user = mUserRecords.get(record.getUserId());
+ if (user == null || !user.mSessions.contains(record)) {
Log.d(TAG, "Unknown session changed playback type. Ignoring.");
return;
}
@@ -318,7 +320,6 @@
}
mPriorityStack.removeSession(session);
- mAllSessions.remove(session);
try {
session.getCallback().asBinder().unlinkToDeath(session, 0);
@@ -455,7 +456,6 @@
throw new RuntimeException("Media Session owner died prematurely.", e);
}
- mAllSessions.add(session);
mPriorityStack.addSession(session, mCurrentUserIdList.contains(userId));
user.addSessionLocked(session);
@@ -1087,16 +1087,10 @@
synchronized (mLock) {
pw.println(mSessionsListeners.size() + " sessions listeners.");
- int count = mAllSessions.size();
- pw.println(count + " Sessions:");
- for (int i = 0; i < count; i++) {
- mAllSessions.get(i).dump(pw, "");
- pw.println();
- }
mPriorityStack.dump(pw, "");
pw.println("User Records:");
- count = mUserRecords.size();
+ int count = mUserRecords.size();
for (int i = 0; i < count; i++) {
UserRecord user = mUserRecords.get(mUserRecords.keyAt(i));
user.dumpLocked(pw, "");
diff --git a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
index 9da94b3..06b6f66 100644
--- a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
@@ -20,6 +20,7 @@
import android.annotation.NonNull;
import android.app.DownloadManager;
import android.app.admin.DevicePolicyManager;
+import android.companion.CompanionDeviceManager;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
@@ -673,6 +674,16 @@
&& doesPackageSupportRuntimePermissions(storageManagerPckg)) {
grantRuntimePermissionsLPw(storageManagerPckg, STORAGE_PERMISSIONS, true, userId);
}
+
+ // Companion devices
+ PackageParser.Package companionDeviceDiscoveryPackage = getSystemPackageLPr(
+ CompanionDeviceManager.COMPANION_DEVICE_DISCOVERY_PACKAGE_NAME);
+ if (companionDeviceDiscoveryPackage != null
+ && doesPackageSupportRuntimePermissions(companionDeviceDiscoveryPackage)) {
+ grantRuntimePermissionsLPw(companionDeviceDiscoveryPackage,
+ LOCATION_PERMISSIONS, true, userId);
+ }
+
mService.mSettings.onDefaultRuntimePermissionsGrantedLPr(userId);
}
}
diff --git a/services/core/java/com/android/server/updates/TzDataInstallReceiver.java b/services/core/java/com/android/server/updates/TzDataInstallReceiver.java
index b704eb1..3c73c88 100644
--- a/services/core/java/com/android/server/updates/TzDataInstallReceiver.java
+++ b/services/core/java/com/android/server/updates/TzDataInstallReceiver.java
@@ -20,7 +20,7 @@
import java.io.File;
import java.io.IOException;
-import libcore.tzdata.update2.TimeZoneBundleInstaller;
+import libcore.tzdata.update2.TimeZoneDistroInstaller;
/**
* An install receiver responsible for installing timezone data updates.
@@ -34,14 +34,14 @@
private static final String UPDATE_DIR_NAME = TZ_DATA_DIR.getPath() + "/updates/";
private static final String UPDATE_METADATA_DIR_NAME = "metadata/";
private static final String UPDATE_VERSION_FILE_NAME = "version";
- private static final String UPDATE_CONTENT_FILE_NAME = "tzdata_bundle.zip";
+ private static final String UPDATE_CONTENT_FILE_NAME = "tzdata_distro.zip";
- private final TimeZoneBundleInstaller installer;
+ private final TimeZoneDistroInstaller installer;
public TzDataInstallReceiver() {
super(UPDATE_DIR_NAME, UPDATE_CONTENT_FILE_NAME, UPDATE_METADATA_DIR_NAME,
UPDATE_VERSION_FILE_NAME);
- installer = new TimeZoneBundleInstaller(TAG, SYSTEM_TZ_DATA_FILE, TZ_DATA_DIR);
+ installer = new TimeZoneDistroInstaller(TAG, SYSTEM_TZ_DATA_FILE, TZ_DATA_DIR);
}
@Override
diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java
index 0a92a81..75a79fd 100644
--- a/services/core/java/com/android/server/wm/DockedStackDividerController.java
+++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java
@@ -152,11 +152,6 @@
int getSmallestWidthDpForBounds(Rect bounds) {
final DisplayInfo di = mDisplayContent.getDisplayInfo();
- // If the bounds are fullscreen, return the value of the fullscreen configuration
- if (bounds == null || (bounds.left == 0 && bounds.top == 0
- && bounds.right == di.logicalWidth && bounds.bottom == di.logicalHeight)) {
- return mDisplayContent.getConfiguration().smallestScreenWidthDp;
- }
final int baseDisplayWidth = mDisplayContent.mBaseDisplayWidth;
final int baseDisplayHeight = mDisplayContent.mBaseDisplayHeight;
int minWidth = Integer.MAX_VALUE;
@@ -185,7 +180,7 @@
mTmpRect2.width(), mTmpRect2.height(), getContentWidth());
mService.mPolicy.getStableInsetsLw(rotation, mTmpRect2.width(), mTmpRect2.height(),
mTmpRect3);
- mService.subtractInsets(mTmpRect2, mTmpRect3, mTmpRect);
+ mService.intersectDisplayInsetBounds(mTmpRect2, mTmpRect3, mTmpRect);
minWidth = Math.min(mTmpRect.width(), minWidth);
}
return (int) (minWidth / mDisplayContent.getDisplayMetrics().density);
diff --git a/services/core/java/com/android/server/wm/StackWindowController.java b/services/core/java/com/android/server/wm/StackWindowController.java
index 36d07e0..142f69a 100644
--- a/services/core/java/com/android/server/wm/StackWindowController.java
+++ b/services/core/java/com/android/server/wm/StackWindowController.java
@@ -16,6 +16,9 @@
package com.android.server.wm;
+import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
+
+import android.app.ActivityManager.StackId;
import android.app.RemoteAction;
import android.content.res.Configuration;
import android.graphics.Rect;
@@ -24,6 +27,8 @@
import android.os.Message;
import android.util.Slog;
import android.util.SparseArray;
+import android.view.DisplayInfo;
+
import com.android.server.UiThread;
import com.android.internal.annotations.VisibleForTesting;
@@ -48,6 +53,12 @@
private final H mHandler;
+ // Temp bounds only used in adjustConfigurationForBounds()
+ private final Rect mTmpRect = new Rect();
+ private final Rect mTmpStableInsets = new Rect();
+ private final Rect mTmpNonDecorInsets = new Rect();
+ private final Rect mTmpDisplayBounds = new Rect();
+
public StackWindowController(int stackId, StackWindowListener listener,
int displayId, boolean onTop, Rect outBounds) {
this(stackId, listener, displayId, onTop, outBounds, WindowManagerService.getInstance());
@@ -289,6 +300,107 @@
}
}
+ /**
+ * Adjusts the screen size in dp's for the {@param config} for the given params.
+ */
+ public void adjustConfigurationForBounds(Rect bounds, Rect insetBounds,
+ Rect nonDecorBounds, Rect stableBounds, boolean overrideWidth,
+ boolean overrideHeight, float density, Configuration config,
+ Configuration parentConfig) {
+ synchronized (mWindowMap) {
+ final TaskStack stack = mContainer;
+ final DisplayContent displayContent = stack.getDisplayContent();
+ final DisplayInfo di = displayContent.getDisplayInfo();
+
+ // Get the insets and display bounds
+ mService.mPolicy.getStableInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight,
+ mTmpStableInsets);
+ mService.mPolicy.getNonDecorInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight,
+ mTmpNonDecorInsets);
+ mTmpDisplayBounds.set(0, 0, di.logicalWidth, di.logicalHeight);
+
+ int width;
+ int height;
+ if (StackId.tasksAreFloating(mStackId)) {
+ // Floating tasks should not be resized to the screen's bounds.
+
+ if (bounds.width() == mTmpDisplayBounds.width() &&
+ bounds.height() == mTmpDisplayBounds.height()) {
+ // If the bounds we are animating is the same as the fullscreen stack
+ // dimensions, then apply the same inset calculations that we normally do for
+ // the fullscreen stack, without intersecting it with the display bounds
+ stableBounds.inset(mTmpStableInsets);
+ nonDecorBounds.inset(mTmpNonDecorInsets);
+ }
+ width = (int) (stableBounds.width() / density);
+ height = (int) (stableBounds.height() / density);
+ } else {
+ // For calculating screenWidthDp, screenWidthDp, we use the stable inset screen
+ // area, i.e. the screen area without the system bars.
+ // Additionally task dimensions should not be bigger than its parents dimensions.
+ // The non decor inset are areas that could never be removed in Honeycomb. See
+ // {@link WindowManagerPolicy#getNonDecorInsetsLw}.
+ intersectDisplayBoundsExcludeInsets(nonDecorBounds,
+ insetBounds != null ? insetBounds : bounds, mTmpNonDecorInsets,
+ mTmpDisplayBounds, overrideWidth, overrideHeight);
+ intersectDisplayBoundsExcludeInsets(stableBounds,
+ insetBounds != null ? insetBounds : bounds, mTmpStableInsets,
+ mTmpDisplayBounds, overrideWidth, overrideHeight);
+ width = Math.min((int) (stableBounds.width() / density),
+ parentConfig.screenWidthDp);
+ height = Math.min((int) (stableBounds.height() / density),
+ parentConfig.screenHeightDp);
+ }
+
+ config.screenWidthDp = width;
+ config.screenHeightDp = height;
+ config.smallestScreenWidthDp = getSmallestWidthForTaskBounds(
+ insetBounds != null ? insetBounds : bounds, density);
+ }
+ }
+
+ /**
+ * Intersects the specified {@code inOutBounds} with the display frame that excludes the stable
+ * inset areas.
+ *
+ * @param inOutBounds The inOutBounds to subtract the stable inset areas from.
+ */
+ private void intersectDisplayBoundsExcludeInsets(Rect inOutBounds, Rect inInsetBounds,
+ Rect stableInsets, Rect displayBounds, boolean overrideWidth, boolean overrideHeight) {
+ mTmpRect.set(inInsetBounds);
+ mService.intersectDisplayInsetBounds(displayBounds, stableInsets, mTmpRect);
+ int leftInset = mTmpRect.left - inInsetBounds.left;
+ int topInset = mTmpRect.top - inInsetBounds.top;
+ int rightInset = overrideWidth ? 0 : inInsetBounds.right - mTmpRect.right;
+ int bottomInset = overrideHeight ? 0 : inInsetBounds.bottom - mTmpRect.bottom;
+ inOutBounds.inset(leftInset, topInset, rightInset, bottomInset);
+ }
+
+ /**
+ * Calculates the smallest width for a task given the {@param bounds}.
+ *
+ * @return the smallest width to be used in the Configuration, in dips
+ */
+ private int getSmallestWidthForTaskBounds(Rect bounds, float density) {
+ final DisplayContent displayContent = mContainer.getDisplayContent();
+ final DisplayInfo displayInfo = displayContent.getDisplayInfo();
+
+ if (bounds == null || (bounds.width() == displayInfo.logicalWidth &&
+ bounds.height() == displayInfo.logicalHeight)) {
+ // If the bounds are fullscreen, return the value of the fullscreen configuration
+ return displayContent.getConfiguration().smallestScreenWidthDp;
+ } else if (StackId.tasksAreFloating(mStackId)) {
+ // For floating tasks, calculate the smallest width from the bounds of the task
+ return (int) (Math.min(bounds.width(), bounds.height()) / density);
+ } else {
+ // Iterating across all screen orientations, and return the minimum of the task
+ // width taking into account that the bounds might change because the snap algorithm
+ // snaps to a different value
+ return displayContent.getDockedDividerController()
+ .getSmallestWidthDpForBounds(bounds);
+ }
+ }
+
void requestResize(Rect bounds) {
mHandler.obtainMessage(H.REQUEST_RESIZE, bounds).sendToTarget();
}
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index b09d699..b9429f4 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -1476,7 +1476,10 @@
@Override
public void getFullScreenBounds(Rect bounds) {
- getDisplayContent().getContentRect(bounds);
+ // This is currently only used for the pinned stack animation when leaving PiP
+ // (see {@link BoundsAnimationController}), and in that case we need to animate this back
+ // to the full bounds to match the fullscreen stack
+ getDisplayContent().getLogicalDisplayRect(bounds);
}
public boolean hasMovementAnimations() {
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 78568fc..5653113 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -6146,6 +6146,7 @@
* Get an array with display ids ordered by focus priority - last items should be given
* focus first. Sparse array just maps position to displayId.
*/
+ // TODO: Maintain display list in focus order in ActivityManager and remove this call.
public void getDisplaysInFocusOrder(SparseIntArray displaysInFocusOrder) {
synchronized(mWindowMap) {
mRoot.getDisplaysInFocusOrder(displaysInFocusOrder);
@@ -7543,63 +7544,12 @@
}
}
- private void getNonDecorInsetsLocked(Rect outInsets) {
- final DisplayInfo di = getDefaultDisplayInfoLocked();
- mPolicy.getNonDecorInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight, outInsets);
- }
-
- /**
- * Intersects the specified {@code inOutBounds} with the display frame that excludes the stable
- * inset areas.
- *
- * @param inOutBounds The inOutBounds to subtract the stable inset areas from.
- */
- public void subtractStableInsets(Rect inOutBounds) {
- synchronized (mWindowMap) {
- getStableInsetsLocked(DEFAULT_DISPLAY, mTmpRect2);
- final DisplayInfo di = getDefaultDisplayInfoLocked();
- mTmpRect.set(0, 0, di.logicalWidth, di.logicalHeight);
- subtractInsets(mTmpRect, mTmpRect2, inOutBounds);
- }
- }
-
- /**
- * Intersects the specified {@code inOutBounds} with the display frame that excludes
- * areas that could never be removed in Honeycomb. See
- * {@link WindowManagerPolicy#getNonDecorInsetsLw}.
- *
- * @param inOutBounds The inOutBounds to subtract the inset areas from.
- */
- public void subtractNonDecorInsets(Rect inOutBounds) {
- synchronized (mWindowMap) {
- getNonDecorInsetsLocked(mTmpRect2);
- final DisplayInfo di = getDefaultDisplayInfoLocked();
- mTmpRect.set(0, 0, di.logicalWidth, di.logicalHeight);
- subtractInsets(mTmpRect, mTmpRect2, inOutBounds);
- }
- }
-
- void subtractInsets(Rect display, Rect insets, Rect inOutBounds) {
+ void intersectDisplayInsetBounds(Rect display, Rect insets, Rect inOutBounds) {
mTmpRect3.set(display);
mTmpRect3.inset(insets);
inOutBounds.intersect(mTmpRect3);
}
- /**
- * Calculates the smallest width for a task given the {@param bounds}. It does that by iterating
- * across all screen orientations, and returns the minimum of the task width taking into account
- * that the bounds might change because the snap algorithm snaps to a different value.
- *
- * @return the smallest width to be used in the Configuration, in dips
- */
- public int getSmallestWidthForTaskBounds(Rect bounds) {
- synchronized (mWindowMap) {
- // TODO(multi-display): Use correct display content here
- return getDefaultDisplayContentLocked().getDockedDividerController()
- .getSmallestWidthDpForBounds(bounds);
- }
- }
-
MousePositionTracker mMousePositionTracker = new MousePositionTracker();
private static class MousePositionTracker implements PointerEventListener {
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 83e209d..31c8261 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -35,6 +35,7 @@
import android.os.IIncidentManager;
import android.os.Looper;
import android.os.PowerManager;
+import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.StrictMode;
@@ -236,6 +237,8 @@
private static final String START_SENSOR_SERVICE = "StartSensorService";
private Future<?> mSensorServiceStart;
+ private Future<?> mZygotePreload;
+
/**
* Start the sensor service. This is a blocking call and can take time.
@@ -688,6 +691,26 @@
}
try {
+ final String SECONDARY_ZYGOTE_PRELOAD = "SecondaryZygotePreload";
+ // We start the preload ~1s before the webview factory preparation, to
+ // ensure that it completes before the 32 bit relro process is forked
+ // from the zygote. In the event that it takes too long, the webview
+ // RELRO process will block, but it will do so without holding any locks.
+ mZygotePreload = SystemServerInitThreadPool.get().submit(() -> {
+ try {
+ Slog.i(TAG, SECONDARY_ZYGOTE_PRELOAD);
+ BootTimingsTraceLog traceLog = new BootTimingsTraceLog(
+ SYSTEM_SERVER_TIMING_ASYNC_TAG, Trace.TRACE_TAG_SYSTEM_SERVER);
+ traceLog.traceBegin(SECONDARY_ZYGOTE_PRELOAD);
+ if (!Process.zygoteProcess.preloadDefault(Build.SUPPORTED_32_BIT_ABIS[0])) {
+ Slog.e(TAG, "Unable to preload default resources");
+ }
+ traceLog.traceEnd();
+ } catch (Exception ex) {
+ Slog.e(TAG, "Exception preloading default resources", ex);
+ }
+ }, SECONDARY_ZYGOTE_PRELOAD);
+
traceBeginAndSlog("StartKeyAttestationApplicationIdProviderService");
ServiceManager.addService("sec_key_att_app_id_provider",
new KeyAttestationApplicationIdProviderService(context));
@@ -1615,6 +1638,8 @@
BootTimingsTraceLog traceLog = new BootTimingsTraceLog(
SYSTEM_SERVER_TIMING_ASYNC_TAG, Trace.TRACE_TAG_SYSTEM_SERVER);
traceLog.traceBegin(WEBVIEW_PREPARATION);
+ ConcurrentUtils.waitForFutureNoInterrupt(mZygotePreload, "Zygote preload");
+ mZygotePreload = null;
mWebViewUpdateService.prepareWebViewInSystemServer();
traceLog.traceEnd();
}, WEBVIEW_PREPARATION);
diff --git a/services/print/java/com/android/server/print/CompanionDeviceManagerService.java b/services/print/java/com/android/server/print/CompanionDeviceManagerService.java
index 9824c1d..9ac8295 100644
--- a/services/print/java/com/android/server/print/CompanionDeviceManagerService.java
+++ b/services/print/java/com/android/server/print/CompanionDeviceManagerService.java
@@ -19,20 +19,28 @@
import static com.android.internal.util.Preconditions.checkNotNull;
-import android.app.PendingIntent;
+import android.Manifest;
import android.companion.AssociationRequest;
+import android.companion.CompanionDeviceManager;
+import android.companion.ICompanionDeviceDiscoveryService;
+import android.companion.ICompanionDeviceDiscoveryServiceCallback;
import android.companion.ICompanionDeviceManager;
-import android.companion.ICompanionDeviceManagerService;
-import android.companion.IOnAssociateCallback;
+import android.companion.IFindDeviceCallback;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.net.NetworkPolicyManager;
import android.os.Binder;
import android.os.IBinder;
+import android.os.IDeviceIdleController;
import android.os.RemoteException;
-import android.util.Log;
+import android.os.ServiceManager;
+import android.util.Slog;
+import com.android.internal.util.ArrayUtils;
import com.android.server.SystemService;
//TODO move to own package!
@@ -40,7 +48,8 @@
public class CompanionDeviceManagerService extends SystemService {
private static final ComponentName SERVICE_TO_BIND_TO = ComponentName.createRelative(
- "com.android.companiondevicemanager", ".DeviceDiscoveryService");
+ CompanionDeviceManager.COMPANION_DEVICE_DISCOVERY_PACKAGE_NAME,
+ ".DeviceDiscoveryService");
private static final boolean DEBUG = false;
private static final String LOG_TAG = "CompanionDeviceManagerService";
@@ -58,14 +67,13 @@
}
class CompanionDeviceManagerImpl extends ICompanionDeviceManager.Stub {
-
@Override
public void associate(
AssociationRequest request,
- IOnAssociateCallback callback,
- String callingPackage) throws RemoteException {
+ IFindDeviceCallback callback,
+ String callingPackage) {
if (DEBUG) {
- Log.i(LOG_TAG, "associate(request = " + request + ", callback = " + callback
+ Slog.i(LOG_TAG, "associate(request = " + request + ", callback = " + callback
+ ", callingPackage = " + callingPackage + ")");
}
checkNotNull(request);
@@ -85,23 +93,24 @@
private ServiceConnection getServiceConnection(
final AssociationRequest<?> request,
- final IOnAssociateCallback callback,
+ final IFindDeviceCallback findDeviceCallback,
final String callingPackage) {
return new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
if (DEBUG) {
- Log.i(LOG_TAG,
+ Slog.i(LOG_TAG,
"onServiceConnected(name = " + name + ", service = "
+ service + ")");
}
try {
- ICompanionDeviceManagerService.Stub
+ ICompanionDeviceDiscoveryService.Stub
.asInterface(service)
.startDiscovery(
request,
- getCallback(callingPackage, callback),
- callingPackage);
+ callingPackage,
+ findDeviceCallback,
+ getServiceCallback());
} catch (RemoteException e) {
throw new RuntimeException(e);
}
@@ -109,39 +118,50 @@
@Override
public void onServiceDisconnected(ComponentName name) {
- if (DEBUG) Log.i(LOG_TAG, "onServiceDisconnected(name = " + name + ")");
+ if (DEBUG) Slog.i(LOG_TAG, "onServiceDisconnected(name = " + name + ")");
}
};
}
- private IOnAssociateCallback.Stub getCallback(
- String callingPackage,
- IOnAssociateCallback propagateTo) {
- return new IOnAssociateCallback.Stub() {
-
+ private ICompanionDeviceDiscoveryServiceCallback.Stub getServiceCallback() {
+ return new ICompanionDeviceDiscoveryServiceCallback.Stub() {
@Override
- public void onSuccess(PendingIntent launcher)
- throws RemoteException {
- if (DEBUG) Log.i(LOG_TAG, "onSuccess(launcher = " + launcher + ")");
- recordSpecialPriviledgesForPackage(callingPackage);
- propagateTo.onSuccess(launcher);
- }
-
- @Override
- public void onFailure(CharSequence reason) throws RemoteException {
- if (DEBUG) Log.i(LOG_TAG, "onFailure()");
- propagateTo.onFailure(reason);
+ public void onDeviceSelected(String packageName, int userId) {
+ grantSpecialAccessPermissionsIfNeeded(packageName, userId);
}
};
}
- void recordSpecialPriviledgesForPackage(String priviledgedPackage) {
- //TODO Show dialog before recording notification access
-// final SettingStringHelper setting =
-// new SettingStringHelper(
-// getContext().getContentResolver(),
-// Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
-// Binder.getCallingUid());
-// setting.write(ColonDelimitedSet.OfStrings.add(setting.read(), priviledgedPackage));
+ private void grantSpecialAccessPermissionsIfNeeded(String packageName, int userId) {
+ final long identity = Binder.clearCallingIdentity();
+ final PackageInfo packageInfo;
+ try {
+ packageInfo = getContext().getPackageManager().getPackageInfoAsUser(
+ packageName, PackageManager.GET_PERMISSIONS, userId);
+ } catch (PackageManager.NameNotFoundException e) {
+ Slog.e(LOG_TAG, "Error granting special access permissions to package:"
+ + packageName, e);
+ return;
+ }
+ try {
+ if (ArrayUtils.contains(packageInfo.requestedPermissions,
+ Manifest.permission.RUN_IN_BACKGROUND)) {
+ IDeviceIdleController idleController = IDeviceIdleController.Stub.asInterface(
+ ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
+ try {
+ idleController.addPowerSaveWhitelistApp(packageName);
+ } catch (RemoteException e) {
+ /* ignore - local call */
+ }
+ }
+ if (ArrayUtils.contains(packageInfo.requestedPermissions,
+ Manifest.permission.USE_DATA_IN_BACKGROUND)) {
+ NetworkPolicyManager.from(getContext()).addUidPolicy(
+ packageInfo.applicationInfo.uid,
+ NetworkPolicyManager.POLICY_ALLOW_METERED_BACKGROUND);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
}
}
diff --git a/tools/layoutlib/bridge/src/android/content/res/Resources_Delegate.java b/tools/layoutlib/bridge/src/android/content/res/Resources_Delegate.java
index d71cc6f..6e3a8e8 100644
--- a/tools/layoutlib/bridge/src/android/content/res/Resources_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/content/res/Resources_Delegate.java
@@ -50,6 +50,7 @@
import android.util.DisplayMetrics;
import android.util.LruCache;
import android.util.TypedValue;
+import android.view.DisplayAdjustments;
import android.view.ViewGroup.LayoutParams;
import java.io.File;
@@ -71,7 +72,8 @@
DisplayMetrics metrics,
Configuration config,
LayoutlibCallback layoutlibCallback) {
- Resources resources = new Resources(assets, metrics, config);
+ Resources resources = new Resources(Resources_Delegate.class.getClassLoader());
+ resources.setImpl(new ResourcesImpl(assets, metrics, config, new DisplayAdjustments()));
resources.mContext = context;
resources.mLayoutlibCallback = layoutlibCallback;
return Resources.mSystem = resources;
diff --git a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/setup/LayoutLibTestCallback.java b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/setup/LayoutLibTestCallback.java
index bae2dc0c..8ebfc65 100644
--- a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/setup/LayoutLibTestCallback.java
+++ b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/setup/LayoutLibTestCallback.java
@@ -132,7 +132,11 @@
@Override
public Integer getResourceId(ResourceType type, String name) {
- return mResources.get(type).get(name);
+ Map<String, Integer> resName2Id = mResources.get(type);
+ if (resName2Id == null) {
+ return null;
+ }
+ return resName2Id.get(name);
}
@Override
diff --git a/tools/layoutlib/create/create.iml b/tools/layoutlib/create/create.iml
index 368b46b..ac97502 100644
--- a/tools/layoutlib/create/create.iml
+++ b/tools/layoutlib/create/create.iml
@@ -12,9 +12,9 @@
<orderEntry type="jdk" jdkName="1.8" jdkType="JavaSDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module-library">
- <library name="asm-5.0">
+ <library name="asm-5.2">
<CLASSES>
- <root url="jar://$MODULE_DIR$/../../../../../prebuilts/misc/common/asm/asm-5.0.jar!/" />
+ <root url="jar://$MODULE_DIR$/../../../../../prebuilts/misc/common/asm/asm-5.2.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>