|  | /* | 
|  | * Copyright (C) 2022 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. | 
|  | */ | 
|  |  | 
|  | package com.android.build.shrinker | 
|  |  | 
|  | import com.android.aapt.Resources | 
|  |  | 
|  | internal fun Resources.ResourceTable.entriesSequence(): Sequence<EntryWrapper> = sequence { | 
|  | for (resourcePackage in packageList) { | 
|  | for (resourceType in resourcePackage.typeList) { | 
|  | for (resourceEntry in resourceType.entryList) { | 
|  | val id = toIdentifier(resourcePackage, resourceType, resourceEntry) | 
|  | yield( | 
|  | EntryWrapper(id, resourcePackage.packageName, resourceType.name, resourceEntry) | 
|  | ) | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | internal fun Resources.ResourceTable.nullOutEntriesWithIds(ids: List<Int>) | 
|  | : Resources.ResourceTable { | 
|  | return nullOutEntriesWithIds(ids, false) | 
|  | } | 
|  |  | 
|  | internal fun Resources.ResourceTable.nullOutEntriesWithIds( | 
|  | ids: List<Int>, pruneResourceNames: Boolean): Resources.ResourceTable { | 
|  | if (ids.isEmpty()) { | 
|  | return this | 
|  | } | 
|  | val packageMappings = calculatePackageMappings(ids) | 
|  | val tableBuilder = this.toBuilder() | 
|  | tableBuilder.packageBuilderList.forEach { | 
|  | val typeMappings = packageMappings[it.packageId.id] | 
|  | if (typeMappings != null) { | 
|  | it.typeBuilderList.forEach { type -> | 
|  | val entryList = typeMappings[type.typeId.id] | 
|  | if (entryList != null) { | 
|  | type.entryBuilderList.forEach { entry -> | 
|  | if (entryList.contains(entry.entryId.id)) { | 
|  | entry.clearConfigValue() | 
|  | if (pruneResourceNames) { | 
|  | entry.clearName(); | 
|  | } | 
|  | if (entry.hasOverlayableItem()) { | 
|  | entry.clearOverlayableItem() | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  | return tableBuilder.build() | 
|  | } | 
|  |  | 
|  | private fun calculatePackageMappings(ids: List<Int>): MutableMap<Int, Map<Int, List<Int>>> { | 
|  | val sortedIds = ids.sorted() | 
|  | val packageMapping = mutableMapOf<Int, Map<Int, List<Int>>>() | 
|  | var typeMapping = mutableMapOf<Int, List<Int>>() | 
|  | var entryList = mutableListOf<Int>() | 
|  | var oldPackageId = -1 | 
|  | var oldTypeId = -1 | 
|  | for (value in sortedIds) { | 
|  | val packageId = packageIdFromIdentifier(value) | 
|  | val typeId = typeIdFromIdentifier(value) | 
|  | val entryId = entryIdFromIdentifier(value) | 
|  | if (packageId != oldPackageId) { | 
|  | typeMapping = mutableMapOf() | 
|  | packageMapping.put(packageId, typeMapping) | 
|  | oldPackageId = packageId | 
|  | oldTypeId = -1 | 
|  | } | 
|  | if (typeId != oldTypeId) { | 
|  | entryList = mutableListOf() | 
|  | typeMapping.put(typeId, entryList) | 
|  | oldTypeId = typeId | 
|  | } | 
|  | entryList.add(entryId) | 
|  | } | 
|  | return packageMapping | 
|  | } | 
|  |  | 
|  | internal data class EntryWrapper( | 
|  | val id: Int, | 
|  | val packageName: String, | 
|  | val type: String, | 
|  | val entry: Resources.Entry | 
|  | ) | 
|  |  | 
|  | fun toIdentifier( | 
|  | resourcePackage: Resources.Package, | 
|  | type: Resources.Type, | 
|  | entry: Resources.Entry | 
|  | ): Int = | 
|  | (resourcePackage.packageId.id shl 24) or (type.typeId.id shl 16) or entry.entryId.id | 
|  |  | 
|  | private fun packageIdFromIdentifier( | 
|  | identifier: Int | 
|  | ): Int = | 
|  | identifier shr 24 | 
|  |  | 
|  | private fun typeIdFromIdentifier( | 
|  | identifier: Int | 
|  | ): Int = | 
|  | (identifier and 0x00FF0000) shr 16 | 
|  |  | 
|  | private fun entryIdFromIdentifier( | 
|  | identifier: Int | 
|  | ): Int = | 
|  | (identifier and 0x0000FFFF) | 
|  |  | 
|  |  |