Load /metadata/password_slots/slot_map lazily.
This fixes a 6ms regression in SystemServerTiming_MakeLockSettingsServiceReady, since the slot map is only needed when adding or removing a PIN. Bug: 128334055 Test: atest frameworks/base/services/tests/servicestests/src/com/android/server/locksettings Test: atest PasswordSlotManagerTests Test: atest google/perf/boottime/boottime-test Test: PIN unlocks device after booting into GSI Change-Id: Ib2e0c05575d07496792188716b962ca622df28e6
This commit is contained in:
@@ -52,10 +52,12 @@ public class PasswordSlotManager {
|
|||||||
// This maps each used password slot to the OS image that created it. Password slots are
|
// This maps each used password slot to the OS image that created it. Password slots are
|
||||||
// integer keys/indices into secure storage. The OS image is recorded as a string. The factory
|
// integer keys/indices into secure storage. The OS image is recorded as a string. The factory
|
||||||
// image is "host" and GSIs are "gsi<N>" where N >= 1.
|
// image is "host" and GSIs are "gsi<N>" where N >= 1.
|
||||||
private final Map<Integer, String> mSlotMap;
|
private Map<Integer, String> mSlotMap;
|
||||||
|
|
||||||
|
// Cache the active slots until loadSlotMap() is called.
|
||||||
|
private Set<Integer> mActiveSlots;
|
||||||
|
|
||||||
public PasswordSlotManager() {
|
public PasswordSlotManager() {
|
||||||
mSlotMap = loadSlotMap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
@@ -74,6 +76,11 @@ public class PasswordSlotManager {
|
|||||||
* @throws RuntimeException
|
* @throws RuntimeException
|
||||||
*/
|
*/
|
||||||
public void refreshActiveSlots(Set<Integer> activeSlots) throws RuntimeException {
|
public void refreshActiveSlots(Set<Integer> activeSlots) throws RuntimeException {
|
||||||
|
if (mSlotMap == null) {
|
||||||
|
mActiveSlots = new HashSet<Integer>(activeSlots);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Update which slots are owned by the current image.
|
// Update which slots are owned by the current image.
|
||||||
final HashSet<Integer> slotsToDelete = new HashSet<Integer>();
|
final HashSet<Integer> slotsToDelete = new HashSet<Integer>();
|
||||||
for (Map.Entry<Integer, String> entry : mSlotMap.entrySet()) {
|
for (Map.Entry<Integer, String> entry : mSlotMap.entrySet()) {
|
||||||
@@ -100,6 +107,7 @@ public class PasswordSlotManager {
|
|||||||
* @throws RuntimeException
|
* @throws RuntimeException
|
||||||
*/
|
*/
|
||||||
public void markSlotInUse(int slot) throws RuntimeException {
|
public void markSlotInUse(int slot) throws RuntimeException {
|
||||||
|
ensureSlotMapLoaded();
|
||||||
if (mSlotMap.containsKey(slot) && !mSlotMap.get(slot).equals(getMode())) {
|
if (mSlotMap.containsKey(slot) && !mSlotMap.get(slot).equals(getMode())) {
|
||||||
throw new RuntimeException("password slot " + slot + " is not available");
|
throw new RuntimeException("password slot " + slot + " is not available");
|
||||||
}
|
}
|
||||||
@@ -113,6 +121,7 @@ public class PasswordSlotManager {
|
|||||||
* @throws RuntimeException
|
* @throws RuntimeException
|
||||||
*/
|
*/
|
||||||
public void markSlotDeleted(int slot) throws RuntimeException {
|
public void markSlotDeleted(int slot) throws RuntimeException {
|
||||||
|
ensureSlotMapLoaded();
|
||||||
if (mSlotMap.containsKey(slot) && mSlotMap.get(slot) != getMode()) {
|
if (mSlotMap.containsKey(slot) && mSlotMap.get(slot) != getMode()) {
|
||||||
throw new RuntimeException("password slot " + slot + " cannot be deleted");
|
throw new RuntimeException("password slot " + slot + " cannot be deleted");
|
||||||
}
|
}
|
||||||
@@ -126,6 +135,7 @@ public class PasswordSlotManager {
|
|||||||
* @return Integer set of all used slots.
|
* @return Integer set of all used slots.
|
||||||
*/
|
*/
|
||||||
public Set<Integer> getUsedSlots() {
|
public Set<Integer> getUsedSlots() {
|
||||||
|
ensureSlotMapLoaded();
|
||||||
return Collections.unmodifiableSet(mSlotMap.keySet());
|
return Collections.unmodifiableSet(mSlotMap.keySet());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,8 +177,21 @@ public class PasswordSlotManager {
|
|||||||
return new HashMap<Integer, String>();
|
return new HashMap<Integer, String>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ensureSlotMapLoaded() {
|
||||||
|
if (mSlotMap == null) {
|
||||||
|
mSlotMap = loadSlotMap();
|
||||||
|
if (mActiveSlots != null) {
|
||||||
|
refreshActiveSlots(mActiveSlots);
|
||||||
|
mActiveSlots = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
protected void saveSlotMap(OutputStream stream) throws IOException {
|
protected void saveSlotMap(OutputStream stream) throws IOException {
|
||||||
|
if (mSlotMap == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
final Properties props = new Properties();
|
final Properties props = new Properties();
|
||||||
for (Map.Entry<Integer, String> entry : mSlotMap.entrySet()) {
|
for (Map.Entry<Integer, String> entry : mSlotMap.entrySet()) {
|
||||||
props.setProperty(entry.getKey().toString(), entry.getValue());
|
props.setProperty(entry.getKey().toString(), entry.getValue());
|
||||||
@@ -177,6 +200,9 @@ public class PasswordSlotManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void saveSlotMap() {
|
private void saveSlotMap() {
|
||||||
|
if (mSlotMap == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (!getSlotMapFile().getParentFile().exists()) {
|
if (!getSlotMapFile().getParentFile().exists()) {
|
||||||
Slog.w(TAG, "Not saving slot map, " + getSlotMapDir() + " does not exist");
|
Slog.w(TAG, "Not saving slot map, " + getSlotMapDir() + " does not exist");
|
||||||
return;
|
return;
|
||||||
|
|||||||
Reference in New Issue
Block a user