diff options
Diffstat (limited to 'libs')
| -rw-r--r-- | libs/androidfw/ApkAssets.cpp | 5 | ||||
| -rw-r--r-- | libs/androidfw/Idmap.cpp | 20 | ||||
| -rw-r--r-- | libs/androidfw/include/androidfw/Idmap.h | 18 | ||||
| -rw-r--r-- | libs/androidfw/tests/Idmap_test.cpp | 30 | ||||
| -rw-r--r-- | libs/hwui/Android.bp | 9 | ||||
| -rw-r--r-- | libs/hwui/apex/android_bitmap.cpp | 5 | ||||
| -rw-r--r-- | libs/hwui/jni/AnimatedImageDrawable.cpp | 2 | ||||
| -rw-r--r-- | libs/hwui/jni/ByteBufferStreamAdaptor.cpp | 20 | ||||
| -rw-r--r-- | libs/hwui/jni/CreateJavaOutputStreamAdaptor.cpp | 4 | ||||
| -rw-r--r-- | libs/hwui/jni/Utils.cpp | 10 | ||||
| -rw-r--r-- | libs/hwui/jni/Utils.h | 10 | ||||
| -rw-r--r-- | libs/hwui/pipeline/skia/SkiaPipeline.cpp | 2 | ||||
| -rw-r--r-- | libs/hwui/tests/unit/ABitmapTests.cpp | 46 | ||||
| -rw-r--r-- | libs/hwui/tests/unit/SkiaPipelineTests.cpp | 37 | 
14 files changed, 177 insertions, 41 deletions
diff --git a/libs/androidfw/ApkAssets.cpp b/libs/androidfw/ApkAssets.cpp index 918e7af12d31..05f4d6b63a4c 100644 --- a/libs/androidfw/ApkAssets.cpp +++ b/libs/androidfw/ApkAssets.cpp @@ -385,7 +385,7 @@ std::unique_ptr<const ApkAssets> ApkAssets::LoadOverlay(const std::string& idmap    const StringPiece idmap_data(        reinterpret_cast<const char*>(idmap_asset->getBuffer(true /*wordAligned*/)),        static_cast<size_t>(idmap_asset->getLength())); -  std::unique_ptr<const LoadedIdmap> loaded_idmap = LoadedIdmap::Load(idmap_data); +  std::unique_ptr<const LoadedIdmap> loaded_idmap = LoadedIdmap::Load(idmap_path, idmap_data);    if (loaded_idmap == nullptr) {      LOG(ERROR) << "failed to load IDMAP " << idmap_path;      return {}; @@ -538,8 +538,9 @@ bool ApkAssets::IsUpToDate() const {      // Loaders are invalidated by the app, not the system, so assume they are up to date.      return true;    } +  return (!loaded_idmap_ || loaded_idmap_->IsUpToDate()) && +      last_mod_time_ == getFileModDate(path_.c_str()); -  return last_mod_time_ == getFileModDate(path_.c_str());  }  }  // namespace android diff --git a/libs/androidfw/Idmap.cpp b/libs/androidfw/Idmap.cpp index 0b2fd9ec982d..eb6ee9525bb9 100644 --- a/libs/androidfw/Idmap.cpp +++ b/libs/androidfw/Idmap.cpp @@ -20,6 +20,7 @@  #include "android-base/logging.h"  #include "android-base/stringprintf.h" +#include "androidfw/misc.h"  #include "androidfw/ResourceTypes.h"  #include "androidfw/Util.h"  #include "utils/ByteOrder.h" @@ -192,7 +193,9 @@ static bool IsValidIdmapHeader(const StringPiece& data) {    return true;  } -LoadedIdmap::LoadedIdmap(const Idmap_header* header, +LoadedIdmap::LoadedIdmap(std::string&& idmap_path, +                         const time_t last_mod_time, +                         const Idmap_header* header,                           const Idmap_data_header* data_header,                           const Idmap_target_entry* target_entries,                           const Idmap_overlay_entry* overlay_entries, @@ -201,7 +204,9 @@ LoadedIdmap::LoadedIdmap(const Idmap_header* header,         data_header_(data_header),         target_entries_(target_entries),         overlay_entries_(overlay_entries), -       string_pool_(string_pool) { +       string_pool_(string_pool), +       idmap_path_(std::move(idmap_path)), +       idmap_last_mod_time_(last_mod_time) {    size_t length = strnlen(reinterpret_cast<const char*>(header_->overlay_path),                            arraysize(header_->overlay_path)); @@ -212,7 +217,8 @@ LoadedIdmap::LoadedIdmap(const Idmap_header* header,    target_apk_path_.assign(reinterpret_cast<const char*>(header_->target_path), length);  } -std::unique_ptr<const LoadedIdmap> LoadedIdmap::Load(const StringPiece& idmap_data) { +std::unique_ptr<const LoadedIdmap> LoadedIdmap::Load(const StringPiece& idmap_path, +                                                     const StringPiece& idmap_data) {    ATRACE_CALL();    if (!IsValidIdmapHeader(idmap_data)) {      return {}; @@ -275,10 +281,14 @@ std::unique_ptr<const LoadedIdmap> LoadedIdmap::Load(const StringPiece& idmap_da    // Can't use make_unique because LoadedIdmap constructor is private.    std::unique_ptr<LoadedIdmap> loaded_idmap = std::unique_ptr<LoadedIdmap>( -      new LoadedIdmap(header, data_header, target_entries, overlay_entries, -                      idmap_string_pool.release())); +      new LoadedIdmap(idmap_path.to_string(), getFileModDate(idmap_path.data()), header, +                      data_header, target_entries, overlay_entries, idmap_string_pool.release()));    return std::move(loaded_idmap);  } +bool LoadedIdmap::IsUpToDate() const { +  return idmap_last_mod_time_ == getFileModDate(idmap_path_.c_str()); +} +  }  // namespace android diff --git a/libs/androidfw/include/androidfw/Idmap.h b/libs/androidfw/include/androidfw/Idmap.h index ccb57f373473..ecc1ce65d124 100644 --- a/libs/androidfw/include/androidfw/Idmap.h +++ b/libs/androidfw/include/androidfw/Idmap.h @@ -142,7 +142,13 @@ class IdmapResMap {  class LoadedIdmap {   public:    // Loads an IDMAP from a chunk of memory. Returns nullptr if the IDMAP data was malformed. -  static std::unique_ptr<const LoadedIdmap> Load(const StringPiece& idmap_data); +  static std::unique_ptr<const LoadedIdmap> Load(const StringPiece& idmap_path, +                                                 const StringPiece& idmap_data); + +  // Returns the path to the IDMAP. +  inline const std::string& IdmapPath() const { +    return idmap_path_; +  }    // Returns the path to the RRO (Runtime Resource Overlay) APK for which this IDMAP was generated.    inline const std::string& OverlayApkPath() const { @@ -167,6 +173,10 @@ class LoadedIdmap {      return OverlayDynamicRefTable(data_header_, overlay_entries_, target_assigned_package_id);    } +  // Returns whether the idmap file on disk has not been modified since the construction of this +  // LoadedIdmap. +  bool IsUpToDate() const; +   protected:    // Exposed as protected so that tests can subclass and mock this class out.    LoadedIdmap() = default; @@ -177,13 +187,17 @@ class LoadedIdmap {    const Idmap_overlay_entry* overlay_entries_;    const std::unique_ptr<ResStringPool> string_pool_; +  const std::string idmap_path_;    std::string overlay_apk_path_;    std::string target_apk_path_; +  const time_t idmap_last_mod_time_;   private:    DISALLOW_COPY_AND_ASSIGN(LoadedIdmap); -  explicit LoadedIdmap(const Idmap_header* header, +  explicit LoadedIdmap(std::string&& idmap_path, +                       time_t last_mod_time, +                       const Idmap_header* header,                         const Idmap_data_header* data_header,                         const Idmap_target_entry* target_entries,                         const Idmap_overlay_entry* overlay_entries, diff --git a/libs/androidfw/tests/Idmap_test.cpp b/libs/androidfw/tests/Idmap_test.cpp index 41ba637da5d7..7aa0dbbafab3 100644 --- a/libs/androidfw/tests/Idmap_test.cpp +++ b/libs/androidfw/tests/Idmap_test.cpp @@ -38,7 +38,7 @@ class IdmapTest : public ::testing::Test {   protected:    void SetUp() override {      // Move to the test data directory so the idmap can locate the overlay APK. -    std::string original_path = base::GetExecutableDirectory(); +    original_path = base::GetExecutableDirectory();      chdir(GetTestDataPath().c_str());      system_assets_ = ApkAssets::Load("system/system.apk"); @@ -49,10 +49,14 @@ class IdmapTest : public ::testing::Test {      overlayable_assets_ = ApkAssets::Load("overlayable/overlayable.apk");      ASSERT_NE(nullptr, overlayable_assets_); +  } + +  void TearDown() override {      chdir(original_path.c_str());    }   protected: +  std::string original_path;    std::unique_ptr<const ApkAssets> system_assets_;    std::unique_ptr<const ApkAssets> overlay_assets_;    std::unique_ptr<const ApkAssets> overlayable_assets_; @@ -221,8 +225,7 @@ TEST_F(IdmapTest, OverlaidResourceHasSameName) {  TEST_F(IdmapTest, OverlayLoaderInterop) {    std::string contents; -  auto loader_assets = ApkAssets::LoadTable(GetTestDataPath() + "/loader/resources.arsc", -                                            PROPERTY_LOADER); +  auto loader_assets = ApkAssets::LoadTable("loader/resources.arsc", PROPERTY_LOADER);    AssetManager2 asset_manager;    asset_manager.SetApkAssets({overlayable_assets_.get(), loader_assets.get(), @@ -241,4 +244,25 @@ TEST_F(IdmapTest, OverlayLoaderInterop) {    ASSERT_EQ(GetStringFromApkAssets(asset_manager, val, cookie), "loader");  } +TEST_F(IdmapTest, OverlayAssetsIsUpToDate) { +  std::string idmap_contents; +  ASSERT_TRUE(base::ReadFileToString("overlay/overlay.idmap", &idmap_contents)); + +  TemporaryFile temp_file; +  ASSERT_TRUE(base::WriteStringToFile(idmap_contents, temp_file.path)); + +  auto apk_assets = ApkAssets::LoadOverlay(temp_file.path); +  ASSERT_NE(nullptr, apk_assets); +  ASSERT_TRUE(apk_assets->IsUpToDate()); + +  unlink(temp_file.path); +  ASSERT_FALSE(apk_assets->IsUpToDate()); +  sleep(2); + +  base::WriteStringToFile("hello", temp_file.path); +  sleep(2); + +  ASSERT_FALSE(apk_assets->IsUpToDate()); +} +  }  // namespace diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp index ac2fd98248d0..aa842ff6a7b7 100644 --- a/libs/hwui/Android.bp +++ b/libs/hwui/Android.bp @@ -171,7 +171,6 @@ cc_library_headers {  cc_defaults {      name: "android_graphics_apex", -    host_supported: true,      cflags: [          "-Wno-unused-parameter",          "-Wno-non-virtual-dtor", @@ -231,7 +230,6 @@ cc_library_headers {  cc_defaults {      name: "android_graphics_jni", -    host_supported: true,      cflags: [          "-Wno-unused-parameter",          "-Wno-non-virtual-dtor", @@ -537,7 +535,11 @@ cc_defaults {  cc_test {      name: "hwui_unit_tests", -    defaults: ["hwui_test_defaults"], +    defaults: [ +        "hwui_test_defaults", +        "android_graphics_apex", +        "android_graphics_jni", +    ],      static_libs: [          "libgmock", @@ -549,6 +551,7 @@ cc_test {      srcs: [          "tests/unit/main.cpp", +        "tests/unit/ABitmapTests.cpp",          "tests/unit/CacheManagerTests.cpp",          "tests/unit/CanvasContextTests.cpp",          "tests/unit/CommonPoolTests.cpp", diff --git a/libs/hwui/apex/android_bitmap.cpp b/libs/hwui/apex/android_bitmap.cpp index b56a619b00aa..3780ba072308 100644 --- a/libs/hwui/apex/android_bitmap.cpp +++ b/libs/hwui/apex/android_bitmap.cpp @@ -163,10 +163,9 @@ jobject ABitmapConfig_getConfigFromFormat(JNIEnv* env, AndroidBitmapFormat forma  void ABitmap_notifyPixelsChanged(ABitmap* bitmapHandle) {      Bitmap* bitmap = TypeCast::toBitmap(bitmapHandle); -    if (bitmap->isImmutable()) { -        ALOGE("Attempting to modify an immutable Bitmap!"); +    if (!bitmap->isImmutable()) { +        bitmap->notifyPixelsChanged();      } -    return bitmap->notifyPixelsChanged();  }  namespace { diff --git a/libs/hwui/jni/AnimatedImageDrawable.cpp b/libs/hwui/jni/AnimatedImageDrawable.cpp index 055075d0c42a..1ff156593c41 100644 --- a/libs/hwui/jni/AnimatedImageDrawable.cpp +++ b/libs/hwui/jni/AnimatedImageDrawable.cpp @@ -183,7 +183,7 @@ public:      }      ~InvokeListener() override { -        auto* env = get_env_or_die(mJvm); +        auto* env = requireEnv(mJvm);          env->DeleteWeakGlobalRef(mWeakRef);      } diff --git a/libs/hwui/jni/ByteBufferStreamAdaptor.cpp b/libs/hwui/jni/ByteBufferStreamAdaptor.cpp index db5f6f6c684f..b10540cb3fbd 100644 --- a/libs/hwui/jni/ByteBufferStreamAdaptor.cpp +++ b/libs/hwui/jni/ByteBufferStreamAdaptor.cpp @@ -9,24 +9,6 @@ using namespace android;  static jmethodID gByteBuffer_getMethodID;  static jmethodID gByteBuffer_setPositionMethodID; -/** - * Helper method for accessing the JNI interface pointer. - * - * Image decoding (which this supports) is started on a thread that is already - * attached to the Java VM. But an AnimatedImageDrawable continues decoding on - * the AnimatedImageThread, which is not attached. This will attach if - * necessary. - */ -static JNIEnv* requireEnv(JavaVM* jvm) { -    JNIEnv* env; -    if (jvm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) { -        if (jvm->AttachCurrentThreadAsDaemon(&env, nullptr) != JNI_OK) { -            LOG_ALWAYS_FATAL("Failed to AttachCurrentThread!"); -        } -    } -    return env; -} -  class ByteBufferStream : public SkStreamAsset {  private:      ByteBufferStream(JavaVM* jvm, jobject jbyteBuffer, size_t initialPosition, size_t length, @@ -304,7 +286,7 @@ std::unique_ptr<SkStream> CreateByteBufferStreamAdaptor(JNIEnv* env, jobject jby          auto* context = new release_proc_context{jvm, jbyteBuffer};          auto releaseProc = [](const void*, void* context) {              auto* c = reinterpret_cast<release_proc_context*>(context); -            JNIEnv* env = get_env_or_die(c->jvm); +            JNIEnv* env = requireEnv(c->jvm);              env->DeleteGlobalRef(c->jbyteBuffer);              delete c;          }; diff --git a/libs/hwui/jni/CreateJavaOutputStreamAdaptor.cpp b/libs/hwui/jni/CreateJavaOutputStreamAdaptor.cpp index 39483b55992b..f1c6b29204b2 100644 --- a/libs/hwui/jni/CreateJavaOutputStreamAdaptor.cpp +++ b/libs/hwui/jni/CreateJavaOutputStreamAdaptor.cpp @@ -49,13 +49,13 @@ public:      }      ~JavaInputStreamAdaptor() override { -        auto* env = android::get_env_or_die(fJvm); +        auto* env = android::requireEnv(fJvm);          env->DeleteGlobalRef(fJavaInputStream);          env->DeleteGlobalRef(fJavaByteArray);      }      size_t read(void* buffer, size_t size) override { -        auto* env = android::get_env_or_die(fJvm); +        auto* env = android::requireEnv(fJvm);          if (!fSwallowExceptions && checkException(env)) {              // Just in case the caller did not clear from a previous exception.              return 0; diff --git a/libs/hwui/jni/Utils.cpp b/libs/hwui/jni/Utils.cpp index 17c194d04f84..34fd6687d52c 100644 --- a/libs/hwui/jni/Utils.cpp +++ b/libs/hwui/jni/Utils.cpp @@ -159,3 +159,13 @@ JNIEnv* android::get_env_or_die(JavaVM* jvm) {      }      return env;  } + +JNIEnv* android::requireEnv(JavaVM* jvm) { +    JNIEnv* env; +    if (jvm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) { +        if (jvm->AttachCurrentThreadAsDaemon(&env, nullptr) != JNI_OK) { +            LOG_ALWAYS_FATAL("Failed to AttachCurrentThread!"); +        } +    } +    return env; +} diff --git a/libs/hwui/jni/Utils.h b/libs/hwui/jni/Utils.h index 89255177ba2e..f628cc3c85ed 100644 --- a/libs/hwui/jni/Utils.h +++ b/libs/hwui/jni/Utils.h @@ -78,6 +78,16 @@ bool isSeekable(int descriptor);  JNIEnv* get_env_or_die(JavaVM* jvm); +/** + * Helper method for accessing the JNI interface pointer. + * + * Image decoding (which this supports) is started on a thread that is already + * attached to the Java VM. But an AnimatedImageDrawable continues decoding on + * the AnimatedImageThread, which is not attached. This will attach if + * necessary. + */ +JNIEnv* requireEnv(JavaVM* jvm); +  }; // namespace android  #endif  // _ANDROID_GRAPHICS_UTILS_H_ diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.cpp b/libs/hwui/pipeline/skia/SkiaPipeline.cpp index 41aa1ff80e3c..5088494d6a07 100644 --- a/libs/hwui/pipeline/skia/SkiaPipeline.cpp +++ b/libs/hwui/pipeline/skia/SkiaPipeline.cpp @@ -418,9 +418,9 @@ void SkiaPipeline::endCapture(SkSurface* surface) {                  auto data = picture->serialize();                  savePictureAsync(data, mCapturedFile);                  mCaptureSequence = 0; +                mCaptureMode = CaptureMode::None;              }          } -        mCaptureMode = CaptureMode::None;          mRecorder.reset();      }  } diff --git a/libs/hwui/tests/unit/ABitmapTests.cpp b/libs/hwui/tests/unit/ABitmapTests.cpp new file mode 100644 index 000000000000..8e2f7e09d406 --- /dev/null +++ b/libs/hwui/tests/unit/ABitmapTests.cpp @@ -0,0 +1,46 @@ +/* + * Copyright 2020 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 "android/graphics/bitmap.h" +#include "apex/TypeCast.h" +#include "hwui/Bitmap.h" +#include "tests/common/TestUtils.h" + +using namespace android; +using namespace android::uirenderer; + +TEST(ABitmap, notifyPixelsChanged) { +    // generate a bitmap and its public API handle +    sk_sp<Bitmap> bitmap(TestUtils::createBitmap(1, 1)); +    ABitmap* abmp = android::TypeCast::toABitmap(bitmap.get()); + +    // verify that notification changes the genID +    uint32_t genID = bitmap->getGenerationID(); +    ABitmap_notifyPixelsChanged(abmp); +    ASSERT_TRUE(bitmap->getGenerationID() != genID); + +    // mark the bitmap as immutable +    ASSERT_FALSE(bitmap->isImmutable()); +    bitmap->setImmutable(); +    ASSERT_TRUE(bitmap->isImmutable()); + +    // attempt to notify that the pixels have changed +    genID = bitmap->getGenerationID(); +    ABitmap_notifyPixelsChanged(abmp); +    ASSERT_TRUE(bitmap->getGenerationID() == genID); +} diff --git a/libs/hwui/tests/unit/SkiaPipelineTests.cpp b/libs/hwui/tests/unit/SkiaPipelineTests.cpp index 90bcd1c0e370..1208062d9da0 100644 --- a/libs/hwui/tests/unit/SkiaPipelineTests.cpp +++ b/libs/hwui/tests/unit/SkiaPipelineTests.cpp @@ -403,3 +403,40 @@ RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, context_lost) {      renderThread.destroyRenderingContext();      EXPECT_FALSE(pipeline->isSurfaceReady());  } + +RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, pictureCallback) { +    // create a pipeline and add a picture callback +    auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread); +    int callbackCount = 0; +    pipeline->setPictureCapturedCallback( +            [&callbackCount](sk_sp<SkPicture>&& picture) { callbackCount += 1; }); + +    // create basic red frame and render it +    auto redNode = TestUtils::createSkiaNode( +            0, 0, 1, 1, [](RenderProperties& props, SkiaRecordingCanvas& redCanvas) { +                redCanvas.drawColor(SK_ColorRED, SkBlendMode::kSrcOver); +            }); +    LayerUpdateQueue layerUpdateQueue; +    SkRect dirty = SkRectMakeLargest(); +    std::vector<sp<RenderNode>> renderNodes; +    renderNodes.push_back(redNode); +    bool opaque = true; +    android::uirenderer::Rect contentDrawBounds(0, 0, 1, 1); +    auto surface = SkSurface::MakeRasterN32Premul(1, 1); +    pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface, +                          SkMatrix::I()); + +    // verify the callback was called +    EXPECT_EQ(1, callbackCount); + +    // render a second frame and check the callback count +    pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface, +                          SkMatrix::I()); +    EXPECT_EQ(2, callbackCount); + +    // unset the callback, render another frame, check callback was not invoked +    pipeline->setPictureCapturedCallback(nullptr); +    pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface, +                          SkMatrix::I()); +    EXPECT_EQ(2, callbackCount); +}  |