Skip to content

Commit

Permalink
Merge branch 'main' into arsc
Browse files Browse the repository at this point in the history
  • Loading branch information
garanj authored Jul 24, 2024
2 parents 28e4e6c + f136a1a commit 4171635
Show file tree
Hide file tree
Showing 52 changed files with 2,632 additions and 405 deletions.
30 changes: 30 additions & 0 deletions .github/workflows/gradle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,33 @@ jobs:
with:
build-root-directory: third_party/wff
arguments: :specification:validator:build
build_wff_optimizer:
runs-on: ubuntu-latest

steps:
- name: Checkout project
uses: actions/checkout@v3
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: "17"
distribution: "corretto"
architecture: "x64"
- name: Setup Android SDK
uses: android-actions/setup-android@v3
with:
packages: "tools platform-tools build-tools;30.0.3"
- name: Get project hash
run: |
git_hash=$(git rev-parse --short "$GITHUB_SHA")
echo "git_hash=$git_hash" >> $GITHUB_ENV
- name: Build wff-optimizer.jar
uses: gradle/actions/setup-gradle@v3
with:
build-root-directory: tools
arguments: wff-optimizer:jar -Dmemory-footprint.git_hash=${{ env.git_hash }}
- name: Test wff-optimizer
uses: gradle/actions/setup-gradle@v3
with:
build-root-directory: tools
arguments: wff-optimizer:test
9 changes: 8 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@ The [Memory footprint evaluator][memory-footprint] allows you to check watch
faces ahead of submission to Play or to incorporate memory usage checking into
your tools and processes.

## Watch Face Format optimizer

The [Watch Face Format optimizer][optimizer] is a tool which can be incorporated
into your work flow to reduce the memory usage of your watch face at runtime, by
optimizing aspects of your WFF XML and your resources.

## Samples

For WFF samples, please see the [Wear OS Samples repository][samples] on GitHub.
Expand All @@ -48,4 +54,5 @@ Watch Face Format is distributed under the Apache 2.0 license, see the
[samples]: https://github.com/android/wear-os-samples/tree/main/WatchFaceFormat
[xsd-specs]: third_party/wff/specification/documents/1/
[xsd-validator]: third_party/wff/README.md
[wff-features]: https://developer.android.com/training/wearables/wff/features
[wff-features]: https://developer.android.com/training/wearables/wff/features
[optimizer]: tools/wff-optimizer/
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.google.wear.watchface.dfx.memory;

import static com.google.wear.watchface.dfx.memory.WatchFaceDocuments.findSceneNode;

import org.w3c.dom.Document;

import java.util.Map;

