Merge "Add netd and connmetrics into telephony dump"
diff --git a/cmds/installd/Android.bp b/cmds/installd/Android.bp
index c5a8f49..4619427 100644
--- a/cmds/installd/Android.bp
+++ b/cmds/installd/Android.bp
@@ -145,9 +145,11 @@
     ],
     shared_libs: [
         "libbase",
+        "libbinder",
         "liblog",
         "libprotobuf-cpp-full",
         "libselinux",
+        "libutils",
         "libziparchive",
     ],
     static_libs: [
@@ -156,6 +158,7 @@
         "lib_apex_manifest_proto",
         "libavb",
         "libdm",
+        "libvold_binder",
     ],
 }
 
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 72571cf..20142aa 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -58,6 +58,7 @@
 using android::base::EndsWith;
 using android::base::GetBoolProperty;
 using android::base::GetProperty;
+using android::base::ReadFdToString;
 using android::base::ReadFully;
 using android::base::StringPrintf;
 using android::base::WriteFully;
@@ -319,6 +320,7 @@
                bool background_job_compile,
                int profile_fd,
                const char* class_loader_context,
+               const std::string& class_loader_context_fds,
                int target_sdk_version,
                bool enable_hidden_api_checks,
                bool generate_compact_dex,
@@ -423,9 +425,14 @@
             target_sdk_version_arg = StringPrintf("-Xtarget-sdk-version:%d", target_sdk_version);
         }
         std::string class_loader_context_arg;
+        std::string class_loader_context_fds_arg;
         if (class_loader_context != nullptr) {
             class_loader_context_arg = StringPrintf("--class-loader-context=%s",
                                                     class_loader_context);
+            if (!class_loader_context_fds.empty()) {
+                class_loader_context_fds_arg = StringPrintf("--class-loader-context-fds=%s",
+                                                            class_loader_context_fds.c_str());
+            }
         }
 
         if (swap_fd >= 0) {
@@ -518,6 +525,7 @@
         AddArg(profile_arg);
         AddArg(base_dir);
         AddArg(class_loader_context_arg);
+        AddArg(class_loader_context_fds_arg);
         if (generate_minidebug_info) {
             AddArg(kMinidebugDex2oatFlag);
         }
@@ -1514,14 +1522,15 @@
 class RunDexoptAnalyzer : public ExecVHelper {
  public:
     RunDexoptAnalyzer(const std::string& dex_file,
-                    int vdex_fd,
-                    int oat_fd,
-                    int zip_fd,
-                    const std::string& instruction_set,
-                    const std::string& compiler_filter,
-                    bool profile_was_updated,
-                    bool downgrade,
-                    const char* class_loader_context) {
+                      int vdex_fd,
+                      int oat_fd,
+                      int zip_fd,
+                      const std::string& instruction_set,
+                      const std::string& compiler_filter,
+                      bool profile_was_updated,
+                      bool downgrade,
+                      const char* class_loader_context,
+                      const std::string& class_loader_context_fds) {
         CHECK_GE(zip_fd, 0);
 
         // We always run the analyzer in the background job.
@@ -1540,6 +1549,10 @@
         if (class_loader_context != nullptr) {
             class_loader_context_arg += class_loader_context;
         }
+        std::string class_loader_context_fds_arg = "--class-loader-context-fds=";
+        if (!class_loader_context_fds.empty()) {
+            class_loader_context_fds_arg += class_loader_context_fds;
+        }
 
         // program name, dex file, isa, filter
         AddArg(dex_file_arg);
@@ -1560,10 +1573,27 @@
         }
         if (class_loader_context != nullptr) {
             AddArg(class_loader_context_arg.c_str());
+            if (!class_loader_context_fds.empty()) {
+                AddArg(class_loader_context_fds_arg.c_str());
+            }
         }
 
         PrepareArgs(dexoptanalyzer_bin);
     }
+
+    // Dexoptanalyzer mode which flattens the given class loader context and
+    // prints a list of its dex files in that flattened order.
+    RunDexoptAnalyzer(const char* class_loader_context) {
+        CHECK(class_loader_context != nullptr);
+
+        // We always run the analyzer in the background job.
+        const char* dexoptanalyzer_bin = select_execution_binary(
+             kDexoptanalyzerPath, kDexoptanalyzerDebugPath, /*background_job_compile=*/ true);
+
+        AddArg("--flatten-class-loader-context");
+        AddArg(std::string("--class-loader-context=") + class_loader_context);
+        PrepareArgs(dexoptanalyzer_bin);
+    }
 };
 
 // Prepares the oat dir for the secondary dex files.
@@ -1743,6 +1773,95 @@
     return true;
 }
 
+static bool get_class_loader_context_dex_paths(const char* class_loader_context, int uid,
+        /* out */ std::vector<std::string>* context_dex_paths) {
+    if (class_loader_context == nullptr) {
+      return true;
+    }
+
+    LOG(DEBUG) << "Getting dex paths for context " << class_loader_context;
+
+    // Pipe to get the hash result back from our child process.
+    unique_fd pipe_read, pipe_write;
+    if (!Pipe(&pipe_read, &pipe_write)) {
+        PLOG(ERROR) << "Failed to create pipe";
+        return false;
+    }
+
+    pid_t pid = fork();
+    if (pid == 0) {
+        // child -- drop privileges before continuing.
+        drop_capabilities(uid);
+
+        // Route stdout to `pipe_write`
+        while ((dup2(pipe_write, STDOUT_FILENO) == -1) && (errno == EINTR)) {}
+        pipe_write.reset();
+        pipe_read.reset();
+
+        RunDexoptAnalyzer run_dexopt_analyzer(class_loader_context);
+        run_dexopt_analyzer.Exec(kSecondaryDexDexoptAnalyzerSkippedFailExec);
+    }
+
+    /* parent */
+    pipe_write.reset();
+
+    std::string str_dex_paths;
+    if (!ReadFdToString(pipe_read, &str_dex_paths)) {
+        PLOG(ERROR) << "Failed to read from pipe";
+        return false;
+    }
+    pipe_read.reset();
+
+    int return_code = wait_child(pid);
+    if (!WIFEXITED(return_code)) {
+        PLOG(ERROR) << "Error waiting for child dexoptanalyzer process";
+        return false;
+    }
+
+    constexpr int kFlattenClassLoaderContextSuccess = 50;
+    return_code = WEXITSTATUS(return_code);
+    if (return_code != kFlattenClassLoaderContextSuccess) {
+        LOG(ERROR) << "Dexoptanalyzer could not flatten class loader context, code=" << return_code;
+        return false;
+    }
+
+    if (!str_dex_paths.empty()) {
+        *context_dex_paths = android::base::Split(str_dex_paths, ":");
+    }
+    return true;
+}
+
+static int open_dex_paths(const std::vector<std::string>& dex_paths,
+        /* out */ std::vector<unique_fd>* zip_fds, /* out */ std::string* error_msg) {
+    for (const std::string& dex_path : dex_paths) {
+        zip_fds->emplace_back(open(dex_path.c_str(), O_RDONLY));
+        if (zip_fds->back().get() < 0) {
+            *error_msg = StringPrintf(
+                    "installd cannot open '%s' for input during dexopt", dex_path.c_str());
+            if (errno == ENOENT) {
+                return kSecondaryDexDexoptAnalyzerSkippedNoFile;
+            } else {
+                return kSecondaryDexDexoptAnalyzerSkippedOpenZip;
+            }
+        }
+    }
+    return 0;
+}
+
+static std::string join_fds(const std::vector<unique_fd>& fds) {
+    std::stringstream ss;
+    bool is_first = true;
+    for (const unique_fd& fd : fds) {
+        if (is_first) {
+            is_first = false;
+        } else {
+            ss << ":";
+        }
+        ss << fd.get();
+    }
+    return ss.str();
+}
+
 // Processes the dex_path as a secondary dex files and return true if the path dex file should
 // be compiled. Returns false for errors (logged) or true if the secondary dex path was process
 // successfully.
