blob: e81c951464b8b2bd64cb29381518c8a5f7165fd3 [file] [log] [blame]
Rico Winda6e4efc2023-08-03 07:51:44 +02001/*
2 * Copyright (C) 2022 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
17package com.android.build.shrinker
18
19import com.android.aapt.Resources
20
21internal fun Resources.ResourceTable.entriesSequence(): Sequence<EntryWrapper> = sequence {
22 for (resourcePackage in packageList) {
23 for (resourceType in resourcePackage.typeList) {
24 for (resourceEntry in resourceType.entryList) {
25 val id = toIdentifier(resourcePackage, resourceType, resourceEntry)
26 yield(
27 EntryWrapper(id, resourcePackage.packageName, resourceType.name, resourceEntry)
28 )
29 }
30 }
31 }
32}
33
34internal fun Resources.ResourceTable.nullOutEntriesWithIds(ids: List<Int>)
35 : Resources.ResourceTable {
Rico Wind28f4d622024-02-20 13:54:46 +010036 return nullOutEntriesWithIds(ids, false)
37}
38
39internal fun Resources.ResourceTable.nullOutEntriesWithIds(
40 ids: List<Int>, pruneResourceNames: Boolean): Resources.ResourceTable {
Rico Winda6e4efc2023-08-03 07:51:44 +020041 if (ids.isEmpty()) {
42 return this
43 }
44 val packageMappings = calculatePackageMappings(ids)
45 val tableBuilder = this.toBuilder()
Rico Wind28f4d622024-02-20 13:54:46 +010046 tableBuilder.packageBuilderList.forEach {
Rico Winda6e4efc2023-08-03 07:51:44 +020047 val typeMappings = packageMappings[it.packageId.id]
48 if (typeMappings != null) {
Rico Wind28f4d622024-02-20 13:54:46 +010049 it.typeBuilderList.forEach { type ->
Rico Winda6e4efc2023-08-03 07:51:44 +020050 val entryList = typeMappings[type.typeId.id]
51 if (entryList != null) {
52 type.entryBuilderList.forEach { entry ->
53 if (entryList.contains(entry.entryId.id)) {
54 entry.clearConfigValue()
Rico Wind28f4d622024-02-20 13:54:46 +010055 if (pruneResourceNames) {
56 entry.clearName();
57 }
Rico Winda6e4efc2023-08-03 07:51:44 +020058 if (entry.hasOverlayableItem()) {
59 entry.clearOverlayableItem()
60 }
61 }
62 }
63 }
64 }
65 }
66 }
67 return tableBuilder.build()
68}
69
70private fun calculatePackageMappings(ids: List<Int>): MutableMap<Int, Map<Int, List<Int>>> {
71 val sortedIds = ids.sorted()
72 val packageMapping = mutableMapOf<Int, Map<Int, List<Int>>>()
73 var typeMapping = mutableMapOf<Int, List<Int>>()
74 var entryList = mutableListOf<Int>()
75 var oldPackageId = -1
76 var oldTypeId = -1
77 for (value in sortedIds) {
78 val packageId = packageIdFromIdentifier(value)
79 val typeId = typeIdFromIdentifier(value)
80 val entryId = entryIdFromIdentifier(value)
81 if (packageId != oldPackageId) {
82 typeMapping = mutableMapOf()
83 packageMapping.put(packageId, typeMapping)
84 oldPackageId = packageId
85 oldTypeId = -1
86 }
87 if (typeId != oldTypeId) {
88 entryList = mutableListOf()
89 typeMapping.put(typeId, entryList)
90 oldTypeId = typeId
91 }
92 entryList.add(entryId)
93 }
94 return packageMapping
95}
96
97internal data class EntryWrapper(
98 val id: Int,
99 val packageName: String,
100 val type: String,
101 val entry: Resources.Entry
102)
103
Rico Windd773abd2024-02-19 11:25:18 +0100104fun toIdentifier(
Rico Winda6e4efc2023-08-03 07:51:44 +0200105 resourcePackage: Resources.Package,
106 type: Resources.Type,
107 entry: Resources.Entry
108): Int =
109 (resourcePackage.packageId.id shl 24) or (type.typeId.id shl 16) or entry.entryId.id
110
111private fun packageIdFromIdentifier(
112 identifier: Int
113): Int =
Rico Windbfc60b02024-11-11 16:46:15 +0100114 identifier ushr 24
Rico Winda6e4efc2023-08-03 07:51:44 +0200115
116private fun typeIdFromIdentifier(
117 identifier: Int
118): Int =
119 (identifier and 0x00FF0000) shr 16
120
121private fun entryIdFromIdentifier(
122 identifier: Int
123): Int =
124 (identifier and 0x0000FFFF)
125
126