diff options
59 files changed, 742 insertions, 823 deletions
diff --git a/api/current.txt b/api/current.txt index d1b77f2c1096..ece35366967c 100644 --- a/api/current.txt +++ b/api/current.txt @@ -15953,7 +15953,6 @@ package android.graphics.text { public class MeasuredText { method public void getBounds(@IntRange(from=0) int, @IntRange(from=0) int, @NonNull android.graphics.Rect); method @FloatRange(from=0.0f) @Px public float getCharWidthAt(@IntRange(from=0) int); - method @NonNull public char[] getChars(); method @FloatRange(from=0.0) @Px public float getWidth(@IntRange(from=0) int, @IntRange(from=0) int); } @@ -43189,6 +43188,7 @@ package android.telecom { method public void unregisterCallback(android.telecom.Call.Callback); field @Deprecated public static final String AVAILABLE_PHONE_ACCOUNTS = "selectPhoneAccountAccounts"; field public static final String EXTRA_LAST_EMERGENCY_CALLBACK_TIME_MILLIS = "android.telecom.extra.LAST_EMERGENCY_CALLBACK_TIME_MILLIS"; + field public static final String EXTRA_SILENT_RINGING_REQUESTED = "android.telecom.extra.SILENT_RINGING_REQUESTED"; field public static final String EXTRA_SUGGESTED_PHONE_ACCOUNTS = "android.telecom.extra.SUGGESTED_PHONE_ACCOUNTS"; field public static final int STATE_ACTIVE = 4; // 0x4 field public static final int STATE_CONNECTING = 9; // 0x9 @@ -43376,6 +43376,7 @@ package android.telecom { public static class CallScreeningService.CallResponse { method public boolean getDisallowCall(); method public boolean getRejectCall(); + method public boolean getSilenceCall(); method public boolean getSkipCallLog(); method public boolean getSkipNotification(); } @@ -43385,6 +43386,7 @@ package android.telecom { method public android.telecom.CallScreeningService.CallResponse build(); method public android.telecom.CallScreeningService.CallResponse.Builder setDisallowCall(boolean); method public android.telecom.CallScreeningService.CallResponse.Builder setRejectCall(boolean); + method @NonNull public android.telecom.CallScreeningService.CallResponse.Builder setSilenceCall(boolean); method public android.telecom.CallScreeningService.CallResponse.Builder setSkipCallLog(boolean); method public android.telecom.CallScreeningService.CallResponse.Builder setSkipNotification(boolean); } diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto index b8e8fdc6a9f2..7a753aecc4cb 100644 --- a/cmds/statsd/src/atoms.proto +++ b/cmds/statsd/src/atoms.proto @@ -45,6 +45,7 @@ import "frameworks/base/core/proto/android/stats/docsui/docsui_enums.proto"; import "frameworks/base/core/proto/android/stats/devicepolicy/device_policy.proto"; import "frameworks/base/core/proto/android/stats/devicepolicy/device_policy_enums.proto"; import "frameworks/base/core/proto/android/stats/launcher/launcher.proto"; +import "frameworks/base/core/proto/android/stats/storage/storage_enums.proto"; import "frameworks/base/core/proto/android/stats/style/style_enums.proto"; import "frameworks/base/core/proto/android/telecomm/enums.proto"; import "frameworks/base/core/proto/android/telephony/enums.proto"; @@ -250,6 +251,7 @@ message Atom { HiddenApiUsed hidden_api_used = 178 [(allow_from_any_uid) = true]; StyleUIChanged style_ui_changed = 179; PrivacyIndicatorsInteracted privacy_indicators_interacted = 180; + AppInstallOnExternalStorageReported app_install_on_external_storage_reported = 181; } // Pulled events will start at field 10000. @@ -2558,6 +2560,18 @@ message AppOptimizedAfterDowngraded { } /** + * Logs whenever an app is installed on external storage. + * Logged from: + frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java + */ +message AppInstallOnExternalStorageReported { + // The type of external storage. + optional android.stats.storage.ExternalStorageType storage_type = 1; + // The name of the package that is installed on the sd card. + optional string package_name = 2; +} + +/** * Logs when an app crashes. * Logged from: * frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java index 664f0a37a459..f6cfe4855070 100644 --- a/core/java/android/app/ActivityManagerInternal.java +++ b/core/java/android/app/ActivityManagerInternal.java @@ -329,6 +329,9 @@ public abstract class ActivityManagerInternal { /** Returns true if the given uid is the app in the foreground. */ public abstract boolean isAppForeground(int uid); + /** Returns true if the given uid is currently marked 'bad' */ + public abstract boolean isAppBad(ApplicationInfo info); + /** Remove pending backup for the given userId. */ public abstract void clearPendingBackup(int userId); diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl index 29e6807a3244..15084de0d7dd 100644 --- a/core/java/android/app/INotificationManager.aidl +++ b/core/java/android/app/INotificationManager.aidl @@ -193,7 +193,7 @@ interface INotificationManager void setNotificationDelegate(String callingPkg, String delegate); String getNotificationDelegate(String callingPkg); - boolean canNotifyAsPackage(String callingPkg, String targetPkg); + boolean canNotifyAsPackage(String callingPkg, String targetPkg, int userId); void setPrivateNotificationsAllowed(boolean allow); boolean getPrivateNotificationsAllowed(); diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java index 11b40c244482..6a301c91bb06 100644 --- a/core/java/android/app/NotificationManager.java +++ b/core/java/android/app/NotificationManager.java @@ -627,7 +627,7 @@ public class NotificationManager { public boolean canNotifyAsPackage(@NonNull String pkg) { INotificationManager service = getService(); try { - return service.canNotifyAsPackage(mContext.getPackageName(), pkg); + return service.canNotifyAsPackage(mContext.getPackageName(), pkg, mContext.getUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index efb3bfc1f6d2..49a29f0ac80d 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -338,6 +338,16 @@ public abstract class Context { public static final int BIND_ADJUST_BELOW_PERCEPTIBLE = 0x0100; /** + * Flag for {@link #bindService}: This flag is intended to be used only by the system to adjust + * the scheduling policy for IMEs (and any other out-of-process user-visible components that + * work closely with the top app) so that UI hosted in such services can have the same + * scheduling policy (e.g. SCHED_FIFO when it is enabled and TOP_APP_PRIORITY_BOOST otherwise) + * as the actual top-app. + * @hide + */ + public static final int BIND_SCHEDULE_LIKE_TOP_APP = 0x00080000; + + /** * Flag for {@link #bindService}: allow background activity starts from the bound service's * process. * This flag is only respected if the caller is holding diff --git a/core/java/com/android/internal/widget/ILockSettings.aidl b/core/java/com/android/internal/widget/ILockSettings.aidl index 3be7c3e35895..41e2fc84593e 100644 --- a/core/java/com/android/internal/widget/ILockSettings.aidl +++ b/core/java/com/android/internal/widget/ILockSettings.aidl @@ -62,6 +62,7 @@ interface ILockSettings { void systemReady(); void userPresent(int userId); int getStrongAuthForUser(int userId); + boolean hasPendingEscrowToken(int userId); // Keystore RecoveryController methods. // {@code ServiceSpecificException} may be thrown to signal an error, which caller can diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java index c09537670556..1965609ff959 100644 --- a/core/java/com/android/internal/widget/LockPatternUtils.java +++ b/core/java/com/android/internal/widget/LockPatternUtils.java @@ -1638,7 +1638,7 @@ public class LockPatternUtils { } /** - * @see StrongAuthTracker#isFingerprintAllowedForUser + * @see StrongAuthTracker#isBiometricAllowedForUser(int) */ public boolean isBiometricAllowedForUser(int userId) { return (getStrongAuthForUser(userId) & ~StrongAuthTracker.ALLOWING_BIOMETRIC) == 0; @@ -1980,6 +1980,18 @@ public class LockPatternUtils { } /** + * Returns whether the given user has pending escrow tokens + */ + public boolean hasPendingEscrowToken(int userId) { + try { + return getLockSettings().hasPendingEscrowToken(userId); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + return false; + } + + /** * Return true if the device supports the lock screen feature, false otherwise. */ public boolean hasSecureLockScreen() { diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp index 9f9fbf9eb26d..c4c16ee0ef9b 100644 --- a/core/jni/android_view_RenderNode.cpp +++ b/core/jni/android_view_RenderNode.cpp @@ -31,6 +31,7 @@ #include <renderthread/CanvasContext.h> #include <TreeInfo.h> #include <hwui/Paint.h> +#include <utils/TraceUtils.h> #include "core_jni_helpers.h" diff --git a/core/proto/android/app/settings_enums.proto b/core/proto/android/app/settings_enums.proto index 927c85f2db8e..7ad922312fa9 100644 --- a/core/proto/android/app/settings_enums.proto +++ b/core/proto/android/app/settings_enums.proto @@ -2302,4 +2302,7 @@ enum PageId { // Panel for Wifi PANEL_WIFI = 1687; + + // Open: Settings > Special App Access > Do not disturb control for app + ZEN_ACCESS_DETAIL = 1692; } diff --git a/core/proto/android/stats/storage/storage_enums.proto b/core/proto/android/stats/storage/storage_enums.proto new file mode 100644 index 000000000000..6892e287472f --- /dev/null +++ b/core/proto/android/stats/storage/storage_enums.proto @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +syntax = "proto2"; + +package android.stats.storage; + +enum ExternalStorageType { + UNKNOWN = 0; + SD_CARD = 1; + USB = 2; + OTHER = 3; +} diff --git a/graphics/java/android/graphics/text/MeasuredText.java b/graphics/java/android/graphics/text/MeasuredText.java index 66bcd8650b95..9db7533044e2 100644 --- a/graphics/java/android/graphics/text/MeasuredText.java +++ b/graphics/java/android/graphics/text/MeasuredText.java @@ -65,6 +65,7 @@ public class MeasuredText { /** * Returns the characters in the paragraph used to compute this MeasuredText instance. + * @hide */ public @NonNull char[] getChars() { return mChars; diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp index 4f1b2a4fcbf8..ebba4cb79dfb 100644 --- a/libs/hwui/Android.bp +++ b/libs/hwui/Android.bp @@ -191,7 +191,7 @@ cc_defaults { "surfacetexture/EGLConsumer.cpp", "surfacetexture/ImageConsumer.cpp", "surfacetexture/SurfaceTexture.cpp", - "thread/TaskManager.cpp", + "thread/CommonPool.cpp", "utils/Blur.cpp", "utils/Color.cpp", "utils/GLUtils.cpp", @@ -308,6 +308,7 @@ cc_test { "tests/unit/main.cpp", "tests/unit/CacheManagerTests.cpp", "tests/unit/CanvasContextTests.cpp", + "tests/unit/CommonPoolTests.cpp", "tests/unit/DamageAccumulatorTests.cpp", "tests/unit/DeferredLayerUpdaterTests.cpp", "tests/unit/FatVectorTests.cpp", @@ -381,7 +382,6 @@ cc_benchmark { "tests/microbench/LinearAllocatorBench.cpp", "tests/microbench/PathParserBench.cpp", "tests/microbench/RenderNodeBench.cpp", - "tests/microbench/TaskManagerBench.cpp", ], } diff --git a/libs/hwui/Readback.cpp b/libs/hwui/Readback.cpp index fe633e96b9d7..fb60a966c48f 100644 --- a/libs/hwui/Readback.cpp +++ b/libs/hwui/Readback.cpp @@ -28,6 +28,7 @@ #include "hwui/Bitmap.h" #include "utils/Color.h" #include "utils/MathUtils.h" +#include "utils/TraceUtils.h" using namespace android::uirenderer::renderthread; diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.cpp b/libs/hwui/pipeline/skia/SkiaPipeline.cpp index a00a36f93501..721a115c1381 100644 --- a/libs/hwui/pipeline/skia/SkiaPipeline.cpp +++ b/libs/hwui/pipeline/skia/SkiaPipeline.cpp @@ -25,6 +25,7 @@ #include <SkPictureRecorder.h> #include "TreeInfo.h" #include "VectorDrawable.h" +#include "thread/CommonPool.h" #include "utils/TraceUtils.h" #include <unistd.h> @@ -49,10 +50,6 @@ SkiaPipeline::~SkiaPipeline() { unpinImages(); } -TaskManager* SkiaPipeline::getTaskManager() { - return mRenderThread.cacheManager().getTaskManager(); -} - void SkiaPipeline::onDestroyHardwareResources() { unpinImages(); mRenderThread.cacheManager().trimStaleResources(); @@ -225,42 +222,21 @@ void SkiaPipeline::renderVectorDrawableCache() { } } -class SkiaPipeline::SavePictureProcessor : public TaskProcessor<bool> { -public: - explicit SavePictureProcessor(TaskManager* taskManager) : TaskProcessor<bool>(taskManager) {} - - struct SavePictureTask : public Task<bool> { - sk_sp<SkData> data; - std::string filename; - }; - - void savePicture(const sk_sp<SkData>& data, const std::string& filename) { - sp<SavePictureTask> task(new SavePictureTask()); - task->data = data; - task->filename = filename; - TaskProcessor<bool>::add(task); - } - - virtual void onProcess(const sp<Task<bool>>& task) override { - ATRACE_NAME("SavePictureTask"); - SavePictureTask* t = static_cast<SavePictureTask*>(task.get()); - - if (0 == access(t->filename.c_str(), F_OK)) { - task->setResult(false); +static void savePictureAsync(const sk_sp<SkData>& data, const std::string& filename) { + CommonPool::post([data, filename] { + if (0 == access(filename.c_str(), F_OK)) { return; } - SkFILEWStream stream(t->filename.c_str()); + SkFILEWStream stream(filename.c_str()); if (stream.isValid()) { - stream.write(t->data->data(), t->data->size()); + stream.write(data->data(), data->size()); stream.flush(); SkDebugf("SKP Captured Drawing Output (%d bytes) for frame. %s", stream.bytesWritten(), - t->filename.c_str()); + filename.c_str()); } - - task->setResult(true); - } -}; + }); +} SkCanvas* SkiaPipeline::tryCapture(SkSurface* surface) { if (CC_UNLIKELY(Properties::skpCaptureEnabled)) { @@ -297,16 +273,10 @@ void SkiaPipeline::endCapture(SkSurface* surface) { ATRACE_END(); // offload saving to file in a different thread - if (!mSavePictureProcessor.get()) { - TaskManager* taskManager = getTaskManager(); - mSavePictureProcessor = new SavePictureProcessor( - taskManager->canRunTasks() ? taskManager : nullptr); - } if (1 == mCaptureSequence) { - mSavePictureProcessor->savePicture(data, mCapturedFile); + savePictureAsync(data, mCapturedFile); } else { - mSavePictureProcessor->savePicture( - data, + savePictureAsync(data, mCapturedFile + "_" + std::to_string(mCaptureSequence)); } mCaptureSequence--; diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.h b/libs/hwui/pipeline/skia/SkiaPipeline.h index 7381e0417a2d..41d864653b67 100644 --- a/libs/hwui/pipeline/skia/SkiaPipeline.h +++ b/libs/hwui/pipeline/skia/SkiaPipeline.h @@ -33,8 +33,6 @@ public: explicit SkiaPipeline(renderthread::RenderThread& thread); virtual ~SkiaPipeline(); - TaskManager* getTaskManager() override; - void onDestroyHardwareResources() override; bool pinImages(std::vector<SkImage*>& mutableImages) override; @@ -157,11 +155,7 @@ private: * mCaptureSequence counts how many frames are left to take in the sequence. */ int mCaptureSequence = 0; - /** - * mSavePictureProcessor is used to run the file saving code in a separate thread. - */ - class SavePictureProcessor; - sp<SavePictureProcessor> mSavePictureProcessor; + /** * mRecorder holds the current picture recorder. We could store it on the stack to support * parallel tryCapture calls (not really needed). diff --git a/libs/hwui/renderthread/CacheManager.cpp b/libs/hwui/renderthread/CacheManager.cpp index 6c04232ab7f5..8b02c11911ca 100644 --- a/libs/hwui/renderthread/CacheManager.cpp +++ b/libs/hwui/renderthread/CacheManager.cpp @@ -23,6 +23,7 @@ #include "pipeline/skia/SkiaMemoryTracer.h" #include "Properties.h" #include "renderstate/RenderState.h" +#include "thread/CommonPool.h" #include <GrContextOptions.h> #include <SkExecutor.h> @@ -76,29 +77,15 @@ void CacheManager::updateContextCacheSizes() { mGrContext->setResourceCacheLimits(mMaxResources, mMaxResourceBytes); } -class CacheManager::SkiaTaskProcessor : public TaskProcessor<bool>, public SkExecutor { +class CommonPoolExecutor : public SkExecutor { public: - explicit SkiaTaskProcessor(TaskManager* taskManager) : TaskProcessor<bool>(taskManager) {} - - // This is really a Task<void> but that doesn't really work when Future<> - // expects to be able to get/set a value - struct SkiaTask : public Task<bool> { - std::function<void()> func; - }; - virtual void add(std::function<void(void)> func) override { - sp<SkiaTask> task(new SkiaTask()); - task->func = func; - TaskProcessor<bool>::add(task); - } - - virtual void onProcess(const sp<Task<bool> >& task) override { - SkiaTask* t = static_cast<SkiaTask*>(task.get()); - t->func(); - task->setResult(true); + CommonPool::post(std::move(func)); } }; +static CommonPoolExecutor sDefaultExecutor; + void CacheManager::configureContext(GrContextOptions* contextOptions, const void* identity, ssize_t size) { contextOptions->fAllowPathMaskCaching = true; @@ -107,12 +94,7 @@ void CacheManager::configureContext(GrContextOptions* contextOptions, const void // provided to Skia. contextOptions->fGlyphCacheTextureMaximumBytes = GrNextSizePow2(mMaxSurfaceArea); - if (mTaskManager.canRunTasks()) { - if (!mTaskProcessor.get()) { - mTaskProcessor = new SkiaTaskProcessor(&mTaskManager); - } - contextOptions->fExecutor = mTaskProcessor.get(); - } + contextOptions->fExecutor = &sDefaultExecutor; auto& cache = skiapipeline::ShaderCache::get(); cache.initShaderDiskCache(identity, size); diff --git a/libs/hwui/renderthread/CacheManager.h b/libs/hwui/renderthread/CacheManager.h index 66f04f1ba266..b0286e8cde25 100644 --- a/libs/hwui/renderthread/CacheManager.h +++ b/libs/hwui/renderthread/CacheManager.h @@ -24,8 +24,6 @@ #include <vector> #include "pipeline/skia/VectorDrawableAtlas.h" -#include "thread/TaskManager.h" -#include "thread/TaskProcessor.h" namespace android { @@ -54,8 +52,6 @@ public: size_t getCacheSize() const { return mMaxResourceBytes; } size_t getBackgroundCacheSize() const { return mBackgroundResourceBytes; } - TaskManager* getTaskManager() { return &mTaskManager; } - private: friend class RenderThread; @@ -78,10 +74,6 @@ private: }; sp<skiapipeline::VectorDrawableAtlas> mVectorDrawableAtlas; - - class SkiaTaskProcessor; - sp<SkiaTaskProcessor> mTaskProcessor; - TaskManager mTaskManager; }; } /* namespace renderthread */ diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp index f5b4d9359ee9..baa41c1ec698 100644 --- a/libs/hwui/renderthread/CanvasContext.cpp +++ b/libs/hwui/renderthread/CanvasContext.cpp @@ -27,8 +27,10 @@ #include "pipeline/skia/SkiaOpenGLPipeline.h" #include "pipeline/skia/SkiaPipeline.h" #include "pipeline/skia/SkiaVulkanPipeline.h" +#include "thread/CommonPool.h" #include "utils/GLUtils.h" #include "utils/TimeUtils.h" +#include "utils/TraceUtils.h" #include "../Properties.h" #include <cutils/properties.h> @@ -603,31 +605,14 @@ void CanvasContext::waitOnFences() { if (mFrameFences.size()) { ATRACE_CALL(); for (auto& fence : mFrameFences) { - fence->getResult(); + fence.get(); } mFrameFences.clear(); } } -class CanvasContext::FuncTaskProcessor : public TaskProcessor<bool> { -public: - explicit FuncTaskProcessor(TaskManager* taskManager) : TaskProcessor<bool>(taskManager) {} - - virtual void onProcess(const sp<Task<bool> >& task) override { - FuncTask* t = static_cast<FuncTask*>(task.get()); - t->func(); - task->setResult(true); - } -}; - void CanvasContext::enqueueFrameWork(std::function<void()>&& func) { - if (!mFrameWorkProcessor.get()) { - mFrameWorkProcessor = new FuncTaskProcessor(mRenderPipeline->getTaskManager()); - } - sp<FuncTask> task(new FuncTask()); - task->func = func; - mFrameFences.push_back(task); - mFrameWorkProcessor->add(task); + mFrameFences.push_back(CommonPool::async(std::move(func))); } int64_t CanvasContext::getFrameNumber() { diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h index 4da0eac85bb0..abca34225f98 100644 --- a/libs/hwui/renderthread/CanvasContext.h +++ b/libs/hwui/renderthread/CanvasContext.h @@ -28,8 +28,6 @@ #include "ReliableSurface.h" #include "renderthread/RenderTask.h" #include "renderthread/RenderThread.h" -#include "thread/Task.h" -#include "thread/TaskProcessor.h" #include <EGL/egl.h> #include <SkBitmap.h> @@ -42,6 +40,7 @@ #include <set> #include <string> #include <vector> +#include <future> namespace android { namespace uirenderer { @@ -274,15 +273,7 @@ private: // Stores the bounds of the main content. Rect mContentDrawBounds; - // TODO: This is really a Task<void> but that doesn't really work - // when Future<> expects to be able to get/set a value - struct FuncTask : public Task<bool> { - std::function<void()> func; - }; - class FuncTaskProcessor; - - std::vector<sp<FuncTask>> mFrameFences; - sp<TaskProcessor<bool>> mFrameWorkProcessor; + std::vector<std::future<void>> mFrameFences; std::unique_ptr<IRenderPipeline> mRenderPipeline; std::vector<std::function<void(int64_t)>> mFrameCompleteCallbacks; diff --git a/libs/hwui/renderthread/IRenderPipeline.h b/libs/hwui/renderthread/IRenderPipeline.h index 2cfc8df38297..0502eb88b6a5 100644 --- a/libs/hwui/renderthread/IRenderPipeline.h +++ b/libs/hwui/renderthread/IRenderPipeline.h @@ -75,7 +75,6 @@ public: virtual void renderLayers(const LightGeometry& lightGeometry, LayerUpdateQueue* layerUpdateQueue, bool opaque, const LightInfo& lightInfo) = 0; - virtual TaskManager* getTaskManager() = 0; virtual bool createOrUpdateLayer(RenderNode* node, const DamageAccumulator& damageAccumulator, ErrorHandler* errorHandler) = 0; virtual bool pinImages(std::vector<SkImage*>& mutableImages) = 0; diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp index 34f76d9b3579..1bcb819509af 100644 --- a/libs/hwui/renderthread/RenderProxy.cpp +++ b/libs/hwui/renderthread/RenderProxy.cpp @@ -31,6 +31,7 @@ #include "renderthread/RenderThread.h" #include "utils/Macros.h" #include "utils/TimeUtils.h" +#include "utils/TraceUtils.h" #include <ui/GraphicBuffer.h> diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp index c784d64f820c..def805adeeea 100644 --- a/libs/hwui/renderthread/RenderThread.cpp +++ b/libs/hwui/renderthread/RenderThread.cpp @@ -28,6 +28,7 @@ #include "renderstate/RenderState.h" #include "utils/FatVector.h" #include "utils/TimeUtils.h" +#include "utils/TraceUtils.h" #ifdef HWUI_GLES_WRAP_ENABLED #include "debug/GlesDriver.h" diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp index 6dacc7a0ea07..9916da5d9f10 100644 --- a/libs/hwui/renderthread/VulkanManager.cpp +++ b/libs/hwui/renderthread/VulkanManager.cpp @@ -23,6 +23,7 @@ #include "RenderThread.h" #include "renderstate/RenderState.h" #include "utils/FatVector.h" +#include "utils/TraceUtils.h" #include <GrBackendSemaphore.h> #include <GrBackendSurface.h> diff --git a/libs/hwui/tests/macrobench/TestSceneRunner.cpp b/libs/hwui/tests/macrobench/TestSceneRunner.cpp index 0e61899ed58b..b45dbc8b832b 100644 --- a/libs/hwui/tests/macrobench/TestSceneRunner.cpp +++ b/libs/hwui/tests/macrobench/TestSceneRunner.cpp @@ -21,6 +21,7 @@ #include "tests/common/TestContext.h" #include "tests/common/TestScene.h" #include "tests/common/scenes/TestSceneBase.h" +#include "utils/TraceUtils.h" #include <benchmark/benchmark.h> #include <gui/Surface.h> diff --git a/libs/hwui/tests/microbench/TaskManagerBench.cpp b/libs/hwui/tests/microbench/TaskManagerBench.cpp deleted file mode 100644 index 4153baec22b5..000000000000 --- a/libs/hwui/tests/microbench/TaskManagerBench.cpp +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <benchmark/benchmark.h> - -#include "thread/Task.h" -#include "thread/TaskManager.h" -#include "thread/TaskProcessor.h" -#include "thread/ThreadBase.h" - -#include <atomic> -#include <vector> - -using namespace android; -using namespace android::uirenderer; - -class TrivialTask : public Task<char> {}; - -class TrivialProcessor : public TaskProcessor<char> { -public: - explicit TrivialProcessor(TaskManager* manager) : TaskProcessor(manager) {} - virtual ~TrivialProcessor() {} - virtual void onProcess(const sp<Task<char>>& task) override { - TrivialTask* t = static_cast<TrivialTask*>(task.get()); - t->setResult(reinterpret_cast<intptr_t>(t) % 16 == 0 ? 'a' : 'b'); - } -}; - -class TestThread : public ThreadBase, public virtual RefBase {}; - -void BM_TaskManager_allocateTask(benchmark::State& state) { - std::vector<sp<TrivialTask>> tasks; - tasks.reserve(state.max_iterations); - - while (state.KeepRunning()) { - tasks.emplace_back(new TrivialTask); - benchmark::DoNotOptimize(tasks.back()); - } -} -BENCHMARK(BM_TaskManager_allocateTask); - -void BM_TaskManager_enqueueTask(benchmark::State& state) { - TaskManager taskManager; - sp<TrivialProcessor> processor(new TrivialProcessor(&taskManager)); - std::vector<sp<TrivialTask>> tasks; - tasks.reserve(state.max_iterations); - - while (state.KeepRunning()) { - tasks.emplace_back(new TrivialTask); - benchmark::DoNotOptimize(tasks.back()); - processor->add(tasks.back()); - } - - for (sp<TrivialTask>& task : tasks) { - task->getResult(); - } -} -BENCHMARK(BM_TaskManager_enqueueTask); - -void BM_TaskManager_enqueueRunDeleteTask(benchmark::State& state) { - TaskManager taskManager; - sp<TrivialProcessor> processor(new TrivialProcessor(&taskManager)); - std::vector<sp<TrivialTask>> tasks; - tasks.reserve(state.max_iterations); - - while (state.KeepRunning()) { - tasks.emplace_back(new TrivialTask); - benchmark::DoNotOptimize(tasks.back()); - processor->add(tasks.back()); - } - state.ResumeTiming(); - for (sp<TrivialTask>& task : tasks) { - benchmark::DoNotOptimize(task->getResult()); - } - tasks.clear(); - state.PauseTiming(); -} -BENCHMARK(BM_TaskManager_enqueueRunDeleteTask); - -void BM_Thread_enqueueTask(benchmark::State& state) { - sp<TestThread> thread{new TestThread}; - thread->start(); - - atomic_int counter(0); - int expected = 0; - while (state.KeepRunning()) { - expected++; - thread->queue().post([&counter]() { counter++; }); - } - thread->queue().runSync([]() {}); - - thread->requestExit(); - thread->join(); - if (counter != expected) { - printf("Ran %d lambads, should have been %d\n", counter.load(), expected); - } -} -BENCHMARK(BM_Thread_enqueueTask); - -void BM_Thread_enqueueRunDeleteTask(benchmark::State& state) { - sp<TestThread> thread{new TestThread}; - thread->start(); - std::vector<std::future<int>> tasks; - tasks.reserve(state.max_iterations); - - int expected = 0; - while (state.KeepRunning()) { - tasks.emplace_back(thread->queue().async([expected]() -> int { return expected + 1; })); - expected++; - } - state.ResumeTiming(); - expected = 0; - for (auto& future : tasks) { - if (future.get() != ++expected) { - printf("Mismatch expected %d vs. observed %d\n", expected, future.get()); - } - } - tasks.clear(); - state.PauseTiming(); -} -BENCHMARK(BM_Thread_enqueueRunDeleteTask);
\ No newline at end of file diff --git a/libs/hwui/tests/unit/CommonPoolTests.cpp b/libs/hwui/tests/unit/CommonPoolTests.cpp new file mode 100644 index 000000000000..c564ed632786 --- /dev/null +++ b/libs/hwui/tests/unit/CommonPoolTests.cpp @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <gtest/gtest.h> + +#include "thread/CommonPool.h" + +#include <array> +#include <condition_variable> +#include <set> +#include <thread> +#include "unistd.h" + +using namespace android; +using namespace android::uirenderer; + +TEST(CommonPool, post) { + std::atomic_bool ran(false); + CommonPool::post([&ran] { ran = true; }); + for (int i = 0; !ran && i < 1000; i++) { + usleep(1); + } + EXPECT_TRUE(ran) << "Failed to flip atomic after 1 second"; +} + +TEST(CommonPool, threadCount) { + std::set<pid_t> threads; + std::array<std::future<pid_t>, 64> futures; + for (int i = 0; i < futures.size(); i++) { + futures[i] = CommonPool::async([] { + usleep(10); + return gettid(); + }); + } + for (auto& f : futures) { + threads.insert(f.get()); + } + EXPECT_EQ(threads.size(), CommonPool::THREAD_COUNT); + EXPECT_EQ(0, threads.count(gettid())); +} + +TEST(CommonPool, singleThread) { + std::mutex mutex; + std::condition_variable fence; + bool isProcessing = false; + bool queuedSecond = false; + + auto f1 = CommonPool::async([&] { + { + std::unique_lock lock{mutex}; + isProcessing = true; + fence.notify_all(); + while (!queuedSecond) { + fence.wait(lock); + } + } + return gettid(); + }); + + { + std::unique_lock lock{mutex}; + while (!isProcessing) { + fence.wait(lock); + } + } + + auto f2 = CommonPool::async([] { + return gettid(); + }); + + { + std::unique_lock lock{mutex}; + queuedSecond = true; + fence.notify_all(); + } + + auto tid1 = f1.get(); + auto tid2 = f2.get(); + EXPECT_EQ(tid1, tid2); + EXPECT_NE(gettid(), tid1); +} + +TEST(CommonPool, fullQueue) { + std::mutex lock; + std::condition_variable fence; + bool signaled = false; + static constexpr auto QUEUE_COUNT = CommonPool::THREAD_COUNT + CommonPool::QUEUE_SIZE + 10; + std::atomic_int queuedCount{0}; + std::array<std::future<void>, QUEUE_COUNT> futures; + + std::thread queueThread{[&] { + for (int i = 0; i < QUEUE_COUNT; i++) { + futures[i] = CommonPool::async([&] { + std::unique_lock _lock{lock}; + while (!signaled) { + fence.wait(_lock); + } + }); + queuedCount++; + } + }}; + + int previous; + do { + previous = queuedCount.load(); + usleep(10000); + } while (previous != queuedCount.load()); + + EXPECT_GT(queuedCount.load(), CommonPool::QUEUE_SIZE); + EXPECT_LT(queuedCount.load(), QUEUE_COUNT); + + { + std::unique_lock _lock{lock}; + signaled = true; + fence.notify_all(); + } + + queueThread.join(); + EXPECT_EQ(queuedCount.load(), QUEUE_COUNT); + + // Ensure all our tasks are finished before return as they have references to the stack + for (auto& f : futures) { + f.get(); + } +}
\ No newline at end of file diff --git a/libs/hwui/tests/unit/main.cpp b/libs/hwui/tests/unit/main.cpp index 63d15403b607..83d888c310f0 100644 --- a/libs/hwui/tests/unit/main.cpp +++ b/libs/hwui/tests/unit/main.cpp @@ -22,9 +22,6 @@ #include "debug/NullGlesDriver.h" #include "hwui/Typeface.h" #include "tests/common/LeakChecker.h" -#include "thread/Task.h" -#include "thread/TaskManager.h" -#include "thread/TaskProcessor.h" #include <signal.h> diff --git a/libs/hwui/thread/Barrier.h b/libs/hwui/thread/Barrier.h deleted file mode 100644 index bb750ca0fa88..000000000000 --- a/libs/hwui/thread/Barrier.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2013 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. - */ - -#ifndef ANDROID_HWUI_BARRIER_H -#define ANDROID_HWUI_BARRIER_H - -#include <utils/Condition.h> - -namespace android { -namespace uirenderer { - -class Barrier { -public: - explicit Barrier(Condition::WakeUpType type = Condition::WAKE_UP_ALL) - : mType(type), mOpened(false) {} - ~Barrier() {} - - void open() { - Mutex::Autolock l(mLock); - mOpened = true; - mCondition.signal(mType); - } - - void wait() const { - Mutex::Autolock l(mLock); - while (!mOpened) { - mCondition.wait(mLock); - } - } - -private: - Condition::WakeUpType mType; - volatile bool mOpened; - mutable Mutex mLock; - mutable Condition mCondition; -}; - -} // namespace uirenderer -} // namespace android - -#endif // ANDROID_HWUI_BARRIER_H diff --git a/libs/hwui/thread/CommonPool.cpp b/libs/hwui/thread/CommonPool.cpp new file mode 100644 index 000000000000..7f94a152cf8d --- /dev/null +++ b/libs/hwui/thread/CommonPool.cpp @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CommonPool.h" + +#include <sys/resource.h> +#include <utils/Trace.h> +#include "renderthread/RenderThread.h" + +#include <array> + +namespace android { +namespace uirenderer { + +CommonPool::CommonPool() { + ATRACE_CALL(); + + CommonPool* pool = this; + // Create 2 workers + for (int i = 0; i < THREAD_COUNT; i++) { + std::thread worker([pool, i] { + { + std::array<char, 20> name{"hwuiTask"}; + snprintf(name.data(), name.size(), "hwuiTask%d", i); + auto self = pthread_self(); + pthread_setname_np(self, name.data()); + setpriority(PRIO_PROCESS, 0, PRIORITY_FOREGROUND); + auto startHook = renderthread::RenderThread::getOnStartHook(); + if (startHook) { + startHook(name.data()); + } + } + pool->workerLoop(); + }); + worker.detach(); + } +} + +void CommonPool::post(Task&& task) { + static CommonPool pool; + pool.enqueue(std::move(task)); +} + +void CommonPool::enqueue(Task&& task) { + std::unique_lock lock(mLock); + while (!mWorkQueue.hasSpace()) { + lock.unlock(); + usleep(100); + lock.lock(); + } + mWorkQueue.push(std::move(task)); + if (mWaitingThreads == THREAD_COUNT || (mWaitingThreads > 0 && mWorkQueue.size() > 1)) { + mCondition.notify_one(); + } +} + +void CommonPool::workerLoop() { + std::unique_lock lock(mLock); + while (true) { + if (!mWorkQueue.hasWork()) { + mWaitingThreads++; + mCondition.wait(lock); + mWaitingThreads--; + } + // Need to double-check that work is still available now that we have the lock + // It may have already been grabbed by a different thread + while (mWorkQueue.hasWork()) { + auto work = mWorkQueue.pop(); + lock.unlock(); + work(); + lock.lock(); + } + } +} + +} // namespace uirenderer +} // namespace android
\ No newline at end of file diff --git a/libs/hwui/thread/CommonPool.h b/libs/hwui/thread/CommonPool.h new file mode 100644 index 000000000000..aef2990d6343 --- /dev/null +++ b/libs/hwui/thread/CommonPool.h @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FRAMEWORKS_BASE_COMMONPOOL_H +#define FRAMEWORKS_BASE_COMMONPOOL_H + +#include "utils/Macros.h" + +#include <log/log.h> + +#include <condition_variable> +#include <functional> +#include <future> +#include <mutex> + +namespace android { +namespace uirenderer { + +template <class T, int SIZE> +class ArrayQueue { + PREVENT_COPY_AND_ASSIGN(ArrayQueue); + static_assert(SIZE > 0, "Size must be positive"); + +public: + ArrayQueue() = default; + ~ArrayQueue() = default; + + constexpr size_t capacity() const { return SIZE; } + constexpr bool hasWork() const { return mHead != mTail; } + constexpr bool hasSpace() const { return ((mHead + 1) % SIZE) != mTail; } + constexpr int size() const { + if (mHead > mTail) { + return mHead - mTail; + } else { + return mTail - mHead + SIZE; + } + } + + constexpr void push(T&& t) { + int newHead = (mHead + 1) % SIZE; + LOG_ALWAYS_FATAL_IF(newHead == mTail, "no space"); + + mBuffer[mHead] = std::move(t); + mHead = newHead; + } + + constexpr T&& pop() { + LOG_ALWAYS_FATAL_IF(mTail == mHead, "empty"); + int index = mTail; + mTail = (mTail + 1) % SIZE; + return std::move(mBuffer[index]); + } + +private: + T mBuffer[SIZE]; + int mHead = 0; + int mTail = 0; +}; + +class CommonPool { + PREVENT_COPY_AND_ASSIGN(CommonPool); + +public: + using Task = std::function<void()>; + static constexpr auto THREAD_COUNT = 2; + static constexpr auto QUEUE_SIZE = 128; + + static void post(Task&& func); + + template <class F> + static auto async(F&& func) -> std::future<decltype(func())> { + typedef std::packaged_task<decltype(func())()> task_t; + auto task = std::make_shared<task_t>(std::forward<F>(func)); + post([task]() { std::invoke(*task); }); + return task->get_future(); + } + + template <class F> + static auto runSync(F&& func) -> decltype(func()) { + std::packaged_task<decltype(func())()> task{std::forward<F>(func)}; + post([&task]() { std::invoke(task); }); + return task.get_future().get(); + }; + +private: + CommonPool(); + ~CommonPool() {} + + void enqueue(Task&&); + + void workerLoop(); + + std::mutex mLock; + std::condition_variable mCondition; + int mWaitingThreads = 0; + ArrayQueue<Task, QUEUE_SIZE> mWorkQueue; +}; + +} // namespace uirenderer +} // namespace android + +#endif // FRAMEWORKS_BASE_COMMONPOOL_H diff --git a/libs/hwui/thread/Future.h b/libs/hwui/thread/Future.h deleted file mode 100644 index df53348e58fb..000000000000 --- a/libs/hwui/thread/Future.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2013 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. - */ - -#ifndef ANDROID_HWUI_FUTURE_H -#define ANDROID_HWUI_FUTURE_H - -#include <utils/RefBase.h> - -#include "Barrier.h" - -namespace android { -namespace uirenderer { - -template <typename T> -class Future : public LightRefBase<Future<T> > { -public: - explicit Future(Condition::WakeUpType type = Condition::WAKE_UP_ONE) - : mBarrier(type), mResult() {} - ~Future() {} - - /** - * Returns the result of this future, blocking if - * the result is not available yet. - */ - T get() const { - mBarrier.wait(); - return mResult; - } - - /** - * This method must be called only once. - */ - void produce(T result) { - mResult = result; - mBarrier.open(); - } - -private: - Barrier mBarrier; - T mResult; -}; - -} // namespace uirenderer -} // namespace android - -#endif // ANDROID_HWUI_FUTURE_H diff --git a/libs/hwui/thread/Signal.h b/libs/hwui/thread/Signal.h deleted file mode 100644 index 6d33ac473ac4..000000000000 --- a/libs/hwui/thread/Signal.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2013 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. - */ - -#ifndef ANDROID_HWUI_SIGNAL_H -#define ANDROID_HWUI_SIGNAL_H - -#include <stdint.h> -#include <sys/types.h> -#include <utils/threads.h> - -namespace android { -namespace uirenderer { - -class Signal { -public: - explicit Signal(Condition::WakeUpType type = Condition::WAKE_UP_ALL) - : mType(type), mSignaled(false) {} - ~Signal() {} - - void signal() { - { - Mutex::Autolock l(mLock); - mSignaled = true; - } - mCondition.signal(mType); - } - - void wait() { - Mutex::Autolock l(mLock); - while (!mSignaled) { - mCondition.wait(mLock); - } - mSignaled = false; - } - -private: - Condition::WakeUpType mType; - volatile bool mSignaled; - mutable Mutex mLock; - mutable Condition mCondition; -}; - -} // namespace uirenderer -} // namespace android - -#endif // ANDROID_HWUI_SIGNAL_H diff --git a/libs/hwui/thread/Task.h b/libs/hwui/thread/Task.h deleted file mode 100644 index 228ce19a2fd5..000000000000 --- a/libs/hwui/thread/Task.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2013 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. - */ - -#ifndef ANDROID_HWUI_TASK_H -#define ANDROID_HWUI_TASK_H - -#include <utils/RefBase.h> -#include <utils/Trace.h> - -#include "Future.h" - -namespace android { -namespace uirenderer { - -class TaskBase : public RefBase { -public: - TaskBase() {} - virtual ~TaskBase() {} -}; - -template <typename T> -class Task : public TaskBase { -public: - Task() : mFuture(new Future<T>()) {} - virtual ~Task() {} - - T getResult() const { return mFuture->get(); } - - void setResult(T result) { mFuture->produce(result); } - -protected: - const sp<Future<T> >& future() const { return mFuture; } - -private: - sp<Future<T> > mFuture; -}; - -} // namespace uirenderer -} // namespace android - -#endif // ANDROID_HWUI_TASK_H diff --git a/libs/hwui/thread/TaskManager.cpp b/libs/hwui/thread/TaskManager.cpp deleted file mode 100644 index de10ff1824ee..000000000000 --- a/libs/hwui/thread/TaskManager.cpp +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (C) 2013 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 <sys/resource.h> -#include <sys/sysinfo.h> - -#include "Task.h" -#include "TaskManager.h" -#include "TaskProcessor.h" -#include "utils/MathUtils.h" -#include "renderthread/RenderThread.h" - -namespace android { -namespace uirenderer { - -/////////////////////////////////////////////////////////////////////////////// -// Manager -/////////////////////////////////////////////////////////////////////////////// - -TaskManager::TaskManager() { - // Get the number of available CPUs. This value does not change over time. - int cpuCount = sysconf(_SC_NPROCESSORS_CONF); - - // Really no point in making more than 2 of these worker threads, but - // we do want to limit ourselves to 1 worker thread on dual-core devices. - int workerCount = cpuCount > 2 ? 2 : 1; - for (int i = 0; i < workerCount; i++) { - String8 name; - name.appendFormat("hwuiTask%d", i + 1); - mThreads.push_back(new WorkerThread(name)); - } -} - -TaskManager::~TaskManager() { - for (size_t i = 0; i < mThreads.size(); i++) { - mThreads[i]->exit(); - } -} - -bool TaskManager::canRunTasks() const { - return mThreads.size() > 0; -} - -void TaskManager::stop() { - for (size_t i = 0; i < mThreads.size(); i++) { - mThreads[i]->exit(); - } -} - -bool TaskManager::addTaskBase(const sp<TaskBase>& task, const sp<TaskProcessorBase>& processor) { - if (mThreads.size() > 0) { - TaskWrapper wrapper(task, processor); - - size_t minQueueSize = INT_MAX; - sp<WorkerThread> thread; - - for (size_t i = 0; i < mThreads.size(); i++) { - if (mThreads[i]->getTaskCount() < minQueueSize) { - thread = mThreads[i]; - minQueueSize = mThreads[i]->getTaskCount(); - } - } - - return thread->addTask(wrapper); - } - return false; -} - -/////////////////////////////////////////////////////////////////////////////// -// Thread -/////////////////////////////////////////////////////////////////////////////// - -status_t TaskManager::WorkerThread::readyToRun() { - setpriority(PRIO_PROCESS, 0, PRIORITY_FOREGROUND); - auto onStartHook = renderthread::RenderThread::getOnStartHook(); - if (onStartHook) { - onStartHook(mName.c_str()); - } - - return NO_ERROR; -} - -bool TaskManager::WorkerThread::threadLoop() { - mSignal.wait(); - std::vector<TaskWrapper> tasks; - { - Mutex::Autolock l(mLock); - tasks.swap(mTasks); - } - - for (size_t i = 0; i < tasks.size(); i++) { - const TaskWrapper& task = tasks[i]; - task.mProcessor->process(task.mTask); - } - - return true; -} - -bool TaskManager::WorkerThread::addTask(const TaskWrapper& task) { - if (!isRunning()) { - run(mName.string(), PRIORITY_DEFAULT); - } else if (exitPending()) { - return false; - } - - { - Mutex::Autolock l(mLock); - mTasks.push_back(task); - } - mSignal.signal(); - - return true; -} - -size_t TaskManager::WorkerThread::getTaskCount() const { - Mutex::Autolock l(mLock); - return mTasks.size(); -} - -void TaskManager::WorkerThread::exit() { - requestExit(); - mSignal.signal(); -} - -} // namespace uirenderer -} // namespace android diff --git a/libs/hwui/thread/TaskManager.h b/libs/hwui/thread/TaskManager.h deleted file mode 100644 index 6c67222a12d7..000000000000 --- a/libs/hwui/thread/TaskManager.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (C) 2013 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. - */ - -#ifndef ANDROID_HWUI_TASK_MANAGER_H -#define ANDROID_HWUI_TASK_MANAGER_H - -#include <utils/Mutex.h> -#include <utils/String8.h> -#include <utils/Thread.h> - -#include "Signal.h" - -#include <vector> - -namespace android { -namespace uirenderer { - -template <typename T> -class Task; -class TaskBase; - -template <typename T> -class TaskProcessor; -class TaskProcessorBase; - -class TaskManager { -public: - TaskManager(); - ~TaskManager(); - - /** - * Returns true if this task manager can run tasks, - * false otherwise. This method will typically return - * false on a single CPU core device. - */ - bool canRunTasks() const; - - /** - * Stops all allocated threads. Adding tasks will start - * the threads again as necessary. - */ - void stop(); - -private: - template <typename T> - friend class TaskProcessor; - - template <typename T> - bool addTask(const sp<Task<T> >& task, const sp<TaskProcessor<T> >& processor) { - return addTaskBase(sp<TaskBase>(task), sp<TaskProcessorBase>(processor)); - } - - bool addTaskBase(const sp<TaskBase>& task, const sp<TaskProcessorBase>& processor); - - struct TaskWrapper { - TaskWrapper() : mTask(), mProcessor() {} - - TaskWrapper(const sp<TaskBase>& task, const sp<TaskProcessorBase>& processor) - : mTask(task), mProcessor(processor) {} - - sp<TaskBase> mTask; - sp<TaskProcessorBase> mProcessor; - }; - - class WorkerThread : public Thread { - public: - explicit WorkerThread(const String8& name) - : Thread(false), mSignal(Condition::WAKE_UP_ONE), mName(name) {} - - bool addTask(const TaskWrapper& task); - size_t getTaskCount() const; - void exit(); - - private: - virtual status_t readyToRun() override; - virtual bool threadLoop() override; - - // Lock for the list of tasks - mutable Mutex mLock; - std::vector<TaskWrapper> mTasks; - - // Signal used to wake up the thread when a new - // task is available in the list - mutable Signal mSignal; - - const String8 mName; - }; - - std::vector<sp<WorkerThread> > mThreads; -}; - -} // namespace uirenderer -} // namespace android - -#endif // ANDROID_HWUI_TASK_MANAGER_H diff --git a/libs/hwui/thread/TaskProcessor.h b/libs/hwui/thread/TaskProcessor.h deleted file mode 100644 index 8117ae6409c4..000000000000 --- a/libs/hwui/thread/TaskProcessor.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (C) 2013 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. - */ - -#ifndef ANDROID_HWUI_TASK_PROCESSOR_H -#define ANDROID_HWUI_TASK_PROCESSOR_H - -#include <utils/RefBase.h> - -#include "Task.h" -#include "TaskManager.h" - -namespace android { -namespace uirenderer { - -class TaskProcessorBase : public RefBase { -public: - TaskProcessorBase() {} - virtual ~TaskProcessorBase(){}; - - virtual void process(const sp<TaskBase>& task) = 0; -}; - -template <typename T> -class TaskProcessor : public TaskProcessorBase { -public: - explicit TaskProcessor(TaskManager* manager) : mManager(manager) {} - virtual ~TaskProcessor() {} - - void add(const sp<Task<T> >& task) { - if (!addImpl(task)) { - // fall back to immediate execution - process(task); - } - } - - virtual void onProcess(const sp<Task<T> >& task) = 0; - -private: - bool addImpl(const sp<Task<T> >& task); - - virtual void process(const sp<TaskBase>& task) override { - sp<Task<T> > realTask = static_cast<Task<T>*>(task.get()); - // This is the right way to do it but sp<> doesn't play nice - // sp<Task<T> > realTask = static_cast<sp<Task<T> > >(task); - onProcess(realTask); - } - - TaskManager* mManager; -}; - -template <typename T> -bool TaskProcessor<T>::addImpl(const sp<Task<T> >& task) { - if (mManager) { - sp<TaskProcessor<T> > self(this); - return mManager->addTask(task, self); - } - return false; -} - -}; // namespace uirenderer -}; // namespace android - -#endif // ANDROID_HWUI_TASK_PROCESSOR_H diff --git a/libs/hwui/thread/WorkQueue.h b/libs/hwui/thread/WorkQueue.h index 7a6e638e0568..42f8503fd000 100644 --- a/libs/hwui/thread/WorkQueue.h +++ b/libs/hwui/thread/WorkQueue.h @@ -26,7 +26,6 @@ #include <functional> #include <future> #include <mutex> -#include <variant> #include <vector> namespace android::uirenderer { diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java index 4bc3897c4477..2ec935598c1b 100644 --- a/media/java/android/media/MediaCodecInfo.java +++ b/media/java/android/media/MediaCodecInfo.java @@ -3223,14 +3223,83 @@ public final class MediaCodecInfo { // These constants were originally in-line with OMX values, but this // correspondence is no longer maintained. + // Profiles and levels for AVC Codec, corresponding to the definitions in + // "SERIES H: AUDIOVISUAL AND MULTIMEDIA SYSTEMS, + // Infrastructure of audiovisual services – Coding of moving video + // Advanced video coding for generic audiovisual services" + // found at + // https://www.itu.int/rec/T-REC-H.264-201704-I + + /** + * AVC Baseline profile. + * See definition in + * <a href="https://www.itu.int/rec/T-REC-H.264-201704-I">H.264 recommendation</a>, + * Annex A. + */ public static final int AVCProfileBaseline = 0x01; + + /** + * AVC Main profile. + * See definition in + * <a href="https://www.itu.int/rec/T-REC-H.264-201704-I">H.264 recommendation</a>, + * Annex A. + */ public static final int AVCProfileMain = 0x02; + + /** + * AVC Extended profile. + * See definition in + * <a href="https://www.itu.int/rec/T-REC-H.264-201704-I">H.264 recommendation</a>, + * Annex A. + */ public static final int AVCProfileExtended = 0x04; + + /** + * AVC High profile. + * See definition in + * <a href="https://www.itu.int/rec/T-REC-H.264-201704-I">H.264 recommendation</a>, + * Annex A. + */ public static final int AVCProfileHigh = 0x08; + + /** + * AVC High 10 profile. + * See definition in + * <a href="https://www.itu.int/rec/T-REC-H.264-201704-I">H.264 recommendation</a>, + * Annex A. + */ public static final int AVCProfileHigh10 = 0x10; + + /** + * AVC High 4:2:2 profile. + * See definition in + * <a href="https://www.itu.int/rec/T-REC-H.264-201704-I">H.264 recommendation</a>, + * Annex A. + */ public static final int AVCProfileHigh422 = 0x20; + + /** + * AVC High 4:4:4 profile. + * See definition in + * <a href="https://www.itu.int/rec/T-REC-H.264-201704-I">H.264 recommendation</a>, + * Annex A. + */ public static final int AVCProfileHigh444 = 0x40; + + /** + * AVC Constrained Baseline profile. + * See definition in + * <a href="https://www.itu.int/rec/T-REC-H.264-201704-I">H.264 recommendation</a>, + * Annex A. + */ public static final int AVCProfileConstrainedBaseline = 0x10000; + + /** + * AVC Constrained High profile. + * See definition in + * <a href="https://www.itu.int/rec/T-REC-H.264-201704-I">H.264 recommendation</a>, + * Annex A. + */ public static final int AVCProfileConstrainedHigh = 0x80000; public static final int AVCLevel1 = 0x01; @@ -3420,8 +3489,34 @@ public final class MediaCodecInfo { public static final int DolbyVisionLevelUhd48 = 0x80; public static final int DolbyVisionLevelUhd60 = 0x100; + // Profiles and levels for AV1 Codec, corresponding to the + // definitions in + // "AV1 Bitstream & Decoding Process Specification", Annex A + // found at + // https://aomedia.org/av1-bitstream-and-decoding-process-specification/ + + /** + * AV1 Main profile. + * See definition in + * <a href="https://aomedia.org/av1-bitstream-and-decoding-process-specification/"> AV1 Bitstream and Decoding Process Specification</a> + * Annex A. + */ public static final int AV1Profile0 = 0x1; + + /** + * AV1 High profile. + * See definition in + * <a href="https://aomedia.org/av1-bitstream-and-decoding-process-specification/"> AV1 Bitstream and Decoding Process Specification</a> + * Annex A. + */ public static final int AV1Profile1 = 0x2; + + /** + * AV1 Professional profile. + * See definition in + * <a href="https://aomedia.org/av1-bitstream-and-decoding-process-specification/"> AV1 Bitstream and Decoding Process Specification</a> + * Annex A. + */ public static final int AV1Profile2 = 0x4; public static final int AV1Level2 = 0x1; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBackAction.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBackAction.java index 7a42b03947ae..1478a0780eb7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBackAction.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBackAction.java @@ -20,7 +20,6 @@ import android.annotation.NonNull; import android.hardware.input.InputManager; import android.os.Handler; import android.os.SystemClock; -import android.view.HapticFeedbackConstants; import android.view.InputDevice; import android.view.KeyCharacterMap; import android.view.KeyEvent; @@ -103,7 +102,6 @@ public class NavigationBackAction extends NavigationGestureAction { private void performBack() { sendEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK); sendEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK); - mNavigationBarView.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY); } private boolean shouldExecuteBackOnUp() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarEdgePanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarEdgePanel.java index fcf5893eafcc..4c7fdb0a6a7a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarEdgePanel.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarEdgePanel.java @@ -22,6 +22,7 @@ import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.PixelFormat; +import android.os.SystemClock; import android.util.FloatProperty; import android.util.MathUtils; import android.view.Gravity; @@ -31,6 +32,7 @@ import android.view.View; import android.view.WindowManager; import com.android.systemui.R; +import com.android.systemui.shared.system.QuickStepContract; public class NavigationBarEdgePanel extends View { private static final String TAG = "NavigationBarEdgePanel"; @@ -48,6 +50,7 @@ public class NavigationBarEdgePanel extends View { private static final float START_POINTING_RATIO = 0.3f; private static final float POINTEDNESS_BEFORE_SNAP_RATIO = 0.4f; private static final int ANIM_DURATION_MS = 150; + private static final long HAPTIC_TIMEOUT_MS = 200; private final Paint mPaint = new Paint(); private final Paint mProtectionPaint = new Paint(); @@ -65,6 +68,8 @@ public class NavigationBarEdgePanel extends View { private float mStartY; private float mStartX; + private boolean mDragSlopPassed; + private long mLastSlopHapticTime; private boolean mGestureDetected; private boolean mArrowsPointLeft; private float mGestureLength; @@ -169,6 +174,7 @@ public class NavigationBarEdgePanel extends View { public boolean onTouchEvent(MotionEvent event) { switch (event.getActionMasked()) { case MotionEvent.ACTION_DOWN : { + mDragSlopPassed = false; show(event.getX(), event.getY()); break; } @@ -263,6 +269,13 @@ public class NavigationBarEdgePanel extends View { private void handleNewSwipePoint(float x) { float dist = MathUtils.abs(x - mStartX); + // Apply a haptic on drag slop passed + if (!mDragSlopPassed && dist > QuickStepContract.getQuickStepDragSlopPx()) { + mDragSlopPassed = true; + performHapticFeedback(HapticFeedbackConstants.CLOCK_TICK); + mLastSlopHapticTime = SystemClock.uptimeMillis(); + } + setDragProgress(MathUtils.constrainedMap( 0, 1.0f, 0, mGestureLength * TRACK_LENGTH_MULTIPLIER, @@ -286,7 +299,10 @@ public class NavigationBarEdgePanel extends View { } } else { if (!mGestureDetected) { - performHapticFeedback(HapticFeedbackConstants.CLOCK_TICK); + // Prevent another haptic if it was just used + if (SystemClock.uptimeMillis() - mLastSlopHapticTime > HAPTIC_TIMEOUT_MS) { + performHapticFeedback(HapticFeedbackConstants.CLOCK_TICK); + } mGestureDetected = true; mLegAnimator.setFloatValues(1f); diff --git a/proto/src/metrics_constants/metrics_constants.proto b/proto/src/metrics_constants/metrics_constants.proto index bc4286356ead..f106228fc6f0 100644 --- a/proto/src/metrics_constants/metrics_constants.proto +++ b/proto/src/metrics_constants/metrics_constants.proto @@ -7117,6 +7117,9 @@ message MetricsEvent { // overridden by the system. FIELD_NOTIFICATION_IMPORTANCE_ASST = 1691; + // Open: Settings > Special App Access > Do not disturb control for app + ZEN_ACCESS_DETAIL = 1692; + // ---- End Q Constants, all Q constants go above this line ---- // Add new aosp constants above this line. // END OF AOSP CONSTANTS diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index 627010606b31..e357ce8ce929 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -1600,6 +1600,11 @@ public final class ActiveServices { "BIND_TREAT_LIKE_ACTIVITY"); } + if ((flags & Context.BIND_SCHEDULE_LIKE_TOP_APP) != 0 && !isCallerSystem) { + throw new SecurityException("Non-system caller (pid=" + Binder.getCallingPid() + + ") set BIND_SCHEDULE_LIKE_TOP_APP when binding service " + service); + } + if ((flags & Context.BIND_ALLOW_WHITELIST_MANAGEMENT) != 0 && !isCallerSystem) { throw new SecurityException( "Non-system caller " + caller + " (pid=" + Binder.getCallingPid() diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 7c6049cd0c90..82254761817e 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -5492,6 +5492,12 @@ public class ActivityManagerService extends IActivityManager.Stub } } + private boolean isAppBad(ApplicationInfo info) { + synchronized (this) { + return mAppErrors.isBadProcessLocked(info); + } + } + // NOTE: this is an internal method used by the OnShellCommand implementation only and should // be guarded by permission checking. int getUidState(int uid) { @@ -18078,6 +18084,11 @@ public class ActivityManagerService extends IActivityManager.Stub } @Override + public boolean isAppBad(ApplicationInfo info) { + return ActivityManagerService.this.isAppBad(info); + } + + @Override public void clearPendingBackup(int userId) { ActivityManagerService.this.clearPendingBackup(userId); } diff --git a/services/core/java/com/android/server/am/ConnectionRecord.java b/services/core/java/com/android/server/am/ConnectionRecord.java index af1031e5b887..a1c941e085a6 100644 --- a/services/core/java/com/android/server/am/ConnectionRecord.java +++ b/services/core/java/com/android/server/am/ConnectionRecord.java @@ -192,6 +192,9 @@ final class ConnectionRecord { if ((flags&Context.BIND_TREAT_LIKE_ACTIVITY) != 0) { sb.append("LACT "); } + if ((flags & Context.BIND_SCHEDULE_LIKE_TOP_APP) != 0) { + sb.append("SLTA "); + } if ((flags&Context.BIND_VISIBLE) != 0) { sb.append("VIS "); } diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java index 4e03b72e6ce6..9056f76c4086 100644 --- a/services/core/java/com/android/server/am/OomAdjuster.java +++ b/services/core/java/com/android/server/am/OomAdjuster.java @@ -1294,6 +1294,11 @@ public final class OomAdjuster { ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND; } } + if (schedGroup < ProcessList.SCHED_GROUP_TOP_APP + && (cr.flags & Context.BIND_SCHEDULE_LIKE_TOP_APP) != 0) { + schedGroup = ProcessList.SCHED_GROUP_TOP_APP; + } + if (!trackedProcState) { cr.trackProcState(clientProcState, mAdjSeq, now); } diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java index 150303aa6a46..647e95284534 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java @@ -231,7 +231,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub Context.BIND_AUTO_CREATE | Context.BIND_TREAT_LIKE_ACTIVITY | Context.BIND_FOREGROUND_SERVICE - | Context.BIND_SHOWING_UI; + | Context.BIND_SHOWING_UI + | Context.BIND_SCHEDULE_LIKE_TOP_APP; @Retention(SOURCE) @IntDef({HardKeyboardBehavior.WIRELESS_AFFORDANCE, HardKeyboardBehavior.WIRED_AFFORDANCE}) diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java index cefe583fc5d1..14b73012d126 100644 --- a/services/core/java/com/android/server/job/JobSchedulerService.java +++ b/services/core/java/com/android/server/job/JobSchedulerService.java @@ -2494,24 +2494,33 @@ public class JobSchedulerService extends com.android.server.SystemService } } - // The expensive check last: validate that the defined package+service is + // The expensive check: validate that the defined package+service is // still present & viable. - final boolean componentPresent; + final ServiceInfo service; try { - componentPresent = (AppGlobals.getPackageManager().getServiceInfo( + service = AppGlobals.getPackageManager().getServiceInfo( job.getServiceComponent(), PackageManager.MATCH_DEBUG_TRIAGED_MISSING, - job.getUserId()) != null); + job.getUserId()); } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } - if (DEBUG) { - Slog.v(TAG, "isReadyToBeExecutedLocked: " + job.toShortString() - + " componentPresent=" + componentPresent); + if (service == null) { + if (DEBUG) { + Slog.v(TAG, "isReadyToBeExecutedLocked: " + job.toShortString() + + " component not present"); + } + return false; } // Everything else checked out so far, so this is the final yes/no check - return componentPresent; + final boolean appIsBad = mActivityManagerInternal.isAppBad(service.applicationInfo); + if (DEBUG) { + if (appIsBad) { + Slog.i(TAG, "App is bad for " + job.toShortString() + " so not runnable"); + } + } + return !appIsBad; } private void evaluateControllerStatesLocked(final JobStatus job) { diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java index a53ab84f733e..293813add594 100644 --- a/services/core/java/com/android/server/locksettings/LockSettingsService.java +++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java @@ -2699,6 +2699,14 @@ public class LockSettingsService extends ILockSettings.Stub { } } + @Override + public boolean hasPendingEscrowToken(int userId) { + checkPasswordReadPermission(userId); + synchronized (mSpManager) { + return !mSpManager.getPendingTokensForUser(userId).isEmpty(); + } + } + private boolean removeEscrowToken(long handle, int userId) { synchronized (mSpManager) { if (handle == getSyntheticPasswordHandleLocked(userId)) { diff --git a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java index 142ad53136fc..1ba0e8ce7839 100644 --- a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java +++ b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java @@ -751,7 +751,7 @@ public class SyntheticPasswordManager { /** * Create a token based Synthetic password for the given user. - * @return + * @return the handle of the token */ public long createTokenBasedSyntheticPassword(byte[] token, int userId, @Nullable EscrowTokenStateChangeCallback changeCallback) { diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 88e697c15a72..4a215cf7febb 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -2504,15 +2504,20 @@ public class NotificationManagerService extends SystemService { } @Override - public boolean canNotifyAsPackage(String callingPkg, String targetPkg) { + public boolean canNotifyAsPackage(String callingPkg, String targetPkg, int userId) { checkCallerIsSameApp(callingPkg); final int callingUid = Binder.getCallingUid(); UserHandle user = UserHandle.getUserHandleForUid(callingUid); + if (user.getIdentifier() != userId) { + getContext().enforceCallingPermission( + android.Manifest.permission.INTERACT_ACROSS_USERS, + "canNotifyAsPackage for user " + userId); + } try { ApplicationInfo info = mPackageManager.getApplicationInfo(targetPkg, MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE, - user.getIdentifier()); + userId); if (info != null) { return mPreferencesHelper.isDelegateAllowed( targetPkg, info.uid, callingPkg, callingUid); diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index e5b6397e863d..4e8ef7100466 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -160,9 +160,9 @@ import android.content.pm.InstantAppInfo; import android.content.pm.InstantAppRequest; import android.content.pm.InstrumentationInfo; import android.content.pm.IntentFilterVerificationInfo; -import android.content.pm.PackageBackwardCompatibility; import android.content.pm.KeySet; import android.content.pm.ModuleInfo; +import android.content.pm.PackageBackwardCompatibility; import android.content.pm.PackageInfo; import android.content.pm.PackageInfoLite; import android.content.pm.PackageInstaller; @@ -232,6 +232,7 @@ import android.os.Trace; import android.os.UserHandle; import android.os.UserManager; import android.os.UserManagerInternal; +import android.os.storage.DiskInfo; import android.os.storage.IStorageManager; import android.os.storage.StorageEventListener; import android.os.storage.StorageManager; @@ -245,6 +246,7 @@ import android.provider.Settings.Secure; import android.security.KeyStore; import android.security.SystemKeyStore; import android.service.pm.PackageServiceDumpProto; +import android.stats.storage.StorageEnums; import android.system.ErrnoException; import android.system.Os; import android.text.TextUtils; @@ -269,6 +271,7 @@ import android.util.Slog; import android.util.SparseArray; import android.util.SparseBooleanArray; import android.util.SparseIntArray; +import android.util.StatsLog; import android.util.TimingsTraceLog; import android.util.Xml; import android.util.jar.StrictJarFile; @@ -1912,6 +1915,15 @@ public class PackageManagerService extends IPackageManager.Stub // Send broadcast package appeared if external for all users if (isExternal(res.pkg)) { + if (!update) { + int packageExternalStorageType = + getPackageExternalStorageType(res.pkg); + // If the package was installed externally, log it. + if (packageExternalStorageType != StorageEnums.UNKNOWN) { + StatsLog.write(StatsLog.APP_INSTALL_ON_EXTERNAL_STORAGE_REPORTED, + packageExternalStorageType, res.pkg.packageName); + } + } if (DEBUG_INSTALL) { Slog.i(TAG, "upgrading pkg " + res.pkg + " is external"); } @@ -2000,6 +2012,32 @@ public class PackageManagerService extends IPackageManager.Stub } } + /** + * Gets the type of the external storage a package is installed on. + * @param pkg The package for which to get the external storage type. + * @return {@link StorageEnum#TYPE_UNKNOWN} if it is not stored externally or the corresponding + * {@link StorageEnum} storage type value if it is. + */ + private int getPackageExternalStorageType(PackageParser.Package pkg) { + final StorageManager storage = mContext.getSystemService(StorageManager.class); + VolumeInfo volume = storage.findVolumeByUuid(pkg.applicationInfo.storageUuid.toString()); + if (volume != null) { + DiskInfo disk = volume.getDisk(); + if (disk != null) { + if (disk.isSd()) { + return StorageEnums.SD_CARD; + } + if (disk.isUsb()) { + return StorageEnums.USB; + } + if (isExternal(pkg)) { + return StorageEnums.OTHER; + } + } + } + return StorageEnums.UNKNOWN; + } + private StorageEventListener mStorageListener = new StorageEventListener() { @Override public void onVolumeStateChanged(VolumeInfo vol, int oldState, int newState) { diff --git a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java index 775152587166..6a07a45ed360 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java @@ -338,12 +338,15 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { initializeCredentialUnderSP(password, PRIMARY_USER_ID); final byte[] storageKey = mStorageManager.getUserUnlockToken(PRIMARY_USER_ID); + assertFalse(mService.hasPendingEscrowToken(PRIMARY_USER_ID)); long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID, null); assertFalse(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID)); + assertTrue(mService.hasPendingEscrowToken(PRIMARY_USER_ID)); mService.verifyCredential(password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID).getResponseCode(); assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID)); + assertFalse(mService.hasPendingEscrowToken(PRIMARY_USER_ID)); mLocalService.setLockCredentialWithToken(pattern, LockPatternUtils.CREDENTIAL_TYPE_PATTERN, handle, token, PASSWORD_QUALITY_SOMETHING, PRIMARY_USER_ID); diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java index 4626840e6263..6f967593e6f1 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java @@ -37,6 +37,7 @@ import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_ON import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR; import static android.content.pm.PackageManager.FEATURE_WATCH; import static android.content.pm.PackageManager.PERMISSION_DENIED; +import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.os.Build.VERSION_CODES.O_MR1; import static android.os.Build.VERSION_CODES.P; import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE; @@ -111,6 +112,7 @@ import android.testing.AndroidTestingRunner; import android.testing.TestableContext; import android.testing.TestableLooper; import android.testing.TestableLooper.RunWithLooper; +import android.testing.TestablePermissions; import android.text.Html; import android.util.ArrayMap; import android.util.ArraySet; @@ -4171,6 +4173,25 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { } @Test + public void testCanNotifyAsUser_crossUser() throws Exception { + // same user no problem + mBinderService.canNotifyAsPackage("src", "target", mContext.getUserId()); + + // cross user, no permission, problem + try { + mBinderService.canNotifyAsPackage("src", "target", mContext.getUserId() + 1); + fail("Should not be callable cross user without cross user permission"); + } catch (SecurityException e) { + // good + } + + // cross user, with permission, no problem + TestablePermissions perms = mContext.getTestablePermissions(); + perms.setPermission(android.Manifest.permission.INTERACT_ACROSS_USERS, PERMISSION_GRANTED); + mBinderService.canNotifyAsPackage("src", "target", mContext.getUserId() + 1); + } + + @Test public void setDefaultAssistantForUser_fromConfigXml() { clearDeviceConfig(); ComponentName xmlConfig = new ComponentName("config", "xml"); diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java index dcaa49996d0b..c05a3461e26e 100644 --- a/telecomm/java/android/telecom/Call.java +++ b/telecomm/java/android/telecom/Call.java @@ -144,6 +144,16 @@ public final class Call { public static final String EXTRA_LAST_EMERGENCY_CALLBACK_TIME_MILLIS = "android.telecom.extra.LAST_EMERGENCY_CALLBACK_TIME_MILLIS"; + + /** + * Extra key used to indicate whether a {@link CallScreeningService} has requested to silence + * the ringtone for a call. If the {@link InCallService} declares + * {@link TelecomManager#METADATA_IN_CALL_SERVICE_RINGING} in its manifest, it should not + * play a ringtone for an incoming call with this extra key set. + */ + public static final String EXTRA_SILENT_RINGING_REQUESTED = + "android.telecom.extra.SILENT_RINGING_REQUESTED"; + /** * Call event sent from a {@link Call} via {@link #sendCallEvent(String, Bundle)} to inform * Telecom that the user has requested that the current {@link Call} should be handed over diff --git a/telecomm/java/android/telecom/CallScreeningService.java b/telecomm/java/android/telecom/CallScreeningService.java index 2fa388fa037e..b1aece7fbe81 100644 --- a/telecomm/java/android/telecom/CallScreeningService.java +++ b/telecomm/java/android/telecom/CallScreeningService.java @@ -259,12 +259,14 @@ public abstract class CallScreeningService extends Service { public static class CallResponse { private final boolean mShouldDisallowCall; private final boolean mShouldRejectCall; + private final boolean mShouldSilenceCall; private final boolean mShouldSkipCallLog; private final boolean mShouldSkipNotification; private CallResponse( boolean shouldDisallowCall, boolean shouldRejectCall, + boolean shouldSilenceCall, boolean shouldSkipCallLog, boolean shouldSkipNotification) { if (!shouldDisallowCall @@ -276,6 +278,7 @@ public abstract class CallScreeningService extends Service { mShouldRejectCall = shouldRejectCall; mShouldSkipCallLog = shouldSkipCallLog; mShouldSkipNotification = shouldSkipNotification; + mShouldSilenceCall = shouldSilenceCall; } /* @@ -294,6 +297,13 @@ public abstract class CallScreeningService extends Service { } /* + * @return Whether the ringtone should be silenced for the incoming call. + */ + public boolean getSilenceCall() { + return mShouldSilenceCall; + } + + /* * @return Whether the incoming call should not be displayed in the call log. */ public boolean getSkipCallLog() { @@ -310,6 +320,7 @@ public abstract class CallScreeningService extends Service { public static class Builder { private boolean mShouldDisallowCall; private boolean mShouldRejectCall; + private boolean mShouldSilenceCall; private boolean mShouldSkipCallLog; private boolean mShouldSkipNotification; @@ -331,6 +342,21 @@ public abstract class CallScreeningService extends Service { } /** + * Sets whether ringing should be silenced for the incoming call. When set + * to {@code true}, the Telecom framework will not play a ringtone for the call. + * The call will, however, still be sent to the default dialer app if it is not blocked. + * A {@link CallScreeningService} can use this to ensure a potential nuisance call is + * still surfaced to the user, but in a less intrusive manner. + * + * Setting this to true only makes sense when the call has not been disallowed + * using {@link #setDisallowCall(boolean)}. + */ + public @NonNull Builder setSilenceCall(boolean shouldSilenceCall) { + mShouldSilenceCall = shouldSilenceCall; + return this; + } + + /** * Sets whether the incoming call should not be displayed in the call log. This property * should only be set to true if the call is disallowed. * <p> @@ -356,6 +382,7 @@ public abstract class CallScreeningService extends Service { return new CallResponse( mShouldDisallowCall, mShouldRejectCall, + mShouldSilenceCall, mShouldSkipCallLog, mShouldSkipNotification); } @@ -411,10 +438,11 @@ public abstract class CallScreeningService extends Service { public abstract void onScreenCall(@NonNull Call.Details callDetails); /** - * Responds to the given incoming call, either allowing it or disallowing it. + * Responds to the given incoming call, either allowing it, silencing it or disallowing it. * <p> * The {@link CallScreeningService} calls this method to inform the system whether the call - * should be silently blocked or not. + * should be silently blocked or not. In the event that it should not be blocked, it may + * also be requested to ring silently. * <p> * Calls to this method are ignored unless the {@link Call.Details#getCallDirection()} is * {@link Call.Details#DIRECTION_INCOMING}. @@ -436,6 +464,8 @@ public abstract class CallScreeningService extends Service { !response.getSkipCallLog(), !response.getSkipNotification(), new ComponentName(getPackageName(), getClass().getName())); + } else if (response.getSilenceCall()) { + mCallScreeningAdapter.silenceCall(callDetails.getTelecomCallId()); } else { mCallScreeningAdapter.allowCall(callDetails.getTelecomCallId()); } diff --git a/telecomm/java/com/android/internal/telecom/ICallScreeningAdapter.aidl b/telecomm/java/com/android/internal/telecom/ICallScreeningAdapter.aidl index a86c83068c6c..1160d27e8f7d 100644 --- a/telecomm/java/com/android/internal/telecom/ICallScreeningAdapter.aidl +++ b/telecomm/java/com/android/internal/telecom/ICallScreeningAdapter.aidl @@ -29,6 +29,8 @@ import android.telecom.CallIdentification; oneway interface ICallScreeningAdapter { void allowCall(String callId); + void silenceCall(String callId); + void disallowCall( String callId, boolean shouldReject, diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java index 524d080c2ea5..2b00363f5406 100755 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -1520,6 +1520,14 @@ public class CarrierConfigManager { "carrier_app_no_wake_signal_config"; /** + * Determines whether the carrier app needed to be involved when users try to finish setting up + * the SIM card to get network service. + * @hide + */ + public static final String KEY_CARRIER_APP_REQUIRED_DURING_SIM_SETUP_BOOL = + "carrier_app_required_during_setup_bool"; + + /** * Default value for {@link Settings.Global#DATA_ROAMING} * @hide */ @@ -2922,6 +2930,7 @@ public class CarrierConfigManager { + "com.android.internal.telephony.CARRIER_SIGNAL_RESET" }); sDefaults.putStringArray(KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY, null); + sDefaults.putBoolean(KEY_CARRIER_APP_REQUIRED_DURING_SIM_SETUP_BOOL, false); // Default carrier app configurations diff --git a/wifi/java/android/net/wifi/WifiNetworkSuggestion.java b/wifi/java/android/net/wifi/WifiNetworkSuggestion.java index 32a7a477466d..a9c9939875e9 100644 --- a/wifi/java/android/net/wifi/WifiNetworkSuggestion.java +++ b/wifi/java/android/net/wifi/WifiNetworkSuggestion.java @@ -403,7 +403,7 @@ public final class WifiNetworkSuggestion implements Parcelable { * .setWpa3Passphrase("test6789") * .build() * final List<WifiNetworkSuggestion> suggestionsList = - * new ArrayList<WifiNetworkSuggestion> {{ + * new ArrayList<WifiNetworkSuggestion> {{ * add(suggestion1); * add(suggestion2); * add(suggestion3); |