Loading services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java +3 −1 Original line number Diff line number Diff line Loading @@ -568,7 +568,9 @@ class SyntheticPasswordManager { } } private @Nullable IWeaver getWeaverAidlService() { @VisibleForTesting @Nullable protected IWeaver getWeaverAidlService() { final IWeaver aidlWeaver; try { aidlWeaver = Loading services/tests/servicestests/src/com/android/server/locksettings/MockSyntheticPasswordManager.java +28 −4 Original line number Diff line number Diff line Loading @@ -15,8 +15,10 @@ */ package com.android.server.locksettings; import static org.junit.Assert.assertNull; import android.content.Context; import android.hardware.weaver.V1_0.IWeaver; import android.hardware.weaver.IWeaver; import android.os.RemoteException; import android.os.UserManager; import android.util.ArrayMap; Loading @@ -35,6 +37,8 @@ public class MockSyntheticPasswordManager extends SyntheticPasswordManager { private FakeGateKeeperService mGateKeeper; private MockWeaverService mWeaverService; private IWeaver mWeaverAidl; private android.hardware.weaver.V1_0.IWeaver mWeaverHidl; public MockSyntheticPasswordManager(Context context, LockSettingsStorage storage, FakeGateKeeperService gatekeeper, UserManager userManager, Loading Loading @@ -112,13 +116,33 @@ public class MockSyntheticPasswordManager extends SyntheticPasswordManager { } } /** Enables MockWeaverService. */ public void enableWeaver() { enableWeaverAidl(); } /** Enables MockWeaverService with the current (AIDL) interface. */ public void enableWeaverAidl() { assertNull(mWeaverService); mWeaverService = new MockWeaverService(); mWeaverAidl = mWeaverService; } @Override protected IWeaver getWeaverHidlService() throws RemoteException { return mWeaverService; protected IWeaver getWeaverAidlService() { return mWeaverAidl; } public void enableWeaver() { /** Enables MockWeaverService with the old (HIDL) interface. */ public void enableWeaverHidl() { assertNull(mWeaverService); mWeaverService = new MockWeaverService(); mWeaverHidl = mWeaverService.asHidl(); } @Override protected android.hardware.weaver.V1_0.IWeaver getWeaverHidlService() throws RemoteException { return mWeaverHidl; } public int getSumOfWeaverFailureCounters() { Loading services/tests/servicestests/src/com/android/server/locksettings/MockWeaverService.java +103 −21 Original line number Diff line number Diff line package com.android.server.locksettings; import android.hardware.weaver.V1_0.IWeaver; import android.hardware.weaver.V1_0.WeaverConfig; import android.hardware.weaver.V1_0.WeaverReadResponse; import android.hardware.weaver.V1_0.WeaverStatus; import static org.mockito.Mockito.mock; import android.hardware.weaver.IWeaver; import android.hardware.weaver.WeaverConfig; import android.hardware.weaver.WeaverReadResponse; import android.hardware.weaver.WeaverReadStatus; import android.os.IBinder; import android.os.RemoteException; import java.util.ArrayList; import java.util.Arrays; public class MockWeaverService extends IWeaver.Stub { public class MockWeaverService implements IWeaver { private static final int MAX_SLOTS = 8; private static final int KEY_LENGTH = 256 / 8; private static final int VALUE_LENGTH = 256 / 8; private static class WeaverSlot { public ArrayList<Byte> key; public ArrayList<Byte> value; public byte[] key; public byte[] value; public int failureCounter; } Loading @@ -30,46 +33,125 @@ public class MockWeaverService extends IWeaver.Stub { } @Override public void getConfig(getConfigCallback cb) throws RemoteException { public WeaverConfig getConfig() throws RemoteException { WeaverConfig config = new WeaverConfig(); config.keySize = KEY_LENGTH; config.valueSize = VALUE_LENGTH; config.slots = MAX_SLOTS; cb.onValues(WeaverStatus.OK, config); return config; } @Override public int write(int slotId, ArrayList<Byte> key, ArrayList<Byte> value) throws RemoteException { public void write(int slotId, byte[] key, byte[] value) throws RemoteException { if (slotId < 0 || slotId >= MAX_SLOTS) { throw new RuntimeException("Invalid slot id"); } WeaverSlot slot = mSlots[slotId]; slot.key = (ArrayList<Byte>) key.clone(); slot.value = (ArrayList<Byte>) value.clone(); slot.key = key.clone(); slot.value = value.clone(); slot.failureCounter = 0; return WeaverStatus.OK; } @Override public void read(int slotId, ArrayList<Byte> key, readCallback cb) throws RemoteException { public WeaverReadResponse read(int slotId, byte[] key) throws RemoteException { if (slotId < 0 || slotId >= MAX_SLOTS) { throw new RuntimeException("Invalid slot id"); } WeaverReadResponse response = new WeaverReadResponse(); WeaverSlot slot = mSlots[slotId]; if (key.equals(slot.key)) { response.value.addAll(slot.value); cb.onValues(WeaverStatus.OK, response); WeaverReadResponse response = new WeaverReadResponse(); if (Arrays.equals(key, slot.key)) { response.value = slot.value.clone(); response.status = WeaverReadStatus.OK; slot.failureCounter = 0; } else { cb.onValues(WeaverStatus.FAILED, response); response.status = WeaverReadStatus.INCORRECT_KEY; slot.failureCounter++; } return response; } @Override public String getInterfaceHash() { throw new UnsupportedOperationException(); } @Override public int getInterfaceVersion() { return 2; } @Override public IBinder asBinder() { return mock(IBinder.class); } public int getSumOfFailureCounters() { return Arrays.stream(mSlots).mapToInt(slot -> slot.failureCounter).sum(); } /** Returns an adapter object that implements the old (HIDL) Weaver interface. */ public android.hardware.weaver.V1_0.IWeaver.Stub asHidl() { return new MockWeaverServiceHidlAdapter(); } private class MockWeaverServiceHidlAdapter extends android.hardware.weaver.V1_0.IWeaver.Stub { @Override public void getConfig(getConfigCallback cb) throws RemoteException { WeaverConfig aidlConfig = MockWeaverService.this.getConfig(); android.hardware.weaver.V1_0.WeaverConfig hidlConfig = new android.hardware.weaver.V1_0.WeaverConfig(); hidlConfig.keySize = aidlConfig.keySize; hidlConfig.valueSize = aidlConfig.valueSize; hidlConfig.slots = aidlConfig.slots; cb.onValues(android.hardware.weaver.V1_0.WeaverStatus.OK, hidlConfig); } @SuppressWarnings("NonApiType") @Override public int write(int slotId, ArrayList<Byte> key, ArrayList<Byte> value) throws RemoteException { MockWeaverService.this.write(slotId, fromByteArrayList(key), fromByteArrayList(value)); return android.hardware.weaver.V1_0.WeaverStatus.OK; } @SuppressWarnings("NonApiType") @Override public void read(int slotId, ArrayList<Byte> key, readCallback cb) throws RemoteException { WeaverReadResponse aidlResponse = MockWeaverService.this.read(slotId, fromByteArrayList(key)); android.hardware.weaver.V1_0.WeaverReadResponse hidlResponse = new android.hardware.weaver.V1_0.WeaverReadResponse(); int hidlStatus = switch (aidlResponse.status) { case WeaverReadStatus.OK -> android.hardware.weaver.V1_0.WeaverStatus.OK; case WeaverReadStatus.INCORRECT_KEY -> android.hardware.weaver.V1_0.WeaverReadStatus.INCORRECT_KEY; case WeaverReadStatus.THROTTLE -> android.hardware.weaver.V1_0.WeaverReadStatus.THROTTLE; default -> android.hardware.weaver.V1_0.WeaverStatus.FAILED; }; if (aidlResponse.value != null) { hidlResponse.value = toByteArrayList(aidlResponse.value); } cb.onValues(hidlStatus, hidlResponse); } @SuppressWarnings("NonApiType") private static ArrayList<Byte> toByteArrayList(byte[] data) { ArrayList<Byte> result = new ArrayList<Byte>(data.length); for (int i = 0; i < data.length; i++) { result.add(data[i]); } return result; } @SuppressWarnings("NonApiType") private static byte[] fromByteArrayList(ArrayList<Byte> data) { byte[] result = new byte[data.size()]; for (int i = 0; i < data.size(); i++) { result[i] = data.get(i); } return result; } } } services/tests/servicestests/src/com/android/server/locksettings/WeaverAidlBasedSyntheticPasswordTests.java 0 → 100644 +35 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 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.server.locksettings; import android.platform.test.annotations.Presubmit; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; import org.junit.Before; import org.junit.runner.RunWith; @SmallTest @Presubmit @RunWith(AndroidJUnit4.class) public class WeaverAidlBasedSyntheticPasswordTests extends WeaverBasedSyntheticPasswordTests { @Before public void setup() { mSpManager.enableWeaverAidl(); } } services/tests/servicestests/src/com/android/server/locksettings/WeaverBasedSyntheticPasswordTests.java +1 −16 Original line number Diff line number Diff line Loading @@ -6,28 +6,13 @@ import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.when; import android.platform.test.annotations.Presubmit; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; import com.android.server.locksettings.LockSettingsStorage.PersistentData; import com.google.android.collect.Sets; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @SmallTest @Presubmit @RunWith(AndroidJUnit4.class) public class WeaverBasedSyntheticPasswordTests extends SyntheticPasswordTests { @Before public void enableWeaver() throws Exception { mSpManager.enableWeaver(); } public abstract class WeaverBasedSyntheticPasswordTests extends SyntheticPasswordTests { // Tests that if the device is not yet provisioned and the FRP credential uses Weaver, then the // Weaver slot of the FRP credential is not reused. Assumes that Weaver slots are allocated Loading Loading
services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java +3 −1 Original line number Diff line number Diff line Loading @@ -568,7 +568,9 @@ class SyntheticPasswordManager { } } private @Nullable IWeaver getWeaverAidlService() { @VisibleForTesting @Nullable protected IWeaver getWeaverAidlService() { final IWeaver aidlWeaver; try { aidlWeaver = Loading
services/tests/servicestests/src/com/android/server/locksettings/MockSyntheticPasswordManager.java +28 −4 Original line number Diff line number Diff line Loading @@ -15,8 +15,10 @@ */ package com.android.server.locksettings; import static org.junit.Assert.assertNull; import android.content.Context; import android.hardware.weaver.V1_0.IWeaver; import android.hardware.weaver.IWeaver; import android.os.RemoteException; import android.os.UserManager; import android.util.ArrayMap; Loading @@ -35,6 +37,8 @@ public class MockSyntheticPasswordManager extends SyntheticPasswordManager { private FakeGateKeeperService mGateKeeper; private MockWeaverService mWeaverService; private IWeaver mWeaverAidl; private android.hardware.weaver.V1_0.IWeaver mWeaverHidl; public MockSyntheticPasswordManager(Context context, LockSettingsStorage storage, FakeGateKeeperService gatekeeper, UserManager userManager, Loading Loading @@ -112,13 +116,33 @@ public class MockSyntheticPasswordManager extends SyntheticPasswordManager { } } /** Enables MockWeaverService. */ public void enableWeaver() { enableWeaverAidl(); } /** Enables MockWeaverService with the current (AIDL) interface. */ public void enableWeaverAidl() { assertNull(mWeaverService); mWeaverService = new MockWeaverService(); mWeaverAidl = mWeaverService; } @Override protected IWeaver getWeaverHidlService() throws RemoteException { return mWeaverService; protected IWeaver getWeaverAidlService() { return mWeaverAidl; } public void enableWeaver() { /** Enables MockWeaverService with the old (HIDL) interface. */ public void enableWeaverHidl() { assertNull(mWeaverService); mWeaverService = new MockWeaverService(); mWeaverHidl = mWeaverService.asHidl(); } @Override protected android.hardware.weaver.V1_0.IWeaver getWeaverHidlService() throws RemoteException { return mWeaverHidl; } public int getSumOfWeaverFailureCounters() { Loading
services/tests/servicestests/src/com/android/server/locksettings/MockWeaverService.java +103 −21 Original line number Diff line number Diff line package com.android.server.locksettings; import android.hardware.weaver.V1_0.IWeaver; import android.hardware.weaver.V1_0.WeaverConfig; import android.hardware.weaver.V1_0.WeaverReadResponse; import android.hardware.weaver.V1_0.WeaverStatus; import static org.mockito.Mockito.mock; import android.hardware.weaver.IWeaver; import android.hardware.weaver.WeaverConfig; import android.hardware.weaver.WeaverReadResponse; import android.hardware.weaver.WeaverReadStatus; import android.os.IBinder; import android.os.RemoteException; import java.util.ArrayList; import java.util.Arrays; public class MockWeaverService extends IWeaver.Stub { public class MockWeaverService implements IWeaver { private static final int MAX_SLOTS = 8; private static final int KEY_LENGTH = 256 / 8; private static final int VALUE_LENGTH = 256 / 8; private static class WeaverSlot { public ArrayList<Byte> key; public ArrayList<Byte> value; public byte[] key; public byte[] value; public int failureCounter; } Loading @@ -30,46 +33,125 @@ public class MockWeaverService extends IWeaver.Stub { } @Override public void getConfig(getConfigCallback cb) throws RemoteException { public WeaverConfig getConfig() throws RemoteException { WeaverConfig config = new WeaverConfig(); config.keySize = KEY_LENGTH; config.valueSize = VALUE_LENGTH; config.slots = MAX_SLOTS; cb.onValues(WeaverStatus.OK, config); return config; } @Override public int write(int slotId, ArrayList<Byte> key, ArrayList<Byte> value) throws RemoteException { public void write(int slotId, byte[] key, byte[] value) throws RemoteException { if (slotId < 0 || slotId >= MAX_SLOTS) { throw new RuntimeException("Invalid slot id"); } WeaverSlot slot = mSlots[slotId]; slot.key = (ArrayList<Byte>) key.clone(); slot.value = (ArrayList<Byte>) value.clone(); slot.key = key.clone(); slot.value = value.clone(); slot.failureCounter = 0; return WeaverStatus.OK; } @Override public void read(int slotId, ArrayList<Byte> key, readCallback cb) throws RemoteException { public WeaverReadResponse read(int slotId, byte[] key) throws RemoteException { if (slotId < 0 || slotId >= MAX_SLOTS) { throw new RuntimeException("Invalid slot id"); } WeaverReadResponse response = new WeaverReadResponse(); WeaverSlot slot = mSlots[slotId]; if (key.equals(slot.key)) { response.value.addAll(slot.value); cb.onValues(WeaverStatus.OK, response); WeaverReadResponse response = new WeaverReadResponse(); if (Arrays.equals(key, slot.key)) { response.value = slot.value.clone(); response.status = WeaverReadStatus.OK; slot.failureCounter = 0; } else { cb.onValues(WeaverStatus.FAILED, response); response.status = WeaverReadStatus.INCORRECT_KEY; slot.failureCounter++; } return response; } @Override public String getInterfaceHash() { throw new UnsupportedOperationException(); } @Override public int getInterfaceVersion() { return 2; } @Override public IBinder asBinder() { return mock(IBinder.class); } public int getSumOfFailureCounters() { return Arrays.stream(mSlots).mapToInt(slot -> slot.failureCounter).sum(); } /** Returns an adapter object that implements the old (HIDL) Weaver interface. */ public android.hardware.weaver.V1_0.IWeaver.Stub asHidl() { return new MockWeaverServiceHidlAdapter(); } private class MockWeaverServiceHidlAdapter extends android.hardware.weaver.V1_0.IWeaver.Stub { @Override public void getConfig(getConfigCallback cb) throws RemoteException { WeaverConfig aidlConfig = MockWeaverService.this.getConfig(); android.hardware.weaver.V1_0.WeaverConfig hidlConfig = new android.hardware.weaver.V1_0.WeaverConfig(); hidlConfig.keySize = aidlConfig.keySize; hidlConfig.valueSize = aidlConfig.valueSize; hidlConfig.slots = aidlConfig.slots; cb.onValues(android.hardware.weaver.V1_0.WeaverStatus.OK, hidlConfig); } @SuppressWarnings("NonApiType") @Override public int write(int slotId, ArrayList<Byte> key, ArrayList<Byte> value) throws RemoteException { MockWeaverService.this.write(slotId, fromByteArrayList(key), fromByteArrayList(value)); return android.hardware.weaver.V1_0.WeaverStatus.OK; } @SuppressWarnings("NonApiType") @Override public void read(int slotId, ArrayList<Byte> key, readCallback cb) throws RemoteException { WeaverReadResponse aidlResponse = MockWeaverService.this.read(slotId, fromByteArrayList(key)); android.hardware.weaver.V1_0.WeaverReadResponse hidlResponse = new android.hardware.weaver.V1_0.WeaverReadResponse(); int hidlStatus = switch (aidlResponse.status) { case WeaverReadStatus.OK -> android.hardware.weaver.V1_0.WeaverStatus.OK; case WeaverReadStatus.INCORRECT_KEY -> android.hardware.weaver.V1_0.WeaverReadStatus.INCORRECT_KEY; case WeaverReadStatus.THROTTLE -> android.hardware.weaver.V1_0.WeaverReadStatus.THROTTLE; default -> android.hardware.weaver.V1_0.WeaverStatus.FAILED; }; if (aidlResponse.value != null) { hidlResponse.value = toByteArrayList(aidlResponse.value); } cb.onValues(hidlStatus, hidlResponse); } @SuppressWarnings("NonApiType") private static ArrayList<Byte> toByteArrayList(byte[] data) { ArrayList<Byte> result = new ArrayList<Byte>(data.length); for (int i = 0; i < data.length; i++) { result.add(data[i]); } return result; } @SuppressWarnings("NonApiType") private static byte[] fromByteArrayList(ArrayList<Byte> data) { byte[] result = new byte[data.size()]; for (int i = 0; i < data.size(); i++) { result[i] = data.get(i); } return result; } } }
services/tests/servicestests/src/com/android/server/locksettings/WeaverAidlBasedSyntheticPasswordTests.java 0 → 100644 +35 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 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.server.locksettings; import android.platform.test.annotations.Presubmit; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; import org.junit.Before; import org.junit.runner.RunWith; @SmallTest @Presubmit @RunWith(AndroidJUnit4.class) public class WeaverAidlBasedSyntheticPasswordTests extends WeaverBasedSyntheticPasswordTests { @Before public void setup() { mSpManager.enableWeaverAidl(); } }
services/tests/servicestests/src/com/android/server/locksettings/WeaverBasedSyntheticPasswordTests.java +1 −16 Original line number Diff line number Diff line Loading @@ -6,28 +6,13 @@ import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.when; import android.platform.test.annotations.Presubmit; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; import com.android.server.locksettings.LockSettingsStorage.PersistentData; import com.google.android.collect.Sets; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @SmallTest @Presubmit @RunWith(AndroidJUnit4.class) public class WeaverBasedSyntheticPasswordTests extends SyntheticPasswordTests { @Before public void enableWeaver() throws Exception { mSpManager.enableWeaver(); } public abstract class WeaverBasedSyntheticPasswordTests extends SyntheticPasswordTests { // Tests that if the device is not yet provisioned and the FRP credential uses Weaver, then the // Weaver slot of the FRP credential is not reused. Assumes that Weaver slots are allocated Loading