1 /*
2  * Copyright (C) 2012 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.android.systemui.recent;
18 
19 import android.app.Activity;
20 import android.app.ActivityManager;
21 import android.app.WallpaperManager;
22 import android.content.BroadcastReceiver;
23 import android.content.Context;
24 import android.content.Intent;
25 import android.content.IntentFilter;
26 import android.os.Bundle;
27 import android.os.UserHandle;
28 import android.view.MotionEvent;
29 import android.view.View;
30 import android.view.WindowManager;
31 
32 import com.android.systemui.R;
33 import com.android.systemui.statusbar.StatusBarPanel;
34 
35 import java.util.List;
36 
37 public class RecentsActivity extends Activity {
38     public static final String TOGGLE_RECENTS_INTENT = "com.android.systemui.recent.action.TOGGLE_RECENTS";
39     public static final String PRELOAD_INTENT = "com.android.systemui.recent.action.PRELOAD";
40     public static final String CANCEL_PRELOAD_INTENT = "com.android.systemui.recent.CANCEL_PRELOAD";
41     public static final String CLOSE_RECENTS_INTENT = "com.android.systemui.recent.action.CLOSE";
42     public static final String WINDOW_ANIMATION_START_INTENT = "com.android.systemui.recent.action.WINDOW_ANIMATION_START";
43     public static final String PRELOAD_PERMISSION = "com.android.systemui.recent.permission.PRELOAD";
44     public static final String WAITING_FOR_WINDOW_ANIMATION_PARAM = "com.android.systemui.recent.WAITING_FOR_WINDOW_ANIMATION";
45     private static final String WAS_SHOWING = "was_showing";
46 
47     private RecentsPanelView mRecentsPanel;
48     private IntentFilter mIntentFilter;
49     private boolean mShowing;
50     private boolean mForeground;
51 
52     private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
53         @Override
54         public void onReceive(Context context, Intent intent) {
55             if (CLOSE_RECENTS_INTENT.equals(intent.getAction())) {
56                 if (mRecentsPanel != null && mRecentsPanel.isShowing()) {
57                     if (mShowing && !mForeground) {
58                         // Captures the case right before we transition to another activity
59                         mRecentsPanel.show(false);
60                     }
61                 }
62             } else if (WINDOW_ANIMATION_START_INTENT.equals(intent.getAction())) {
63                 if (mRecentsPanel != null) {
64                     mRecentsPanel.onWindowAnimationStart();
65                 }
66             }
67         }
68     };
69 
70     public class TouchOutsideListener implements View.OnTouchListener {
71         private StatusBarPanel mPanel;
72 
TouchOutsideListener(StatusBarPanel panel)73         public TouchOutsideListener(StatusBarPanel panel) {
74             mPanel = panel;
75         }
76 
onTouch(View v, MotionEvent ev)77         public boolean onTouch(View v, MotionEvent ev) {
78             final int action = ev.getAction();
79             if (action == MotionEvent.ACTION_OUTSIDE
80                     || (action == MotionEvent.ACTION_DOWN
81                     && !mPanel.isInContentArea((int) ev.getX(), (int) ev.getY()))) {
82                 dismissAndGoHome();
83                 return true;
84             }
85             return false;
86         }
87     }
88 
89     @Override
onPause()90     public void onPause() {
91         overridePendingTransition(
92                 R.anim.recents_return_to_launcher_enter,
93                 R.anim.recents_return_to_launcher_exit);
94         mForeground = false;
95         super.onPause();
96     }
97 
98     @Override
onStop()99     public void onStop() {
100         mShowing = false;
101         if (mRecentsPanel != null) {
102             mRecentsPanel.onUiHidden();
103         }
104         super.onStop();
105     }
106 
updateWallpaperVisibility(boolean visible)107     private void updateWallpaperVisibility(boolean visible) {
108         int wpflags = visible ? WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER : 0;
109         int curflags = getWindow().getAttributes().flags
110                 & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
111         if (wpflags != curflags) {
112             getWindow().setFlags(wpflags, WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER);
113         }
114     }
115 
forceOpaqueBackground(Context context)116     public static boolean forceOpaqueBackground(Context context) {
117         return WallpaperManager.getInstance(context).getWallpaperInfo() != null;
118     }
119 
120     @Override
onStart()121     public void onStart() {
122         // Hide wallpaper if it's not a static image
123         if (forceOpaqueBackground(this)) {
124             updateWallpaperVisibility(false);
125         } else {
126             updateWallpaperVisibility(true);
127         }
128         mShowing = true;
129         if (mRecentsPanel != null) {
130             // Call and refresh the recent tasks list in case we didn't preload tasks
131             // or in case we don't get an onNewIntent
132             mRecentsPanel.refreshRecentTasksList();
133             mRecentsPanel.refreshViews();
134         }
135         super.onStart();
136     }
137 
138     @Override
onResume()139     public void onResume() {
140         mForeground = true;
141         super.onResume();
142     }
143 
144     @Override
onBackPressed()145     public void onBackPressed() {
146         dismissAndGoBack();
147     }
148 
dismissAndGoHome()149     public void dismissAndGoHome() {
150         if (mRecentsPanel != null) {
151             Intent homeIntent = new Intent(Intent.ACTION_MAIN, null);
152             homeIntent.addCategory(Intent.CATEGORY_HOME);
153             homeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
154                     | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
155             startActivityAsUser(homeIntent, new UserHandle(UserHandle.USER_CURRENT));
156             mRecentsPanel.show(false);
157         }
158     }
159 
dismissAndGoBack()160     public void dismissAndGoBack() {
161         if (mRecentsPanel != null) {
162             final ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
163 
164             final List<ActivityManager.RecentTaskInfo> recentTasks =
165                     am.getRecentTasks(2,
166                             ActivityManager.RECENT_WITH_EXCLUDED |
167                             ActivityManager.RECENT_IGNORE_UNAVAILABLE |
168                             ActivityManager.RECENT_INCLUDE_PROFILES);
169             if (recentTasks.size() > 1 &&
170                     mRecentsPanel.simulateClick(recentTasks.get(1).persistentId)) {
171                 // recents panel will take care of calling show(false) through simulateClick
172                 return;
173             }
174             mRecentsPanel.show(false);
175         }
176         finish();
177     }
178 
179     @Override
onCreate(Bundle savedInstanceState)180     protected void onCreate(Bundle savedInstanceState) {
181         getWindow().addPrivateFlags(
182                 WindowManager.LayoutParams.PRIVATE_FLAG_INHERIT_TRANSLUCENT_DECOR);
183         setContentView(R.layout.status_bar_recent_panel);
184         mRecentsPanel = (RecentsPanelView) findViewById(R.id.recents_root);
185         mRecentsPanel.setOnTouchListener(new TouchOutsideListener(mRecentsPanel));
186         mRecentsPanel.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE
187                 | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
188                 | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
189 
190         final RecentTasksLoader recentTasksLoader = RecentTasksLoader.getInstance(this);
191         recentTasksLoader.setRecentsPanel(mRecentsPanel, mRecentsPanel);
192         mRecentsPanel.setMinSwipeAlpha(
193                 getResources().getInteger(R.integer.config_recent_item_min_alpha) / 100f);
194 
195         if (savedInstanceState == null ||
196                 savedInstanceState.getBoolean(WAS_SHOWING)) {
197             handleIntent(getIntent(), (savedInstanceState == null));
198         }
199         mIntentFilter = new IntentFilter();
200         mIntentFilter.addAction(CLOSE_RECENTS_INTENT);
201         mIntentFilter.addAction(WINDOW_ANIMATION_START_INTENT);
202         registerReceiver(mIntentReceiver, mIntentFilter);
203         super.onCreate(savedInstanceState);
204     }
205 
206     @Override
onSaveInstanceState(Bundle outState)207     protected void onSaveInstanceState(Bundle outState) {
208         outState.putBoolean(WAS_SHOWING, mRecentsPanel.isShowing());
209     }
210 
211     @Override
onDestroy()212     protected void onDestroy() {
213         RecentTasksLoader.getInstance(this).setRecentsPanel(null, mRecentsPanel);
214         unregisterReceiver(mIntentReceiver);
215         super.onDestroy();
216     }
217 
218     @Override
onNewIntent(Intent intent)219     protected void onNewIntent(Intent intent) {
220         handleIntent(intent, true);
221     }
222 
handleIntent(Intent intent, boolean checkWaitingForAnimationParam)223     private void handleIntent(Intent intent, boolean checkWaitingForAnimationParam) {
224         super.onNewIntent(intent);
225 
226         if (TOGGLE_RECENTS_INTENT.equals(intent.getAction())) {
227             if (mRecentsPanel != null) {
228                 if (mRecentsPanel.isShowing()) {
229                     dismissAndGoBack();
230                 } else {
231                     final RecentTasksLoader recentTasksLoader = RecentTasksLoader.getInstance(this);
232                     boolean waitingForWindowAnimation = checkWaitingForAnimationParam &&
233                             intent.getBooleanExtra(WAITING_FOR_WINDOW_ANIMATION_PARAM, false);
234                     mRecentsPanel.show(true, recentTasksLoader.getLoadedTasks(),
235                             recentTasksLoader.isFirstScreenful(), waitingForWindowAnimation);
236                 }
237             }
238         }
239     }
240 
isForeground()241     boolean isForeground() {
242         return mForeground;
243     }
244 
isActivityShowing()245     boolean isActivityShowing() {
246          return mShowing;
247     }
248 }
249