From 44b3697cd2a1f2548018e2feefa6bbb5d9cc6f75 Mon Sep 17 00:00:00 2001 From: Lee Shombert Date: Fri, 4 Jun 2021 17:08:31 -0700 Subject: [PATCH] A space-efficient 2D matrix - clean up Bug: Bug: 188447813 Convert WatchedSparseBooleanMatrix to pack bits into ints instead of bytes. This eliminates a lot of casts and it is probably slightly faster. Force the control information arrays in the matrix to resize in step with the values array. The default behavior of GrowingArrayUtils is to double the size of an array when it needs to grow, which is unnecessarily large. Also, the control arrays are shrunk along with the value array. Use the ArrayUtils methods for array allocation. This is consistent with classes in android.util. Test: atest * CtsContentTestCases:IntentFilterTest * CtsDynamicMimeHostTestCases * CtsRoleTestCases * FrameworksServicesTests:UserSystemPackageInstallerTest * FrameworksServicesTests:PackageManagerSettingsTests * FrameworksServicesTests:PackageManagerServiceTest * FrameworksServicesTests:AppsFilterTest * FrameworksServicesTests:PackageInstallerSessionTest * FrameworksServicesTests:ScanTests * UserLifecycleTests#startUser * UserLifecycleTests#stopUser * UserLifecycleTests#switchUser * FrameworksServicesTests:WatcherTest * android.appsecurity.cts.EphemeralTest * android.appsecurity.cts.InstantAppUserTest Change-Id: I8427905361e1471c91433c77628aa34b12b1044d --- .../utils/WatchedSparseBooleanMatrix.java | 79 +++++++++++-------- 1 file changed, 45 insertions(+), 34 deletions(-) diff --git a/services/core/java/com/android/server/utils/WatchedSparseBooleanMatrix.java b/services/core/java/com/android/server/utils/WatchedSparseBooleanMatrix.java index bf54bd527f574..9b0ef15c8bd69 100644 --- a/services/core/java/com/android/server/utils/WatchedSparseBooleanMatrix.java +++ b/services/core/java/com/android/server/utils/WatchedSparseBooleanMatrix.java @@ -67,7 +67,8 @@ public class WatchedSparseBooleanMatrix extends WatchableImpl implements Snappab * */ @@ -79,10 +80,9 @@ public class WatchedSparseBooleanMatrix extends WatchableImpl implements Snappab static final int STEP = 64; /** - * There are 8 bits in a byte. The constant is defined here only to make it easy to - * find in the code. + * The number of bits in the mValues array element. */ - private static final int BYTE = 8; + private static final int PACKING = 32; /** * Constants that index into the string array returned by matrixToString. The primary @@ -123,7 +123,7 @@ public class WatchedSparseBooleanMatrix extends WatchableImpl implements Snappab /** * The boolean array. This array is always {@code mOrder x mOrder} in size. */ - private byte[] mValues; + private int[] mValues; /** * A convenience function called when the elements are added to or removed from the storage. @@ -157,10 +157,10 @@ public class WatchedSparseBooleanMatrix extends WatchableImpl implements Snappab throw new RuntimeException("mOrder is " + mOrder + " initCap is " + initialCapacity); } - mInUse = new boolean[mOrder]; + mInUse = ArrayUtils.newUnpaddedBooleanArray(mOrder); mKeys = ArrayUtils.newUnpaddedIntArray(mOrder); mMap = ArrayUtils.newUnpaddedIntArray(mOrder); - mValues = new byte[mOrder * mOrder / 8]; + mValues = ArrayUtils.newUnpaddedIntArray(mOrder * mOrder / PACKING); mSize = 0; } @@ -301,8 +301,8 @@ public class WatchedSparseBooleanMatrix extends WatchableImpl implements Snappab */ private boolean valueAtInternal(int row, int col) { int element = row * mOrder + col; - int offset = element / BYTE; - int mask = 1 << (element % BYTE); + int offset = element / PACKING; + int mask = 1 << (element % PACKING); return (mValues[offset] & mask) != 0; } @@ -324,8 +324,8 @@ public class WatchedSparseBooleanMatrix extends WatchableImpl implements Snappab */ private void setValueAtInternal(int row, int col, boolean value) { int element = row * mOrder + col; - int offset = element / BYTE; - byte mask = (byte) (1 << (element % BYTE)); + int offset = element / PACKING; + int mask = 1 << (element % PACKING); if (value) { mValues[offset] |= mask; } else { @@ -377,10 +377,10 @@ public class WatchedSparseBooleanMatrix extends WatchableImpl implements Snappab mSize++; // Initialize the row and column corresponding to the new index. - int valueRow = mOrder / BYTE; - int offset = newIndex / BYTE; - byte mask = (byte) (~(1 << (newIndex % BYTE))); - Arrays.fill(mValues, newIndex * valueRow, (newIndex + 1) * valueRow, (byte) 0); + int valueRow = mOrder / PACKING; + int offset = newIndex / PACKING; + int mask = ~(1 << (newIndex % PACKING)); + Arrays.fill(mValues, newIndex * valueRow, (newIndex + 1) * valueRow, 0); for (int n = 0; n < mSize; n++) { mValues[n * valueRow + offset] &= mask; } @@ -412,25 +412,36 @@ public class WatchedSparseBooleanMatrix extends WatchableImpl implements Snappab * Expand the 2D array. This also extends the free list. */ private void growMatrix() { - resizeValues(mOrder + STEP); + resizeMatrix(mOrder + STEP); } /** * Resize the values array to the new dimension. */ - private void resizeValues(int newOrder) { - - boolean[] newInuse = Arrays.copyOf(mInUse, newOrder); + private void resizeMatrix(int newOrder) { + if (newOrder % STEP != 0) { + throw new IllegalArgumentException("matrix order " + newOrder + + " is not a multiple of " + STEP); + } int minOrder = Math.min(mOrder, newOrder); - byte[] newValues = new byte[newOrder * newOrder / BYTE]; + boolean[] newInUse = ArrayUtils.newUnpaddedBooleanArray(newOrder); + System.arraycopy(mInUse, 0, newInUse, 0, minOrder); + int[] newMap = ArrayUtils.newUnpaddedIntArray(newOrder); + System.arraycopy(mMap, 0, newMap, 0, minOrder); + int[] newKeys = ArrayUtils.newUnpaddedIntArray(newOrder); + System.arraycopy(mKeys, 0, newKeys, 0, minOrder); + + int[] newValues = ArrayUtils.newUnpaddedIntArray(newOrder * newOrder / PACKING); for (int i = 0; i < minOrder; i++) { - int row = mOrder * i / BYTE; - int newRow = newOrder * i / BYTE; - System.arraycopy(mValues, row, newValues, newRow, minOrder / BYTE); + int row = mOrder * i / PACKING; + int newRow = newOrder * i / PACKING; + System.arraycopy(mValues, row, newValues, newRow, minOrder / PACKING); } - mInUse = newInuse; + mInUse = newInUse; + mMap = newMap; + mKeys = newKeys; mValues = newValues; mOrder = newOrder; } @@ -482,21 +493,21 @@ public class WatchedSparseBooleanMatrix extends WatchableImpl implements Snappab int src = mMap[srcIndex]; mInUse[src] = false; mMap[srcIndex] = dst; - System.arraycopy(mValues, src * mOrder / BYTE, - mValues, dst * mOrder / BYTE, - mOrder / BYTE); - int srcOffset = (src / BYTE); - byte srcMask = (byte) (1 << (src % BYTE)); - int dstOffset = (dst / BYTE); - byte dstMask = (byte) (1 << (dst % BYTE)); + System.arraycopy(mValues, src * mOrder / PACKING, + mValues, dst * mOrder / PACKING, + mOrder / PACKING); + int srcOffset = (src / PACKING); + int srcMask = 1 << (src % PACKING); + int dstOffset = (dst / PACKING); + int dstMask = 1 << (dst % PACKING); for (int i = 0; i < mOrder; i++) { if ((mValues[srcOffset] & srcMask) == 0) { mValues[dstOffset] &= ~dstMask; } else { mValues[dstOffset] |= dstMask; } - srcOffset += mOrder / BYTE; - dstOffset += mOrder / BYTE; + srcOffset += mOrder / PACKING; + dstOffset += mOrder / PACKING; } } } @@ -508,7 +519,7 @@ public class WatchedSparseBooleanMatrix extends WatchableImpl implements Snappab pack(); int unused = (mOrder - mSize) / STEP; if (unused > 0) { - resizeValues(mOrder - (unused * STEP)); + resizeMatrix(mOrder - (unused * STEP)); } }