@@ -1754,7 +1873,7 @@
         int dexopt_flags, const char* volume_uuid, int uid, const char* instruction_set,
         const char* compiler_filter, bool* is_public_out, int* dexopt_needed_out,
         std::string* oat_dir_out, bool downgrade, const char* class_loader_context,
-        /* out */ std::string* error_msg) {
+        const std::vector<std::string>& context_dex_paths, /* out */ std::string* error_msg) {
     LOG(DEBUG) << "Processing secondary dex path " << dex_path;
     int storage_flag;
     if (!validate_dexopt_storage_flags(dexopt_flags, &storage_flag, error_msg)) {
@@ -1794,6 +1913,13 @@
             }
         }
 
+        // Open class loader context dex files.
+        std::vector<unique_fd> context_zip_fds;
+        int open_dex_paths_rc = open_dex_paths(context_dex_paths, &context_zip_fds, error_msg);
+        if (open_dex_paths_rc != 0) {
+            _exit(open_dex_paths_rc);
+        }
+
         // Prepare the oat directories.
         if (!prepare_secondary_dex_oat_dir(dex_path, uid, instruction_set)) {
             _exit(kSecondaryDexDexoptAnalyzerSkippedPrepareDir);
@@ -1825,7 +1951,8 @@
                                               instruction_set,
                                               compiler_filter, profile_was_updated,
                                               downgrade,
-                                              class_loader_context);
+                                              class_loader_context,
+                                              join_fds(context_zip_fds));
         run_dexopt_analyzer.Exec(kSecondaryDexDexoptAnalyzerSkippedFailExec);
     }
 
@@ -1913,10 +2040,16 @@
 
     // Check if we're dealing with a secondary dex file and if we need to compile it.
     std::string oat_dir_str;
+    std::vector<std::string> context_dex_paths;
     if (is_secondary_dex) {
+        if (!get_class_loader_context_dex_paths(class_loader_context, uid, &context_dex_paths)) {
+            *error_msg = "Failed acquiring context dex paths";
+            return -1;  // We had an error, logged in the process method.
+        }
+
         if (process_secondary_dex_dexopt(dex_path, pkgname, dexopt_flags, volume_uuid, uid,
                 instruction_set, compiler_filter, &is_public, &dexopt_needed, &oat_dir_str,
-                downgrade, class_loader_context, error_msg)) {
+                downgrade, class_loader_context, context_dex_paths, error_msg)) {
             oat_dir = oat_dir_str.c_str();
             if (dexopt_needed == NO_DEXOPT_NEEDED) {
                 return 0;  // Nothing to do, report success.
@@ -1928,7 +2061,7 @@
             return -1;  // We had an error, logged in the process method.
         }
     } else {
-        // Currently these flags are only use for secondary dex files.
+        // Currently these flags are only used for secondary dex files.
         // Verify that they are not set for primary apks.
         CHECK((dexopt_flags & DEXOPT_STORAGE_CE) == 0);
         CHECK((dexopt_flags & DEXOPT_STORAGE_DE) == 0);
@@ -1942,6 +2075,13 @@
         return -1;
     }
 
+    // Open class loader context dex files.
+    std::vector<unique_fd> context_input_fds;
+    if (open_dex_paths(context_dex_paths, &context_input_fds, error_msg) != 0) {
+        LOG(ERROR) << *error_msg;
+        return -1;
+    }
+
     // Create the output OAT file.
     char out_oat_path[PKG_PATH_MAX];
     Dex2oatFileWrapper out_oat_fd = open_oat_out_file(dex_path, oat_dir, is_public, uid,
@@ -2010,6 +2150,7 @@
                       background_job_compile,
                       reference_profile_fd.get(),
                       class_loader_context,
+                      join_fds(context_input_fds),
                       target_sdk_version,
                       enable_hidden_api_checks,
                       generate_compact_dex,
diff --git a/cmds/installd/otapreopt_chroot.cpp b/cmds/installd/otapreopt_chroot.cpp
index 0fdc9d6..2e2cc18 100644
--- a/cmds/installd/otapreopt_chroot.cpp
+++ b/cmds/installd/otapreopt_chroot.cpp
@@ -25,6 +25,7 @@
 #include <android-base/logging.h>
 #include <android-base/macros.h>
 #include <android-base/stringprintf.h>
+#include <libdm/dm.h>
 #include <selinux/android.h>
 
 #include <apexd.h>
@@ -77,6 +78,37 @@
     }
 }
 
+static void TryExtraMount(const char* name, const char* slot, const char* target) {
+    std::string partition_name = StringPrintf("%s%s", name, slot);
+
+    // See whether update_engine mounted a logical partition.
+    {
+        auto& dm = dm::DeviceMapper::Instance();
+        if (dm.GetState(partition_name) != dm::DmDeviceState::INVALID) {
+            std::string path;
+            if (dm.GetDmDevicePathByName(partition_name, &path)) {
+                int mount_result = mount(path.c_str(),
+                                         target,
+                                         "ext4",
+                                         MS_RDONLY,
+                                         /* data */ nullptr);
+                if (mount_result == 0) {
+                    return;
+                }
+            }
+        }
+    }
+
+    // Fall back and attempt a direct mount.
+    std::string block_device = StringPrintf("/dev/block/by-name/%s", partition_name.c_str());
+    int mount_result = mount(block_device.c_str(),
+                             target,
+                             "ext4",
+                             MS_RDONLY,
+                             /* data */ nullptr);
+    UNUSED(mount_result);
+}
+
 // Entry for otapreopt_chroot. Expected parameters are:
 //   [cmd] [status-fd] [target-slot] "dexopt" [dexopt-params]
 // The file descriptor denoted by status-fd will be closed. The rest of the parameters will
