Loading services/core/java/com/android/server/wm/LaunchParamsPersister.java +163 −100 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import android.content.pm.ActivityInfo; import android.content.pm.PackageManagerInternal; import android.graphics.Rect; import android.os.Environment; import android.os.Process; import android.util.ArrayMap; import android.util.ArraySet; import android.util.AtomicFile; Loading Loading @@ -50,6 +51,9 @@ import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; import java.util.function.IntFunction; /** Loading Loading @@ -83,6 +87,12 @@ class LaunchParamsPersister { private PackageList mPackageList; /** * A map from user ID to the active {@link LoadingTask} when we're loading the launch params for * that user. */ private final SparseArray<LoadingTask> mLoadingTaskMap = new SparseArray<>(); /** * A dual layer map that first maps user ID to a secondary map, which maps component name (the * launching activity of tasks) to {@link PersistableLaunchParams} that stores launch metadata Loading Loading @@ -117,113 +127,33 @@ class LaunchParamsPersister { } void onUnlockUser(int userId) { loadLaunchParams(userId); } void onCleanupUser(int userId) { mLaunchParamsMap.remove(userId); } private void loadLaunchParams(int userId) { final List<File> filesToDelete = new ArrayList<>(); final File launchParamsFolder = getLaunchParamFolder(userId); if (!launchParamsFolder.isDirectory()) { Slog.i(TAG, "Didn't find launch param folder for user " + userId); if (mLoadingTaskMap.contains(userId)) { Slog.e(TAG, "Duplicated onUnlockUser " + userId); return; } final Set<String> packages = new ArraySet<>(mPackageList.getPackageNames()); final File[] paramsFiles = launchParamsFolder.listFiles(); final ArrayMap<ComponentName, PersistableLaunchParams> map = new ArrayMap<>(paramsFiles.length); mLaunchParamsMap.put(userId, map); for (File paramsFile : paramsFiles) { if (!paramsFile.isFile()) { Slog.w(TAG, paramsFile.getAbsolutePath() + " is not a file."); continue; } if (!paramsFile.getName().endsWith(LAUNCH_PARAMS_FILE_SUFFIX)) { Slog.w(TAG, "Unexpected params file name: " + paramsFile.getName()); filesToDelete.add(paramsFile); continue; } String paramsFileName = paramsFile.getName(); // Migrate all records from old separator to new separator. final int oldSeparatorIndex = paramsFileName.indexOf(OLD_ESCAPED_COMPONENT_SEPARATOR); if (oldSeparatorIndex != -1) { if (paramsFileName.indexOf( OLD_ESCAPED_COMPONENT_SEPARATOR, oldSeparatorIndex + 1) != -1) { // Rare case. We have more than one old escaped component separator probably // because this app uses underscore in their package name. We can't distinguish // which one is the real separator so let's skip it. filesToDelete.add(paramsFile); continue; } paramsFileName = paramsFileName.replace( OLD_ESCAPED_COMPONENT_SEPARATOR, ESCAPED_COMPONENT_SEPARATOR); final File newFile = new File(launchParamsFolder, paramsFileName); if (paramsFile.renameTo(newFile)) { paramsFile = newFile; } else { // Rare case. For some reason we can't rename the file. Let's drop this record // instead. filesToDelete.add(paramsFile); continue; } } final String componentNameString = paramsFileName.substring( 0 /* beginIndex */, paramsFileName.length() - LAUNCH_PARAMS_FILE_SUFFIX.length()) .replace(ESCAPED_COMPONENT_SEPARATOR, ORIGINAL_COMPONENT_SEPARATOR); final ComponentName name = ComponentName.unflattenFromString( componentNameString); if (name == null) { Slog.w(TAG, "Unexpected file name: " + paramsFileName); filesToDelete.add(paramsFile); continue; } if (!packages.contains(name.getPackageName())) { // Rare case. PersisterQueue doesn't have a chance to remove files for removed // packages last time. filesToDelete.add(paramsFile); continue; } try (InputStream in = new FileInputStream(paramsFile)) { final PersistableLaunchParams params = new PersistableLaunchParams(); final TypedXmlPullParser parser = Xml.resolvePullParser(in); int event; while ((event = parser.next()) != XmlPullParser.END_DOCUMENT && event != XmlPullParser.END_TAG) { if (event != XmlPullParser.START_TAG) { continue; } final String tagName = parser.getName(); if (!TAG_LAUNCH_PARAMS.equals(tagName)) { Slog.w(TAG, "Unexpected tag name: " + tagName); continue; final LoadingTask task = new LoadingTask(userId); mLoadingTaskMap.put(userId, task); task.execute(); } params.restore(paramsFile, parser); void onCleanupUser(int userId) { // There is no need to abort the task itself. Just let the loading task finish silently // without modifying any state. mLoadingTaskMap.remove(userId); mLaunchParamsMap.remove(userId); } map.put(name, params); addComponentNameToLaunchParamAffinityMapIfNotNull( name, params.mWindowLayoutAffinity); } catch (Exception e) { Slog.w(TAG, "Failed to restore launch params for " + name, e); filesToDelete.add(paramsFile); } private void waitAndMoveResultIfLoading(int userId) { final LoadingTask task = mLoadingTaskMap.removeReturnOld(userId); if (task == null) { return; } if (!filesToDelete.isEmpty()) { mPersisterQueue.addItem(new CleanUpComponentQueueItem(filesToDelete), true); final ArrayMap<ComponentName, PersistableLaunchParams> map = task.get(); if (map == null) { return; } mLaunchParamsMap.put(userId, map); } void saveTask(Task task) { Loading @@ -236,6 +166,7 @@ class LaunchParamsPersister { return; } final int userId = task.mUserId; waitAndMoveResultIfLoading(userId); PersistableLaunchParams params; ArrayMap<ComponentName, PersistableLaunchParams> map = mLaunchParamsMap.get(userId); if (map == null) { Loading Loading @@ -297,6 +228,7 @@ class LaunchParamsPersister { void getLaunchParams(Task task, ActivityRecord activity, LaunchParams outParams) { final ComponentName name = task != null ? task.realActivity : activity.mActivityComponent; final int userId = task != null ? task.mUserId : activity.mUserId; waitAndMoveResultIfLoading(userId); final String windowLayoutAffinity; if (task != null) { windowLayoutAffinity = task.mWindowLayoutAffinity; Loading Loading @@ -394,6 +326,137 @@ class LaunchParamsPersister { } } private class LoadingTask implements Callable<ArrayMap<ComponentName, PersistableLaunchParams>> { private final int mUserId; private final FutureTask<ArrayMap<ComponentName, PersistableLaunchParams>> mFutureTask; private LoadingTask(int userId) { mUserId = userId; mFutureTask = new FutureTask<>(this); } private void execute() { new Thread(mFutureTask).start(); } private ArrayMap<ComponentName, PersistableLaunchParams> get() { try { return mFutureTask.get(); } catch (InterruptedException e) { throw new RuntimeException(e); } catch (ExecutionException e) { Slog.e(TAG, "Failed to load launch params for user#" + mUserId, e); return null; } } @Override public ArrayMap<ComponentName, PersistableLaunchParams> call() { Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); final List<File> filesToDelete = new ArrayList<>(); final File launchParamsFolder = getLaunchParamFolder(mUserId); if (!launchParamsFolder.isDirectory()) { Slog.i(TAG, "Didn't find launch param folder for user " + mUserId); return null; } final Set<String> packages = new ArraySet<>(mPackageList.getPackageNames()); final File[] paramsFiles = launchParamsFolder.listFiles(); final ArrayMap<ComponentName, PersistableLaunchParams> map = new ArrayMap<>(paramsFiles.length); for (File paramsFile : paramsFiles) { if (!paramsFile.isFile()) { Slog.w(TAG, paramsFile.getAbsolutePath() + " is not a file."); continue; } if (!paramsFile.getName().endsWith(LAUNCH_PARAMS_FILE_SUFFIX)) { Slog.w(TAG, "Unexpected params file name: " + paramsFile.getName()); filesToDelete.add(paramsFile); continue; } String paramsFileName = paramsFile.getName(); // Migrate all records from old separator to new separator. final int oldSeparatorIndex = paramsFileName.indexOf(OLD_ESCAPED_COMPONENT_SEPARATOR); if (oldSeparatorIndex != -1) { if (paramsFileName.indexOf( OLD_ESCAPED_COMPONENT_SEPARATOR, oldSeparatorIndex + 1) != -1) { // Rare case. We have more than one old escaped component separator probably // because this app uses underscore in their package name. We can't // distinguish which one is the real separator so let's skip it. filesToDelete.add(paramsFile); continue; } paramsFileName = paramsFileName.replace( OLD_ESCAPED_COMPONENT_SEPARATOR, ESCAPED_COMPONENT_SEPARATOR); final File newFile = new File(launchParamsFolder, paramsFileName); if (paramsFile.renameTo(newFile)) { paramsFile = newFile; } else { // Rare case. For some reason we can't rename the file. Let's drop this // record instead. filesToDelete.add(paramsFile); continue; } } final String componentNameString = paramsFileName.substring( 0 /* beginIndex */, paramsFileName.length() - LAUNCH_PARAMS_FILE_SUFFIX.length()) .replace(ESCAPED_COMPONENT_SEPARATOR, ORIGINAL_COMPONENT_SEPARATOR); final ComponentName name = ComponentName.unflattenFromString( componentNameString); if (name == null) { Slog.w(TAG, "Unexpected file name: " + paramsFileName); filesToDelete.add(paramsFile); continue; } if (!packages.contains(name.getPackageName())) { // Rare case. PersisterQueue doesn't have a chance to remove files for removed // packages last time. filesToDelete.add(paramsFile); continue; } try (InputStream in = new FileInputStream(paramsFile)) { final PersistableLaunchParams params = new PersistableLaunchParams(); final TypedXmlPullParser parser = Xml.resolvePullParser(in); int event; while ((event = parser.next()) != XmlPullParser.END_DOCUMENT && event != XmlPullParser.END_TAG) { if (event != XmlPullParser.START_TAG) { continue; } final String tagName = parser.getName(); if (!TAG_LAUNCH_PARAMS.equals(tagName)) { Slog.w(TAG, "Unexpected tag name: " + tagName); continue; } params.restore(paramsFile, parser); } map.put(name, params); addComponentNameToLaunchParamAffinityMapIfNotNull( name, params.mWindowLayoutAffinity); } catch (Exception e) { Slog.w(TAG, "Failed to restore launch params for " + name, e); filesToDelete.add(paramsFile); } } if (!filesToDelete.isEmpty()) { mPersisterQueue.addItem(new CleanUpComponentQueueItem(filesToDelete), true); } return map; } } private class LaunchParamsWriteQueueItem implements PersisterQueue.WriteQueueItem<LaunchParamsWriteQueueItem> { private final int mUserId; Loading Loading @@ -466,7 +529,7 @@ class LaunchParamsPersister { } } private class CleanUpComponentQueueItem implements PersisterQueue.WriteQueueItem { private static class CleanUpComponentQueueItem implements PersisterQueue.WriteQueueItem { private final List<File> mComponentFiles; private CleanUpComponentQueueItem(List<File> componentFiles) { Loading @@ -483,7 +546,7 @@ class LaunchParamsPersister { } } private class PersistableLaunchParams { private static class PersistableLaunchParams { private static final String ATTR_WINDOWING_MODE = "windowing_mode"; private static final String ATTR_DISPLAY_UNIQUE_ID = "display_unique_id"; private static final String ATTR_BOUNDS = "bounds"; Loading services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java +15 −0 Original line number Diff line number Diff line Loading @@ -494,6 +494,21 @@ public class LaunchParamsPersisterTests extends WindowTestsBase { assertTrue("Result should be empty.", mResult.isEmpty()); } @Test public void testAbortsLoadingWhenUserCleansUpBeforeLoadingFinishes() { mTarget.saveTask(mTestTask); mPersisterQueue.flush(); final LaunchParamsPersister target = new LaunchParamsPersister(mPersisterQueue, mSupervisor, mUserFolderGetter); target.onSystemReady(); target.onUnlockUser(TEST_USER_ID); target.onCleanupUser(TEST_USER_ID); target.getLaunchParams(mTestTask, null, mResult); assertTrue("Result should be empty.", mResult.isEmpty()); } private static boolean deleteRecursively(File file) { boolean result = true; if (file.isDirectory()) { Loading Loading
services/core/java/com/android/server/wm/LaunchParamsPersister.java +163 −100 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import android.content.pm.ActivityInfo; import android.content.pm.PackageManagerInternal; import android.graphics.Rect; import android.os.Environment; import android.os.Process; import android.util.ArrayMap; import android.util.ArraySet; import android.util.AtomicFile; Loading Loading @@ -50,6 +51,9 @@ import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; import java.util.function.IntFunction; /** Loading Loading @@ -83,6 +87,12 @@ class LaunchParamsPersister { private PackageList mPackageList; /** * A map from user ID to the active {@link LoadingTask} when we're loading the launch params for * that user. */ private final SparseArray<LoadingTask> mLoadingTaskMap = new SparseArray<>(); /** * A dual layer map that first maps user ID to a secondary map, which maps component name (the * launching activity of tasks) to {@link PersistableLaunchParams} that stores launch metadata Loading Loading @@ -117,113 +127,33 @@ class LaunchParamsPersister { } void onUnlockUser(int userId) { loadLaunchParams(userId); } void onCleanupUser(int userId) { mLaunchParamsMap.remove(userId); } private void loadLaunchParams(int userId) { final List<File> filesToDelete = new ArrayList<>(); final File launchParamsFolder = getLaunchParamFolder(userId); if (!launchParamsFolder.isDirectory()) { Slog.i(TAG, "Didn't find launch param folder for user " + userId); if (mLoadingTaskMap.contains(userId)) { Slog.e(TAG, "Duplicated onUnlockUser " + userId); return; } final Set<String> packages = new ArraySet<>(mPackageList.getPackageNames()); final File[] paramsFiles = launchParamsFolder.listFiles(); final ArrayMap<ComponentName, PersistableLaunchParams> map = new ArrayMap<>(paramsFiles.length); mLaunchParamsMap.put(userId, map); for (File paramsFile : paramsFiles) { if (!paramsFile.isFile()) { Slog.w(TAG, paramsFile.getAbsolutePath() + " is not a file."); continue; } if (!paramsFile.getName().endsWith(LAUNCH_PARAMS_FILE_SUFFIX)) { Slog.w(TAG, "Unexpected params file name: " + paramsFile.getName()); filesToDelete.add(paramsFile); continue; } String paramsFileName = paramsFile.getName(); // Migrate all records from old separator to new separator. final int oldSeparatorIndex = paramsFileName.indexOf(OLD_ESCAPED_COMPONENT_SEPARATOR); if (oldSeparatorIndex != -1) { if (paramsFileName.indexOf( OLD_ESCAPED_COMPONENT_SEPARATOR, oldSeparatorIndex + 1) != -1) { // Rare case. We have more than one old escaped component separator probably // because this app uses underscore in their package name. We can't distinguish // which one is the real separator so let's skip it. filesToDelete.add(paramsFile); continue; } paramsFileName = paramsFileName.replace( OLD_ESCAPED_COMPONENT_SEPARATOR, ESCAPED_COMPONENT_SEPARATOR); final File newFile = new File(launchParamsFolder, paramsFileName); if (paramsFile.renameTo(newFile)) { paramsFile = newFile; } else { // Rare case. For some reason we can't rename the file. Let's drop this record // instead. filesToDelete.add(paramsFile); continue; } } final String componentNameString = paramsFileName.substring( 0 /* beginIndex */, paramsFileName.length() - LAUNCH_PARAMS_FILE_SUFFIX.length()) .replace(ESCAPED_COMPONENT_SEPARATOR, ORIGINAL_COMPONENT_SEPARATOR); final ComponentName name = ComponentName.unflattenFromString( componentNameString); if (name == null) { Slog.w(TAG, "Unexpected file name: " + paramsFileName); filesToDelete.add(paramsFile); continue; } if (!packages.contains(name.getPackageName())) { // Rare case. PersisterQueue doesn't have a chance to remove files for removed // packages last time. filesToDelete.add(paramsFile); continue; } try (InputStream in = new FileInputStream(paramsFile)) { final PersistableLaunchParams params = new PersistableLaunchParams(); final TypedXmlPullParser parser = Xml.resolvePullParser(in); int event; while ((event = parser.next()) != XmlPullParser.END_DOCUMENT && event != XmlPullParser.END_TAG) { if (event != XmlPullParser.START_TAG) { continue; } final String tagName = parser.getName(); if (!TAG_LAUNCH_PARAMS.equals(tagName)) { Slog.w(TAG, "Unexpected tag name: " + tagName); continue; final LoadingTask task = new LoadingTask(userId); mLoadingTaskMap.put(userId, task); task.execute(); } params.restore(paramsFile, parser); void onCleanupUser(int userId) { // There is no need to abort the task itself. Just let the loading task finish silently // without modifying any state. mLoadingTaskMap.remove(userId); mLaunchParamsMap.remove(userId); } map.put(name, params); addComponentNameToLaunchParamAffinityMapIfNotNull( name, params.mWindowLayoutAffinity); } catch (Exception e) { Slog.w(TAG, "Failed to restore launch params for " + name, e); filesToDelete.add(paramsFile); } private void waitAndMoveResultIfLoading(int userId) { final LoadingTask task = mLoadingTaskMap.removeReturnOld(userId); if (task == null) { return; } if (!filesToDelete.isEmpty()) { mPersisterQueue.addItem(new CleanUpComponentQueueItem(filesToDelete), true); final ArrayMap<ComponentName, PersistableLaunchParams> map = task.get(); if (map == null) { return; } mLaunchParamsMap.put(userId, map); } void saveTask(Task task) { Loading @@ -236,6 +166,7 @@ class LaunchParamsPersister { return; } final int userId = task.mUserId; waitAndMoveResultIfLoading(userId); PersistableLaunchParams params; ArrayMap<ComponentName, PersistableLaunchParams> map = mLaunchParamsMap.get(userId); if (map == null) { Loading Loading @@ -297,6 +228,7 @@ class LaunchParamsPersister { void getLaunchParams(Task task, ActivityRecord activity, LaunchParams outParams) { final ComponentName name = task != null ? task.realActivity : activity.mActivityComponent; final int userId = task != null ? task.mUserId : activity.mUserId; waitAndMoveResultIfLoading(userId); final String windowLayoutAffinity; if (task != null) { windowLayoutAffinity = task.mWindowLayoutAffinity; Loading Loading @@ -394,6 +326,137 @@ class LaunchParamsPersister { } } private class LoadingTask implements Callable<ArrayMap<ComponentName, PersistableLaunchParams>> { private final int mUserId; private final FutureTask<ArrayMap<ComponentName, PersistableLaunchParams>> mFutureTask; private LoadingTask(int userId) { mUserId = userId; mFutureTask = new FutureTask<>(this); } private void execute() { new Thread(mFutureTask).start(); } private ArrayMap<ComponentName, PersistableLaunchParams> get() { try { return mFutureTask.get(); } catch (InterruptedException e) { throw new RuntimeException(e); } catch (ExecutionException e) { Slog.e(TAG, "Failed to load launch params for user#" + mUserId, e); return null; } } @Override public ArrayMap<ComponentName, PersistableLaunchParams> call() { Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); final List<File> filesToDelete = new ArrayList<>(); final File launchParamsFolder = getLaunchParamFolder(mUserId); if (!launchParamsFolder.isDirectory()) { Slog.i(TAG, "Didn't find launch param folder for user " + mUserId); return null; } final Set<String> packages = new ArraySet<>(mPackageList.getPackageNames()); final File[] paramsFiles = launchParamsFolder.listFiles(); final ArrayMap<ComponentName, PersistableLaunchParams> map = new ArrayMap<>(paramsFiles.length); for (File paramsFile : paramsFiles) { if (!paramsFile.isFile()) { Slog.w(TAG, paramsFile.getAbsolutePath() + " is not a file."); continue; } if (!paramsFile.getName().endsWith(LAUNCH_PARAMS_FILE_SUFFIX)) { Slog.w(TAG, "Unexpected params file name: " + paramsFile.getName()); filesToDelete.add(paramsFile); continue; } String paramsFileName = paramsFile.getName(); // Migrate all records from old separator to new separator. final int oldSeparatorIndex = paramsFileName.indexOf(OLD_ESCAPED_COMPONENT_SEPARATOR); if (oldSeparatorIndex != -1) { if (paramsFileName.indexOf( OLD_ESCAPED_COMPONENT_SEPARATOR, oldSeparatorIndex + 1) != -1) { // Rare case. We have more than one old escaped component separator probably // because this app uses underscore in their package name. We can't // distinguish which one is the real separator so let's skip it. filesToDelete.add(paramsFile); continue; } paramsFileName = paramsFileName.replace( OLD_ESCAPED_COMPONENT_SEPARATOR, ESCAPED_COMPONENT_SEPARATOR); final File newFile = new File(launchParamsFolder, paramsFileName); if (paramsFile.renameTo(newFile)) { paramsFile = newFile; } else { // Rare case. For some reason we can't rename the file. Let's drop this // record instead. filesToDelete.add(paramsFile); continue; } } final String componentNameString = paramsFileName.substring( 0 /* beginIndex */, paramsFileName.length() - LAUNCH_PARAMS_FILE_SUFFIX.length()) .replace(ESCAPED_COMPONENT_SEPARATOR, ORIGINAL_COMPONENT_SEPARATOR); final ComponentName name = ComponentName.unflattenFromString( componentNameString); if (name == null) { Slog.w(TAG, "Unexpected file name: " + paramsFileName); filesToDelete.add(paramsFile); continue; } if (!packages.contains(name.getPackageName())) { // Rare case. PersisterQueue doesn't have a chance to remove files for removed // packages last time. filesToDelete.add(paramsFile); continue; } try (InputStream in = new FileInputStream(paramsFile)) { final PersistableLaunchParams params = new PersistableLaunchParams(); final TypedXmlPullParser parser = Xml.resolvePullParser(in); int event; while ((event = parser.next()) != XmlPullParser.END_DOCUMENT && event != XmlPullParser.END_TAG) { if (event != XmlPullParser.START_TAG) { continue; } final String tagName = parser.getName(); if (!TAG_LAUNCH_PARAMS.equals(tagName)) { Slog.w(TAG, "Unexpected tag name: " + tagName); continue; } params.restore(paramsFile, parser); } map.put(name, params); addComponentNameToLaunchParamAffinityMapIfNotNull( name, params.mWindowLayoutAffinity); } catch (Exception e) { Slog.w(TAG, "Failed to restore launch params for " + name, e); filesToDelete.add(paramsFile); } } if (!filesToDelete.isEmpty()) { mPersisterQueue.addItem(new CleanUpComponentQueueItem(filesToDelete), true); } return map; } } private class LaunchParamsWriteQueueItem implements PersisterQueue.WriteQueueItem<LaunchParamsWriteQueueItem> { private final int mUserId; Loading Loading @@ -466,7 +529,7 @@ class LaunchParamsPersister { } } private class CleanUpComponentQueueItem implements PersisterQueue.WriteQueueItem { private static class CleanUpComponentQueueItem implements PersisterQueue.WriteQueueItem { private final List<File> mComponentFiles; private CleanUpComponentQueueItem(List<File> componentFiles) { Loading @@ -483,7 +546,7 @@ class LaunchParamsPersister { } } private class PersistableLaunchParams { private static class PersistableLaunchParams { private static final String ATTR_WINDOWING_MODE = "windowing_mode"; private static final String ATTR_DISPLAY_UNIQUE_ID = "display_unique_id"; private static final String ATTR_BOUNDS = "bounds"; Loading
services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java +15 −0 Original line number Diff line number Diff line Loading @@ -494,6 +494,21 @@ public class LaunchParamsPersisterTests extends WindowTestsBase { assertTrue("Result should be empty.", mResult.isEmpty()); } @Test public void testAbortsLoadingWhenUserCleansUpBeforeLoadingFinishes() { mTarget.saveTask(mTestTask); mPersisterQueue.flush(); final LaunchParamsPersister target = new LaunchParamsPersister(mPersisterQueue, mSupervisor, mUserFolderGetter); target.onSystemReady(); target.onUnlockUser(TEST_USER_ID); target.onCleanupUser(TEST_USER_ID); target.getLaunchParams(mTestTask, null, mResult); assertTrue("Result should be empty.", mResult.isEmpty()); } private static boolean deleteRecursively(File file) { boolean result = true; if (file.isDirectory()) { Loading