Merge "Fix tapping on more than one failure notification."
diff --git a/core/res/res/drawable-hdpi/ic_user_secure.png b/core/res/res/drawable-hdpi/ic_user_secure.png
new file mode 100644
index 0000000..60dcf2a
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_user_secure.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_user_secure.png b/core/res/res/drawable-mdpi/ic_user_secure.png
new file mode 100644
index 0000000..0dea77a
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_user_secure.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_user_secure.png b/core/res/res/drawable-xhdpi/ic_user_secure.png
new file mode 100644
index 0000000..a6ef51a
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_user_secure.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_user_secure.png b/core/res/res/drawable-xxhdpi/ic_user_secure.png
new file mode 100644
index 0000000..e6154e5
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_user_secure.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/ic_user_secure.png b/core/res/res/drawable-xxxhdpi/ic_user_secure.png
new file mode 100644
index 0000000..9a3959b
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/ic_user_secure.png
Binary files differ
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 73cd175..f75f023 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2522,6 +2522,7 @@
<java-symbol type="string" name="user_encrypted_title" />
<java-symbol type="string" name="user_encrypted_message" />
<java-symbol type="string" name="user_encrypted_detail" />
+ <java-symbol type="drawable" name="ic_user_secure" />
<java-symbol type="string" name="usb_mtp_launch_notification_title" />
<java-symbol type="string" name="usb_mtp_launch_notification_description" />
diff --git a/libs/hwui/BakedOpDispatcher.cpp b/libs/hwui/BakedOpDispatcher.cpp
index 04e0755..2184755 100644
--- a/libs/hwui/BakedOpDispatcher.cpp
+++ b/libs/hwui/BakedOpDispatcher.cpp
@@ -663,13 +663,7 @@
}
void BakedOpDispatcher::onShadowOp(BakedOpRenderer& renderer, const ShadowOp& op, const BakedOpState& state) {
- TessellationCache::vertexBuffer_pair_t buffers;
- renderer.caches().tessellationCache.getShadowBuffers(&state.computedState.transform,
- op.localClipRect, op.casterAlpha >= 1.0f, op.casterPath,
- &op.shadowMatrixXY, &op.shadowMatrixZ,
- op.lightCenter, renderer.getLightInfo().lightRadius,
- buffers);
-
+ TessellationCache::vertexBuffer_pair_t buffers = *(op.shadowTask->getResult());
renderShadow(renderer, state, op.casterAlpha, buffers.first, buffers.second);
}
diff --git a/libs/hwui/BakedOpRenderer.h b/libs/hwui/BakedOpRenderer.h
index 10c4698..55ea935 100644
--- a/libs/hwui/BakedOpRenderer.h
+++ b/libs/hwui/BakedOpRenderer.h
@@ -45,13 +45,11 @@
* Position agnostic shadow lighting info. Used with all shadow ops in scene.
*/
struct LightInfo {
- LightInfo() : LightInfo(0, 0, 0) {}
- LightInfo(float lightRadius, uint8_t ambientShadowAlpha,
+ LightInfo() : LightInfo(0, 0) {}
+ LightInfo(uint8_t ambientShadowAlpha,
uint8_t spotShadowAlpha)
- : lightRadius(lightRadius)
- , ambientShadowAlpha(ambientShadowAlpha)
+ : ambientShadowAlpha(ambientShadowAlpha)
, spotShadowAlpha(spotShadowAlpha) {}
- float lightRadius;
uint8_t ambientShadowAlpha;
uint8_t spotShadowAlpha;
};
diff --git a/libs/hwui/BakedOpState.cpp b/libs/hwui/BakedOpState.cpp
index 87844f9..a542c26 100644
--- a/libs/hwui/BakedOpState.cpp
+++ b/libs/hwui/BakedOpState.cpp
@@ -63,16 +63,11 @@
}
}
-ResolvedRenderState::ResolvedRenderState(LinearAllocator& allocator, Snapshot& snapshot) {
- transform = *snapshot.transform;
-
- // Since the op doesn't have known bounds, we conservatively set the mapped bounds
- // to the current clipRect, and clipSideFlags to Full.
- clipState = snapshot.mutateClipArea().serializeClip(allocator);
- LOG_ALWAYS_FATAL_IF(!clipState, "clipState required");
- clippedBounds = clipState->rect;
- clipSideFlags = OpClipSideFlags::Full;
-}
+ResolvedRenderState::ResolvedRenderState(LinearAllocator& allocator, Snapshot& snapshot)
+ : transform(*snapshot.transform)
+ , clipState(snapshot.mutateClipArea().serializeClip(allocator))
+ , clippedBounds(clipState->rect)
+ , clipSideFlags(OpClipSideFlags::Full) {}
ResolvedRenderState::ResolvedRenderState(const ClipRect* viewportRect, const Rect& dstRect)
: transform(Matrix4::identity())
diff --git a/libs/hwui/FrameBuilder.cpp b/libs/hwui/FrameBuilder.cpp
index 4740e1f..57e5b9d 100644
--- a/libs/hwui/FrameBuilder.cpp
+++ b/libs/hwui/FrameBuilder.cpp
@@ -33,17 +33,11 @@
FrameBuilder::FrameBuilder(const LayerUpdateQueue& layers, const SkRect& clip,
uint32_t viewportWidth, uint32_t viewportHeight,
- const std::vector< sp<RenderNode> >& nodes, const Vector3& lightCenter)
- : FrameBuilder(layers, clip, viewportWidth, viewportHeight, nodes, lightCenter,
- Rect(0, 0, 0, 0)) {
-}
-
-
-FrameBuilder::FrameBuilder(const LayerUpdateQueue& layers, const SkRect& clip,
- uint32_t viewportWidth, uint32_t viewportHeight,
- const std::vector< sp<RenderNode> >& nodes, const Vector3& lightCenter,
- const Rect &contentDrawBounds)
- : mCanvasState(*this) {
+ const std::vector< sp<RenderNode> >& nodes,
+ const LightGeometry& lightGeometry, const Rect &contentDrawBounds, Caches* caches)
+ : mCanvasState(*this)
+ , mCaches(caches)
+ , mLightRadius(lightGeometry.radius) {
ATRACE_NAME("prepare drawing commands");
mLayerBuilders.reserve(layers.entries().size());
@@ -55,7 +49,7 @@
mLayerStack.push_back(0);
mCanvasState.initializeSaveStack(viewportWidth, viewportHeight,
clip.fLeft, clip.fTop, clip.fRight, clip.fBottom,
- lightCenter);
+ lightGeometry.center);
// Render all layers to be updated, in order. Defer in reverse order, so that they'll be
// updated in the order they're passed in (mLayerBuilders are issued to Renderer in reverse)
@@ -367,13 +361,28 @@
casterPath = frameAllocatedPath;
}
- ShadowOp* shadowOp = new (mAllocator) ShadowOp(casterNodeOp, casterAlpha, casterPath,
- mCanvasState.getLocalClipBounds(),
- mCanvasState.currentSnapshot()->getRelativeLightCenter());
- BakedOpState* bakedOpState = BakedOpState::tryShadowOpConstruct(
- mAllocator, *mCanvasState.writableSnapshot(), shadowOp);
- if (CC_LIKELY(bakedOpState)) {
- currentLayer().deferUnmergeableOp(mAllocator, bakedOpState, OpBatchType::Shadow);
+
+ if (CC_LIKELY(!mCanvasState.getRenderTargetClipBounds().isEmpty())) {
+ Matrix4 shadowMatrixXY(casterNodeOp.localMatrix);
+ Matrix4 shadowMatrixZ(casterNodeOp.localMatrix);
+ node.applyViewPropertyTransforms(shadowMatrixXY, false);
+ node.applyViewPropertyTransforms(shadowMatrixZ, true);
+
+ LOG_ALWAYS_FATAL_IF(!mCaches, "Caches needed for shadows");
+ sp<TessellationCache::ShadowTask> task = mCaches->tessellationCache.getShadowTask(
+ mCanvasState.currentTransform(),
+ mCanvasState.getLocalClipBounds(),
+ casterAlpha >= 1.0f,
+ casterPath,
+ &shadowMatrixXY, &shadowMatrixZ,
+ mCanvasState.currentSnapshot()->getRelativeLightCenter(),
+ mLightRadius);
+ ShadowOp* shadowOp = mAllocator.create<ShadowOp>(task, casterAlpha);
+ BakedOpState* bakedOpState = BakedOpState::tryShadowOpConstruct(
+ mAllocator, *mCanvasState.writableSnapshot(), shadowOp);
+ if (CC_LIKELY(bakedOpState)) {
+ currentLayer().deferUnmergeableOp(mAllocator, bakedOpState, OpBatchType::Shadow);
+ }
}
}
diff --git a/libs/hwui/FrameBuilder.h b/libs/hwui/FrameBuilder.h
index 01d52ce..f44306a 100644
--- a/libs/hwui/FrameBuilder.h
+++ b/libs/hwui/FrameBuilder.h
@@ -55,14 +55,24 @@
*/
class FrameBuilder : public CanvasStateClient {
public:
+ struct LightGeometry {
+ Vector3 center;
+ float radius;
+ };
+
+ // TODO: remove
FrameBuilder(const LayerUpdateQueue& layers, const SkRect& clip,
uint32_t viewportWidth, uint32_t viewportHeight,
- const std::vector< sp<RenderNode> >& nodes, const Vector3& lightCenter);
+ const std::vector< sp<RenderNode> >& nodes,
+ const LightGeometry& lightGeometry,
+ Caches* caches)
+ : FrameBuilder(layers, clip, viewportWidth, viewportHeight, nodes, lightGeometry, Rect(), caches) {}
FrameBuilder(const LayerUpdateQueue& layers, const SkRect& clip,
uint32_t viewportWidth, uint32_t viewportHeight,
- const std::vector< sp<RenderNode> >& nodes, const Vector3& lightCenter,
- const Rect &contentDrawBounds);
+ const std::vector< sp<RenderNode> >& nodes,
+ const LightGeometry& lightGeometry,
+ const Rect &contentDrawBounds, Caches* caches);
virtual ~FrameBuilder() {}
@@ -216,7 +226,11 @@
CanvasState mCanvasState;
- // contains ResolvedOps and Batches
+ Caches* mCaches = nullptr;
+
+ float mLightRadius;
+
+ // contains single-frame objects, such as BakedOpStates, LayerBuilders, Batches
LinearAllocator mAllocator;
};
diff --git a/libs/hwui/RecordedOp.h b/libs/hwui/RecordedOp.h
index d27064b..bb26e2e 100644
--- a/libs/hwui/RecordedOp.h
+++ b/libs/hwui/RecordedOp.h
@@ -22,6 +22,7 @@
#include "Matrix.h"
#include "Rect.h"
#include "RenderNode.h"
+#include "TessellationCache.h"
#include "utils/LinearAllocator.h"
#include "Vector.h"
@@ -346,25 +347,13 @@
* State construction handles these properties specially, ignoring matrix/bounds.
*/
struct ShadowOp : RecordedOp {
- ShadowOp(const RenderNodeOp& casterOp, float casterAlpha, const SkPath* casterPath,
- const Rect& localClipRect, const Vector3& lightCenter)
+ ShadowOp(sp<TessellationCache::ShadowTask>& shadowTask, float casterAlpha)
: RecordedOp(RecordedOpId::ShadowOp, Rect(), Matrix4::identity(), nullptr, nullptr)
- , shadowMatrixXY(casterOp.localMatrix)
- , shadowMatrixZ(casterOp.localMatrix)
- , casterAlpha(casterAlpha)
- , casterPath(casterPath)
- , localClipRect(localClipRect)
- , lightCenter(lightCenter) {
- const RenderNode& node = *casterOp.renderNode;
- node.applyViewPropertyTransforms(shadowMatrixXY, false);
- node.applyViewPropertyTransforms(shadowMatrixZ, true);
+ , shadowTask(shadowTask)
+ , casterAlpha(casterAlpha) {
};
- Matrix4 shadowMatrixXY;
- Matrix4 shadowMatrixZ;
+ sp<TessellationCache::ShadowTask> shadowTask;
const float casterAlpha;
- const SkPath* casterPath;
- const Rect localClipRect;
- const Vector3 lightCenter;
};
struct SimpleRectsOp : RecordedOp { // Filled, no AA (TODO: better name?)
diff --git a/libs/hwui/TessellationCache.cpp b/libs/hwui/TessellationCache.cpp
index 0835c29..461e819 100644
--- a/libs/hwui/TessellationCache.cpp
+++ b/libs/hwui/TessellationCache.cpp
@@ -160,45 +160,6 @@
// Shadow tessellation task processing
///////////////////////////////////////////////////////////////////////////////
-class ShadowTask : public Task<TessellationCache::vertexBuffer_pair_t*> {
-public:
- ShadowTask(const Matrix4* drawTransform, const Rect& localClip, bool opaque,
- const SkPath* casterPerimeter, const Matrix4* transformXY, const Matrix4* transformZ,
- const Vector3& lightCenter, float lightRadius)
- : drawTransform(*drawTransform)
- , localClip(localClip)
- , opaque(opaque)
- , casterPerimeter(*casterPerimeter)
- , transformXY(*transformXY)
- , transformZ(*transformZ)
- , lightCenter(lightCenter)
- , lightRadius(lightRadius) {
- }
-
- ~ShadowTask() {
- TessellationCache::vertexBuffer_pair_t* bufferPair = getResult();
- delete bufferPair->getFirst();
- delete bufferPair->getSecond();
- delete bufferPair;
- }
-
- /* Note - we deep copy all task parameters, because *even though* pointers into Allocator
- * controlled objects (like the SkPath and Matrix4s) should be safe for the entire frame,
- * certain Allocators are destroyed before trim() is called to flush incomplete tasks.
- *
- * These deep copies could be avoided, long term, by cancelling or flushing outstanding tasks
- * before tearning down single-frame LinearAllocators.
- */
- const Matrix4 drawTransform;
- const Rect localClip;
- bool opaque;
- const SkPath casterPerimeter;
- const Matrix4 transformXY;
- const Matrix4 transformZ;
- const Vector3 lightCenter;
- const float lightRadius;
-};
-
static void mapPointFakeZ(Vector3& point, const mat4* transformXY, const mat4* transformZ) {
// map z coordinate with true 3d matrix
point.z = transformZ->mapZ(point);
@@ -288,7 +249,7 @@
~ShadowProcessor() {}
virtual void onProcess(const sp<Task<TessellationCache::vertexBuffer_pair_t*> >& task) override {
- ShadowTask* t = static_cast<ShadowTask*>(task.get());
+ TessellationCache::ShadowTask* t = static_cast<TessellationCache::ShadowTask*>(task.get());
ATRACE_NAME("shadow tessellation");
VertexBuffer* ambientBuffer = new VertexBuffer;
@@ -415,6 +376,29 @@
outBuffers = *(task->getResult());
}
+sp<TessellationCache::ShadowTask> TessellationCache::getShadowTask(
+ const Matrix4* drawTransform, const Rect& localClip,
+ bool opaque, const SkPath* casterPerimeter,
+ const Matrix4* transformXY, const Matrix4* transformZ,
+ const Vector3& lightCenter, float lightRadius) {
+ ShadowDescription key(casterPerimeter, drawTransform);
+ ShadowTask* task = static_cast<ShadowTask*>(mShadowCache.get(key));
+ if (!task) {
+ precacheShadows(drawTransform, localClip, opaque, casterPerimeter,
+ transformXY, transformZ, lightCenter, lightRadius);
+ task = static_cast<ShadowTask*>(mShadowCache.get(key));
+ }
+ LOG_ALWAYS_FATAL_IF(task == nullptr, "shadow not precached");
+ return task;
+}
+
+TessellationCache::ShadowTask::~ShadowTask() {
+ TessellationCache::vertexBuffer_pair_t* bufferPair = getResult();
+ delete bufferPair->getFirst();
+ delete bufferPair->getSecond();
+ delete bufferPair;
+}
+
///////////////////////////////////////////////////////////////////////////////
// Tessellation precaching
///////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/TessellationCache.h b/libs/hwui/TessellationCache.h
index 06e567e..977c2d9e 100644
--- a/libs/hwui/TessellationCache.h
+++ b/libs/hwui/TessellationCache.h
@@ -26,6 +26,7 @@
#include "utils/Pair.h"
#include <SkPaint.h>
+#include <SkPath.h>
#include <utils/LruCache.h>
#include <utils/Mutex.h>
@@ -33,7 +34,6 @@
class SkBitmap;
class SkCanvas;
-class SkPath;
struct SkRect;
namespace android {
@@ -89,6 +89,40 @@
hash_t hash() const;
};
+ class ShadowTask : public Task<TessellationCache::vertexBuffer_pair_t*> {
+ public:
+ ShadowTask(const Matrix4* drawTransform, const Rect& localClip, bool opaque,
+ const SkPath* casterPerimeter, const Matrix4* transformXY, const Matrix4* transformZ,
+ const Vector3& lightCenter, float lightRadius)
+ : drawTransform(*drawTransform)
+ , localClip(localClip)
+ , opaque(opaque)
+ , casterPerimeter(*casterPerimeter)
+ , transformXY(*transformXY)
+ , transformZ(*transformZ)
+ , lightCenter(lightCenter)
+ , lightRadius(lightRadius) {
+ }
+
+ ~ShadowTask();
+
+ /* Note - we deep copy all task parameters, because *even though* pointers into Allocator
+ * controlled objects (like the SkPath and Matrix4s) should be safe for the entire frame,
+ * certain Allocators are destroyed before trim() is called to flush incomplete tasks.
+ *
+ * These deep copies could be avoided, long term, by cancelling or flushing outstanding
+ * tasks before tearing down single-frame LinearAllocators.
+ */
+ const Matrix4 drawTransform;
+ const Rect localClip;
+ bool opaque;
+ const SkPath casterPerimeter;
+ const Matrix4 transformXY;
+ const Matrix4 transformZ;
+ const Vector3 lightCenter;
+ const float lightRadius;
+ };
+
TessellationCache();
~TessellationCache();
@@ -133,17 +167,22 @@
const VertexBuffer* getRoundRect(const Matrix4& transform, const SkPaint& paint,
float width, float height, float rx, float ry);
+ // TODO: delete these when switching to HWUI_NEW_OPS
void precacheShadows(const Matrix4* drawTransform, const Rect& localClip,
bool opaque, const SkPath* casterPerimeter,
const Matrix4* transformXY, const Matrix4* transformZ,
const Vector3& lightCenter, float lightRadius);
-
void getShadowBuffers(const Matrix4* drawTransform, const Rect& localClip,
bool opaque, const SkPath* casterPerimeter,
const Matrix4* transformXY, const Matrix4* transformZ,
const Vector3& lightCenter, float lightRadius,
vertexBuffer_pair_t& outBuffers);
+ sp<ShadowTask> getShadowTask(const Matrix4* drawTransform, const Rect& localClip,
+ bool opaque, const SkPath* casterPerimeter,
+ const Matrix4* transformXY, const Matrix4* transformZ,
+ const Vector3& lightCenter, float lightRadius);
+
private:
class Buffer;
class TessellationTask;
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index e7cf3ec..d411621 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -33,10 +33,6 @@
#include "utils/GLUtils.h"
#include "utils/TimeUtils.h"
-#if HWUI_NEW_OPS
-#include "FrameBuilder.h"
-#endif
-
#include <cutils/properties.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <private/hwui/DrawGlInfo.h>
@@ -152,7 +148,7 @@
void CanvasContext::setup(int width, int height, float lightRadius,
uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) {
#if HWUI_NEW_OPS
- mLightInfo.lightRadius = lightRadius;
+ mLightGeometry.radius = lightRadius;
mLightInfo.ambientShadowAlpha = ambientShadowAlpha;
mLightInfo.spotShadowAlpha = spotShadowAlpha;
#else
@@ -163,7 +159,7 @@
void CanvasContext::setLightCenter(const Vector3& lightCenter) {
#if HWUI_NEW_OPS
- mLightCenter = lightCenter;
+ mLightGeometry.center = lightCenter;
#else
if (!mCanvas) return;
mCanvas->setLightCenter(lightCenter);
@@ -345,7 +341,7 @@
#if HWUI_NEW_OPS
FrameBuilder frameBuilder(mLayerUpdateQueue, dirty, frame.width(), frame.height(),
- mRenderNodes, mLightCenter, mContentDrawBounds);
+ mRenderNodes, mLightGeometry, mContentDrawBounds, &Caches::getInstance());
mLayerUpdateQueue.clear();
BakedOpRenderer renderer(Caches::getInstance(), mRenderThread.renderState(),
mOpaque, mLightInfo);
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 270fb1f..63a7977 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -31,6 +31,7 @@
#if HWUI_NEW_OPS
#include "BakedOpDispatcher.h"
#include "BakedOpRenderer.h"
+#include "FrameBuilder.h"
#endif
#include <cutils/compiler.h>
@@ -197,7 +198,7 @@
OpenGLRenderer* mCanvas = nullptr;
#if HWUI_NEW_OPS
BakedOpRenderer::LightInfo mLightInfo;
- Vector3 mLightCenter = { 0, 0, 0 };
+ FrameBuilder::LightGeometry mLightGeometry = { {0, 0, 0}, 0 };
#endif
bool mHaveNewSurface = false;
diff --git a/libs/hwui/tests/microbench/FrameBuilderBench.cpp b/libs/hwui/tests/microbench/FrameBuilderBench.cpp
index f9c2b67..7845eb4 100644
--- a/libs/hwui/tests/microbench/FrameBuilderBench.cpp
+++ b/libs/hwui/tests/microbench/FrameBuilderBench.cpp
@@ -37,7 +37,8 @@
using namespace android::uirenderer::test;
const LayerUpdateQueue sEmptyLayerUpdateQueue;
-const Vector3 sLightCenter = {100, 100, 100};
+const FrameBuilder::LightGeometry sLightGeometry = { {100, 100, 100}, 50};
+const BakedOpRenderer::LightInfo sLightInfo = { 128, 128 };
static std::vector<sp<RenderNode>> createTestNodeList() {
auto node = TestUtils::createNode(0, 0, 200, 200,
@@ -67,7 +68,7 @@
StartBenchmarkTiming();
for (int i = 0; i < iters; i++) {
FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 200), 100, 200,
- nodes, sLightCenter);
+ nodes, sLightGeometry, nullptr);
MicroBench::DoNotOptimize(&frameBuilder);
}
StopBenchmarkTiming();
@@ -77,7 +78,6 @@
void BM_FrameBuilder_deferAndRender::Run(int iters) {
TestUtils::runOnRenderThread([this, iters](RenderThread& thread) {
auto nodes = createTestNodeList();
- BakedOpRenderer::LightInfo lightInfo = {50.0f, 128, 128 };
RenderState& renderState = thread.renderState();
Caches& caches = Caches::getInstance();
@@ -85,9 +85,9 @@
StartBenchmarkTiming();
for (int i = 0; i < iters; i++) {
FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 200), 100, 200,
- nodes, sLightCenter);
+ nodes, sLightGeometry, nullptr);
- BakedOpRenderer renderer(caches, renderState, true, lightInfo);
+ BakedOpRenderer renderer(caches, renderState, true, sLightInfo);
frameBuilder.replayBakedOps<BakedOpDispatcher>(renderer);
MicroBench::DoNotOptimize(&renderer);
}
@@ -119,7 +119,7 @@
for (int i = 0; i < iters; i++) {
FrameBuilder frameBuilder(sEmptyLayerUpdateQueue,
SkRect::MakeWH(gDisplay.w, gDisplay.h), gDisplay.w, gDisplay.h,
- nodes, sLightCenter);
+ nodes, sLightGeometry, nullptr);
MicroBench::DoNotOptimize(&frameBuilder);
}
benchmark.StopBenchmarkTiming();
@@ -129,7 +129,6 @@
int iters, const char* sceneName) {
TestUtils::runOnRenderThread([&benchmark, iters, sceneName](RenderThread& thread) {
auto nodes = getSyncedSceneNodes(sceneName);
- BakedOpRenderer::LightInfo lightInfo = {50.0f, 128, 128 }; // TODO!
RenderState& renderState = thread.renderState();
Caches& caches = Caches::getInstance();
@@ -138,9 +137,9 @@
for (int i = 0; i < iters; i++) {
FrameBuilder frameBuilder(sEmptyLayerUpdateQueue,
SkRect::MakeWH(gDisplay.w, gDisplay.h), gDisplay.w, gDisplay.h,
- nodes, sLightCenter);
+ nodes, sLightGeometry, nullptr);
- BakedOpRenderer renderer(caches, renderState, true, lightInfo);
+ BakedOpRenderer renderer(caches, renderState, true, sLightInfo);
frameBuilder.replayBakedOps<BakedOpDispatcher>(renderer);
MicroBench::DoNotOptimize(&renderer);
}
diff --git a/libs/hwui/tests/unit/FrameBuilderTests.cpp b/libs/hwui/tests/unit/FrameBuilderTests.cpp
index 618df14..f49dd3f 100644
--- a/libs/hwui/tests/unit/FrameBuilderTests.cpp
+++ b/libs/hwui/tests/unit/FrameBuilderTests.cpp
@@ -30,7 +30,8 @@
namespace uirenderer {
const LayerUpdateQueue sEmptyLayerUpdateQueue;
-const Vector3 sLightCenter = {100, 100, 100};
+const FrameBuilder::LightGeometry sLightGeometry = { {100, 100, 100}, 50};
+
/**
* Virtual class implemented by each test to redirect static operation / state transitions to
@@ -132,7 +133,7 @@
canvas.drawBitmap(bitmap, 10, 10, nullptr);
});
FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 200), 100, 200,
- TestUtils::createSyncedNodeList(node), sLightCenter);
+ TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr);
SimpleTestRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(4, renderer.getIndex()); // 2 ops + start + end
@@ -158,7 +159,7 @@
canvas.drawPoint(50, 50, strokedPaint);
});
FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 200), 100, 200,
- TestUtils::createSyncedNodeList(node), sLightCenter);
+ TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr);
SimpleStrokeTestRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(1, renderer.getIndex());
@@ -173,7 +174,7 @@
canvas.restore();
});
FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
- TestUtils::createSyncedNodeList(node), sLightCenter);
+ TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr);
FailRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
@@ -208,7 +209,7 @@
});
FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
- TestUtils::createSyncedNodeList(node), sLightCenter);
+ TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr);
SimpleBatchingTestRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(2 * LOOPS, renderer.getIndex())
@@ -250,7 +251,7 @@
});
FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 100), 100, 100,
- TestUtils::createSyncedNodeList(node), sLightCenter);
+ TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr);
ClippedMergingTestRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(4, renderer.getIndex());
@@ -278,7 +279,7 @@
TestUtils::drawTextToCanvas(&canvas, "Test string1", paint, 100, 100); // not clipped
});
FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(400, 400), 400, 400,
- TestUtils::createSyncedNodeList(node), sLightCenter);
+ TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr);
TextMergingTestRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(2, renderer.getIndex()) << "Expect 2 ops";
@@ -309,7 +310,7 @@
}
});
FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 2000), 200, 2000,
- TestUtils::createSyncedNodeList(node), sLightCenter);
+ TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr);
TextStrikethroughTestRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(2 * LOOPS, renderer.getIndex())
@@ -343,7 +344,7 @@
canvas.restore();
});
FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
- TestUtils::createSyncedNodeList(node), sLightCenter);
+ TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr);
TextureLayerTestRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(1, renderer.getIndex());
@@ -388,7 +389,7 @@
});
FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
- TestUtils::createSyncedNodeList(parent), sLightCenter);
+ TestUtils::createSyncedNodeList(parent), sLightGeometry, nullptr);
RenderNodeTestRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
}
@@ -412,7 +413,7 @@
FrameBuilder frameBuilder(sEmptyLayerUpdateQueue,
SkRect::MakeLTRB(10, 20, 30, 40), // clip to small area, should see in receiver
- 200, 200, TestUtils::createSyncedNodeList(node), sLightCenter);
+ 200, 200, TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr);
ClippedTestRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
}
@@ -454,7 +455,7 @@
canvas.restore();
});
FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
- TestUtils::createSyncedNodeList(node), sLightCenter);
+ TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr);
SaveLayerSimpleTestRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(4, renderer.getIndex());
@@ -526,7 +527,7 @@
});
FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(800, 800), 800, 800,
- TestUtils::createSyncedNodeList(node), sLightCenter);
+ TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr);
SaveLayerNestedTestRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(10, renderer.getIndex());
@@ -546,7 +547,7 @@
canvas.restore();
});
FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
- TestUtils::createSyncedNodeList(node), sLightCenter);
+ TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr);
FailRenderer renderer;
// should see no ops, even within the layer, since the layer should be rejected
@@ -589,7 +590,7 @@
canvas.restore();
});
FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
- TestUtils::createSyncedNodeList(node), sLightCenter);
+ TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr);
SaveLayerUnclippedSimpleTestRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(4, renderer.getIndex());
@@ -643,7 +644,7 @@
canvas.restoreToCount(restoreTo);
});
FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
- TestUtils::createSyncedNodeList(node), sLightCenter);
+ TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr);
SaveLayerUnclippedMergedClearsTestRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(10, renderer.getIndex())
@@ -705,7 +706,7 @@
canvas.restore();
});
FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(600, 600), 600, 600,
- TestUtils::createSyncedNodeList(node), sLightCenter);
+ TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr);
SaveLayerUnclippedComplexTestRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(12, renderer.getIndex());
@@ -763,7 +764,7 @@
layerUpdateQueue.enqueueLayerWithDamage(node.get(), Rect(25, 25, 75, 75));
FrameBuilder frameBuilder(layerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
- syncedNodeList, sLightCenter);
+ syncedNodeList, sLightGeometry, nullptr);
HwLayerSimpleTestRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(6, renderer.getIndex());
@@ -864,7 +865,7 @@
layerUpdateQueue.enqueueLayerWithDamage(parent.get(), Rect(200, 200));
FrameBuilder frameBuilder(layerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
- syncedList, sLightCenter);
+ syncedList, sLightGeometry, nullptr);
HwLayerComplexTestRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(13, renderer.getIndex());
@@ -913,7 +914,7 @@
drawOrderedNode(&canvas, 9, -10.0f); // in reorder=false at this point, so played inorder
});
FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 100), 100, 100,
- TestUtils::createSyncedNodeList(parent), sLightCenter);
+ TestUtils::createSyncedNodeList(parent), sLightGeometry, nullptr);
ZReorderTestRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(10, renderer.getIndex());
@@ -996,7 +997,7 @@
});
FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 100), 100, 100,
- TestUtils::createSyncedNodeList(parent), sLightCenter);
+ TestUtils::createSyncedNodeList(parent), sLightGeometry, nullptr);
ProjectionReorderTestRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(3, renderer.getIndex());
@@ -1014,18 +1015,18 @@
});
}
-TEST(FrameBuilder, shadow) {
+RENDERTHREAD_TEST(FrameBuilder, shadow) {
class ShadowTestRenderer : public TestRendererBase {
public:
void onShadowOp(const ShadowOp& op, const BakedOpState& state) override {
EXPECT_EQ(0, mIndex++);
EXPECT_FLOAT_EQ(1.0f, op.casterAlpha);
- EXPECT_TRUE(op.casterPath->isRect(nullptr));
- EXPECT_MATRIX_APPROX_EQ(Matrix4::identity(), op.shadowMatrixXY);
+ EXPECT_TRUE(op.shadowTask->casterPerimeter.isRect(nullptr));
+ EXPECT_MATRIX_APPROX_EQ(Matrix4::identity(), op.shadowTask->transformXY);
Matrix4 expectedZ;
expectedZ.loadTranslate(0, 0, 5);
- EXPECT_MATRIX_APPROX_EQ(expectedZ, op.shadowMatrixZ);
+ EXPECT_MATRIX_APPROX_EQ(expectedZ, op.shadowTask->transformZ);
}
void onRectOp(const RectOp& op, const BakedOpState& state) override {
EXPECT_EQ(1, mIndex++);
@@ -1039,13 +1040,13 @@
});
FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
- TestUtils::createSyncedNodeList(parent), sLightCenter);
+ TestUtils::createSyncedNodeList(parent), sLightGeometry, &Caches::getInstance());
ShadowTestRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(2, renderer.getIndex());
}
-TEST(FrameBuilder, shadowSaveLayer) {
+RENDERTHREAD_TEST(FrameBuilder, shadowSaveLayer) {
class ShadowSaveLayerTestRenderer : public TestRendererBase {
public:
OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) override {
@@ -1054,8 +1055,8 @@
}
void onShadowOp(const ShadowOp& op, const BakedOpState& state) override {
EXPECT_EQ(1, mIndex++);
- EXPECT_FLOAT_EQ(50, op.lightCenter.x);
- EXPECT_FLOAT_EQ(40, op.lightCenter.y);
+ EXPECT_FLOAT_EQ(50, op.shadowTask->lightCenter.x);
+ EXPECT_FLOAT_EQ(40, op.shadowTask->lightCenter.y);
}
void onRectOp(const RectOp& op, const BakedOpState& state) override {
EXPECT_EQ(2, mIndex++);
@@ -1080,7 +1081,9 @@
});
FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
- TestUtils::createSyncedNodeList(parent), (Vector3) { 100, 100, 100 });
+ TestUtils::createSyncedNodeList(parent),
+ (FrameBuilder::LightGeometry) {{ 100, 100, 100 }, 50},
+ &Caches::getInstance());
ShadowSaveLayerTestRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(5, renderer.getIndex());
@@ -1094,8 +1097,9 @@
}
void onShadowOp(const ShadowOp& op, const BakedOpState& state) override {
EXPECT_EQ(1, mIndex++);
- EXPECT_FLOAT_EQ(50, op.lightCenter.x);
- EXPECT_FLOAT_EQ(40, op.lightCenter.y);
+ EXPECT_FLOAT_EQ(50, op.shadowTask->lightCenter.x);
+ EXPECT_FLOAT_EQ(40, op.shadowTask->lightCenter.y);
+ EXPECT_FLOAT_EQ(30, op.shadowTask->lightRadius);
}
void onRectOp(const RectOp& op, const BakedOpState& state) override {
EXPECT_EQ(2, mIndex++);
@@ -1130,7 +1134,9 @@
LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid
layerUpdateQueue.enqueueLayerWithDamage(parent.get(), Rect(100, 100));
FrameBuilder frameBuilder(layerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
- syncedList, (Vector3) { 100, 100, 100 });
+ syncedList,
+ (FrameBuilder::LightGeometry) {{ 100, 100, 100 }, 30},
+ &Caches::getInstance());
ShadowHwLayerTestRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(5, renderer.getIndex());
@@ -1159,7 +1165,9 @@
});
FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
- TestUtils::createSyncedNodeList(parent), sLightCenter);
+ TestUtils::createSyncedNodeList(parent),
+ (FrameBuilder::LightGeometry) {{ 100, 100, 100 }, 50},
+ &Caches::getInstance());
ShadowLayeringTestRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(4, renderer.getIndex());
@@ -1187,7 +1195,7 @@
});
FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 100), 200, 200,
- TestUtils::createSyncedNodeList(node), sLightCenter);
+ TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr);
PropertyTestRenderer renderer(opValidateCallback);
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(1, renderer.getIndex()) << "Should have seen one op";
@@ -1328,7 +1336,8 @@
});
auto nodes = TestUtils::createSyncedNodeList(node); // sync before querying height
- FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, nodes, sLightCenter);
+ FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
+ nodes, sLightGeometry, nullptr);
SaveLayerAlphaClipTestRenderer renderer(outObservedData);
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
diff --git a/libs/hwui/tests/unit/LeakCheckTests.cpp b/libs/hwui/tests/unit/LeakCheckTests.cpp
index 4a635fb..da786c7 100644
--- a/libs/hwui/tests/unit/LeakCheckTests.cpp
+++ b/libs/hwui/tests/unit/LeakCheckTests.cpp
@@ -27,7 +27,8 @@
using namespace android::uirenderer;
const LayerUpdateQueue sEmptyLayerUpdateQueue;
-const Vector3 sLightCenter = {100, 100, 100};
+const FrameBuilder::LightGeometry sLightGeometery = { {100, 100, 100}, 50};
+const BakedOpRenderer::LightInfo sLightInfo = { 128, 128 };
RENDERTHREAD_TEST(LeakCheck, saveLayerUnclipped_simple) {
auto node = TestUtils::createNode(0, 0, 200, 200,
@@ -36,12 +37,11 @@
canvas.drawRect(0, 0, 200, 200, SkPaint());
canvas.restore();
});
- BakedOpRenderer::LightInfo lightInfo = {50.0f, 128, 128};
RenderState& renderState = renderThread.renderState();
Caches& caches = Caches::getInstance();
FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
- TestUtils::createSyncedNodeList(node), sLightCenter);
- BakedOpRenderer renderer(caches, renderState, true, lightInfo);
+ TestUtils::createSyncedNodeList(node), sLightGeometery, nullptr);
+ BakedOpRenderer renderer(caches, renderState, true, sLightInfo);
frameBuilder.replayBakedOps<BakedOpDispatcher>(renderer);
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
index d3a35d9..c64953d 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
@@ -92,7 +92,6 @@
mList = (ListView) view.findViewById(android.R.id.list);
mList.setOnItemClickListener(mItemListener);
mList.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
-
return view;
}
@@ -161,6 +160,7 @@
final RootInfo testRoot = ((RootItem) item).root;
if (Objects.equals(testRoot, root)) {
mList.setItemChecked(i, true);
+ mList.setSelection(i);
return;
}
}
diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java
index d0cd536..81607a9 100644
--- a/services/core/java/com/android/server/LockSettingsService.java
+++ b/services/core/java/com/android/server/LockSettingsService.java
@@ -200,7 +200,7 @@
PendingIntent.FLAG_UPDATE_CURRENT);
Notification notification = new Notification.Builder(mContext)
- .setSmallIcon(com.android.internal.R.drawable.ic_secure)
+ .setSmallIcon(com.android.internal.R.drawable.ic_user_secure)
.setWhen(0)
.setOngoing(true)
.setTicker(title)
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 0f614ca..5f46567 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -930,6 +930,9 @@
/** @return a specific user restriction that's in effect currently. */
@Override
public boolean hasUserRestriction(String restrictionKey, int userId) {
+ if (!UserRestrictionsUtils.isValidRestriction(restrictionKey)) {
+ return false;
+ }
Bundle restrictions = getEffectiveUserRestrictions(userId);
return restrictions != null && restrictions.getBoolean(restrictionKey);
}
@@ -946,6 +949,9 @@
@Override
public boolean hasBaseUserRestriction(String restrictionKey, int userId) {
checkManageUsersPermission("hasBaseUserRestriction");
+ if (!UserRestrictionsUtils.isValidRestriction(restrictionKey)) {
+ return false;
+ }
synchronized (mRestrictionsLock) {
Bundle bundle = mBaseUserRestrictions.get(userId);
return (bundle != null && bundle.getBoolean(restrictionKey, false));
@@ -955,6 +961,9 @@
@Override
public void setUserRestriction(String key, boolean value, int userId) {
checkManageUsersPermission("setUserRestriction");
+ if (!UserRestrictionsUtils.isValidRestriction(key)) {
+ return;
+ }
synchronized (mRestrictionsLock) {
// Note we can't modify Bundles stored in mBaseUserRestrictions directly, so create
// a copy.
diff --git a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
index f11872e..f57f75f 100644
--- a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
+++ b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
@@ -36,6 +36,7 @@
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.util.Log;
+import android.util.Slog;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlSerializer;
@@ -56,7 +57,15 @@
private UserRestrictionsUtils() {
}
- public static final Set<String> USER_RESTRICTIONS = Sets.newArraySet(
+ private static Set<String> newSetWithUniqueCheck(String[] strings) {
+ final Set<String> ret = Sets.newArraySet(strings);
+
+ // Make sure there's no overlap.
+ Preconditions.checkState(ret.size() == strings.length);
+ return ret;
+ }
+
+ public static final Set<String> USER_RESTRICTIONS = newSetWithUniqueCheck(new String[] {
UserManager.DISALLOW_CONFIG_WIFI,
UserManager.DISALLOW_MODIFY_ACCOUNTS,
UserManager.DISALLOW_INSTALL_APPS,
@@ -95,7 +104,7 @@
UserManager.DISALLOW_DATA_ROAMING,
UserManager.DISALLOW_SET_USER_ICON,
UserManager.DISALLOW_SET_WALLPAPER
- );
+ });
/**
* Set of user restriction which we don't want to persist.
@@ -141,6 +150,17 @@
UserManager.DISALLOW_UNMUTE_MICROPHONE
);
+ /**
+ * Throws {@link IllegalArgumentException} if the given restriction name is invalid.
+ */
+ public static boolean isValidRestriction(@NonNull String restriction) {
+ if (!USER_RESTRICTIONS.contains(restriction)) {
+ Slog.wtf(TAG, "Unknown restriction: " + restriction);
+ return false;
+ }
+ return true;
+ }
+
public static void writeRestrictions(@NonNull XmlSerializer serializer,
@Nullable Bundle restrictions, @NonNull String tag) throws IOException {
if (restrictions == null) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index cfe147e..39c21f1 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -3656,7 +3656,7 @@
if (!(isProfileOwner(adminComponent, userHandle)
|| isDeviceOwner(adminComponent, userHandle))) {
final boolean preN = getTargetSdk(admin.info.getPackageName(), userHandle)
- < android.os.Build.VERSION_CODES.N;
+ <= android.os.Build.VERSION_CODES.M;
// As of N, password resetting to empty/null is not allowed anymore.
// TODO Should we allow DO/PO to set an empty password?
if (TextUtils.isEmpty(password)) {
@@ -6867,6 +6867,10 @@
@Override
public void setUserRestriction(ComponentName who, String key, boolean enabledFromThisOwner) {
Preconditions.checkNotNull(who, "ComponentName is null");
+ if (!UserRestrictionsUtils.isValidRestriction(key)) {
+ return;
+ }
+
final int userHandle = mInjector.userHandleGetCallingUserId();
synchronized (this) {
ActiveAdmin activeAdmin =