@@ -137,29 +169,11 @@
         LOG(ERROR) << "Target slot suffix not legal: " << arg[2];
         exit(207);
     }
-    {
-      std::string vendor_partition = StringPrintf("/dev/block/by-name/vendor%s",
-                                                  arg[2]);
-      int vendor_result = mount(vendor_partition.c_str(),
-                                "/postinstall/vendor",
-                                "ext4",
-                                MS_RDONLY,
-                                /* data */ nullptr);
-      UNUSED(vendor_result);
-    }
+    TryExtraMount("vendor", arg[2], "/postinstall/vendor");
 
     // Try to mount the product partition. update_engine doesn't do this for us, but we
     // want it for product APKs. Same notes as vendor above.
-    {
-      std::string product_partition = StringPrintf("/dev/block/by-name/product%s",
-                                                   arg[2]);
-      int product_result = mount(product_partition.c_str(),
-                                 "/postinstall/product",
-                                 "ext4",
-                                 MS_RDONLY,
-                                 /* data */ nullptr);
-      UNUSED(product_result);
-    }
+    TryExtraMount("product", arg[2], "/postinstall/product");
 
     // Setup APEX mount point and its security context.
     static constexpr const char* kPostinstallApexDir = "/postinstall/apex";
diff --git a/cmds/installd/tests/installd_dexopt_test.cpp b/cmds/installd/tests/installd_dexopt_test.cpp
index 71b710b..36d5a60 100644
--- a/cmds/installd/tests/installd_dexopt_test.cpp
+++ b/cmds/installd/tests/installd_dexopt_test.cpp
@@ -327,16 +327,21 @@
 
     void CompileSecondaryDex(const std::string& path, int32_t dex_storage_flag,
             bool should_binder_call_succeed, bool should_dex_be_compiled = true,
-            /*out */ binder::Status* binder_result = nullptr, int32_t uid = -1) {
+            /*out */ binder::Status* binder_result = nullptr, int32_t uid = -1,
+            const char* class_loader_context = nullptr) {
         if (uid == -1) {
             uid = kTestAppUid;
         }
+        if (class_loader_context == nullptr) {
+            class_loader_context = "&";
+        }
         std::unique_ptr<std::string> package_name_ptr(new std::string(package_name_));
         int32_t dexopt_needed = 0;  // does not matter;
         std::unique_ptr<std::string> out_path = nullptr;  // does not matter
         int32_t dex_flags = DEXOPT_SECONDARY_DEX | dex_storage_flag;
         std::string compiler_filter = "speed-profile";
-        std::unique_ptr<std::string> class_loader_context_ptr(new std::string("&"));
+        std::unique_ptr<std::string> class_loader_context_ptr(
+                new std::string(class_loader_context));
         std::unique_ptr<std::string> se_info_ptr(new std::string(se_info_));
         bool downgrade = false;
         int32_t target_sdk_version = 0;  // default
@@ -555,12 +560,26 @@
         /*binder_ok*/ true, /*compile_ok*/ true);
 }
 
+TEST_F(DexoptTest, DexoptSecondaryCeWithContext) {
+    LOG(INFO) << "DexoptSecondaryCeWithContext";
+    std::string class_loader_context = "PCL[" + secondary_dex_ce_ + "]";
+    CompileSecondaryDex(secondary_dex_ce_, DEXOPT_STORAGE_CE,
+        /*binder_ok*/ true, /*compile_ok*/ true, nullptr, -1, class_loader_context.c_str());
+}
+
 TEST_F(DexoptTest, DexoptSecondaryDe) {
     LOG(INFO) << "DexoptSecondaryDe";
     CompileSecondaryDex(secondary_dex_de_, DEXOPT_STORAGE_DE,
         /*binder_ok*/ true, /*compile_ok*/ true);
 }
 
+TEST_F(DexoptTest, DexoptSecondaryDeWithContext) {
+    LOG(INFO) << "DexoptSecondaryDeWithContext";
+    std::string class_loader_context = "PCL[" + secondary_dex_de_ + "]";
+    CompileSecondaryDex(secondary_dex_de_, DEXOPT_STORAGE_DE,
+        /*binder_ok*/ true, /*compile_ok*/ true, nullptr, -1, class_loader_context.c_str());
+}
+
 TEST_F(DexoptTest, DexoptSecondaryDoesNotExist) {
     LOG(INFO) << "DexoptSecondaryDoesNotExist";
     // If the file validates but does not exist we do not treat it as an error.
@@ -576,7 +595,7 @@
     CompileSecondaryDex(secondary_dex_ce_, DEXOPT_STORAGE_DE,
         /*binder_ok*/ false,  /*compile_ok*/ false, &status);
     EXPECT_STREQ(status.toString8().c_str(),
-                 "Status(-8): '-1: Dexoptanalyzer path validation failed'");
+                 "Status(-8, EX_SERVICE_SPECIFIC): '-1: Dexoptanalyzer path validation failed'");
 }
 
 TEST_F(DexoptTest, DexoptSecondaryAppOwnershipValidationError) {
@@ -585,7 +604,7 @@
     CompileSecondaryDex("/data/data/random.app/secondary.jar", DEXOPT_STORAGE_CE,
         /*binder_ok*/ false,  /*compile_ok*/ false, &status);
     EXPECT_STREQ(status.toString8().c_str(),
-                 "Status(-8): '-1: Dexoptanalyzer path validation failed'");
+                 "Status(-8, EX_SERVICE_SPECIFIC): '-1: Dexoptanalyzer path validation failed'");
 }
 
 TEST_F(DexoptTest, DexoptSecondaryAcessViaDifferentUidError) {
@@ -593,7 +612,8 @@
     binder::Status status;
     CompileSecondaryDex(secondary_dex_ce_, DEXOPT_STORAGE_CE,
         /*binder_ok*/ false,  /*compile_ok*/ false, &status, kSystemUid);
-    EXPECT_STREQ(status.toString8().c_str(), "Status(-8): '-1: Dexoptanalyzer open zip failed'");
+    EXPECT_STREQ(status.toString8().c_str(),
+                 "Status(-8, EX_SERVICE_SPECIFIC): '-1: Dexoptanalyzer open zip failed'");
 }
 
 TEST_F(DexoptTest, DexoptPrimaryPublic) {
@@ -615,7 +635,7 @@
                           DEX2OAT_FROM_SCRATCH,
                           &status);
     EXPECT_STREQ(status.toString8().c_str(),
-                 "Status(-8): \'256: Dex2oat invocation for "
+                 "Status(-8, EX_SERVICE_SPECIFIC): \'256: Dex2oat invocation for "
                  "/data/app/com.installd.test.dexopt/base.jar failed: unspecified dex2oat error'");
 }
 
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index 99a3a75..5f79804 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -174,8 +174,25 @@
     virtual status_t setActiveColorMode(const sp<IBinder>& display,
             ui::ColorMode colorMode) = 0;
 
