Merge "Map MediaStore items to StorageVolume."
diff --git a/Android.bp b/Android.bp
index 1ee7405..6288940 100644
--- a/Android.bp
+++ b/Android.bp
@@ -69,7 +69,6 @@
"core/java/android/app/ITaskStackListener.aidl",
"core/java/android/app/IBackupAgent.aidl",
"core/java/android/app/IEphemeralResolver.aidl",
- "core/java/android/app/IInputForwarder.aidl",
"core/java/android/app/IInstantAppResolver.aidl",
"core/java/android/app/IInstrumentationWatcher.aidl",
"core/java/android/app/INotificationManager.aidl",
diff --git a/api/TEST_MAPPING b/api/TEST_MAPPING
index 8a676e9..2cdf54b 100644
--- a/api/TEST_MAPPING
+++ b/api/TEST_MAPPING
@@ -2,6 +2,9 @@
"presubmit": [
{
"name": "CtsCurrentApiSignatureTestCases"
+ },
+ {
+ "name": "GtsUnofficialApisUsageTestCases"
}
]
}
diff --git a/api/current.txt b/api/current.txt
index 01890c8..4ac827a 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -38610,13 +38610,13 @@
public static final class MediaStore.Images.Media implements android.provider.MediaStore.Images.ImageColumns {
ctor public MediaStore.Images.Media();
- method public static android.graphics.Bitmap getBitmap(android.content.ContentResolver, android.net.Uri) throws java.io.FileNotFoundException, java.io.IOException;
+ method @Deprecated public static android.graphics.Bitmap getBitmap(android.content.ContentResolver, android.net.Uri) throws java.io.FileNotFoundException, java.io.IOException;
method public static android.net.Uri getContentUri(String);
- method public static String insertImage(android.content.ContentResolver, String, String, String) throws java.io.FileNotFoundException;
- method public static String insertImage(android.content.ContentResolver, android.graphics.Bitmap, String, String);
- method public static android.database.Cursor query(android.content.ContentResolver, android.net.Uri, String[]);
- method public static android.database.Cursor query(android.content.ContentResolver, android.net.Uri, String[], String, String);
- method public static android.database.Cursor query(android.content.ContentResolver, android.net.Uri, String[], String, String[], String);
+ method @Deprecated public static String insertImage(android.content.ContentResolver, String, String, String) throws java.io.FileNotFoundException;
+ method @Deprecated public static String insertImage(android.content.ContentResolver, android.graphics.Bitmap, String, String);
+ method @Deprecated public static android.database.Cursor query(android.content.ContentResolver, android.net.Uri, String[]);
+ method @Deprecated public static android.database.Cursor query(android.content.ContentResolver, android.net.Uri, String[], String, String);
+ method @Deprecated public static android.database.Cursor query(android.content.ContentResolver, android.net.Uri, String[], String, String[], String);
field public static final String CONTENT_TYPE = "vnd.android.cursor.dir/image";
field public static final String DEFAULT_SORT_ORDER = "bucket_display_name";
field public static final android.net.Uri EXTERNAL_CONTENT_URI;
@@ -38685,7 +38685,7 @@
public static final class MediaStore.Video {
ctor public MediaStore.Video();
- method public static android.database.Cursor query(android.content.ContentResolver, android.net.Uri, String[]);
+ method @Deprecated public static android.database.Cursor query(android.content.ContentResolver, android.net.Uri, String[]);
field public static final String DEFAULT_SORT_ORDER = "_display_name";
}
diff --git a/config/hiddenapi-greylist.txt b/config/hiddenapi-greylist.txt
index dc2ed4c..a836e8e 100644
--- a/config/hiddenapi-greylist.txt
+++ b/config/hiddenapi-greylist.txt
@@ -170,7 +170,6 @@
Landroid/app/IAssistDataReceiver$Stub;-><init>()V
Landroid/app/IAssistDataReceiver;->onHandleAssistData(Landroid/os/Bundle;)V
Landroid/app/IAssistDataReceiver;->onHandleAssistScreenshot(Landroid/graphics/Bitmap;)V
-Landroid/app/IInputForwarder;->forwardEvent(Landroid/view/InputEvent;)Z
Landroid/app/IInstrumentationWatcher$Stub;-><init>()V
Landroid/app/IInstrumentationWatcher;->instrumentationStatus(Landroid/content/ComponentName;ILandroid/os/Bundle;)V
Landroid/app/INotificationManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
diff --git a/core/java/android/annotation/CurrentTimeMillisLong.java b/core/java/android/annotation/CurrentTimeMillisLong.java
index 9846cce..355bb5a 100644
--- a/core/java/android/annotation/CurrentTimeMillisLong.java
+++ b/core/java/android/annotation/CurrentTimeMillisLong.java
@@ -25,12 +25,12 @@
import java.lang.annotation.Target;
/**
- * @memberDoc Value is a non-negative timestamp in the
- * {@link System#currentTimeMillis()} time base.
- * @paramDoc Value is a non-negative timestamp in the
- * {@link System#currentTimeMillis()} time base.
- * @returnDoc Value is a non-negative timestamp in the
- * {@link System#currentTimeMillis()} time base.
+ * @memberDoc Value is a non-negative timestamp measured as the number of
+ * milliseconds since 1970-01-01T00:00:00Z.
+ * @paramDoc Value is a non-negative timestamp measured as the number of
+ * milliseconds since 1970-01-01T00:00:00Z.
+ * @returnDoc Value is a non-negative timestamp measured as the number of
+ * milliseconds since 1970-01-01T00:00:00Z.
* @hide
*/
@Retention(SOURCE)
diff --git a/core/java/android/annotation/CurrentTimeSecondsLong.java b/core/java/android/annotation/CurrentTimeSecondsLong.java
new file mode 100644
index 0000000..2b4ffd7
--- /dev/null
+++ b/core/java/android/annotation/CurrentTimeSecondsLong.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.annotation;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * @memberDoc Value is a non-negative timestamp measured as the number of
+ * seconds since 1970-01-01T00:00:00Z.
+ * @paramDoc Value is a non-negative timestamp measured as the number of
+ * seconds since 1970-01-01T00:00:00Z.
+ * @returnDoc Value is a non-negative timestamp measured as the number of
+ * seconds since 1970-01-01T00:00:00Z.
+ * @hide
+ */
+@Retention(SOURCE)
+@Target({METHOD, PARAMETER, FIELD})
+public @interface CurrentTimeSecondsLong {
+}
diff --git a/core/java/android/annotation/Px.java b/core/java/android/annotation/Px.java
index ad99fdb..cec7f80 100644
--- a/core/java/android/annotation/Px.java
+++ b/core/java/android/annotation/Px.java
@@ -29,6 +29,7 @@
* Denotes that a numeric parameter, field or method return value is expected
* to represent a pixel dimension.
*
+ * @memberDoc This units of this value are pixels.
* @paramDoc This units of this value are pixels.
* @returnDoc This units of this value are pixels.
* {@hide}
diff --git a/core/java/android/app/ActivityView.java b/core/java/android/app/ActivityView.java
index bcbeb22..e0ae4e3 100644
--- a/core/java/android/app/ActivityView.java
+++ b/core/java/android/app/ActivityView.java
@@ -29,12 +29,17 @@
import android.graphics.Insets;
import android.hardware.display.DisplayManager;
import android.hardware.display.VirtualDisplay;
+import android.hardware.input.InputManager;
import android.os.RemoteException;
+import android.os.SystemClock;
import android.os.UserHandle;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.IWindowManager;
+import android.view.InputDevice;
+import android.view.KeyCharacterMap;
+import android.view.KeyEvent;
import android.view.SurfaceControl;
import android.view.SurfaceHolder;
import android.view.SurfaceSession;
@@ -346,6 +351,32 @@
mSurfaceView.setVisibility(visibility);
}
+ /**
+ * Injects a pair of down/up key events with keycode {@link KeyEvent#KEYCODE_BACK} to the
+ * virtual display.
+ */
+ public void performBackPress() {
+ if (mVirtualDisplay == null) {
+ return;
+ }
+ final int displayId = mVirtualDisplay.getDisplay().getDisplayId();
+ final InputManager im = InputManager.getInstance();
+ im.injectInputEvent(createKeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK, displayId),
+ InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
+ im.injectInputEvent(createKeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK, displayId),
+ InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
+ }
+
+ private static KeyEvent createKeyEvent(int action, int code, int displayId) {
+ long when = SystemClock.uptimeMillis();
+ final KeyEvent ev = new KeyEvent(when, when, action, code, 0 /* repeat */,
+ 0 /* metaState */, KeyCharacterMap.VIRTUAL_KEYBOARD, 0 /* scancode */,
+ KeyEvent.FLAG_FROM_SYSTEM | KeyEvent.FLAG_VIRTUAL_HARD_KEY,
+ InputDevice.SOURCE_KEYBOARD);
+ ev.setDisplayId(displayId);
+ return ev;
+ }
+
private void initVirtualDisplay(SurfaceSession surfaceSession) {
if (mVirtualDisplay != null) {
throw new IllegalStateException("Trying to initialize for the second time.");
diff --git a/core/java/android/app/IInputForwarder.aidl b/core/java/android/app/IInputForwarder.aidl
deleted file mode 100644
index d6be63e..0000000
--- a/core/java/android/app/IInputForwarder.aidl
+++ /dev/null
@@ -1,29 +0,0 @@
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app;
-
-import android.view.InputEvent;
-
-/**
- * Forwards input events into owned activity container, used in {@link android.app.ActivityView}.
- * To forward input to other apps {@link android.Manifest.permission.INJECT_EVENTS} permission is
- * required.
- * @hide
- */
-interface IInputForwarder {
- boolean forwardEvent(in InputEvent event);
-}
\ No newline at end of file
diff --git a/core/java/android/hardware/input/IInputManager.aidl b/core/java/android/hardware/input/IInputManager.aidl
index 97868fa..64448fd9 100644
--- a/core/java/android/hardware/input/IInputManager.aidl
+++ b/core/java/android/hardware/input/IInputManager.aidl
@@ -16,7 +16,6 @@
package android.hardware.input;
-import android.app.IInputForwarder;
import android.hardware.input.InputDeviceIdentifier;
import android.hardware.input.KeyboardLayout;
import android.hardware.input.IInputDevicesChangedListener;
@@ -82,7 +81,4 @@
void setCustomPointerIcon(in PointerIcon icon);
void requestPointerCapture(IBinder windowToken, boolean enabled);
-
- /** Create input forwarder to deliver touch events to owned display. */
- IInputForwarder createInputForwarder(int displayId);
}
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index bfb7c58..fec5c34 100644
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -21,7 +21,6 @@
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemService;
import android.annotation.UnsupportedAppUsage;
-import android.app.IInputForwarder;
import android.content.Context;
import android.media.AudioAttributes;
import android.os.Binder;
@@ -934,26 +933,6 @@
}
}
-
- /**
- * Create an {@link IInputForwarder} targeted to provided display.
- * {@link android.Manifest.permission.INJECT_EVENTS} permission is required to call this method.
- *
- * @param displayId Id of the target display where input events should be forwarded.
- * Display must exist and must be owned by the caller.
- * @return The forwarder instance.
- *
- * @hide
- */
- @UnsupportedAppUsage
- public IInputForwarder createInputForwarder(int displayId) {
- try {
- return mIm.createInputForwarder(displayId);
- } catch (RemoteException ex) {
- throw ex.rethrowFromSystemServer();
- }
- }
-
private void populateInputDevicesLocked() {
if (mInputDevicesChangedListener == null) {
final InputDevicesChangedListener listener = new InputDevicesChangedListener();
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index 3feccf5..0aed981 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -388,7 +388,7 @@
/** {@hide} */
public static File getDataStagingDirectory(String volumeUuid) {
- return new File(getDataDirectory(volumeUuid), "staging");
+ return new File(getDataDirectory(volumeUuid), "pkg_staging");
}
/** {@hide} */
diff --git a/core/java/android/os/ZygoteProcess.java b/core/java/android/os/ZygoteProcess.java
index ee3d354..1de8117 100644
--- a/core/java/android/os/ZygoteProcess.java
+++ b/core/java/android/os/ZygoteProcess.java
@@ -21,6 +21,7 @@
import android.content.pm.ApplicationInfo;
import android.net.LocalSocket;
import android.net.LocalSocketAddress;
+import android.provider.DeviceConfig;
import android.util.Log;
import android.util.Slog;
@@ -66,16 +67,6 @@
/**
* @hide for internal use only.
*/
- public static final String ZYGOTE_SOCKET_NAME = "zygote";
-
- /**
- * @hide for internal use only.
- */
- public static final String ZYGOTE_SECONDARY_SOCKET_NAME = "zygote_secondary";
-
- /**
- * @hide for internal use only.
- */
public static final int ZYGOTE_CONNECT_TIMEOUT_MS = 20000;
/**
@@ -89,19 +80,14 @@
/**
* @hide for internal use only
*/
- public static final String BLASTULA_POOL_SOCKET_NAME = "blastula_pool";
-
- /**
- * @hide for internal use only
- */
- public static final String BLASTULA_POOL_SECONDARY_SOCKET_NAME = "blastula_pool_secondary";
-
- /**
- * @hide for internal use only
- */
private static final String LOG_TAG = "ZygoteProcess";
/**
+ * The default value for enabling the blastula pool.
+ */
+ private static final String BLASTULA_POOL_ENABLED_DEFAULT = "false";
+
+ /**
* The name of the socket used to communicate with the primary zygote.
*/
private final LocalSocketAddress mZygoteSocketAddress;
@@ -110,6 +96,7 @@
* The name of the secondary (alternate ABI) zygote socket.
*/
private final LocalSocketAddress mZygoteSecondarySocketAddress;
+
/**
* The name of the socket used to communicate with the primary blastula pool.
*/
@@ -122,17 +109,21 @@
public ZygoteProcess() {
mZygoteSocketAddress =
- new LocalSocketAddress(ZYGOTE_SOCKET_NAME, LocalSocketAddress.Namespace.RESERVED);
+ new LocalSocketAddress(Zygote.PRIMARY_SOCKET_NAME,
+ LocalSocketAddress.Namespace.RESERVED);
mZygoteSecondarySocketAddress =
- new LocalSocketAddress(ZYGOTE_SECONDARY_SOCKET_NAME,
+ new LocalSocketAddress(Zygote.SECONDARY_SOCKET_NAME,
LocalSocketAddress.Namespace.RESERVED);
mBlastulaPoolSocketAddress =
- new LocalSocketAddress(BLASTULA_POOL_SOCKET_NAME,
+ new LocalSocketAddress(Zygote.BLASTULA_POOL_PRIMARY_SOCKET_NAME,
LocalSocketAddress.Namespace.RESERVED);
mBlastulaPoolSecondarySocketAddress =
- new LocalSocketAddress(BLASTULA_POOL_SECONDARY_SOCKET_NAME,
+ new LocalSocketAddress(Zygote.BLASTULA_POOL_SECONDARY_SOCKET_NAME,
LocalSocketAddress.Namespace.RESERVED);
+
+ // TODO (chriswailes): Uncomment when the blastula pool can be enabled.
+// fetchBlastulaPoolEnabledProp();
}
public ZygoteProcess(LocalSocketAddress primarySocketAddress,
@@ -272,6 +263,15 @@
private ZygoteState secondaryZygoteState;
/**
+ * If the blastula pool should be created and used to start applications.
+ *
+ * Setting this value to false will disable the creation, maintenance, and use of the blastula
+ * pool. When the blastula pool is disabled the application lifecycle will be identical to
+ * previous versions of Android.
+ */
+ private boolean mBlastulaPoolEnabled = false;
+
+ /**
* Start a new process.
*
* <p>If processes are enabled, a new process is created and the
@@ -327,6 +327,14 @@
@Nullable String sandboxId,
boolean useBlastulaPool,
@Nullable String[] zygoteArgs) {
+ if (fetchBlastulaPoolEnabledProp()) {
+ // TODO (chriswailes): Send the appropriate command to the zygotes
+ Log.i(LOG_TAG, "Blastula pool enabled property set to: " + mBlastulaPoolEnabled);
+
+ // This can't be enabled yet, but we do want to test this code path.
+ mBlastulaPoolEnabled = false;
+ }
+
try {
return startViaZygote(processClass, niceName, uid, gid, gids,
runtimeFlags, mountExternal, targetSdkVersion, seInfo,
@@ -407,7 +415,7 @@
Process.ProcessStartResult result = new Process.ProcessStartResult();
// TODO (chriswailes): Move branch body into separate function.
- if (useBlastulaPool && Zygote.BLASTULA_POOL_ENABLED && isValidBlastulaCommand(args)) {
+ if (useBlastulaPool && isValidBlastulaCommand(args)) {
LocalSocket blastulaSessionSocket = null;
try {
@@ -620,6 +628,7 @@
final StringBuilder sb = new StringBuilder();
sb.append("--packages-for-uid=");
+ // TODO (chriswailes): Replace with String.join
for (int i = 0; i < packagesForUid.length; ++i) {
if (i != 0) {
sb.append(',');
@@ -656,11 +665,42 @@
synchronized(mLock) {
return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi),
- useBlastulaPool,
+ useBlastulaPool && mBlastulaPoolEnabled,
argsForZygote);
}
}
+ private boolean fetchBlastulaPoolEnabledProp() {
+ boolean origVal = mBlastulaPoolEnabled;
+
+ final String propertyString =
+ Zygote.getSystemProperty(
+ DeviceConfig.RuntimeNative.BLASTULA_POOL_ENABLED,
+ BLASTULA_POOL_ENABLED_DEFAULT);
+
+ if (!propertyString.isEmpty()) {
+ mBlastulaPoolEnabled =
+ Zygote.getSystemPropertyBoolean(
+ DeviceConfig.RuntimeNative.BLASTULA_POOL_ENABLED,
+ Boolean.parseBoolean(BLASTULA_POOL_ENABLED_DEFAULT));
+ }
+
+ return origVal != mBlastulaPoolEnabled;
+ }
+
+ private long mLastPropCheckTimestamp = 0;
+
+ private boolean fetchBlastulaPoolEnabledPropWithMinInterval() {
+ final long currentTimestamp = SystemClock.elapsedRealtime();
+
+ if (currentTimestamp - mLastPropCheckTimestamp >= Zygote.PROPERTY_CHECK_INTERVAL) {
+ mLastPropCheckTimestamp = currentTimestamp;
+ return fetchBlastulaPoolEnabledProp();
+ }
+
+ return false;
+ }
+
/**
* Closes the connections to the zygote, if they exist.
*/
@@ -940,7 +980,7 @@
/**
* Try connecting to the Zygote over and over again until we hit a time-out.
- * @param socketName The name of the socket to connect to.
+ * @param zygoteSocketName The name of the socket to connect to.
*/
public static void waitForConnectionToZygote(String zygoteSocketName) {
final LocalSocketAddress zygoteSocketAddress =
@@ -950,7 +990,7 @@
/**
* Try connecting to the Zygote over and over again until we hit a time-out.
- * @param address The name of the socket to connect to.
+ * @param zygoteSocketAddress The name of the socket to connect to.
*/
public static void waitForConnectionToZygote(LocalSocketAddress zygoteSocketAddress) {
int numRetries = ZYGOTE_CONNECT_TIMEOUT_MS / ZYGOTE_CONNECT_RETRY_DELAY_MS;
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index 7eb0300..f6a8388 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -145,6 +145,38 @@
@SystemApi
public interface RuntimeNative {
String NAMESPACE = "runtime_native";
+
+ /**
+ * Zygote flags. See {@link com.internal.os.Zygote}.
+ */
+
+ /**
+ * If {@code true}, enables the blastula pool feature.
+ *
+ * @hide for internal use only
+ */
+ String BLASTULA_POOL_ENABLED = "blastula_pool_enabled";
+
+ /**
+ * The maximum number of processes to keep in the blastula pool.
+ *
+ * @hide for internal use only
+ */
+ String BLASTULA_POOL_SIZE_MAX = "blastula_pool_size_max";
+
+ /**
+ * The minimum number of processes to keep in the blastula pool.
+ *
+ * @hide for internal use only
+ */
+ String BLASTULA_POOL_SIZE_MIN = "blastula_pool_size_max";
+
+ /**
+ * The threshold used to determine if the pool should be refilled.
+ *
+ * @hide for internal use only
+ */
+ String BLASTULA_POOL_REFILL_THRESHOLD = "blastula_refill_threshold";
}
/**
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index 1b10bef..643307e 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -17,6 +17,8 @@
package android.provider;
import android.annotation.BytesLong;
+import android.annotation.CurrentTimeMillisLong;
+import android.annotation.CurrentTimeSecondsLong;
import android.annotation.DurationMillisLong;
import android.annotation.IntRange;
import android.annotation.NonNull;
@@ -40,7 +42,9 @@
import android.database.DatabaseUtils;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
+import android.graphics.ImageDecoder;
import android.graphics.Point;
+import android.graphics.PostProcessor;
import android.media.ExifInterface;
import android.net.Uri;
import android.os.Bundle;
@@ -78,8 +82,15 @@
import java.util.regex.Pattern;
/**
- * The Media provider contains meta data for all available media on both internal
- * and external storage devices.
+ * The contract between the media provider and applications. Contains
+ * definitions for the supported URIs and columns.
+ * <p>
+ * The media provider provides an indexed collection of common media types, such
+ * as {@link Audio}, {@link Video}, and {@link Images}, from any attached
+ * storage devices. Each collection is organized based on the primary MIME type
+ * of the underlying content; for example, {@code image/*} content is indexed
+ * under {@link Images}. The {@link Files} collection provides a broad view
+ * across all collections, and does not filter by MIME type.
*/
public final class MediaStore {
private final static String TAG = "MediaStore";
@@ -847,11 +858,11 @@
}
/**
- * Common fields for most MediaProvider tables
+ * Common media metadata columns.
*/
public interface MediaColumns extends BaseColumns {
/**
- * Path to the file on disk.
+ * Path to the media item on disk.
* <p>
* Note that apps may not have filesystem permissions to directly access
* this path. Instead of trying to open this path directly, apps should
@@ -871,7 +882,7 @@
public static final String DATA = "_data";
/**
- * Hash of the file on disk.
+ * Hash of the media item on disk.
* <p>
* Contains a 20-byte binary blob which is the SHA-1 hash of the file as
* persisted on disk. For performance reasons, the hash may not be
@@ -890,35 +901,35 @@
public static final String HASH = "_hash";
/**
- * The size of the file in bytes
+ * The size of the media item.
*/
+ @BytesLong
@Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String SIZE = "_size";
/**
- * The display name of the file
+ * The display name of the media item.
*/
@Column(Cursor.FIELD_TYPE_STRING)
public static final String DISPLAY_NAME = "_display_name";
/**
- * The title of the content
+ * The title of the media item.
*/
@Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
public static final String TITLE = "title";
/**
- * The time the file was added to the media provider
- * Units are seconds since 1970.
+ * The time the media item was first added.
*/
+ @CurrentTimeSecondsLong
@Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String DATE_ADDED = "date_added";
/**
- * The time the file was last modified
- * Units are seconds since 1970.
- * NOTE: This is for internal use by the media scanner. Do not modify this field.
+ * The time the media item was last modified.
*/
+ @CurrentTimeSecondsLong
@Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String DATE_MODIFIED = "date_modified";
@@ -986,23 +997,25 @@
public static final String IS_TRASHED = "is_trashed";
/**
- * The time the file should be considered expired. Units are seconds
- * since 1970. Typically only meaningful in the context of
- * {@link #IS_PENDING} or {@link #IS_TRASHED}.
+ * The time the media item should be considered expired. Typically only
+ * meaningful in the context of {@link #IS_PENDING} or
+ * {@link #IS_TRASHED}.
+ *
* @removed
*/
@Deprecated
+ @CurrentTimeSecondsLong
@Column(Cursor.FIELD_TYPE_INTEGER)
public static final String DATE_EXPIRES = "date_expires";
/**
- * The width of the image/video in pixels.
+ * The width of the media item, in pixels.
*/
@Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String WIDTH = "width";
/**
- * The height of the image/video in pixels.
+ * The height of the media item, in pixels.
*/
@Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String HEIGHT = "height";
@@ -1151,8 +1164,7 @@
}
/**
- * Fields for master table for all media files.
- * Table also contains MediaColumns._ID, DATA, SIZE and DATE_MODIFIED.
+ * File metadata columns.
*/
public interface FileColumns extends MediaColumns {
/**
@@ -1179,15 +1191,26 @@
public static final String PARENT = "parent";
/**
- * The MIME type of the file
- * <P>Type: TEXT</P>
+ * The MIME type of the media item.
+ * <p>
+ * This is typically defined based on the file extension of the media
+ * item. However, it may be the value of the {@code format} attribute
+ * defined by the <em>Dublin Core Media Initiative</em> standard,
+ * extracted from any XMP metadata contained within this media item.
+ * <p class="note">
+ * Note: the {@code format} attribute may be ignored if the top-level
+ * MIME type disagrees with the file extension. For example, it's
+ * reasonable for an {@code image/jpeg} file to declare a {@code format}
+ * of {@code image/vnd.google.panorama360+jpg}, but declaring a
+ * {@code format} of {@code audio/ogg} would be ignored.
+ * <p>
+ * This is a read-only column that is automatically computed.
*/
@Column(Cursor.FIELD_TYPE_STRING)
public static final String MIME_TYPE = "mime_type";
/**
- * The title of the content
- * <P>Type: TEXT</P>
+ * The title of the media item.
*/
@Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
public static final String TITLE = "title";
@@ -1245,10 +1268,12 @@
public static final Point MICRO_SIZE = new Point(96, 96);
}
- /** Column fields for downloaded files used in {@link Downloads} table */
+ /**
+ * Download metadata columns.
+ */
public interface DownloadColumns extends MediaColumns {
/**
- * Uri indicating where the file has been downloaded from.
+ * Uri indicating where the item has been downloaded from.
*/
@Column(Cursor.FIELD_TYPE_STRING)
String DOWNLOAD_URI = "download_uri";
@@ -1422,9 +1447,12 @@
}
/**
- * Contains meta data for all available images.
+ * Collection of all media with MIME type of {@code image/*}.
*/
public static final class Images {
+ /**
+ * Image metadata columns.
+ */
public interface ImageColumns extends MediaColumns {
/**
* The description of the image
@@ -1473,9 +1501,9 @@
public static final String LONGITUDE = "longitude";
/**
- * The date & time that the image was taken in units
- * of milliseconds since jan 1, 1970.
+ * The time the media item was taken.
*/
+ @CurrentTimeMillisLong
@Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String DATE_TAKEN = "datetaken";
@@ -1531,16 +1559,34 @@
}
public static final class Media implements ImageColumns {
+ /**
+ * @deprecated all queries should be performed through
+ * {@link ContentResolver} directly, which offers modern
+ * features like {@link CancellationSignal}.
+ */
+ @Deprecated
public static final Cursor query(ContentResolver cr, Uri uri, String[] projection) {
return cr.query(uri, projection, null, null, DEFAULT_SORT_ORDER);
}
+ /**
+ * @deprecated all queries should be performed through
+ * {@link ContentResolver} directly, which offers modern
+ * features like {@link CancellationSignal}.
+ */
+ @Deprecated
public static final Cursor query(ContentResolver cr, Uri uri, String[] projection,
String where, String orderBy) {
return cr.query(uri, projection, where,
null, orderBy == null ? DEFAULT_SORT_ORDER : orderBy);
}
+ /**
+ * @deprecated all queries should be performed through
+ * {@link ContentResolver} directly, which offers modern
+ * features like {@link CancellationSignal}.
+ */
+ @Deprecated
public static final Cursor query(ContentResolver cr, Uri uri, String[] projection,
String selection, String [] selectionArgs, String orderBy) {
return cr.query(uri, projection, selection,
@@ -1552,9 +1598,12 @@
*
* @param cr The content resolver to use
* @param url The url of the image
- * @throws FileNotFoundException
- * @throws IOException
+ * @deprecated loading of images should be performed through
+ * {@link ImageDecoder#createSource(ContentResolver, Uri)},
+ * which offers modern features like
+ * {@link PostProcessor}.
*/
+ @Deprecated
public static final Bitmap getBitmap(ContentResolver cr, Uri url)
throws FileNotFoundException, IOException {
InputStream input = cr.openInputStream(url);
@@ -1571,8 +1620,11 @@
* @param name The name of the image
* @param description The description of the image
* @return The URL to the newly created image
- * @throws FileNotFoundException
+ * @deprecated inserting of images should be performed through
+ * {@link MediaStore#createPending(Context, PendingParams)},
+ * which offers richer control over lifecycle.
*/
+ @Deprecated
public static final String insertImage(ContentResolver cr, String imagePath,
String name, String description) throws FileNotFoundException {
// Check if file exists with a FileInputStream
@@ -1599,7 +1651,11 @@
* @param description The description of the image
* @return The URL to the newly created image, or <code>null</code> if the image failed to be stored
* for any reason.
+ * @deprecated inserting of images should be performed through
+ * {@link MediaStore#createPending(Context, PendingParams)},
+ * which offers richer control over lifecycle.
*/
+ @Deprecated
public static final String insertImage(ContentResolver cr, Bitmap source,
String title, String description) {
ContentValues values = new ContentValues();
@@ -1694,15 +1750,33 @@
*/
@Deprecated
public static class Thumbnails implements BaseColumns {
+ /**
+ * @deprecated all queries should be performed through
+ * {@link ContentResolver} directly, which offers modern
+ * features like {@link CancellationSignal}.
+ */
+ @Deprecated
public static final Cursor query(ContentResolver cr, Uri uri, String[] projection) {
return cr.query(uri, projection, null, null, DEFAULT_SORT_ORDER);
}
+ /**
+ * @deprecated all queries should be performed through
+ * {@link ContentResolver} directly, which offers modern
+ * features like {@link CancellationSignal}.
+ */
+ @Deprecated
public static final Cursor queryMiniThumbnails(ContentResolver cr, Uri uri, int kind,
String[] projection) {
return cr.query(uri, projection, "kind = " + kind, null, DEFAULT_SORT_ORDER);
}
+ /**
+ * @deprecated all queries should be performed through
+ * {@link ContentResolver} directly, which offers modern
+ * features like {@link CancellationSignal}.
+ */
+ @Deprecated
public static final Cursor queryMiniThumbnail(ContentResolver cr, long origId, int kind,
String[] projection) {
return cr.query(EXTERNAL_CONTENT_URI, projection,
@@ -1885,11 +1959,11 @@
}
/**
- * Container for all audio content.
+ * Collection of all media with MIME type of {@code audio/*}.
*/
public static final class Audio {
/**
- * Columns for audio file that show up in multiple tables.
+ * Audio metadata columns.
*/
public interface AudioColumns extends MediaColumns {
@@ -1901,15 +1975,17 @@
public static final String TITLE_KEY = "title_key";
/**
- * The duration of the audio file, in ms
+ * The duration of the audio item.
*/
+ @DurationMillisLong
@Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String DURATION = "duration";
/**
- * The position, in ms, playback was at when playback for this file
- * was last stopped.
+ * The position within the audio item at which playback should be
+ * resumed.
*/
+ @DurationMillisLong
@Column(Cursor.FIELD_TYPE_INTEGER)
public static final String BOOKMARK = "bookmark";
@@ -2187,7 +2263,7 @@
}
/**
- * Columns representing an audio genre
+ * Audio genre metadata columns.
*/
public interface GenresColumns {
/**
@@ -2290,7 +2366,7 @@
}
/**
- * Columns representing a playlist
+ * Audio playlist metadata columns.
*/
public interface PlaylistsColumns {
/**
@@ -2321,17 +2397,16 @@
public static final String DATA = "_data";
/**
- * The time the file was added to the media provider
- * Units are seconds since 1970.
+ * The time the media item was first added.
*/
+ @CurrentTimeSecondsLong
@Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String DATE_ADDED = "date_added";
/**
- * The time the file was last modified
- * Units are seconds since 1970.
- * NOTE: This is for internal use by the media scanner. Do not modify this field.
+ * The time the media item was last modified.
*/
+ @CurrentTimeSecondsLong
@Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String DATE_MODIFIED = "date_modified";
}
@@ -2450,7 +2525,7 @@
}
/**
- * Columns representing an artist
+ * Audio artist metadata columns.
*/
public interface ArtistColumns {
/**
@@ -2537,7 +2612,7 @@
}
/**
- * Columns representing an album
+ * Audio album metadata columns.
*/
public interface AlbumColumns {
@@ -2707,6 +2782,9 @@
}
}
+ /**
+ * Collection of all media with MIME type of {@code video/*}.
+ */
public static final class Video {
/**
@@ -2714,15 +2792,25 @@
*/
public static final String DEFAULT_SORT_ORDER = MediaColumns.DISPLAY_NAME;
+ /**
+ * @deprecated all queries should be performed through
+ * {@link ContentResolver} directly, which offers modern
+ * features like {@link CancellationSignal}.
+ */
+ @Deprecated
public static final Cursor query(ContentResolver cr, Uri uri, String[] projection) {
return cr.query(uri, projection, null, null, DEFAULT_SORT_ORDER);
}
+ /**
+ * Video metadata columns.
+ */
public interface VideoColumns extends MediaColumns {
/**
- * The duration of the video file, in ms
+ * The duration of the video item.
*/
+ @DurationMillisLong
@Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String DURATION = "duration";
@@ -2799,9 +2887,9 @@
public static final String LONGITUDE = "longitude";
/**
- * The date & time that the video was taken in units
- * of milliseconds since jan 1, 1970.
+ * The time the media item was taken.
*/
+ @CurrentTimeMillisLong
@Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String DATE_TAKEN = "datetaken";
@@ -2849,11 +2937,10 @@
public static final String GROUP_ID = "group_id";
/**
- * The bookmark for the video. Time in ms. Represents the location in the video that the
- * video should start playing at the next time it is opened. If the value is null or
- * out of the range 0..DURATION-1 then the video should start playing from the
- * beginning.
+ * The position within the video item at which playback should be
+ * resumed.
*/
+ @DurationMillisLong
@Column(Cursor.FIELD_TYPE_INTEGER)
public static final String BOOKMARK = "bookmark";
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index d925d7e..5d298bf 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -12393,6 +12393,14 @@
public static final String GAME_DRIVER_WHITELIST = "game_driver_whitelist";
/**
+ * List of libraries in sphal accessible by Game Driver
+ * The string is a list of library names, separated by colon.
+ * i.e. <lib1>:<lib2>:...:<libN>
+ * @hide
+ */
+ public static final String GAME_DRIVER_SPHAL_LIBRARIES = "game_driver_sphal_libraries";
+
+ /**
* Ordered GPU debug layer list for Vulkan
* i.e. <layer1>:<layer2>:...:<layerN>
* @hide
diff --git a/core/java/android/widget/SearchView.java b/core/java/android/widget/SearchView.java
index 630c38a..172f1d8 100644
--- a/core/java/android/widget/SearchView.java
+++ b/core/java/android/widget/SearchView.java
@@ -2078,6 +2078,11 @@
return ic;
}
+ @Override
+ public boolean checkInputConnectionProxy(View view) {
+ return view == mSearchView;
+ }
+
private void showSoftInputIfNecessary() {
if (mHasPendingShowSoftInputRequest) {
final InputMethodManager imm =
diff --git a/core/java/com/android/internal/colorextraction/ColorExtractor.java b/core/java/com/android/internal/colorextraction/ColorExtractor.java
index 258d081..d9fd3b5 100644
--- a/core/java/com/android/internal/colorextraction/ColorExtractor.java
+++ b/core/java/com/android/internal/colorextraction/ColorExtractor.java
@@ -21,7 +21,7 @@
import android.app.WallpaperColors;
import android.app.WallpaperManager;
import android.content.Context;
-import android.os.Trace;
+import android.os.AsyncTask;
import android.util.Log;
import android.util.SparseArray;
@@ -53,11 +53,11 @@
protected WallpaperColors mLockColors;
public ColorExtractor(Context context) {
- this(context, new Tonal(context));
+ this(context, new Tonal(context), true /* immediately */);
}
@VisibleForTesting
- public ColorExtractor(Context context, ExtractionType extractionType) {
+ public ColorExtractor(Context context, ExtractionType extractionType, boolean immediately) {
mContext = context;
mExtractionType = extractionType;
@@ -71,23 +71,48 @@
}
mOnColorsChangedListeners = new ArrayList<>();
- GradientColors[] systemColors = mGradientColors.get(WallpaperManager.FLAG_SYSTEM);
- GradientColors[] lockColors = mGradientColors.get(WallpaperManager.FLAG_LOCK);
WallpaperManager wallpaperManager = mContext.getSystemService(WallpaperManager.class);
if (wallpaperManager == null) {
Log.w(TAG, "Can't listen to color changes!");
} else {
wallpaperManager.addOnColorsChangedListener(this, null /* handler */);
+ initExtractColors(wallpaperManager, immediately);
+ }
+ }
- // Initialize all gradients with the current colors
- Trace.beginSection("ColorExtractor#getWallpaperColors");
+ private void initExtractColors(WallpaperManager wallpaperManager, boolean immediately) {
+ if (immediately) {
mSystemColors = wallpaperManager.getWallpaperColors(WallpaperManager.FLAG_SYSTEM);
mLockColors = wallpaperManager.getWallpaperColors(WallpaperManager.FLAG_LOCK);
- Trace.endSection();
+ extractWallpaperColors();
+ } else {
+ new LoadWallpaperColors().executeOnExecutor(
+ AsyncTask.THREAD_POOL_EXECUTOR, wallpaperManager);
}
+ }
- // Initialize all gradients with the current colors
+ private class LoadWallpaperColors extends AsyncTask<WallpaperManager, Void, Void> {
+ private WallpaperColors mSystemColors;
+ private WallpaperColors mLockColors;
+ @Override
+ protected Void doInBackground(WallpaperManager... params) {
+ mSystemColors = params[0].getWallpaperColors(WallpaperManager.FLAG_SYSTEM);
+ mLockColors = params[0].getWallpaperColors(WallpaperManager.FLAG_LOCK);
+ return null;
+ }
+ @Override
+ protected void onPostExecute(Void b) {
+ ColorExtractor.this.mSystemColors = mSystemColors;
+ ColorExtractor.this.mLockColors = mLockColors;
+ extractWallpaperColors();
+ triggerColorsChanged(WallpaperManager.FLAG_SYSTEM | WallpaperManager.FLAG_LOCK);
+ }
+ }
+
+ private void extractWallpaperColors() {
+ GradientColors[] systemColors = mGradientColors.get(WallpaperManager.FLAG_SYSTEM);
+ GradientColors[] lockColors = mGradientColors.get(WallpaperManager.FLAG_LOCK);
extractInto(mSystemColors,
systemColors[TYPE_NORMAL],
systemColors[TYPE_DARK],
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index 40d7868..22884ac 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -29,6 +29,7 @@
import android.os.Process;
import android.os.SystemProperties;
import android.os.Trace;
+import android.provider.DeviceConfig;
import android.system.ErrnoException;
import android.system.Os;
import android.util.Log;
@@ -129,21 +130,6 @@
public static final int BLASTULA_MANAGEMENT_MESSAGE_BYTES = 8;
/**
- * If the blastula pool should be created and used to start applications.
- *
- * Setting this value to false will disable the creation, maintenance, and use of the blastula
- * pool. When the blastula pool is disabled the application lifecycle will be identical to
- * previous versions of Android.
- */
- public static final boolean BLASTULA_POOL_ENABLED = false;
-
- /**
- * File descriptor used for communication between the signal handler and the ZygoteServer poll
- * loop.
- * */
- protected static FileDescriptor sBlastulaPoolEventFD;
-
- /**
* An extraArg passed when a zygote process is forking a child-zygote, specifying a name
* in the abstract socket namespace. This socket name is what the new child zygote
* should listen for connections on.
@@ -174,44 +160,40 @@
private static final String ANDROID_SOCKET_PREFIX = "ANDROID_SOCKET_";
/**
- * The maximum value that the sBlastulaPoolMax variable may take. This value
- * is a mirror of BLASTULA_POOL_MAX_LIMIT found in com_android_internal_os_Zygote.cpp.
+ * The duration to wait before re-checking Zygote related system properties.
+ *
+ * Five minutes in milliseconds.
*/
- static final int BLASTULA_POOL_MAX_LIMIT = 10;
-
- /**
- * The minimum value that the sBlastulaPoolMin variable may take.
- */
- static final int BLASTULA_POOL_MIN_LIMIT = 1;
-
- /**
- * The runtime-adjustable maximum Blastula pool size.
- */
- static int sBlastulaPoolMax = BLASTULA_POOL_MAX_LIMIT;
-
- /**
- * The runtime-adjustable minimum Blastula pool size.
- */
- static int sBlastulaPoolMin = BLASTULA_POOL_MIN_LIMIT;
-
- /**
- * The runtime-adjustable value used to determine when to re-fill the
- * blastula pool. The pool will be re-filled when
- * (sBlastulaPoolMax - gBlastulaPoolCount) >= sBlastulaPoolRefillThreshold.
- */
- // TODO (chriswailes): This must be updated at the same time as sBlastulaPoolMax.
- static int sBlastulaPoolRefillThreshold = (sBlastulaPoolMax / 2);
+ public static final long PROPERTY_CHECK_INTERVAL = 300000;
/**
* @hide for internal use only
*/
public static final int SOCKET_BUFFER_SIZE = 256;
- private static LocalServerSocket sBlastulaPoolSocket = null;
-
/** a prototype instance for a future List.toArray() */
protected static final int[][] INT_ARRAY_2D = new int[0][0];
+ /**
+ * @hide for internal use only.
+ */
+ public static final String PRIMARY_SOCKET_NAME = "zygote";
+
+ /**
+ * @hide for internal use only.
+ */
+ public static final String SECONDARY_SOCKET_NAME = "zygote_secondary";
+
+ /**
+ * @hide for internal use only
+ */
+ public static final String BLASTULA_POOL_PRIMARY_SOCKET_NAME = "blastula_pool";
+
+ /**
+ * @hide for internal use only
+ */
+ public static final String BLASTULA_POOL_SECONDARY_SOCKET_NAME = "blastula_pool_secondary";
+
private Zygote() {}
/** Called for some security initialization before any fork. */
@@ -428,70 +410,47 @@
protected static native void nativeGetSocketFDs(boolean isPrimary);
/**
- * Initialize the blastula pool and fill it with the desired number of
- * processes.
+ * Returns the raw string value of a system property.
+ *
+ * Note that Device Config is not available without an application so SystemProperties is used
+ * instead.
+ *
+ * TODO (chriswailes): Cache the system property location in native code and then write a JNI
+ * function to fetch it.
*/
- protected static Runnable initBlastulaPool() {
- if (BLASTULA_POOL_ENABLED) {
- sBlastulaPoolEventFD = getBlastulaPoolEventFD();
-
- return fillBlastulaPool(null);
- } else {
- return null;
- }
+ public static String getSystemProperty(String propertyName, String defaultValue) {
+ return SystemProperties.get(
+ String.join(".",
+ "persist.device_config",
+ DeviceConfig.RuntimeNative.NAMESPACE,
+ propertyName),
+ defaultValue);
}
/**
- * Checks to see if the current policy says that pool should be refilled, and spawns new
- * blastulas if necessary.
+ * Returns the value of a system property converted to a boolean using specific logic.
*
- * NOTE: This function doesn't need to be guarded with BLASTULA_POOL_ENABLED because it is
- * only called from contexts that are only valid if the pool is enabled.
+ * Note that Device Config is not available without an application so SystemProperties is used
+ * instead.
*
- * @param sessionSocketRawFDs Anonymous session sockets that are currently open
- * @return In the Zygote process this function will always return null; in blastula processes
- * this function will return a Runnable object representing the new application that is
- * passed up from blastulaMain.
+ * @see SystemProperties.getBoolean
+ *
+ * TODO (chriswailes): Cache the system property location in native code and then write a JNI
+ * function to fetch it.
*/
- protected static Runnable fillBlastulaPool(int[] sessionSocketRawFDs) {
- Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Zygote:FillBlastulaPool");
-
- int blastulaPoolCount = getBlastulaPoolCount();
-
- int numBlastulasToSpawn = sBlastulaPoolMax - blastulaPoolCount;
-
- if (blastulaPoolCount < sBlastulaPoolMin
- || numBlastulasToSpawn >= sBlastulaPoolRefillThreshold) {
-
- // Disable some VM functionality and reset some system values
- // before forking.
- ZygoteHooks.preFork();
- resetNicePriority();
-
- while (blastulaPoolCount++ < sBlastulaPoolMax) {
- Runnable caller = forkBlastula(sessionSocketRawFDs);
-
- if (caller != null) {
- return caller;
- }
- }
-
- // Re-enable runtime services for the Zygote. Blastula services
- // are re-enabled in specializeBlastula.
- ZygoteHooks.postForkCommon();
-
- Log.i("zygote", "Filled the blastula pool. New blastulas: " + numBlastulasToSpawn);
- }
-
- Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
-
- return null;
+ public static boolean getSystemPropertyBoolean(String propertyName, Boolean defaultValue) {
+ return SystemProperties.getBoolean(
+ String.join(".",
+ "persist.device_config",
+ DeviceConfig.RuntimeNative.NAMESPACE,
+ propertyName),
+ defaultValue);
}
/**
* @return Number of blastulas currently in the pool
*/
- private static int getBlastulaPoolCount() {
+ static int getBlastulaPoolCount() {
return nativeGetBlastulaPoolCount();
}
@@ -501,7 +460,7 @@
* @return The event FD used for communication between the signal handler and the ZygoteServer
* poll loop
*/
- private static FileDescriptor getBlastulaPoolEventFD() {
+ static FileDescriptor getBlastulaPoolEventFD() {
FileDescriptor fd = new FileDescriptor();
fd.setInt$(nativeGetBlastulaPoolEventFD());
@@ -518,7 +477,8 @@
* this function will return a Runnable object representing the new application that is
* passed up from blastulaMain.
*/
- private static Runnable forkBlastula(int[] sessionSocketRawFDs) {
+ static Runnable forkBlastula(LocalServerSocket blastulaPoolSocket,
+ int[] sessionSocketRawFDs) {
FileDescriptor[] pipeFDs = null;
try {
@@ -532,7 +492,7 @@
if (pid == 0) {
IoUtils.closeQuietly(pipeFDs[0]);
- return blastulaMain(pipeFDs[1]);
+ return blastulaMain(blastulaPoolSocket, pipeFDs[1]);
} else {
// The read-end of the pipe will be closed by the native code.
// See removeBlastulaTableEntry();
@@ -553,7 +513,8 @@
* of the ZygoteServer.
* @return A runnable oject representing the new application.
*/
- static Runnable blastulaMain(FileDescriptor writePipe) {
+ private static Runnable blastulaMain(LocalServerSocket blastulaPoolSocket,
+ FileDescriptor writePipe) {
final int pid = Process.myPid();
LocalSocket sessionSocket = null;
@@ -563,7 +524,7 @@
while (true) {
try {
- sessionSocket = sBlastulaPoolSocket.accept();
+ sessionSocket = blastulaPoolSocket.accept();
BufferedReader blastulaReader =
new BufferedReader(new InputStreamReader(sessionSocket.getInputStream()));
@@ -611,7 +572,7 @@
System.exit(-1);
} finally {
IoUtils.closeQuietly(sessionSocket);
- IoUtils.closeQuietly(sBlastulaPoolSocket);
+ IoUtils.closeQuietly(blastulaPoolSocket);
}
try {
@@ -660,7 +621,7 @@
* exception if an invalid arugment is encountered.
* @param args The arguments to test
*/
- static void validateBlastulaCommand(ZygoteArguments args) {
+ private static void validateBlastulaCommand(ZygoteArguments args) {
if (args.mAbiListQuery) {
throw new IllegalArgumentException(BLASTULA_ERROR_PREFIX + "--query-abi-list");
} else if (args.mPidQuery) {
@@ -851,20 +812,6 @@
}
/**
- * Creates a managed object representing the Blastula pool socket that has
- * already been initialized and bound by init.
- *
- * TODO (chriswailes): Move the name selection logic into this function.
- *
- * @throws RuntimeException when open fails
- */
- static void createBlastulaSocket(String socketName) {
- if (BLASTULA_POOL_ENABLED && sBlastulaPoolSocket == null) {
- sBlastulaPoolSocket = createManagedSocketFromInitSocket(socketName);
- }
- }
-
- /**
* Creates a managed LocalServerSocket object using a file descriptor
* created by an init.rc script. The init scripts that specify the
* sockets name can be found in system/core/rootdir. The socket is bound
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index e132abd..7cddf75 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -755,7 +755,7 @@
}
public static void main(String argv[]) {
- ZygoteServer zygoteServer = new ZygoteServer();
+ ZygoteServer zygoteServer = null;
// Mark zygote start. This ensures that thread creation will throw
// an error.
@@ -783,7 +783,7 @@
RuntimeInit.enableDdms();
boolean startSystemServer = false;
- String socketName = "zygote";
+ String zygoteSocketName = "zygote";
String abiList = null;
boolean enableLazyPreload = false;
for (int i = 1; i < argv.length; i++) {
@@ -794,26 +794,19 @@
} else if (argv[i].startsWith(ABI_LIST_ARG)) {
abiList = argv[i].substring(ABI_LIST_ARG.length());
} else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
- socketName = argv[i].substring(SOCKET_NAME_ARG.length());
+ zygoteSocketName = argv[i].substring(SOCKET_NAME_ARG.length());
} else {
throw new RuntimeException("Unknown command line argument: " + argv[i]);
}
}
+ final boolean isPrimaryZygote = zygoteSocketName.equals(Zygote.PRIMARY_SOCKET_NAME);
+
if (abiList == null) {
throw new RuntimeException("No ABI list supplied.");
}
- // TODO (chriswailes): Wrap these three calls in a helper function?
- final String blastulaSocketName =
- socketName.equals(ZygoteProcess.ZYGOTE_SOCKET_NAME)
- ? ZygoteProcess.BLASTULA_POOL_SOCKET_NAME
- : ZygoteProcess.BLASTULA_POOL_SECONDARY_SOCKET_NAME;
-
- zygoteServer.createZygoteSocket(socketName);
- Zygote.createBlastulaSocket(blastulaSocketName);
-
- Zygote.getSocketFDs(socketName.equals(ZygoteProcess.ZYGOTE_SOCKET_NAME));
+ Zygote.getSocketFDs(isPrimaryZygote);
// In some configurations, we avoid preloading resources and classes eagerly.
// In such cases, we will preload things prior to our first fork.
@@ -846,8 +839,10 @@
ZygoteHooks.stopZygoteNoThreadCreation();
+ zygoteServer = new ZygoteServer(isPrimaryZygote);
+
if (startSystemServer) {
- Runnable r = forkSystemServer(abiList, socketName, zygoteServer);
+ Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);
// {@code r == null} in the parent (zygote) process, and {@code r != null} in the
// child (system_server) process.
@@ -857,23 +852,18 @@
}
}
- // If the return value is null then this is the zygote process
- // returning to the normal control flow. If it returns a Runnable
- // object then this is a blastula that has finished specializing.
- caller = Zygote.initBlastulaPool();
+ Log.i(TAG, "Accepting command socket connections");
- if (caller == null) {
- Log.i(TAG, "Accepting command socket connections");
-
- // The select loop returns early in the child process after a fork and
- // loops forever in the zygote.
- caller = zygoteServer.runSelectLoop(abiList);
- }
+ // The select loop returns early in the child process after a fork and
+ // loops forever in the zygote.
+ caller = zygoteServer.runSelectLoop(abiList);
} catch (Throwable ex) {
Log.e(TAG, "System zygote died with exception", ex);
throw ex;
} finally {
- zygoteServer.closeServerSocket();
+ if (zygoteServer != null) {
+ zygoteServer.closeServerSocket();
+ }
}
// We're in the child process and have exited the select loop. Proceed to execute the
@@ -894,8 +884,8 @@
}
private static void waitForSecondaryZygote(String socketName) {
- String otherZygoteName = ZygoteProcess.ZYGOTE_SOCKET_NAME.equals(socketName)
- ? ZygoteProcess.ZYGOTE_SECONDARY_SOCKET_NAME : ZygoteProcess.ZYGOTE_SOCKET_NAME;
+ String otherZygoteName = Zygote.PRIMARY_SOCKET_NAME.equals(socketName)
+ ? Zygote.SECONDARY_SOCKET_NAME : Zygote.PRIMARY_SOCKET_NAME;
ZygoteProcess.waitForConnectionToZygote(otherZygoteName);
}
diff --git a/core/java/com/android/internal/os/ZygoteServer.java b/core/java/com/android/internal/os/ZygoteServer.java
index a78c095..24269ef 100644
--- a/core/java/com/android/internal/os/ZygoteServer.java
+++ b/core/java/com/android/internal/os/ZygoteServer.java
@@ -20,12 +20,17 @@
import android.net.LocalServerSocket;
import android.net.LocalSocket;
+import android.os.SystemClock;
+import android.os.Trace;
+import android.provider.DeviceConfig;
import android.system.ErrnoException;
import android.system.Os;
import android.system.StructPollfd;
import android.util.Log;
import android.util.Slog;
+import dalvik.system.ZygoteHooks;
+
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.FileDescriptor;
@@ -38,7 +43,7 @@
* Provides functions to wait for commands on a UNIX domain socket, and fork
* off child processes that inherit the initial state of the VM.%
*
- * Please see {@link ZygoteConnection.Arguments} for documentation on the
+ * Please see {@link ZygoteArguments} for documentation on the
* client protocol.
*/
class ZygoteServer {
@@ -46,11 +51,48 @@
public static final String TAG = "ZygoteServer";
/**
+ * The maximim value that will be accepted from the BLASTULA_POOL_SIZE_MAX device property.
+ * is a mirror of BLASTULA_POOL_MAX_LIMIT found in com_android_internal_os_Zygote.cpp.
+ */
+ private static final int BLASTULA_POOL_SIZE_MAX_LIMIT = 100;
+
+ /**
+ * The minimum value that will be accepted from the BLASTULA_POOL_SIZE_MIN device property.
+ */
+ private static final int BLASTULA_POOL_SIZE_MIN_LIMIT = 1;
+
+ /** The default value used for the BLASTULA_POOL_SIZE_MAX device property */
+ private static final String BLASTULA_POOL_SIZE_MAX_DEFAULT = "10";
+
+ /** The default value used for the BLASTULA_POOL_SIZE_MIN device property */
+ private static final String BLASTULA_POOL_SIZE_MIN_DEFAULT = "1";
+
+ /**
+ * If the blastula pool should be created and used to start applications.
+ *
+ * Setting this value to false will disable the creation, maintenance, and use of the blastula
+ * pool. When the blastula pool is disabled the application lifecycle will be identical to
+ * previous versions of Android.
+ */
+ private boolean mBlastulaPoolEnabled = false;
+
+ /**
* Listening socket that accepts new server connections.
*/
private LocalServerSocket mZygoteSocket;
/**
+ * The name of the blastula socket to use if the blastula pool is enabled.
+ */
+ private LocalServerSocket mBlastulaPoolSocket;
+
+ /**
+ * File descriptor used for communication between the signal handler and the ZygoteServer poll
+ * loop.
+ * */
+ private FileDescriptor mBlastulaPoolEventFD;
+
+ /**
* Whether or not mZygoteSocket's underlying FD should be closed directly.
* If mZygoteSocket is created with an existing FD, closing the socket does
* not close the FD and it must be closed explicitly. If the socket is created
@@ -64,25 +106,55 @@
*/
private boolean mIsForkChild;
- ZygoteServer() { }
+ /**
+ * The runtime-adjustable maximum Blastula pool size.
+ */
+ private int mBlastulaPoolSizeMax = 0;
- void setForkChild() {
- mIsForkChild = true;
+ /**
+ * The runtime-adjustable minimum Blastula pool size.
+ */
+ private int mBlastulaPoolSizeMin = 0;
+
+ /**
+ * The runtime-adjustable value used to determine when to re-fill the
+ * blastula pool. The pool will be re-filled when
+ * (sBlastulaPoolMax - gBlastulaPoolCount) >= sBlastulaPoolRefillThreshold.
+ */
+ private int mBlastulaPoolRefillThreshold = 0;
+
+ ZygoteServer() {
+ mBlastulaPoolEventFD = null;
+ mZygoteSocket = null;
+ mBlastulaPoolSocket = null;
}
/**
- * Creates a managed object representing the Zygote socket that has already
- * been initialized and bound by init.
+ * Initialize the Zygote server with the Zygote server socket, blastula pool server socket,
+ * and blastula pool event FD.
*
- * TODO (chriswailes): Move the name selection logic into this function.
- *
- * @throws RuntimeException when open fails
+ * @param isPrimaryZygote If this is the primary Zygote or not.
*/
- void createZygoteSocket(String socketName) {
- if (mZygoteSocket == null) {
- mZygoteSocket = Zygote.createManagedSocketFromInitSocket(socketName);
- mCloseSocketFd = true;
+ ZygoteServer(boolean isPrimaryZygote) {
+ mBlastulaPoolEventFD = Zygote.getBlastulaPoolEventFD();
+
+ if (isPrimaryZygote) {
+ mZygoteSocket = Zygote.createManagedSocketFromInitSocket(Zygote.PRIMARY_SOCKET_NAME);
+ mBlastulaPoolSocket =
+ Zygote.createManagedSocketFromInitSocket(
+ Zygote.BLASTULA_POOL_PRIMARY_SOCKET_NAME);
+ } else {
+ mZygoteSocket = Zygote.createManagedSocketFromInitSocket(Zygote.SECONDARY_SOCKET_NAME);
+ mBlastulaPoolSocket =
+ Zygote.createManagedSocketFromInitSocket(
+ Zygote.BLASTULA_POOL_SECONDARY_SOCKET_NAME);
}
+
+ fetchBlastulaPoolPolicyProps();
+ }
+
+ void setForkChild() {
+ mIsForkChild = true;
}
/**
@@ -151,6 +223,104 @@
return mZygoteSocket.getFileDescriptor();
}
+ private void fetchBlastulaPoolPolicyProps() {
+ final String blastulaPoolSizeMaxPropString =
+ Zygote.getSystemProperty(
+ DeviceConfig.RuntimeNative.BLASTULA_POOL_SIZE_MAX,
+ BLASTULA_POOL_SIZE_MAX_DEFAULT);
+
+ if (!blastulaPoolSizeMaxPropString.isEmpty()) {
+ mBlastulaPoolSizeMax =
+ Integer.min(
+ Integer.parseInt(blastulaPoolSizeMaxPropString),
+ BLASTULA_POOL_SIZE_MAX_LIMIT);
+ }
+
+ final String blastulaPoolSizeMinPropString =
+ Zygote.getSystemProperty(
+ DeviceConfig.RuntimeNative.BLASTULA_POOL_SIZE_MIN,
+ BLASTULA_POOL_SIZE_MIN_DEFAULT);
+
+ if (!blastulaPoolSizeMinPropString.isEmpty()) {
+ mBlastulaPoolSizeMin =
+ Integer.max(
+ Integer.parseInt(blastulaPoolSizeMinPropString),
+ BLASTULA_POOL_SIZE_MIN_LIMIT);
+ }
+
+ final String blastulaPoolRefillThresholdPropString =
+ Zygote.getSystemProperty(
+ DeviceConfig.RuntimeNative.BLASTULA_POOL_REFILL_THRESHOLD,
+ Integer.toString(mBlastulaPoolSizeMax / 2));
+
+ if (!blastulaPoolRefillThresholdPropString.isEmpty()) {
+ mBlastulaPoolRefillThreshold =
+ Integer.min(
+ Integer.parseInt(blastulaPoolRefillThresholdPropString),
+ mBlastulaPoolSizeMax);
+ }
+
+ }
+
+ private long mLastPropCheckTimestamp = 0;
+
+ private void fetchBlastulaPoolPolicyPropsWithMinInterval() {
+ final long currentTimestamp = SystemClock.elapsedRealtime();
+
+ if (currentTimestamp - mLastPropCheckTimestamp >= Zygote.PROPERTY_CHECK_INTERVAL) {
+ fetchBlastulaPoolPolicyProps();
+ mLastPropCheckTimestamp = currentTimestamp;
+ }
+ }
+
+ /**
+ * Checks to see if the current policy says that pool should be refilled, and spawns new
+ * blastulas if necessary.
+ *
+ * @param sessionSocketRawFDs Anonymous session sockets that are currently open
+ * @return In the Zygote process this function will always return null; in blastula processes
+ * this function will return a Runnable object representing the new application that is
+ * passed up from blastulaMain.
+ */
+ private Runnable fillBlastulaPool(int[] sessionSocketRawFDs) {
+ Log.i(TAG, "FDHUNT - Marker 2 - fillBlastulaPool");
+
+ if (mBlastulaPoolEnabled) {
+ Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Zygote:FillBlastulaPool");
+
+ int blastulaPoolCount = Zygote.getBlastulaPoolCount();
+ int numBlastulasToSpawn = mBlastulaPoolSizeMax - blastulaPoolCount;
+
+ if (blastulaPoolCount < mBlastulaPoolSizeMin
+ || numBlastulasToSpawn >= mBlastulaPoolRefillThreshold) {
+
+ // Disable some VM functionality and reset some system values
+ // before forking.
+ ZygoteHooks.preFork();
+ Zygote.resetNicePriority();
+
+ while (blastulaPoolCount++ < mBlastulaPoolSizeMax) {
+ Runnable caller = Zygote.forkBlastula(mBlastulaPoolSocket, sessionSocketRawFDs);
+
+ if (caller != null) {
+ return caller;
+ }
+ }
+
+ // Re-enable runtime services for the Zygote. Blastula services
+ // are re-enabled in specializeBlastula.
+ ZygoteHooks.postForkCommon();
+
+ Log.i("zygote",
+ "Filled the blastula pool. New blastulas: " + numBlastulasToSpawn);
+ }
+
+ Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+ }
+
+ return null;
+ }
+
/**
* Runs the zygote process's select loop. Accepts new connections as
* they happen, and reads commands from connections one spawn-request's
@@ -164,6 +334,8 @@
peers.add(null);
while (true) {
+ fetchBlastulaPoolPolicyPropsWithMinInterval();
+
int[] blastulaPipeFDs = Zygote.getBlastulaPipeFDs();
// Space for all of the socket FDs, the Blastula Pool Event FD, and
@@ -181,7 +353,7 @@
final int blastulaPoolEventFDIndex = pollIndex;
pollFDs[pollIndex] = new StructPollfd();
- pollFDs[pollIndex].fd = Zygote.sBlastulaPoolEventFD;
+ pollFDs[pollIndex].fd = mBlastulaPoolEventFD;
pollFDs[pollIndex].events = (short) POLLIN;
++pollIndex;
@@ -275,6 +447,8 @@
} else {
// Either the blastula pool event FD or a blastula reporting pipe.
+ Log.i(TAG, "FDHUNT - Marker 1 - runSelectLoop");
+
// If this is the event FD the payload will be the number of blastulas removed.
// If this is a reporting pipe FD the payload will be the PID of the blastula
// that was just specialized.
@@ -316,7 +490,7 @@
.mapToInt(fd -> fd.getInt$())
.toArray();
- final Runnable command = Zygote.fillBlastulaPool(sessionSocketRawFDs);
+ final Runnable command = fillBlastulaPool(sessionSocketRawFDs);
if (command != null) {
return command;
diff --git a/core/java/com/android/internal/policy/DividerSnapAlgorithm.java b/core/java/com/android/internal/policy/DividerSnapAlgorithm.java
index a8ad810..c46f867 100644
--- a/core/java/com/android/internal/policy/DividerSnapAlgorithm.java
+++ b/core/java/com/android/internal/policy/DividerSnapAlgorithm.java
@@ -137,6 +137,7 @@
mDismissStartTarget = mTargets.get(0);
mDismissEndTarget = mTargets.get(mTargets.size() - 1);
mMiddleTarget = mTargets.get(mTargets.size() / 2);
+ mMiddleTarget.isMiddleTarget = true;
}
/**
@@ -438,6 +439,8 @@
public final int flag;
+ public boolean isMiddleTarget;
+
/**
* Multiplier used to calculate distance to snap position. The lower this value, the harder
* it's to snap on this target
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index d69d416..c45900c 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -667,6 +667,11 @@
char methodTraceFileSizeBuf[sizeof("-Xmethod-trace-file-size:") + PROPERTY_VALUE_MAX];
std::string fingerprintBuf;
char jdwpProviderBuf[sizeof("-XjdwpProvider:") - 1 + PROPERTY_VALUE_MAX];
+ char bootImageBuf[sizeof("-Ximage:") - 1 + PROPERTY_VALUE_MAX];
+
+ if (parseRuntimeOption("dalvik.vm.boot-image", bootImageBuf, "-Ximage:")) {
+ ALOGI("Boot image: '%s'\n", bootImageBuf);
+ }
bool checkJni = false;
property_get("dalvik.vm.checkjni", propBuf, "");
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 7b4e4ea..4649b52 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -1357,6 +1357,9 @@
SetSchedulerPolicy(fail_fn);
+ __android_log_close();
+ stats_log_close();
+
const char* se_info_ptr = se_info.has_value() ? se_info.value().c_str() : nullptr;
const char* nice_name_ptr = nice_name.has_value() ? nice_name.value().c_str() : nullptr;
diff --git a/core/proto/android/providers/settings/global.proto b/core/proto/android/providers/settings/global.proto
index c9957f3..cccb40d 100644
--- a/core/proto/android/providers/settings/global.proto
+++ b/core/proto/android/providers/settings/global.proto
@@ -453,6 +453,8 @@
optional SettingProto game_driver_blacklists = 14;
// ANGLE - Show a dialog box when ANGLE is selected for the currently running PKG
optional SettingProto show_angle_in_use_dialog = 15;
+ // Game Driver - List of libraries in sphal accessible by Game Driver
+ optional SettingProto game_driver_sphal_libraries = 16;
}
optional Gpu gpu = 59;
diff --git a/core/tests/coretests/src/android/net/UriTest.java b/core/tests/coretests/src/android/net/UriTest.java
index a33de7b..a71000b 100644
--- a/core/tests/coretests/src/android/net/UriTest.java
+++ b/core/tests/coretests/src/android/net/UriTest.java
@@ -182,8 +182,7 @@
uri = Uri.parse("http://bob%40lee%3ajr@local%68ost:4%32");
assertEquals("bob@lee:jr", uri.getUserInfo());
- assertEquals("localhost", uri.getHost());
- assertEquals(42, uri.getPort());
+ assertEquals("localhost:42", uri.getHost());
uri = Uri.parse("http://localhost");
assertEquals("localhost", uri.getHost());
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index c57b609..bb5e8df 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -494,6 +494,7 @@
Settings.Global.GAME_DRIVER_BLACKLISTS,
Settings.Global.GAME_DRIVER_BLACKLIST,
Settings.Global.GAME_DRIVER_WHITELIST,
+ Settings.Global.GAME_DRIVER_SPHAL_LIBRARIES,
Settings.Global.GLOBAL_SETTINGS_SHOW_ANGLE_IN_USE_DIALOG_BOX,
Settings.Global.GPU_DEBUG_LAYER_APP,
Settings.Global.ENABLE_GNSS_RAW_MEAS_FULL_TRACKING,
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index db4b131..81b304d 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -724,6 +724,9 @@
dumpSetting(s, p,
Settings.Global.GAME_DRIVER_BLACKLISTS,
GlobalSettingsProto.Gpu.GAME_DRIVER_BLACKLISTS);
+ dumpSetting(s, p,
+ Settings.Global.GAME_DRIVER_SPHAL_LIBRARIES,
+ GlobalSettingsProto.Gpu.GAME_DRIVER_SPHAL_LIBRARIES);
p.end(gpuToken);
final long hdmiToken = p.start(GlobalSettingsProto.HDMI);
diff --git a/packages/SystemUI/res/layout-land/global_actions_grid.xml b/packages/SystemUI/res/layout-land/global_actions_grid.xml
index 911b661..480f523 100644
--- a/packages/SystemUI/res/layout-land/global_actions_grid.xml
+++ b/packages/SystemUI/res/layout-land/global_actions_grid.xml
@@ -29,10 +29,10 @@
android:layoutDirection="ltr"
android:layout_marginTop="@dimen/global_actions_grid_side_margin"
android:translationZ="@dimen/global_actions_translate"
- android:paddingLeft="@dimen/global_actions_grid_top_padding"
- android:paddingRight="@dimen/global_actions_grid_bottom_padding"
- android:paddingTop="@dimen/global_actions_grid_left_padding"
- android:paddingBottom="@dimen/global_actions_grid_right_padding"
+ android:paddingLeft="@dimen/global_actions_grid_horizontal_padding"
+ android:paddingRight="@dimen/global_actions_grid_horizontal_padding"
+ android:paddingTop="@dimen/global_actions_grid_vertical_padding"
+ android:paddingBottom="@dimen/global_actions_grid_vertical_padding"
android:background="?android:attr/colorBackgroundFloating"
>
<LinearLayout
@@ -61,17 +61,18 @@
<!-- For separated items-->
<LinearLayout
android:id="@+id/separated_button"
- android:layout_width="wrap_content"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/global_actions_grid_side_margin"
android:layout_marginBottom="@dimen/global_actions_grid_side_margin"
- android:paddingTop="@dimen/global_actions_grid_left_padding"
- android:paddingLeft="@dimen/global_actions_grid_top_padding"
- android:paddingBottom="@dimen/global_actions_grid_right_padding"
- android:paddingRight="@dimen/global_actions_grid_bottom_padding"
+ android:paddingLeft="@dimen/global_actions_grid_horizontal_padding"
+ android:paddingRight="@dimen/global_actions_grid_horizontal_padding"
+ android:paddingTop="@dimen/global_actions_grid_vertical_padding"
+ android:paddingBottom="@dimen/global_actions_grid_vertical_padding"
android:orientation="horizontal"
android:layoutDirection="ltr"
android:background="?android:attr/colorBackgroundFloating"
+ android:gravity="center"
android:translationZ="@dimen/global_actions_translate"
/>
diff --git a/packages/SystemUI/res/layout-land/global_actions_grid_seascape.xml b/packages/SystemUI/res/layout-land/global_actions_grid_seascape.xml
index 669be1b..4f86826 100644
--- a/packages/SystemUI/res/layout-land/global_actions_grid_seascape.xml
+++ b/packages/SystemUI/res/layout-land/global_actions_grid_seascape.xml
@@ -23,17 +23,18 @@
<LinearLayout
android:id="@+id/separated_button"
android:layout_gravity="top|left"
- android:layout_width="wrap_content"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/global_actions_grid_side_margin"
android:layout_marginBottom="@dimen/global_actions_grid_side_margin"
- android:paddingTop="@dimen/global_actions_grid_left_padding"
- android:paddingLeft="@dimen/global_actions_grid_top_padding"
- android:paddingBottom="@dimen/global_actions_grid_right_padding"
- android:paddingRight="@dimen/global_actions_grid_bottom_padding"
+ android:paddingLeft="@dimen/global_actions_grid_horizontal_padding"
+ android:paddingRight="@dimen/global_actions_grid_horizontal_padding"
+ android:paddingTop="@dimen/global_actions_grid_vertical_padding"
+ android:paddingBottom="@dimen/global_actions_grid_vertical_padding"
android:orientation="horizontal"
android:layoutDirection="rtl"
android:background="?android:attr/colorBackgroundFloating"
+ android:gravity="center"
android:translationZ="@dimen/global_actions_translate"
/>
@@ -44,12 +45,12 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
- android:layout_marginTop="@dimen/global_actions_grid_side_margin"
+ android:layout_marginBottom="@dimen/global_actions_grid_side_margin"
android:translationZ="@dimen/global_actions_translate"
- android:paddingLeft="@dimen/global_actions_grid_top_padding"
- android:paddingRight="@dimen/global_actions_grid_bottom_padding"
- android:paddingTop="@dimen/global_actions_grid_left_padding"
- android:paddingBottom="@dimen/global_actions_grid_right_padding"
+ android:paddingLeft="@dimen/global_actions_grid_horizontal_padding"
+ android:paddingRight="@dimen/global_actions_grid_horizontal_padding"
+ android:paddingTop="@dimen/global_actions_grid_vertical_padding"
+ android:paddingBottom="@dimen/global_actions_grid_vertical_padding"
android:background="?android:attr/colorBackgroundFloating"
>
<LinearLayout
diff --git a/packages/SystemUI/res/layout/global_actions_grid.xml b/packages/SystemUI/res/layout/global_actions_grid.xml
index 1b56fa0..729e96e 100644
--- a/packages/SystemUI/res/layout/global_actions_grid.xml
+++ b/packages/SystemUI/res/layout/global_actions_grid.xml
@@ -23,15 +23,16 @@
<LinearLayout
android:id="@+id/separated_button"
android:layout_width="wrap_content"
- android:layout_height="wrap_content"
+ android:layout_height="match_parent"
android:layout_marginLeft="@dimen/global_actions_grid_side_margin"
android:layout_marginRight="@dimen/global_actions_grid_side_margin"
- android:paddingTop="@dimen/global_actions_grid_top_padding"
- android:paddingLeft="@dimen/global_actions_grid_left_padding"
- android:paddingBottom="@dimen/global_actions_grid_bottom_padding"
- android:paddingRight="@dimen/global_actions_grid_right_padding"
+ android:paddingLeft="@dimen/global_actions_grid_horizontal_padding"
+ android:paddingRight="@dimen/global_actions_grid_horizontal_padding"
+ android:paddingTop="@dimen/global_actions_grid_vertical_padding"
+ android:paddingBottom="@dimen/global_actions_grid_vertical_padding"
android:orientation="vertical"
android:background="?android:attr/colorBackgroundFloating"
+ android:gravity="center"
android:translationZ="@dimen/global_actions_translate"
/>
@@ -44,10 +45,10 @@
android:layoutDirection="rtl"
android:layout_marginRight="@dimen/global_actions_grid_side_margin"
android:translationZ="@dimen/global_actions_translate"
- android:paddingLeft="@dimen/global_actions_grid_left_padding"
- android:paddingRight="@dimen/global_actions_grid_right_padding"
- android:paddingTop="@dimen/global_actions_grid_top_padding"
- android:paddingBottom="@dimen/global_actions_grid_bottom_padding"
+ android:paddingLeft="@dimen/global_actions_grid_horizontal_padding"
+ android:paddingRight="@dimen/global_actions_grid_horizontal_padding"
+ android:paddingTop="@dimen/global_actions_grid_vertical_padding"
+ android:paddingBottom="@dimen/global_actions_grid_vertical_padding"
android:background="?android:attr/colorBackgroundFloating"
>
<LinearLayout
diff --git a/packages/SystemUI/res/layout/global_actions_grid_item.xml b/packages/SystemUI/res/layout/global_actions_grid_item.xml
index a893839..5dee09d 100644
--- a/packages/SystemUI/res/layout/global_actions_grid_item.xml
+++ b/packages/SystemUI/res/layout/global_actions_grid_item.xml
@@ -18,46 +18,43 @@
work around this for now with LinearLayouts. -->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="72dp"
- android:layout_height="72dp"
- android:gravity="center"
+ android:layout_width="@dimen/global_actions_grid_item_width"
+ android:layout_height="@dimen/global_actions_grid_item_height"
+ android:gravity="top|center_horizontal"
android:orientation="vertical"
android:layout_marginTop="@dimen/global_actions_grid_item_vertical_margin"
android:layout_marginBottom="@dimen/global_actions_grid_item_vertical_margin"
android:layout_marginLeft="@dimen/global_actions_grid_item_side_margin"
android:layout_marginRight="@dimen/global_actions_grid_item_side_margin"
- android:paddingEnd="4dip"
- android:paddingStart="4dip">
-
+>
<ImageView
android:id="@*android:id/icon"
- android:layout_width="24dp"
- android:layout_height="24dp"
- android:layout_gravity="center"
+ android:layout_width="@dimen/global_actions_grid_item_icon_width"
+ android:layout_height="@dimen/global_actions_grid_item_icon_height"
+ android:layout_marginTop="@dimen/global_actions_grid_item_icon_top_margin"
+ android:layout_marginBottom="@dimen/global_actions_grid_item_icon_bottom_margin"
+ android:layout_marginLeft="@dimen/global_actions_grid_item_icon_side_margin"
+ android:layout_marginRight="@dimen/global_actions_grid_item_icon_side_margin"
android:scaleType="center"
android:alpha="?android:attr/primaryContentAlpha"
/>
<TextView
android:id="@*android:id/message"
- android:layout_width="wrap_content"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_gravity="top|center_horizontal"
- android:paddingTop="10dp"
android:gravity="center"
- android:textSize="12sp"
+ android:textSize="12dp"
android:textAppearance="?android:attr/textAppearanceSmall"
- android:singleLine="true"
/>
<TextView
+ android:visibility="gone"
android:id="@*android:id/status"
- android:layout_width="wrap_content"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_gravity="top|center_horizontal"
android:gravity="center"
android:textColor="?android:attr/textColorTertiary"
android:textAppearance="?android:attr/textAppearanceSmall"
- android:singleLine="true"
/>
</LinearLayout>
diff --git a/packages/SystemUI/res/values-sw320dp-land/dimens.xml b/packages/SystemUI/res/values-sw320dp-land/dimens.xml
new file mode 100644
index 0000000..2ec5abd
--- /dev/null
+++ b/packages/SystemUI/res/values-sw320dp-land/dimens.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<resources>
+
+ <!-- Global actions grid -->
+ <dimen name="global_actions_grid_vertical_padding">3dp</dimen>
+ <dimen name="global_actions_grid_horizontal_padding">0dp</dimen>
+
+ <dimen name="global_actions_grid_item_side_margin">4dp</dimen>
+ <dimen name="global_actions_grid_item_vertical_margin">5dp</dimen>
+
+</resources>
+
diff --git a/packages/SystemUI/res/values-sw320dp/dimens.xml b/packages/SystemUI/res/values-sw320dp/dimens.xml
new file mode 100644
index 0000000..0c2b1cc
--- /dev/null
+++ b/packages/SystemUI/res/values-sw320dp/dimens.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<resources>
+
+ <!-- Global actions grid -->
+ <dimen name="global_actions_grid_container_bottom_margin">16dp</dimen>
+
+ <dimen name="global_actions_grid_vertical_padding">0dp</dimen>
+ <dimen name="global_actions_grid_horizontal_padding">3dp</dimen>
+
+ <dimen name="global_actions_grid_item_side_margin">5dp</dimen>
+ <dimen name="global_actions_grid_item_vertical_margin">4dp</dimen>
+ <dimen name="global_actions_grid_item_width">64dp</dimen>
+ <dimen name="global_actions_grid_item_height">64dp</dimen>
+
+ <dimen name="global_actions_grid_item_icon_width">18dp</dimen>
+ <dimen name="global_actions_grid_item_icon_height">18dp</dimen>
+ <dimen name="global_actions_grid_item_icon_top_margin">12dp</dimen>
+ <dimen name="global_actions_grid_item_icon_side_margin">22dp</dimen>
+ <dimen name="global_actions_grid_item_icon_bottom_margin">4dp</dimen>
+
+</resources>
+
diff --git a/packages/SystemUI/res/values-sw410dp-land/dimens.xml b/packages/SystemUI/res/values-sw410dp-land/dimens.xml
new file mode 100644
index 0000000..61ba2d0
--- /dev/null
+++ b/packages/SystemUI/res/values-sw410dp-land/dimens.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<resources>
+
+ <!-- Global actions grid -->
+ <dimen name="global_actions_grid_vertical_padding">4dp</dimen>
+ <dimen name="global_actions_grid_horizontal_padding">8dp</dimen>
+
+ <dimen name="global_actions_grid_item_side_margin">8dp</dimen>
+ <dimen name="global_actions_grid_item_vertical_margin">12dp</dimen>
+
+</resources>
+
diff --git a/packages/SystemUI/res/values-sw410dp/dimens.xml b/packages/SystemUI/res/values-sw410dp/dimens.xml
index 5ce6524..4197eb2 100644
--- a/packages/SystemUI/res/values-sw410dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw410dp/dimens.xml
@@ -21,4 +21,22 @@
for different hardware and product builds. -->
<resources>
<dimen name="qs_detail_items_padding_top">16dp</dimen>
+
+ <!-- Global actions grid -->
+ <dimen name="global_actions_grid_container_bottom_margin">16dp</dimen>
+
+ <dimen name="global_actions_grid_vertical_padding">8dp</dimen>
+ <dimen name="global_actions_grid_horizontal_padding">4dp</dimen>
+
+ <dimen name="global_actions_grid_item_side_margin">12dp</dimen>
+ <dimen name="global_actions_grid_item_vertical_margin">8dp</dimen>
+ <dimen name="global_actions_grid_item_width">72dp</dimen>
+ <dimen name="global_actions_grid_item_height">72dp</dimen>
+
+ <dimen name="global_actions_grid_item_icon_width">24dp</dimen>
+ <dimen name="global_actions_grid_item_icon_height">24dp</dimen>
+ <dimen name="global_actions_grid_item_icon_top_margin">16dp</dimen>
+ <dimen name="global_actions_grid_item_icon_side_margin">24dp</dimen>
+ <dimen name="global_actions_grid_item_icon_bottom_margin">4dp</dimen>
+
</resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 1c7ee36..8ecca26 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -841,26 +841,15 @@
<dimen name="default_gear_space">18dp</dimen>
<dimen name="cell_overlay_padding">18dp</dimen>
+ <!-- Global actions power menu -->
<dimen name="global_actions_panel_width">120dp</dimen>
-
- <dimen name="global_actions_grid_container_bottom_margin">16dp</dimen>
-
- <dimen name="global_actions_grid_side_margin">4dp</dimen>
- <dimen name="global_actions_grid_separated_panel_width">104dp</dimen>
- <dimen name="global_actions_grid_top_padding">8dp</dimen>
- <dimen name="global_actions_grid_bottom_padding">8dp</dimen>
- <dimen name="global_actions_grid_left_padding">4dp</dimen>
- <dimen name="global_actions_grid_right_padding">4dp</dimen>
-
- <dimen name="global_actions_grid_item_side_margin">12dp</dimen>
- <dimen name="global_actions_grid_item_vertical_margin">8dp</dimen>
-
<dimen name="global_actions_top_padding">120dp</dimen>
-
<dimen name="global_actions_padding">12dp</dimen>
-
<dimen name="global_actions_translate">9dp</dimen>
+ <!-- Global actions grid layout -->
+ <dimen name="global_actions_grid_side_margin">4dp</dimen>
+
<!-- The maximum offset in either direction that elements are moved horizontally to prevent
burn-in on AOD. -->
<dimen name="burn_in_prevention_offset_x">8dp</dimen>
diff --git a/packages/SystemUI/src/com/android/systemui/MultiListLayout.java b/packages/SystemUI/src/com/android/systemui/MultiListLayout.java
index 00ff518..8c49d56 100644
--- a/packages/SystemUI/src/com/android/systemui/MultiListLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/MultiListLayout.java
@@ -151,7 +151,10 @@
return null;
}
- interface RotationListener {
+ /**
+ * Interface to provide callbacks which trigger when this list detects a rotation.
+ */
+ public interface RotationListener {
void onRotate(int from, int to);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
index e62c77de..0832296 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
@@ -243,6 +243,16 @@
}
/**
+ * Directs a back gesture at the bubble stack. When opened, the current expanded bubble
+ * is forwarded a back key down/up pair.
+ */
+ public void performBackPressIfNeeded() {
+ if (mStackView != null) {
+ mStackView.performBackPressIfNeeded();
+ }
+ }
+
+ /**
* Adds or updates a bubble associated with the provided notification entry.
*
* @param notif the notification associated with this bubble.
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
index 492eadd..6dee8ad 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
@@ -335,6 +335,14 @@
updateView();
}
+ boolean performBackPressIfNeeded() {
+ if (mActivityView == null || !usingActivityView()) {
+ return false;
+ }
+ mActivityView.performBackPress();
+ return true;
+ }
+
@Override
public void onClick(View view) {
if (mEntry == null) {
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
index ed9b38b..eae17eea 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
@@ -815,4 +815,15 @@
getNormalizedYPosition());
}
}
+
+ /**
+ * Called when a back gesture should be directed to the Bubbles stack. When expanded,
+ * a back key down/up event pair is forwarded to the bubble Activity.
+ */
+ boolean performBackPressIfNeeded() {
+ if (!isExpanded()) {
+ return false;
+ }
+ return mExpandedBubble.expandedView.performBackPressIfNeeded();
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java b/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java
index 900ea72..a74c328 100644
--- a/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java
+++ b/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java
@@ -61,7 +61,7 @@
@VisibleForTesting
public SysuiColorExtractor(Context context, ExtractionType type, boolean registerVisibility) {
- super(context, type);
+ super(context, type, false /* immediately */);
mTonal = type instanceof Tonal ? (Tonal) type : new Tonal(context);
mWpHiddenColors = new GradientColors();
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index 7c9b286..3fa6035 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -33,7 +33,6 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.UserInfo;
-import android.content.res.Configuration;
import android.database.ContentObserver;
import android.graphics.Point;
import android.graphics.drawable.Drawable;
@@ -161,8 +160,6 @@
private final ScreenshotHelper mScreenshotHelper;
private final ScreenRecordHelper mScreenRecordHelper;
- private int mLastRotation;
-
/**
* @param context everything needs a context :(
*/
@@ -205,8 +202,6 @@
mScreenshotHelper = new ScreenshotHelper(context);
mScreenRecordHelper = new ScreenRecordHelper(context);
- mLastRotation = RotationUtils.getRotation(mContext);
-
Dependency.get(ConfigurationController.class).addCallback(this);
}
@@ -432,15 +427,6 @@
mContext.getTheme().applyStyle(mContext.getThemeResId(), true);
}
- @Override
- public void onConfigChanged(Configuration newConfig) {
- int rotation = RotationUtils.getRotation(mContext);
- if (rotation != mLastRotation) {
- mDialog.onRotate();
- }
- mLastRotation = rotation;
- }
-
public void destroy() {
Dependency.get(ConfigurationController.class).removeCallback(this);
}
@@ -1540,13 +1526,7 @@
return true;
}
});
- }
-
- public void onRotate() {
- if (mShowing && isGridEnabled(mContext)) {
- initializeLayout();
- updateList();
- }
+ mGlobalActionsLayout.setRotationListener(this::onRotate);
}
private int getGlobalActionsLayoutId(Context context) {
@@ -1703,6 +1683,13 @@
public void setKeyguardShowing(boolean keyguardShowing) {
mKeyguardShowing = keyguardShowing;
}
+
+ public void onRotate(int from, int to) {
+ if (mShowing && isGridEnabled(mContext)) {
+ initializeLayout();
+ updateList();
+ }
+ }
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index 7a7d1f6..bb34a87 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -461,6 +461,9 @@
if (mSnapAlgorithm == null) {
mSnapAlgorithm = new DividerSnapAlgorithm(getContext().getResources(), mDisplayWidth,
mDisplayHeight, mDividerSize, isHorizontalDivision(), mStableInsets, mDockSide);
+ if (mSnapTargetBeforeMinimized != null && mSnapTargetBeforeMinimized.isMiddleTarget) {
+ mSnapTargetBeforeMinimized = mSnapAlgorithm.getMiddleTarget();
+ }
}
if (mMinimizedSnapAlgorithm == null) {
mMinimizedSnapAlgorithm = new DividerSnapAlgorithm(getContext().getResources(),
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 008eeef..51ffc1d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -3261,7 +3261,11 @@
return true;
}
if (mState != StatusBarState.KEYGUARD && mState != StatusBarState.SHADE_LOCKED) {
- animateCollapsePanels();
+ if (mNotificationPanel.canPanelBeCollapsed()) {
+ animateCollapsePanels();
+ } else {
+ mBubbleController.performBackPressIfNeeded();
+ }
return true;
}
if (mKeyguardUserSwitcher != null && mKeyguardUserSwitcher.hideIfNotSimple(true)) {
diff --git a/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java b/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
index 8160e04..6714b0a 100644
--- a/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
+++ b/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
@@ -660,7 +660,7 @@
++mCount;
} catch (Exception e) {
Slog.e(TAG, "Error when attempting restore: " + e.toString());
- keyValueAgentErrorCleanup();
+ keyValueAgentErrorCleanup(false);
executeNextState(UnifiedRestoreState.RUNNING_QUEUE);
}
}
@@ -686,6 +686,7 @@
boolean staging = !packageName.equals("android");
ParcelFileDescriptor stage;
File downloadFile = (staging) ? mStageName : mBackupDataName;
+ boolean startedAgentRestore = false;
try {
IBackupTransport transport =
@@ -766,13 +767,15 @@
long restoreAgentTimeoutMillis = mAgentTimeoutParameters.getRestoreAgentTimeoutMillis();
backupManagerService.prepareOperationTimeout(
mEphemeralOpToken, restoreAgentTimeoutMillis, this, OP_TYPE_RESTORE_WAIT);
+ startedAgentRestore = true;
mAgent.doRestore(mBackupData, appVersionCode, mNewState,
mEphemeralOpToken, backupManagerService.getBackupManagerBinder());
} catch (Exception e) {
Slog.e(TAG, "Unable to call app for restore: " + packageName, e);
EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE,
packageName, e.toString());
- keyValueAgentErrorCleanup(); // clears any pending timeout messages as well
+ // Clears any pending timeout messages as well.
+ keyValueAgentErrorCleanup(startedAgentRestore);
// After a restore failure we go back to running the queue. If there
// are no more packages to be restored that will be handled by the
@@ -832,7 +835,7 @@
Slog.e(TAG, "Unable to finalize restore of " + packageName);
EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE,
packageName, e.toString());
- keyValueAgentErrorCleanup();
+ keyValueAgentErrorCleanup(true);
executeNextState(UnifiedRestoreState.RUNNING_QUEUE);
}
}
@@ -1110,11 +1113,18 @@
mListener.onFinished(callerLogString);
}
- void keyValueAgentErrorCleanup() {
- // If the agent fails restore, it might have put the app's data
- // into an incoherent state. For consistency we wipe its data
- // again in this case before continuing with normal teardown
- backupManagerService.clearApplicationDataAfterRestoreFailure(mCurrentPackage.packageName);
+ /**
+ * @param clearAppData - set to {@code true} if the backup agent had already been invoked when
+ * restore faied. So the app data may be in corrupted state and has to be cleared.
+ */
+ void keyValueAgentErrorCleanup(boolean clearAppData) {
+ if (clearAppData) {
+ // If the agent fails restore, it might have put the app's data
+ // into an incoherent state. For consistency we wipe its data
+ // again in this case before continuing with normal teardown
+ backupManagerService.clearApplicationDataAfterRestoreFailure(
+ mCurrentPackage.packageName);
+ }
keyValueAgentCleanup();
}
@@ -1251,7 +1261,7 @@
// Some kind of horrible semantic error; we're in an unexpected state.
// Back off hard and wind up.
Slog.e(TAG, "Unexpected restore callback into state " + mState);
- keyValueAgentErrorCleanup();
+ keyValueAgentErrorCleanup(true);
nextState = UnifiedRestoreState.FINAL;
break;
}
@@ -1271,7 +1281,7 @@
EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE,
mCurrentPackage.packageName, "restore timeout");
// Handle like an agent that threw on invocation: wipe it and go on to the next
- keyValueAgentErrorCleanup();
+ keyValueAgentErrorCleanup(true);
executeNextState(UnifiedRestoreState.RUNNING_QUEUE);
}
diff --git a/services/core/java/com/android/server/am/CoreSettingsObserver.java b/services/core/java/com/android/server/am/CoreSettingsObserver.java
index 8ffb67a..06d0152 100644
--- a/services/core/java/com/android/server/am/CoreSettingsObserver.java
+++ b/services/core/java/com/android/server/am/CoreSettingsObserver.java
@@ -79,6 +79,7 @@
sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_BLACKLIST, String.class);
sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_WHITELIST, String.class);
sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_BLACKLISTS, String.class);
+ sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_SPHAL_LIBRARIES, String.class);
// add other global settings here...
}
diff --git a/services/core/java/com/android/server/input/InputForwarder.java b/services/core/java/com/android/server/input/InputForwarder.java
deleted file mode 100644
index 00af839..0000000
--- a/services/core/java/com/android/server/input/InputForwarder.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.server.input;
-
-import android.app.IInputForwarder;
-import android.hardware.input.InputManagerInternal;
-import android.view.InputEvent;
-
-import com.android.server.LocalServices;
-
-import static android.hardware.input.InputManager.INJECT_INPUT_EVENT_MODE_ASYNC;
-
-/**
- * Basic implementation of {@link IInputForwarder}.
- */
-class InputForwarder extends IInputForwarder.Stub {
-
- private final InputManagerInternal mInputManagerInternal;
- private final int mDisplayId;
-
- InputForwarder(int displayId) {
- mDisplayId = displayId;
- mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
- }
-
- @Override
- public boolean forwardEvent(InputEvent event) {
- event.setDisplayId(mDisplayId);
- return mInputManagerInternal.injectInputEvent(event, INJECT_INPUT_EVENT_MODE_ASYNC);
- }
-}
\ No newline at end of file
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 28393a2..87c7441 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -17,7 +17,6 @@
package com.android.server.input;
import android.annotation.NonNull;
-import android.app.IInputForwarder;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
@@ -1685,29 +1684,6 @@
nativeMonitor(mPtr);
}
- // Binder call
- @Override
- public IInputForwarder createInputForwarder(int displayId) throws RemoteException {
- if (!checkCallingPermission(android.Manifest.permission.INJECT_EVENTS,
- "createInputForwarder()")) {
- throw new SecurityException("Requires INJECT_EVENTS permission");
- }
- final DisplayManager displayManager = mContext.getSystemService(DisplayManager.class);
- final Display display = displayManager.getDisplay(displayId);
- if (display == null) {
- throw new IllegalArgumentException(
- "Can't create input forwarder for non-existent displayId: " + displayId);
- }
- final int callingUid = Binder.getCallingUid();
- final int displayOwnerUid = display.getOwnerUid();
- if (callingUid != displayOwnerUid) {
- throw new SecurityException(
- "Only owner of the display can forward input events to it.");
- }
-
- return new InputForwarder(displayId);
- }
-
// Native callback.
private void notifyConfigurationChanged(long whenNanos) {
mWindowManagerCallbacks.notifyConfigurationChanged();
diff --git a/services/core/java/com/android/server/pm/ApexManager.java b/services/core/java/com/android/server/pm/ApexManager.java
index dac4b6f..8051abb 100644
--- a/services/core/java/com/android/server/pm/ApexManager.java
+++ b/services/core/java/com/android/server/pm/ApexManager.java
@@ -27,6 +27,7 @@
import android.content.pm.PackageParser.PackageParserException;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.ServiceManager.ServiceNotFoundException;
import android.util.Slog;
import com.android.internal.util.IndentingPrintWriter;
@@ -50,8 +51,12 @@
private final Map<String, PackageInfo> mActivePackagesCache;
ApexManager() {
- mApexService = IApexService.Stub.asInterface(
- ServiceManager.getService("apexservice"));
+ try {
+ mApexService = IApexService.Stub.asInterface(
+ ServiceManager.getServiceOrThrow("apexservice"));
+ } catch (ServiceNotFoundException e) {
+ throw new IllegalStateException("Required service apexservice not available");
+ }
mActivePackagesCache = populateActivePackagesCache();
}
@@ -151,7 +156,7 @@
}
/**
- * Mark a staged session previously submitted using {@cde submitStagedSession} as ready to be
+ * Mark a staged session previously submitted using {@code submitStagedSession} as ready to be
* applied at next reboot.
*
* @param sessionId the identifier of the {@link PackageInstallerSession} being marked as ready.
@@ -167,6 +172,27 @@
}
/**
+ * Marks a staged session as successful.
+ *
+ * <p>Only activated session can be marked as successful.
+ *
+ * @param sessionId the identifier of the {@link PackageInstallerSession} being marked as
+ * successful.
+ */
+ void markStagedSessionSuccessful(int sessionId) {
+ try {
+ mApexService.markStagedSessionSuccessful(sessionId);
+ } catch (RemoteException re) {
+ Slog.e(TAG, "Unable to contact apexservice", re);
+ throw new RuntimeException(re);
+ } catch (Exception e) {
+ // It is fine to just log an exception in this case. APEXd will be able to recover in
+ // case markStagedSessionSuccessful fails.
+ Slog.e(TAG, "Failed to mark session " + sessionId + " as successful", e);
+ }
+ }
+
+ /**
* Dumps various state information to the provided {@link PrintWriter} object.
*
* @param pw the {@link PrintWriter} object to send information to.
@@ -196,7 +222,7 @@
ipw.increaseIndent();
final ApexSessionInfo[] sessions = mApexService.getSessions();
for (ApexSessionInfo si : sessions) {
- ipw.println("Session ID: " + Integer.toString(si.sessionId));
+ ipw.println("Session ID: " + si.sessionId);
ipw.increaseIndent();
if (si.isUnknown) {
ipw.println("State: UNKNOWN");
@@ -206,8 +232,6 @@
ipw.println("State: STAGED");
} else if (si.isActivated) {
ipw.println("State: ACTIVATED");
- } else if (si.isActivationPendingRetry) {
- ipw.println("State: ACTIVATION PENDING RETRY");
} else if (si.isActivationFailed) {
ipw.println("State: ACTIVATION FAILED");
}
diff --git a/services/core/java/com/android/server/pm/OWNERS b/services/core/java/com/android/server/pm/OWNERS
index 640b155..8ce2568 100644
--- a/services/core/java/com/android/server/pm/OWNERS
+++ b/services/core/java/com/android/server/pm/OWNERS
@@ -9,6 +9,10 @@
toddke@android.com
toddke@google.com
+# apex support
+per-file ApexManager.java = dariofreni@google.com, narayan@google.com, toddke@android.com, toddke@google.com
+per-file StagingManager.java = dariofreni@google.com, narayan@google.com, toddke@android.com, toddke@google.com
+
# dex
per-file AbstractStatsBase.java = agampe@google.com
per-file AbstractStatsBase.java = calin@google.com
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index 6c212d6..d1ebc94 100644
--- a/services/core/java/com/android/server/pm/StagingManager.java
+++ b/services/core/java/com/android/server/pm/StagingManager.java
@@ -247,7 +247,8 @@
}
private void resumeSession(@NonNull PackageInstallerSession session) {
- if (sessionContainsApex(session)) {
+ boolean hasApex = sessionContainsApex(session);
+ if (hasApex) {
// Check with apexservice whether the apex packages have been activated.
ApexSessionInfo apexSessionInfo = mApexManager.getStagedSessionInfo(session.sessionId);
if (apexSessionInfo == null) {
@@ -271,7 +272,7 @@
mBgHandler.post(() -> preRebootVerification(session));
return;
}
- if (!apexSessionInfo.isActivated) {
+ if (!apexSessionInfo.isActivated && !apexSessionInfo.isSuccess) {
// In all the remaining cases apexd will try to apply the session again at next
// boot. Nothing to do here for now.
Slog.w(TAG, "Staged session " + session.sessionId + " scheduled to be applied "
@@ -287,7 +288,11 @@
+ "more information.");
return;
}
+
session.setStagedSessionApplied();
+ if (hasApex) {
+ mApexManager.markStagedSessionSuccessful(session.sessionId);
+ }
}
private String findFirstAPKInDir(File stageDir) {
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index f56b984..8df5a71 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -1181,11 +1181,9 @@
@NonNull int[] updatedUserIds) {
AppOpsManager appOpsManager = mContext.getSystemService(AppOpsManager.class);
- if (pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) {
- return updatedUserIds;
- }
-
String pkgName = pkg.packageName;
+ boolean supportsRuntimePermissions = pkg.applicationInfo.targetSdkVersion
+ >= Build.VERSION_CODES.M;
int[] users = UserManagerService.getInstance().getUserIds();
int numUsers = users.length;
@@ -1210,15 +1208,17 @@
if ((flags & (FLAG_PERMISSION_GRANTED_BY_DEFAULT
| FLAG_PERMISSION_POLICY_FIXED | FLAG_PERMISSION_SYSTEM_FIXED))
== 0) {
- int revokeResult = ps.revokeRuntimePermission(bp, userId);
- if (revokeResult
- != PERMISSION_OPERATION_FAILURE) {
-
- if (DEBUG_PERMISSIONS) {
- Slog.i(TAG, "Revoking runtime permission " + permission
- + " for " + pkgName
- + " as it is now requested");
+ if (supportsRuntimePermissions) {
+ int revokeResult = ps.revokeRuntimePermission(bp, userId);
+ if (revokeResult != PERMISSION_OPERATION_FAILURE) {
+ if (DEBUG_PERMISSIONS) {
+ Slog.i(TAG, "Revoking runtime permission "
+ + permission + " for " + pkgName
+ + " as it is now requested");
+ }
}
+ } else {
+ setAppOpMode(permission, pkg, userId, MODE_IGNORED);
}
List<String> fgPerms = mBackgroundPermissions.get(permission);
diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
index ceaf829..05d3c17 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
@@ -16,6 +16,7 @@
package com.android.server.rollback;
+import android.annotation.NonNull;
import android.app.AppOpsManager;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -842,6 +843,7 @@
String packageName = newPackage.packageName;
for (PackageRollbackInfo info : rd.packages) {
if (info.getPackageName().equals(packageName)) {
+ info.getInstalledUsers().addAll(IntArray.wrap(installedUsers));
AppDataRollbackHelper.SnapshotAppDataResult rs =
mAppDataRollbackHelper.snapshotAppData(packageName, installedUsers);
info.getPendingBackups().addAll(rs.pendingBackups);
@@ -874,7 +876,7 @@
* the child sessions, not the parent session.
*/
private boolean enableRollbackForSession(PackageInstaller.SessionInfo session,
- int[] installedUsers, boolean snapshotUserData) {
+ @NonNull int[] installedUsers, boolean snapshotUserData) {
// TODO: Don't attempt to enable rollback for split installs.
final int installFlags = session.installFlags;
if ((installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) == 0) {
@@ -1016,7 +1018,7 @@
}
if (!session.isMultiPackage()) {
- if (!enableRollbackForSession(session, null, false)) {
+ if (!enableRollbackForSession(session, new int[0], false)) {
Log.e(TAG, "Unable to enable rollback for session: " + sessionId);
result.offer(false);
return;
@@ -1030,7 +1032,7 @@
result.offer(false);
return;
}
- if (!enableRollbackForSession(childSession, null, false)) {
+ if (!enableRollbackForSession(childSession, new int[0], false)) {
Log.e(TAG, "Unable to enable rollback for session: " + sessionId);
result.offer(false);
return;
diff --git a/services/core/java/com/android/server/rollback/TEST_MAPPING b/services/core/java/com/android/server/rollback/TEST_MAPPING
index c1d95ac..6be93a0 100644
--- a/services/core/java/com/android/server/rollback/TEST_MAPPING
+++ b/services/core/java/com/android/server/rollback/TEST_MAPPING
@@ -2,6 +2,9 @@
"presubmit": [
{
"name": "RollbackTest"
+ },
+ {
+ "name": "StagedRollbackTest"
}
]
}
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index f33c518..087de69 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -87,8 +87,6 @@
import static android.os.Build.VERSION_CODES.O;
import static android.os.Process.SYSTEM_UID;
import static android.view.Display.INVALID_DISPLAY;
-import static android.view.WindowManagerPolicyConstants.NAV_BAR_LEFT;
-import static android.view.WindowManagerPolicyConstants.NAV_BAR_RIGHT;
import static com.android.server.am.ActivityRecordProto.CONFIGURATION_CONTAINER;
import static com.android.server.am.ActivityRecordProto.FRONT_OF_TASK;
@@ -2828,28 +2826,6 @@
outAppBounds.setEmpty();
}
- // TODO(b/112288258): Remove below calculation because the position information in bounds
- // will be replaced by the offset of surface.
- final Rect appBounds = parentConfig.windowConfiguration.getAppBounds();
- if (appBounds != null) {
- final Rect outBounds = inOutConfig.windowConfiguration.getBounds();
- final int activityWidth = outBounds.width();
- final int navBarPosition = mAtmService.mWindowManager.getNavBarPosition(getDisplayId());
- if (navBarPosition == NAV_BAR_LEFT) {
- // Position the activity frame on the opposite side of the nav bar.
- outBounds.left = appBounds.right - activityWidth;
- outBounds.right = appBounds.right;
- } else if (navBarPosition == NAV_BAR_RIGHT) {
- // Position the activity frame on the opposite side of the nav bar.
- outBounds.left = 0;
- outBounds.right = activityWidth + appBounds.left;
- } else if (appBounds.width() > activityWidth) {
- // Horizontally center the frame.
- outBounds.left = appBounds.left + (appBounds.width() - activityWidth) / 2;
- outBounds.right = outBounds.left + activityWidth;
- }
- }
-
task.computeConfigResourceOverrides(inOutConfig, parentConfig, insideParentBounds);
}
diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index 0a3c2fb..c685b05 100644
--- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
@@ -2332,6 +2332,20 @@
if (!task.canBeLaunchedOnDisplay(actualDisplayId)) {
throw new IllegalStateException("Task resolved to incompatible display");
}
+
+ final ActivityDisplay preferredDisplay =
+ mRootActivityContainer.getActivityDisplay(preferredDisplayId);
+
+ final boolean singleTaskInstance = preferredDisplay != null
+ && preferredDisplay.isSingleTaskInstance();
+
+ if (singleTaskInstance) {
+ // Suppress the warning toast if the preferredDisplay was set to singleTask.
+ // The singleTaskInstance displays will only contain one task and any attempt to
+ // launch new task will re-route to the default display.
+ return;
+ }
+
if (preferredDisplayId != actualDisplayId) {
Slog.w(TAG, "Failed to put " + task + " on display " + preferredDisplayId);
// Display a warning toast that we failed to put a task on a secondary display.
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 3430987..21a557e 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -2164,9 +2164,6 @@
// A modal window uses the whole compatibility bounds.
flags |= FLAG_NOT_TOUCH_MODAL;
mTmpRect.set(mAppToken.getResolvedOverrideBounds());
- // TODO(b/112288258): Remove the forced offset when the override bounds always
- // starts from zero (See {@link ActivityRecord#resolveOverrideConfiguration}).
- mTmpRect.offsetTo(0, 0);
} else {
// Non-modal uses the application based frame.
mTmpRect.set(mWindowFrames.mCompatFrame);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 9523202..9767efd 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -5181,7 +5181,7 @@
Preconditions.checkNotNull(who, "ComponentName is null");
final int userHandle = mInjector.userHandleGetCallingUserId();
synchronized (getLockObject()) {
- ActiveAdmin ap = getActiveAdminForCallerLocked(
+ final ActiveAdmin ap = getActiveAdminForCallerLocked(
who, DeviceAdminInfo.USES_POLICY_FORCE_LOCK, parent);
if (ap.maximumTimeToUnlock != timeMs) {
ap.maximumTimeToUnlock = timeMs;
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index 8c36905..a1db3e8 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -27,9 +27,6 @@
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
-import static com.android.server.policy.WindowManagerPolicy.NAV_BAR_BOTTOM;
-import static com.android.server.policy.WindowManagerPolicy.NAV_BAR_LEFT;
-import static com.android.server.policy.WindowManagerPolicy.NAV_BAR_RIGHT;
import static com.android.server.wm.ActivityStack.ActivityState.INITIALIZING;
import static com.android.server.wm.ActivityStack.ActivityState.PAUSING;
import static com.android.server.wm.ActivityStack.ActivityState.RESUMED;
@@ -158,35 +155,6 @@
assertTrue(mActivity.isState(STOPPED));
}
- @Test
- public void testPositionLimitedAspectRatioNavBarBottom() {
- verifyPositionWithLimitedAspectRatio(NAV_BAR_BOTTOM, new Rect(0, 0, 1000, 2000), 1.5f,
- new Rect(0, 0, 1000, 1500));
- }
-
- @Test
- public void testPositionLimitedAspectRatioNavBarLeft() {
- verifyPositionWithLimitedAspectRatio(NAV_BAR_LEFT, new Rect(0, 0, 2000, 1000), 1.5f,
- new Rect(500, 0, 2000, 1000));
- }
-
- @Test
- public void testPositionLimitedAspectRatioNavBarRight() {
- verifyPositionWithLimitedAspectRatio(NAV_BAR_RIGHT, new Rect(0, 0, 2000, 1000), 1.5f,
- new Rect(0, 0, 1500, 1000));
- }
-
- private void verifyPositionWithLimitedAspectRatio(int navBarPosition, Rect taskBounds,
- float aspectRatio, Rect expectedActivityBounds) {
- // Verify with nav bar on the right.
- when(mService.mWindowManager.getNavBarPosition(mActivity.getDisplayId()))
- .thenReturn(navBarPosition);
- mTask.getConfiguration().windowConfiguration.setAppBounds(taskBounds);
- mActivity.info.maxAspectRatio = aspectRatio;
- ensureActivityConfiguration();
- assertEquals(expectedActivityBounds, mActivity.getBounds());
- }
-
private void ensureActivityConfiguration() {
mActivity.ensureActivityConfiguration(0 /* globalChanges */, false /* preserveWindow */);
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
index 3eb9085..b0e20b8 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -35,6 +35,7 @@
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.reset;
@@ -54,7 +55,6 @@
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.doNothing;
import android.graphics.Insets;
import android.graphics.Matrix;
@@ -87,6 +87,7 @@
*/
@SmallTest
@Presubmit
+@FlakyTest(bugId = 124127512)
public class WindowStateTests extends WindowTestsBase {
private static int sPreviousNewInsetsMode;
@@ -389,6 +390,7 @@
}
@Test
+ @FlakyTest(bugId = 74078662)
public void testLayoutSeqResetOnReparent() {
final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
app.mLayoutSeq = 1;
@@ -445,6 +447,7 @@
}
@Test
+ @FlakyTest(bugId = 74078662)
public void testDisplayCutoutIsCalculatedRelativeToFrame() {
final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
WindowFrames wf = app.getWindowFrames();
diff --git a/tests/DexLoggerIntegrationTests/src/com/android/server/pm/dex/DexLoggerIntegrationTests.java b/tests/DexLoggerIntegrationTests/src/com/android/server/pm/dex/DexLoggerIntegrationTests.java
index 1cf960a..99d1f5ff4 100644
--- a/tests/DexLoggerIntegrationTests/src/com/android/server/pm/dex/DexLoggerIntegrationTests.java
+++ b/tests/DexLoggerIntegrationTests/src/com/android/server/pm/dex/DexLoggerIntegrationTests.java
@@ -65,6 +65,8 @@
@RunWith(JUnit4.class)
public final class DexLoggerIntegrationTests {
+ private static final String SHA_256 = "SHA-256";
+
// Event log tag used for SNET related events
private static final int SNET_TAG = 0x534e4554;
@@ -76,6 +78,13 @@
private static final int IDLE_LOGGING_JOB_ID = 2030028;
private static final int AUDIT_WATCHING_JOB_ID = 203142925;
+ // For tests that rely on parsing audit logs, how often to retry. (There are many reasons why
+ // we might not see the audit logs, including throttling and delays in log generation, so to
+ // avoid flakiness we run these tests multiple times, allowing progressively longer between
+ // code loading and checking the logs on each try.)
+ private static final int AUDIT_LOG_RETRIES = 10;
+ private static final int RETRY_DELAY_MS = 2_000;
+
private static Context sContext;
private static int sMyUid;
@@ -144,78 +153,65 @@
@Test
public void testGeneratesEvents_nativeLibrary() throws Exception {
- File privateCopyFile = privateFile("copied.so");
- String expectedNameHash =
- "996223BAD4B4FE75C57A3DEC61DB9C0B38E0A7AD479FC95F33494F4BC55A0F0E";
- String expectedContentHash =
- copyAndHashResource(libraryPath("DexLoggerNativeTestLibrary.so"), privateCopyFile);
+ new TestNativeCodeWithRetries() {
+ @Override
+ protected void loadNativeCode(int tryNumber) throws Exception {
+ // We need to use a different file name for each retry, because once a file is
+ // loaded, re-loading it has no effect.
+ String privateCopyName = "copied" + tryNumber + ".so";
+ File privateCopyFile = privateFile(privateCopyName);
+ mExpectedNameHash = hashOf(privateCopyName);
+ mExpectedContentHash = copyAndHashResource(
+ libraryPath("DexLoggerNativeTestLibrary.so"), privateCopyFile);
- System.load(privateCopyFile.toString());
-
- // Run the job to scan generated audit log entries
- runDynamicCodeLoggingJob(AUDIT_WATCHING_JOB_ID);
-
- // And then make sure we log events about it
- long previousEventNanos = mostRecentEventTimeNanos();
- runDynamicCodeLoggingJob(IDLE_LOGGING_JOB_ID);
-
- assertDclLoggedSince(previousEventNanos, DCL_NATIVE_SUBTAG,
- expectedNameHash, expectedContentHash);
+ System.load(privateCopyFile.toString());
+ }
+ }.runTest();
}
@Test
public void testGeneratesEvents_nativeLibrary_escapedName() throws Exception {
- // A file name with a space will be escaped in the audit log; verify we un-escape it
- // correctly.
- File privateCopyFile = privateFile("second copy.so");
- String expectedNameHash =
- "8C39990C560B4F36F83E208E279F678746FE23A790E4C50F92686584EA2041CA";
- String expectedContentHash =
- copyAndHashResource(libraryPath("DexLoggerNativeTestLibrary.so"), privateCopyFile);
+ new TestNativeCodeWithRetries() {
+ @Override
+ protected void loadNativeCode(int tryNumber) throws Exception {
+ // A file name with a space will be escaped in the audit log; verify we un-escape it
+ // correctly.
+ String privateCopyName = "second copy " + tryNumber + ".so";
+ File privateCopyFile = privateFile(privateCopyName);
+ mExpectedNameHash = hashOf(privateCopyName);
+ mExpectedContentHash = copyAndHashResource(
+ libraryPath("DexLoggerNativeTestLibrary.so"), privateCopyFile);
- System.load(privateCopyFile.toString());
-
- // Run the job to scan generated audit log entries
- runDynamicCodeLoggingJob(AUDIT_WATCHING_JOB_ID);
-
- // And then make sure we log events about it
- long previousEventNanos = mostRecentEventTimeNanos();
- runDynamicCodeLoggingJob(IDLE_LOGGING_JOB_ID);
-
- assertDclLoggedSince(previousEventNanos, DCL_NATIVE_SUBTAG,
- expectedNameHash, expectedContentHash);
+ System.load(privateCopyFile.toString());
+ }
+ }.runTest();
}
@Test
public void testGeneratesEvents_nativeExecutable() throws Exception {
- File privateCopyFile = privateFile("test_executable");
- String expectedNameHash =
- "3FBEC3F925A132D18F347F11AE9A5BB8DE1238828F8B4E064AA86EB68BD46DCF";
- String expectedContentHash =
- copyAndHashResource("/DexLoggerNativeExecutable", privateCopyFile);
- assertThat(privateCopyFile.setExecutable(true)).isTrue();
+ new TestNativeCodeWithRetries() {
+ @Override
+ protected void loadNativeCode(int tryNumber) throws Exception {
+ String privateCopyName = "test_executable" + tryNumber;
+ File privateCopyFile = privateFile(privateCopyName);
+ mExpectedNameHash = hashOf(privateCopyName);
+ mExpectedContentHash = copyAndHashResource(
+ "/DexLoggerNativeExecutable", privateCopyFile);
+ assertThat(privateCopyFile.setExecutable(true)).isTrue();
- Process process = Runtime.getRuntime().exec(privateCopyFile.toString());
- int exitCode = process.waitFor();
- assertThat(exitCode).isEqualTo(0);
-
- // Run the job to scan generated audit log entries
- runDynamicCodeLoggingJob(AUDIT_WATCHING_JOB_ID);
-
- // And then make sure we log events about it
- long previousEventNanos = mostRecentEventTimeNanos();
- runDynamicCodeLoggingJob(IDLE_LOGGING_JOB_ID);
-
- assertDclLoggedSince(previousEventNanos, DCL_NATIVE_SUBTAG,
- expectedNameHash, expectedContentHash);
+ Process process = Runtime.getRuntime().exec(privateCopyFile.toString());
+ int exitCode = process.waitFor();
+ assertThat(exitCode).isEqualTo(0);
+ }
+ }.runTest();
}
@Test
public void testGeneratesEvents_spoofed_validFile() throws Exception {
File privateCopyFile = privateFile("spoofed");
- String expectedContentHash =
- copyAndHashResource("/DexLoggerNativeExecutable", privateCopyFile);
+ String expectedContentHash = copyAndHashResource(
+ "/DexLoggerNativeExecutable", privateCopyFile);
EventLog.writeEvent(EventLog.getTagCode("auditd"),
"type=1400 avc: granted { execute_no_trans } "
@@ -304,6 +300,40 @@
assertNoDclLoggedSince(previousEventNanos, DCL_NATIVE_SUBTAG, expectedNameHash);
}
+ // Abstract out the logic for running a native code loading test multiple times if needed and
+ // leaving time for audit messages to reach the log.
+ private abstract class TestNativeCodeWithRetries {
+ String mExpectedContentHash;
+ String mExpectedNameHash;
+
+ abstract void loadNativeCode(int tryNumber) throws Exception;
+
+ final void runTest() throws Exception {
+ List<String> messages = null;
+
+ for (int i = 0; i < AUDIT_LOG_RETRIES; i++) {
+ loadNativeCode(i);
+
+ SystemClock.sleep(i * RETRY_DELAY_MS);
+
+ // Run the job to scan generated audit log entries
+ runDynamicCodeLoggingJob(AUDIT_WATCHING_JOB_ID);
+
+ // And then make sure we log events about it
+ long previousEventNanos = mostRecentEventTimeNanos();
+ runDynamicCodeLoggingJob(IDLE_LOGGING_JOB_ID);
+
+ messages = findMatchingEvents(
+ previousEventNanos, DCL_NATIVE_SUBTAG, mExpectedNameHash);
+ if (!messages.isEmpty()) {
+ break;
+ }
+ }
+
+ assertHasDclLog(messages, mExpectedContentHash);
+ }
+ }
+
private static File privateFile(String name) {
return new File(sContext.getDir("dcl", Context.MODE_PRIVATE), name);
}
@@ -315,7 +345,7 @@
}
private static String copyAndHashResource(String resourcePath, File copyTo) throws Exception {
- MessageDigest hasher = MessageDigest.getInstance("SHA-256");
+ MessageDigest hasher = MessageDigest.getInstance(SHA_256);
// Copy the jar from our Java resources to a private data directory
Class<?> thisClass = DexLoggerIntegrationTests.class;
@@ -334,6 +364,16 @@
// Compute the SHA-256 of the file content so we can check that it is the same as the value
// we see logged.
+ return toHexString(hasher);
+ }
+
+ private String hashOf(String input) throws Exception {
+ MessageDigest hasher = MessageDigest.getInstance(SHA_256);
+ hasher.update(input.getBytes());
+ return toHexString(hasher);
+ }
+
+ private static String toHexString(MessageDigest hasher) {
Formatter formatter = new Formatter();
for (byte b : hasher.digest()) {
formatter.format("%02X", b);
@@ -388,6 +428,10 @@
List<String> messages =
findMatchingEvents(previousEventNanos, expectedSubTag, expectedNameHash);
+ assertHasDclLog(messages, expectedContentHash);
+ }
+
+ private static void assertHasDclLog(List<String> messages, String expectedContentHash) {
assertWithMessage("Expected exactly one matching log entry").that(messages).hasSize(1);
assertThat(messages.get(0)).endsWith(expectedContentHash);
}
diff --git a/tests/Internal/src/com/android/internal/colorextraction/ColorExtractorTest.java b/tests/Internal/src/com/android/internal/colorextraction/ColorExtractorTest.java
index cb6a83d..39608a4 100644
--- a/tests/Internal/src/com/android/internal/colorextraction/ColorExtractorTest.java
+++ b/tests/Internal/src/com/android/internal/colorextraction/ColorExtractorTest.java
@@ -56,7 +56,7 @@
@Test
public void ColorExtractor_extractWhenInitialized() {
ExtractionType type = mock(Tonal.class);
- new ColorExtractor(mContext, type);
+ new ColorExtractor(mContext, type, true);
// 1 for lock and 1 for system
verify(type, times(2))
.extractInto(any(), any(), any(), any());
@@ -83,7 +83,7 @@
outGradientColorsDark.set(colorsExpectedDark);
outGradientColorsExtraDark.set(colorsExpectedExtraDark);
};
- ColorExtractor extractor = new ColorExtractor(mContext, type);
+ ColorExtractor extractor = new ColorExtractor(mContext, type, true);
GradientColors colors = extractor.getColors(WallpaperManager.FLAG_SYSTEM,
ColorExtractor.TYPE_NORMAL);
@@ -98,7 +98,7 @@
public void addOnColorsChangedListener_invokesListener() {
ColorExtractor.OnColorsChangedListener mockedListeners =
mock(ColorExtractor.OnColorsChangedListener.class);
- ColorExtractor extractor = new ColorExtractor(mContext, new Tonal(mContext));
+ ColorExtractor extractor = new ColorExtractor(mContext, new Tonal(mContext), true);
extractor.addOnColorsChangedListener(mockedListeners);
extractor.onColorsChanged(new WallpaperColors(Color.valueOf(Color.RED), null, null),
diff --git a/tests/RollbackTest/TEST_MAPPING b/tests/RollbackTest/TEST_MAPPING
index c1d95ac..6be93a0 100644
--- a/tests/RollbackTest/TEST_MAPPING
+++ b/tests/RollbackTest/TEST_MAPPING
@@ -2,6 +2,9 @@
"presubmit": [
{
"name": "RollbackTest"
+ },
+ {
+ "name": "StagedRollbackTest"
}
]
}
diff --git a/tools/aapt2/ResourceParser.cpp b/tools/aapt2/ResourceParser.cpp
index c188782..d0237f8 100644
--- a/tools/aapt2/ResourceParser.cpp
+++ b/tools/aapt2/ResourceParser.cpp
@@ -1637,7 +1637,9 @@
if (!(plural->values[index] = ParseXml(
parser, android::ResTable_map::TYPE_STRING, kNoRawString))) {
error = true;
+ continue;
}
+
plural->values[index]->SetSource(item_source);
} else if (!ShouldIgnoreElement(element_namespace, element_name)) {
diff --git a/tools/aapt2/integration-tests/Android.mk b/tools/aapt2/integration-tests/Android.mk
deleted file mode 100644
index 6361f9b..0000000
--- a/tools/aapt2/integration-tests/Android.mk
+++ /dev/null
@@ -1,2 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tools/aapt2/integration-tests/AutoVersionTest/Android.bp b/tools/aapt2/integration-tests/AutoVersionTest/Android.bp
new file mode 100644
index 0000000..79fb573
--- /dev/null
+++ b/tools/aapt2/integration-tests/AutoVersionTest/Android.bp
@@ -0,0 +1,20 @@
+//
+// Copyright (C) 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+android_test {
+ name: "AaptAutoVersionTest",
+ sdk_version: "current",
+}
diff --git a/tools/aapt2/integration-tests/AutoVersionTest/Android.mk b/tools/aapt2/integration-tests/AutoVersionTest/Android.mk
deleted file mode 100644
index 03cce35..0000000
--- a/tools/aapt2/integration-tests/AutoVersionTest/Android.mk
+++ /dev/null
@@ -1,24 +0,0 @@
-#
-# Copyright (C) 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_USE_AAPT2 := true
-LOCAL_PACKAGE_NAME := AaptAutoVersionTest
-LOCAL_SDK_VERSION := current
-LOCAL_MODULE_TAGS := tests
-include $(BUILD_PACKAGE)
diff --git a/tools/aapt2/integration-tests/BasicTest/Android.bp b/tools/aapt2/integration-tests/BasicTest/Android.bp
new file mode 100644
index 0000000..a94a01f
--- /dev/null
+++ b/tools/aapt2/integration-tests/BasicTest/Android.bp
@@ -0,0 +1,20 @@
+//
+// Copyright (C) 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+android_test {
+ name: "AaptBasicTest",
+ sdk_version: "current",
+}
diff --git a/tools/aapt2/integration-tests/BasicTest/Android.mk b/tools/aapt2/integration-tests/BasicTest/Android.mk
deleted file mode 100644
index d160554..0000000
--- a/tools/aapt2/integration-tests/BasicTest/Android.mk
+++ /dev/null
@@ -1,24 +0,0 @@
-#
-# Copyright (C) 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_USE_AAPT2 := true
-LOCAL_PACKAGE_NAME := AaptBasicTest
-LOCAL_SDK_VERSION := current
-LOCAL_MODULE_TAGS := tests
-include $(BUILD_PACKAGE)
diff --git a/tools/aapt2/integration-tests/StaticLibTest/Android.mk b/tools/aapt2/integration-tests/StaticLibTest/Android.mk
deleted file mode 100644
index 6361f9b..0000000
--- a/tools/aapt2/integration-tests/StaticLibTest/Android.mk
+++ /dev/null
@@ -1,2 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tools/aapt2/integration-tests/StaticLibTest/App/Android.bp b/tools/aapt2/integration-tests/StaticLibTest/App/Android.bp
new file mode 100644
index 0000000..9aadff3
--- /dev/null
+++ b/tools/aapt2/integration-tests/StaticLibTest/App/Android.bp
@@ -0,0 +1,34 @@
+//
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+android_test {
+
+ name: "AaptTestStaticLib_App",
+ sdk_version: "current",
+ srcs: ["src/**/*.java"],
+ asset_dirs: [
+ "assets",
+ "assets2",
+ ],
+ static_libs: [
+ "AaptTestStaticLib_LibOne",
+ "AaptTestStaticLib_LibTwo",
+ ],
+ aaptflags: [
+ "--no-version-vectors",
+ "--no-version-transitions",
+ ],
+}
diff --git a/tools/aapt2/integration-tests/StaticLibTest/App/Android.mk b/tools/aapt2/integration-tests/StaticLibTest/App/Android.mk
deleted file mode 100644
index 3cce35d..0000000
--- a/tools/aapt2/integration-tests/StaticLibTest/App/Android.mk
+++ /dev/null
@@ -1,30 +0,0 @@
-#
-# Copyright (C) 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_USE_AAPT2 := true
-LOCAL_PACKAGE_NAME := AaptTestStaticLib_App
-LOCAL_SDK_VERSION := current
-LOCAL_MODULE_TAGS := tests
-LOCAL_SRC_FILES := $(call all-java-files-under,src)
-LOCAL_ASSET_DIR := $(LOCAL_PATH)/assets $(LOCAL_PATH)/assets2
-LOCAL_STATIC_ANDROID_LIBRARIES := \
- AaptTestStaticLib_LibOne \
- AaptTestStaticLib_LibTwo
-LOCAL_AAPT_FLAGS := --no-version-vectors --no-version-transitions
-include $(BUILD_PACKAGE)
diff --git a/tools/aapt2/integration-tests/StaticLibTest/LibOne/Android.bp b/tools/aapt2/integration-tests/StaticLibTest/LibOne/Android.bp
new file mode 100644
index 0000000..4c81813
--- /dev/null
+++ b/tools/aapt2/integration-tests/StaticLibTest/LibOne/Android.bp
@@ -0,0 +1,22 @@
+//
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+android_library {
+ name: "AaptTestStaticLib_LibOne",
+ sdk_version: "current",
+ srcs: ["src/**/*.java"],
+ resource_dirs: ["res"],
+}
diff --git a/tools/aapt2/integration-tests/StaticLibTest/LibOne/Android.mk b/tools/aapt2/integration-tests/StaticLibTest/LibOne/Android.mk
deleted file mode 100644
index da25f64..0000000
--- a/tools/aapt2/integration-tests/StaticLibTest/LibOne/Android.mk
+++ /dev/null
@@ -1,29 +0,0 @@
-#
-# Copyright (C) 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_USE_AAPT2 := true
-LOCAL_MODULE := AaptTestStaticLib_LibOne
-LOCAL_SDK_VERSION := current
-LOCAL_MODULE_TAGS := tests
-LOCAL_SRC_FILES := $(call all-java-files-under,src)
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-
-# We need this to compile the Java sources of AaptTestStaticLib_LibTwo using javac.
-LOCAL_JAR_EXCLUDE_FILES := none
-include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/tools/aapt2/integration-tests/StaticLibTest/LibTwo/Android.bp b/tools/aapt2/integration-tests/StaticLibTest/LibTwo/Android.bp
new file mode 100644
index 0000000..7c4f7ed
--- /dev/null
+++ b/tools/aapt2/integration-tests/StaticLibTest/LibTwo/Android.bp
@@ -0,0 +1,23 @@
+//
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+android_library {
+ name: "AaptTestStaticLib_LibTwo",
+ sdk_version: "current",
+ srcs: ["src/**/*.java"],
+ resource_dirs: ["res"],
+ libs: ["AaptTestStaticLib_LibOne"],
+}
diff --git a/tools/aapt2/integration-tests/StaticLibTest/LibTwo/Android.mk b/tools/aapt2/integration-tests/StaticLibTest/LibTwo/Android.mk
deleted file mode 100644
index 27a3134..0000000
--- a/tools/aapt2/integration-tests/StaticLibTest/LibTwo/Android.mk
+++ /dev/null
@@ -1,28 +0,0 @@
-#
-# Copyright (C) 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_USE_AAPT2 := true
-LOCAL_MODULE := AaptTestStaticLib_LibTwo
-LOCAL_SDK_VERSION := current
-LOCAL_MODULE_TAGS := tests
-LOCAL_SRC_FILES := $(call all-java-files-under,src)
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-LOCAL_SHARED_ANDROID_LIBRARIES := AaptTestStaticLib_LibOne
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
diff --git a/tools/aapt2/integration-tests/SymlinkTest/Android.bp b/tools/aapt2/integration-tests/SymlinkTest/Android.bp
new file mode 100644
index 0000000..68e6148
--- /dev/null
+++ b/tools/aapt2/integration-tests/SymlinkTest/Android.bp
@@ -0,0 +1,20 @@
+//
+// Copyright (C) 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+android_test {
+ name: "AaptSymlinkTest",
+ sdk_version: "current",
+}
diff --git a/tools/aapt2/integration-tests/SymlinkTest/Android.mk b/tools/aapt2/integration-tests/SymlinkTest/Android.mk
deleted file mode 100644
index 8da1141..0000000
--- a/tools/aapt2/integration-tests/SymlinkTest/Android.mk
+++ /dev/null
@@ -1,24 +0,0 @@
-#
-# Copyright (C) 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_USE_AAPT2 := true
-LOCAL_PACKAGE_NAME := AaptSymlinkTest
-LOCAL_SDK_VERSION := current
-LOCAL_MODULE_TAGS := tests
-include $(BUILD_PACKAGE)