summaryrefslogtreecommitdiffstats
path: root/tests/ActivityTests
diff options
context:
space:
mode:
authorDianne Hackborn <hackbod@google.com>2014-08-24 16:45:38 -0700
committerDianne Hackborn <hackbod@google.com>2014-08-26 11:16:59 -0700
commit89ad456ea49cb62615ebdcac83a2515743bbe5fa (patch)
tree4fdd6b948f74930ad10beca0a042e40f36efc50c /tests/ActivityTests
parent1ce1ba68acbfcbd4100d8c4be7d17a1f0623fd62 (diff)
downloadframeworks_base-89ad456ea49cb62615ebdcac83a2515743bbe5fa.zip
frameworks_base-89ad456ea49cb62615ebdcac83a2515743bbe5fa.tar.gz
frameworks_base-89ad456ea49cb62615ebdcac83a2515743bbe5fa.tar.bz2
Fix issue #16311398: Limit number of documents a process can open
In application processes, monitor for when we start getting close to the Dalvik heap limit, and ask the activity manager to try to prune old activity instances in that case. Add an explicit API for apps to ask that they have their own activity instances cleaned up, if they want. Fix some bugs in launching activities that were not correctly applying the "multi task" behavior in the appropriate situations of document-centric recents. Clean up the activity manager's process removal code to all share a common path. Add a new "Spam" option to ActivityTests, which continually creates new tasks, checking that the activity manager will now prune old tasks rather than letting the app run out of RAM. And while I was was doing this, I found problems with the path for bringing an empty task to the foreground -- it could make a new task instead of re-starting the root activity in the existing task. This is fixed, and some code in the recents UI for working around the bug is removed. And as long as I am doing that, we now have nice hooks in to the activity manager for AppTask to give some APIs for better managing the task, so add those along with more tests for these APIs in ActivityTests. We should look at also having the activity manager try to prune old tasks when it sees app processes being killed, to better balance memory use across multiple processes when some processes may host many documents. That however is for another CL... Change-Id: I2bb81c3f92819350c868c7a7470b35817eb9bea9
Diffstat (limited to 'tests/ActivityTests')
-rw-r--r--tests/ActivityTests/AndroidManifest.xml5
-rw-r--r--tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java105
-rw-r--r--tests/ActivityTests/src/com/google/android/test/activity/DocActivity.java35
-rw-r--r--tests/ActivityTests/src/com/google/android/test/activity/SpamActivity.java31
4 files changed, 173 insertions, 3 deletions
diff --git a/tests/ActivityTests/AndroidManifest.xml b/tests/ActivityTests/AndroidManifest.xml
index c0898d3..3fb547d 100644
--- a/tests/ActivityTests/AndroidManifest.xml
+++ b/tests/ActivityTests/AndroidManifest.xml
@@ -31,6 +31,11 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
+ <activity android:name="SpamActivity" android:label="Spam!"
+ android:documentLaunchMode="always">
+ </activity>
+ <activity android:name="DocActivity" android:label="Some doc">
+ </activity>
<service android:name="SingleUserService"
android:singleUser="true" android:exported="true">
</service>
diff --git a/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java b/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java
index 7f3aa77..ea0db56 100644
--- a/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java
+++ b/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java
@@ -21,6 +21,7 @@ import java.util.List;
import android.app.Activity;
import android.app.ActivityManager;
+import android.app.ActivityOptions;
import android.app.AlertDialog;
import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
@@ -29,13 +30,15 @@ import android.content.ContentProviderClient;
import android.content.Intent;
import android.content.ServiceConnection;
import android.graphics.BitmapFactory;
+import android.net.Uri;
import android.os.Bundle;
+import android.os.Handler;
import android.os.IBinder;
+import android.os.Message;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
import android.graphics.Bitmap;
-import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
@@ -60,6 +63,28 @@ public class ActivityTestMain extends Activity {
ArrayList<ServiceConnection> mConnections = new ArrayList<ServiceConnection>();
+ static final int MSG_SPAM = 1;
+
+ final Handler mHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_SPAM: {
+ boolean fg = msg.arg1 != 0;
+ Intent intent = new Intent(ActivityTestMain.this, SpamActivity.class);
+ Bundle options = null;
+ if (fg) {
+ ActivityOptions opts = ActivityOptions.makeLaunchTaskBehindAnimation();
+ options = opts.toBundle();
+ }
+ startActivity(intent, options);
+ scheduleSpam(!fg);
+ } break;
+ }
+ super.handleMessage(msg);
+ }
+ };
+
class BroadcastResultReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
@@ -143,7 +168,8 @@ public class ActivityTestMain extends Activity {
@Override
public boolean onCreateOptionsMenu(Menu menu) {
menu.add("Animate!").setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
- @Override public boolean onMenuItemClick(MenuItem item) {
+ @Override
+ public boolean onMenuItemClick(MenuItem item) {
AlertDialog.Builder builder = new AlertDialog.Builder(ActivityTestMain.this,
R.style.SlowDialog);
builder.setTitle("This is a title");
@@ -316,6 +342,49 @@ public class ActivityTestMain extends Activity {
return true;
}
});
+ menu.add("Open Doc").setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
+ @Override public boolean onMenuItemClick(MenuItem item) {
+ ActivityManager.AppTask task = findDocTask();
+ if (task == null) {
+ Intent intent = new Intent(ActivityTestMain.this, DocActivity.class);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT
+ | Intent.FLAG_ACTIVITY_MULTIPLE_TASK
+ | Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS);
+ startActivity(intent);
+ } else {
+ task.moveToFront();
+ }
+ return true;
+ }
+ });
+ menu.add("Stack Doc").setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
+ @Override public boolean onMenuItemClick(MenuItem item) {
+ ActivityManager.AppTask task = findDocTask();
+ if (task != null) {
+ ActivityManager.RecentTaskInfo recent = task.getTaskInfo();
+ Intent intent = new Intent(ActivityTestMain.this, DocActivity.class);
+ if (recent.id >= 0) {
+ // Stack on top.
+ intent.putExtra(DocActivity.LABEL, "Stacked");
+ task.startActivity(ActivityTestMain.this, intent, null);
+ } else {
+ // Start root activity.
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT
+ | Intent.FLAG_ACTIVITY_MULTIPLE_TASK
+ | Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS);
+ intent.putExtra(DocActivity.LABEL, "New Root");
+ task.startActivity(ActivityTestMain.this, intent, null);
+ }
+ }
+ return true;
+ }
+ });
+ menu.add("Spam!").setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
+ @Override public boolean onMenuItemClick(MenuItem item) {
+ scheduleSpam(false);
+ return true;
+ }
+ });
return true;
}
@@ -342,6 +411,12 @@ public class ActivityTestMain extends Activity {
mConnections.clear();
}
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ mHandler.removeMessages(MSG_SPAM);
+ }
+
void addAppRecents(int count) {
ActivityManager am = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
Intent intent = new Intent(Intent.ACTION_MAIN);
@@ -371,7 +446,31 @@ public class ActivityTestMain extends Activity {
}
}
}
- private View scrollWrap(View view) {
+
+ ActivityManager.AppTask findDocTask() {
+ ActivityManager am = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
+ List<ActivityManager.AppTask> tasks = am.getAppTasks();
+ if (tasks != null) {
+ for (int i=0; i<tasks.size(); i++) {
+ ActivityManager.AppTask task = tasks.get(i);
+ ActivityManager.RecentTaskInfo recent = task.getTaskInfo();
+ if (recent.baseIntent != null
+ && recent.baseIntent.getComponent().getClassName().equals(
+ DocActivity.class.getCanonicalName())) {
+ return task;
+ }
+ }
+ }
+ return null;
+ }
+
+ void scheduleSpam(boolean fg) {
+ mHandler.removeMessages(MSG_SPAM);
+ Message msg = mHandler.obtainMessage(MSG_SPAM, fg ? 1 : 0, 0);
+ mHandler.sendMessageDelayed(msg, 500);
+ }
+
+ private View scrollWrap(View view) {
ScrollView scroller = new ScrollView(this);
scroller.addView(view, new ScrollView.LayoutParams(ScrollView.LayoutParams.MATCH_PARENT,
ScrollView.LayoutParams.MATCH_PARENT));
diff --git a/tests/ActivityTests/src/com/google/android/test/activity/DocActivity.java b/tests/ActivityTests/src/com/google/android/test/activity/DocActivity.java
new file mode 100644
index 0000000..6330c79
--- /dev/null
+++ b/tests/ActivityTests/src/com/google/android/test/activity/DocActivity.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.android.test.activity;
+
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.os.Bundle;
+
+public class DocActivity extends Activity {
+ static final String LABEL = "label";
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ String label = getIntent().getStringExtra(LABEL);
+ if (label != null) {
+ setTaskDescription(new ActivityManager.TaskDescription(label));
+ setTitle(label);
+ }
+ }
+}
diff --git a/tests/ActivityTests/src/com/google/android/test/activity/SpamActivity.java b/tests/ActivityTests/src/com/google/android/test/activity/SpamActivity.java
new file mode 100644
index 0000000..e5de559
--- /dev/null
+++ b/tests/ActivityTests/src/com/google/android/test/activity/SpamActivity.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.android.test.activity;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class SpamActivity extends Activity {
+ byte[] mBytes;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ // Chew up some RAM -- 8 megs worth.
+ mBytes = new byte[8*1024*1024];
+ }
+}