-    /* Capture the specified screen. requires READ_FRAME_BUFFER permission
-     * This function will fail if there is a secure window on screen.
+    /**
+     * Capture the specified screen. This requires READ_FRAME_BUFFER
+     * permission.  This function will fail if there is a secure window on
+     * screen.
+     *
+     * This function can capture a subregion (the source crop) of the screen.
+     * The subregion can be optionally rotated.  It will also be scaled to
+     * match the size of the output buffer.
+     *
+     * At the moment, sourceCrop is ignored and is always set to the visible
+     * region (projected display viewport) of the screen.
+     *
+     * reqWidth and reqHeight specifies the size of the buffer.  When either
+     * of them is 0, they are set to the size of the logical display viewport.
+     *
+     * When useIdentityTransform is true, layer transformations are disabled.
+     *
+     * rotation specifies the rotation of the source crop (and the pixels in
+     * it) around its center.
      */
     virtual status_t captureScreen(const sp<IBinder>& display, sp<GraphicBuffer>* outBuffer,
                                    Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index 788962e..38de701 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -152,10 +152,24 @@
     sp<IBinder> token;
     sp<IGraphicBufferProducer> surface;
     uint32_t layerStack;
+
+    // These states define how layers are projected onto the physical display.
+    //
+    // Layers are first clipped to `viewport'.  They are then translated and
+    // scaled from `viewport' to `frame'.  Finally, they are rotated according
+    // to `orientation', `width', and `height'.
+    //
+    // For example, assume viewport is Rect(0, 0, 200, 100), frame is Rect(20,
+    // 10, 420, 210), and the size of the display is WxH.  When orientation is
+    // 0, layers will be scaled by a factor of 2 and translated by (20, 10).
+    // When orientation is 1, layers will be additionally rotated by 90
+    // degrees around the origin clockwise and translated by (W, 0).
     uint32_t orientation;
     Rect viewport;
     Rect frame;
+
     uint32_t width, height;
+
     status_t write(Parcel& output) const;
     status_t read(const Parcel& input);
 };
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index f5b5eda..707cb42 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -204,7 +204,7 @@
 
     if (!blackOutLayer) {
         // TODO: we could be more subtle with isFixedSize()
-        const bool useFiltering = getFiltering() || needsFiltering(renderArea) || isFixedSize();
+        const bool useFiltering = needsFiltering(renderArea) || isFixedSize();
 
         // Query the texture matrix given our current filtering mode.
         float textureMatrix[16];
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 309fd0a..65c3839 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -224,6 +224,7 @@
         std::unique_ptr<RE::Surface> renderSurface,
         int displayWidth,
         int displayHeight,
+        int displayInstallOrientation,
         bool hasWideColorGamut,
         const HdrCapabilities& hdrCapabilities,
         const int32_t supportedPerFrameMetadata,
@@ -239,6 +240,7 @@
       mSurface{std::move(renderSurface)},
       mDisplayWidth(displayWidth),
       mDisplayHeight(displayHeight),
+      mDisplayInstallOrientation(displayInstallOrientation),
       mPageFlipCount(0),
       mIsSecure(isSecure),
       mLayerStack(NO_LAYER_STACK),
@@ -610,9 +612,8 @@
     // need to take care of primary display rotation for mGlobalTransform
     // for case if the panel is not installed aligned with device orientation
     if (mType == DisplayType::DISPLAY_PRIMARY) {
-        int primaryDisplayOrientation = mFlinger->getPrimaryDisplayOrientation();
         DisplayDevice::orientationToTransfrom(
-                (orientation + primaryDisplayOrientation) % (DisplayState::eOrientation270 + 1),
+                (orientation + mDisplayInstallOrientation) % (DisplayState::eOrientation270 + 1),
                 w, h, &R);
     }
 
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index 6c3bd91..3cf06bc 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -25,7 +25,7 @@
 #include <math/mat4.h>
 
 #include <binder/IBinder.h>
-#include <gui/ISurfaceComposer.h>
+#include <gui/LayerState.h>
 #include <hardware/hwcomposer_defs.h>
 #include <ui/GraphicTypes.h>
 #include <ui/HdrCapabilities.h>
@@ -88,6 +88,7 @@
             std::unique_ptr<RE::Surface> renderSurface,
             int displayWidth,
             int displayHeight,
+            int displayInstallOrientation,
             bool hasWideColorGamut,
             const HdrCapabilities& hdrCapabilities,
             const int32_t supportedPerFrameMetadata,
@@ -111,6 +112,7 @@
 
     int         getWidth() const;
     int         getHeight() const;
+    int         getInstallOrientation() const { return mDisplayInstallOrientation; }
 
     void                    setVisibleLayersSortedByZ(const Vector< sp<Layer> >& layers);
     const Vector< sp<Layer> >& getVisibleLayersSortedByZ() const;
@@ -234,6 +236,7 @@
     std::unique_ptr<RE::Surface> mSurface;
     int             mDisplayWidth;
     int             mDisplayHeight;
+    const int       mDisplayInstallOrientation;
     mutable uint32_t mPageFlipCount;
     String8         mDisplayName;
     bool            mIsSecure;
@@ -337,23 +340,108 @@
 class DisplayRenderArea : public RenderArea {
 public:
     DisplayRenderArea(const sp<const DisplayDevice> device,
-                      ISurfaceComposer::Rotation rotation = ISurfaceComposer::eRotateNone)
-          : DisplayRenderArea(device, device->getBounds(), device->getHeight(), device->getWidth(),
+                      Transform::orientation_flags rotation = Transform::ROT_0)
+          : DisplayRenderArea(device, device->getBounds(), device->getWidth(), device->getHeight(),
                               rotation) {}
-    DisplayRenderArea(const sp<const DisplayDevice> device, Rect sourceCrop, uint32_t reqHeight,
-                      uint32_t reqWidth, ISurfaceComposer::Rotation rotation)
-          : RenderArea(reqHeight, reqWidth, CaptureFill::OPAQUE, rotation), mDevice(device),
-                              mSourceCrop(sourceCrop) {}
+    DisplayRenderArea(const sp<const DisplayDevice> device, Rect sourceCrop, uint32_t reqWidth,
+                      uint32_t reqHeight, Transform::orientation_flags rotation)
+          : RenderArea(reqWidth, reqHeight, CaptureFill::OPAQUE,
+                       getDisplayRotation(rotation, device->getInstallOrientation())),
+            mDevice(device),
+            mSourceCrop(sourceCrop) {}
 
     const Transform& getTransform() const override { return mDevice->getTransform(); }
     Rect getBounds() const override { return mDevice->getBounds(); }
     int getHeight() const override { return mDevice->getHeight(); }
     int getWidth() const override { return mDevice->getWidth(); }
     bool isSecure() const override { return mDevice->isSecure(); }
-    bool needsFiltering() const override { return mDevice->needsFiltering(); }
-    Rect getSourceCrop() const override { return mSourceCrop; }
+
+    bool needsFiltering() const override {
+        // check if the projection from the logical display to the physical
+        // display needs filtering
+        if (mDevice->needsFiltering()) {
+            return true;
+        }
+
+        // check if the projection from the logical render area (i.e., the
+        // physical display) to the physical render area requires filtering
+        const Rect sourceCrop = getSourceCrop();
+        int width = sourceCrop.width();
+        int height = sourceCrop.height();
+        if (getRotationFlags() & Transform::ROT_90) {
+            std::swap(width, height);
+        }
+        return width != getReqWidth() || height != getReqHeight();
+    }
+
+    Rect getSourceCrop() const override {
+        // use the (projected) logical display viewport by default
+        if (mSourceCrop.isEmpty()) {
+            return mDevice->getScissor();
+        }
+
+        const int orientation = mDevice->getInstallOrientation();
+        if (orientation == DisplayState::eOrientationDefault) {
+            return mSourceCrop;
+        }
+
+        // Install orientation is transparent to the callers.  Apply it now.
+        uint32_t flags = 0x00;
+        switch (orientation) {
+            case DisplayState::eOrientation90:
+                flags = Transform::ROT_90;
+                break;
+            case DisplayState::eOrientation180:
+                flags = Transform::ROT_180;
+                break;
+            case DisplayState::eOrientation270:
+                flags = Transform::ROT_270;
+                break;
+        }
+        Transform tr;
+        tr.set(flags, getWidth(), getHeight());
+        return tr.transform(mSourceCrop);
+    }
 
 private:
+    // Install orientation is transparent to the callers.  We need to cancel
+    // it out by modifying rotation flags.
+    static Transform::orientation_flags getDisplayRotation(
+            Transform::orientation_flags rotation, int orientation) {
+        if (orientation == DisplayState::eOrientationDefault) {
+            return rotation;
+        }
+
+        // convert hw orientation into flag presentation
+        // here inverse transform needed
+        uint8_t hw_rot_90 = 0x00;
+        uint8_t hw_flip_hv = 0x00;
+        switch (orientation) {
+            case DisplayState::eOrientation90:
+                hw_rot_90 = Transform::ROT_90;
+                hw_flip_hv = Transform::ROT_180;
+                break;
+            case DisplayState::eOrientation180:
+                hw_flip_hv = Transform::ROT_180;
+                break;
+            case DisplayState::eOrientation270:
+                hw_rot_90 = Transform::ROT_90;
+                break;
+        }
+
+        // transform flags operation
+        // 1) flip H V if both have ROT_90 flag
+        // 2) XOR these flags
+        uint8_t rotation_rot_90 = rotation & Transform::ROT_90;
+        uint8_t rotation_flip_hv = rotation & Transform::ROT_180;
+        if (rotation_rot_90 & hw_rot_90) {
+            rotation_flip_hv = (~rotation_flip_hv) & Transform::ROT_180;
+        }
+
+        return static_cast<Transform::orientation_flags>(
+                (rotation_rot_90 ^ hw_rot_90) | (rotation_flip_hv ^ hw_flip_hv));
+    }
+
     const sp<const DisplayDevice> mDevice;
     const Rect mSourceCrop;
 };
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 0caac9b..72f1fc4 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -88,7 +88,6 @@
         mCurrentOpacity(true),
         mCurrentFrameNumber(0),
         mFrameLatencyNeeded(false),
-        mFiltering(false),
         mNeedsFiltering(false),
         mProtectedByApp(false),
         mClientRef(client),
@@ -793,14 +792,6 @@
     return true;
 }
 
