2 * Copyright (C) 2008 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com.android.internal.policy.impl;
19 import android.app.ActivityManager;
20 import android.app.Dialog;
21 import android.app.StatusBarManager;
22 import android.content.ActivityNotFoundException;
23 import android.content.BroadcastReceiver;
24 import android.content.Context;
25 import android.content.Intent;
26 import android.content.IntentFilter;
27 import android.content.res.Resources;
28 import android.content.pm.ActivityInfo;
29 import android.content.pm.PackageManager;
30 import android.content.pm.ResolveInfo;
31 import android.graphics.drawable.Drawable;
32 import android.os.Bundle;
33 import android.os.Handler;
34 import android.util.Log;
35 import android.view.View;
36 import android.view.Window;
37 import android.view.WindowManager;
38 import android.view.View.OnClickListener;
39 import android.widget.TextView;
41 import java.util.List;
43 public class RecentApplicationsDialog extends Dialog implements OnClickListener {
44 // Elements for debugging support
45 // private static final String LOG_TAG = "RecentApplicationsDialog";
46 private static final boolean DBG_FORCE_EMPTY_LIST = false;
48 static private StatusBarManager sStatusBar;
50 private static final int NUM_BUTTONS = 8;
51 private static final int MAX_RECENT_TASKS = NUM_BUTTONS * 2; // allow for some discards
53 final TextView[] mIcons = new TextView[NUM_BUTTONS];
55 IntentFilter mBroadcastIntentFilter = new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
57 Handler mHandler = new Handler();
58 Runnable mCleanup = new Runnable() {
60 // dump extra memory we're hanging on to
61 for (TextView icon: mIcons) {
62 icon.setCompoundDrawables(null, null, null, null);
68 private int mIconSize;
70 public RecentApplicationsDialog(Context context) {
71 super(context, com.android.internal.R.style.Theme_Dialog_RecentApplications);
73 final Resources resources = context.getResources();
74 mIconSize = (int) resources.getDimension(android.R.dimen.app_icon_size);
78 * We create the recent applications dialog just once, and it stays around (hidden)
79 * until activated by the user.
81 * @see PhoneWindowManager#showRecentAppsDialog
84 protected void onCreate(Bundle savedInstanceState) {
85 super.onCreate(savedInstanceState);
87 Context context = getContext();
89 if (sStatusBar == null) {
90 sStatusBar = (StatusBarManager)context.getSystemService(Context.STATUS_BAR_SERVICE);
93 Window window = getWindow();
94 window.requestFeature(Window.FEATURE_NO_TITLE);
95 window.setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG);
96 window.setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
97 WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
98 window.setTitle("Recents");
100 setContentView(com.android.internal.R.layout.recent_apps_dialog);
102 final WindowManager.LayoutParams params = window.getAttributes();
103 params.width = WindowManager.LayoutParams.MATCH_PARENT;
104 params.height = WindowManager.LayoutParams.MATCH_PARENT;
105 window.setAttributes(params);
106 window.setFlags(0, WindowManager.LayoutParams.FLAG_DIM_BEHIND);
108 mIcons[0] = (TextView)findViewById(com.android.internal.R.id.button0);
109 mIcons[1] = (TextView)findViewById(com.android.internal.R.id.button1);
110 mIcons[2] = (TextView)findViewById(com.android.internal.R.id.button2);
111 mIcons[3] = (TextView)findViewById(com.android.internal.R.id.button3);
112 mIcons[4] = (TextView)findViewById(com.android.internal.R.id.button4);
113 mIcons[5] = (TextView)findViewById(com.android.internal.R.id.button5);
114 mIcons[6] = (TextView)findViewById(com.android.internal.R.id.button6);
115 mIcons[7] = (TextView)findViewById(com.android.internal.R.id.button7);
116 mNoAppsText = findViewById(com.android.internal.R.id.no_applications_message);
118 for (TextView b: mIcons) {
119 b.setOnClickListener(this);
124 * Handler for user clicks. If a button was clicked, launch the corresponding activity.
126 public void onClick(View v) {
128 for (TextView b: mIcons) {
130 // prepare a launch intent and send it
131 Intent intent = (Intent)b.getTag();
132 if (intent != null) {
133 intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY);
135 getContext().startActivity(intent);
136 } catch (ActivityNotFoundException e) {
137 Log.w("Recent", "Unable to launch recent task", e);
147 * Set up and show the recent activities dialog.
150 public void onStart() {
153 if (sStatusBar != null) {
154 sStatusBar.disable(StatusBarManager.DISABLE_EXPAND);
157 // receive broadcasts
158 getContext().registerReceiver(mBroadcastReceiver, mBroadcastIntentFilter);
160 mHandler.removeCallbacks(mCleanup);
164 * Dismiss the recent activities dialog.
167 public void onStop() {
170 if (sStatusBar != null) {
171 sStatusBar.disable(StatusBarManager.DISABLE_NONE);
174 // stop receiving broadcasts
175 getContext().unregisterReceiver(mBroadcastReceiver);
177 mHandler.postDelayed(mCleanup, 100);
181 * Reload the 6 buttons with recent activities
183 private void reloadButtons() {
185 final Context context = getContext();
186 final PackageManager pm = context.getPackageManager();
187 final ActivityManager am = (ActivityManager)
188 context.getSystemService(Context.ACTIVITY_SERVICE);
189 final List<ActivityManager.RecentTaskInfo> recentTasks =
190 am.getRecentTasks(MAX_RECENT_TASKS, ActivityManager.RECENT_IGNORE_UNAVAILABLE);
192 ActivityInfo homeInfo =
193 new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME)
194 .resolveActivityInfo(pm, 0);
196 IconUtilities iconUtilities = new IconUtilities(getContext());
198 // Performance note: Our android performance guide says to prefer Iterator when
199 // using a List class, but because we know that getRecentTasks() always returns
200 // an ArrayList<>, we'll use a simple index instead.
202 int numTasks = recentTasks.size();
203 for (int i = 0; i < numTasks && (index < NUM_BUTTONS); ++i) {
204 final ActivityManager.RecentTaskInfo info = recentTasks.get(i);
206 // for debug purposes only, disallow first result to create empty lists
207 if (DBG_FORCE_EMPTY_LIST && (i == 0)) continue;
209 Intent intent = new Intent(info.baseIntent);
210 if (info.origActivity != null) {
211 intent.setComponent(info.origActivity);
214 // Skip the current home activity.
215 if (homeInfo != null) {
216 if (homeInfo.packageName.equals(
217 intent.getComponent().getPackageName())
218 && homeInfo.name.equals(
219 intent.getComponent().getClassName())) {
224 intent.setFlags((intent.getFlags()&~Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED)
225 | Intent.FLAG_ACTIVITY_NEW_TASK);
226 final ResolveInfo resolveInfo = pm.resolveActivity(intent, 0);
227 if (resolveInfo != null) {
228 final ActivityInfo activityInfo = resolveInfo.activityInfo;
229 final String title = activityInfo.loadLabel(pm).toString();
230 Drawable icon = activityInfo.loadIcon(pm);
232 if (title != null && title.length() > 0 && icon != null) {
233 final TextView tv = mIcons[index];
235 icon = iconUtilities.createIconDrawable(icon);
236 tv.setCompoundDrawables(null, icon, null, null);
238 tv.setVisibility(View.VISIBLE);
239 tv.setPressed(false);
246 // handle the case of "no icons to show"
247 mNoAppsText.setVisibility((index == 0) ? View.VISIBLE : View.GONE);
250 for (; index < NUM_BUTTONS; ++index) {
251 mIcons[index].setVisibility(View.GONE);
256 * This is the listener for the ACTION_CLOSE_SYSTEM_DIALOGS intent. It's an indication that
257 * we should close ourselves immediately, in order to allow a higher-priority UI to take over
258 * (e.g. phone call received).
260 private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
262 public void onReceive(Context context, Intent intent) {
263 String action = intent.getAction();
264 if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)) {
265 String reason = intent.getStringExtra(PhoneWindowManager.SYSTEM_DIALOG_REASON_KEY);
266 if (! PhoneWindowManager.SYSTEM_DIALOG_REASON_RECENT_APPS.equals(reason)) {