diff options
| -rw-r--r-- | services/core/java/com/android/server/display/PersistentDataStore.java | 90 | ||||
| -rw-r--r-- | services/tests/servicestests/src/com/android/server/display/PersistentDataStoreTest.java | 13 |
2 files changed, 69 insertions, 34 deletions
diff --git a/services/core/java/com/android/server/display/PersistentDataStore.java b/services/core/java/com/android/server/display/PersistentDataStore.java index 2eba080e369e..4b93d8f42da3 100644 --- a/services/core/java/com/android/server/display/PersistentDataStore.java +++ b/services/core/java/com/android/server/display/PersistentDataStore.java @@ -20,6 +20,7 @@ import android.annotation.Nullable; import android.graphics.Point; import android.hardware.display.BrightnessConfiguration; import android.hardware.display.WifiDisplay; +import android.os.Handler; import android.util.AtomicFile; import android.util.Slog; import android.util.SparseArray; @@ -31,12 +32,14 @@ import android.util.Xml; import android.view.Display; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.os.BackgroundThread; import com.android.internal.util.XmlUtils; import libcore.io.IoUtils; import org.xmlpull.v1.XmlPullParserException; +import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; @@ -141,13 +144,22 @@ final class PersistentDataStore { // The interface for methods which should be replaced by the test harness. private Injector mInjector; + private final Handler mHandler; + private final Object mFileAccessLock = new Object(); + public PersistentDataStore() { this(new Injector()); } @VisibleForTesting PersistentDataStore(Injector injector) { + this(injector, BackgroundThread.getHandler()); + } + + @VisibleForTesting + PersistentDataStore(Injector injector, Handler handler) { mInjector = injector; + mHandler = handler; } public void saveIfNeeded() { @@ -418,45 +430,61 @@ final class PersistentDataStore { } private void load() { - clearState(); + synchronized (mFileAccessLock) { + clearState(); - final InputStream is; - try { - is = mInjector.openRead(); - } catch (FileNotFoundException ex) { - return; - } + final InputStream is; + try { + is = mInjector.openRead(); + } catch (FileNotFoundException ex) { + return; + } - TypedXmlPullParser parser; - try { - parser = Xml.resolvePullParser(is); - loadFromXml(parser); - } catch (IOException ex) { - Slog.w(TAG, "Failed to load display manager persistent store data.", ex); - clearState(); - } catch (XmlPullParserException ex) { - Slog.w(TAG, "Failed to load display manager persistent store data.", ex); - clearState(); - } finally { - IoUtils.closeQuietly(is); + TypedXmlPullParser parser; + try { + parser = Xml.resolvePullParser(is); + loadFromXml(parser); + } catch (IOException ex) { + Slog.w(TAG, "Failed to load display manager persistent store data.", ex); + clearState(); + } catch (XmlPullParserException ex) { + Slog.w(TAG, "Failed to load display manager persistent store data.", ex); + clearState(); + } finally { + IoUtils.closeQuietly(is); + } } } private void save() { - final OutputStream os; + final ByteArrayOutputStream os; try { - os = mInjector.startWrite(); - boolean success = false; - try { - TypedXmlSerializer serializer = Xml.resolveSerializer(os); - saveToXml(serializer); - serializer.flush(); - success = true; - } finally { - mInjector.finishWrite(os, success); - } + os = new ByteArrayOutputStream(); + + TypedXmlSerializer serializer = Xml.resolveSerializer(os); + saveToXml(serializer); + + mHandler.removeCallbacksAndMessages(/* token */ null); + mHandler.post(() -> { + synchronized (mFileAccessLock) { + OutputStream fileOutput = null; + try { + fileOutput = mInjector.startWrite(); + os.writeTo(fileOutput); + fileOutput.flush(); + } catch (IOException ex) { + Slog.w(TAG, "Failed to save display manager persistent store data.", ex); + } finally { + if (fileOutput != null) { + mInjector.finishWrite(fileOutput, true); + } + } + } + }); + + serializer.flush(); } catch (IOException ex) { - Slog.w(TAG, "Failed to save display manager persistent store data.", ex); + Slog.w(TAG, "Failed to process the XML serializer.", ex); } } diff --git a/services/tests/servicestests/src/com/android/server/display/PersistentDataStoreTest.java b/services/tests/servicestests/src/com/android/server/display/PersistentDataStoreTest.java index 57a9cb278c80..9fe8609c85a1 100644 --- a/services/tests/servicestests/src/com/android/server/display/PersistentDataStoreTest.java +++ b/services/tests/servicestests/src/com/android/server/display/PersistentDataStoreTest.java @@ -24,6 +24,8 @@ import static org.junit.Assert.assertTrue; import android.content.Context; import android.hardware.display.BrightnessConfiguration; +import android.os.Handler; +import android.os.test.TestLooper; import android.util.Pair; import androidx.test.InstrumentationRegistry; @@ -47,11 +49,14 @@ import java.nio.charset.StandardCharsets; public class PersistentDataStoreTest { private PersistentDataStore mDataStore; private TestInjector mInjector; + private TestLooper mTestLooper; @Before public void setUp() { mInjector = new TestInjector(); - mDataStore = new PersistentDataStore(mInjector); + mTestLooper = new TestLooper(); + Handler handler = new Handler(mTestLooper.getLooper()); + mDataStore = new PersistentDataStore(mInjector, handler); } @Test @@ -147,7 +152,7 @@ public class PersistentDataStoreTest { } @Test - public void testStoreAndReloadOfDisplayBrightnessConfigurations() { + public void testStoreAndReloadOfDisplayBrightnessConfigurations() throws InterruptedException { final String uniqueDisplayId = "test:123"; int userSerial = 0; String packageName = "pdsTestPackage"; @@ -178,6 +183,7 @@ public class PersistentDataStoreTest { final ByteArrayOutputStream baos = new ByteArrayOutputStream(); mInjector.setWriteStream(baos); mDataStore.saveIfNeeded(); + mTestLooper.dispatchAll(); assertTrue(mInjector.wasWriteSuccessful()); TestInjector newInjector = new TestInjector(); PersistentDataStore newDataStore = new PersistentDataStore(newInjector); @@ -222,7 +228,7 @@ public class PersistentDataStoreTest { } @Test - public void testStoreAndReloadOfBrightnessConfigurations() { + public void testStoreAndReloadOfBrightnessConfigurations() throws InterruptedException { final float[] lux = { 0f, 10f }; final float[] nits = {1f, 100f }; final BrightnessConfiguration config = new BrightnessConfiguration.Builder(lux, nits) @@ -238,6 +244,7 @@ public class PersistentDataStoreTest { final ByteArrayOutputStream baos = new ByteArrayOutputStream(); mInjector.setWriteStream(baos); mDataStore.saveIfNeeded(); + mTestLooper.dispatchAll(); assertTrue(mInjector.wasWriteSuccessful()); TestInjector newInjector = new TestInjector(); |