-void Layer::setFiltering(bool filtering) {
-    mFiltering = filtering;
-}
-
-bool Layer::getFiltering() const {
-    return mFiltering;
-}
-
 // ----------------------------------------------------------------------------
 // local state
 // ----------------------------------------------------------------------------
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 301f190..239f397 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -530,9 +530,6 @@
     // -----------------------------------------------------------------------
 
     void clearWithOpenGL(const RenderArea& renderArea) const;
-    void setFiltering(bool filtering);
-    bool getFiltering() const;
-
 
     inline const State& getDrawingState() const { return mDrawingState; }
     inline const State& getCurrentState() const { return mCurrentState; }
@@ -755,8 +752,6 @@
     bool mCurrentOpacity;
     std::atomic<uint64_t> mCurrentFrameNumber;
     bool mFrameLatencyNeeded;
-    // Whether filtering is forced on or not
-    bool mFiltering;
     // Whether filtering is needed b/c of the drawingstate
     bool mNeedsFiltering;
 
diff --git a/services/surfaceflinger/RenderArea.cpp b/services/surfaceflinger/RenderArea.cpp
index 1a8edf3..93759e8 100644
--- a/services/surfaceflinger/RenderArea.cpp
+++ b/services/surfaceflinger/RenderArea.cpp
@@ -1,7 +1,5 @@
 #include "RenderArea.h"
 
-#include <gui/LayerState.h>
-
 namespace android {
 
 float RenderArea::getCaptureFillValue(CaptureFill captureFill) {
@@ -13,37 +11,5 @@
             return 1.0f;
     }
 }
-/*
- * Checks that the requested width and height are valid and updates them to the render area
- * dimensions if they are set to 0
- */
-status_t RenderArea::updateDimensions(int displayRotation) {
-    // get screen geometry
-
-    uint32_t width = getWidth();
-    uint32_t height = getHeight();
-
-    if (mRotationFlags & Transform::ROT_90) {
-        std::swap(width, height);
-    }
-
-    if (displayRotation & DisplayState::eOrientationSwapMask) {
-        std::swap(width, height);
-    }
-
-    if ((mReqWidth > width) || (mReqHeight > height)) {
-        ALOGE("size mismatch (%d, %d) > (%d, %d)", mReqWidth, mReqHeight, width, height);
-        return BAD_VALUE;
-    }
-
-    if (mReqWidth == 0) {
-        mReqWidth = width;
-    }
-    if (mReqHeight == 0) {
-        mReqHeight = height;
-    }
-
-    return NO_ERROR;
-}
 
 } // namespace android
diff --git a/services/surfaceflinger/RenderArea.h b/services/surfaceflinger/RenderArea.h
index 96e4b5f..d980bd5 100644
--- a/services/surfaceflinger/RenderArea.h
+++ b/services/surfaceflinger/RenderArea.h
@@ -1,50 +1,80 @@
 #pragma once
 