/** Computes the memory footprint of a watch face in active. */
public class ActiveMemoryFootprintCalculator {
private final VariantConfigValue activeConfigValue;
private final Document document;
private final Map<String, DrawableResourceDetails> resourceMemoryMap;
private final EvaluationSettings evaluationSettings;

ActiveMemoryFootprintCalculator(
Document document,
Map<String, DrawableResourceDetails> resourceMemoryMap,
EvaluationSettings evaluationSettings) {
this.activeConfigValue = VariantConfigValue.active(evaluationSettings);
this.document = document;
this.resourceMemoryMap = resourceMemoryMap;
this.evaluationSettings = evaluationSettings;
}

long computeAmbientMemoryFootprint() {
DrawableNodeConfigTable drawableNodeConfigTable =
DrawableNodeConfigTable.create(findSceneNode(document), activeConfigValue);
WatchFaceResourceCollector resourceCollector =
new WatchFaceResourceCollector(document, resourceMemoryMap, evaluationSettings);
return new DynamicNodePerConfigurationFootprintCalculator(
document,
resourceMemoryMap,
evaluationSettings,
activeConfigValue,
resourceCollector,
drawableNodeConfigTable)
.calculateMaxFootprintBytes();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,10 @@ class AmbientMemoryFootprintCalculator {
private final VariantConfigValue ambientConfigValue;
private final Document document;
private final Map<String, DrawableResourceDetails> resourceMemoryMap;

/** Maps a resource to the first resource found with the same sha-1. */
private final Map<String, String> resourceDedupMap = new HashMap<>();

private final WatchFaceResourceCollector resourceCollector;
private final EvaluationSettings evaluationSettings;

Expand Down Expand Up @@ -110,7 +112,8 @@ long computeAmbientMemoryFootprint(long screenWidth, long screenHeight) {
new PerConfigurationDynamicResources();
Visitor visitor =
new Visitor(
perConfigurationDynamicResources, /* prevNodeIsDrawnDynamically= */ true,
perConfigurationDynamicResources,
/* prevNodeIsDrawnDynamically= */ true,
/* numClocks= */ 0);
visitor.visitNodes(findSceneNode(document));

Expand Down Expand Up @@ -171,13 +174,8 @@ long computeMaximumResourceUsage(Set<String> topLevelResources) {
for (Set<String> set : sets) {
long total = 0;
for (String resource : set) {
DrawableResourceDetails details = resourceMemoryMap.get(resource);
if (details == null) {
throw new TestFailedException(
String.format(
"Asset %s was not found in the watch face package",
resource));
}
DrawableResourceDetails details =
DrawableResourceDetails.findInMap(resourceMemoryMap, resource);
long imageBytes = details.getBiggestFrameFootprintBytes();

// If this image can be downsampled then the size is halved.
Expand All @@ -193,7 +191,7 @@ long computeMaximumResourceUsage(Set<String> topLevelResources) {
((double) imageBytes) / 1024 / 1024,
details.getWidth(),
details.getHeight(),
details.canUseRGB565() ? "RGB565" : "ARGB8888" );
details.canUseRGB565() ? "RGB565" : "ARGB8888");
}
total += imageBytes;
if (maxResourceSize < imageBytes) {
Expand All @@ -210,8 +208,9 @@ long computeMaximumResourceUsage(Set<String> topLevelResources) {

if (evaluationSettings.isVerbose()) {
long average = (numResources > 0) ? (maxTotal / numResources) : 0;
System.out.printf("Resource count %s average size %s max size %s\n", numResources,
average, maxResourceSize);
System.out.printf(
"Resource count %s average size %s max size %s\n",
numResources, average, maxResourceSize);
}

return maxTotal;
Expand Down Expand Up @@ -351,8 +350,11 @@ private void processConfiguration(Node node) {
continue;
}

Visitor visitor = new Visitor(
perConfigurationDynamicResources, prevNodeIsDrawnDynamically, numClocks);
Visitor visitor =
new Visitor(
perConfigurationDynamicResources,
prevNodeIsDrawnDynamically,
numClocks);
visitor.visitNodes(childNodes.item(i));

if (maxConfigNumLayers < visitor.numLayers) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import java.security.MessageDigest;
import java.util.Formatter;
import java.util.Iterator;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;

Expand Down Expand Up @@ -352,8 +353,8 @@ String getSha1() {
}

/**
* Whether this image can be quantised into an RGB565 image with out loosing too much
* visual fidelity.
* Whether this image can be quantised into an RGB565 image with out loosing too much visual
* fidelity.
*/
boolean canUseRGB565() {
return canUseRGB565;
Expand Down Expand Up @@ -462,7 +463,13 @@ public boolean equals(Object o) {
@Override
public int hashCode() {
return Objects.hash(
name, numberOfImages, biggestFrameFootprintBytes, bounds, width, height, sha1,
name,
numberOfImages,
biggestFrameFootprintBytes,
bounds,
width,
height,
sha1,
canUseRGB565);
}

Expand Down Expand Up @@ -523,7 +530,13 @@ public Builder setCanUseRGB565(boolean canUseRGB565) {

public DrawableResourceDetails build() {
return new DrawableResourceDetails(
name, numberOfImages, biggestFrameFootprintBytes, bounds, width, height, sha1,
name,
numberOfImages,
biggestFrameFootprintBytes,
bounds,
width,
height,
sha1,
canUseRGB565);
}
}
Expand Down Expand Up @@ -612,7 +625,7 @@ private static class QualtizationStats {
long visiblePixelQuantizationErrorSum = 0;

double getVisibleError() {
return (double)visiblePixelQuantizationErrorSum / (double)visiblePixels;
return (double) visiblePixelQuantizationErrorSum / (double) visiblePixels;
}
}

Expand Down Expand Up @@ -667,4 +680,15 @@ private static String byteArray2Hex(final byte[] hash) {
}
return formatter.toString();
}

static DrawableResourceDetails findInMap(
Map<String, DrawableResourceDetails> resourceMemoryMap, String resourceName) {
DrawableResourceDetails details = resourceMemoryMap.get(resourceName);
if (details == null) {
throw new TestFailedException(
String.format(
"Asset %s was not found in the watch face package", resourceName));
}
return details;
}
}
Loading

0 comments on commit 4171635

Please sign in to comment.