Check user unlocked before write to /data/system_ce/0/snapshots

When reboot device. TaskSnapshotPersister create directory
"/data/system_ce/0/snapshots" before FBE decrypt.
Then WTF occur.

Bug: 154787951
Test: Device boots without WTF error
Change-Id: Ie9d4a28008adc93e27bc8ab015a3a6507428c3e4
This commit is contained in:
Guo Li
2020-04-23 21:39:01 +08:00
committed by Peter Kalauskas
parent aea56520a4
commit 2f9987f507
2 changed files with 50 additions and 4 deletions

View File

@@ -28,12 +28,14 @@ import android.graphics.Bitmap;
import android.graphics.Bitmap.Config; import android.graphics.Bitmap.Config;
import android.os.Process; import android.os.Process;
import android.os.SystemClock; import android.os.SystemClock;
import android.os.UserManagerInternal;
import android.util.ArraySet; import android.util.ArraySet;
import android.util.AtomicFile; import android.util.AtomicFile;
import android.util.Slog; import android.util.Slog;
import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting;
import com.android.server.LocalServices;
import com.android.server.wm.nano.WindowManagerProtos.TaskSnapshotProto; import com.android.server.wm.nano.WindowManagerProtos.TaskSnapshotProto;
import java.io.File; import java.io.File;
@@ -72,6 +74,7 @@ class TaskSnapshotPersister {
private final float mLowResScaleFactor; private final float mLowResScaleFactor;
private boolean mEnableLowResSnapshots; private boolean mEnableLowResSnapshots;
private final boolean mUse16BitFormat; private final boolean mUse16BitFormat;
private final UserManagerInternal mUserManagerInternal;
/** /**
* The list of ids of the tasks that have been persisted since {@link #removeObsoleteFiles} was * The list of ids of the tasks that have been persisted since {@link #removeObsoleteFiles} was
@@ -82,6 +85,8 @@ class TaskSnapshotPersister {
TaskSnapshotPersister(WindowManagerService service, DirectoryResolver resolver) { TaskSnapshotPersister(WindowManagerService service, DirectoryResolver resolver) {
mDirectoryResolver = resolver; mDirectoryResolver = resolver;
mUserManagerInternal = LocalServices.getService(UserManagerInternal.class);
final float highResTaskSnapshotScale = service.mContext.getResources().getFloat( final float highResTaskSnapshotScale = service.mContext.getResources().getFloat(
com.android.internal.R.dimen.config_highResTaskSnapshotScale); com.android.internal.R.dimen.config_highResTaskSnapshotScale);
final float lowResTaskSnapshotScale = service.mContext.getResources().getFloat( final float lowResTaskSnapshotScale = service.mContext.getResources().getFloat(
@@ -191,7 +196,7 @@ class TaskSnapshotPersister {
return; return;
} }
} }
SystemClock.sleep(100); SystemClock.sleep(DELAY_MS);
} }
} }
@@ -233,7 +238,7 @@ class TaskSnapshotPersister {
private boolean createDirectory(int userId) { private boolean createDirectory(int userId) {
final File dir = getDirectory(userId); final File dir = getDirectory(userId);
return dir.exists() || dir.mkdirs(); return dir.exists() || dir.mkdir();
} }
private void deleteSnapshot(int taskId, int userId) { private void deleteSnapshot(int taskId, int userId) {
@@ -258,18 +263,26 @@ class TaskSnapshotPersister {
android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
while (true) { while (true) {
WriteQueueItem next; WriteQueueItem next;
boolean isReadyToWrite = false;
synchronized (mLock) { synchronized (mLock) {
if (mPaused) { if (mPaused) {
next = null; next = null;
} else { } else {
next = mWriteQueue.poll(); next = mWriteQueue.poll();
if (next != null) { if (next != null) {
next.onDequeuedLocked(); if (next.isReady()) {
isReadyToWrite = true;
next.onDequeuedLocked();
} else {
mWriteQueue.addLast(next);
}
} }
} }
} }
if (next != null) { if (next != null) {
next.write(); if (isReadyToWrite) {
next.write();
}
SystemClock.sleep(DELAY_MS); SystemClock.sleep(DELAY_MS);
} }
synchronized (mLock) { synchronized (mLock) {
@@ -289,6 +302,13 @@ class TaskSnapshotPersister {
}; };
private abstract class WriteQueueItem { private abstract class WriteQueueItem {
/**
* @return {@code true} if item is ready to have {@link WriteQueueItem#write} called
*/
boolean isReady() {
return true;
}
abstract void write(); abstract void write();
/** /**
@@ -327,6 +347,11 @@ class TaskSnapshotPersister {
mStoreQueueItems.remove(this); mStoreQueueItems.remove(this);
} }
@Override
boolean isReady() {
return mUserManagerInternal.isUserUnlocked(mUserId);
}
@Override @Override
void write() { void write() {
if (!createDirectory(mUserId)) { if (!createDirectory(mUserId)) {

View File

@@ -24,6 +24,7 @@ import static android.graphics.GraphicBuffer.USAGE_SW_READ_RARELY;
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy; import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
@@ -39,10 +40,15 @@ import android.graphics.PixelFormat;
import android.graphics.Point; import android.graphics.Point;
import android.graphics.Rect; import android.graphics.Rect;
import android.os.UserManager; import android.os.UserManager;
import android.os.UserManagerInternal;
import android.view.Surface; import android.view.Surface;
import com.android.server.LocalServices;
import org.junit.After; import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before; import org.junit.Before;
import org.junit.BeforeClass;
import java.io.File; import java.io.File;
import java.util.function.Predicate; import java.util.function.Predicate;
@@ -70,11 +76,26 @@ class TaskSnapshotPersisterTestBase extends WindowTestsBase {
mLowResScale = lowResScale; mLowResScale = lowResScale;
} }
@BeforeClass
public static void setUpOnce() {
final UserManagerInternal userManager = mock(UserManagerInternal.class);
LocalServices.addService(UserManagerInternal.class, userManager);
}
@AfterClass
public static void tearDownOnce() {
LocalServices.removeServiceForTest(UserManagerInternal.class);
}
@Before @Before
public void setUp() { public void setUp() {
final UserManager um = UserManager.get(getInstrumentation().getTargetContext()); final UserManager um = UserManager.get(getInstrumentation().getTargetContext());
mTestUserId = um.getUserHandle(); mTestUserId = um.getUserHandle();
final UserManagerInternal userManagerInternal =
LocalServices.getService(UserManagerInternal.class);
when(userManagerInternal.isUserUnlocked(mTestUserId)).thenReturn(true);
mContextSpy = spy(new ContextWrapper(mWm.mContext)); mContextSpy = spy(new ContextWrapper(mWm.mContext));
mResourcesSpy = spy(mContextSpy.getResources()); mResourcesSpy = spy(mContextSpy.getResources());
when(mContextSpy.getResources()).thenReturn(mResourcesSpy); when(mContextSpy.getResources()).thenReturn(mResourcesSpy);