-#include <ui/GraphicTypes.h>
-
 #include "Transform.h"
 
 #include <functional>
 
 namespace android {
 
+// RenderArea describes a rectangular area that layers can be rendered to.
+//
+// There is a logical render area and a physical render area.  When a layer is
+// rendered to the render area, it is first transformed and clipped to the logical
+// render area.  The transformed and clipped layer is then projected onto the
+// physical render area.
 class RenderArea {
-
 public:
     enum class CaptureFill {CLEAR, OPAQUE};
 
     static float getCaptureFillValue(CaptureFill captureFill);
 
-    RenderArea(uint32_t reqHeight, uint32_t reqWidth, CaptureFill captureFill,
-               ISurfaceComposer::Rotation rotation = ISurfaceComposer::eRotateNone)
-          : mReqHeight(reqHeight), mReqWidth(reqWidth), mCaptureFill(captureFill) {
-        mRotationFlags = Transform::fromRotation(rotation);
-    }
+    RenderArea(uint32_t reqWidth, uint32_t reqHeight, CaptureFill captureFill,
+               Transform::orientation_flags rotation = Transform::ROT_0)
+          : mReqWidth(reqWidth),
+            mReqHeight(reqHeight),
+            mCaptureFill(captureFill),
+            mRotationFlags(rotation) {}
 
     virtual ~RenderArea() = default;
 
-    virtual const Transform& getTransform() const = 0;
-    virtual Rect getBounds() const = 0;
-    virtual int getHeight() const = 0;
-    virtual int getWidth() const = 0;
-    virtual bool isSecure() const = 0;
-    virtual bool needsFiltering() const = 0;
-    virtual Rect getSourceCrop() const = 0;
-
+    // Invoke drawLayers to render layers into the render area.
     virtual void render(std::function<void()> drawLayers) { drawLayers(); }
 
-    int getReqHeight() const { return mReqHeight; };
-    int getReqWidth() const { return mReqWidth; };
-    Transform::orientation_flags getRotationFlags() const { return mRotationFlags; };
-    status_t updateDimensions(int displayRotation);
+    // Returns true if the render area is secure.  A secure layer should be
+    // blacked out / skipped when rendered to an insecure render area.
+    virtual bool isSecure() const = 0;
 
+    // Returns true if the otherwise disabled layer filtering should be
+    // enabled when rendering to this render area.
+    virtual bool needsFiltering() const = 0;
+
+    // Returns the transform to be applied on layers to transform them into
+    // the logical render area.
+    virtual const Transform& getTransform() const = 0;
+
+    // Returns the size of the logical render area.  Layers are clipped to the
+    // logical render area.
+    virtual int getWidth() const = 0;
+    virtual int getHeight() const = 0;
+    virtual Rect getBounds() const = 0;
+
+    // Returns the source crop of the render area.  The source crop defines
+    // how layers are projected from the logical render area onto the physical
+    // render area.  It can be larger than the logical render area.  It can
+    // also be optionally rotated.
+    //
+    // Layers are first clipped to the source crop (in addition to being
+    // clipped to the logical render area already).  The source crop and the
+    // layers are then rotated around the center of the source crop, and
+    // scaled to the physical render area linearly.
+    virtual Rect getSourceCrop() const = 0;
+
+    // Returns the rotation of the source crop and the layers.
+    Transform::orientation_flags getRotationFlags() const { return mRotationFlags; };
+
+    // Returns the size of the physical render area.
+    int getReqWidth() const { return mReqWidth; };
+    int getReqHeight() const { return mReqHeight; };
+
+    // Returns the fill color of the physical render area.  Regions not
+    // covered by any rendered layer should be filled with this color.
     CaptureFill getCaptureFill() const { return mCaptureFill; };
 
 private:
-    uint32_t mReqHeight;
-    uint32_t mReqWidth;
-    Transform::orientation_flags mRotationFlags;
-    CaptureFill mCaptureFill;
+    const uint32_t mReqWidth;
+    const uint32_t mReqHeight;
+    const CaptureFill mCaptureFill;
+    const Transform::orientation_flags mRotationFlags;
 };
 
 } // namespace android
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 4ec1e7f..78d751a 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -75,6 +75,7 @@
 #include "LayerVector.h"
 #include "MonitoredProducer.h"
 #include "SurfaceFlinger.h"
+#include "Transform.h"
 #include "clz.h"
 
 #include "DisplayHardware/ComposerHal.h"
