TaskPersisterTest.java revision b258f6a4bd685e5efcb36c02d5817f659e10479b
1/* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.server.am; 18 19import android.app.ActivityManager; 20import android.content.ContentResolver; 21import android.content.pm.ActivityInfo; 22import android.content.pm.UserInfo; 23import android.os.Environment; 24import android.os.SystemClock; 25import android.os.UserHandle; 26import android.os.UserManager; 27import android.provider.Settings; 28import android.test.AndroidTestCase; 29import android.util.Log; 30import android.util.SparseBooleanArray; 31import android.util.Xml; 32 33import com.android.internal.util.FastXmlSerializer; 34import com.android.internal.util.XmlUtils; 35import com.android.server.am.TaskPersister; 36 37import java.io.File; 38import java.io.IOException; 39import java.io.StringReader; 40import java.io.StringWriter; 41import java.util.Random; 42 43import libcore.io.IoUtils; 44 45import org.xmlpull.v1.XmlPullParser; 46import org.xmlpull.v1.XmlPullParserException; 47import org.xmlpull.v1.XmlSerializer; 48 49public class TaskPersisterTest extends AndroidTestCase { 50 private static final String TEST_USER_NAME = "AM-Test-User"; 51 52 private TaskPersister mTaskPersister; 53 private int testUserId; 54 private UserManager mUserManager; 55 56 @Override 57 public void setUp() throws Exception { 58 super.setUp(); 59 mUserManager = UserManager.get(getContext()); 60 mTaskPersister = new TaskPersister(getContext().getFilesDir()); 61 testUserId = createUser(TEST_USER_NAME, 0); 62 } 63 64 @Override 65 public void tearDown() throws Exception { 66 super.tearDown(); 67 mTaskPersister.unloadUserDataFromMemory(testUserId); 68 removeUser(testUserId); 69 } 70 71 private int getRandomTaskIdForUser(int userId) { 72 int taskId = (int) (Math.random() * UserHandle.PER_USER_RANGE); 73 taskId += UserHandle.PER_USER_RANGE * userId; 74 return taskId; 75 } 76 77 public void testTaskIdsPersistence() { 78 SparseBooleanArray taskIdsOnFile = mTaskPersister.loadPersistedTaskIdsForUser(testUserId); 79 for (int i = 0; i < 100; i++) { 80 taskIdsOnFile.put(getRandomTaskIdForUser(testUserId), true); 81 } 82 mTaskPersister.writePersistedTaskIdsForUser(taskIdsOnFile, testUserId); 83 SparseBooleanArray newTaskIdsOnFile = mTaskPersister 84 .loadPersistedTaskIdsForUser(testUserId); 85 assertTrue("TaskIds written differ from TaskIds read back from file", 86 taskIdsOnFile.equals(newTaskIdsOnFile)); 87 } 88 89 public void testActiveTimeMigration() { 90 // Simulate a migration scenario by setting the last write uptime to zero 91 ContentResolver cr = getContext().getContentResolver(); 92 Settings.Secure.putLong(cr, 93 Settings.Secure.TASK_PERSISTER_LAST_WRITE_UPTIME, 0); 94 95 // Create a dummy task record with an absolute time 1s before now 96 long pastOffset = 1000; 97 long activeTime = System.currentTimeMillis() - pastOffset; 98 TaskRecord tr0 = createDummyTaskRecordWithActiveTime(activeTime, activeTime); 99 100 // Save and load the tasks with no last persist uptime (0) 101 String tr0XmlStr = serializeTaskRecordToXmlString(tr0); 102 TaskRecord xtr0 = unserializeTaskRecordFromXmlString(tr0XmlStr, 0); 103 104 // Ensure that the absolute time has been migrated to be relative to the current elapsed 105 // time 106 assertTrue("Expected firstActiveTime to be migrated from: " + tr0.firstActiveTime + 107 " instead found: " + xtr0.firstActiveTime, 108 xtr0.firstActiveTime <= -pastOffset); 109 assertTrue("Expected lastActiveTime to be migrated from: " + tr0.lastActiveTime + 110 " instead found: " + xtr0.lastActiveTime, 111 xtr0.lastActiveTime <= -pastOffset); 112 113 // Ensure that the last active uptime is not set so that SystemUI can migrate it itself 114 // assuming that the last persist time is zero 115 Settings.Secure.putLongForUser(cr, 116 Settings.Secure.OVERVIEW_LAST_VISIBLE_TASK_ACTIVE_UPTIME, 0, testUserId); 117 mTaskPersister.restoreTasksForUserLocked(testUserId); 118 long lastVisTaskActiveTime = Settings.Secure.getLongForUser(cr, 119 Settings.Secure.OVERVIEW_LAST_VISIBLE_TASK_ACTIVE_UPTIME, -1, testUserId); 120 assertTrue("Expected last visible task active time is zero", lastVisTaskActiveTime == 0); 121 } 122 123 public void testActiveTimeOffsets() { 124 // Simulate a normal boot scenario by setting the last write uptime 125 long lastWritePastOffset = 1000; 126 long lastVisActivePastOffset = 500; 127 ContentResolver cr = getContext().getContentResolver(); 128 Settings.Secure.putLong(cr, 129 Settings.Secure.TASK_PERSISTER_LAST_WRITE_UPTIME, lastWritePastOffset); 130 131 // Create a dummy task record with an absolute time 1s before now 132 long activeTime = 250; 133 TaskRecord tr0 = createDummyTaskRecordWithActiveTime(activeTime, activeTime); 134 135 // Save and load the tasks with the last persist time 136 String tr0XmlStr = serializeTaskRecordToXmlString(tr0); 137 TaskRecord xtr0 = unserializeTaskRecordFromXmlString(tr0XmlStr, lastWritePastOffset); 138 139 // Ensure that the prior elapsed time has been offset to be relative to the current boot 140 // time 141 assertTrue("Expected firstActiveTime to be offset from: " + tr0.firstActiveTime + 142 " instead found: " + xtr0.firstActiveTime, 143 xtr0.firstActiveTime <= (-lastWritePastOffset + activeTime)); 144 assertTrue("Expected lastActiveTime to be offset from: " + tr0.lastActiveTime + 145 " instead found: " + xtr0.lastActiveTime, 146 xtr0.lastActiveTime <= (-lastWritePastOffset + activeTime)); 147 148 // Ensure that we update the last active uptime as well by simulating a restoreTasks call 149 Settings.Secure.putLongForUser(cr, 150 Settings.Secure.OVERVIEW_LAST_VISIBLE_TASK_ACTIVE_UPTIME, lastVisActivePastOffset, 151 testUserId); 152 mTaskPersister.restoreTasksForUserLocked(testUserId); 153 long lastVisTaskActiveTime = Settings.Secure.getLongForUser(cr, 154 Settings.Secure.OVERVIEW_LAST_VISIBLE_TASK_ACTIVE_UPTIME, Long.MAX_VALUE, 155 testUserId); 156 assertTrue("Expected last visible task active time to be offset", lastVisTaskActiveTime <= 157 (-lastWritePastOffset + lastVisActivePastOffset)); 158 } 159 160 private TaskRecord createDummyTaskRecordWithActiveTime(long firstActiveTime, 161 long lastActiveTime) { 162 ActivityInfo info = createDummyActivityInfo(); 163 ActivityManager.TaskDescription td = new ActivityManager.TaskDescription(); 164 TaskRecord t = new TaskRecord(null, 0, info, null, td, null); 165 t.firstActiveTime = firstActiveTime; 166 t.lastActiveTime = lastActiveTime; 167 return t; 168 } 169 170 private ActivityInfo createDummyActivityInfo() { 171 ActivityInfo info = new ActivityInfo(); 172 info.applicationInfo = getContext().getApplicationInfo(); 173 return info; 174 } 175 176 private String serializeTaskRecordToXmlString(TaskRecord tr) { 177 StringWriter stringWriter = new StringWriter(); 178 179 try { 180 final XmlSerializer xmlSerializer = new FastXmlSerializer(); 181 xmlSerializer.setOutput(stringWriter); 182 183 xmlSerializer.startDocument(null, true); 184 xmlSerializer.startTag(null, TaskPersister.TAG_TASK); 185 tr.saveToXml(xmlSerializer); 186 xmlSerializer.endTag(null, TaskPersister.TAG_TASK); 187 xmlSerializer.endDocument(); 188 xmlSerializer.flush(); 189 } catch (Exception e) { 190 e.printStackTrace(); 191 } 192 193 return stringWriter.toString(); 194 } 195 196 private TaskRecord unserializeTaskRecordFromXmlString(String xmlStr, long lastPersistUptime) { 197 StringReader reader = null; 198 TaskRecord task = null; 199 try { 200 reader = new StringReader(xmlStr); 201 final XmlPullParser in = Xml.newPullParser(); 202 in.setInput(reader); 203 204 int event; 205 while (((event = in.next()) != XmlPullParser.END_DOCUMENT) && 206 event != XmlPullParser.END_TAG) { 207 final String name = in.getName(); 208 if (event == XmlPullParser.START_TAG) { 209 if (TaskPersister.TAG_TASK.equals(name)) { 210 task = TaskRecord.restoreFromXml(in, null, null, lastPersistUptime); 211 } 212 } 213 XmlUtils.skipCurrentTag(in); 214 } 215 } catch (Exception e) { 216 return null; 217 } finally { 218 IoUtils.closeQuietly(reader); 219 } 220 return task; 221 } 222 223 private int createUser(String name, int flags) { 224 UserInfo user = mUserManager.createUser(name, flags); 225 if (user == null) { 226 fail("Error while creating the test user: " + TEST_USER_NAME); 227 } 228 return user.id; 229 } 230 231 private void removeUser(int userId) { 232 if (!mUserManager.removeUser(userId)) { 233 fail("Error while removing the test user: " + TEST_USER_NAME); 234 } 235 } 236}