Merge "[AWARE] Add annotations to ParcelablePeerHandle"
diff --git a/api/current.txt b/api/current.txt
index 8e356d0..1f4eb8f 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -43968,7 +43968,6 @@
field public static final String EXTRA_INCOMING_CALL_EXTRAS = "android.telecom.extra.INCOMING_CALL_EXTRAS";
field public static final String EXTRA_INCOMING_VIDEO_STATE = "android.telecom.extra.INCOMING_VIDEO_STATE";
field public static final String EXTRA_IS_DEFAULT_CALL_SCREENING_APP = "android.telecom.extra.IS_DEFAULT_CALL_SCREENING_APP";
- field public static final String EXTRA_IS_ENABLED = "android.telecom.extra.IS_ENABLED";
field public static final String EXTRA_NOTIFICATION_COUNT = "android.telecom.extra.NOTIFICATION_COUNT";
field public static final String EXTRA_NOTIFICATION_PHONE_NUMBER = "android.telecom.extra.NOTIFICATION_PHONE_NUMBER";
field public static final String EXTRA_OUTGOING_CALL_EXTRAS = "android.telecom.extra.OUTGOING_CALL_EXTRAS";
diff --git a/api/system-current.txt b/api/system-current.txt
index 0f1ab29..447f576 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -1576,6 +1576,7 @@
method public boolean getAllocateAggressive();
method @Deprecated public boolean getAllowDowngrade();
method public boolean getDontKillApp();
+ method public boolean getEnableRollback();
method @Nullable public String[] getGrantedRuntimePermissions();
method public boolean getInstallAsFullApp(boolean);
method public boolean getInstallAsInstantApp(boolean);
@@ -1587,7 +1588,7 @@
method @RequiresPermission(android.Manifest.permission.ALLOCATE_AGGRESSIVE) public void setAllocateAggressive(boolean);
method @Deprecated public void setAllowDowngrade(boolean);
method public void setDontKillApp(boolean);
- method public void setEnableRollback();
+ method public void setEnableRollback(boolean);
method @RequiresPermission(android.Manifest.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS) public void setGrantedRuntimePermissions(String[]);
method @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES) public void setInstallAsApex();
method public void setInstallAsInstantApp(boolean);
@@ -1822,18 +1823,18 @@
public final class PackageRollbackInfo implements android.os.Parcelable {
method public int describeContents();
- method public String getPackageName();
- method public android.content.pm.VersionedPackage getVersionRolledBackFrom();
- method public android.content.pm.VersionedPackage getVersionRolledBackTo();
+ method @NonNull public String getPackageName();
+ method @NonNull public android.content.pm.VersionedPackage getVersionRolledBackFrom();
+ method @NonNull public android.content.pm.VersionedPackage getVersionRolledBackTo();
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.content.rollback.PackageRollbackInfo> CREATOR;
}
public final class RollbackInfo implements android.os.Parcelable {
method public int describeContents();
- method public java.util.List<android.content.pm.VersionedPackage> getCausePackages();
+ method @NonNull public java.util.List<android.content.pm.VersionedPackage> getCausePackages();
method public int getCommittedSessionId();
- method public java.util.List<android.content.rollback.PackageRollbackInfo> getPackages();
+ method @NonNull public java.util.List<android.content.rollback.PackageRollbackInfo> getPackages();
method public int getRollbackId();
method public boolean isStaged();
method public void writeToParcel(android.os.Parcel, int);
@@ -1843,7 +1844,7 @@
public final class RollbackManager {
method @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS) public void commitRollback(int, @NonNull java.util.List<android.content.pm.VersionedPackage>, @NonNull android.content.IntentSender);
method @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS) public void expireRollbackForPackage(@NonNull String);
- method @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS) public java.util.List<android.content.rollback.RollbackInfo> getAvailableRollbacks();
+ method @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS) @NonNull public java.util.List<android.content.rollback.RollbackInfo> getAvailableRollbacks();
method @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS) @NonNull public java.util.List<android.content.rollback.RollbackInfo> getRecentlyCommittedRollbacks();
method @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS) public void reloadPersistedData();
field public static final String EXTRA_STATUS = "android.content.rollback.extra.STATUS";
@@ -5187,10 +5188,10 @@
public static interface Binder.ProxyTransactListener {
method public void onTransactEnded(@Nullable Object);
- method public Object onTransactStarted(android.os.IBinder, int);
+ method @Nullable public Object onTransactStarted(@NonNull android.os.IBinder, int);
}
- public class BugreportManager {
+ public final class BugreportManager {
method @RequiresPermission(android.Manifest.permission.DUMP) public void cancelBugreport();
method @RequiresPermission(android.Manifest.permission.DUMP) public void startBugreport(@NonNull android.os.ParcelFileDescriptor, @Nullable android.os.ParcelFileDescriptor, @NonNull android.os.BugreportParams, @NonNull java.util.concurrent.Executor, @NonNull android.os.BugreportManager.BugreportCallback);
}
@@ -5199,7 +5200,7 @@
ctor public BugreportManager.BugreportCallback();
method public void onError(int);
method public void onFinished();
- method public void onProgress(float);
+ method public void onProgress(@FloatRange(from=0.0f, to=100.0f) float);
field public static final int BUGREPORT_ERROR_ANOTHER_REPORT_IN_PROGRESS = 5; // 0x5
field public static final int BUGREPORT_ERROR_INVALID_INPUT = 1; // 0x1
field public static final int BUGREPORT_ERROR_RUNTIME = 2; // 0x2
@@ -5208,7 +5209,7 @@
}
public final class BugreportParams {
- ctor public BugreportParams(@android.os.BugreportParams.BugreportMode int);
+ ctor public BugreportParams(int);
method public int getMode();
field public static final int BUGREPORT_MODE_FULL = 0; // 0x0
field public static final int BUGREPORT_MODE_INTERACTIVE = 1; // 0x1
@@ -5218,9 +5219,6 @@
field public static final int BUGREPORT_MODE_WIFI = 5; // 0x5
}
- @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @IntDef(prefix={"BUGREPORT_MODE_"}, value={android.os.BugreportParams.BUGREPORT_MODE_FULL, android.os.BugreportParams.BUGREPORT_MODE_INTERACTIVE, android.os.BugreportParams.BUGREPORT_MODE_REMOTE, android.os.BugreportParams.BUGREPORT_MODE_WEAR, android.os.BugreportParams.BUGREPORT_MODE_TELEPHONY, android.os.BugreportParams.BUGREPORT_MODE_WIFI}) public static @interface BugreportParams.BugreportMode {
- }
-
public static class Build.VERSION {
field public static final String PREVIEW_SDK_FINGERPRINT;
}
diff --git a/api/system-removed.txt b/api/system-removed.txt
index 7e04469..18d0ec0 100644
--- a/api/system-removed.txt
+++ b/api/system-removed.txt
@@ -60,6 +60,14 @@
}
+package android.content.pm {
+
+ public static class PackageInstaller.SessionParams implements android.os.Parcelable {
+ method @Deprecated public void setEnableRollback();
+ }
+
+}
+
package android.location {
public class LocationManager {
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index d758c4d..7b4dd19 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -1448,14 +1448,33 @@
/**
* Request that rollbacks be enabled for the given upgrade.
+ *
+ * @removed
+ * @deprecated use {@link #setEnableRollback(boolean)} instead.
* @hide
*/
+ @Deprecated
@SystemApi
public void setEnableRollback() {
installFlags |= PackageManager.INSTALL_ENABLE_ROLLBACK;
}
/**
+ * Request that rollbacks be enabled or disabled for the given upgrade.
+ *
+ * @param enable set to {@code true} to enable, {@code false} to disable
+ * @hide
+ */
+ @SystemApi
+ public void setEnableRollback(boolean enable) {
+ if (enable) {
+ installFlags |= PackageManager.INSTALL_ENABLE_ROLLBACK;
+ } else {
+ installFlags &= ~PackageManager.INSTALL_ENABLE_ROLLBACK;
+ }
+ }
+
+ /**
* @deprecated use {@link #setRequestDowngrade(boolean)}.
* {@hide}
*/
@@ -2058,6 +2077,16 @@
}
/**
+ * Return whether rollback is enabled or disabled for the given upgrade.
+ *
+ * @hide
+ */
+ @SystemApi
+ public boolean getEnableRollback() {
+ return (installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) != 0;
+ }
+
+ /**
* Get the value set in {@link SessionParams#setAllocateAggressive(boolean)}.
*
* @hide
diff --git a/core/java/android/content/rollback/PackageRollbackInfo.java b/core/java/android/content/rollback/PackageRollbackInfo.java
index 03810f5..c0414fc 100644
--- a/core/java/android/content/rollback/PackageRollbackInfo.java
+++ b/core/java/android/content/rollback/PackageRollbackInfo.java
@@ -89,6 +89,7 @@
/**
* Returns the name of the package to roll back from.
*/
+ @NonNull
public String getPackageName() {
return mVersionRolledBackFrom.getPackageName();
}
@@ -96,6 +97,7 @@
/**
* Returns the version of the package rolled back from.
*/
+ @NonNull
public VersionedPackage getVersionRolledBackFrom() {
return mVersionRolledBackFrom;
}
@@ -103,6 +105,7 @@
/**
* Returns the version of the package rolled back to.
*/
+ @NonNull
public VersionedPackage getVersionRolledBackTo() {
return mVersionRolledBackTo;
}
diff --git a/core/java/android/content/rollback/RollbackInfo.java b/core/java/android/content/rollback/RollbackInfo.java
index 29b99e0..a363718 100644
--- a/core/java/android/content/rollback/RollbackInfo.java
+++ b/core/java/android/content/rollback/RollbackInfo.java
@@ -16,6 +16,7 @@
package android.content.rollback;
+import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.content.pm.VersionedPackage;
import android.os.Parcel;
@@ -72,6 +73,7 @@
/**
* Returns the list of package that are rolled back.
*/
+ @NonNull
public List<PackageRollbackInfo> getPackages() {
return mPackages;
}
@@ -105,6 +107,7 @@
* As provided to {@link #commitRollback} when the rollback was committed.
* This is only applicable for rollbacks that have been committed.
*/
+ @NonNull
public List<VersionedPackage> getCausePackages() {
return mCausePackages;
}
diff --git a/core/java/android/content/rollback/RollbackManager.java b/core/java/android/content/rollback/RollbackManager.java
index c043491..4e8c254 100644
--- a/core/java/android/content/rollback/RollbackManager.java
+++ b/core/java/android/content/rollback/RollbackManager.java
@@ -57,6 +57,7 @@
* MANAGE_ROLLBACKS permission.
*/
@RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS)
+ @NonNull
public List<RollbackInfo> getAvailableRollbacks() {
try {
return mBinder.getAvailableRollbacks().getList();
diff --git a/core/java/android/net/ParseException.java b/core/java/android/net/ParseException.java
index 68b209b..2380e86 100644
--- a/core/java/android/net/ParseException.java
+++ b/core/java/android/net/ParseException.java
@@ -24,6 +24,7 @@
public String response;
ParseException(String response) {
+ super(response);
this.response = response;
}
}
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java
index b28c2f4..d5ef249 100644
--- a/core/java/android/os/Binder.java
+++ b/core/java/android/os/Binder.java
@@ -653,7 +653,8 @@
*
* @return an object that will be passed back to #onTransactEnded (or null).
*/
- Object onTransactStarted(IBinder binder, int transactionCode);
+ @Nullable
+ Object onTransactStarted(@NonNull IBinder binder, int transactionCode);
/**
* Called after onTranact (even when an exception is thrown).
diff --git a/core/java/android/os/BugreportManager.java b/core/java/android/os/BugreportManager.java
index 684369a..672624c 100644
--- a/core/java/android/os/BugreportManager.java
+++ b/core/java/android/os/BugreportManager.java
@@ -17,6 +17,7 @@
package android.os;
import android.annotation.CallbackExecutor;
+import android.annotation.FloatRange;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -39,7 +40,7 @@
*/
@SystemApi
@SystemService(Context.BUGREPORT_SERVICE)
-public class BugreportManager {
+public final class BugreportManager {
private final Context mContext;
private final IDumpstate mBinder;
@@ -90,7 +91,7 @@
* Called when there is a progress update.
* @param progress the progress in [0.0, 100.0]
*/
- public void onProgress(float progress) {}
+ public void onProgress(@FloatRange(from = 0f, to = 100f) float progress) {}
/**
* Called when taking bugreport resulted in an error.
diff --git a/core/java/android/os/BugreportParams.java b/core/java/android/os/BugreportParams.java
index 3871375..279ccae 100644
--- a/core/java/android/os/BugreportParams.java
+++ b/core/java/android/os/BugreportParams.java
@@ -41,6 +41,7 @@
/**
* Defines acceptable types of bugreports.
+ * @hide
*/
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = { "BUGREPORT_MODE_" }, value = {
diff --git a/core/java/com/android/internal/widget/MediaNotificationView.java b/core/java/com/android/internal/widget/MediaNotificationView.java
index de86d92..e7d240a 100644
--- a/core/java/com/android/internal/widget/MediaNotificationView.java
+++ b/core/java/com/android/internal/widget/MediaNotificationView.java
@@ -126,6 +126,9 @@
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
if (mImagePushIn > 0) {
+ if (this.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) {
+ mImagePushIn *= -1;
+ }
mRightIcon.layout(mRightIcon.getLeft() + mImagePushIn, mRightIcon.getTop(),
mRightIcon.getRight() + mImagePushIn, mRightIcon.getBottom());
}
diff --git a/core/res/res/layout/notification_material_media_seekbar.xml b/core/res/res/layout/notification_material_media_seekbar.xml
index c23ca83..4aa8acc 100644
--- a/core/res/res/layout/notification_material_media_seekbar.xml
+++ b/core/res/res/layout/notification_material_media_seekbar.xml
@@ -50,7 +50,7 @@
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_marginStart="@dimen/notification_content_margin_start"
- android:gravity="left"
+ android:gravity="start"
/>
<TextView android:id="@+id/notification_media_total_time"
@@ -59,7 +59,7 @@
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_marginEnd="@dimen/notification_content_margin_end"
- android:gravity="right"
+ android:gravity="end"
/>
</FrameLayout>
</LinearLayout>
\ No newline at end of file
diff --git a/core/res/res/values-night/values.xml b/core/res/res/values-night/values.xml
index a2ad3b9..4e6b712 100644
--- a/core/res/res/values-night/values.xml
+++ b/core/res/res/values-night/values.xml
@@ -24,6 +24,7 @@
<item name="colorError">@color/error_color_device_default_dark</item>
<item name="colorControlNormal">?attr/textColorPrimary</item>
<item name="alertDialogTheme">@style/Theme.DeviceDefault.Dialog.Alert</item>
+ <item name="forceDarkAllowed">false</item>
<!-- QS panel background -->
<item name="colorBackgroundFloating">@color/black</item>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index b7f594e..442ad7e 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -3943,4 +3943,8 @@
<!-- The default peak refresh rate for a given device. Change this value if you want to allow
for higher refresh rates to be automatically used out of the box -->
<integer name="config_defaultPeakRefreshRate">60</integer>
+
+ <!-- The type of the light sensor to be used by the display framework for things like
+ auto-brightness. If unset, then it just gets the default sensor of type TYPE_LIGHT. -->
+ <string name="config_displayLightSensorType" translatable="false" />
</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 96a3d96..c7e19c5 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3693,5 +3693,9 @@
<java-symbol type="string" name="mime_type_presentation" />
<java-symbol type="string" name="mime_type_presentation_ext" />
+ <!-- For high refresh rate displays -->
<java-symbol type="integer" name="config_defaultPeakRefreshRate" />
+
+ <!-- For Auto-Brightness -->
+ <java-symbol type="string" name="config_displayLightSensorType" />
</resources>
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index 793dd8d..4f1b2a4 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -69,6 +69,7 @@
"libminikin",
"libandroidfw",
"libcrypto",
+ "libsync",
],
static_libs: [
"libEGL_blobCache",
@@ -180,6 +181,7 @@
"renderthread/EglManager.cpp",
"renderthread/ReliableSurface.cpp",
"renderthread/VulkanManager.cpp",
+ "renderthread/VulkanSurface.cpp",
"renderthread/RenderProxy.cpp",
"renderthread/RenderTask.cpp",
"renderthread/RenderThread.cpp",
diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
index 87cffb5..edde6d3 100644
--- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
@@ -55,20 +55,8 @@
}
Frame SkiaVulkanPipeline::getFrame() {
- LOG_ALWAYS_FATAL_IF(mVkSurface == nullptr,
- "drawRenderNode called on a context with no surface!");
-
- SkSurface* backBuffer = mVkManager.getBackbufferSurface(&mVkSurface);
- LOG_ALWAYS_FATAL_IF(mVkSurface == nullptr,
- "drawRenderNode called on a context with an invalid surface");
- if (backBuffer == nullptr) {
- SkDebugf("failed to get backbuffer");
- return Frame(-1, -1, 0);
- }
-
- Frame frame(mVkSurface->windowWidth(), mVkSurface->windowHeight(),
- mVkManager.getAge(mVkSurface));
- return frame;
+ LOG_ALWAYS_FATAL_IF(mVkSurface == nullptr, "getFrame() called on a context with no surface!");
+ return mVkManager.dequeueNextBuffer(mVkSurface);
}
bool SkiaVulkanPipeline::draw(const Frame& frame, const SkRect& screenDirty, const SkRect& dirty,
@@ -77,13 +65,13 @@
bool opaque, const LightInfo& lightInfo,
const std::vector<sp<RenderNode>>& renderNodes,
FrameInfoVisualizer* profiler) {
- sk_sp<SkSurface> backBuffer = mVkSurface->getBackBufferSurface();
+ sk_sp<SkSurface> backBuffer = mVkSurface->getCurrentSkSurface();
if (backBuffer.get() == nullptr) {
return false;
}
SkiaPipeline::updateLighting(lightGeometry, lightInfo);
renderFrame(*layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds,
- backBuffer, mVkSurface->preTransform());
+ backBuffer, mVkSurface->getCurrentPreTransform());
ShaderCache::get().onVkFrameFlushed(mRenderThread.getGrContext());
layerUpdateQueue->clear();
@@ -113,7 +101,7 @@
currentFrameInfo->markSwapBuffers();
if (*requireSwap) {
- mVkManager.swapBuffers(mVkSurface);
+ mVkManager.swapBuffers(mVkSurface, screenDirty);
}
return *requireSwap;
diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h
index 2c24edd..77a7ab1 100644
--- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h
+++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h
@@ -18,6 +18,7 @@
#include "SkiaPipeline.h"
#include "renderthread/VulkanManager.h"
+#include "renderthread/VulkanSurface.h"
#include "renderstate/RenderState.h"
diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp
index 5af660c..d4c6eae 100644
--- a/libs/hwui/renderthread/VulkanManager.cpp
+++ b/libs/hwui/renderthread/VulkanManager.cpp
@@ -16,6 +16,7 @@
#include "VulkanManager.h"
+#include <android/sync.h>
#include <gui/Surface.h>
#include "Properties.h"
@@ -23,6 +24,7 @@
#include "renderstate/RenderState.h"
#include "utils/FatVector.h"
+#include <GrBackendSemaphore.h>
#include <GrBackendSurface.h>
#include <GrContext.h>
#include <GrTypes.h>
@@ -142,6 +144,7 @@
GET_INST_PROC(GetPhysicalDeviceProperties);
GET_INST_PROC(GetPhysicalDeviceQueueFamilyProperties);
GET_INST_PROC(GetPhysicalDeviceFeatures2);
+ GET_INST_PROC(GetPhysicalDeviceImageFormatProperties2);
GET_INST_PROC(CreateDevice);
GET_INST_PROC(EnumerateDeviceExtensionProperties);
GET_INST_PROC(CreateAndroidSurfaceKHR);
@@ -318,11 +321,6 @@
GET_DEV_PROC(GetDeviceQueue);
GET_DEV_PROC(DeviceWaitIdle);
GET_DEV_PROC(DestroyDevice);
- GET_DEV_PROC(CreateSwapchainKHR);
- GET_DEV_PROC(DestroySwapchainKHR);
- GET_DEV_PROC(GetSwapchainImagesKHR);
- GET_DEV_PROC(AcquireNextImageKHR);
- GET_DEV_PROC(QueuePresentKHR);
GET_DEV_PROC(CreateCommandPool);
GET_DEV_PROC(DestroyCommandPool);
GET_DEV_PROC(AllocateCommandBuffers);
@@ -426,201 +424,102 @@
};
}
-// Returns the next BackbufferInfo to use for the next draw. The function will make sure all
-// previous uses have finished before returning.
-VulkanSurface::BackbufferInfo* VulkanManager::getAvailableBackbuffer(VulkanSurface* surface) {
- SkASSERT(surface->mBackbuffers);
+Frame VulkanManager::dequeueNextBuffer(VulkanSurface* surface) {
- ++surface->mCurrentBackbufferIndex;
- if (surface->mCurrentBackbufferIndex > surface->mImageCount) {
- surface->mCurrentBackbufferIndex = 0;
+ VulkanSurface::NativeBufferInfo* bufferInfo = surface->dequeueNativeBuffer();
+
+ if (bufferInfo == nullptr) {
+ ALOGE("VulkanSurface::dequeueNativeBuffer called with an invalid surface!");
+ return Frame(-1, -1, 0);
}
- VulkanSurface::BackbufferInfo* backbuffer =
- surface->mBackbuffers + surface->mCurrentBackbufferIndex;
+ LOG_ALWAYS_FATAL_IF(!bufferInfo->dequeued);
- // Before we reuse a backbuffer, make sure its fences have all signaled so that we can safely
- // reuse its commands buffers.
- VkResult res = mWaitForFences(mDevice, 2, backbuffer->mUsageFences, true, UINT64_MAX);
- if (res != VK_SUCCESS) {
- return nullptr;
+ if (bufferInfo->dequeue_fence != -1) {
+ int fence_clone = dup(bufferInfo->dequeue_fence);
+ if (fence_clone == -1) {
+ ALOGE("dup(fence) failed, stalling until signalled: %s (%d)", strerror(errno), errno);
+ sync_wait(bufferInfo->dequeue_fence, -1 /* forever */);
+ } else {
+ VkSemaphoreCreateInfo semaphoreInfo;
+ semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
+ semaphoreInfo.pNext = nullptr;
+ semaphoreInfo.flags = 0;
+ VkSemaphore semaphore;
+ VkResult err = mCreateSemaphore(mDevice, &semaphoreInfo, nullptr, &semaphore);
+ LOG_ALWAYS_FATAL_IF(VK_SUCCESS != err, "Failed to create import semaphore, err: %d",
+ err);
+
+ VkImportSemaphoreFdInfoKHR importInfo;
+ importInfo.sType = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR;
+ importInfo.pNext = nullptr;
+ importInfo.semaphore = semaphore;
+ importInfo.flags = VK_SEMAPHORE_IMPORT_TEMPORARY_BIT;
+ importInfo.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;
+ importInfo.fd = fence_clone;
+
+ err = mImportSemaphoreFdKHR(mDevice, &importInfo);
+ LOG_ALWAYS_FATAL_IF(VK_SUCCESS != err, "Failed to import semaphore, err: %d", err);
+
+ GrBackendSemaphore backendSemaphore;
+ backendSemaphore.initVulkan(semaphore);
+ bufferInfo->skSurface->wait(1, &backendSemaphore);
+ }
}
- return backbuffer;
+ int bufferAge = (mSwapBehavior == SwapBehavior::Discard) ? 0 : surface->getCurrentBuffersAge();
+ return Frame(surface->logicalWidth(), surface->logicalHeight(), bufferAge);
}
-static SkMatrix getPreTransformMatrix(int width, int height,
- VkSurfaceTransformFlagBitsKHR transform) {
- switch (transform) {
- case VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR:
- return SkMatrix::I();
- case VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR:
- return SkMatrix::MakeAll(0, -1, height, 1, 0, 0, 0, 0, 1);
- case VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR:
- return SkMatrix::MakeAll(-1, 0, width, 0, -1, height, 0, 0, 1);
- case VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR:
- return SkMatrix::MakeAll(0, 1, 0, -1, 0, width, 0, 0, 1);
- case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR:
- return SkMatrix::MakeAll(-1, 0, width, 0, 1, 0, 0, 0, 1);
- case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR:
- return SkMatrix::MakeAll(0, -1, height, -1, 0, width, 0, 0, 1);
- case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR:
- return SkMatrix::MakeAll(1, 0, 0, 0, -1, height, 0, 0, 1);
- case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR:
- return SkMatrix::MakeAll(0, 1, 0, 1, 0, 0, 0, 0, 1);
- default:
- LOG_ALWAYS_FATAL("Unsupported pre transform of swapchain.");
- }
- return SkMatrix::I();
-}
-
-
-SkSurface* VulkanManager::getBackbufferSurface(VulkanSurface** surfaceOut) {
- // Recreate VulkanSurface, if ANativeWindow has been resized.
- VulkanSurface* surface = *surfaceOut;
- int windowWidth = 0, windowHeight = 0;
- ANativeWindow* window = surface->mNativeWindow;
- window->query(window, NATIVE_WINDOW_WIDTH, &windowWidth);
- window->query(window, NATIVE_WINDOW_HEIGHT, &windowHeight);
- if (windowWidth != surface->mWindowWidth || windowHeight != surface->mWindowHeight) {
- ColorMode colorMode = surface->mColorMode;
- sk_sp<SkColorSpace> colorSpace = surface->mColorSpace;
- SkColorType colorType = surface->mColorType;
- GrContext* grContext = surface->mGrContext;
- destroySurface(surface);
- *surfaceOut = createSurface(window, colorMode, colorSpace, colorType, grContext);
- surface = *surfaceOut;
- if (!surface) {
- return nullptr;
- }
+void VulkanManager::swapBuffers(VulkanSurface* surface, const SkRect& dirtyRect) {
+ if (CC_UNLIKELY(Properties::waitForGpuCompletion)) {
+ ATRACE_NAME("Finishing GPU work");
+ mDeviceWaitIdle(mDevice);
}
- VulkanSurface::BackbufferInfo* backbuffer = getAvailableBackbuffer(surface);
- SkASSERT(backbuffer);
+ VkExportSemaphoreCreateInfo exportInfo;
+ exportInfo.sType = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO;
+ exportInfo.pNext = nullptr;
+ exportInfo.handleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;
- VkResult res;
+ VkSemaphoreCreateInfo semaphoreInfo;
+ semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
+ semaphoreInfo.pNext = &exportInfo;
+ semaphoreInfo.flags = 0;
+ VkSemaphore semaphore;
+ VkResult err = mCreateSemaphore(mDevice, &semaphoreInfo, nullptr, &semaphore);
+ ALOGE_IF(VK_SUCCESS != err, "VulkanManager::swapBuffers(): Failed to create semaphore");
- res = mResetFences(mDevice, 2, backbuffer->mUsageFences);
- SkASSERT(VK_SUCCESS == res);
+ GrBackendSemaphore backendSemaphore;
+ backendSemaphore.initVulkan(semaphore);
- // The acquire will signal the attached mAcquireSemaphore. We use this to know the image has
- // finished presenting and that it is safe to begin sending new commands to the returned image.
- res = mAcquireNextImageKHR(mDevice, surface->mSwapchain, UINT64_MAX,
- backbuffer->mAcquireSemaphore, VK_NULL_HANDLE,
- &backbuffer->mImageIndex);
+ VulkanSurface::NativeBufferInfo* bufferInfo = surface->getCurrentBufferInfo();
- if (VK_ERROR_SURFACE_LOST_KHR == res) {
- // need to figure out how to create a new vkSurface without the platformData*
- // maybe use attach somehow? but need a Window
- return nullptr;
- }
- if (VK_ERROR_OUT_OF_DATE_KHR == res || VK_SUBOPTIMAL_KHR == res) {
- // tear swapchain down and try again
- if (!createSwapchain(surface)) {
- return nullptr;
- }
- backbuffer = getAvailableBackbuffer(surface);
- res = mResetFences(mDevice, 2, backbuffer->mUsageFences);
- SkASSERT(VK_SUCCESS == res);
+ int fenceFd = -1;
+ GrSemaphoresSubmitted submitted =
+ bufferInfo->skSurface->flush(SkSurface::BackendSurfaceAccess::kPresent,
+ SkSurface::kNone_FlushFlags, 1, &backendSemaphore);
+ if (submitted == GrSemaphoresSubmitted::kYes) {
+ VkSemaphoreGetFdInfoKHR getFdInfo;
+ getFdInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR;
+ getFdInfo.pNext = nullptr;
+ getFdInfo.semaphore = semaphore;
+ getFdInfo.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;
- // acquire the image
- res = mAcquireNextImageKHR(mDevice, surface->mSwapchain, UINT64_MAX,
- backbuffer->mAcquireSemaphore, VK_NULL_HANDLE,
- &backbuffer->mImageIndex);
-
- if (VK_SUCCESS != res) {
- return nullptr;
- }
+ err = mGetSemaphoreFdKHR(mDevice, &getFdInfo, &fenceFd);
+ ALOGE_IF(VK_SUCCESS != err, "VulkanManager::swapBuffers(): Failed to get semaphore Fd");
+ } else {
+ ALOGE("VulkanManager::swapBuffers(): Semaphore submission failed");
+ mQueueWaitIdle(mGraphicsQueue);
}
- // set up layout transfer from initial to color attachment
- VkImageLayout layout = surface->mImageInfos[backbuffer->mImageIndex].mImageLayout;
- SkASSERT(VK_IMAGE_LAYOUT_UNDEFINED == layout || VK_IMAGE_LAYOUT_PRESENT_SRC_KHR == layout);
- VkPipelineStageFlags srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
- VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
- VkAccessFlags srcAccessMask = 0;
- VkAccessFlags dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
- VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+ surface->presentCurrentBuffer(dirtyRect, fenceFd);
- VkImageMemoryBarrier imageMemoryBarrier = {
- VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType
- NULL, // pNext
- srcAccessMask, // outputMask
- dstAccessMask, // inputMask
- layout, // oldLayout
- VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // newLayout
- mPresentQueueIndex, // srcQueueFamilyIndex
- mGraphicsQueueIndex, // dstQueueFamilyIndex
- surface->mImages[backbuffer->mImageIndex], // image
- {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1} // subresourceRange
- };
- mResetCommandBuffer(backbuffer->mTransitionCmdBuffers[0], 0);
-
- VkCommandBufferBeginInfo info;
- memset(&info, 0, sizeof(VkCommandBufferBeginInfo));
- info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
- info.flags = 0;
- mBeginCommandBuffer(backbuffer->mTransitionCmdBuffers[0], &info);
-
- mCmdPipelineBarrier(backbuffer->mTransitionCmdBuffers[0], srcStageMask, dstStageMask, 0, 0,
- nullptr, 0, nullptr, 1, &imageMemoryBarrier);
-
- mEndCommandBuffer(backbuffer->mTransitionCmdBuffers[0]);
-
- VkPipelineStageFlags waitDstStageFlags = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
- // insert the layout transfer into the queue and wait on the acquire
- VkSubmitInfo submitInfo;
- memset(&submitInfo, 0, sizeof(VkSubmitInfo));
- submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
- submitInfo.waitSemaphoreCount = 1;
- // Wait to make sure aquire semaphore set above has signaled.
- submitInfo.pWaitSemaphores = &backbuffer->mAcquireSemaphore;
- submitInfo.pWaitDstStageMask = &waitDstStageFlags;
- submitInfo.commandBufferCount = 1;
- submitInfo.pCommandBuffers = &backbuffer->mTransitionCmdBuffers[0];
- submitInfo.signalSemaphoreCount = 0;
-
- // Attach first fence to submission here so we can track when the command buffer finishes.
- mQueueSubmit(mGraphicsQueue, 1, &submitInfo, backbuffer->mUsageFences[0]);
-
- // We need to notify Skia that we changed the layout of the wrapped VkImage
- sk_sp<SkSurface> skSurface = surface->mImageInfos[backbuffer->mImageIndex].mSurface;
- GrBackendRenderTarget backendRT = skSurface->getBackendRenderTarget(
- SkSurface::kFlushRead_BackendHandleAccess);
- if (!backendRT.isValid()) {
- SkASSERT(backendRT.isValid());
- return nullptr;
- }
- backendRT.setVkImageLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
-
- surface->mPreTransform = getPreTransformMatrix(surface->windowWidth(),
- surface->windowHeight(),
- surface->mTransform);
-
- surface->mBackbuffer = std::move(skSurface);
- return surface->mBackbuffer.get();
-}
-
-void VulkanManager::destroyBuffers(VulkanSurface* surface) {
- if (surface->mBackbuffers) {
- for (uint32_t i = 0; i < surface->mImageCount + 1; ++i) {
- mWaitForFences(mDevice, 2, surface->mBackbuffers[i].mUsageFences, true, UINT64_MAX);
- surface->mBackbuffers[i].mImageIndex = -1;
- mDestroySemaphore(mDevice, surface->mBackbuffers[i].mAcquireSemaphore, nullptr);
- mDestroySemaphore(mDevice, surface->mBackbuffers[i].mRenderSemaphore, nullptr);
- mFreeCommandBuffers(mDevice, mCommandPool, 2,
- surface->mBackbuffers[i].mTransitionCmdBuffers);
- mDestroyFence(mDevice, surface->mBackbuffers[i].mUsageFences[0], 0);
- mDestroyFence(mDevice, surface->mBackbuffers[i].mUsageFences[1], 0);
- }
- }
-
- delete[] surface->mBackbuffers;
- surface->mBackbuffers = nullptr;
- delete[] surface->mImageInfos;
- surface->mImageInfos = nullptr;
- delete[] surface->mImages;
- surface->mImages = nullptr;
+ // Exporting a semaphore with copy transference via vkGetSemaphoreFdKHR, has the same effect of
+ // destroying the semaphore and creating a new one with the same handle, and the payloads
+ // ownership is move to the Fd we created. Thus the semaphore is in a state that we can delete
+ // it and we don't need to wait on the command buffer we submitted to finish.
+ mDestroySemaphore(mDevice, semaphore, nullptr);
}
void VulkanManager::destroySurface(VulkanSurface* surface) {
@@ -630,271 +529,9 @@
}
mDeviceWaitIdle(mDevice);
- destroyBuffers(surface);
-
- if (VK_NULL_HANDLE != surface->mSwapchain) {
- mDestroySwapchainKHR(mDevice, surface->mSwapchain, nullptr);
- surface->mSwapchain = VK_NULL_HANDLE;
- }
-
- if (VK_NULL_HANDLE != surface->mVkSurface) {
- mDestroySurfaceKHR(mInstance, surface->mVkSurface, nullptr);
- surface->mVkSurface = VK_NULL_HANDLE;
- }
delete surface;
}
-void VulkanManager::createBuffers(VulkanSurface* surface, VkFormat format, VkExtent2D extent) {
- mGetSwapchainImagesKHR(mDevice, surface->mSwapchain, &surface->mImageCount, nullptr);
- SkASSERT(surface->mImageCount);
- surface->mImages = new VkImage[surface->mImageCount];
- mGetSwapchainImagesKHR(mDevice, surface->mSwapchain, &surface->mImageCount, surface->mImages);
-
- SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
-
- // set up initial image layouts and create surfaces
- surface->mImageInfos = new VulkanSurface::ImageInfo[surface->mImageCount];
- for (uint32_t i = 0; i < surface->mImageCount; ++i) {
- GrVkImageInfo info;
- info.fImage = surface->mImages[i];
- info.fAlloc = GrVkAlloc();
- info.fImageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
- info.fImageTiling = VK_IMAGE_TILING_OPTIMAL;
- info.fFormat = format;
- info.fLevelCount = 1;
-
- GrBackendRenderTarget backendRT(extent.width, extent.height, 0, 0, info);
-
- VulkanSurface::ImageInfo& imageInfo = surface->mImageInfos[i];
- imageInfo.mSurface = SkSurface::MakeFromBackendRenderTarget(
- surface->mGrContext, backendRT, kTopLeft_GrSurfaceOrigin,
- surface->mColorType, surface->mColorSpace, &props);
- }
-
- SkASSERT(mCommandPool != VK_NULL_HANDLE);
-
- // set up the backbuffers
- VkSemaphoreCreateInfo semaphoreInfo;
- memset(&semaphoreInfo, 0, sizeof(VkSemaphoreCreateInfo));
- semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
- semaphoreInfo.pNext = nullptr;
- semaphoreInfo.flags = 0;
- VkCommandBufferAllocateInfo commandBuffersInfo;
- memset(&commandBuffersInfo, 0, sizeof(VkCommandBufferAllocateInfo));
- commandBuffersInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
- commandBuffersInfo.pNext = nullptr;
- commandBuffersInfo.commandPool = mCommandPool;
- commandBuffersInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
- commandBuffersInfo.commandBufferCount = 2;
- VkFenceCreateInfo fenceInfo;
- memset(&fenceInfo, 0, sizeof(VkFenceCreateInfo));
- fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
- fenceInfo.pNext = nullptr;
- fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
-
- // we create one additional backbuffer structure here, because we want to
- // give the command buffers they contain a chance to finish before we cycle back
- surface->mBackbuffers = new VulkanSurface::BackbufferInfo[surface->mImageCount + 1];
- for (uint32_t i = 0; i < surface->mImageCount + 1; ++i) {
- SkDEBUGCODE(VkResult res);
- surface->mBackbuffers[i].mImageIndex = -1;
- SkDEBUGCODE(res =) mCreateSemaphore(mDevice, &semaphoreInfo, nullptr,
- &surface->mBackbuffers[i].mAcquireSemaphore);
- SkDEBUGCODE(res =) mCreateSemaphore(mDevice, &semaphoreInfo, nullptr,
- &surface->mBackbuffers[i].mRenderSemaphore);
- SkDEBUGCODE(res =) mAllocateCommandBuffers(mDevice, &commandBuffersInfo,
- surface->mBackbuffers[i].mTransitionCmdBuffers);
- SkDEBUGCODE(res =) mCreateFence(mDevice, &fenceInfo, nullptr,
- &surface->mBackbuffers[i].mUsageFences[0]);
- SkDEBUGCODE(res =) mCreateFence(mDevice, &fenceInfo, nullptr,
- &surface->mBackbuffers[i].mUsageFences[1]);
- SkASSERT(VK_SUCCESS == res);
- }
- surface->mCurrentBackbufferIndex = surface->mImageCount;
-}
-
-bool VulkanManager::createSwapchain(VulkanSurface* surface) {
- // check for capabilities
- VkSurfaceCapabilitiesKHR caps;
- VkResult res = mGetPhysicalDeviceSurfaceCapabilitiesKHR(mPhysicalDevice,
- surface->mVkSurface, &caps);
- if (VK_SUCCESS != res) {
- return false;
- }
-
- uint32_t surfaceFormatCount;
- res = mGetPhysicalDeviceSurfaceFormatsKHR(mPhysicalDevice, surface->mVkSurface,
- &surfaceFormatCount, nullptr);
- if (VK_SUCCESS != res) {
- return false;
- }
-
- FatVector<VkSurfaceFormatKHR, 4> surfaceFormats(surfaceFormatCount);
- res = mGetPhysicalDeviceSurfaceFormatsKHR(mPhysicalDevice, surface->mVkSurface,
- &surfaceFormatCount, surfaceFormats.data());
- if (VK_SUCCESS != res) {
- return false;
- }
-
- uint32_t presentModeCount;
- res = mGetPhysicalDeviceSurfacePresentModesKHR(mPhysicalDevice,
- surface->mVkSurface, &presentModeCount, nullptr);
- if (VK_SUCCESS != res) {
- return false;
- }
-
- FatVector<VkPresentModeKHR, VK_PRESENT_MODE_RANGE_SIZE_KHR> presentModes(presentModeCount);
- res = mGetPhysicalDeviceSurfacePresentModesKHR(mPhysicalDevice,
- surface->mVkSurface, &presentModeCount,
- presentModes.data());
- if (VK_SUCCESS != res) {
- return false;
- }
-
- if (!SkToBool(caps.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR)) {
- return false;
- }
- VkSurfaceTransformFlagBitsKHR transform;
- if (SkToBool(caps.supportedTransforms & caps.currentTransform) &&
- !SkToBool(caps.currentTransform & VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR)) {
- transform = caps.currentTransform;
- } else {
- transform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
- }
-
- VkExtent2D extent = caps.currentExtent;
- // clamp width; to handle currentExtent of -1 and protect us from broken hints
- if (extent.width < caps.minImageExtent.width) {
- extent.width = caps.minImageExtent.width;
- }
- SkASSERT(extent.width <= caps.maxImageExtent.width);
- // clamp height
- if (extent.height < caps.minImageExtent.height) {
- extent.height = caps.minImageExtent.height;
- }
- SkASSERT(extent.height <= caps.maxImageExtent.height);
-
- VkExtent2D swapExtent = extent;
- if (transform == VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR ||
- transform == VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR ||
- transform == VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR ||
- transform == VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR) {
- swapExtent.width = extent.height;
- swapExtent.height = extent.width;
- }
-
- surface->mWindowWidth = extent.width;
- surface->mWindowHeight = extent.height;
-
- uint32_t imageCount = std::max<uint32_t>(3, caps.minImageCount);
- if (caps.maxImageCount > 0 && imageCount > caps.maxImageCount) {
- // Application must settle for fewer images than desired:
- imageCount = caps.maxImageCount;
- }
-
- // Currently Skia requires the images to be color attchments and support all transfer
- // operations.
- VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
- VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
- VK_IMAGE_USAGE_TRANSFER_DST_BIT;
- SkASSERT((caps.supportedUsageFlags & usageFlags) == usageFlags);
-
- SkASSERT(caps.supportedCompositeAlpha &
- (VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR | VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR));
- VkCompositeAlphaFlagBitsKHR composite_alpha =
- (caps.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR)
- ? VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR
- : VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
-
- VkFormat surfaceFormat = VK_FORMAT_R8G8B8A8_UNORM;
- VkColorSpaceKHR colorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
- if (surface->mColorType == SkColorType::kRGBA_F16_SkColorType) {
- surfaceFormat = VK_FORMAT_R16G16B16A16_SFLOAT;
- }
-
- if (surface->mColorMode == ColorMode::WideColorGamut) {
- skcms_Matrix3x3 surfaceGamut;
- LOG_ALWAYS_FATAL_IF(!surface->mColorSpace->toXYZD50(&surfaceGamut),
- "Could not get gamut matrix from color space");
- if (memcmp(&surfaceGamut, &SkNamedGamut::kSRGB, sizeof(surfaceGamut)) == 0) {
- colorSpace = VK_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR_EXT;
- } else if (memcmp(&surfaceGamut, &SkNamedGamut::kDCIP3, sizeof(surfaceGamut)) == 0) {
- colorSpace = VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT;
- } else {
- LOG_ALWAYS_FATAL("Unreachable: unsupported wide color space.");
- }
- }
-
- bool foundSurfaceFormat = false;
- for (uint32_t i = 0; i < surfaceFormatCount; ++i) {
- if (surfaceFormat == surfaceFormats[i].format
- && colorSpace == surfaceFormats[i].colorSpace) {
- foundSurfaceFormat = true;
- break;
- }
- }
-
- if (!foundSurfaceFormat) {
- return false;
- }
-
- // FIFO is always available and will match what we do on GL so just pick that here.
- VkPresentModeKHR mode = VK_PRESENT_MODE_FIFO_KHR;
-
- VkSwapchainCreateInfoKHR swapchainCreateInfo;
- memset(&swapchainCreateInfo, 0, sizeof(VkSwapchainCreateInfoKHR));
- swapchainCreateInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
- swapchainCreateInfo.surface = surface->mVkSurface;
- swapchainCreateInfo.minImageCount = imageCount;
- swapchainCreateInfo.imageFormat = surfaceFormat;
- swapchainCreateInfo.imageColorSpace = colorSpace;
- swapchainCreateInfo.imageExtent = swapExtent;
- swapchainCreateInfo.imageArrayLayers = 1;
- swapchainCreateInfo.imageUsage = usageFlags;
-
- uint32_t queueFamilies[] = {mGraphicsQueueIndex, mPresentQueueIndex};
- if (mGraphicsQueueIndex != mPresentQueueIndex) {
- swapchainCreateInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
- swapchainCreateInfo.queueFamilyIndexCount = 2;
- swapchainCreateInfo.pQueueFamilyIndices = queueFamilies;
- } else {
- swapchainCreateInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
- swapchainCreateInfo.queueFamilyIndexCount = 0;
- swapchainCreateInfo.pQueueFamilyIndices = nullptr;
- }
-
- swapchainCreateInfo.preTransform = transform;
- swapchainCreateInfo.compositeAlpha = composite_alpha;
- swapchainCreateInfo.presentMode = mode;
- swapchainCreateInfo.clipped = true;
- swapchainCreateInfo.oldSwapchain = surface->mSwapchain;
-
- res = mCreateSwapchainKHR(mDevice, &swapchainCreateInfo, nullptr, &surface->mSwapchain);
- if (VK_SUCCESS != res) {
- return false;
- }
-
- surface->mTransform = transform;
-
- // destroy the old swapchain
- if (swapchainCreateInfo.oldSwapchain != VK_NULL_HANDLE) {
- mDeviceWaitIdle(mDevice);
-
- destroyBuffers(surface);
-
- mDestroySwapchainKHR(mDevice, swapchainCreateInfo.oldSwapchain, nullptr);
- }
-
- createBuffers(surface, surfaceFormat, swapExtent);
-
- // The window content is not updated (frozen) until a buffer of the window size is received.
- // This prevents temporary stretching of the window after it is resized, but before the first
- // buffer with new size is enqueued.
- native_window_set_scaling_mode(surface->mNativeWindow, NATIVE_WINDOW_SCALING_MODE_FREEZE);
-
- return true;
-}
-
VulkanSurface* VulkanManager::createSurface(ANativeWindow* window, ColorMode colorMode,
sk_sp<SkColorSpace> surfaceColorSpace,
SkColorType surfaceColorType,
@@ -904,185 +541,8 @@
return nullptr;
}
- VulkanSurface* surface = new VulkanSurface(colorMode, window, surfaceColorSpace,
- surfaceColorType, grContext);
-
- VkAndroidSurfaceCreateInfoKHR surfaceCreateInfo;
- memset(&surfaceCreateInfo, 0, sizeof(VkAndroidSurfaceCreateInfoKHR));
- surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR;
- surfaceCreateInfo.pNext = nullptr;
- surfaceCreateInfo.flags = 0;
- surfaceCreateInfo.window = window;
-
- VkResult res = mCreateAndroidSurfaceKHR(mInstance, &surfaceCreateInfo, nullptr,
- &surface->mVkSurface);
- if (VK_SUCCESS != res) {
- delete surface;
- return nullptr;
- }
-
- SkDEBUGCODE(VkBool32 supported; res = mGetPhysicalDeviceSurfaceSupportKHR(
- mPhysicalDevice, mPresentQueueIndex, surface->mVkSurface, &supported);
- // All physical devices and queue families on Android must be capable of
- // presentation with any native window.
- SkASSERT(VK_SUCCESS == res && supported););
-
- if (!createSwapchain(surface)) {
- destroySurface(surface);
- return nullptr;
- }
-
- return surface;
-}
-
-// Helper to know which src stage flags we need to set when transitioning to the present layout
-static VkPipelineStageFlags layoutToPipelineSrcStageFlags(const VkImageLayout layout) {
- if (VK_IMAGE_LAYOUT_GENERAL == layout) {
- return VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
- } else if (VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL == layout ||
- VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL == layout) {
- return VK_PIPELINE_STAGE_TRANSFER_BIT;
- } else if (VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL == layout) {
- return VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
- } else if (VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL == layout ||
- VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL == layout) {
- return VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
- } else if (VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL == layout) {
- return VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
- } else if (VK_IMAGE_LAYOUT_PREINITIALIZED == layout) {
- return VK_PIPELINE_STAGE_HOST_BIT;
- }
-
- SkASSERT(VK_IMAGE_LAYOUT_UNDEFINED == layout);
- return VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
-}
-
-// Helper to know which src access mask we need to set when transitioning to the present layout
-static VkAccessFlags layoutToSrcAccessMask(const VkImageLayout layout) {
- VkAccessFlags flags = 0;
- if (VK_IMAGE_LAYOUT_GENERAL == layout) {
- flags = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
- VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT |
- VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_HOST_WRITE_BIT |
- VK_ACCESS_HOST_READ_BIT;
- } else if (VK_IMAGE_LAYOUT_PREINITIALIZED == layout) {
- flags = VK_ACCESS_HOST_WRITE_BIT;
- } else if (VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL == layout) {
- flags = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
- } else if (VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL == layout) {
- flags = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
- } else if (VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL == layout) {
- flags = VK_ACCESS_TRANSFER_WRITE_BIT;
- } else if (VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL == layout) {
- flags = VK_ACCESS_TRANSFER_READ_BIT;
- } else if (VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL == layout) {
- flags = VK_ACCESS_SHADER_READ_BIT;
- }
- return flags;
-}
-
-void VulkanManager::swapBuffers(VulkanSurface* surface) {
- if (CC_UNLIKELY(Properties::waitForGpuCompletion)) {
- ATRACE_NAME("Finishing GPU work");
- mDeviceWaitIdle(mDevice);
- }
-
- SkASSERT(surface->mBackbuffers);
- VulkanSurface::BackbufferInfo* backbuffer =
- surface->mBackbuffers + surface->mCurrentBackbufferIndex;
-
- SkSurface* skSurface = surface->mImageInfos[backbuffer->mImageIndex].mSurface.get();
- GrBackendRenderTarget backendRT = skSurface->getBackendRenderTarget(
- SkSurface::kFlushRead_BackendHandleAccess);
- SkASSERT(backendRT.isValid());
-
- GrVkImageInfo imageInfo;
- SkAssertResult(backendRT.getVkImageInfo(&imageInfo));
-
- // Check to make sure we never change the actually wrapped image
- SkASSERT(imageInfo.fImage == surface->mImages[backbuffer->mImageIndex]);
-
- // We need to transition the image to VK_IMAGE_LAYOUT_PRESENT_SRC_KHR and make sure that all
- // previous work is complete for before presenting. So we first add the necessary barrier here.
- VkImageLayout layout = imageInfo.fImageLayout;
- VkPipelineStageFlags srcStageMask = layoutToPipelineSrcStageFlags(layout);
- VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
- VkAccessFlags srcAccessMask = layoutToSrcAccessMask(layout);
- VkAccessFlags dstAccessMask = 0;
-
- VkImageMemoryBarrier imageMemoryBarrier = {
- VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType
- NULL, // pNext
- srcAccessMask, // outputMask
- dstAccessMask, // inputMask
- layout, // oldLayout
- VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, // newLayout
- mGraphicsQueueIndex, // srcQueueFamilyIndex
- mPresentQueueIndex, // dstQueueFamilyIndex
- surface->mImages[backbuffer->mImageIndex], // image
- {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1} // subresourceRange
- };
-
- mResetCommandBuffer(backbuffer->mTransitionCmdBuffers[1], 0);
- VkCommandBufferBeginInfo info;
- memset(&info, 0, sizeof(VkCommandBufferBeginInfo));
- info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
- info.flags = 0;
- mBeginCommandBuffer(backbuffer->mTransitionCmdBuffers[1], &info);
- mCmdPipelineBarrier(backbuffer->mTransitionCmdBuffers[1], srcStageMask, dstStageMask, 0, 0,
- nullptr, 0, nullptr, 1, &imageMemoryBarrier);
- mEndCommandBuffer(backbuffer->mTransitionCmdBuffers[1]);
-
- surface->mImageInfos[backbuffer->mImageIndex].mImageLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
-
- // insert the layout transfer into the queue and wait on the acquire
- VkSubmitInfo submitInfo;
- memset(&submitInfo, 0, sizeof(VkSubmitInfo));
- submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
- submitInfo.waitSemaphoreCount = 0;
- submitInfo.pWaitDstStageMask = 0;
- submitInfo.commandBufferCount = 1;
- submitInfo.pCommandBuffers = &backbuffer->mTransitionCmdBuffers[1];
- submitInfo.signalSemaphoreCount = 1;
- // When this command buffer finishes we will signal this semaphore so that we know it is now
- // safe to present the image to the screen.
- submitInfo.pSignalSemaphores = &backbuffer->mRenderSemaphore;
-
- // Attach second fence to submission here so we can track when the command buffer finishes.
- mQueueSubmit(mGraphicsQueue, 1, &submitInfo, backbuffer->mUsageFences[1]);
-
- // Submit present operation to present queue. We use a semaphore here to make sure all rendering
- // to the image is complete and that the layout has been change to present on the graphics
- // queue.
- const VkPresentInfoKHR presentInfo = {
- VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, // sType
- NULL, // pNext
- 1, // waitSemaphoreCount
- &backbuffer->mRenderSemaphore, // pWaitSemaphores
- 1, // swapchainCount
- &surface->mSwapchain, // pSwapchains
- &backbuffer->mImageIndex, // pImageIndices
- NULL // pResults
- };
-
- mQueuePresentKHR(mPresentQueue, &presentInfo);
-
- surface->mBackbuffer.reset();
- surface->mImageInfos[backbuffer->mImageIndex].mLastUsed = surface->mCurrentTime;
- surface->mImageInfos[backbuffer->mImageIndex].mInvalid = false;
- surface->mCurrentTime++;
-}
-
-int VulkanManager::getAge(VulkanSurface* surface) {
- SkASSERT(surface->mBackbuffers);
- VulkanSurface::BackbufferInfo* backbuffer =
- surface->mBackbuffers + surface->mCurrentBackbufferIndex;
- if (mSwapBehavior == SwapBehavior::Discard ||
- surface->mImageInfos[backbuffer->mImageIndex].mInvalid) {
- return 0;
- }
- uint16_t lastUsed = surface->mImageInfos[backbuffer->mImageIndex].mLastUsed;
- return surface->mCurrentTime - lastUsed;
+ return VulkanSurface::Create(window, colorMode, surfaceColorType, surfaceColorSpace, grContext,
+ *this);
}
bool VulkanManager::setupDummyCommandBuffer() {
diff --git a/libs/hwui/renderthread/VulkanManager.h b/libs/hwui/renderthread/VulkanManager.h
index 95c9630..c3d2891 100644
--- a/libs/hwui/renderthread/VulkanManager.h
+++ b/libs/hwui/renderthread/VulkanManager.h
@@ -28,7 +28,9 @@
#include <ui/Fence.h>
#include <utils/StrongPointer.h>
#include <vk/GrVkBackendContext.h>
+#include "Frame.h"
#include "IRenderPipeline.h"
+#include "VulkanSurface.h"
class GrVkExtensions;
@@ -38,66 +40,6 @@
class RenderThread;
-class VulkanSurface {
-public:
- VulkanSurface(ColorMode colorMode, ANativeWindow* window, sk_sp<SkColorSpace> colorSpace,
- SkColorType colorType, GrContext* grContext)
- : mColorMode(colorMode), mNativeWindow(window), mColorSpace(colorSpace),
- mColorType(colorType), mGrContext(grContext) {}
-
- sk_sp<SkSurface> getBackBufferSurface() { return mBackbuffer; }
-
- // The width and height are are the logical width and height for when submitting draws to the
- // surface. In reality if the window is rotated the underlying VkImage may have the width and
- // height swapped.
- int windowWidth() const { return mWindowWidth; }
- int windowHeight() const { return mWindowHeight; }
-
- SkMatrix& preTransform() { return mPreTransform; }
-
-private:
- friend class VulkanManager;
- struct BackbufferInfo {
- uint32_t mImageIndex; // image this is associated with
- VkSemaphore mAcquireSemaphore; // we signal on this for acquisition of image
- VkSemaphore mRenderSemaphore; // we wait on this for rendering to be done
- VkCommandBuffer
- mTransitionCmdBuffers[2]; // to transition layout between present and render
- // We use these fences to make sure the above Command buffers have finished their work
- // before attempting to reuse them or destroy them.
- VkFence mUsageFences[2];
- };
-
- struct ImageInfo {
- VkImageLayout mImageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
- sk_sp<SkSurface> mSurface;
- uint16_t mLastUsed = 0;
- bool mInvalid = true;
- };
-
- sk_sp<SkSurface> mBackbuffer;
-
- VkSurfaceKHR mVkSurface = VK_NULL_HANDLE;
- VkSwapchainKHR mSwapchain = VK_NULL_HANDLE;
-
- BackbufferInfo* mBackbuffers = nullptr;
- uint32_t mCurrentBackbufferIndex;
-
- uint32_t mImageCount;
- VkImage* mImages = nullptr;
- ImageInfo* mImageInfos;
- uint16_t mCurrentTime = 0;
- ColorMode mColorMode;
- ANativeWindow* mNativeWindow;
- int mWindowWidth = 0;
- int mWindowHeight = 0;
- sk_sp<SkColorSpace> mColorSpace;
- SkColorType mColorType;
- VkSurfaceTransformFlagBitsKHR mTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
- SkMatrix mPreTransform;
- GrContext* mGrContext;
-};
-
// This class contains the shared global Vulkan objects, such as VkInstance, VkDevice and VkQueue,
// which are re-used by CanvasContext. This class is created once and should be used by all vulkan
// windowing contexts. The VulkanManager must be initialized before use.
@@ -114,33 +56,19 @@
// Quick check to see if the VulkanManager has been initialized.
bool hasVkContext() { return mDevice != VK_NULL_HANDLE; }
- // Given a window this creates a new VkSurfaceKHR and VkSwapchain and stores them inside a new
- // VulkanSurface object which is returned.
+ // Create and destroy functions for wrapping an ANativeWindow in a VulkanSurface
VulkanSurface* createSurface(ANativeWindow* window, ColorMode colorMode,
sk_sp<SkColorSpace> surfaceColorSpace,
SkColorType surfaceColorType,
GrContext* grContext);
-
- // Destroy the VulkanSurface and all associated vulkan objects.
void destroySurface(VulkanSurface* surface);
+ Frame dequeueNextBuffer(VulkanSurface* surface);
+ void swapBuffers(VulkanSurface* surface, const SkRect& dirtyRect);
+
// Cleans up all the global state in the VulkanManger.
void destroy();
- // No work is needed to make a VulkanSurface current, and all functions require that a
- // VulkanSurface is passed into them so we just return true here.
- bool isCurrent(VulkanSurface* surface) { return true; }
-
- int getAge(VulkanSurface* surface);
-
- // Returns an SkSurface which wraps the next image returned from vkAcquireNextImageKHR. It also
- // will transition the VkImage from a present layout to color attachment so that it can be used
- // by the client for drawing.
- SkSurface* getBackbufferSurface(VulkanSurface** surface);
-
- // Presents the current VkImage.
- void swapBuffers(VulkanSurface* surface);
-
// Inserts a wait on fence command into the Vulkan command buffer.
status_t fenceWait(sp<Fence>& fence);
@@ -153,17 +81,10 @@
sk_sp<GrContext> createContext(const GrContextOptions& options);
private:
+ friend class VulkanSurface;
// Sets up the VkInstance and VkDevice objects. Also fills out the passed in
// VkPhysicalDeviceFeatures struct.
void setupDevice(GrVkExtensions&, VkPhysicalDeviceFeatures2&);
-
- void destroyBuffers(VulkanSurface* surface);
-
- bool createSwapchain(VulkanSurface* surface);
- void createBuffers(VulkanSurface* surface, VkFormat format, VkExtent2D extent);
-
- VulkanSurface::BackbufferInfo* getAvailableBackbuffer(VulkanSurface* surface);
-
bool setupDummyCommandBuffer();
// simple wrapper class that exists only to initialize a pointer to NULL
@@ -190,13 +111,6 @@
VkPtr<PFN_vkGetPhysicalDeviceSurfaceFormatsKHR> mGetPhysicalDeviceSurfaceFormatsKHR;
VkPtr<PFN_vkGetPhysicalDeviceSurfacePresentModesKHR> mGetPhysicalDeviceSurfacePresentModesKHR;
- VkPtr<PFN_vkCreateSwapchainKHR> mCreateSwapchainKHR;
- VkPtr<PFN_vkDestroySwapchainKHR> mDestroySwapchainKHR;
- VkPtr<PFN_vkGetSwapchainImagesKHR> mGetSwapchainImagesKHR;
- VkPtr<PFN_vkAcquireNextImageKHR> mAcquireNextImageKHR;
- VkPtr<PFN_vkQueuePresentKHR> mQueuePresentKHR;
- VkPtr<PFN_vkCreateSharedSwapchainsKHR> mCreateSharedSwapchainsKHR;
-
// Instance Functions
VkPtr<PFN_vkEnumerateInstanceVersion> mEnumerateInstanceVersion;
VkPtr<PFN_vkEnumerateInstanceExtensionProperties> mEnumerateInstanceExtensionProperties;
@@ -207,6 +121,7 @@
VkPtr<PFN_vkGetPhysicalDeviceProperties> mGetPhysicalDeviceProperties;
VkPtr<PFN_vkGetPhysicalDeviceQueueFamilyProperties> mGetPhysicalDeviceQueueFamilyProperties;
VkPtr<PFN_vkGetPhysicalDeviceFeatures2> mGetPhysicalDeviceFeatures2;
+ VkPtr<PFN_vkGetPhysicalDeviceImageFormatProperties2> mGetPhysicalDeviceImageFormatProperties2;
VkPtr<PFN_vkCreateDevice> mCreateDevice;
VkPtr<PFN_vkEnumerateDeviceExtensionProperties> mEnumerateDeviceExtensionProperties;
diff --git a/libs/hwui/renderthread/VulkanSurface.cpp b/libs/hwui/renderthread/VulkanSurface.cpp
new file mode 100644
index 0000000..c03c3a8
--- /dev/null
+++ b/libs/hwui/renderthread/VulkanSurface.cpp
@@ -0,0 +1,536 @@
+/*
+ * 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.
+ */
+
+#include "VulkanSurface.h"
+
+#include <algorithm>
+#include <SkSurface.h>
+
+#include "VulkanManager.h"
+#include "utils/TraceUtils.h"
+#include "utils/Color.h"
+
+namespace android {
+namespace uirenderer {
+namespace renderthread {
+
+static bool IsTransformSupported(int transform) {
+ // For now, only support pure rotations, not flip or flip-and-rotate, until we have
+ // more time to test them and build sample code. As far as I know we never actually
+ // use anything besides pure rotations anyway.
+ return transform == 0
+ || transform == NATIVE_WINDOW_TRANSFORM_ROT_90
+ || transform == NATIVE_WINDOW_TRANSFORM_ROT_180
+ || transform == NATIVE_WINDOW_TRANSFORM_ROT_270;
+}
+
+static int InvertTransform(int transform) {
+ switch (transform) {
+ case NATIVE_WINDOW_TRANSFORM_ROT_90:
+ return NATIVE_WINDOW_TRANSFORM_ROT_270;
+ case NATIVE_WINDOW_TRANSFORM_ROT_180:
+ return NATIVE_WINDOW_TRANSFORM_ROT_180;
+ case NATIVE_WINDOW_TRANSFORM_ROT_270:
+ return NATIVE_WINDOW_TRANSFORM_ROT_90;
+ default:
+ return 0;
+ }
+}
+
+static int ConvertVkTransformToNative(VkSurfaceTransformFlagsKHR transform) {
+ switch (transform) {
+ case VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR:
+ return NATIVE_WINDOW_TRANSFORM_ROT_270;
+ case VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR:
+ return NATIVE_WINDOW_TRANSFORM_ROT_180;
+ case VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR:
+ return NATIVE_WINDOW_TRANSFORM_ROT_90;
+ case VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR:
+ case VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR:
+ default:
+ return 0;
+ }
+}
+
+static SkMatrix GetPreTransformMatrix(SkISize windowSize, int transform) {
+ const int width = windowSize.width();
+ const int height = windowSize.height();
+
+ switch (transform) {
+ case 0:
+ return SkMatrix::I();
+ case NATIVE_WINDOW_TRANSFORM_ROT_90:
+ return SkMatrix::MakeAll(0, -1, height, 1, 0, 0, 0, 0, 1);
+ case NATIVE_WINDOW_TRANSFORM_ROT_180:
+ return SkMatrix::MakeAll(-1, 0, width, 0, -1, height, 0, 0, 1);
+ case NATIVE_WINDOW_TRANSFORM_ROT_270:
+ return SkMatrix::MakeAll(0, 1, 0, -1, 0, width, 0, 0, 1);
+ default:
+ LOG_ALWAYS_FATAL("Unsupported Window Transform (%d)", transform);
+ }
+ return SkMatrix::I();
+}
+
+void VulkanSurface::ComputeWindowSizeAndTransform(WindowInfo* windowInfo, const SkISize& minSize,
+ const SkISize& maxSize) {
+ SkISize& windowSize = windowInfo->size;
+
+ // clamp width & height to handle currentExtent of -1 and protect us from broken hints
+ if (windowSize.width() < minSize.width() || windowSize.width() > maxSize.width()
+ || windowSize.height() < minSize.height() || windowSize.height() > maxSize.height()) {
+ int width = std::min(maxSize.width(), std::max(minSize.width(), windowSize.width()));
+ int height = std::min(maxSize.height(), std::max(minSize.height(), windowSize.height()));
+ ALOGE("Invalid Window Dimensions [%d, %d]; clamping to [%d, %d]",
+ windowSize.width(), windowSize.height(), width, height);
+ windowSize.set(width, height);
+ }
+
+ windowInfo->actualSize = windowSize;
+ if (windowInfo->transform & HAL_TRANSFORM_ROT_90) {
+ windowInfo->actualSize.set(windowSize.height(), windowSize.width());
+ }
+
+ windowInfo->preTransform = GetPreTransformMatrix(windowInfo->size, windowInfo->transform);
+}
+
+static bool ResetNativeWindow(ANativeWindow* window) {
+ // -- Reset the native window --
+ // The native window might have been used previously, and had its properties
+ // changed from defaults. That will affect the answer we get for queries
+ // like MIN_UNDEQUEUED_BUFFERS. Reset to a known/default state before we
+ // attempt such queries.
+
+ int err = native_window_api_connect(window, NATIVE_WINDOW_API_EGL);
+ if (err != 0) {
+ ALOGW("native_window_api_connect failed: %s (%d)", strerror(-err), err);
+ return false;
+ }
+
+ // this will match what we do on GL so pick that here.
+ err = window->setSwapInterval(window, 1);
+ if (err != 0) {
+ ALOGW("native_window->setSwapInterval(1) failed: %s (%d)", strerror(-err), err);
+ return false;
+ }
+
+ err = native_window_set_shared_buffer_mode(window, false);
+ if (err != 0) {
+ ALOGW("native_window_set_shared_buffer_mode(false) failed: %s (%d)", strerror(-err), err);
+ return false;
+ }
+
+ err = native_window_set_auto_refresh(window, false);
+ if (err != 0) {
+ ALOGW("native_window_set_auto_refresh(false) failed: %s (%d)", strerror(-err), err);
+ return false;
+ }
+
+ return true;
+}
+
+class VkSurfaceAutoDeleter {
+public:
+ VkSurfaceAutoDeleter(VkInstance instance, VkSurfaceKHR surface,
+ PFN_vkDestroySurfaceKHR destroySurfaceKHR)
+ : mInstance(instance)
+ , mSurface(surface)
+ , mDestroySurfaceKHR(destroySurfaceKHR) {}
+ ~VkSurfaceAutoDeleter() {
+ destroy();
+ }
+
+ void destroy() {
+ if (mSurface != VK_NULL_HANDLE) {
+ mDestroySurfaceKHR(mInstance, mSurface, nullptr);
+ mSurface = VK_NULL_HANDLE;
+ }
+ }
+
+private:
+ VkInstance mInstance;
+ VkSurfaceKHR mSurface;
+ PFN_vkDestroySurfaceKHR mDestroySurfaceKHR;
+};
+
+VulkanSurface* VulkanSurface::Create(ANativeWindow* window, ColorMode colorMode,
+ SkColorType colorType, sk_sp<SkColorSpace> colorSpace,
+ GrContext* grContext, const VulkanManager& vkManager) {
+
+ VkAndroidSurfaceCreateInfoKHR surfaceCreateInfo;
+ memset(&surfaceCreateInfo, 0, sizeof(VkAndroidSurfaceCreateInfoKHR));
+ surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR;
+ surfaceCreateInfo.pNext = nullptr;
+ surfaceCreateInfo.flags = 0;
+ surfaceCreateInfo.window = window;
+
+ VkSurfaceKHR vkSurface = VK_NULL_HANDLE;
+ VkResult res = vkManager.mCreateAndroidSurfaceKHR(vkManager.mInstance, &surfaceCreateInfo,
+ nullptr, &vkSurface);
+ if (VK_SUCCESS != res) {
+ ALOGE("VulkanSurface::Create() vkCreateAndroidSurfaceKHR failed (%d)", res);
+ return nullptr;
+ }
+
+ VkSurfaceAutoDeleter vkSurfaceDeleter(vkManager.mInstance, vkSurface,
+ vkManager.mDestroySurfaceKHR);
+
+ SkDEBUGCODE(VkBool32 supported; res = vkManager.mGetPhysicalDeviceSurfaceSupportKHR(
+ vkManager.mPhysicalDevice, vkManager.mPresentQueueIndex, vkSurface, &supported);
+ // All physical devices and queue families on Android must be capable of
+ // presentation with any native window.
+ SkASSERT(VK_SUCCESS == res && supported););
+
+ // check for capabilities
+ VkSurfaceCapabilitiesKHR caps;
+ res = vkManager.mGetPhysicalDeviceSurfaceCapabilitiesKHR(vkManager.mPhysicalDevice, vkSurface,
+ &caps);
+ if (VK_SUCCESS != res) {
+ ALOGE("VulkanSurface::Create() vkGetPhysicalDeviceSurfaceCapabilitiesKHR failed (%d)", res);
+ return nullptr;
+ }
+
+ LOG_ALWAYS_FATAL_IF(0 == (caps.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR));
+
+ /*
+ * We must destroy the VK Surface before attempting to update the window as doing so after
+ * will cause the native window to be modified in unexpected ways.
+ */
+ vkSurfaceDeleter.destroy();
+
+ /*
+ * Populate Window Info struct
+ */
+ WindowInfo windowInfo;
+
+ windowInfo.transform = ConvertVkTransformToNative(caps.supportedTransforms);
+ windowInfo.size = SkISize::Make(caps.currentExtent.width, caps.currentExtent.height);
+
+ const SkISize minSize = SkISize::Make(caps.minImageExtent.width, caps.minImageExtent.height);
+ const SkISize maxSize = SkISize::Make(caps.maxImageExtent.width, caps.maxImageExtent.height);
+ ComputeWindowSizeAndTransform(&windowInfo, minSize, maxSize);
+
+ windowInfo.bufferCount = std::max<uint32_t>(VulkanSurface::sMaxBufferCount, caps.minImageCount);
+ if (caps.maxImageCount > 0 && windowInfo.bufferCount > caps.maxImageCount) {
+ // Application must settle for fewer images than desired:
+ windowInfo.bufferCount = caps.maxImageCount;
+ }
+
+ // Currently Skia requires the images to be color attachments and support all transfer
+ // operations.
+ VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
+ VK_IMAGE_USAGE_SAMPLED_BIT |
+ VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
+ VK_IMAGE_USAGE_TRANSFER_DST_BIT;
+ LOG_ALWAYS_FATAL_IF((caps.supportedUsageFlags & usageFlags) != usageFlags);
+
+ windowInfo.dataspace = HAL_DATASPACE_V0_SRGB;
+ if (colorMode == ColorMode::WideColorGamut) {
+ skcms_Matrix3x3 surfaceGamut;
+ LOG_ALWAYS_FATAL_IF(!colorSpace->toXYZD50(&surfaceGamut),
+ "Could not get gamut matrix from color space");
+ if (memcmp(&surfaceGamut, &SkNamedGamut::kSRGB, sizeof(surfaceGamut)) == 0) {
+ windowInfo.dataspace = HAL_DATASPACE_V0_SCRGB;
+ } else if (memcmp(&surfaceGamut, &SkNamedGamut::kDCIP3, sizeof(surfaceGamut)) == 0) {
+ windowInfo.dataspace = HAL_DATASPACE_DISPLAY_P3;
+ } else {
+ LOG_ALWAYS_FATAL("Unreachable: unsupported wide color space.");
+ }
+ }
+
+ windowInfo.pixelFormat = ColorTypeToPixelFormat(colorType);
+ VkFormat vkPixelFormat = VK_FORMAT_R8G8B8A8_UNORM;
+ if (windowInfo.pixelFormat == PIXEL_FORMAT_RGBA_FP16) {
+ vkPixelFormat = VK_FORMAT_R16G16B16A16_SFLOAT;
+ }
+
+ uint64_t producerUsage =
+ AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER | AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
+ uint64_t consumerUsage;
+ native_window_get_consumer_usage(window, &consumerUsage);
+ windowInfo.windowUsageFlags = consumerUsage | producerUsage;
+
+ /*
+ * Now we attempt to modify the window!
+ */
+ if (!UpdateWindow(window, windowInfo)) {
+ return nullptr;
+ }
+
+ return new VulkanSurface(window, windowInfo, minSize, maxSize, grContext);
+}
+
+bool VulkanSurface::UpdateWindow(ANativeWindow* window, const WindowInfo& windowInfo) {
+ ATRACE_CALL();
+
+ if (!ResetNativeWindow(window)) {
+ return false;
+ }
+
+ // -- Configure the native window --
+ int err = native_window_set_buffers_format(window, windowInfo.pixelFormat);
+ if (err != 0) {
+ ALOGE("VulkanSurface::UpdateWindow() native_window_set_buffers_format(%d) failed: %s (%d)",
+ windowInfo.pixelFormat, strerror(-err), err);
+ return false;
+ }
+
+ err = native_window_set_buffers_data_space(window, windowInfo.dataspace);
+ if (err != 0) {
+ ALOGE("VulkanSurface::UpdateWindow() native_window_set_buffers_data_space(%d) "
+ "failed: %s (%d)", windowInfo.dataspace, strerror(-err), err);
+ return false;
+ }
+
+ const SkISize& size = windowInfo.actualSize;
+ err = native_window_set_buffers_dimensions(window, size.width(), size.height());
+ if (err != 0) {
+ ALOGE("VulkanSurface::UpdateWindow() native_window_set_buffers_dimensions(%d,%d) "
+ "failed: %s (%d)", size.width(), size.height(), strerror(-err), err);
+ return false;
+ }
+
+ // native_window_set_buffers_transform() expects the transform the app is requesting that
+ // the compositor perform during composition. With native windows, pre-transform works by
+ // rendering with the same transform the compositor is applying (as in Vulkan), but
+ // then requesting the inverse transform, so that when the compositor does
+ // it's job the two transforms cancel each other out and the compositor ends
+ // up applying an identity transform to the app's buffer.
+ err = native_window_set_buffers_transform(window, InvertTransform(windowInfo.transform));
+ if (err != 0) {
+ ALOGE("VulkanSurface::UpdateWindow() native_window_set_buffers_transform(%d) "
+ "failed: %s (%d)", windowInfo.transform, strerror(-err), err);
+ return false;
+ }
+
+ // Vulkan defaults to NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW, but this is different than
+ // HWUI's expectation
+ err = native_window_set_scaling_mode(window, NATIVE_WINDOW_SCALING_MODE_FREEZE);
+ if (err != 0) {
+ ALOGE("VulkanSurface::UpdateWindow() native_window_set_scaling_mode(SCALE_TO_WINDOW) "
+ "failed: %s (%d)", strerror(-err), err);
+ return false;
+ }
+
+ // Lower layer insists that we have at least two buffers.
+ err = native_window_set_buffer_count(window, std::max(2, windowInfo.bufferCount));
+ if (err != 0) {
+ ALOGE("VulkanSurface::UpdateWindow() native_window_set_buffer_count(%d) failed: %s (%d)",
+ windowInfo.bufferCount, strerror(-err), err);
+ return false;
+ }
+
+ err = native_window_set_usage(window, windowInfo.windowUsageFlags);
+ if (err != 0) {
+ ALOGE("VulkanSurface::UpdateWindow() native_window_set_usage failed: %s (%d)",
+ strerror(-err), err);
+ return false;
+ }
+
+ return err == 0;
+}
+
+VulkanSurface::VulkanSurface(ANativeWindow* window, const WindowInfo& windowInfo,
+ SkISize minWindowSize, SkISize maxWindowSize, GrContext* grContext)
+ : mNativeWindow(window)
+ , mWindowInfo(windowInfo)
+ , mGrContext(grContext)
+ , mMinWindowSize(minWindowSize)
+ , mMaxWindowSize(maxWindowSize) { }
+
+VulkanSurface::~VulkanSurface() {
+ releaseBuffers();
+
+ // release the native window to be available for use by other clients
+ int err = native_window_api_disconnect(mNativeWindow.get(), NATIVE_WINDOW_API_EGL);
+ ALOGW_IF(err != 0, "native_window_api_disconnect failed: %s (%d)", strerror(-err), err);
+}
+
+void VulkanSurface::releaseBuffers() {
+ for (uint32_t i = 0; i < VulkanSurface::sMaxBufferCount; i++) {
+ VulkanSurface::NativeBufferInfo& bufferInfo = mNativeBuffers[i];
+
+ if (bufferInfo.buffer.get() != nullptr && bufferInfo.dequeued) {
+ int err = mNativeWindow->cancelBuffer(mNativeWindow.get(), bufferInfo.buffer.get(),
+ bufferInfo.dequeue_fence);
+ if (err != 0) {
+ ALOGE("cancelBuffer[%u] failed during destroy: %s (%d)", i, strerror(-err), err);
+ }
+ bufferInfo.dequeued = false;
+
+ if (bufferInfo.dequeue_fence >= 0) {
+ close(bufferInfo.dequeue_fence);
+ bufferInfo.dequeue_fence = -1;
+ }
+ }
+
+ LOG_ALWAYS_FATAL_IF(bufferInfo.dequeued);
+ LOG_ALWAYS_FATAL_IF(bufferInfo.dequeue_fence != -1);
+
+ bufferInfo.skSurface.reset();
+ bufferInfo.buffer.clear();
+ bufferInfo.hasValidContents = false;
+ bufferInfo.lastPresentedCount = 0;
+ }
+}
+
+VulkanSurface::NativeBufferInfo* VulkanSurface::dequeueNativeBuffer() {
+ // Set the dequeue index to invalid in case of error and only reset it to the correct
+ // value at the end of the function if everything dequeued correctly.
+ mDequeuedIndex = -1;
+
+ //check if the native window has been resized or rotated and update accordingly
+ SkISize newSize = SkISize::MakeEmpty();
+ int transformHint = 0;
+ mNativeWindow->query(mNativeWindow.get(), NATIVE_WINDOW_WIDTH, &newSize.fWidth);
+ mNativeWindow->query(mNativeWindow.get(), NATIVE_WINDOW_HEIGHT, &newSize.fHeight);
+ mNativeWindow->query(mNativeWindow.get(), NATIVE_WINDOW_TRANSFORM_HINT, &transformHint);
+ if (newSize != mWindowInfo.actualSize || transformHint != mWindowInfo.transform) {
+ WindowInfo newWindowInfo = mWindowInfo;
+ newWindowInfo.size = newSize;
+ newWindowInfo.transform = IsTransformSupported(transformHint) ? transformHint : 0;
+ ComputeWindowSizeAndTransform(&newWindowInfo, mMinWindowSize, mMaxWindowSize);
+
+ int err = 0;
+ if (newWindowInfo.actualSize != mWindowInfo.actualSize) {
+ // reset the native buffers and update the window
+ err = native_window_set_buffers_dimensions(mNativeWindow.get(),
+ newWindowInfo.actualSize.width(),
+ newWindowInfo.actualSize.height());
+ if (err != 0) {
+ ALOGE("native_window_set_buffers_dimensions(%d,%d) failed: %s (%d)",
+ newWindowInfo.actualSize.width(),
+ newWindowInfo.actualSize.height(), strerror(-err), err);
+ return nullptr;
+ }
+ // reset the NativeBufferInfo (including SkSurface) associated with the old buffers. The
+ // new NativeBufferInfo storage will be populated lazily as we dequeue each new buffer.
+ releaseBuffers();
+ // TODO should we ask the nativewindow to allocate buffers?
+ }
+
+ if (newWindowInfo.transform != mWindowInfo.transform) {
+ err = native_window_set_buffers_transform(mNativeWindow.get(),
+ InvertTransform(newWindowInfo.transform));
+ if (err != 0) {
+ ALOGE("native_window_set_buffers_transform(%d) failed: %s (%d)",
+ newWindowInfo.transform, strerror(-err), err);
+ newWindowInfo.transform = mWindowInfo.transform;
+ ComputeWindowSizeAndTransform(&newWindowInfo, mMinWindowSize, mMaxWindowSize);
+ }
+ }
+
+ mWindowInfo = newWindowInfo;
+ }
+
+ ANativeWindowBuffer* buffer;
+ int fence_fd;
+ int err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buffer, &fence_fd);
+ if (err != 0) {
+ ALOGE("dequeueBuffer failed: %s (%d)", strerror(-err), err);
+ return nullptr;
+ }
+
+ uint32_t idx;
+ for (idx = 0; idx < mWindowInfo.bufferCount; idx++) {
+ if (mNativeBuffers[idx].buffer.get() == buffer) {
+ mNativeBuffers[idx].dequeued = true;
+ mNativeBuffers[idx].dequeue_fence = fence_fd;
+ break;
+ } else if (mNativeBuffers[idx].buffer.get() == nullptr) {
+ // increasing the number of buffers we have allocated
+ mNativeBuffers[idx].buffer = buffer;
+ mNativeBuffers[idx].dequeued = true;
+ mNativeBuffers[idx].dequeue_fence = fence_fd;
+ break;
+ }
+ }
+ if (idx == mWindowInfo.bufferCount) {
+ ALOGE("dequeueBuffer returned unrecognized buffer");
+ mNativeWindow->cancelBuffer(mNativeWindow.get(), buffer, fence_fd);
+ return nullptr;
+ }
+
+ VulkanSurface::NativeBufferInfo* bufferInfo = &mNativeBuffers[idx];
+
+ if (bufferInfo->skSurface.get() == nullptr) {
+ bufferInfo->skSurface =
+ SkSurface::MakeFromAHardwareBuffer(mGrContext,
+ ANativeWindowBuffer_getHardwareBuffer(bufferInfo->buffer.get()),
+ kTopLeft_GrSurfaceOrigin, DataSpaceToColorSpace(mWindowInfo.dataspace),
+ nullptr);
+ if (bufferInfo->skSurface.get() == nullptr) {
+ ALOGE("SkSurface::MakeFromAHardwareBuffer failed");
+ mNativeWindow->cancelBuffer(mNativeWindow.get(), buffer, fence_fd);
+ return nullptr;
+ }
+ }
+
+ mDequeuedIndex = idx;
+ return bufferInfo;
+}
+
+bool VulkanSurface::presentCurrentBuffer(const SkRect& dirtyRect, int semaphoreFd) {
+ if (!dirtyRect.isEmpty()) {
+ SkRect transformedRect;
+ mWindowInfo.preTransform.mapRect(&transformedRect, dirtyRect);
+
+ SkIRect transformedIRect;
+ transformedRect.roundOut(&transformedIRect);
+ transformedIRect.intersect(0, 0, mWindowInfo.size.fWidth, mWindowInfo.size.fHeight);
+
+ // map to bottom-left coordinate system
+ android_native_rect_t aRect;
+ aRect.left = transformedIRect.x();
+ aRect.top = mWindowInfo.size.fHeight - (transformedIRect.y() + transformedIRect.height());
+ aRect.right = aRect.left + transformedIRect.width();
+ aRect.bottom = aRect.top - transformedIRect.height();
+
+ int err = native_window_set_surface_damage(mNativeWindow.get(), &aRect, 1);
+ ALOGE_IF(err != 0, "native_window_set_surface_damage failed: %s (%d)", strerror(-err), err);
+ }
+
+ VulkanSurface::NativeBufferInfo& currentBuffer = mNativeBuffers[mDequeuedIndex];
+ int queuedFd = (semaphoreFd != -1) ? semaphoreFd : currentBuffer.dequeue_fence;
+ int err = mNativeWindow->queueBuffer(mNativeWindow.get(), currentBuffer.buffer.get(), queuedFd);
+
+ currentBuffer.dequeued = false;
+ // queueBuffer always closes fence, even on error
+ if (err != 0) {
+ ALOGE("queueBuffer failed: %s (%d)", strerror(-err), err);
+ mNativeWindow->cancelBuffer(mNativeWindow.get(), currentBuffer.buffer.get(),
+ currentBuffer.dequeue_fence);
+ } else {
+ currentBuffer.hasValidContents = true;
+ currentBuffer.lastPresentedCount = mPresentCount;
+ mPresentCount++;
+ }
+
+ if (currentBuffer.dequeue_fence >= 0) {
+ close(currentBuffer.dequeue_fence);
+ currentBuffer.dequeue_fence = -1;
+ }
+
+ return err == 0;
+}
+
+int VulkanSurface::getCurrentBuffersAge() {
+ VulkanSurface::NativeBufferInfo& currentBuffer = mNativeBuffers[mDequeuedIndex];
+ return currentBuffer.hasValidContents ? (mPresentCount - currentBuffer.lastPresentedCount) : 0;
+}
+
+} /* namespace renderthread */
+} /* namespace uirenderer */
+} /* namespace android */
diff --git a/libs/hwui/renderthread/VulkanSurface.h b/libs/hwui/renderthread/VulkanSurface.h
new file mode 100644
index 0000000..4fd9cd2
--- /dev/null
+++ b/libs/hwui/renderthread/VulkanSurface.h
@@ -0,0 +1,127 @@
+/*
+ * 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.
+ */
+#pragma once
+
+#include <system/graphics.h>
+#include <system/window.h>
+#include <vulkan/vulkan.h>
+
+#include <SkSize.h>
+#include <SkRefCnt.h>
+
+#include "IRenderPipeline.h"
+
+class SkSurface;
+
+namespace android {
+namespace uirenderer {
+namespace renderthread {
+
+class VulkanManager;
+
+class VulkanSurface {
+public:
+ static VulkanSurface* Create(ANativeWindow* window,
+ ColorMode colorMode,
+ SkColorType colorType,
+ sk_sp<SkColorSpace> colorSpace,
+ GrContext* grContext,
+ const VulkanManager& vkManager);
+ ~VulkanSurface();
+
+ sk_sp<SkSurface> getCurrentSkSurface() { return mNativeBuffers[mDequeuedIndex].skSurface; }
+ const SkMatrix& getCurrentPreTransform() { return mWindowInfo.preTransform; }
+
+private:
+ /*
+ * All structs/methods in this private section are specifically for use by the VulkanManager
+ *
+ */
+ friend VulkanManager;
+ struct NativeBufferInfo {
+ sk_sp<SkSurface> skSurface;
+ sp<ANativeWindowBuffer> buffer;
+ // The fence is only valid when the buffer is dequeued, and should be
+ // -1 any other time. When valid, we own the fd, and must ensure it is
+ // closed: either by closing it explicitly when queueing the buffer,
+ // or by passing ownership e.g. to ANativeWindow::cancelBuffer().
+ int dequeue_fence = -1;
+ bool dequeued = false;
+ uint32_t lastPresentedCount = 0;
+ bool hasValidContents = false;
+ };
+
+ NativeBufferInfo* dequeueNativeBuffer();
+ NativeBufferInfo* getCurrentBufferInfo() { return &mNativeBuffers[mDequeuedIndex]; }
+ bool presentCurrentBuffer(const SkRect& dirtyRect, int semaphoreFd);
+
+ // The width and height are are the logical width and height for when submitting draws to the
+ // surface. In reality if the window is rotated the underlying window may have the width and
+ // height swapped.
+ int logicalWidth() const { return mWindowInfo.size.width(); }
+ int logicalHeight() const { return mWindowInfo.size.height(); }
+ int getCurrentBuffersAge();
+
+private:
+ /*
+ * All code below this line while logically available to VulkanManager should not be treated
+ * as private to this class.
+ *
+ */
+ static constexpr int sMaxBufferCount = 3;
+
+ struct WindowInfo {
+ SkISize size;
+ PixelFormat pixelFormat;
+ android_dataspace dataspace;
+ int transform;
+ int bufferCount;
+ uint64_t windowUsageFlags;
+
+ // size of the ANativeWindow if the inverse of transform requires us to swap width/height
+ SkISize actualSize;
+ // transform to be applied to the SkSurface to map the coordinates to the provided transform
+ SkMatrix preTransform;
+ };
+
+ VulkanSurface(ANativeWindow* window,
+ const WindowInfo& windowInfo,
+ SkISize minWindowSize,
+ SkISize maxWindowSize,
+ GrContext* grContext);
+ static bool UpdateWindow(ANativeWindow* window,
+ const WindowInfo& windowInfo);
+ static void ComputeWindowSizeAndTransform(WindowInfo* windowInfo,
+ const SkISize& minSize,
+ const SkISize& maxSize);
+ void releaseBuffers();
+
+ NativeBufferInfo mNativeBuffers[VulkanSurface::sMaxBufferCount];
+
+ sp<ANativeWindow> mNativeWindow;
+ WindowInfo mWindowInfo;
+ GrContext* mGrContext;
+
+ int mDequeuedIndex = -1;
+ uint32_t mPresentCount = 0;
+
+ const SkISize mMinWindowSize;
+ const SkISize mMaxWindowSize;
+};
+
+} /* namespace renderthread */
+} /* namespace uirenderer */
+} /* namespace android */
\ No newline at end of file
diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java
index bc91ca3..4cd8971 100644
--- a/media/java/android/media/ExifInterface.java
+++ b/media/java/android/media/ExifInterface.java
@@ -73,6 +73,12 @@
* Supported formats are: JPEG, DNG, CR2, NEF, NRW, ARW, RW2, ORF, PEF, SRW, RAF and HEIF.
* <p>
* Attribute mutation is supported for JPEG image files.
+ * <p>
+ * Note: It is recommended to use the <a href="{@docRoot}jetpack/androidx.html">AndroidX</a>
+ * <a href="{@docRoot}reference/androidx/exifinterface/media/ExifInterface.html">ExifInterface
+ * Library</a> since it is a superset of this class. In addition to the functionalities of this
+ * class, it supports parsing extra metadata such as exposure and data compression information
+ * as well as setting extra metadata such as GPS and datetime information.
*/
public class ExifInterface {
private static final String TAG = "ExifInterface";
@@ -1316,14 +1322,14 @@
}
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
- private final String mFilename;
- private final FileDescriptor mSeekableFileDescriptor;
- private final AssetManager.AssetInputStream mAssetInputStream;
- private final boolean mIsInputStream;
+ private String mFilename;
+ private FileDescriptor mSeekableFileDescriptor;
+ private AssetManager.AssetInputStream mAssetInputStream;
+ private boolean mIsInputStream;
private int mMimeType;
@UnsupportedAppUsage
private final HashMap[] mAttributes = new HashMap[EXIF_TAGS.length];
- private Set<Integer> mAttributesOffsets = new HashSet<>(EXIF_TAGS.length);
+ private Set<Integer> mHandledIfdOffsets = new HashSet<>(EXIF_TAGS.length);
private ByteOrder mExifByteOrder = ByteOrder.BIG_ENDIAN;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
private boolean mHasThumbnail;
@@ -1350,7 +1356,10 @@
* Reads Exif tags from the specified image file.
*/
public ExifInterface(@NonNull File file) throws IOException {
- this(file.getAbsolutePath());
+ if (file == null) {
+ throw new NullPointerException("file cannot be null");
+ }
+ initForFilename(file.getName());
}
/**
@@ -1358,23 +1367,9 @@
*/
public ExifInterface(@NonNull String filename) throws IOException {
if (filename == null) {
- throw new IllegalArgumentException("filename cannot be null");
+ throw new NullPointerException("filename cannot be null");
}
- FileInputStream in = null;
- mAssetInputStream = null;
- mFilename = filename;
- mIsInputStream = false;
- try {
- in = new FileInputStream(filename);
- if (isSeekableFD(in.getFD())) {
- mSeekableFileDescriptor = in.getFD();
- } else {
- mSeekableFileDescriptor = null;
- }
- loadAttributes(in);
- } finally {
- IoUtils.closeQuietly(in);
- }
+ initForFilename(filename);
}
/**
@@ -1384,7 +1379,7 @@
*/
public ExifInterface(@NonNull FileDescriptor fileDescriptor) throws IOException {
if (fileDescriptor == null) {
- throw new IllegalArgumentException("fileDescriptor cannot be null");
+ throw new NullPointerException("fileDescriptor cannot be null");
}
mAssetInputStream = null;
mFilename = null;
@@ -1418,7 +1413,7 @@
*/
public ExifInterface(@NonNull InputStream inputStream) throws IOException {
if (inputStream == null) {
- throw new IllegalArgumentException("inputStream cannot be null");
+ throw new NullPointerException("inputStream cannot be null");
}
mFilename = null;
if (inputStream instanceof AssetManager.AssetInputStream) {
@@ -1443,6 +1438,9 @@
* @param tag the name of the tag.
*/
private @Nullable ExifAttribute getExifAttribute(@NonNull String tag) {
+ if (tag == null) {
+ throw new NullPointerException("tag shouldn't be null");
+ }
// Retrieves all tag groups. The value from primary image tag group has a higher priority
// than the value from the thumbnail tag group if there are more than one candidates.
for (int i = 0; i < EXIF_TAGS.length; ++i) {
@@ -1461,6 +1459,9 @@
* @param tag the name of the tag.
*/
public @Nullable String getAttribute(@NonNull String tag) {
+ if (tag == null) {
+ throw new NullPointerException("tag shouldn't be null");
+ }
ExifAttribute attribute = getExifAttribute(tag);
if (attribute != null) {
if (!sTagSetForCompatibility.contains(tag)) {
@@ -1499,6 +1500,9 @@
* @param defaultValue the value to return if the tag is not available.
*/
public int getAttributeInt(@NonNull String tag, int defaultValue) {
+ if (tag == null) {
+ throw new NullPointerException("tag shouldn't be null");
+ }
ExifAttribute exifAttribute = getExifAttribute(tag);
if (exifAttribute == null) {
return defaultValue;
@@ -1520,6 +1524,9 @@
* @param defaultValue the value to return if the tag is not available.
*/
public double getAttributeDouble(@NonNull String tag, double defaultValue) {
+ if (tag == null) {
+ throw new NullPointerException("tag shouldn't be null");
+ }
ExifAttribute exifAttribute = getExifAttribute(tag);
if (exifAttribute == null) {
return defaultValue;
@@ -1539,6 +1546,9 @@
* @param value the value of the tag.
*/
public void setAttribute(@NonNull String tag, @Nullable String value) {
+ if (tag == null) {
+ throw new NullPointerException("tag shouldn't be null");
+ }
// Convert the given value to rational values for backwards compatibility.
if (value != null && sTagSetForCompatibility.contains(tag)) {
if (tag.equals(TAG_GPS_TIMESTAMP)) {
@@ -1708,6 +1718,9 @@
* determine whether the image data format is JPEG or not.
*/
private void loadAttributes(@NonNull InputStream in) throws IOException {
+ if (in == null) {
+ throw new NullPointerException("inputstream shouldn't be null");
+ }
try {
// Initialize mAttributes.
for (int i = 0; i < EXIF_TAGS.length; ++i) {
@@ -2043,6 +2056,9 @@
* that means offsets may have changed.
*/
public @Nullable long[] getAttributeRange(@NonNull String tag) {
+ if (tag == null) {
+ throw new NullPointerException("tag shouldn't be null");
+ }
if (mModified) {
throw new IllegalStateException(
"The underlying file has been modified since being parsed");
@@ -2064,6 +2080,9 @@
* no tag was found.
*/
public @Nullable byte[] getAttributeBytes(@NonNull String tag) {
+ if (tag == null) {
+ throw new NullPointerException("tag shouldn't be null");
+ }
final ExifAttribute attribute = getExifAttribute(tag);
if (attribute != null) {
return attribute.bytes;
@@ -2234,6 +2253,24 @@
}
}
+ private void initForFilename(String filename) throws IOException {
+ FileInputStream in = null;
+ mAssetInputStream = null;
+ mFilename = filename;
+ mIsInputStream = false;
+ try {
+ in = new FileInputStream(filename);
+ if (isSeekableFD(in.getFD())) {
+ mSeekableFileDescriptor = in.getFD();
+ } else {
+ mSeekableFileDescriptor = null;
+ }
+ loadAttributes(in);
+ } finally {
+ IoUtils.closeQuietly(in);
+ }
+ }
+
// Checks the type of image file
private int getMimeType(BufferedInputStream in) throws IOException {
in.mark(SIGNATURE_CHECK_SIZE);
@@ -3085,6 +3122,9 @@
// Reads image file directory, which is a tag group in EXIF.
private void readImageFileDirectory(ByteOrderedDataInputStream dataInputStream,
@IfdType int ifdType) throws IOException {
+ // Save offset of current IFD to prevent reading an IFD that is already read.
+ mHandledIfdOffsets.add(dataInputStream.mPosition);
+
if (dataInputStream.mPosition + 2 > dataInputStream.mLength) {
// Return if there is no data from the offset.
return;
@@ -3223,9 +3263,7 @@
// 1. Exists within the boundaries of the input stream
// 2. Does not point to a previously read IFD.
if (offset > 0L && offset < dataInputStream.mLength) {
- if (!mAttributesOffsets.contains((int) offset)) {
- // Save offset of current IFD to prevent reading an IFD that is already read
- mAttributesOffsets.add(dataInputStream.mPosition);
+ if (!mHandledIfdOffsets.contains((int) offset)) {
dataInputStream.seek(offset);
readImageFileDirectory(dataInputStream, nextIfdType);
} else {
@@ -3279,9 +3317,7 @@
// 1. Exists within the boundaries of the input stream
// 2. Does not point to a previously read IFD.
if (nextIfdOffset > 0L && nextIfdOffset < dataInputStream.mLength) {
- if (!mAttributesOffsets.contains(nextIfdOffset)) {
- // Save offset of current IFD to prevent reading an IFD that is already read.
- mAttributesOffsets.add(dataInputStream.mPosition);
+ if (!mHandledIfdOffsets.contains(nextIfdOffset)) {
dataInputStream.seek(nextIfdOffset);
// Do not overwrite thumbnail IFD data if it alreay exists.
if (mAttributes[IFD_TYPE_THUMBNAIL].isEmpty()) {
diff --git a/packages/ExtServices/src/android/ext/services/notification/AssistantSettings.java b/packages/ExtServices/src/android/ext/services/notification/AssistantSettings.java
index ba361c4..46288bb 100644
--- a/packages/ExtServices/src/android/ext/services/notification/AssistantSettings.java
+++ b/packages/ExtServices/src/android/ext/services/notification/AssistantSettings.java
@@ -22,7 +22,6 @@
import android.os.Handler;
import android.provider.DeviceConfig;
import android.provider.Settings;
-import android.text.TextUtils;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
@@ -128,17 +127,17 @@
}
private void updateFromDeviceConfigFlags() {
- mGenerateReplies = DeviceConfigHelper.getBoolean(
+ mGenerateReplies = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SYSTEMUI,
SystemUiDeviceConfigFlags.NAS_GENERATE_REPLIES, DEFAULT_GENERATE_REPLIES);
- mGenerateActions = DeviceConfigHelper.getBoolean(
+ mGenerateActions = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SYSTEMUI,
SystemUiDeviceConfigFlags.NAS_GENERATE_ACTIONS, DEFAULT_GENERATE_ACTIONS);
- mMaxMessagesToExtract = DeviceConfigHelper.getInteger(
+ mMaxMessagesToExtract = DeviceConfig.getInt(DeviceConfig.NAMESPACE_SYSTEMUI,
SystemUiDeviceConfigFlags.NAS_MAX_MESSAGES_TO_EXTRACT,
DEFAULT_MAX_MESSAGES_TO_EXTRACT);
- mMaxSuggestions = DeviceConfigHelper.getInteger(
+ mMaxSuggestions = DeviceConfig.getInt(DeviceConfig.NAMESPACE_SYSTEMUI,
SystemUiDeviceConfigFlags.NAS_MAX_SUGGESTIONS, DEFAULT_MAX_SUGGESTIONS);
mOnUpdateRunnable.run();
@@ -170,34 +169,6 @@
mOnUpdateRunnable.run();
}
- static class DeviceConfigHelper {
-
- static int getInteger(String key, int defaultValue) {
- String value = getValue(key);
- if (TextUtils.isEmpty(value)) {
- return defaultValue;
- }
- try {
- return Integer.parseInt(value);
- } catch (NumberFormatException ex) {
- return defaultValue;
- }
- }
-
- static boolean getBoolean(String key, boolean defaultValue) {
- String value = getValue(key);
- if (TextUtils.isEmpty(value)) {
- return defaultValue;
- }
- return Boolean.parseBoolean(value);
- }
-
- private static String getValue(String key) {
- return DeviceConfig.getProperty(
- DeviceConfig.NAMESPACE_SYSTEMUI, key);
- }
- }
-
public interface Factory {
AssistantSettings createAndRegister(Handler handler, ContentResolver resolver, int userId,
Runnable onUpdateRunnable);
diff --git a/packages/ExtServices/tests/src/android/ext/services/notification/AssistantSettingsTest.java b/packages/ExtServices/tests/src/android/ext/services/notification/AssistantSettingsTest.java
index 293b5b8..ad52e2b 100644
--- a/packages/ExtServices/tests/src/android/ext/services/notification/AssistantSettingsTest.java
+++ b/packages/ExtServices/tests/src/android/ext/services/notification/AssistantSettingsTest.java
@@ -120,7 +120,7 @@
}
@Test
- public void testGenerateRepliesEmptyFlag() {
+ public void testGenerateRepliesNullFlag() {
runWithShellPermissionIdentity(() -> setProperty(
DeviceConfig.NAMESPACE_SYSTEMUI,
SystemUiDeviceConfigFlags.NAS_GENERATE_REPLIES,
@@ -136,12 +136,12 @@
runWithShellPermissionIdentity(() -> setProperty(
DeviceConfig.NAMESPACE_SYSTEMUI,
SystemUiDeviceConfigFlags.NAS_GENERATE_REPLIES,
- "",
+ null,
false /* makeDefault */));
mAssistantSettings.onDeviceConfigPropertyChanged(
DeviceConfig.NAMESPACE_SYSTEMUI,
SystemUiDeviceConfigFlags.NAS_GENERATE_REPLIES,
- "");
+ null);
// Go back to the default value.
assertTrue(mAssistantSettings.mGenerateReplies);
@@ -178,7 +178,7 @@
}
@Test
- public void testGenerateActionsEmptyFlag() {
+ public void testGenerateActionsNullFlag() {
runWithShellPermissionIdentity(() -> setProperty(
DeviceConfig.NAMESPACE_SYSTEMUI,
SystemUiDeviceConfigFlags.NAS_GENERATE_ACTIONS,
@@ -194,12 +194,12 @@
runWithShellPermissionIdentity(() -> setProperty(
DeviceConfig.NAMESPACE_SYSTEMUI,
SystemUiDeviceConfigFlags.NAS_GENERATE_ACTIONS,
- "",
+ null,
false /* makeDefault */));
mAssistantSettings.onDeviceConfigPropertyChanged(
DeviceConfig.NAMESPACE_SYSTEMUI,
SystemUiDeviceConfigFlags.NAS_GENERATE_ACTIONS,
- "");
+ null);
// Go back to the default value.
assertTrue(mAssistantSettings.mGenerateActions);
diff --git a/packages/NetworkStack/TEST_MAPPING b/packages/NetworkStack/TEST_MAPPING
index 55ba591..fe9731fe 100644
--- a/packages/NetworkStack/TEST_MAPPING
+++ b/packages/NetworkStack/TEST_MAPPING
@@ -1,5 +1,5 @@
{
- "postsubmit": [
+ "presubmit": [
{
"name": "NetworkStackTests"
}
diff --git a/packages/NetworkStack/tests/Android.bp b/packages/NetworkStack/tests/Android.bp
index f22b647..e64f284 100644
--- a/packages/NetworkStack/tests/Android.bp
+++ b/packages/NetworkStack/tests/Android.bp
@@ -22,7 +22,6 @@
resource_dirs: ["res"],
static_libs: [
"androidx.test.rules",
- "frameworks-base-testutils",
"mockito-target-extended-minus-junit4",
"NetworkStackLib",
"testables",
diff --git a/packages/NetworkStack/tests/src/android/net/ip/IpClientTest.java b/packages/NetworkStack/tests/src/android/net/ip/IpClientTest.java
index 1990229..bd488ea 100644
--- a/packages/NetworkStack/tests/src/android/net/ip/IpClientTest.java
+++ b/packages/NetworkStack/tests/src/android/net/ip/IpClientTest.java
@@ -34,6 +34,7 @@
import static org.mockito.Mockito.when;
import android.app.AlarmManager;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.res.Resources;
import android.net.ConnectivityManager;
@@ -46,14 +47,11 @@
import android.net.shared.InitialConfiguration;
import android.net.shared.ProvisioningConfiguration;
import android.net.util.InterfaceParams;
-import android.provider.Settings;
-import android.test.mock.MockContentResolver;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.internal.R;
-import com.android.internal.util.test.FakeSettingsProvider;
import com.android.server.NetworkObserver;
import com.android.server.NetworkObserverRegistry;
@@ -94,7 +92,7 @@
@Mock private IIpClientCallbacks mCb;
@Mock private AlarmManager mAlarm;
@Mock private IpClient.Dependencies mDependencies;
- private MockContentResolver mContentResolver;
+ @Mock private ContentResolver mContentResolver;
private NetworkObserver mObserver;
private InterfaceParams mIfParams;
@@ -109,9 +107,6 @@
when(mDependencies.getNetd(any())).thenReturn(mNetd);
when(mResources.getInteger(R.integer.config_networkAvoidBadWifi))
.thenReturn(DEFAULT_AVOIDBADWIFI_CONFIG_VALUE);
-
- mContentResolver = new MockContentResolver();
- mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
when(mContext.getContentResolver()).thenReturn(mContentResolver);
mIfParams = null;
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java
index bed3030..785dd56 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java
@@ -108,12 +108,43 @@
return true;
}
+ /**
+ * Get A2dp devices matching connection states{
+ * @code BluetoothProfile.STATE_CONNECTED,
+ * @code BluetoothProfile.STATE_CONNECTING,
+ * @code BluetoothProfile.STATE_DISCONNECTING}
+ *
+ * @return Matching device list
+ */
public List<BluetoothDevice> getConnectedDevices() {
- if (mService == null) return new ArrayList<BluetoothDevice>(0);
- return mService.getDevicesMatchingConnectionStates(
- new int[] {BluetoothProfile.STATE_CONNECTED,
- BluetoothProfile.STATE_CONNECTING,
- BluetoothProfile.STATE_DISCONNECTING});
+ return getDevicesByStates(new int[] {
+ BluetoothProfile.STATE_CONNECTED,
+ BluetoothProfile.STATE_CONNECTING,
+ BluetoothProfile.STATE_DISCONNECTING});
+ }
+
+ /**
+ * Get A2dp devices matching connection states{
+ * @code BluetoothProfile.STATE_DISCONNECTED,
+ * @code BluetoothProfile.STATE_CONNECTED,
+ * @code BluetoothProfile.STATE_CONNECTING,
+ * @code BluetoothProfile.STATE_DISCONNECTING}
+ *
+ * @return Matching device list
+ */
+ public List<BluetoothDevice> getConnectableDevices() {
+ return getDevicesByStates(new int[] {
+ BluetoothProfile.STATE_DISCONNECTED,
+ BluetoothProfile.STATE_CONNECTED,
+ BluetoothProfile.STATE_CONNECTING,
+ BluetoothProfile.STATE_DISCONNECTING});
+ }
+
+ private List<BluetoothDevice> getDevicesByStates(int[] states) {
+ if (mService == null) {
+ return new ArrayList<BluetoothDevice>(0);
+ }
+ return mService.getDevicesMatchingConnectionStates(states);
}
public boolean connect(BluetoothDevice device) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java
index 41c1d60..ebaeb74 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java
@@ -106,12 +106,43 @@
return true;
}
+ /**
+ * Get Hearing Aid devices matching connection states{
+ * @code BluetoothProfile.STATE_CONNECTED,
+ * @code BluetoothProfile.STATE_CONNECTING,
+ * @code BluetoothProfile.STATE_DISCONNECTING}
+ *
+ * @return Matching device list
+ */
public List<BluetoothDevice> getConnectedDevices() {
- if (mService == null) return new ArrayList<BluetoothDevice>(0);
- return mService.getDevicesMatchingConnectionStates(
- new int[] {BluetoothProfile.STATE_CONNECTED,
- BluetoothProfile.STATE_CONNECTING,
- BluetoothProfile.STATE_DISCONNECTING});
+ return getDevicesByStates(new int[] {
+ BluetoothProfile.STATE_CONNECTED,
+ BluetoothProfile.STATE_CONNECTING,
+ BluetoothProfile.STATE_DISCONNECTING});
+ }
+
+ /**
+ * Get Hearing Aid devices matching connection states{
+ * @code BluetoothProfile.STATE_DISCONNECTED,
+ * @code BluetoothProfile.STATE_CONNECTED,
+ * @code BluetoothProfile.STATE_CONNECTING,
+ * @code BluetoothProfile.STATE_DISCONNECTING}
+ *
+ * @return Matching device list
+ */
+ public List<BluetoothDevice> getConnectableDevices() {
+ return getDevicesByStates(new int[] {
+ BluetoothProfile.STATE_DISCONNECTED,
+ BluetoothProfile.STATE_CONNECTED,
+ BluetoothProfile.STATE_CONNECTING,
+ BluetoothProfile.STATE_DISCONNECTING});
+ }
+
+ private List<BluetoothDevice> getDevicesByStates(int[] states) {
+ if (mService == null) {
+ return new ArrayList<BluetoothDevice>(0);
+ }
+ return mService.getDevicesMatchingConnectionStates(states);
}
public boolean connect(BluetoothDevice device) {
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index b985b6b..4adece9 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -287,7 +287,6 @@
<item name="*android:lockPatternStyle">@style/LockPatternStyle</item>
<item name="passwordStyle">@style/PasswordTheme</item>
<item name="backgroundProtectedStyle">@style/BackgroundProtectedStyle</item>
- <item name="android:forceDarkAllowed">false</item>
<!-- Needed for MediaRoute chooser dialog -->
<item name="*android:isLightTheme">false</item>
diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java
index 7295008..9df6ba5 100644
--- a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java
+++ b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java
@@ -29,6 +29,7 @@
import android.opengl.GLSurfaceView;
import android.os.Build;
import android.util.Log;
+import android.util.MathUtils;
import com.android.systemui.ImageWallpaper;
import com.android.systemui.ImageWallpaper.ImageGLView;
@@ -43,6 +44,8 @@
public class ImageWallpaperRenderer implements GLSurfaceView.Renderer,
ImageWallpaper.WallpaperStatusListener, ImageRevealHelper.RevealStateListener {
private static final String TAG = ImageWallpaperRenderer.class.getSimpleName();
+ private static final float SCALE_VIEWPORT_MIN = 0.98f;
+ private static final float SCALE_VIEWPORT_MAX = 1f;
private final WallpaperManager mWallpaperManager;
private final ImageGLProgram mProgram;
@@ -52,6 +55,8 @@
private final ImageGLView mGLView;
private float mXOffset = 0f;
private float mYOffset = 0f;
+ private int mWidth = 0;
+ private int mHeight = 0;
public ImageWallpaperRenderer(Context context, ImageGLView glView) {
mWallpaperManager = context.getSystemService(WallpaperManager.class);
@@ -87,6 +92,8 @@
Log.d(TAG, "onSurfaceChanged: width=" + width + ", height=" + height
+ ", xOffset=" + mXOffset + ", yOffset=" + mYOffset);
}
+ mWidth = width;
+ mHeight = height;
mWallpaper.adjustTextureCoordinates(mWallpaperManager.getBitmap(),
width, height, mXOffset, mYOffset);
}
@@ -102,10 +109,21 @@
glUniform1f(mWallpaper.getHandle(ImageGLWallpaper.U_PER85), per85);
glUniform1f(mWallpaper.getHandle(ImageGLWallpaper.U_REVEAL), reveal);
+ scaleViewport(reveal);
mWallpaper.useTexture();
mWallpaper.draw();
}
+ private void scaleViewport(float reveal) {
+ // Interpolation between SCALE_VIEWPORT_MAX and SCALE_VIEWPORT_MIN by reveal.
+ float vpScaled = MathUtils.lerp(SCALE_VIEWPORT_MAX, SCALE_VIEWPORT_MIN, reveal);
+ // Calculate the offset amount from the lower left corner.
+ float offset = (SCALE_VIEWPORT_MAX - vpScaled) / 2;
+ // Change the viewport.
+ glViewport((int) (mWidth * offset), (int) (mHeight * offset),
+ (int) (mWidth * vpScaled), (int) (mHeight * vpScaled));
+ }
+
@Override
public void onAmbientModeChanged(boolean inAmbientMode, long duration) {
mImageRevealHelper.updateAwake(!inAmbientMode, duration);
diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java
index 5cca159..5d0fa26 100644
--- a/services/core/java/com/android/server/VibratorService.java
+++ b/services/core/java/com/android/server/VibratorService.java
@@ -111,6 +111,8 @@
// intensity level. It's important that we apply the scaling on the delta between the two so
// that the default intensity level applies no scaling to application provided effects.
private final SparseArray<ScaleLevel> mScaleLevels;
+ private final LinkedList<VibrationInfo> mPreviousRingVibrations;
+ private final LinkedList<VibrationInfo> mPreviousNotificationVibrations;
private final LinkedList<VibrationInfo> mPreviousVibrations;
private final int mPreviousVibrationsLimit;
private final boolean mAllowPriorityVibrationsInLowPowerMode;
@@ -354,6 +356,8 @@
mAllowPriorityVibrationsInLowPowerMode = mContext.getResources().getBoolean(
com.android.internal.R.bool.config_allowPriorityVibrationsInLowPowerMode);
+ mPreviousRingVibrations = new LinkedList<>();
+ mPreviousNotificationVibrations = new LinkedList<>();
mPreviousVibrations = new LinkedList<>();
IntentFilter filter = new IntentFilter();
@@ -620,10 +624,19 @@
}
private void addToPreviousVibrationsLocked(Vibration vib) {
- if (mPreviousVibrations.size() > mPreviousVibrationsLimit) {
- mPreviousVibrations.removeFirst();
+ final LinkedList<VibrationInfo> previousVibrations;
+ if (vib.isRingtone()) {
+ previousVibrations = mPreviousRingVibrations;
+ } else if (vib.isNotification()) {
+ previousVibrations = mPreviousNotificationVibrations;
+ } else {
+ previousVibrations = mPreviousVibrations;
}
- mPreviousVibrations.addLast(vib.toInfo());
+
+ if (previousVibrations.size() > mPreviousVibrationsLimit) {
+ previousVibrations.removeFirst();
+ }
+ previousVibrations.addLast(vib.toInfo());
}
@Override // Binder call
@@ -1355,6 +1368,18 @@
pw.println(" mNotificationIntensity=" + mNotificationIntensity);
pw.println(" mRingIntensity=" + mRingIntensity);
pw.println("");
+ pw.println(" Previous ring vibrations:");
+ for (VibrationInfo info : mPreviousRingVibrations) {
+ pw.print(" ");
+ pw.println(info.toString());
+ }
+
+ pw.println(" Previous notification vibrations:");
+ for (VibrationInfo info : mPreviousNotificationVibrations) {
+ pw.print(" ");
+ pw.println(info.toString());
+ }
+
pw.println(" Previous vibrations:");
for (VibrationInfo info : mPreviousVibrations) {
pw.print(" ");
diff --git a/services/core/java/com/android/server/connectivity/PacManager.java b/services/core/java/com/android/server/connectivity/PacManager.java
index 9789688..1ac09ad 100644
--- a/services/core/java/com/android/server/connectivity/PacManager.java
+++ b/services/core/java/com/android/server/connectivity/PacManager.java
@@ -70,9 +70,8 @@
private static final long MAX_PAC_SIZE = 20 * 1000 * 1000;
// Return values for #setCurrentProxyScriptUrl
- enum ToSendOrNotToSendBroadcast {
- DONT_SEND_BROADCAST, DO_SEND_BROADCAST
- }
+ public static final boolean DONT_SEND_BROADCAST = false;
+ public static final boolean DO_SEND_BROADCAST = true;
private String mCurrentPac;
@GuardedBy("mProxyLock")
@@ -176,11 +175,11 @@
* @param proxy Proxy information that is about to be broadcast.
* @return Returns whether the broadcast should be sent : either DO_ or DONT_SEND_BROADCAST
*/
- synchronized ToSendOrNotToSendBroadcast setCurrentProxyScriptUrl(ProxyInfo proxy) {
+ synchronized boolean setCurrentProxyScriptUrl(ProxyInfo proxy) {
if (!Uri.EMPTY.equals(proxy.getPacFileUrl())) {
if (proxy.getPacFileUrl().equals(mPacUrl) && (proxy.getPort() > 0)) {
// Allow to send broadcast, nothing to do.
- return ToSendOrNotToSendBroadcast.DO_SEND_BROADCAST;
+ return DO_SEND_BROADCAST;
}
mPacUrl = proxy.getPacFileUrl();
mCurrentDelay = DELAY_1;
@@ -188,7 +187,7 @@
mHasDownloaded = false;
getAlarmManager().cancel(mPacRefreshIntent);
bind();
- return ToSendOrNotToSendBroadcast.DONT_SEND_BROADCAST;
+ return DONT_SEND_BROADCAST;
} else {
getAlarmManager().cancel(mPacRefreshIntent);
synchronized (mProxyLock) {
@@ -204,7 +203,7 @@
}
}
}
- return ToSendOrNotToSendBroadcast.DO_SEND_BROADCAST;
+ return DO_SEND_BROADCAST;
}
}
diff --git a/services/core/java/com/android/server/connectivity/ProxyTracker.java b/services/core/java/com/android/server/connectivity/ProxyTracker.java
index a671287..e715890 100644
--- a/services/core/java/com/android/server/connectivity/ProxyTracker.java
+++ b/services/core/java/com/android/server/connectivity/ProxyTracker.java
@@ -208,8 +208,7 @@
public void sendProxyBroadcast() {
final ProxyInfo defaultProxy = getDefaultProxy();
final ProxyInfo proxyInfo = null != defaultProxy ? defaultProxy : new ProxyInfo("", 0, "");
- if (mPacManager.setCurrentProxyScriptUrl(proxyInfo)
- == PacManager.ToSendOrNotToSendBroadcast.DONT_SEND_BROADCAST) {
+ if (mPacManager.setCurrentProxyScriptUrl(proxyInfo) == PacManager.DONT_SEND_BROADCAST) {
return;
}
if (DBG) Slog.d(TAG, "sending Proxy Broadcast for " + proxyInfo);
diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
index 1f28a6c..6d7dff5 100644
--- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java
+++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
@@ -216,7 +216,7 @@
private PackageManager mPackageManager;
public AutomaticBrightnessController(Callbacks callbacks, Looper looper,
- SensorManager sensorManager, BrightnessMappingStrategy mapper,
+ SensorManager sensorManager, Sensor lightSensor, BrightnessMappingStrategy mapper,
int lightSensorWarmUpTime, int brightnessMin, int brightnessMax, float dozeScaleFactor,
int lightSensorRate, int initialLightSensorRate, long brighteningLightDebounceConfig,
long darkeningLightDebounceConfig, boolean resetAmbientLuxAfterWarmUpConfig,
@@ -249,7 +249,7 @@
new AmbientLightRingBuffer(mNormalLightSensorRate, mAmbientLightHorizon);
if (!DEBUG_PRETEND_LIGHT_SENSOR_ABSENT) {
- mLightSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
+ mLightSensor = lightSensor;
}
mActivityTaskManager = ActivityTaskManager.getService();
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 74cda9d..b79ead0 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -44,6 +44,7 @@
import android.os.Trace;
import android.os.UserHandle;
import android.provider.Settings;
+import android.text.TextUtils;
import android.util.MathUtils;
import android.util.Slog;
import android.util.TimeUtils;
@@ -58,6 +59,7 @@
import com.android.server.policy.WindowManagerPolicy;
import java.io.PrintWriter;
+import java.util.List;
/**
* Controls the power state of the display.
@@ -474,10 +476,14 @@
int shortTermModelTimeout = resources.getInteger(
com.android.internal.R.integer.config_autoBrightnessShortTermModelTimeout);
+ String lightSensorType = resources.getString(
+ com.android.internal.R.string.config_displayLightSensorType);
+ Sensor lightSensor = findDisplayLightSensor(lightSensorType);
+
mBrightnessMapper = BrightnessMappingStrategy.create(resources);
if (mBrightnessMapper != null) {
mAutomaticBrightnessController = new AutomaticBrightnessController(this,
- handler.getLooper(), sensorManager, mBrightnessMapper,
+ handler.getLooper(), sensorManager, lightSensor, mBrightnessMapper,
lightSensorWarmUpTimeConfig, mScreenBrightnessRangeMinimum,
mScreenBrightnessRangeMaximum, dozeScaleFactor, lightSensorRate,
initialLightSensorRate, brighteningLightDebounce, darkeningLightDebounce,
@@ -530,6 +536,19 @@
mDisplayWhiteBalanceController = displayWhiteBalanceController;
}
+ private Sensor findDisplayLightSensor(String sensorType) {
+ if (!TextUtils.isEmpty(sensorType)) {
+ List<Sensor> sensors = mSensorManager.getSensorList(Sensor.TYPE_ALL);
+ for (int i = 0; i < sensors.size(); i++) {
+ Sensor sensor = sensors.get(i);
+ if (sensorType.equals(sensor.getStringType())) {
+ return sensor;
+ }
+ }
+ }
+ return mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
+ }
+
/**
* Returns true if the proximity sensor screen-off function is available.
*/
diff --git a/services/core/java/com/android/server/rollback/TEST_MAPPING b/services/core/java/com/android/server/rollback/TEST_MAPPING
index 6be93a0..921b754 100644
--- a/services/core/java/com/android/server/rollback/TEST_MAPPING
+++ b/services/core/java/com/android/server/rollback/TEST_MAPPING
@@ -5,6 +5,14 @@
},
{
"name": "StagedRollbackTest"
+ },
+ {
+ "name": "FrameworksServicesTests",
+ "options": [
+ {
+ "include-filter": "com.android.server.rollback"
+ }
+ ]
}
]
}
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 5a746eb..2b23ff0 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -1809,7 +1809,7 @@
}
}
- mNotTop = (mLaunchFlags & FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
+ mNotTop = (mLaunchFlags & FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? sourceRecord : null;
mInTask = inTask;
// In some flows in to this function, we retrieve the task record and hold on to it
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 515ac52..db59030 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -392,7 +392,8 @@
final ArrayList<WindowToken> mExitingTokens = new ArrayList<>();
/** Detect user tapping outside of current focused task bounds .*/
- TaskTapPointerEventListener mTapDetector;
+ @VisibleForTesting
+ final TaskTapPointerEventListener mTapDetector;
/** Detect user tapping outside of current focused stack bounds .*/
private Region mTouchExcludeRegion = new Region();
@@ -876,14 +877,17 @@
mBoundsAnimationController = new BoundsAnimationController(service.mContext,
mAppTransition, AnimationThread.getHandler(), animationHandler);
- if (mWmService.mInputManager != null) {
- final InputChannel inputChannel = mWmService.mInputManager.monitorInput("Display "
- + mDisplayId, mDisplayId);
- mPointerEventDispatcher = inputChannel != null
- ? new PointerEventDispatcher(inputChannel) : null;
- } else {
- mPointerEventDispatcher = null;
- }
+ final InputChannel inputChannel = mWmService.mInputManager.monitorInput(
+ "PointerEventDispatcher" + mDisplayId, mDisplayId);
+ mPointerEventDispatcher = new PointerEventDispatcher(inputChannel);
+
+ // Tap Listeners are supported for:
+ // 1. All physical displays (multi-display).
+ // 2. VirtualDisplays on VR, AA (and everything else).
+ mTapDetector = new TaskTapPointerEventListener(mWmService, this);
+ registerPointerEventListener(mTapDetector);
+ registerPointerEventListener(mWmService.mMousePositionTracker);
+
mDisplayPolicy = new DisplayPolicy(service, this);
mDisplayRotation = new DisplayRotation(service, this);
if (isDefaultDisplay) {
@@ -1511,19 +1515,6 @@
mDisplayFrames.onDisplayInfoUpdated(mDisplayInfo,
calculateDisplayCutoutForRotation(mDisplayInfo.rotation));
-
- // Tap Listeners are supported for:
- // 1. All physical displays (multi-display).
- // 2. VirtualDisplays on VR, AA (and everything else).
- if (mPointerEventDispatcher != null && mTapDetector == null) {
- if (DEBUG_DISPLAY) {
- Slog.d(TAG,
- "Registering PointerEventListener for DisplayId: " + mDisplayId);
- }
- mTapDetector = new TaskTapPointerEventListener(mWmService, this);
- registerPointerEventListener(mTapDetector);
- registerPointerEventListener(mWmService.mMousePositionTracker);
- }
}
/**
@@ -2450,9 +2441,7 @@
mTmpRegion.set(mTmpRect);
mTouchExcludeRegion.op(mTmpRegion, Op.UNION);
}
- if (mTapDetector != null) {
- mTapDetector.setTouchExcludeRegion(mTouchExcludeRegion);
- }
+ mTapDetector.setTouchExcludeRegion(mTouchExcludeRegion);
}
/**
@@ -2502,11 +2491,7 @@
mWmService.stopFreezingDisplayLocked();
super.removeImmediately();
if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Removing display=" + this);
- if (mPointerEventDispatcher != null && mTapDetector != null) {
- unregisterPointerEventListener(mTapDetector);
- unregisterPointerEventListener(mWmService.mMousePositionTracker);
- mTapDetector = null;
- }
+ mPointerEventDispatcher.dispose();
mWmService.mAnimator.removeDisplayLocked(mDisplayId);
mWindowingLayer.release();
mOverlayLayer.release();
@@ -2516,7 +2501,6 @@
mRemovingDisplay = false;
}
- mDisplayPolicy.onDisplayRemoved();
mWmService.mWindowPlacerLocked.requestTraversal();
}
@@ -4825,15 +4809,11 @@
}
void registerPointerEventListener(@NonNull PointerEventListener listener) {
- if (mPointerEventDispatcher != null) {
- mPointerEventDispatcher.registerInputEventListener(listener);
- }
+ mPointerEventDispatcher.registerInputEventListener(listener);
}
void unregisterPointerEventListener(@NonNull PointerEventListener listener) {
- if (mPointerEventDispatcher != null) {
- mPointerEventDispatcher.unregisterInputEventListener(listener);
- }
+ mPointerEventDispatcher.unregisterInputEventListener(listener);
}
void prepareAppTransition(@WindowManager.TransitionType int transit,
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 5862d43..e48361f 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -221,7 +221,6 @@
}
}
- @VisibleForTesting
private final SystemGesturesPointerEventListener mSystemGestures;
private volatile int mLidState = LID_ABSENT;
@@ -548,10 +547,6 @@
return mDisplayContent.getDisplayId();
}
- void onDisplayRemoved() {
- mDisplayContent.unregisterPointerEventListener(mSystemGestures);
- }
-
void configure(int width, int height, int shortSizeDp) {
// Allow the navigation bar to move on non-square small devices (phones).
mNavigationBarCanMove = width != height && shortSizeDp < 600;
diff --git a/services/core/java/com/android/server/wm/PointerEventDispatcher.java b/services/core/java/com/android/server/wm/PointerEventDispatcher.java
index f815fa0..8d08aa3 100644
--- a/services/core/java/com/android/server/wm/PointerEventDispatcher.java
+++ b/services/core/java/com/android/server/wm/PointerEventDispatcher.java
@@ -28,11 +28,13 @@
import java.util.ArrayList;
public class PointerEventDispatcher extends InputEventReceiver {
- ArrayList<PointerEventListener> mListeners = new ArrayList<PointerEventListener>();
- PointerEventListener[] mListenersArray = new PointerEventListener[0];
+ private final InputChannel mInputChannel;
+ private final ArrayList<PointerEventListener> mListeners = new ArrayList<>();
+ private PointerEventListener[] mListenersArray = new PointerEventListener[0];
public PointerEventDispatcher(InputChannel inputChannel) {
super(inputChannel, UiThread.getHandler().getLooper());
+ mInputChannel = inputChannel;
}
@Override
@@ -87,4 +89,15 @@
mListenersArray = null;
}
}
+
+ /** Dispose the associated input channel and clean up the listeners. */
+ @Override
+ public void dispose() {
+ super.dispose();
+ mInputChannel.dispose();
+ synchronized (mListeners) {
+ mListeners.clear();
+ mListenersArray = null;
+ }
+ }
}
diff --git a/services/tests/uiservicestests/Android.bp b/services/tests/uiservicestests/Android.bp
index 92198fa..0ef2d15 100644
--- a/services/tests/uiservicestests/Android.bp
+++ b/services/tests/uiservicestests/Android.bp
@@ -18,6 +18,7 @@
"services.usage",
"guava",
"androidx.test.rules", "hamcrest-library",
+ "compatibility-device-util-axt",
"mockito-target-inline-minus-junit4",
"platform-test-annotations",
"hamcrest-library",
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 7df52b2..49d8ad0 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -42,6 +42,8 @@
import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE;
import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL;
+import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
+
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertNotNull;
@@ -4178,7 +4180,7 @@
mService.setNotificationAssistantAccessGrantedCallback(
mNotificationAssistantAccessGrantedCallback);
- mService.setDefaultAssistantForUser(0);
+ runWithShellPermissionIdentity(() -> mService.setDefaultAssistantForUser(0));
verify(mNotificationAssistantAccessGrantedCallback)
.onGranted(eq(xmlConfig), eq(0), eq(true));
@@ -4198,7 +4200,7 @@
mService.setNotificationAssistantAccessGrantedCallback(
mNotificationAssistantAccessGrantedCallback);
- mService.setDefaultAssistantForUser(0);
+ runWithShellPermissionIdentity(() -> mService.setDefaultAssistantForUser(0));
verify(mNotificationAssistantAccessGrantedCallback)
.onGranted(eq(deviceConfig), eq(0), eq(true));
@@ -4219,22 +4221,22 @@
mService.setNotificationAssistantAccessGrantedCallback(
mNotificationAssistantAccessGrantedCallback);
- mService.setDefaultAssistantForUser(0);
+ runWithShellPermissionIdentity(() -> mService.setDefaultAssistantForUser(0));
verify(mNotificationAssistantAccessGrantedCallback)
.onGranted(eq(xmlConfig), eq(0), eq(true));
}
private void clearDeviceConfig() {
- DeviceConfig.resetToDefaults(
- Settings.RESET_MODE_PACKAGE_DEFAULTS, DeviceConfig.NAMESPACE_SYSTEMUI);
+ runWithShellPermissionIdentity(() -> DeviceConfig.resetToDefaults(
+ Settings.RESET_MODE_PACKAGE_DEFAULTS, DeviceConfig.NAMESPACE_SYSTEMUI));
}
private void setDefaultAssistantInDeviceConfig(String componentName) {
- DeviceConfig.setProperty(
+ runWithShellPermissionIdentity(() -> DeviceConfig.setProperty(
DeviceConfig.NAMESPACE_SYSTEMUI,
SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE,
componentName,
- false);
+ false));
}
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
index d202e16..032eba1 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -270,7 +270,7 @@
WindowTestUtils.TestAppWindowToken createTestAppWindowToken(DisplayContent dc, int
windowingMode, int activityType) {
return createTestAppWindowToken(dc, windowingMode, activityType,
- true /*skipOnParentChanged */);
+ false /*skipOnParentChanged */);
}
WindowTestUtils.TestAppWindowToken createTestAppWindowToken(DisplayContent dc, int
diff --git a/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java b/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java
index 2907021..2fc6efa 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java
@@ -74,7 +74,7 @@
public SurfaceControl.Transaction setLayer(SurfaceControl sc, int layer) {
mRelativeLayersForControl.remove(sc);
mLayersForControl.put(sc, layer);
- return super.setLayer(sc, layer);
+ return this;
}
@Override
@@ -83,7 +83,7 @@
int layer) {
mRelativeLayersForControl.put(sc, relativeTo);
mLayersForControl.put(sc, layer);
- return super.setRelativeLayer(sc, relativeTo, layer);
+ return this;
}
private int getLayer(SurfaceControl sc) {
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 7688ac6..6f9bc2c 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -478,12 +478,6 @@
"android.telecom.extra.START_CALL_WITH_RTT";
/**
- * A boolean extra set to indicate whether an app is eligible to be bound to when there are
- * ongoing calls on the device.
- */
- public static final String EXTRA_IS_ENABLED = "android.telecom.extra.IS_ENABLED";
-
- /**
* A boolean meta-data value indicating whether an {@link InCallService} implements an
* in-call user interface. Dialer implementations (see {@link #getDefaultDialerPackage()}) which
* would also like to replace the in-call interface should set this meta-data to {@code true} in
diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTestUtils.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTestUtils.java
index ed8a533..a03fae0 100644
--- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTestUtils.java
+++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTestUtils.java
@@ -165,9 +165,7 @@
PackageInstaller packageInstaller = context.getPackageManager().getPackageInstaller();
PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(
PackageInstaller.SessionParams.MODE_FULL_INSTALL);
- if (enableRollback) {
- params.setEnableRollback();
- }
+ params.setEnableRollback(enableRollback);
int sessionId = packageInstaller.createSession(params);
session = packageInstaller.openSession(sessionId);
@@ -224,11 +222,9 @@
if (staged) {
multiPackageParams.setStaged();
}
- if (enableRollback) {
- // TODO: Do we set this on the parent params, the child params, or
- // both?
- multiPackageParams.setEnableRollback();
- }
+ // TODO: Do we set this on the parent params, the child params, or
+ // both?
+ multiPackageParams.setEnableRollback(enableRollback);
int multiPackageId = packageInstaller.createSession(multiPackageParams);
PackageInstaller.Session multiPackage = packageInstaller.openSession(multiPackageId);
@@ -242,9 +238,7 @@
if (resourceName.endsWith(".apex")) {
params.setInstallAsApex();
}
- if (enableRollback) {
- params.setEnableRollback();
- }
+ params.setEnableRollback(enableRollback);
int sessionId = packageInstaller.createSession(params);
session = packageInstaller.openSession(sessionId);