@@ -112,6 +113,27 @@
 using ui::RenderIntent;
 
 namespace {
+
+#pragma clang diagnostic push
+#pragma clang diagnostic error "-Wswitch-enum"
+
+Transform::orientation_flags fromSurfaceComposerRotation(ISurfaceComposer::Rotation rotation) {
+    switch (rotation) {
+        case ISurfaceComposer::eRotateNone:
+            return Transform::ROT_0;
+        case ISurfaceComposer::eRotate90:
+            return Transform::ROT_90;
+        case ISurfaceComposer::eRotate180:
+            return Transform::ROT_180;
+        case ISurfaceComposer::eRotate270:
+            return Transform::ROT_270;
+    }
+    ALOGE("Invalid rotation passed to captureScreen(): %d\n", rotation);
+    return Transform::ROT_0;
+}
+
+#pragma clang diagnostic pop
+
 class ConditionalLock {
 public:
     ConditionalLock(Mutex& mutex, bool lock) : mMutex(mutex), mLocked(lock) {
@@ -144,7 +166,7 @@
 int64_t SurfaceFlinger::maxFrameBufferAcquiredBuffers;
 // TODO(courtneygo): Rename hasWideColorDisplay to clarify its actual meaning.
 bool SurfaceFlinger::hasWideColorDisplay;
-
+int SurfaceFlinger::primaryDisplayOrientation = DisplayState::eOrientationDefault;
 
 std::string getHwcServiceName() {
     char value[PROPERTY_VALUE_MAX] = {};
@@ -278,19 +300,19 @@
 
     switch (primaryDisplayOrientation) {
         case V1_1::DisplayOrientation::ORIENTATION_90:
-            mPrimaryDisplayOrientation = DisplayState::eOrientation90;
+            SurfaceFlinger::primaryDisplayOrientation = DisplayState::eOrientation90;
             break;
         case V1_1::DisplayOrientation::ORIENTATION_180:
-            mPrimaryDisplayOrientation = DisplayState::eOrientation180;
+            SurfaceFlinger::primaryDisplayOrientation = DisplayState::eOrientation180;
             break;
         case V1_1::DisplayOrientation::ORIENTATION_270:
-            mPrimaryDisplayOrientation = DisplayState::eOrientation270;
+            SurfaceFlinger::primaryDisplayOrientation = DisplayState::eOrientation270;
             break;
         default:
-            mPrimaryDisplayOrientation = DisplayState::eOrientationDefault;
+            SurfaceFlinger::primaryDisplayOrientation = DisplayState::eOrientationDefault;
             break;
     }
-    ALOGV("Primary Display Orientation is set to %2d.", mPrimaryDisplayOrientation);
+    ALOGV("Primary Display Orientation is set to %2d.", SurfaceFlinger::primaryDisplayOrientation);
 
     mPrimaryDispSync.init(SurfaceFlinger::hasSyncFramework, SurfaceFlinger::dispSyncPresentTimeOffset);
 
@@ -952,7 +974,7 @@
         info.secure = true;
 
         if (type == DisplayDevice::DISPLAY_PRIMARY &&
-            mPrimaryDisplayOrientation & DisplayState::eOrientationSwapMask) {
+            primaryDisplayOrientation & DisplayState::eOrientationSwapMask) {
             std::swap(info.w, info.h);
         }
 
@@ -2395,6 +2417,9 @@
         nativeWindow->setSwapInterval(nativeWindow.get(), 0);
     }
 
+    const int displayInstallOrientation = state.type == DisplayDevice::DISPLAY_PRIMARY ?
+        primaryDisplayOrientation : DisplayState::eOrientationDefault;
+
     // virtual displays are always considered enabled
     auto initialPowerMode = (state.type >= DisplayDevice::DISPLAY_VIRTUAL) ? HWC_POWER_MODE_NORMAL
                                                                            : HWC_POWER_MODE_OFF;
@@ -2402,7 +2427,7 @@
     sp<DisplayDevice> hw =
             new DisplayDevice(this, state.type, hwcId, state.isSecure, display, nativeWindow,
                               dispSurface, std::move(renderSurface), displayWidth, displayHeight,
-                              hasWideColorGamut, hdrCapabilities,
+                              displayInstallOrientation, hasWideColorGamut, hdrCapabilities,
                               supportedPerFrameMetadata, hwcColorModes, initialPowerMode);
 
     if (maxFrameBufferAcquiredBuffers >= 3) {
@@ -4832,20 +4857,24 @@
 
     if (CC_UNLIKELY(display == 0)) return BAD_VALUE;
 
-    const sp<const DisplayDevice> device(getDisplayDeviceLocked(display));
-    if (CC_UNLIKELY(device == 0)) return BAD_VALUE;
+    auto renderAreaRotation = fromSurfaceComposerRotation(rotation);
 
-    const Rect& dispScissor = device->getScissor();
-    if (!dispScissor.isEmpty()) {
-        sourceCrop.set(dispScissor);
-        // adb shell screencap will default reqWidth and reqHeight to zeros.
+    sp<DisplayDevice> device;
+    {
+        Mutex::Autolock _l(mStateLock);
+
+        device = getDisplayDeviceLocked(display);
+        if (!device) return BAD_VALUE;
+
+        // set the requested width/height to the logical display viewport size
+        // by default
         if (reqWidth == 0 || reqHeight == 0) {
             reqWidth = uint32_t(device->getViewport().width());
             reqHeight = uint32_t(device->getViewport().height());
         }
     }
 
-    DisplayRenderArea renderArea(device, sourceCrop, reqHeight, reqWidth, rotation);
+    DisplayRenderArea renderArea(device, sourceCrop, reqWidth, reqHeight, renderAreaRotation);
 
     auto traverseLayers = std::bind(std::mem_fn(&SurfaceFlinger::traverseLayersInDisplay), this,
                                     device, minLayerZ, maxLayerZ, std::placeholders::_1);
@@ -4861,9 +4890,10 @@
     public:
         LayerRenderArea(SurfaceFlinger* flinger, const sp<Layer>& layer, const Rect crop,
                         int32_t reqWidth, int32_t reqHeight, bool childrenOnly)
-              : RenderArea(reqHeight, reqWidth, CaptureFill::CLEAR),
+              : RenderArea(reqWidth, reqHeight, CaptureFill::CLEAR),
                 mLayer(layer),
                 mCrop(crop),
+                mNeedsFiltering(false),
                 mFlinger(flinger),
                 mChildrenOnly(childrenOnly) {}
         const Transform& getTransform() const override { return mTransform; }
@@ -4874,7 +4904,7 @@
         int getHeight() const override { return mLayer->getDrawingState().active.h; }
         int getWidth() const override { return mLayer->getDrawingState().active.w; }
         bool isSecure() const override { return false; }
-        bool needsFiltering() const override { return false; }
+        bool needsFiltering() const override { return mNeedsFiltering; }
         Rect getSourceCrop() const override {
             if (mCrop.isEmpty()) {
                 return getBounds();
@@ -4895,6 +4925,11 @@
         };
 
         void render(std::function<void()> drawLayers) override {
+            const Rect sourceCrop = getSourceCrop();
+            // no need to check rotation because there is none
+            mNeedsFiltering = sourceCrop.width() != getReqWidth() ||
+                sourceCrop.height() != getReqHeight();
+
             if (!mChildrenOnly) {
                 mTransform = mLayer->getTransform().inverse();
                 drawLayers();
@@ -4917,6 +4952,7 @@
         // layer which has no properties set and which does not draw.
         sp<ContainerLayer> screenshotParentLayer;
         Transform mTransform;
+        bool mNeedsFiltering;
 
         SurfaceFlinger* mFlinger;
         const bool mChildrenOnly;
@@ -4951,6 +4987,14 @@
     int32_t reqWidth = crop.width() * frameScale;
     int32_t reqHeight = crop.height() * frameScale;
 
+    // really small crop or frameScale
+    if (reqWidth <= 0) {
+        reqWidth = 1;
+    }
+    if (reqHeight <= 0) {
+        reqHeight = 1;
+    }
+
     LayerRenderArea renderArea(this, parent, crop, reqWidth, reqHeight, childrenOnly);
 
     auto traverseLayers = [parent, childrenOnly](const LayerVector::Visitor& visitor) {
@@ -4972,8 +5016,6 @@
                                              bool useIdentityTransform) {
     ATRACE_CALL();
 
-    renderArea.updateDimensions(mPrimaryDisplayOrientation);
-
     const uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN |
             GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE;
     *outBuffer = new GraphicBuffer(renderArea.getReqWidth(), renderArea.getReqHeight(),
@@ -5049,57 +5091,12 @@
     auto& engine(getRenderEngine());
 
     // get screen geometry
-    const auto raWidth = renderArea.getWidth();
     const auto raHeight = renderArea.getHeight();
 
     const auto reqWidth = renderArea.getReqWidth();
     const auto reqHeight = renderArea.getReqHeight();
-    Rect sourceCrop = renderArea.getSourceCrop();
-
-    bool filtering = false;
-    if (mPrimaryDisplayOrientation & DisplayState::eOrientationSwapMask) {
-        filtering = static_cast<int32_t>(reqWidth) != raHeight ||
-                static_cast<int32_t>(reqHeight) != raWidth;
-    } else {
-        filtering = static_cast<int32_t>(reqWidth) != raWidth ||
-                static_cast<int32_t>(reqHeight) != raHeight;
-    }
-
-    // if a default or invalid sourceCrop is passed in, set reasonable values
-    if (sourceCrop.width() == 0 || sourceCrop.height() == 0 || !sourceCrop.isValid()) {
-        sourceCrop.setLeftTop(Point(0, 0));
-        sourceCrop.setRightBottom(Point(raWidth, raHeight));
-    } else if (mPrimaryDisplayOrientation != DisplayState::eOrientationDefault) {
-        Transform tr;
-        uint32_t flags = 0x00;
-        switch (mPrimaryDisplayOrientation) {
-            case DisplayState::eOrientation90:
-                flags = Transform::ROT_90;
-                break;
-            case DisplayState::eOrientation180:
-                flags = Transform::ROT_180;
-                break;
-            case DisplayState::eOrientation270:
-                flags = Transform::ROT_270;
-                break;
-        }
-        tr.set(flags, raWidth, raHeight);
-        sourceCrop = tr.transform(sourceCrop);
-    }
-
-    // ensure that sourceCrop is inside screen
-    if (sourceCrop.left < 0) {
-        ALOGE("Invalid crop rect: l = %d (< 0)", sourceCrop.left);
-    }
-    if (sourceCrop.right > raWidth) {
-        ALOGE("Invalid crop rect: r = %d (> %d)", sourceCrop.right, raWidth);
-    }
-    if (sourceCrop.top < 0) {
-        ALOGE("Invalid crop rect: t = %d (< 0)", sourceCrop.top);
-    }
-    if (sourceCrop.bottom > raHeight) {
-        ALOGE("Invalid crop rect: b = %d (> %d)", sourceCrop.bottom, raHeight);
-    }
+    const auto sourceCrop = renderArea.getSourceCrop();
+    const auto rotation = renderArea.getRotationFlags();
 
     // assume ColorMode::SRGB / RenderIntent::COLORIMETRIC
     engine.setOutputDataSpace(Dataspace::SRGB);
@@ -5108,37 +5105,6 @@
     // make sure to clear all GL error flags
     engine.checkErrors();
 
-    Transform::orientation_flags rotation = renderArea.getRotationFlags();
-    if (mPrimaryDisplayOrientation != DisplayState::eOrientationDefault) {
-        // convert hw orientation into flag presentation
-        // here inverse transform needed
-        uint8_t hw_rot_90  = 0x00;
-        uint8_t hw_flip_hv = 0x00;
-        switch (mPrimaryDisplayOrientation) {
-            case DisplayState::eOrientation90:
-                hw_rot_90 = Transform::ROT_90;
-                hw_flip_hv = Transform::ROT_180;
-                break;
-            case DisplayState::eOrientation180:
-                hw_flip_hv = Transform::ROT_180;
-                break;
-            case DisplayState::eOrientation270:
-                hw_rot_90  = Transform::ROT_90;
-                break;
-        }
-
-        // transform flags operation
-        // 1) flip H V if both have ROT_90 flag
-        // 2) XOR these flags
-        uint8_t rotation_rot_90  = rotation & Transform::ROT_90;
-        uint8_t rotation_flip_hv = rotation & Transform::ROT_180;
-        if (rotation_rot_90 & hw_rot_90) {
-            rotation_flip_hv = (~rotation_flip_hv) & Transform::ROT_180;
-        }
-        rotation = static_cast<Transform::orientation_flags>
-                   ((rotation_rot_90 ^ hw_rot_90) | (rotation_flip_hv ^ hw_flip_hv));
-    }
-
     // set-up our viewport
     engine.setViewportAndProjection(reqWidth, reqHeight, sourceCrop, raHeight, yswap,
                                     rotation);
@@ -5149,9 +5115,7 @@
     engine.clearWithColor(0, 0, 0, alpha);
 
     traverseLayers([&](Layer* layer) {
-        if (filtering) layer->setFiltering(true);
         layer->draw(renderArea, useIdentityTransform);
-        if (filtering) layer->setFiltering(false);
     });
 }
 
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index d2b1233..0914a09 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -286,6 +286,8 @@
     // want to support color management to disable color management.
     static bool hasWideColorDisplay;
 
+    static int primaryDisplayOrientation;
+
     static char const* getServiceName() ANDROID_API {
         return "SurfaceFlinger";
     }
@@ -345,8 +347,6 @@
     bool authenticateSurfaceTextureLocked(
         const sp<IGraphicBufferProducer>& bufferProducer) const;
 
-    int getPrimaryDisplayOrientation() const { return mPrimaryDisplayOrientation; }
-
 private:
     friend class Client;
     friend class DisplayEventConnection;
@@ -858,7 +858,6 @@
     mutable std::unique_ptr<MessageQueue> mEventQueue{std::make_unique<impl::MessageQueue>()};
     FrameTracker mAnimFrameTracker;
     DispSync mPrimaryDispSync;
-    int mPrimaryDisplayOrientation = DisplayState::eOrientationDefault;
 
     // protected by mDestroyedLayerLock;
     mutable Mutex mDestroyedLayerLock;
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 558845f..4c5fa99 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -110,7 +110,7 @@
      */
 
     auto& mutableHasWideColorDisplay() { return SurfaceFlinger::hasWideColorDisplay; }
-
+    auto& mutablePrimaryDisplayOrientation() { return SurfaceFlinger::primaryDisplayOrientation; }
     auto& mutableBuiltinDisplays() { return mFlinger->mBuiltinDisplays; }
     auto& mutableCurrentState() { return mFlinger->mCurrentState; }
     auto& mutableDisplays() { return mFlinger->mDisplays; }
@@ -320,10 +320,11 @@
         sp<DisplayDevice> inject() {
             std::unordered_map<ui::ColorMode, std::vector<ui::RenderIntent>> hdrAndRenderIntents;
             sp<DisplayDevice> device =
-                    new DisplayDevice(mFlinger.mFlinger.get(), mType, mHwcId, mSecure, mDisplayToken,
-                                      mNativeWindow, mDisplaySurface, std::move(mRenderSurface), 0,
-                                      0, false, HdrCapabilities(), 0, hdrAndRenderIntents,
-                                      HWC_POWER_MODE_NORMAL);
+                    new DisplayDevice(mFlinger.mFlinger.get(), mType, mHwcId, mSecure,
+                                      mDisplayToken, mNativeWindow, mDisplaySurface,
+                                      std::move(mRenderSurface), 0, 0,
+                                      DisplayState::eOrientationDefault, false, HdrCapabilities(),
+                                      0, hdrAndRenderIntents, HWC_POWER_MODE_NORMAL);
             mFlinger.mutableDisplays().add(mDisplayToken, device);
 
             DisplayDeviceState state(mType, mSecure);