Home | History | Annotate | Download | only in link
      1 /*
      2  * Copyright (C) 2019 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 "link/ResourceExcluder.h"
     18 
     19 #include <algorithm>
     20 
     21 #include "DominatorTree.h"
     22 #include "ResourceTable.h"
     23 #include "trace/TraceBuffer.h"
     24 
     25 using android::ConfigDescription;
     26 
     27 namespace aapt {
     28 
     29 namespace {
     30 
     31 void RemoveIfExcluded(std::set<std::pair<ConfigDescription, int>>& excluded_configs_,
     32                       IAaptContext* context,
     33                       ResourceEntry* entry,
     34                       ResourceConfigValue* value) {
     35   const ConfigDescription& config = value->config;
     36 
     37   // If this entry is a default, ignore
     38   if (config == ConfigDescription::DefaultConfig()) {
     39     return;
     40   }
     41 
     42   for (auto& excluded_pair : excluded_configs_) {
     43 
     44     const ConfigDescription& excluded_config = excluded_pair.first;
     45     const int& excluded_diff = excluded_pair.second;
     46 
     47     // Check whether config contains all flags in excluded config
     48     int node_diff = config.diff(excluded_config);
     49     int masked_diff = excluded_diff & node_diff;
     50 
     51     if (masked_diff == 0) {
     52       if (context->IsVerbose()) {
     53         context->GetDiagnostics()->Note(
     54             DiagMessage(value->value->GetSource())
     55                 << "excluded resource \""
     56                 << entry->name
     57                 << "\" with config "
     58                 << config.toString());
     59       }
     60       value->value = {};
     61       return;
     62     }
     63   }
     64 }
     65 
     66 }  // namespace
     67 
     68 bool ResourceExcluder::Consume(IAaptContext* context, ResourceTable* table) {
     69   TRACE_NAME("ResourceExcluder::Consume");
     70   for (auto& package : table->packages) {
     71     for (auto& type : package->types) {
     72       for (auto& entry : type->entries) {
     73         for (auto& value : entry->values) {
     74           RemoveIfExcluded(excluded_configs_, context, entry.get(), value.get());
     75         }
     76 
     77         // Erase the values that were removed.
     78         entry->values.erase(
     79             std::remove_if(
     80                 entry->values.begin(), entry->values.end(),
     81                 [](const std::unique_ptr<ResourceConfigValue>& val) -> bool {
     82                   return val == nullptr || val->value == nullptr;
     83                 }),
     84             entry->values.end());
     85       }
     86     }
     87   }
     88   return true;
     89 }
     90 
     91 }  // namespace aapt
     92