1 /*
2  * Copyright (C) 2011 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 
17 package com.google.android.test.activity;
18 
19 import android.app.Activity;
20 import android.app.ActivityManager;
21 import android.app.ActivityOptions;
22 import android.app.AlarmManager;
23 import android.app.AlertDialog;
24 import android.app.PendingIntent;
25 import android.content.BroadcastReceiver;
26 import android.content.ComponentName;
27 import android.content.ContentProviderClient;
28 import android.content.Context;
29 import android.content.Intent;
30 import android.content.ServiceConnection;
31 import android.content.pm.UserInfo;
32 import android.content.res.Configuration;
33 import android.graphics.Bitmap;
34 import android.graphics.BitmapFactory;
35 import android.graphics.drawable.Icon;
36 import android.net.Uri;
37 import android.os.Bundle;
38 import android.os.Handler;
39 import android.os.IBinder;
40 import android.os.Message;
41 import android.os.PowerManager;
42 import android.os.RemoteException;
43 import android.os.SystemClock;
44 import android.os.UserHandle;
45 import android.os.UserManager;
46 import android.provider.Settings;
47 import android.util.Log;
48 import android.view.Menu;
49 import android.view.MenuItem;
50 import android.view.View;
51 import android.widget.LinearLayout;
52 import android.widget.ScrollView;
53 import android.widget.TextView;
54 import android.widget.Toast;
55 
56 import java.util.ArrayList;
57 import java.util.List;
58 
59 public class ActivityTestMain extends Activity {
60     static final String TAG = "ActivityTest";
61 
62     static final String KEY_CONFIGURATION = "configuration";
63 
64     ActivityManager mAm;
65     PowerManager mPower;
66     AlarmManager mAlarm;
67     Configuration mOverrideConfig;
68     int mSecondUser;
69 
70     ArrayList<ServiceConnection> mConnections = new ArrayList<ServiceConnection>();
71 
72     ServiceConnection mIsolatedConnection;
73 
74     static final String SLOW_RECEIVER_ACTION = "com.google.android.test.activity.SLOW_ACTION";
75     static final String SLOW_RECEIVER_EXTRA = "slow_ordinal";
76 
77     static final int MSG_SPAM = 1;
78     static final int MSG_SPAM_ALARM = 2;
79     static final int MSG_SLOW_RECEIVER = 3;
80     static final int MSG_SLOW_ALARM_RECEIVER = 4;
81     static final int MSG_REPLACE_BROADCAST = 5;
82 
83     final Handler mHandler = new Handler() {
84         @Override
85         public void handleMessage(Message msg) {
86             switch (msg.what) {
87                 case MSG_SPAM: {
88                     boolean fg = msg.arg1 != 0;
89                     Intent intent = new Intent(ActivityTestMain.this, SpamActivity.class);
90                     Bundle options = null;
91                     if (fg) {
92                         ActivityOptions opts = ActivityOptions.makeTaskLaunchBehind();
93                         options = opts.toBundle();
94                     }
95                     startActivity(intent, options);
96                     scheduleSpam(!fg);
97                 } break;
98                 case MSG_SPAM_ALARM: {
99                     long when = SystemClock.elapsedRealtime();
100                     Intent intent = new Intent(ActivityTestMain.this, AlarmSpamReceiver.class);
101                     intent.setAction("com.example.SPAM_ALARM=" + when);
102                     PendingIntent pi = PendingIntent.getBroadcast(ActivityTestMain.this,
103                             0, intent, PendingIntent.FLAG_MUTABLE_UNAUDITED);
104                     mAlarm.setAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME, when+(30*1000), pi);
105                     scheduleSpamAlarm(30*1000);
106                 } break;
107                 case MSG_SLOW_RECEIVER: {
108                     // Several back to back, to illustrate dispatch policy
109                     Intent intent = new Intent(ActivityTestMain.this, SlowReceiver.class);
110                     intent.setAction(SLOW_RECEIVER_ACTION);
111                     intent.putExtra(SLOW_RECEIVER_EXTRA, 1);
112                     sendOrderedBroadcast(intent, null, mSlowReceiverCompletion, mHandler,
113                             Activity.RESULT_OK, null, null);
114                     intent.putExtra(SLOW_RECEIVER_EXTRA, 2);
115                     sendOrderedBroadcast(intent, null, mSlowReceiverCompletion, mHandler,
116                             Activity.RESULT_OK, null, null);
117                     intent.putExtra(SLOW_RECEIVER_EXTRA, 3);
118                     sendOrderedBroadcast(intent, null, mSlowReceiverCompletion, mHandler,
119                             Activity.RESULT_OK, null, null);
120                 } break;
121                 case MSG_SLOW_ALARM_RECEIVER: {
122                     // Several back to back, to illustrate dispatch policy
123                     Intent intent = new Intent(ActivityTestMain.this, SlowReceiver.class);
124                     intent.setAction(SLOW_RECEIVER_ACTION);
125                     intent.putExtra(SLOW_RECEIVER_EXTRA, 1);
126                     sendOrderedBroadcast(intent, null, mSlowReceiverCompletion, mHandler,
127                             Activity.RESULT_OK, null, null);
128                     intent.putExtra(SLOW_RECEIVER_EXTRA, 2);
129                     sendOrderedBroadcast(intent, null, mSlowReceiverCompletion, mHandler,
130                             Activity.RESULT_OK, null, null);
131                     intent.putExtra(SLOW_RECEIVER_EXTRA, 3);
132                     sendOrderedBroadcast(intent, null, mSlowReceiverCompletion, mHandler,
133                             Activity.RESULT_OK, null, null);
134 
135                     // Also send a broadcast alarm to evaluate the alarm fast-forward policy
136                     intent.putExtra(SLOW_RECEIVER_EXTRA, 4);
137                     PendingIntent pi = PendingIntent.getBroadcast(ActivityTestMain.this, 1, intent, PendingIntent.FLAG_MUTABLE_UNAUDITED);
138                     AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
139                     long now = SystemClock.elapsedRealtime();
140                     Log.i(TAG, "Setting alarm for now + 5 seconds");
141                     am.setExact(AlarmManager.ELAPSED_REALTIME, now + 5_000, pi);
142                 } break;
143                 case MSG_REPLACE_BROADCAST: {
144                     Intent intent = new Intent(ActivityTestMain.this, SlowReceiver.class);
145                     intent.setAction(SLOW_RECEIVER_ACTION);
146                     intent.putExtra(SLOW_RECEIVER_EXTRA, 1);
147                     sendOrderedBroadcast(intent, null, mSlowReceiverCompletion, mHandler,
148                             Activity.RESULT_OK, null, null);
149                     intent.putExtra(SLOW_RECEIVER_EXTRA, 2);
150                     sendOrderedBroadcast(intent, null, mSlowReceiverCompletion, mHandler,
151                             Activity.RESULT_OK, null, null);
152                     intent.putExtra(SLOW_RECEIVER_EXTRA, 5038);
153                     intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
154                     sendOrderedBroadcast(intent, null, mSlowReceiverCompletion, mHandler,
155                             Activity.RESULT_OK, null, null);
156                 } break;
157             }
158             super.handleMessage(msg);
159         }
160     };
161 
162     final BroadcastReceiver mSlowReceiverCompletion = new BroadcastReceiver() {
163         @Override
164         public void onReceive(Context context, Intent intent) {
165             final int extra = intent.getIntExtra(SLOW_RECEIVER_EXTRA, -1);
166             final String msg = "Slow receiver " + extra + " completed";
167             Toast.makeText(ActivityTestMain.this, msg, Toast.LENGTH_LONG)
168                     .show();
169             Log.i(TAG, msg);
170         }
171     };
172 
173     class BroadcastResultReceiver extends BroadcastReceiver {
174         @Override
onReceive(Context context, Intent intent)175         public void onReceive(Context context, Intent intent) {
176             Bundle res = getResultExtras(true);
177             int user = res.getInt("user", -1);
178             Toast.makeText(ActivityTestMain.this,
179                     "Receiver executed as user "
180                     + (user >= 0 ? Integer.toString(user) : "unknown"),
181                     Toast.LENGTH_LONG).show();
182         }
183     }
184 
185     @Override
onCreate(Bundle savedInstanceState)186     protected void onCreate(Bundle savedInstanceState) {
187         super.onCreate(savedInstanceState);
188 
189         Log.i(TAG, "Referrer: " + getReferrer());
190 
191         mAm = getSystemService(ActivityManager.class);
192         mPower = getSystemService(PowerManager.class);
193         mAlarm = getSystemService(AlarmManager.class);
194         if (savedInstanceState != null) {
195             mOverrideConfig = savedInstanceState.getParcelable(KEY_CONFIGURATION);
196             if (mOverrideConfig != null) {
197                 applyOverrideConfiguration(mOverrideConfig);
198             }
199         }
200 
201         UserManager um = (UserManager)getSystemService(Context.USER_SERVICE);
202         List<UserInfo> users = um.getUsers();
203         mSecondUser = Integer.MAX_VALUE;
204         for (UserInfo ui : users) {
205             if (ui.id != 0 && mSecondUser > ui.id) {
206                 mSecondUser = ui.id;
207             }
208         }
209 
210         /*
211         AlertDialog ad = new AlertDialog.Builder(this).setTitle("title").setMessage("message").create();
212         ad.getWindow().getAttributes().type = WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
213         ad.show();
214         */
215     }
216 
217     @Override
onCreateOptionsMenu(Menu menu)218     public boolean onCreateOptionsMenu(Menu menu) {
219         menu.add("Animate!").setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
220             @Override
221             public boolean onMenuItemClick(MenuItem item) {
222                 AlertDialog.Builder builder = new AlertDialog.Builder(ActivityTestMain.this,
223                         R.style.SlowDialog);
224                 builder.setTitle("This is a title");
225                 builder.show();
226                 return true;
227             }
228         });
229         menu.add("Bind!").setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
230             @Override public boolean onMenuItemClick(MenuItem item) {
231                 Intent intent = new Intent(ActivityTestMain.this, SingleUserService.class);
232                 ServiceConnection conn = new ServiceConnection() {
233                     @Override
234                     public void onServiceConnected(ComponentName name, IBinder service) {
235                         Log.i(TAG, "Service connected " + name + " " + service);
236                     }
237                     @Override
238                     public void onServiceDisconnected(ComponentName name) {
239                         Log.i(TAG, "Service disconnected " + name);
240                     }
241                 };
242                 if (bindService(intent, conn, Context.BIND_AUTO_CREATE)) {
243                     mConnections.add(conn);
244                 } else {
245                     Toast.makeText(ActivityTestMain.this, "Failed to bind",
246                             Toast.LENGTH_LONG).show();
247                 }
248                 return true;
249             }
250         });
251         menu.add("Start!").setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
252             @Override public boolean onMenuItemClick(MenuItem item) {
253                 Intent intent = new Intent(ActivityTestMain.this, SingleUserService.class);
254                 startService(intent);
255                 return true;
256             }
257         });
258         menu.add("Rebind Isolated!").setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
259             @Override public boolean onMenuItemClick(MenuItem item) {
260                 Intent intent = new Intent(ActivityTestMain.this, IsolatedService.class);
261                 ServiceConnection conn = new ServiceConnection() {
262                     @Override
263                     public void onServiceConnected(ComponentName name, IBinder service) {
264                         Log.i(TAG, "Isolated service connected " + name + " " + service);
265                     }
266                     @Override
267                     public void onServiceDisconnected(ComponentName name) {
268                         Log.i(TAG, "Isolated service disconnected " + name);
269                     }
270                 };
271                 if (mIsolatedConnection != null) {
272                     Log.i(TAG, "Unbinding existing service: " + mIsolatedConnection);
273                     unbindService(mIsolatedConnection);
274                     mIsolatedConnection = null;
275                 }
276                 Log.i(TAG, "Binding new service: " + conn);
277                 if (bindService(intent, conn, Context.BIND_AUTO_CREATE)) {
278                     mIsolatedConnection = conn;
279                 } else {
280                     Toast.makeText(ActivityTestMain.this, "Failed to bind",
281                             Toast.LENGTH_LONG).show();
282                 }
283                 return true;
284             }
285         });
286         menu.add("Send!").setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
287             @Override public boolean onMenuItemClick(MenuItem item) {
288                 Intent intent = new Intent(ActivityTestMain.this, SingleUserReceiver.class);
289                 sendOrderedBroadcast(intent, null, new BroadcastResultReceiver(),
290                         null, Activity.RESULT_OK, null, null);
291                 return true;
292             }
293         });
294         menu.add("Call!").setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
295             @Override public boolean onMenuItemClick(MenuItem item) {
296                 ContentProviderClient cpl = getContentResolver().acquireContentProviderClient(
297                         SingleUserProvider.AUTHORITY);
298                 Bundle res = null;
299                 try {
300                     res = cpl.call("getuser", null, null);
301                 } catch (RemoteException e) {
302                 }
303                 int user = res != null ? res.getInt("user", -1) : -1;
304                 Toast.makeText(ActivityTestMain.this,
305                         "Provider executed as user "
306                         + (user >= 0 ? Integer.toString(user) : "unknown"),
307                         Toast.LENGTH_LONG).show();
308                 cpl.release();
309                 return true;
310             }
311         });
312         menu.add("Send to user 0!").setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
313             @Override public boolean onMenuItemClick(MenuItem item) {
314                 Intent intent = new Intent(ActivityTestMain.this, UserTarget.class);
315                 sendOrderedBroadcastAsUser(intent, new UserHandle(0), null,
316                         new BroadcastResultReceiver(),
317                         null, Activity.RESULT_OK, null, null);
318                 return true;
319             }
320         });
321         menu.add("Send to user " + mSecondUser + "!").setOnMenuItemClickListener(
322                 new MenuItem.OnMenuItemClickListener() {
323             @Override public boolean onMenuItemClick(MenuItem item) {
324                 Intent intent = new Intent(ActivityTestMain.this, UserTarget.class);
325                 sendOrderedBroadcastAsUser(intent, new UserHandle(mSecondUser), null,
326                         new BroadcastResultReceiver(),
327                         null, Activity.RESULT_OK, null, null);
328                 return true;
329             }
330         });
331         menu.add("Bind to user 0!").setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
332             @Override public boolean onMenuItemClick(MenuItem item) {
333                 Intent intent = new Intent(ActivityTestMain.this, ServiceUserTarget.class);
334                 ServiceConnection conn = new ServiceConnection() {
335                     @Override
336                     public void onServiceConnected(ComponentName name, IBinder service) {
337                         Log.i(TAG, "Service connected " + name + " " + service);
338                     }
339                     @Override
340                     public void onServiceDisconnected(ComponentName name) {
341                         Log.i(TAG, "Service disconnected " + name);
342                     }
343                 };
344                 if (bindServiceAsUser(intent, conn, Context.BIND_AUTO_CREATE, UserHandle.SYSTEM)) {
345                     mConnections.add(conn);
346                 } else {
347                     Toast.makeText(ActivityTestMain.this, "Failed to bind",
348                             Toast.LENGTH_LONG).show();
349                 }
350                 return true;
351             }
352         });
353         menu.add("Bind to user " + mSecondUser + "!").setOnMenuItemClickListener(
354                 new MenuItem.OnMenuItemClickListener() {
355             @Override public boolean onMenuItemClick(MenuItem item) {
356                 Intent intent = new Intent(ActivityTestMain.this, ServiceUserTarget.class);
357                 ServiceConnection conn = new ServiceConnection() {
358                     @Override
359                     public void onServiceConnected(ComponentName name, IBinder service) {
360                         Log.i(TAG, "Service connected " + name + " " + service);
361                     }
362                     @Override
363                     public void onServiceDisconnected(ComponentName name) {
364                         Log.i(TAG, "Service disconnected " + name);
365                     }
366                 };
367                 if (bindServiceAsUser(intent, conn, Context.BIND_AUTO_CREATE,
368                         new UserHandle(mSecondUser))) {
369                     mConnections.add(conn);
370                 } else {
371                     Toast.makeText(ActivityTestMain.this, "Failed to bind",
372                             Toast.LENGTH_LONG).show();
373                 }
374                 return true;
375             }
376         });
377         menu.add("Density!").setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
378             @Override public boolean onMenuItemClick(MenuItem item) {
379                 if (mOverrideConfig == null) {
380                     mOverrideConfig = new Configuration();
381                 }
382                 if (mOverrideConfig.densityDpi == Configuration.DENSITY_DPI_UNDEFINED) {
383                     mOverrideConfig.densityDpi = (getApplicationContext().getResources()
384                             .getConfiguration().densityDpi*2)/3;
385                 } else {
386                     mOverrideConfig.densityDpi = Configuration.DENSITY_DPI_UNDEFINED;
387                 }
388                 recreate();
389                 return true;
390             }
391         });
392         menu.add("HashArray").setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
393             @Override public boolean onMenuItemClick(MenuItem item) {
394                 ArrayMapTests.run();
395                 return true;
396             }
397         });
398         menu.add("Add App Recent").setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
399             @Override public boolean onMenuItemClick(MenuItem item) {
400                 addAppRecents(1);
401                 return true;
402             }
403         });
404         menu.add("Add App 10x Recent").setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
405             @Override public boolean onMenuItemClick(MenuItem item) {
406                 addAppRecents(10);
407                 return true;
408             }
409         });
410         menu.add("Exclude!").setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
411             @Override public boolean onMenuItemClick(MenuItem item) {
412                 setExclude(true);
413                 return true;
414             }
415         });
416         menu.add("Include!").setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
417             @Override public boolean onMenuItemClick(MenuItem item) {
418                 setExclude(false);
419                 return true;
420             }
421         });
422         menu.add("Open Doc").setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
423             @Override public boolean onMenuItemClick(MenuItem item) {
424                 ActivityManager.AppTask task = findDocTask();
425                 if (task == null) {
426                     Intent intent = new Intent(ActivityTestMain.this, DocActivity.class);
427                     intent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT
428                             | Intent.FLAG_ACTIVITY_MULTIPLE_TASK
429                             | Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS);
430                     startActivity(intent);
431                 } else {
432                     task.moveToFront();
433                 }
434                 return true;
435             }
436         });
437         menu.add("Replace broadcast").setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
438             @Override public boolean onMenuItemClick(MenuItem item) {
439                 scheduleReplaceBroadcast();
440                 return true;
441             }
442         });
443         menu.add("Require unknown permission").setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
444             @Override public boolean onMenuItemClick(MenuItem item) {
445                 final Intent intent = new Intent(SLOW_RECEIVER_ACTION);
446                 intent.putExtra(SLOW_RECEIVER_EXTRA, 5038);
447                 sendOrderedBroadcast(intent, "com.google.android.test.activity.permission.UNDEFINED");
448                 return true;
449             }
450         });
451         menu.add("Stack Doc").setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
452             @Override public boolean onMenuItemClick(MenuItem item) {
453                 ActivityManager.AppTask task = findDocTask();
454                 if (task != null) {
455                     ActivityManager.RecentTaskInfo recent = task.getTaskInfo();
456                     Intent intent = new Intent(ActivityTestMain.this, DocActivity.class);
457                     if (recent.id >= 0) {
458                         // Stack on top.
459                         intent.putExtra(DocActivity.LABEL, "Stacked");
460                     } else {
461                         // Start root activity.
462                         intent.putExtra(DocActivity.LABEL, "New Root");
463                     }
464                     task.startActivity(ActivityTestMain.this, intent, null);
465                 }
466                 return true;
467             }
468         });
469         menu.add("Slow receiver").setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
470             @Override public boolean onMenuItemClick(MenuItem item) {
471                 scheduleSlowReceiver();
472                 return true;
473             }
474         });
475         menu.add("Slow alarm receiver").setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
476             @Override public boolean onMenuItemClick(MenuItem item) {
477                 scheduleSlowAlarmReceiver();
478                 return true;
479             }
480         });
481         menu.add("Spam!").setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
482             @Override public boolean onMenuItemClick(MenuItem item) {
483                 scheduleSpam(false);
484                 return true;
485             }
486         });
487         menu.add("Track time").setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
488             @Override public boolean onMenuItemClick(MenuItem item) {
489                 Intent intent = new Intent(Intent.ACTION_SEND);
490                 intent.setType("text/plain");
491                 intent.putExtra(Intent.EXTRA_TEXT, "We are sharing this with you!");
492                 ActivityOptions options = ActivityOptions.makeBasic();
493                 Intent receiveIntent = new Intent(ActivityTestMain.this, TrackTimeReceiver.class);
494                 receiveIntent.putExtra("something", "yeah, this is us!");
495                 options.requestUsageTimeReport(PendingIntent.getBroadcast(ActivityTestMain.this,
496                         0, receiveIntent, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_MUTABLE_UNAUDITED));
497                 startActivity(Intent.createChooser(intent, "Who do you love?"), options.toBundle());
498                 return true;
499             }
500         });
501         menu.add("Transaction fail").setOnMenuItemClickListener(
502                 new MenuItem.OnMenuItemClickListener() {
503             @Override public boolean onMenuItemClick(MenuItem item) {
504                 Intent intent = new Intent(Intent.ACTION_MAIN);
505                 intent.putExtra("gulp", new int[1024 * 1024]);
506                 startActivity(intent);
507                 return true;
508             }
509         });
510         menu.add("Spam idle alarm").setOnMenuItemClickListener(
511                 new MenuItem.OnMenuItemClickListener() {
512             @Override public boolean onMenuItemClick(MenuItem item) {
513                 scheduleSpamAlarm(0);
514                 return true;
515             }
516         });
517         menu.add("Ignore battery optimizations").setOnMenuItemClickListener(
518                 new MenuItem.OnMenuItemClickListener() {
519             @Override public boolean onMenuItemClick(MenuItem item) {
520                 Intent intent;
521                 if (!mPower.isIgnoringBatteryOptimizations(getPackageName())) {
522                     intent = new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
523                     intent.setData(Uri.fromParts("package", getPackageName(), null));
524                 } else {
525                     intent = new Intent(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS);
526                 }
527                 startActivity(intent);
528                 return true;
529             }
530         });
531         return true;
532     }
533 
534     @Override
onStart()535     protected void onStart() {
536         super.onStart();
537         buildUi();
538     }
539 
540     @Override
onPause()541     protected void onPause() {
542         super.onPause();
543         Log.i(TAG, "I'm such a slooow poor loser");
544         try {
545             Thread.sleep(500);
546         } catch (InterruptedException e) {
547         }
548         Log.i(TAG, "See?");
549     }
550 
551     @Override
onSaveInstanceState(Bundle outState)552     protected void onSaveInstanceState(Bundle outState) {
553         super.onSaveInstanceState(outState);
554         if (mOverrideConfig != null) {
555             outState.putParcelable(KEY_CONFIGURATION, mOverrideConfig);
556         }
557     }
558 
559     @Override
onStop()560     protected void onStop() {
561         super.onStop();
562         mHandler.removeMessages(MSG_SPAM_ALARM);
563         mHandler.removeMessages(MSG_SLOW_RECEIVER);
564         for (ServiceConnection conn : mConnections) {
565             unbindService(conn);
566         }
567         mConnections.clear();
568         if (mIsolatedConnection != null) {
569             unbindService(mIsolatedConnection);
570             mIsolatedConnection = null;
571         }
572     }
573 
574     @Override
onDestroy()575     protected void onDestroy() {
576         super.onDestroy();
577         mHandler.removeMessages(MSG_SPAM);
578     }
579 
addAppRecents(int count)580     void addAppRecents(int count) {
581         ActivityManager am = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
582         Intent intent = new Intent(Intent.ACTION_MAIN);
583         intent.addCategory(Intent.CATEGORY_LAUNCHER);
584         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
585         intent.setComponent(new ComponentName(this, ActivityTestMain.class));
586         for (int i=0; i<count; i++) {
587             ActivityManager.TaskDescription desc = new ActivityManager.TaskDescription();
588             desc.setLabel("Added #" + i);
589             Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.icon);
590             if ((i&1) == 0) {
591                 desc.setIcon(Icon.createWithBitmap(bitmap));
592             }
593             int taskId = am.addAppTask(this, intent, desc, bitmap);
594             Log.i(TAG, "Added new task id #" + taskId);
595         }
596     }
597 
setExclude(boolean exclude)598     void setExclude(boolean exclude) {
599         ActivityManager am = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
600         List<ActivityManager.AppTask> tasks = am.getAppTasks();
601         int taskId = getTaskId();
602         for (int i=0; i<tasks.size(); i++) {
603             ActivityManager.AppTask task = tasks.get(i);
604             if (task.getTaskInfo().id == taskId) {
605                 task.setExcludeFromRecents(exclude);
606             }
607         }
608     }
609 
findDocTask()610     ActivityManager.AppTask findDocTask() {
611         ActivityManager am = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
612         List<ActivityManager.AppTask> tasks = am.getAppTasks();
613         if (tasks != null) {
614             for (int i=0; i<tasks.size(); i++) {
615                 ActivityManager.AppTask task = tasks.get(i);
616                 ActivityManager.RecentTaskInfo recent = task.getTaskInfo();
617                 if (recent.baseIntent != null
618                         && recent.baseIntent.getComponent().getClassName().equals(
619                                 DocActivity.class.getCanonicalName())) {
620                     return task;
621                 }
622             }
623         }
624         return null;
625     }
626 
scheduleSpam(boolean fg)627     void scheduleSpam(boolean fg) {
628         mHandler.removeMessages(MSG_SPAM);
629         Message msg = mHandler.obtainMessage(MSG_SPAM, fg ? 1 : 0, 0);
630         mHandler.sendMessageDelayed(msg, 500);
631     }
632 
scheduleSpamAlarm(long delay)633     void scheduleSpamAlarm(long delay) {
634         mHandler.removeMessages(MSG_SPAM_ALARM);
635         Message msg = mHandler.obtainMessage(MSG_SPAM_ALARM);
636         mHandler.sendMessageDelayed(msg, delay);
637     }
638 
scheduleSlowReceiver()639     void scheduleSlowReceiver() {
640         mHandler.removeMessages(MSG_SLOW_RECEIVER);
641         mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_SLOW_RECEIVER), 500);
642     }
643 
scheduleSlowAlarmReceiver()644     void scheduleSlowAlarmReceiver() {
645         mHandler.removeMessages(MSG_SLOW_ALARM_RECEIVER);
646         mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_SLOW_ALARM_RECEIVER), 500);
647     }
648 
scheduleReplaceBroadcast()649     void scheduleReplaceBroadcast() {
650         mHandler.removeMessages(MSG_REPLACE_BROADCAST);
651         mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_REPLACE_BROADCAST), 500);
652     }
653 
scrollWrap(View view)654     private View scrollWrap(View view) {
655         ScrollView scroller = new ScrollView(this);
656         scroller.addView(view, new ScrollView.LayoutParams(ScrollView.LayoutParams.MATCH_PARENT,
657                 ScrollView.LayoutParams.MATCH_PARENT));
658         return scroller;
659     }
660 
buildUi()661     private void buildUi() {
662         LinearLayout top = new LinearLayout(this);
663         top.setOrientation(LinearLayout.VERTICAL);
664 
665         List<ActivityManager.RecentTaskInfo> recents = mAm.getRecentTasks(10,
666                 ActivityManager.RECENT_WITH_EXCLUDED);
667         if (recents != null) {
668             for (int i=0; i<recents.size(); i++) {
669                 ActivityManager.RecentTaskInfo r = recents.get(i);
670                 TextView tv = new TextView(this);
671                 tv.setText(r.baseIntent.getComponent().flattenToShortString());
672                 top.addView(tv, new LinearLayout.LayoutParams(
673                         LinearLayout.LayoutParams.WRAP_CONTENT,
674                         LinearLayout.LayoutParams.WRAP_CONTENT));
675                 LinearLayout item = new LinearLayout(this);
676                 item.setOrientation(LinearLayout.HORIZONTAL);
677                 top.addView(item, new LinearLayout.LayoutParams(
678                         LinearLayout.LayoutParams.WRAP_CONTENT,
679                         LinearLayout.LayoutParams.WRAP_CONTENT));
680             }
681         }
682 
683         setContentView(scrollWrap(top));
684     }
685 }
686