Home | History | Annotate | Download | only in hwui
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "ProfileDataContainer.h"
     18 
     19 #include <errno.h>
     20 
     21 #include <cutils/ashmem.h>
     22 #include <log/log.h>
     23 
     24 #include <errno.h>
     25 #include <sys/mman.h>
     26 
     27 namespace android {
     28 namespace uirenderer {
     29 
     30 void ProfileDataContainer::freeData() {
     31     if (mIsMapped) {
     32         munmap(mData, sizeof(ProfileData));
     33     } else {
     34         delete mData;
     35     }
     36     mIsMapped = false;
     37     mData = nullptr;
     38 }
     39 
     40 void ProfileDataContainer::rotateStorage() {
     41     // If we are mapped we want to stop using the ashmem backend and switch to malloc
     42     // We are expecting a switchStorageToAshmem call to follow this, but it's not guaranteed
     43     // If we aren't sitting on top of ashmem then just do a reset() as it's functionally
     44     // equivalent do a free, malloc, reset.
     45     if (mIsMapped) {
     46         freeData();
     47         mData = new ProfileData;
     48     }
     49     mData->reset();
     50 }
     51 
     52 void ProfileDataContainer::switchStorageToAshmem(int ashmemfd) {
     53     int regionSize = ashmem_get_size_region(ashmemfd);
     54     if (regionSize < 0) {
     55         int err = errno;
     56         ALOGW("Failed to get ashmem region size from fd %d, err %d %s", ashmemfd, err,
     57               strerror(err));
     58         return;
     59     }
     60     if (regionSize < static_cast<int>(sizeof(ProfileData))) {
     61         ALOGW("Ashmem region is too small! Received %d, required %u", regionSize,
     62               static_cast<unsigned int>(sizeof(ProfileData)));
     63         return;
     64     }
     65     ProfileData* newData = reinterpret_cast<ProfileData*>(
     66             mmap(NULL, sizeof(ProfileData), PROT_READ | PROT_WRITE, MAP_SHARED, ashmemfd, 0));
     67     if (newData == MAP_FAILED) {
     68         int err = errno;
     69         ALOGW("Failed to move profile data to ashmem fd %d, error = %d", ashmemfd, err);
     70         return;
     71     }
     72 
     73     newData->mergeWith(*mData);
     74     freeData();
     75     mData = newData;
     76     mIsMapped = true;
     77 }
     78 
     79 } /* namespace uirenderer */
     80 } /* namespace android */
     81