diff options
86 files changed, 1121 insertions, 424 deletions
diff --git a/api/system-current.txt b/api/system-current.txt index 4c9cada100b5..f2b0eaeb2688 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -6423,6 +6423,8 @@ package android.app.admin { field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM"; field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER"; field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION"; + field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_ICON_URI = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_ICON_URI"; + field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_LABEL = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_LABEL"; field public static final deprecated java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME"; field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_SIGNATURE_CHECKSUM = "android.app.extra.PROVISIONING_DEVICE_ADMIN_SIGNATURE_CHECKSUM"; field public static final java.lang.String EXTRA_PROVISIONING_DISCLAIMERS = "android.app.extra.PROVISIONING_DISCLAIMERS"; @@ -6435,8 +6437,10 @@ package android.app.admin { field public static final java.lang.String EXTRA_PROVISIONING_LOCAL_TIME = "android.app.extra.PROVISIONING_LOCAL_TIME"; field public static final java.lang.String EXTRA_PROVISIONING_LOGO_URI = "android.app.extra.PROVISIONING_LOGO_URI"; field public static final java.lang.String EXTRA_PROVISIONING_MAIN_COLOR = "android.app.extra.PROVISIONING_MAIN_COLOR"; + field public static final java.lang.String EXTRA_PROVISIONING_ORGANIZATION_NAME = "android.app.extra.PROVISIONING_ORGANIZATION_NAME"; field public static final java.lang.String EXTRA_PROVISIONING_SKIP_ENCRYPTION = "android.app.extra.PROVISIONING_SKIP_ENCRYPTION"; field public static final java.lang.String EXTRA_PROVISIONING_SKIP_USER_CONSENT = "android.app.extra.PROVISIONING_SKIP_USER_CONSENT"; + field public static final java.lang.String EXTRA_PROVISIONING_SUPPORT_URL = "android.app.extra.PROVISIONING_SUPPORT_URL"; field public static final java.lang.String EXTRA_PROVISIONING_TIME_ZONE = "android.app.extra.PROVISIONING_TIME_ZONE"; field public static final java.lang.String EXTRA_PROVISIONING_WIFI_HIDDEN = "android.app.extra.PROVISIONING_WIFI_HIDDEN"; field public static final java.lang.String EXTRA_PROVISIONING_WIFI_PAC_URL = "android.app.extra.PROVISIONING_WIFI_PAC_URL"; diff --git a/core/java/android/app/ITaskStackListener.aidl b/core/java/android/app/ITaskStackListener.aidl index e454ae170e28..ef997c90166e 100644 --- a/core/java/android/app/ITaskStackListener.aidl +++ b/core/java/android/app/ITaskStackListener.aidl @@ -95,4 +95,11 @@ oneway interface ITaskStackListener { * perform relevant animations before the window disappears. */ void onTaskRemovalStarted(int taskId); + + /** + * Called when the task has been put in a locked state because one or more of the + * activities inside it belong to a managed profile user, and that user has just + * been locked. + */ + void onTaskProfileLocked(int taskId, int userId); } diff --git a/core/java/android/app/TaskStackListener.java b/core/java/android/app/TaskStackListener.java index 063955224e22..ad5e69b5cbd4 100644 --- a/core/java/android/app/TaskStackListener.java +++ b/core/java/android/app/TaskStackListener.java @@ -74,4 +74,8 @@ public abstract class TaskStackListener extends ITaskStackListener.Stub { public void onActivityRequestedOrientationChanged(int taskId, int requestedOrientation) throws RemoteException { } + + @Override + public void onTaskProfileLocked(int taskId, int userId) { + } } diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index a56ff5e15e9b..29633aa4fbdd 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -279,6 +279,8 @@ public class DevicePolicyManager { * <li>{@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION}, optional</li> * <li>{@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER}, optional</li> * <li>{@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM}, optional</li> + * <li>{@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_LABEL}, optional</li> + * <li>{@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_ICON_URI}, optional</li> * <li>{@link #EXTRA_PROVISIONING_LOCAL_TIME} (convert to String), optional</li> * <li>{@link #EXTRA_PROVISIONING_TIME_ZONE}, optional</li> * <li>{@link #EXTRA_PROVISIONING_LOCALE}, optional</li> @@ -290,6 +292,8 @@ public class DevicePolicyManager { * <li>{@link #EXTRA_PROVISIONING_WIFI_PROXY_PORT} (convert to String), optional</li> * <li>{@link #EXTRA_PROVISIONING_WIFI_PROXY_BYPASS}, optional</li> * <li>{@link #EXTRA_PROVISIONING_WIFI_PAC_URL}, optional</li> + * <li>{@link #EXTRA_PROVISIONING_SUPPORT_URL}, optional</li> + * <li>{@link #EXTRA_PROVISIONING_ORGANIZATION_NAME}, optional</li> * <li>{@link #EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE}, optional</li></ul> * * @hide @@ -688,6 +692,67 @@ public class DevicePolicyManager { = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION"; /** + * A String extra holding the localized name of the organization under management. + * + * The name is displayed only during provisioning. + * + * <p>Use in an intent with action {@link #ACTION_PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE} + * + * @hide + */ + @SystemApi + public static final String EXTRA_PROVISIONING_ORGANIZATION_NAME = + "android.app.extra.PROVISIONING_ORGANIZATION_NAME"; + + /** + * A String extra holding a url to the website of the device's provider. The website can be + * opened in a browser during provisioning. + * + * <p>Use in an intent with action {@link #ACTION_PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE} + * + * @hide + */ + @SystemApi + public static final String EXTRA_PROVISIONING_SUPPORT_URL = + "android.app.extra.PROVISIONING_SUPPORT_URL"; + + /** + * A String extra holding the localized name of the device admin package. It should be the same + * as the app label of the package. + * + * <p>Use in an intent with action {@link #ACTION_PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE} + * + * @hide + */ + @SystemApi + public static final String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_LABEL = + "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_LABEL"; + + /** + * A {@link Uri} extra pointing to the app icon of device admin package. This image will be + * shown during the provisioning. + * <h5>The following URI schemes are accepted:</h5> + * <ul> + * <li>content ({@link android.content.ContentResolver#SCHEME_CONTENT})</li> + * <li>android.resource ({@link android.content.ContentResolver#SCHEME_ANDROID_RESOURCE})</li> + * </ul> + * + * <p> It is the responsibility of the caller to provide an image with a reasonable + * pixel density for the device. + * + * <p> If a content: URI is passed, the intent should have the flag + * {@link Intent#FLAG_GRANT_READ_URI_PERMISSION} and the uri should be added to the + * {@link android.content.ClipData} of the intent too. + * + * <p>Use in an intent with action {@link #ACTION_PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE} + * + * @hide + */ + @SystemApi + public static final String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_ICON_URI = + "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_ICON_URI"; + + /** * An int extra holding a minimum required version code for the device admin package. If the * device admin is already installed on the device, it will only be re-downloaded from * {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION} if the version of the @@ -808,7 +873,7 @@ public class DevicePolicyManager { * </ul> * * <p> It is the responsibility of the caller to provide an image with a reasonable - * pixed density for the device. + * pixel density for the device. * * <p> If a content: URI is passed, the intent should have the flag * {@link Intent#FLAG_GRANT_READ_URI_PERMISSION} and the uri should be added to the diff --git a/core/java/android/appwidget/AppWidgetManager.java b/core/java/android/appwidget/AppWidgetManager.java index 318968158559..31e779f0dc4b 100644 --- a/core/java/android/appwidget/AppWidgetManager.java +++ b/core/java/android/appwidget/AppWidgetManager.java @@ -1094,8 +1094,9 @@ public class AppWidgetManager { * <p>Only apps with a foreground activity or a foreground service can call it. Otherwise * it'll throw {@link IllegalStateException}. * - * <p>When an app calls this API when a previous request is still waiting for a response, - * the previous request will be canceled. + * <p>It's up to the launcher how to handle previous pending requests when the same package + * calls this API multiple times in a row. It may ignore the previous requests, + * for example. * * @param provider The {@link ComponentName} for the {@link * android.content.BroadcastReceiver BroadcastReceiver} provider for your AppWidget. diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java index 4b5b995cd218..afd757877603 100644 --- a/core/java/android/content/pm/LauncherApps.java +++ b/core/java/android/content/pm/LauncherApps.java @@ -1200,7 +1200,7 @@ public class LauncherApps { /** * Return {@code TRUE} if a request is valid -- i.e. {@link #accept(Bundle)} has not been - * called, and it has not been canceled. + * called yet. */ public boolean isValid() { try { diff --git a/core/java/android/content/pm/ShortcutManager.java b/core/java/android/content/pm/ShortcutManager.java index c8fb3d174fe0..385340000d83 100644 --- a/core/java/android/content/pm/ShortcutManager.java +++ b/core/java/android/content/pm/ShortcutManager.java @@ -846,8 +846,9 @@ public class ShortcutManager { * <p>Only apps with a foreground activity or a foreground service can call it. Otherwise * it'll throw {@link IllegalStateException}. * - * <p>When an app calls this API when a previous request is still waiting for a response, - * the previous request will be canceled. + * <p>It's up to the launcher how to handle previous pending requests when the same package + * calls this API multiple times in a row. It may ignore the previous requests, + * for example. * * @param shortcut New shortcut to pin. If an app wants to pin an existing (either dynamic * or manifest) shortcut, then it only needs to have an ID, and other fields don't have to diff --git a/core/java/android/util/EventLog.java b/core/java/android/util/EventLog.java index 99f6c2a9c58d..79d16fbfaee8 100644 --- a/core/java/android/util/EventLog.java +++ b/core/java/android/util/EventLog.java @@ -59,7 +59,7 @@ public class EventLog { private Exception mLastWtf; // Layout of event log entry received from Android logger. - // see system/core/include/log/logger.h + // see system/core/include/log/log.h private static final int LENGTH_OFFSET = 0; private static final int HEADER_SIZE_OFFSET = 2; private static final int PROCESS_OFFSET = 4; diff --git a/core/java/android/webkit/WebViewFactory.java b/core/java/android/webkit/WebViewFactory.java index eb0c44c3a07d..d7a49e46a236 100644 --- a/core/java/android/webkit/WebViewFactory.java +++ b/core/java/android/webkit/WebViewFactory.java @@ -59,8 +59,8 @@ public final class WebViewFactory { // visible for WebViewZygoteInit to look up the class by reflection and call preloadInZygote. /** @hide */ - public static final String CHROMIUM_WEBVIEW_FACTORY = - "com.android.webview.chromium.WebViewChromiumFactoryProvider"; + private static final String CHROMIUM_WEBVIEW_FACTORY = + "com.android.webview.chromium.WebViewChromiumFactoryProviderForO"; private static final String CHROMIUM_WEBVIEW_FACTORY_METHOD = "create"; @@ -143,6 +143,23 @@ public final class WebViewFactory { } /** + * @hide + */ + public static Class<WebViewFactoryProvider> getWebViewProviderClass( ClassLoader clazzLoader) + throws ClassNotFoundException{ + try { + return (Class<WebViewFactoryProvider>) Class.forName(CHROMIUM_WEBVIEW_FACTORY, + true, clazzLoader); + } catch (ClassNotFoundException e) { + // TODO: This loads the provider which is not built for O, should be removed + // before the release. + return (Class<WebViewFactoryProvider>) Class.forName( + "com.android.webview.chromium.WebViewChromiumFactoryProvider", + true, clazzLoader); + } + } + + /** * Load the native library for the given package name iff that package * name is the same as the one providing the webview. */ @@ -366,9 +383,9 @@ public final class WebViewFactory { Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "Class.forName()"); try { - return (Class<WebViewFactoryProvider>) Class.forName(CHROMIUM_WEBVIEW_FACTORY, - true, clazzLoader); - } finally { + return getWebViewProviderClass(clazzLoader); + } + finally { Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW); } } catch (ClassNotFoundException e) { diff --git a/core/java/com/android/internal/logging/LogBuilder.java b/core/java/com/android/internal/logging/LogBuilder.java index 634d061e79d1..8e2e114be454 100644 --- a/core/java/com/android/internal/logging/LogBuilder.java +++ b/core/java/com/android/internal/logging/LogBuilder.java @@ -17,8 +17,9 @@ public class LogBuilder { private SparseArray<Object> entries = new SparseArray(); - public LogBuilder() {} - + public LogBuilder(int mainCategory) { + setCategory(mainCategory); + } public LogBuilder setView(View view) { entries.put(MetricsEvent.RESERVED_FOR_LOGBUILDER_VIEW, view.getId()); diff --git a/core/java/com/android/internal/os/WebViewZygoteInit.java b/core/java/com/android/internal/os/WebViewZygoteInit.java index 12d699d2ae15..d82a211446d3 100644 --- a/core/java/com/android/internal/os/WebViewZygoteInit.java +++ b/core/java/com/android/internal/os/WebViewZygoteInit.java @@ -24,6 +24,7 @@ import android.system.Os; import android.text.TextUtils; import android.util.Log; import android.webkit.WebViewFactory; +import android.webkit.WebViewFactoryProvider; import java.io.IOException; import java.lang.reflect.InvocationTargetException; @@ -74,8 +75,8 @@ class WebViewZygoteInit { // call preloadInZygote() on it to give it the opportunity to preload the native library // and perform any other initialisation work that should be shared among the children. try { - Class providerClass = Class.forName(WebViewFactory.CHROMIUM_WEBVIEW_FACTORY, true, - loader); + Class<WebViewFactoryProvider> providerClass = + WebViewFactory.getWebViewProviderClass(loader); Object result = providerClass.getMethod("preloadInZygote").invoke(null); if (!((Boolean)result).booleanValue()) { Log.e(TAG, "preloadInZygote returned false"); diff --git a/core/jni/android/graphics/HarfBuzzNGFaceSkia.cpp b/core/jni/android/graphics/HarfBuzzNGFaceSkia.cpp index aa6348ee2a31..dcb787462a13 100644 --- a/core/jni/android/graphics/HarfBuzzNGFaceSkia.cpp +++ b/core/jni/android/graphics/HarfBuzzNGFaceSkia.cpp @@ -33,7 +33,9 @@ #include "HarfBuzzNGFaceSkia.h" #include <stdlib.h> -#include <cutils/log.h> + +#include <log/log.h> + #include <SkPaint.h> #include <SkPath.h> #include <SkPoint.h> diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp index aa4570ff8d70..14d7e812d583 100644 --- a/core/jni/android_os_Debug.cpp +++ b/core/jni/android_os_Debug.cpp @@ -16,32 +16,32 @@ #define LOG_TAG "android.os.Debug" +#include <assert.h> +#include <ctype.h> +#include <errno.h> #include <fcntl.h> #include <inttypes.h> +#include <malloc.h> #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <unistd.h> -#include <time.h> #include <sys/time.h> -#include <errno.h> -#include <assert.h> -#include <ctype.h> -#include <malloc.h> +#include <time.h> +#include <unistd.h> #include <iomanip> #include <string> -#include "jni.h" +#include <android-base/stringprintf.h> +#include <cutils/debugger.h> +#include <log/log.h> +#include <utils/misc.h> +#include <utils/String8.h> -#include "android-base/stringprintf.h" -#include "cutils/debugger.h" -#include "cutils/log.h" #include "JNIHelp.h" -#include "memtrack/memtrack.h" -#include "memunreachable/memunreachable.h" -#include "utils/misc.h" -#include "utils/String8.h" +#include "jni.h" +#include <memtrack/memtrack.h> +#include <memunreachable/memunreachable.h> namespace android { diff --git a/core/jni/android_os_Trace.cpp b/core/jni/android_os_Trace.cpp index ea893f0dd1bb..de91f70ee8f5 100644 --- a/core/jni/android_os_Trace.cpp +++ b/core/jni/android_os_Trace.cpp @@ -19,15 +19,14 @@ #include <inttypes.h> +#include <cutils/trace.h> +#include <utils/String8.h> +#include <log/log.h> + #include <JNIHelp.h> #include <ScopedUtfChars.h> #include <ScopedStringChars.h> -#include <utils/String8.h> - -#include <cutils/trace.h> -#include <cutils/log.h> - namespace android { static void sanitizeString(String8& utf8Chars) { diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp index 5559d48a58b6..abcd1e7049ef 100644 --- a/core/jni/android_util_Binder.cpp +++ b/core/jni/android_util_Binder.cpp @@ -29,19 +29,19 @@ #include <sys/types.h> #include <unistd.h> -#include <utils/Atomic.h> #include <binder/IInterface.h> +#include <binder/IServiceManager.h> #include <binder/IPCThreadState.h> -#include <utils/Log.h> -#include <utils/SystemClock.h> -#include <utils/List.h> -#include <utils/KeyedVector.h> -#include <log/logger.h> #include <binder/Parcel.h> #include <binder/ProcessState.h> -#include <binder/IServiceManager.h> -#include <utils/threads.h> +#include <log/log.h> +#include <utils/Atomic.h> +#include <utils/KeyedVector.h> +#include <utils/List.h> +#include <utils/Log.h> #include <utils/String8.h> +#include <utils/SystemClock.h> +#include <utils/threads.h> #include <ScopedUtfChars.h> #include <ScopedLocalRef.h> diff --git a/core/jni/android_util_Log.cpp b/core/jni/android_util_Log.cpp index 7719e31f4240..20dfe7809728 100644 --- a/core/jni/android_util_Log.cpp +++ b/core/jni/android_util_Log.cpp @@ -21,7 +21,7 @@ #include <android-base/macros.h> #include <assert.h> #include <cutils/properties.h> -#include <log/logger.h> // For LOGGER_ENTRY_MAX_PAYLOAD. +#include <log/log.h> // For LOGGER_ENTRY_MAX_PAYLOAD. #include <utils/Log.h> #include <utils/String8.h> diff --git a/core/jni/android_util_jar_StrictJarFile.cpp b/core/jni/android_util_jar_StrictJarFile.cpp index 2e31c8b2fc8f..4f1f926c8a22 100644 --- a/core/jni/android_util_jar_StrictJarFile.cpp +++ b/core/jni/android_util_jar_StrictJarFile.cpp @@ -20,13 +20,14 @@ #include <memory> #include <string> +#include <log/log.h> + #include "JNIHelp.h" #include "JniConstants.h" #include "ScopedLocalRef.h" #include "ScopedUtfChars.h" #include "jni.h" #include "ziparchive/zip_archive.h" -#include "cutils/log.h" namespace android { diff --git a/core/tests/coretests/src/com/android/internal/logging/LogBuilderTest.java b/core/tests/coretests/src/com/android/internal/logging/LogBuilderTest.java index e7d23a8edb9c..e3f754ca8925 100644 --- a/core/tests/coretests/src/com/android/internal/logging/LogBuilderTest.java +++ b/core/tests/coretests/src/com/android/internal/logging/LogBuilderTest.java @@ -5,7 +5,7 @@ import junit.framework.TestCase; public class LogBuilderTest extends TestCase { public void testSerialize() { - LogBuilder builder = new LogBuilder(); + LogBuilder builder = new LogBuilder(0); builder.addTaggedData(1, "one"); builder.addTaggedData(2, "two"); Object[] out = builder.serialize(); @@ -16,7 +16,7 @@ public class LogBuilderTest extends TestCase { } public void testInvalidInputThrows() { - LogBuilder builder = new LogBuilder(); + LogBuilder builder = new LogBuilder(0); boolean threw = false; try { builder.addTaggedData(0, new Object()); @@ -28,7 +28,7 @@ public class LogBuilderTest extends TestCase { } public void testValidInputTypes() { - LogBuilder builder = new LogBuilder(); + LogBuilder builder = new LogBuilder(0); builder.addTaggedData(1, "onetwothree"); builder.addTaggedData(2, 123); builder.addTaggedData(3, 123L); diff --git a/libs/androidfw/BackupData.cpp b/libs/androidfw/BackupData.cpp index ba4a4ff4fe63..76a430ee9f0e 100644 --- a/libs/androidfw/BackupData.cpp +++ b/libs/androidfw/BackupData.cpp @@ -16,14 +16,13 @@ #define LOG_TAG "backup_data" -#include <androidfw/BackupHelpers.h> -#include <utils/ByteOrder.h> - #include <stdio.h> #include <string.h> #include <unistd.h> -#include <cutils/log.h> +#include <androidfw/BackupHelpers.h> +#include <log/log.h> +#include <utils/ByteOrder.h> namespace android { diff --git a/libs/androidfw/BackupHelpers.cpp b/libs/androidfw/BackupHelpers.cpp index 78e9d91c4d67..8bfe2b6a259a 100644 --- a/libs/androidfw/BackupHelpers.cpp +++ b/libs/androidfw/BackupHelpers.cpp @@ -18,23 +18,22 @@ #include <androidfw/BackupHelpers.h> -#include <utils/KeyedVector.h> -#include <utils/ByteOrder.h> -#include <utils/String8.h> - #include <errno.h> -#include <sys/types.h> -#include <sys/uio.h> -#include <sys/stat.h> -#include <sys/time.h> // for utimes +#include <fcntl.h> #include <stdio.h> #include <stdlib.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <sys/time.h> // for utimes +#include <sys/uio.h> #include <unistd.h> #include <utime.h> -#include <fcntl.h> #include <zlib.h> -#include <cutils/log.h> +#include <log/log.h> +#include <utils/ByteOrder.h> +#include <utils/KeyedVector.h> +#include <utils/String8.h> namespace android { diff --git a/libs/androidfw/include/androidfw/CursorWindow.h b/libs/androidfw/include/androidfw/CursorWindow.h index 8a2979a3756d..f54356576551 100644 --- a/libs/androidfw/include/androidfw/CursorWindow.h +++ b/libs/androidfw/include/androidfw/CursorWindow.h @@ -17,11 +17,11 @@ #ifndef _ANDROID__DATABASE_WINDOW_H #define _ANDROID__DATABASE_WINDOW_H -#include <cutils/log.h> #include <stddef.h> #include <stdint.h> #include <binder/Parcel.h> +#include <log/log.h> #include <utils/String8.h> #if LOG_NDEBUG diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk index 18e59e551845..8f7787bd5d15 100644 --- a/libs/hwui/Android.mk +++ b/libs/hwui/Android.mk @@ -75,6 +75,7 @@ hwui_src_files := \ FrameInfo.cpp \ FrameInfoVisualizer.cpp \ GammaFontRenderer.cpp \ + GlLayer.cpp \ GlopBuilder.cpp \ GpuMemoryTracker.cpp \ GradientCache.cpp \ @@ -115,6 +116,7 @@ hwui_src_files := \ Texture.cpp \ TextureCache.cpp \ VectorDrawable.cpp \ + VkLayer.cpp \ protos/hwui.proto hwui_test_common_src_files := \ diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp index b463e45fb39b..a0366dee3218 100644 --- a/libs/hwui/Caches.cpp +++ b/libs/hwui/Caches.cpp @@ -17,7 +17,7 @@ #include "Caches.h" #include "GammaFontRenderer.h" -#include "Layer.h" +#include "GlLayer.h" #include "Properties.h" #include "renderstate/RenderState.h" #include "ShadowTessellator.h" @@ -170,9 +170,11 @@ void Caches::dumpMemoryUsage(String8 &log) { for (std::set<Layer*>::iterator it = mRenderState->mActiveLayers.begin(); it != mRenderState->mActiveLayers.end(); it++) { const Layer* layer = *it; - log.appendFormat(" Layer size %dx%d; texid=%u refs=%d\n", + LOG_ALWAYS_FATAL_IF(layer->getApi() != Layer::Api::OpenGL); + const GlLayer* glLayer = static_cast<const GlLayer*>(layer); + log.appendFormat(" GlLayer size %dx%d; texid=%u refs=%d\n", layer->getWidth(), layer->getHeight(), - layer->getTextureId(), + glLayer->getTextureId(), layer->getStrongCount()); memused += layer->getWidth() * layer->getHeight() * 4; } diff --git a/libs/hwui/DamageAccumulator.cpp b/libs/hwui/DamageAccumulator.cpp index 6d5833b3be86..2b4fe17d424d 100644 --- a/libs/hwui/DamageAccumulator.cpp +++ b/libs/hwui/DamageAccumulator.cpp @@ -16,7 +16,7 @@ #include "DamageAccumulator.h" -#include <cutils/log.h> +#include <log/log.h> #include "RenderNode.h" #include "utils/MathUtils.h" diff --git a/libs/hwui/DeferredLayerUpdater.cpp b/libs/hwui/DeferredLayerUpdater.cpp index a7d5f6026d00..3e8e8a1a1ca3 100644 --- a/libs/hwui/DeferredLayerUpdater.cpp +++ b/libs/hwui/DeferredLayerUpdater.cpp @@ -15,6 +15,8 @@ */ #include "DeferredLayerUpdater.h" +#include "GlLayer.h" +#include "VkLayer.h" #include "renderthread/EglManager.h" #include "renderthread/RenderTask.h" #include "utils/PaintUtils.h" @@ -55,13 +57,23 @@ void DeferredLayerUpdater::apply() { mLayer->setAlpha(mAlpha, mMode); if (mSurfaceTexture.get()) { - if (mNeedsGLContextAttach) { - mNeedsGLContextAttach = false; - mSurfaceTexture->attachToContext(mLayer->getTextureId()); - } - if (mUpdateTexImage) { - mUpdateTexImage = false; - doUpdateTexImage(); + if (mLayer->getApi() == Layer::Api::Vulkan) { + if (mUpdateTexImage) { + mUpdateTexImage = false; + doUpdateVkTexImage(); + } + } else { + LOG_ALWAYS_FATAL_IF(mLayer->getApi() != Layer::Api::OpenGL, + "apply surfaceTexture with non GL backend %x, GL %x, VK %x", + mLayer->getApi(), Layer::Api::OpenGL, Layer::Api::Vulkan); + if (mNeedsGLContextAttach) { + mNeedsGLContextAttach = false; + mSurfaceTexture->attachToContext(static_cast<GlLayer*>(mLayer)->getTextureId()); + } + if (mUpdateTexImage) { + mUpdateTexImage = false; + doUpdateTexImage(); + } } if (mTransform) { mLayer->getTransform().load(*mTransform); @@ -71,6 +83,9 @@ void DeferredLayerUpdater::apply() { } void DeferredLayerUpdater::doUpdateTexImage() { + LOG_ALWAYS_FATAL_IF(mLayer->getApi() != Layer::Api::OpenGL, + "doUpdateTexImage non GL backend %x, GL %x, VK %x", + mLayer->getApi(), Layer::Api::OpenGL, Layer::Api::Vulkan); if (mSurfaceTexture->updateTexImage() == NO_ERROR) { float transform[16]; @@ -110,30 +125,53 @@ void DeferredLayerUpdater::doUpdateTexImage() { } } +void DeferredLayerUpdater::doUpdateVkTexImage() { + LOG_ALWAYS_FATAL_IF(mLayer->getApi() != Layer::Api::Vulkan, + "updateLayer non Vulkan backend %x, GL %x, VK %x", + mLayer->getApi(), Layer::Api::OpenGL, Layer::Api::Vulkan); + + static const mat4 identityMatrix; + updateLayer(false, identityMatrix.data); + + VkLayer* vkLayer = static_cast<VkLayer*>(mLayer); + vkLayer->updateTexture(); +} + void DeferredLayerUpdater::updateLayer(bool forceFilter, GLenum renderTarget, const float* textureTransform) { + LOG_ALWAYS_FATAL_IF(mLayer->getApi() != Layer::Api::OpenGL, + "updateLayer non GL backend %x, GL %x, VK %x", + mLayer->getApi(), Layer::Api::OpenGL, Layer::Api::Vulkan); + + updateLayer(forceFilter, textureTransform); + + GlLayer* glLayer = static_cast<GlLayer*>(mLayer); + if (renderTarget != glLayer->getRenderTarget()) { + glLayer->setRenderTarget(renderTarget); + glLayer->bindTexture(); + glLayer->setFilter(GL_NEAREST, false, true); + glLayer->setWrap(GL_CLAMP_TO_EDGE, false, true); + } +} + +void DeferredLayerUpdater::updateLayer(bool forceFilter, const float* textureTransform) { mLayer->setBlend(mBlend); mLayer->setForceFilter(forceFilter); mLayer->setSize(mWidth, mHeight); mLayer->getTexTransform().load(textureTransform); - - if (renderTarget != mLayer->getRenderTarget()) { - mLayer->setRenderTarget(renderTarget); - mLayer->bindTexture(); - mLayer->setFilter(GL_NEAREST, false, true); - mLayer->setWrap(GL_CLAMP_TO_EDGE, false, true); - } } void DeferredLayerUpdater::detachSurfaceTexture() { if (mSurfaceTexture.get()) { - status_t err = mSurfaceTexture->detachFromContext(); - if (err != 0) { - // TODO: Elevate to fatal exception - ALOGE("Failed to detach SurfaceTexture from context %d", err); + if (mLayer->getApi() == Layer::Api::OpenGL) { + status_t err = mSurfaceTexture->detachFromContext(); + if (err != 0) { + // TODO: Elevate to fatal exception + ALOGE("Failed to detach SurfaceTexture from context %d", err); + } + static_cast<GlLayer*>(mLayer)->clearTexture(); } mSurfaceTexture = nullptr; - mLayer->clearTexture(); } } diff --git a/libs/hwui/DeferredLayerUpdater.h b/libs/hwui/DeferredLayerUpdater.h index 733500885e67..ead83144f4d4 100644 --- a/libs/hwui/DeferredLayerUpdater.h +++ b/libs/hwui/DeferredLayerUpdater.h @@ -22,6 +22,9 @@ #include <SkMatrix.h> #include <utils/StrongPointer.h> +#include <GLES2/gl2.h> +#include <GLES2/gl2ext.h> + #include "Layer.h" #include "Rect.h" #include "renderthread/RenderThread.h" @@ -110,6 +113,8 @@ private: Layer* mLayer; void doUpdateTexImage(); + void doUpdateVkTexImage(); + void updateLayer(bool forceFilter, const float* textureTransform); }; } /* namespace uirenderer */ diff --git a/libs/hwui/DeviceInfo.cpp b/libs/hwui/DeviceInfo.cpp index 700642ed7334..d180ba51b304 100644 --- a/libs/hwui/DeviceInfo.cpp +++ b/libs/hwui/DeviceInfo.cpp @@ -13,16 +13,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #include <DeviceInfo.h> #include "Extensions.h" -#include <GLES2/gl2.h> -#include <log/log.h> - #include <thread> #include <mutex> +#include <log/log.h> + +#include <GLES2/gl2.h> + namespace android { namespace uirenderer { diff --git a/libs/hwui/GlLayer.cpp b/libs/hwui/GlLayer.cpp new file mode 100644 index 000000000000..c0ab895260ab --- /dev/null +++ b/libs/hwui/GlLayer.cpp @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "GlLayer.h" + +#include "Caches.h" +#include "RenderNode.h" +#include "renderstate/RenderState.h" +#include "utils/TraceUtils.h" + +#include <utils/Log.h> + +#define ATRACE_LAYER_WORK(label) \ + ATRACE_FORMAT("%s HW Layer DisplayList %s %ux%u", \ + label, \ + (renderNode.get() != NULL) ? renderNode->getName() : "", \ + getWidth(), getHeight()) + +namespace android { +namespace uirenderer { + +GlLayer::GlLayer(RenderState& renderState, uint32_t layerWidth, uint32_t layerHeight) + : Layer(renderState, Api::OpenGL) + , caches(Caches::getInstance()) + , texture(caches) { + texture.mWidth = layerWidth; + texture.mHeight = layerHeight; +} + +GlLayer::~GlLayer() { + if (texture.mId) { + texture.deleteTexture(); + } +} + +void GlLayer::onGlContextLost() { + texture.deleteTexture(); +} + +void GlLayer::bindTexture() const { + if (texture.mId) { + caches.textureState().bindTexture(texture.target(), texture.mId); + } +} + +void GlLayer::generateTexture() { + if (!texture.mId) { + glGenTextures(1, &texture.mId); + } +} + +void GlLayer::clearTexture() { + // There's a rare possibility that Caches could have been destroyed already + // since this method is queued up as a task. + // Since this is a reset method, treat this as non-fatal. + if (caches.isInitialized()) { + caches.textureState().unbindTexture(texture.mId); + } + texture.mId = 0; +} + +}; // namespace uirenderer +}; // namespace android diff --git a/libs/hwui/GlLayer.h b/libs/hwui/GlLayer.h new file mode 100644 index 000000000000..54bf5adc3ace --- /dev/null +++ b/libs/hwui/GlLayer.h @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "Layer.h" + +#include "Texture.h" + +namespace android { +namespace uirenderer { + +// Forward declarations +class Caches; + +/** + * A layer has dimensions and is backed by an OpenGL texture or FBO. + */ +class GlLayer : public Layer { +public: + GlLayer(RenderState& renderState, uint32_t layerWidth, uint32_t layerHeight); + virtual ~GlLayer(); + + uint32_t getWidth() const override { + return texture.mWidth; + } + + uint32_t getHeight() const override { + return texture.mHeight; + } + + void setSize(uint32_t width, uint32_t height) override { + texture.updateSize(width, height, texture.internalFormat(), texture.format(), + texture.target()); + } + + void setBlend(bool blend) override { + texture.blend = blend; + } + + bool isBlend() const override { + return texture.blend; + } + + inline GLuint getTextureId() const { + return texture.id(); + } + + inline Texture& getTexture() { + return texture; + } + + inline GLenum getRenderTarget() const { + return texture.target(); + } + + inline void setRenderTarget(GLenum renderTarget) { + texture.mTarget = renderTarget; + } + + inline bool isRenderable() const { + return texture.target() != GL_NONE; + } + + void setWrap(GLenum wrap, bool bindTexture = false, bool force = false) { + texture.setWrap(wrap, bindTexture, force); + } + + void setFilter(GLenum filter, bool bindTexture = false, bool force = false) { + texture.setFilter(filter, bindTexture, force); + } + + void bindTexture() const; + void generateTexture(); + + /** + * When the caller frees the texture itself, the caller + * must call this method to tell this layer that it lost + * the texture. + */ + void clearTexture(); + + /** + * Lost the GL context but the layer is still around, mark it invalid internally + * so the dtor knows not to do any GL work + */ + void onGlContextLost(); + +private: + Caches& caches; + + /** + * The texture backing this layer. + */ + Texture texture; +}; // struct GlLayer + +}; // namespace uirenderer +}; // namespace android diff --git a/libs/hwui/GlopBuilder.cpp b/libs/hwui/GlopBuilder.cpp index 34e6d39c9104..8a6e038d8e0d 100644 --- a/libs/hwui/GlopBuilder.cpp +++ b/libs/hwui/GlopBuilder.cpp @@ -16,6 +16,7 @@ #include "GlopBuilder.h" #include "Caches.h" +#include "GlLayer.h" #include "Glop.h" #include "Layer.h" #include "Matrix.h" @@ -440,7 +441,7 @@ GlopBuilder& GlopBuilder::setFillLayer(Texture& texture, const SkColorFilter* co return *this; } -GlopBuilder& GlopBuilder::setFillTextureLayer(Layer& layer, float alpha) { +GlopBuilder& GlopBuilder::setFillTextureLayer(GlLayer& layer, float alpha) { TRIGGER_STAGE(kFillStage); REQUIRE_STAGES(kMeshStage | kRoundRectClipStage); diff --git a/libs/hwui/GlopBuilder.h b/libs/hwui/GlopBuilder.h index 8a8b652c393c..87b1568ed72b 100644 --- a/libs/hwui/GlopBuilder.h +++ b/libs/hwui/GlopBuilder.h @@ -28,6 +28,7 @@ namespace android { namespace uirenderer { class Caches; +class GlLayer; class Matrix4; class Patch; class RenderState; @@ -71,7 +72,7 @@ public: GlopBuilder& setFillClear(); GlopBuilder& setFillLayer(Texture& texture, const SkColorFilter* colorFilter, float alpha, SkBlendMode mode, Blend::ModeOrderSwap modeUsage); - GlopBuilder& setFillTextureLayer(Layer& layer, float alpha); + GlopBuilder& setFillTextureLayer(GlLayer& layer, float alpha); // TODO: setFillLayer normally forces its own wrap & filter mode, // which isn't always correct. GlopBuilder& setFillExternalTexture(Texture& texture, Matrix4& textureTransform); diff --git a/libs/hwui/GpuMemoryTracker.cpp b/libs/hwui/GpuMemoryTracker.cpp index 4fb57019264d..a52ec8738015 100644 --- a/libs/hwui/GpuMemoryTracker.cpp +++ b/libs/hwui/GpuMemoryTracker.cpp @@ -67,13 +67,13 @@ void GpuMemoryTracker::stopTrackingObject() { gObjectStats[static_cast<int>(mType)].count--; } -void GpuMemoryTracker::onGLContextCreated() { - LOG_ALWAYS_FATAL_IF(gGpuThread != 0, "We already have a GL thread? " - "current = %lu, gl thread = %lu", pthread_self(), gGpuThread); +void GpuMemoryTracker::onGpuContextCreated() { + LOG_ALWAYS_FATAL_IF(gGpuThread != 0, "We already have a gpu thread? " + "current = %lu, gpu thread = %lu", pthread_self(), gGpuThread); gGpuThread = pthread_self(); } -void GpuMemoryTracker::onGLContextDestroyed() { +void GpuMemoryTracker::onGpuContextDestroyed() { gGpuThread = 0; if (CC_UNLIKELY(gObjectSet.size() > 0)) { std::stringstream os; diff --git a/libs/hwui/GpuMemoryTracker.h b/libs/hwui/GpuMemoryTracker.h index bfb1bf1ba098..18e2330668b0 100644 --- a/libs/hwui/GpuMemoryTracker.h +++ b/libs/hwui/GpuMemoryTracker.h @@ -15,10 +15,11 @@ */ #pragma once -#include <cutils/log.h> #include <pthread.h> #include <ostream> +#include <log/log.h> + namespace android { namespace uirenderer { @@ -43,8 +44,8 @@ public: GpuObjectType objectType() { return mType; } int objectSize() { return mSize; } - static void onGLContextCreated(); - static void onGLContextDestroyed(); + static void onGpuContextCreated(); + static void onGpuContextDestroyed(); static void dump(); static void dump(std::ostream& stream); static int getInstanceCount(GpuObjectType type); diff --git a/libs/hwui/Interpolator.cpp b/libs/hwui/Interpolator.cpp index f94a22d51d9f..d740c038f36d 100644 --- a/libs/hwui/Interpolator.cpp +++ b/libs/hwui/Interpolator.cpp @@ -16,10 +16,11 @@ #include "Interpolator.h" -#include "utils/MathUtils.h" - #include <algorithm> -#include <cutils/log.h> + +#include <log/log.h> + +#include "utils/MathUtils.h" namespace android { namespace uirenderer { diff --git a/libs/hwui/JankTracker.cpp b/libs/hwui/JankTracker.cpp index ed6b211eef1b..0a9bf5450091 100644 --- a/libs/hwui/JankTracker.cpp +++ b/libs/hwui/JankTracker.cpp @@ -15,19 +15,21 @@ */ #include "JankTracker.h" -#include "Properties.h" -#include "utils/TimeUtils.h" +#include <errno.h> +#include <inttypes.h> #include <algorithm> -#include <cutils/ashmem.h> -#include <cutils/log.h> +#include <cmath> #include <cstdio> -#include <errno.h> -#include <inttypes.h> #include <limits> -#include <cmath> #include <sys/mman.h> +#include <cutils/ashmem.h> +#include <log/log.h> + +#include "Properties.h" +#include "utils/TimeUtils.h" + namespace android { namespace uirenderer { diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp index 88817efa80ac..331bb81208b1 100644 --- a/libs/hwui/Layer.cpp +++ b/libs/hwui/Layer.cpp @@ -16,77 +16,36 @@ #include "Layer.h" -#include "Caches.h" -#include "RenderNode.h" #include "renderstate/RenderState.h" -#include "utils/TraceUtils.h" -#include <utils/Log.h> - -#define ATRACE_LAYER_WORK(label) \ - ATRACE_FORMAT("%s HW Layer DisplayList %s %ux%u", \ - label, \ - (renderNode.get() != NULL) ? renderNode->getName() : "", \ - getWidth(), getHeight()) +#include <SkColorFilter.h> namespace android { namespace uirenderer { -Layer::Layer(RenderState& renderState, uint32_t layerWidth, uint32_t layerHeight) +Layer::Layer(RenderState& renderState, Api api) : GpuMemoryTracker(GpuObjectType::Layer) - , state(State::Uncached) - , caches(Caches::getInstance()) - , renderState(renderState) - , texture(caches) { + , mRenderState(renderState) + , mApi(api) { // TODO: This is a violation of Android's typical ref counting, but it // preserves the old inc/dec ref locations. This should be changed... incStrong(nullptr); - texture.mWidth = layerWidth; - texture.mHeight = layerHeight; + renderState.registerLayer(this); } Layer::~Layer() { - renderState.unregisterLayer(this); SkSafeUnref(colorFilter); - if (texture.mId) { - texture.deleteTexture(); - } -} - -void Layer::onGlContextLost() { - texture.deleteTexture(); + mRenderState.unregisterLayer(this); } void Layer::setColorFilter(SkColorFilter* filter) { SkRefCnt_SafeAssign(colorFilter, filter); } -void Layer::bindTexture() const { - if (texture.mId) { - caches.textureState().bindTexture(texture.target(), texture.mId); - } -} - -void Layer::generateTexture() { - if (!texture.mId) { - glGenTextures(1, &texture.mId); - } -} - -void Layer::clearTexture() { - // There's a rare possibility that Caches could have been destroyed already - // since this method is queued up as a task. - // Since this is a reset method, treat this as non-fatal. - if (caches.isInitialized()) { - caches.textureState().unbindTexture(texture.mId); - } - texture.mId = 0; -} - void Layer::postDecStrong() { - renderState.postDecStrong(this); + mRenderState.postDecStrong(this); } }; // namespace uirenderer diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h index 8e71cd11599d..3b639ee49334 100644 --- a/libs/hwui/Layer.h +++ b/libs/hwui/Layer.h @@ -16,25 +16,13 @@ #pragma once -#include <cutils/compiler.h> -#include <sys/types.h> -#include <utils/StrongPointer.h> #include <utils/RefBase.h> -#include <memory> - -#include <GLES2/gl2.h> #include <GpuMemoryTracker.h> -#include <ui/Region.h> - #include <SkPaint.h> #include <SkBlendMode.h> #include "Matrix.h" -#include "Rect.h" -#include "RenderBuffer.h" -#include "Texture.h" -#include "Vertex.h" namespace android { namespace uirenderer { @@ -43,49 +31,33 @@ namespace uirenderer { // Layers /////////////////////////////////////////////////////////////////////////////// -// Forward declarations -class Caches; class RenderState; /** - * A layer has dimensions and is backed by an OpenGL texture or FBO. + * A layer has dimensions and is backed by a backend specific texture or framebuffer. */ class Layer : public VirtualLightRefBase, GpuMemoryTracker { public: - // layer lifecycle, controlled from outside - enum class State { - Uncached = 0, - InCache = 1, - FailedToCache = 2, - RemovedFromCache = 3, - DeletedFromCache = 4, - InGarbageList = 5, + enum class Api { + OpenGL = 0, + Vulkan = 1, }; - State state; // public for logging/debugging purposes - Layer(RenderState& renderState, uint32_t layerWidth, uint32_t layerHeight); + Api getApi() const { + return mApi; + } + ~Layer(); - inline uint32_t getWidth() const { - return texture.mWidth; - } + virtual uint32_t getWidth() const = 0; - inline uint32_t getHeight() const { - return texture.mHeight; - } + virtual uint32_t getHeight() const = 0; - void setSize(uint32_t width, uint32_t height) { - texture.updateSize(width, height, texture.internalFormat(), texture.format(), - texture.target()); - } + virtual void setSize(uint32_t width, uint32_t height) = 0; - inline void setBlend(bool blend) { - texture.blend = blend; - } + virtual void setBlend(bool blend) = 0; - inline bool isBlend() const { - return texture.blend; - } + virtual bool isBlend() const = 0; inline void setForceFilter(bool forceFilter) { this->forceFilter = forceFilter; @@ -112,50 +84,12 @@ public: return mode; } - inline GLuint getTextureId() const { - return texture.id(); - } - - inline Texture& getTexture() { - return texture; - } - - inline GLenum getRenderTarget() const { - return texture.target(); - } - - inline void setRenderTarget(GLenum renderTarget) { - texture.mTarget = renderTarget; - } - - inline bool isRenderable() const { - return texture.target() != GL_NONE; - } - - void setWrap(GLenum wrap, bool bindTexture = false, bool force = false) { - texture.setWrap(wrap, bindTexture, force); - } - - void setFilter(GLenum filter, bool bindTexture = false, bool force = false) { - texture.setFilter(filter, bindTexture, force); - } - inline SkColorFilter* getColorFilter() const { return colorFilter; } void setColorFilter(SkColorFilter* filter); - void bindTexture() const; - void generateTexture(); - - /** - * When the caller frees the texture itself, the caller - * must call this method to tell this layer that it lost - * the texture. - */ - void clearTexture(); - inline mat4& getTexTransform() { return texTransform; } @@ -170,21 +104,13 @@ public: */ void postDecStrong(); - /** - * Lost the GL context but the layer is still around, mark it invalid internally - * so the dtor knows not to do any GL work - */ - void onGlContextLost(); - -private: - Caches& caches; +protected: + Layer(RenderState& renderState, Api api); - RenderState& renderState; + RenderState& mRenderState; - /** - * The texture backing this layer. - */ - Texture texture; +private: + Api mApi; /** * Color filter used to draw this layer. Optional. diff --git a/libs/hwui/OpenGLReadback.cpp b/libs/hwui/OpenGLReadback.cpp index 938b6efa7901..c460c0d2dfd4 100644 --- a/libs/hwui/OpenGLReadback.cpp +++ b/libs/hwui/OpenGLReadback.cpp @@ -19,7 +19,7 @@ #include "Caches.h" #include "Image.h" #include "GlopBuilder.h" -#include "Layer.h" +#include "GlLayer.h" #include "renderstate/RenderState.h" #include "renderthread/EglManager.h" #include "utils/GLUtils.h" @@ -262,7 +262,7 @@ CopyResult OpenGLReadbackImpl::copyImageInto(EGLImageKHR eglImage, } bool OpenGLReadbackImpl::copyLayerInto(renderthread::RenderThread& renderThread, - Layer& layer, SkBitmap* bitmap) { + GlLayer& layer, SkBitmap* bitmap) { return CopyResult::Success == copyTextureInto(Caches::getInstance(), renderThread.renderState(), layer.getTexture(), layer.getTexTransform(), Rect(), bitmap); diff --git a/libs/hwui/OpenGLReadback.h b/libs/hwui/OpenGLReadback.h index f4ebabcdebe5..c9222cff51da 100644 --- a/libs/hwui/OpenGLReadback.h +++ b/libs/hwui/OpenGLReadback.h @@ -22,7 +22,7 @@ namespace android { namespace uirenderer { class Matrix4; -class Layer; +class GlLayer; class OpenGLReadback : public Readback { public: @@ -49,7 +49,7 @@ public: /** * Copies the layer's contents into the provided bitmap. */ - static bool copyLayerInto(renderthread::RenderThread& renderThread, Layer& layer, + static bool copyLayerInto(renderthread::RenderThread& renderThread, GlLayer& layer, SkBitmap* bitmap); protected: diff --git a/libs/hwui/PixelBuffer.h b/libs/hwui/PixelBuffer.h index 9536bc807fbc..77d5e413cb36 100644 --- a/libs/hwui/PixelBuffer.h +++ b/libs/hwui/PixelBuffer.h @@ -18,7 +18,8 @@ #define ANDROID_HWUI_PIXEL_BUFFER_H #include <GLES3/gl3.h> -#include <cutils/log.h> + +#include <log/log.h> namespace android { namespace uirenderer { diff --git a/libs/hwui/Properties.cpp b/libs/hwui/Properties.cpp index 848161e44604..a7663817721d 100644 --- a/libs/hwui/Properties.cpp +++ b/libs/hwui/Properties.cpp @@ -13,17 +13,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include "Properties.h" +#include "Properties.h" #include "Debug.h" -#include <cutils/compiler.h> -#include <cutils/log.h> -#include <cutils/properties.h> - #include <algorithm> #include <cstdlib> +#include <log/log.h> +#include <cutils/compiler.h> +#include <cutils/properties.h> + namespace android { namespace uirenderer { diff --git a/libs/hwui/RecordedOp.h b/libs/hwui/RecordedOp.h index f9a7c36f2786..dea2be68c8db 100644 --- a/libs/hwui/RecordedOp.h +++ b/libs/hwui/RecordedOp.h @@ -17,6 +17,7 @@ #pragma once #include "font/FontUtil.h" +#include "GlLayer.h" #include "Matrix.h" #include "Rect.h" #include "RenderNode.h" @@ -413,7 +414,7 @@ struct TextOnPathOp : RecordedOp { }; struct TextureLayerOp : RecordedOp { - TextureLayerOp(BASE_PARAMS_PAINTLESS, Layer* layer) + TextureLayerOp(BASE_PARAMS_PAINTLESS, GlLayer* layer) : SUPER_PAINTLESS(TextureLayerOp) , layer(layer) {} @@ -424,7 +425,7 @@ struct TextureLayerOp : RecordedOp { , layer(op.layer) { } - Layer* layer; + GlLayer* layer; }; //////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp index ee6279dccb92..b5e5d6801f99 100644 --- a/libs/hwui/RecordingCanvas.cpp +++ b/libs/hwui/RecordingCanvas.cpp @@ -606,13 +606,14 @@ void RecordingCanvas::drawLayer(DeferredLayerUpdater* layerHandle) { // We ref the DeferredLayerUpdater due to its thread-safe ref-counting semantics. mDisplayList->ref(layerHandle); + LOG_ALWAYS_FATAL_IF(layerHandle->backingLayer()->getApi() != Layer::Api::OpenGL); // Note that the backing layer has *not* yet been updated, so don't trust // its width, height, transform, etc...! addOp(alloc().create_trivial<TextureLayerOp>( Rect(layerHandle->getWidth(), layerHandle->getHeight()), *(mState.currentSnapshot()->transform), getRecordedClip(), - layerHandle->backingLayer())); + static_cast<GlLayer*>(layerHandle->backingLayer()))); } void RecordingCanvas::callDrawGLFunction(Functor* functor, diff --git a/libs/hwui/SkiaCanvasProxy.cpp b/libs/hwui/SkiaCanvasProxy.cpp index c5156cfd6844..f32612d21319 100644 --- a/libs/hwui/SkiaCanvasProxy.cpp +++ b/libs/hwui/SkiaCanvasProxy.cpp @@ -16,9 +16,11 @@ #include "SkiaCanvasProxy.h" -#include "hwui/Bitmap.h" +#include <memory> + +#include <log/log.h> -#include <cutils/log.h> +#include "hwui/Bitmap.h" #include <SkLatticeIter.h> #include <SkPatchUtils.h> #include <SkPaint.h> @@ -30,8 +32,6 @@ #include <SkSurface.h> #include <SkTextBlobRunIterator.h> -#include <memory> - namespace android { namespace uirenderer { diff --git a/libs/hwui/SkiaShader.cpp b/libs/hwui/SkiaShader.cpp index fadb96065105..92399864ff23 100644 --- a/libs/hwui/SkiaShader.cpp +++ b/libs/hwui/SkiaShader.cpp @@ -18,7 +18,6 @@ #include "Caches.h" #include "Extensions.h" -#include "Layer.h" #include "Matrix.h" #include "Texture.h" #include "hwui/Bitmap.h" @@ -317,42 +316,6 @@ bool tryStoreCompose(Caches& caches, const SkShader& shader, const Matrix4& mode return true; } -bool tryStoreLayer(Caches& caches, const SkShader& shader, const Matrix4& modelViewMatrix, - GLuint* textureUnit, ProgramDescription* description, - SkiaShaderData::LayerShaderData* outData) { - Layer* layer; - if (!shader.asACustomShader(reinterpret_cast<void**>(&layer))) { - return false; - } - - description->hasBitmap = true; - outData->layer = layer; - outData->bitmapSampler = (*textureUnit)++; - - const float width = layer->getWidth(); - const float height = layer->getHeight(); - - computeScreenSpaceMatrix(outData->textureTransform, SkMatrix::I(), shader.getLocalMatrix(), - modelViewMatrix); - - outData->textureDimension[0] = 1.0f / width; - outData->textureDimension[1] = 1.0f / height; - return true; -} - -void applyLayer(Caches& caches, const SkiaShaderData::LayerShaderData& data) { - caches.textureState().activateTexture(data.bitmapSampler); - - data.layer->bindTexture(); - data.layer->setWrap(GL_CLAMP_TO_EDGE); - data.layer->setFilter(GL_LINEAR); - - glUniform1i(caches.program().getUniform("bitmapSampler"), data.bitmapSampler); - glUniformMatrix4fv(caches.program().getUniform("textureTransform"), 1, - GL_FALSE, &data.textureTransform.data[0]); - glUniform2fv(caches.program().getUniform("textureDimension"), 1, &data.textureDimension[0]); -} - void SkiaShader::store(Caches& caches, const SkShader& shader, const Matrix4& modelViewMatrix, GLuint* textureUnit, ProgramDescription* description, SkiaShaderData* outData) { @@ -374,12 +337,6 @@ void SkiaShader::store(Caches& caches, const SkShader& shader, const Matrix4& mo return; } - if (tryStoreLayer(caches, shader, modelViewMatrix, - textureUnit, description, &outData->layerData)) { - outData->skiaShaderType = kLayer_SkiaShaderType; - return; - } - // Unknown/unsupported type, so explicitly ignore shader outData->skiaShaderType = kNone_SkiaShaderType; } @@ -394,10 +351,6 @@ void SkiaShader::apply(Caches& caches, const SkiaShaderData& data, if (data.skiaShaderType & kBitmap_SkiaShaderType) { applyBitmap(caches, data.bitmapData); } - - if (data.skiaShaderType == kLayer_SkiaShaderType) { - applyLayer(caches, data.layerData); - } } }; // namespace uirenderer diff --git a/libs/hwui/SkiaShader.h b/libs/hwui/SkiaShader.h index d2f37cda9cb3..ab578d540774 100644 --- a/libs/hwui/SkiaShader.h +++ b/libs/hwui/SkiaShader.h @@ -29,7 +29,6 @@ namespace uirenderer { class Caches; class Extensions; -class Layer; class Texture; struct ProgramDescription; @@ -45,7 +44,6 @@ enum SkiaShaderType { kBitmap_SkiaShaderType = 1, kGradient_SkiaShaderType = 2, kCompose_SkiaShaderType = kBitmap_SkiaShaderType | kGradient_SkiaShaderType, - kLayer_SkiaShaderType = 4, }; struct SkiaShaderData { @@ -71,15 +69,6 @@ struct SkiaShaderData { GLuint gradientSampler; GLenum wrapST; } gradientData; - struct LayerShaderData { - Layer* layer; - GLuint bitmapSampler; - GLenum wrapS; - GLenum wrapT; - - Matrix4 textureTransform; - float textureDimension[2]; - } layerData; }; class SkiaShader { diff --git a/libs/hwui/Texture.h b/libs/hwui/Texture.h index c75e88f5dd6e..b8397ccade9c 100644 --- a/libs/hwui/Texture.h +++ b/libs/hwui/Texture.h @@ -159,10 +159,10 @@ public: */ void* isInUse = nullptr; private: - // TODO: Temporarily grant private access to Layer, remove once - // Layer can be de-tangled from being a dual-purpose render target + // TODO: Temporarily grant private access to GlLayer, remove once + // GlLayer can be de-tangled from being a dual-purpose render target // and external texture wrapper - friend class Layer; + friend class GlLayer; // Returns true if the size changed, false if it was the same bool updateSize(uint32_t width, uint32_t height, GLint internalFormat, diff --git a/libs/hwui/VkLayer.cpp b/libs/hwui/VkLayer.cpp new file mode 100644 index 000000000000..391acf13acd0 --- /dev/null +++ b/libs/hwui/VkLayer.cpp @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "VkLayer.h" + +#include "renderstate/RenderState.h" + +#include <SkCanvas.h> +#include <SkSurface.h> + +namespace android { +namespace uirenderer { + +void VkLayer::updateTexture() { + sk_sp<SkSurface> surface; + SkImageInfo info = SkImageInfo::MakeS32(mWidth, mHeight, kPremul_SkAlphaType); + surface = SkSurface::MakeRenderTarget(mRenderState.getGrContext(), SkBudgeted::kNo, info); + surface->getCanvas()->clear(SK_ColorBLUE); + mImage = surface->makeImageSnapshot(SkBudgeted::kNo, SkSurface::kNo_ForceUnique); +} + +void VkLayer::onVkContextDestroyed() { + mImage = nullptr; +} + +}; // namespace uirenderer +}; // namespace android diff --git a/libs/hwui/VkLayer.h b/libs/hwui/VkLayer.h new file mode 100644 index 000000000000..39522b3c0dda --- /dev/null +++ b/libs/hwui/VkLayer.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "Layer.h" + +#include <SkImage.h> + +namespace android { +namespace uirenderer { +/** + * A layer has dimensions and is backed by a VkImage. + */ +class VkLayer : public Layer { +public: + VkLayer(RenderState& renderState, uint32_t layerWidth, uint32_t layerHeight) + : Layer(renderState, Api::Vulkan) {} + + virtual ~VkLayer() {} + + uint32_t getWidth() const override { + return mWidth; + } + + uint32_t getHeight() const override { + return mHeight; + } + + void setSize(uint32_t width, uint32_t height) override { + mWidth = width; + mHeight = height; + } + + void setBlend(bool blend) override { + mBlend = blend; + } + + bool isBlend() const override { + return mBlend; + } + + sk_sp<SkImage> getImage() { + return mImage; + } + + void updateTexture(); + + // If we've destroyed the vulkan context (VkInstance, VkDevice, etc.), we must make sure to + // destroy any VkImages that were made with that context. + void onVkContextDestroyed(); + +private: + int mWidth; + int mHeight; + bool mBlend; + + sk_sp<SkImage> mImage; + +}; // struct VkLayer + +}; // namespace uirenderer +}; // namespace android diff --git a/libs/hwui/hwui/MinikinSkia.cpp b/libs/hwui/hwui/MinikinSkia.cpp index f172473d1652..956f66ed22cb 100644 --- a/libs/hwui/hwui/MinikinSkia.cpp +++ b/libs/hwui/hwui/MinikinSkia.cpp @@ -16,9 +16,10 @@ #include "MinikinSkia.h" +#include <log/log.h> + #include <SkPaint.h> #include <SkTypeface.h> -#include <cutils/log.h> namespace android { diff --git a/libs/hwui/hwui/MinikinUtils.cpp b/libs/hwui/hwui/MinikinUtils.cpp index 8dd165c46d21..713e5099da26 100644 --- a/libs/hwui/hwui/MinikinUtils.cpp +++ b/libs/hwui/hwui/MinikinUtils.cpp @@ -13,15 +13,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #include "MinikinUtils.h" +#include <string> + +#include <log/log.h> + #include "Paint.h" #include "SkPathMeasure.h" #include "Typeface.h" -#include <cutils/log.h> -#include <string> - namespace android { minikin::FontStyle MinikinUtils::prepareMinikinPaint(minikin::MinikinPaint* minikinPaint, diff --git a/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp b/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp index fb2134c51e22..419c8a99fe74 100644 --- a/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp +++ b/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp @@ -52,6 +52,11 @@ void GLFunctorDrawable::onDraw(SkCanvas* canvas) { canvas->flush(); + if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaVulkan) { + canvas->clear(SK_ColorRED); + return; + } + SkImageInfo canvasInfo = canvas->imageInfo(); SkMatrix44 mat4(canvas->getTotalMatrix()); diff --git a/libs/hwui/pipeline/skia/LayerDrawable.cpp b/libs/hwui/pipeline/skia/LayerDrawable.cpp index f2af4a891b12..2ebfbcc1f18e 100644 --- a/libs/hwui/pipeline/skia/LayerDrawable.cpp +++ b/libs/hwui/pipeline/skia/LayerDrawable.cpp @@ -14,8 +14,12 @@ * limitations under the License. */ +#include "GlLayer.h" #include "LayerDrawable.h" +#include "VkLayer.h" + #include "SkColorFilter.h" +#include "SkSurface.h" #include "gl/GrGLTypes.h" namespace android { @@ -35,16 +39,27 @@ bool LayerDrawable::DrawLayer(GrContext* context, SkCanvas* canvas, Layer* layer layer->getTransform().copyTo(transform); canvas->concat(transform); } - GrGLTextureInfo externalTexture; - externalTexture.fTarget = layer->getRenderTarget(); - externalTexture.fID = layer->getTextureId(); - GrBackendTextureDesc textureDescription; - textureDescription.fWidth = layer->getWidth(); - textureDescription.fHeight = layer->getHeight(); - textureDescription.fConfig = kRGBA_8888_GrPixelConfig; - textureDescription.fOrigin = kTopLeft_GrSurfaceOrigin; - textureDescription.fTextureHandle = reinterpret_cast<GrBackendObject>(&externalTexture); - sk_sp<SkImage> layerImage = SkImage::MakeFromTexture(context, textureDescription); + + sk_sp<SkImage> layerImage; + if (layer->getApi() == Layer::Api::OpenGL) { + GlLayer* glLayer = static_cast<GlLayer*>(layer); + GrGLTextureInfo externalTexture; + externalTexture.fTarget = glLayer->getRenderTarget(); + externalTexture.fID = glLayer->getTextureId(); + GrBackendTextureDesc textureDescription; + textureDescription.fWidth = glLayer->getWidth(); + textureDescription.fHeight = glLayer->getHeight(); + textureDescription.fConfig = kRGBA_8888_GrPixelConfig; + textureDescription.fOrigin = kTopLeft_GrSurfaceOrigin; + textureDescription.fTextureHandle = reinterpret_cast<GrBackendObject>(&externalTexture); + layerImage = SkImage::MakeFromTexture(context, textureDescription); + } else { + SkASSERT(layer->getApi() == Layer::Api::Vulkan); + VkLayer* vkLayer = static_cast<VkLayer*>(layer); + canvas->clear(SK_ColorGREEN); + layerImage = vkLayer->getImage(); + } + if (layerImage) { SkPaint paint; paint.setAlpha(layer->getAlpha()); diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp index c8258f748d7e..65a1dc38ab8e 100644 --- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp +++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp @@ -17,6 +17,7 @@ #include "SkiaOpenGLPipeline.h" #include "DeferredLayerUpdater.h" +#include "GlLayer.h" #include "LayerDrawable.h" #include "renderthread/EglManager.h" #include "renderthread/Frame.h" @@ -136,7 +137,7 @@ bool SkiaOpenGLPipeline::copyLayerInto(DeferredLayerUpdater* deferredLayer, SkBi DeferredLayerUpdater* SkiaOpenGLPipeline::createTextureLayer() { mEglManager.initialize(); - Layer* layer = new Layer(mRenderThread.renderState(), 0, 0); + GlLayer* layer = new GlLayer(mRenderThread.renderState(), 0, 0); layer->generateTexture(); return new DeferredLayerUpdater(layer); } diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp index 0d3f4ef6a11a..910c339c4d1c 100644 --- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp +++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp @@ -22,6 +22,7 @@ #include "renderstate/RenderState.h" #include "SkiaPipeline.h" #include "SkiaProfileRenderer.h" +#include "VkLayer.h" #include <SkSurface.h> #include <SkTypes.h> @@ -119,7 +120,8 @@ bool SkiaVulkanPipeline::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bi DeferredLayerUpdater* SkiaVulkanPipeline::createTextureLayer() { mVkManager.initialize(); - Layer* layer = new Layer(mRenderThread.renderState(), 0, 0); + + VkLayer* layer = new VkLayer(mRenderThread.renderState(), 0, 0); return new DeferredLayerUpdater(layer); } diff --git a/libs/hwui/renderstate/RenderState.cpp b/libs/hwui/renderstate/RenderState.cpp index 72af7c98e477..17ee390c90bd 100644 --- a/libs/hwui/renderstate/RenderState.cpp +++ b/libs/hwui/renderstate/RenderState.cpp @@ -13,6 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include "GlLayer.h" +#include "VkLayer.h" #include <GpuMemoryTracker.h> #include "renderstate/RenderState.h" @@ -40,7 +42,7 @@ RenderState::~RenderState() { void RenderState::onGLContextCreated() { LOG_ALWAYS_FATAL_IF(mBlend || mMeshState || mScissor || mStencil, "State object lifecycle not managed correctly"); - GpuMemoryTracker::onGLContextCreated(); + GpuMemoryTracker::onGpuContextCreated(); mBlend = new Blend(); mMeshState = new MeshState(); @@ -55,7 +57,9 @@ void RenderState::onGLContextCreated() { } static void layerLostGlContext(Layer* layer) { - layer->onGlContextLost(); + LOG_ALWAYS_FATAL_IF(layer->getApi() != Layer::Api::OpenGL, + "layerLostGlContext on non GL layer"); + static_cast<GlLayer*>(layer)->onGlContextLost(); } void RenderState::onGLContextDestroyed() { @@ -75,7 +79,29 @@ void RenderState::onGLContextDestroyed() { delete mStencil; mStencil = nullptr; - GpuMemoryTracker::onGLContextDestroyed(); + GpuMemoryTracker::onGpuContextDestroyed(); +} + +void RenderState::onVkContextCreated() { + LOG_ALWAYS_FATAL_IF(mBlend || mMeshState || mScissor || mStencil, + "State object lifecycle not managed correctly"); + GpuMemoryTracker::onGpuContextCreated(); +} + +static void layerDestroyedVkContext(Layer* layer) { + LOG_ALWAYS_FATAL_IF(layer->getApi() != Layer::Api::Vulkan, + "layerLostVkContext on non Vulkan layer"); + static_cast<VkLayer*>(layer)->onVkContextDestroyed(); +} + +void RenderState::onVkContextDestroyed() { + mLayerPool.clear(); + std::for_each(mActiveLayers.begin(), mActiveLayers.end(), layerDestroyedVkContext); + GpuMemoryTracker::onGpuContextDestroyed(); +} + +GrContext* RenderState::getGrContext() const { + return mRenderThread.getGrContext(); } void RenderState::flush(Caches::FlushMode mode) { diff --git a/libs/hwui/renderstate/RenderState.h b/libs/hwui/renderstate/RenderState.h index 3d119dc9e290..d183a15f3842 100644 --- a/libs/hwui/renderstate/RenderState.h +++ b/libs/hwui/renderstate/RenderState.h @@ -35,6 +35,8 @@ #include <utils/RefBase.h> #include <private/hwui/DrawGlInfo.h> +class GrContext; + namespace android { namespace uirenderer { @@ -56,6 +58,9 @@ public: void onGLContextCreated(); void onGLContextDestroyed(); + void onVkContextCreated(); + void onVkContextDestroyed(); + void flush(Caches::FlushMode flushMode); void setViewport(GLsizei width, GLsizei height); @@ -98,6 +103,8 @@ public: OffscreenBufferPool& layerPool() { return mLayerPool; } + GrContext* getGrContext() const; + void dump(); private: diff --git a/libs/hwui/renderthread/OpenGLPipeline.cpp b/libs/hwui/renderthread/OpenGLPipeline.cpp index df085998435b..df40a44a16cb 100644 --- a/libs/hwui/renderthread/OpenGLPipeline.cpp +++ b/libs/hwui/renderthread/OpenGLPipeline.cpp @@ -19,6 +19,7 @@ #include "DeferredLayerUpdater.h" #include "EglManager.h" #include "Frame.h" +#include "GlLayer.h" #include "ProfileRenderer.h" #include "renderstate/RenderState.h" #include "OpenGLReadback.h" @@ -120,12 +121,13 @@ bool OpenGLPipeline::swapBuffers(const Frame& frame, bool drew, const SkRect& sc bool OpenGLPipeline::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) { ATRACE_CALL(); layer->apply(); - return OpenGLReadbackImpl::copyLayerInto(mRenderThread, *(layer->backingLayer()), bitmap); + return OpenGLReadbackImpl::copyLayerInto(mRenderThread, + static_cast<GlLayer&>(*layer->backingLayer()), bitmap); } DeferredLayerUpdater* OpenGLPipeline::createTextureLayer() { mEglManager.initialize(); - Layer* layer = new Layer(mRenderThread.renderState(), 0, 0); + GlLayer* layer = new GlLayer(mRenderThread.renderState(), 0, 0); Caches::getInstance().textureState().activateTexture(0); layer->generateTexture(); diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp index 68c04afb2e08..2b9074499c2a 100644 --- a/libs/hwui/renderthread/VulkanManager.cpp +++ b/libs/hwui/renderthread/VulkanManager.cpp @@ -19,6 +19,7 @@ #include "DeviceInfo.h" #include "Properties.h" #include "RenderThread.h" +#include "renderstate/RenderState.h" #include <GrContext.h> #include <GrTypes.h> @@ -37,10 +38,14 @@ VulkanManager::VulkanManager(RenderThread& thread) : mRenderThread(thread) { void VulkanManager::destroy() { if (!hasVkContext()) return; + mRenderThread.renderState().onVkContextDestroyed(); + mRenderThread.setGrContext(nullptr); + if (VK_NULL_HANDLE != mCommandPool) { mDestroyCommandPool(mBackendContext->fDevice, mCommandPool, nullptr); mCommandPool = VK_NULL_HANDLE; } + mBackendContext.reset(); } void VulkanManager::initialize() { @@ -105,6 +110,8 @@ void VulkanManager::initialize() { if (Properties::enablePartialUpdates && Properties::useBufferAge) { mSwapBehavior = SwapBehavior::BufferAge; } + + mRenderThread.renderState().onVkContextCreated(); } // Returns the next BackbufferInfo to use for the next draw. The function will make sure all @@ -156,6 +163,9 @@ SkSurface* VulkanManager::getBackbufferSurface(VulkanSurface* surface) { if (!createSwapchain(surface)) { return nullptr; } + backbuffer = getAvailableBackbuffer(surface); + res = mResetFences(mBackendContext->fDevice, 2, backbuffer->mUsageFences); + SkASSERT(VK_SUCCESS == res); // acquire the image res = mAcquireNextImageKHR(mBackendContext->fDevice, surface->mSwapchain, UINT64_MAX, diff --git a/libs/hwui/tests/unit/DeferredLayerUpdaterTests.cpp b/libs/hwui/tests/unit/DeferredLayerUpdaterTests.cpp index 0326aa91bb18..f1b888268fde 100644 --- a/libs/hwui/tests/unit/DeferredLayerUpdaterTests.cpp +++ b/libs/hwui/tests/unit/DeferredLayerUpdaterTests.cpp @@ -15,6 +15,7 @@ */ #include "DeferredLayerUpdater.h" +#include "GlLayer.h" #include "renderthread/OpenGLPipeline.h" #include "tests/common/TestUtils.h" @@ -32,7 +33,10 @@ RENDERTHREAD_TEST(DeferredLayerUpdater, updateLayer) { // updates are deferred so the backing layer should still be in its default state - EXPECT_EQ((uint32_t)GL_NONE, layerUpdater->backingLayer()->getRenderTarget()); + if (layerUpdater->backingLayer()->getApi() == Layer::Api::OpenGL) { + GlLayer* glLayer = static_cast<GlLayer*>(layerUpdater->backingLayer()); + EXPECT_EQ((uint32_t)GL_NONE, glLayer->getRenderTarget()); + } EXPECT_EQ(0u, layerUpdater->backingLayer()->getWidth()); EXPECT_EQ(0u, layerUpdater->backingLayer()->getHeight()); EXPECT_FALSE(layerUpdater->backingLayer()->getForceFilter()); @@ -45,7 +49,10 @@ RENDERTHREAD_TEST(DeferredLayerUpdater, updateLayer) { layerUpdater->updateLayer(true, GL_TEXTURE_EXTERNAL_OES, scaledMatrix.data); // the backing layer should now have all the properties applied. - EXPECT_EQ((uint32_t)GL_TEXTURE_EXTERNAL_OES, layerUpdater->backingLayer()->getRenderTarget()); + if (layerUpdater->backingLayer()->getApi() == Layer::Api::OpenGL) { + GlLayer* glLayer = static_cast<GlLayer*>(layerUpdater->backingLayer()); + EXPECT_EQ((uint32_t)GL_TEXTURE_EXTERNAL_OES, glLayer->getRenderTarget()); + } EXPECT_EQ(100u, layerUpdater->backingLayer()->getWidth()); EXPECT_EQ(100u, layerUpdater->backingLayer()->getHeight()); EXPECT_TRUE(layerUpdater->backingLayer()->getForceFilter()); diff --git a/libs/hwui/tests/unit/FrameBuilderTests.cpp b/libs/hwui/tests/unit/FrameBuilderTests.cpp index 21394ae6144a..71c7516be3ba 100644 --- a/libs/hwui/tests/unit/FrameBuilderTests.cpp +++ b/libs/hwui/tests/unit/FrameBuilderTests.cpp @@ -19,6 +19,7 @@ #include <BakedOpState.h> #include <DeferredLayerUpdater.h> #include <FrameBuilder.h> +#include <GlLayer.h> #include <LayerUpdateQueue.h> #include <RecordedOp.h> #include <RecordingCanvas.h> @@ -698,7 +699,10 @@ RENDERTHREAD_TEST(FrameBuilder, textureLayer_combineMatrices) { RENDERTHREAD_TEST(FrameBuilder, textureLayer_reject) { auto layerUpdater = TestUtils::createTextureLayerUpdater(renderThread, 100, 100, SkMatrix::MakeTrans(5, 5)); - layerUpdater->backingLayer()->setRenderTarget(GL_NONE); // Should be rejected + if (layerUpdater->backingLayer()->getApi() != Layer::Api::OpenGL) return; + + GlLayer* glLayer = static_cast<GlLayer*>(layerUpdater->backingLayer()); + glLayer->setRenderTarget(GL_NONE); // Should be rejected auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200, [&layerUpdater](RenderProperties& props, RecordingCanvas& canvas) { diff --git a/libs/hwui/tests/unit/GpuMemoryTrackerTests.cpp b/libs/hwui/tests/unit/GpuMemoryTrackerTests.cpp index aa1dcb2ea51b..8cbd24edbde2 100644 --- a/libs/hwui/tests/unit/GpuMemoryTrackerTests.cpp +++ b/libs/hwui/tests/unit/GpuMemoryTrackerTests.cpp @@ -51,7 +51,7 @@ static void destroyEglContext() { TEST(GpuMemoryTracker, sizeCheck) { destroyEglContext(); - GpuMemoryTracker::onGLContextCreated(); + GpuMemoryTracker::onGpuContextCreated(); ASSERT_EQ(0, GpuMemoryTracker::getTotalSize(GpuObjectType::Texture)); ASSERT_EQ(0, GpuMemoryTracker::getInstanceCount(GpuObjectType::Texture)); { @@ -66,5 +66,5 @@ TEST(GpuMemoryTracker, sizeCheck) { } ASSERT_EQ(0, GpuMemoryTracker::getTotalSize(GpuObjectType::Texture)); ASSERT_EQ(0, GpuMemoryTracker::getInstanceCount(GpuObjectType::Texture)); - GpuMemoryTracker::onGLContextDestroyed(); + GpuMemoryTracker::onGpuContextDestroyed(); } diff --git a/libs/hwui/utils/GLUtils.h b/libs/hwui/utils/GLUtils.h index 94818b2dc44f..c12747805293 100644 --- a/libs/hwui/utils/GLUtils.h +++ b/libs/hwui/utils/GLUtils.h @@ -18,7 +18,7 @@ #include "Debug.h" -#include <cutils/log.h> +#include <log/log.h> namespace android { namespace uirenderer { diff --git a/libs/input/PointerController.cpp b/libs/input/PointerController.cpp index 0b22ad5ba470..7c6046789cdc 100644 --- a/libs/input/PointerController.cpp +++ b/libs/input/PointerController.cpp @@ -15,7 +15,6 @@ */ #define LOG_TAG "PointerController" - //#define LOG_NDEBUG 0 // Log debug messages about pointer updates @@ -23,8 +22,9 @@ #include "PointerController.h" -#include <cutils/log.h> +#include <log/log.h> +// ToDo: Fix code to be warning free #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-parameter" #include <SkBitmap.h> diff --git a/libs/input/SpriteController.cpp b/libs/input/SpriteController.cpp index 18ebd47558bc..4991f0434bc2 100644 --- a/libs/input/SpriteController.cpp +++ b/libs/input/SpriteController.cpp @@ -15,15 +15,15 @@ */ #define LOG_TAG "Sprites" - //#define LOG_NDEBUG 0 #include "SpriteController.h" -#include <cutils/log.h> +#include <log/log.h> #include <utils/String8.h> #include <gui/Surface.h> +// ToDo: Fix code to be warning free #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-parameter" #include <SkBitmap.h> diff --git a/media/mca/filterpacks/native/base/geometry.cpp b/media/mca/filterpacks/native/base/geometry.cpp index 7812d5020c3f..44b13e4fff15 100644 --- a/media/mca/filterpacks/native/base/geometry.cpp +++ b/media/mca/filterpacks/native/base/geometry.cpp @@ -13,10 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#define LOG_TAG "geometry" -#include <cutils/log.h> #include <cmath> +#include <log/log.h> + #include "geometry.h" namespace android { diff --git a/media/mca/filterpacks/native/base/time_util.cpp b/media/mca/filterpacks/native/base/time_util.cpp index 1a78a953de69..7d383df5aea2 100644 --- a/media/mca/filterpacks/native/base/time_util.cpp +++ b/media/mca/filterpacks/native/base/time_util.cpp @@ -13,14 +13,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#define LOG_TAG "time_util" #include "time_util.h" #include "utilities.h" -#include <cutils/log.h> #include <sys/time.h> #include <map> +#include <log/log.h> + namespace android { namespace filterfw { diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml index 5574753bee6c..62f6136026df 100644 --- a/packages/SystemUI/AndroidManifest.xml +++ b/packages/SystemUI/AndroidManifest.xml @@ -483,6 +483,21 @@ android:exported="true" android:enabled="@bool/config_enableKeyguardService" /> + <activity android:name=".keyguard.WorkLockActivity" + android:label="@string/accessibility_desc_work_lock" + android:permission="android.permission.MANAGE_USERS" + android:exported="false" + android:launchMode="singleTop" + android:excludeFromRecents="true" + android:stateNotNeeded="true" + android:resumeWhilePausing="true" + android:theme="@android:style/Theme.Black.NoTitleBar"> + <intent-filter> + <action android:name="android.app.action.CONFIRM_DEVICE_CREDENTIAL_WITH_USER" /> + <category android:name="android.intent.category.DEFAULT" /> + </intent-filter> + </activity> + <activity android:name=".Somnambulator" android:label="@string/start_dreams" android:icon="@mipmap/ic_launcher_dreams" diff --git a/packages/SystemUI/res/layout/qs_customize_panel_content.xml b/packages/SystemUI/res/layout/qs_customize_panel_content.xml index ca0248e066eb..04d0e6524eac 100644 --- a/packages/SystemUI/res/layout/qs_customize_panel_content.xml +++ b/packages/SystemUI/res/layout/qs_customize_panel_content.xml @@ -27,7 +27,7 @@ <android.support.v7.widget.RecyclerView android:id="@android:id/list" - android:layout_width="@dimen/notification_panel_width" + android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:scrollIndicators="top" diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index 34a0397eca8b..05963ac9ff30 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -460,6 +460,8 @@ <string name="accessibility_desc_settings">Settings</string> <!-- Content description for the recent apps panel (not shown on the screen). [CHAR LIMIT=NONE] --> <string name="accessibility_desc_recent_apps">Overview.</string> + <!-- Content description for the graphic shown instead of an activity window while the activity is locked (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_desc_work_lock">Work lock screen</string> <!-- Content description for the close button in the zen mode panel introduction message. [CHAR LIMIT=NONE] --> <string name="accessibility_desc_close">Close</string> diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java index 8e5db97dd27d..ce89aab30911 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java @@ -326,6 +326,12 @@ public class KeyguardViewMediator extends SystemUI { */ private boolean mPendingLock; + /** + * Controller for showing individual "work challenge" lock screen windows inside managed profile + * tasks when the current user has been unlocked but the profile is still locked. + */ + private WorkLockActivityController mWorkLockController; + private boolean mLockLater; private boolean mWakeAndUnlocking; @@ -708,6 +714,8 @@ public class KeyguardViewMediator extends SystemUI { mHideAnimation = AnimationUtils.loadAnimation(mContext, com.android.internal.R.anim.lock_screen_behind_enter); + + mWorkLockController = new WorkLockActivityController(mContext); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java b/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java new file mode 100644 index 000000000000..12cf6fa2db20 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.systemui.keyguard; + +import static android.app.ActivityManager.TaskDescription; + +import android.annotation.ColorInt; +import android.annotation.UserIdInt; +import android.app.Activity; +import android.app.ActivityManager; +import android.app.ActivityOptions; +import android.app.KeyguardManager; +import android.app.PendingIntent; +import android.app.admin.DevicePolicyManager; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.graphics.Color; +import android.os.Bundle; +import android.os.RemoteException; +import android.os.UserHandle; +import android.util.Log; +import android.view.View; + +/** + * Bouncer between work activities and the activity used to confirm credentials before unlocking + * a managed profile. + * <p> + * Shows a solid color when started, based on the organization color of the user it is supposed to + * be blocking. Once focused, it switches to a screen to confirm credentials and auto-dismisses if + * credentials are accepted. + */ +public class WorkLockActivity extends Activity { + private static final String TAG = "WorkLockActivity"; + + /** + * ID of the locked user that this activity blocks access to. + */ + @UserIdInt + private int mUserId; + + /** + * {@see KeyguardManager} + */ + private KeyguardManager mKgm; + + /** + * {@see DevicePolicyManager} + */ + private DevicePolicyManager mDpm; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + mUserId = getIntent().getIntExtra(Intent.EXTRA_USER_ID, UserHandle.myUserId()); + mDpm = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE); + mKgm = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE); + + final IntentFilter lockFilter = new IntentFilter(); + lockFilter.addAction(Intent.ACTION_DEVICE_LOCKED_CHANGED); + registerReceiverAsUser(mLockEventReceiver, UserHandle.ALL, lockFilter, + /* permission */ null, /* scheduler */ null); + + // Once the receiver is registered, check whether anything happened between now and the time + // when this activity was launched. If it did and the user is unlocked now, just quit. + if (!mKgm.isDeviceLocked(mUserId)) { + finish(); + return; + } + + // Get the organization color; this is a 24-bit integer provided by a DPC, guaranteed to + // be completely opaque. + final @ColorInt int color = mDpm.getOrganizationColorForUser(mUserId); + + // Draw captions overlaid on the content view, so the whole window is one solid color. + setOverlayWithDecorCaptionEnabled(true); + + // Match task description to the task stack we are replacing so it's still recognizably the + // original task stack with the same icon and title text. + setTaskDescription(new TaskDescription(null, null, color)); + + // Blank out the activity. When it is on-screen it will look like a Recents thumbnail with + // redaction switched on. + final View blankView = new View(this); + blankView.setBackgroundColor(color); + setContentView(blankView); + + // Respond to input events by showing the prompt to confirm credentials. + blankView.setOnClickListener((View v) -> { + showConfirmCredentialActivity(); + }); + } + + @Override + public void onDestroy() { + unregisterReceiver(mLockEventReceiver); + super.onDestroy(); + } + + @Override + public void onBackPressed() { + // Ignore back presses. + return; + } + + private final BroadcastReceiver mLockEventReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, mUserId); + if (userId == mUserId && !mKgm.isDeviceLocked(mUserId)) { + finish(); + } + } + }; + + private void showConfirmCredentialActivity() { + if (isFinishing() || !mKgm.isDeviceLocked(mUserId)) { + // Don't show the confirm credentials screen if we are already unlocked / unlocking. + return; + } + + final Intent credential = mKgm.createConfirmDeviceCredentialIntent(null, null, mUserId); + if (credential == null) { + return; + } + + final ActivityOptions options = ActivityOptions.makeBasic(); + options.setLaunchTaskId(getTaskId()); + + // Bring this activity back to the foreground after confirming credentials. + final PendingIntent target = PendingIntent.getActivity(this, /* request */ -1, getIntent(), + PendingIntent.FLAG_CANCEL_CURRENT | + PendingIntent.FLAG_ONE_SHOT | + PendingIntent.FLAG_IMMUTABLE, options.toBundle()); + + credential.putExtra(Intent.EXTRA_INTENT, target.getIntentSender()); + try { + ActivityManager.getService().startConfirmDeviceCredentialIntent(credential); + } catch (RemoteException e) { + Log.e(TAG, "Failed to start confirm credential intent", e); + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivityController.java b/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivityController.java new file mode 100644 index 000000000000..22fceffd127f --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivityController.java @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.systemui.keyguard; + +import android.app.Activity; +import android.app.ActivityOptions; +import android.app.KeyguardManager; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.os.UserHandle; + +import com.android.systemui.recents.events.EventBus; +import com.android.systemui.recents.misc.SystemServicesProxy; +import com.android.systemui.recents.misc.SystemServicesProxy.TaskStackListener; + +public class WorkLockActivityController { + private final Context mContext; + + public WorkLockActivityController(Context context) { + mContext = context; + EventBus.getDefault().register(this); + SystemServicesProxy.getInstance(context).registerTaskStackListener(mLockListener); + } + + private void startWorkChallengeInTask(int taskId, int userId) { + Intent intent = new Intent(KeyguardManager.ACTION_CONFIRM_DEVICE_CREDENTIAL_WITH_USER) + .setComponent(new ComponentName(mContext, WorkLockActivity.class)) + .putExtra(Intent.EXTRA_USER_ID, userId) + .addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS + | Intent.FLAG_ACTIVITY_REORDER_TO_FRONT + | Intent.FLAG_ACTIVITY_SINGLE_TOP); + + final ActivityOptions options = ActivityOptions.makeBasic(); + options.setLaunchTaskId(taskId); + options.setTaskOverlay(true); + mContext.startActivityAsUser(intent, options.toBundle(), UserHandle.CURRENT); + } + + private final TaskStackListener mLockListener = new TaskStackListener() { + @Override + public void onTaskProfileLocked(int taskId, int userId) { + startWorkChallengeInTask(taskId, userId); + } + }; +} diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java index 2ba408eca8da..779113216530 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java +++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java @@ -154,6 +154,7 @@ public class SystemServicesProxy { public void onPinnedStackAnimationEnded() { } public void onActivityForcedResizable(String packageName, int taskId) { } public void onActivityDismissingDockedStack() { } + public void onTaskProfileLocked(int taskId, int userId) { } } /** @@ -197,6 +198,11 @@ public class SystemServicesProxy { public void onActivityDismissingDockedStack() throws RemoteException { mHandler.sendEmptyMessage(H.ON_ACTIVITY_DISMISSING_DOCKED_STACK); } + + @Override + public void onTaskProfileLocked(int taskId, int userId) { + mHandler.obtainMessage(H.ON_TASK_PROFILE_LOCKED, taskId, userId).sendToTarget(); + } }; /** @@ -1155,6 +1161,7 @@ public class SystemServicesProxy { private static final int ON_PINNED_STACK_ANIMATION_ENDED = 4; private static final int ON_ACTIVITY_FORCED_RESIZABLE = 5; private static final int ON_ACTIVITY_DISMISSING_DOCKED_STACK = 6; + private static final int ON_TASK_PROFILE_LOCKED = 7; @Override public void handleMessage(Message msg) { @@ -1196,6 +1203,12 @@ public class SystemServicesProxy { } break; } + case ON_TASK_PROFILE_LOCKED: { + for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) { + mTaskStackListeners.get(i).onTaskProfileLocked(msg.arg1, msg.arg2); + } + break; + } } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java index 088f5382b684..c7adb60c25f3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java @@ -313,7 +313,7 @@ public class NotificationGuts extends LinearLayout { } else if (mHighImportanceButton.isChecked()) { return NotificationManager.IMPORTANCE_HIGH; } else { - return NotificationManager.IMPORTANCE_NONE; + return NotificationManager.IMPORTANCE_UNSPECIFIED; } } @@ -333,10 +333,10 @@ public class NotificationGuts extends LinearLayout { // Set to current importance setting switch (importance) { + case NotificationManager.IMPORTANCE_UNSPECIFIED: case NotificationManager.IMPORTANCE_NONE: break; case NotificationManager.IMPORTANCE_MIN: - case NotificationManager.IMPORTANCE_UNSPECIFIED: mMinImportanceButton.setChecked(true); break; case NotificationManager.IMPORTANCE_LOW: diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationGutsTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationGutsTest.java index 2cd6dbd17a7c..c65f7150de0e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationGutsTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationGutsTest.java @@ -210,6 +210,18 @@ public class NotificationGutsTest { @Test @UiThreadTest + public void testCloseControls_DoesNotUpdateNotificationChannelIfUnspecified() throws Exception { + mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_UNSPECIFIED); + mNotificationGuts.bindNotification(mMockPackageManager, mMockINotificationManager, + mMockStatusBarNotification, null, null, null); + + mNotificationGuts.closeControls(-1, -1, true); + verify(mMockINotificationManager, never()).updateNotificationChannelForPackage( + anyString(), anyInt(), any()); + } + + @Test + @UiThreadTest public void testCloseControls_CallsUpdateNotificationChannelIfChanged() throws Exception { mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW); mNotificationGuts.bindNotification(mMockPackageManager, mMockINotificationManager, diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto index bf3620e3b2af..21139da7900f 100644 --- a/proto/src/metrics_constants.proto +++ b/proto/src/metrics_constants.proto @@ -3181,6 +3181,11 @@ message MetricsEvent { // user accepted ACTION_SKIP_DISCLAIMER_SELECTED = 760; + // Enclosing category for group of APP_TRANSITION_FOO events, + // logged when we execute an app transition. + APP_TRANSITION = 761; + + // ---- End O Constants, all O constants go above this line ---- // Add new aosp constants above this line. diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 5b4b4fef1baa..2c1871da6439 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -11875,20 +11875,20 @@ public class ActivityManagerService extends IActivityManager.Stub } synchronized (this) { - if (mStackSupervisor.isUserLockedProfile(userId)) { - final long ident = Binder.clearCallingIdentity(); - try { + final long ident = Binder.clearCallingIdentity(); + try { + if (mUserController.shouldConfirmCredentials(userId)) { final int currentUserId = mUserController.getCurrentUserIdLocked(); - if (mUserController.isLockScreenDisabled(currentUserId)) { - // If there is no device lock, we will show the profile's credential page. - mActivityStarter.showConfirmDeviceCredential(userId); + if (!mKeyguardController.isKeyguardLocked()) { + // If the device is not locked, we will prompt for credentials immediately. + mStackSupervisor.lockAllProfileTasks(userId); } else { // Showing launcher to avoid user entering credential twice. startHomeActivityLocked(currentUserId, "notifyLockedProfile"); } - } finally { - Binder.restoreCallingIdentity(ident); } + } finally { + Binder.restoreCallingIdentity(ident); } } } diff --git a/services/core/java/com/android/server/am/ActivityMetricsLogger.java b/services/core/java/com/android/server/am/ActivityMetricsLogger.java index 3f166fe4ddfb..e46d20457706 100644 --- a/services/core/java/com/android/server/am/ActivityMetricsLogger.java +++ b/services/core/java/com/android/server/am/ActivityMetricsLogger.java @@ -172,7 +172,7 @@ class ActivityMetricsLogger { MetricsLogger.action(mContext, MetricsEvent.APP_TRANSITION_DEVICE_UPTIME_SECONDS, (int) (SystemClock.uptimeMillis() / 1000)); - LogBuilder builder = new LogBuilder(); + LogBuilder builder = new LogBuilder(MetricsEvent.APP_TRANSITION); builder.addTaggedData(MetricsEvent.APP_TRANSITION_COMPONENT_NAME, componentName); builder.addTaggedData(MetricsEvent.APP_TRANSITION_PROCESS_RUNNING, processRunning ? 1 : 0); builder.addTaggedData(MetricsEvent.APP_TRANSITION_DEVICE_UPTIME_SECONDS, diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index a0bb192587d3..8cf0708e22aa 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -764,43 +764,52 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D } /** - * TODO: Handle freefom mode. - * @return true when credential confirmation is needed for the user and there is any - * activity started by the user in any visible stack. + * Detects whether we should show a lock screen in front of this task for a locked user. + * <p> + * We'll do this if either of the following holds: + * <ul> + * <li>The top activity explicitly belongs to {@param userId}.</li> + * <li>The top activity returns a result to an activity belonging to {@param userId}.</li> + * </ul> + * + * @return {@code true} if the top activity looks like it belongs to {@param userId}. */ - boolean isUserLockedProfile(@UserIdInt int userId) { - if (!mService.mUserController.shouldConfirmCredentials(userId)) { - return false; - } - final ActivityStack fullScreenStack = getStack(FULLSCREEN_WORKSPACE_STACK_ID); - final ActivityStack dockedStack = getStack(DOCKED_STACK_ID); - final ActivityStack[] activityStacks = new ActivityStack[] {fullScreenStack, dockedStack}; - for (final ActivityStack activityStack : activityStacks) { - if (activityStack == null) { - continue; - } - if (activityStack.topRunningActivityLocked() == null) { - continue; - } - if (activityStack.getStackVisibilityLocked(null) == STACK_INVISIBLE) { - continue; - } - if (activityStack.isDockedStack() && mIsDockMinimized) { - continue; - } - final TaskRecord topTask = activityStack.topTask(); - if (topTask == null) { - continue; - } - // To handle the case that work app is in the task but just is not the top one. - for (int i = topTask.mActivities.size() - 1; i >= 0; i--) { - final ActivityRecord activityRecord = topTask.mActivities.get(i); - if (activityRecord.userId == userId) { - return true; + private boolean taskTopActivityIsUser(TaskRecord task, @UserIdInt int userId) { + // To handle the case that work app is in the task but just is not the top one. + final ActivityRecord activityRecord = task.getTopActivity(); + final ActivityRecord resultTo = (activityRecord != null ? activityRecord.resultTo : null); + + return (activityRecord != null && activityRecord.userId == userId) + || (resultTo != null && resultTo.userId == userId); + } + + /** + * Find all visible task stacks containing {@param userId} and intercept them with an activity + * to block out the contents and possibly start a credential-confirming intent. + * + * @param userId user handle for the locked managed profile. + */ + void lockAllProfileTasks(@UserIdInt int userId) { + mWindowManager.deferSurfaceLayout(); + try { + final List<ActivityStack> stacks = getStacks(); + for (int stackNdx = stacks.size() - 1; stackNdx >= 0; stackNdx--) { + final List<TaskRecord> tasks = stacks.get(stackNdx).getAllTasks(); + for (int taskNdx = tasks.size() - 1; taskNdx >= 0; taskNdx--) { + final TaskRecord task = tasks.get(taskNdx); + + // Check the task for a top activity belonging to userId, or returning a result + // to an activity belonging to userId. Example case: a document picker for + // personal files, opened by a work app, should still get locked. + if (taskTopActivityIsUser(task, userId)) { + mService.mTaskChangeNotificationController.notifyTaskProfileLocked( + task.taskId, userId); + } } } + } finally { + mWindowManager.continueSurfaceLayout(); } - return false; } void setNextTaskIdForUserLocked(int taskId, int userId) { diff --git a/services/core/java/com/android/server/am/TaskChangeNotificationController.java b/services/core/java/com/android/server/am/TaskChangeNotificationController.java index fd248c6c807a..fbdbb1b2443a 100644 --- a/services/core/java/com/android/server/am/TaskChangeNotificationController.java +++ b/services/core/java/com/android/server/am/TaskChangeNotificationController.java @@ -39,6 +39,7 @@ class TaskChangeNotificationController { static final int NOTIFY_TASK_DESCRIPTION_CHANGED_LISTENERS_MSG = 11; static final int NOTIFY_ACTIVITY_REQUESTED_ORIENTATION_CHANGED_LISTENERS = 12; static final int NOTIFY_TASK_REMOVAL_STARTED_LISTENERS = 13; + static final int NOTIFY_TASK_PROFILE_LOCKED_LISTENERS_MSG = 14; // Delay in notifying task stack change listeners (in millis) static final int NOTIFY_TASK_STACK_CHANGE_LISTENERS_DELAY = 100; @@ -110,6 +111,9 @@ class TaskChangeNotificationController { case NOTIFY_ACTIVITY_DISMISSING_DOCKED_STACK_MSG: forAllListeners((listener) -> listener.onActivityDismissingDockedStack()); break; + case NOTIFY_TASK_PROFILE_LOCKED_LISTENERS_MSG: + forAllListeners((listener) -> listener.onTaskProfileLocked(msg.arg1, msg.arg2)); + break; } } } @@ -228,4 +232,13 @@ class TaskChangeNotificationController { mHandler.obtainMessage(NOTIFY_TASK_REMOVAL_STARTED_LISTENERS, taskId, 0 /* unused */) .sendToTarget(); } + + /** + * Notify listeners that the task has been put in a locked state because one or more of the + * activities inside it belong to a managed profile user that has been locked. + */ + void notifyTaskProfileLocked(int taskId, int userId) { + mHandler.obtainMessage(NOTIFY_TASK_PROFILE_LOCKED_LISTENERS_MSG, taskId, userId) + .sendToTarget(); + } } diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java index 2514012d0d16..b0f67a81db28 100644 --- a/services/core/java/com/android/server/fingerprint/FingerprintService.java +++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java @@ -1142,12 +1142,6 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe mHandler.obtainMessage(MSG_USER_SWITCHING, newUserId, 0 /* unused */) .sendToTarget(); } - - @Override - public void onForegroundProfileSwitch(int newProfileId) throws RemoteException { - mHandler.obtainMessage(MSG_USER_SWITCHING, newProfileId, 0 /* unused */) - .sendToTarget(); - } }, TAG); } catch (RemoteException e) { Slog.w(TAG, "Failed to listen for user switching event" ,e); diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index 775d8a0862f9..6ac172b26e24 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -322,7 +322,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> { if (!configChanged) { return null; } - displayContent.onOverrideConfigurationChanged(currentConfig); + displayContent.onOverrideConfigurationChanged(newConfiguration); if (displayId == DEFAULT_DISPLAY) { // Override configuration of the default display duplicates global config. In this case diff --git a/services/core/jni/com_android_server_connectivity_Vpn.cpp b/services/core/jni/com_android_server_connectivity_Vpn.cpp index c54d732b9285..4d85d9a558aa 100644 --- a/services/core/jni/com_android_server_connectivity_Vpn.cpp +++ b/services/core/jni/com_android_server_connectivity_Vpn.cpp @@ -17,24 +17,25 @@ #define LOG_NDEBUG 0 #define LOG_TAG "VpnJni" -#include <cutils/log.h> -#include "netutils/ifc.h" -#include <stdio.h> -#include <string.h> -#include <sys/ioctl.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/socket.h> -#include <netinet/in.h> #include <arpa/inet.h> #include <errno.h> #include <fcntl.h> - #include <linux/if.h> #include <linux/if_tun.h> #include <linux/route.h> #include <linux/ipv6_route.h> +#include <netinet/in.h> +#include <stdio.h> +#include <string.h> +#include <sys/ioctl.h> +#include <sys/socket.h> +#include <sys/stat.h> +#include <sys/types.h> + +#include <log/log.h> + +#include "netutils/ifc.h" #include "jni.h" #include "JNIHelp.h" diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp index 504626544fe4..fa6405a1dd87 100644 --- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp +++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp @@ -894,11 +894,11 @@ jbyteArray AGnssCallback::convertToIpV4(uint32_t ip) { * interface. */ struct AGnssRilCallback : IAGnssRilCallback { - Return<void> requestSetIdCb(IAGnssRilCallback::ID setIdFlag) override; + Return<void> requestSetIdCb(uint32_t setIdFlag) override; Return<void> requestRefLocCb() override; }; -Return<void> AGnssRilCallback::requestSetIdCb(IAGnssRilCallback::ID setIdFlag) { +Return<void> AGnssRilCallback::requestSetIdCb(uint32_t setIdFlag) { JNIEnv* env = getJniEnv(); env->CallVoidMethod(mCallbacksObj, method_requestSetID, setIdFlag); checkAndClearExceptionFromCallback(env, __FUNCTION__); diff --git a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java index 786c2bb06d96..85931e8ac878 100644 --- a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java +++ b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java @@ -19,6 +19,7 @@ package com.android.server.wm; import org.junit.Test; import org.junit.runner.RunWith; +import android.content.res.Configuration; import android.hardware.display.DisplayManagerGlobal; import android.platform.test.annotations.Presubmit; import android.support.test.filters.SmallTest; @@ -208,6 +209,10 @@ public class DisplayContentTests extends WindowTestsBase { voiceInteractionWindow.removeImmediately(); } + /** + * This tests stack movement between displays and proper stack's, task's and app token's display + * container references updates. + */ @Test public void testMoveStackBetweenDisplays() throws Exception { // Create second display. @@ -238,4 +243,28 @@ public class DisplayContentTests extends WindowTestsBase { assertEquals(sDisplayContent, task.getDisplayContent()); assertEquals(sDisplayContent, token.getDisplayContent()); } + + /** + * This tests override configuration updates for display content. + */ + @Test + public void testDisplayOverrideConfigUpdate() throws Exception { + final int displayId = sDisplayContent.getDisplayId(); + final Configuration currentOverrideConfig = sDisplayContent.getOverrideConfiguration(); + + // Create new, slightly changed override configuration and apply it to the display. + final Configuration newOverrideConfig = new Configuration(currentOverrideConfig); + newOverrideConfig.densityDpi += 120; + newOverrideConfig.fontScale += 0.3; + + sWm.setNewDisplayOverrideConfiguration(newOverrideConfig, displayId); + + // Check that override config is applied. + assertEquals(newOverrideConfig, sDisplayContent.getOverrideConfiguration()); + + // Check that global configuration is updated, as we've updated default display's config. + final Configuration globalConfig = sWm.mRoot.getConfiguration(); + assertEquals(newOverrideConfig.densityDpi, globalConfig.densityDpi); + assertEquals(newOverrideConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */); + } } |