summaryrefslogtreecommitdiffstats
path: root/packages
diff options
context:
space:
mode:
authorWinson Chung <winsonc@winsonc-macpro.mtv.corp.google.com>2014-04-30 17:11:13 -0700
committerWinson Chung <winsonc@google.com>2014-05-02 18:45:40 -0700
commitf7bca430d9356c26d6df222d2c90bc7668262f6b (patch)
treeb5eedce7233d680f86461839bfb1bfc2dec3b36c /packages
parentf5e22e71cb5f8699a4312c797af068f655cbe629 (diff)
downloadframeworks_base-f7bca430d9356c26d6df222d2c90bc7668262f6b.zip
frameworks_base-f7bca430d9356c26d6df222d2c90bc7668262f6b.tar.gz
frameworks_base-f7bca430d9356c26d6df222d2c90bc7668262f6b.tar.bz2
Adding ability to load a search widget into Recents.
Change-Id: Ie17d9b9a47c979774b39a37e87f75d9dadc79ad9
Diffstat (limited to 'packages')
-rw-r--r--packages/SystemUI/AndroidManifest.xml3
-rw-r--r--packages/SystemUI/res/values/dimens.xml5
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/Console.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/Constants.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java128
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java71
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsService.java30
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java102
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java117
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java17
10 files changed, 362 insertions, 120 deletions
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index e6cdda0..6b62c25 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -98,6 +98,9 @@
<uses-permission android:name="android.permission.ACCESS_KEYGUARD_SECURE_STORAGE" />
<uses-permission android:name="android.permission.TRUST_LISTENER" />
+ <!-- Recents -->
+ <uses-permission android:name="android.permission.BIND_APPWIDGET" />
+
<!-- Wifi Display -->
<uses-permission android:name="android.permission.CONFIGURE_WIFI_DISPLAY" />
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 2f2914c..1900fea 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -231,10 +231,7 @@
<dimen name="recents_task_stack_scroll_dismiss_info_pane_distance">50dp</dimen>
<!-- The height of the search bar space. -->
- <dimen name="recents_search_bar_space_height">40dp</dimen>
-
- <!-- The search bar edge margins. -->
- <dimen name="recents_search_bar_space_edge_margins">12dp</dimen>
+ <dimen name="recents_search_bar_space_height">64dp</dimen>
<!-- Used to calculate the translation animation duration, the expected amount of movement
in dps over one second of time. -->
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Console.java b/packages/SystemUI/src/com/android/systemui/recents/Console.java
index 4b75c99..c8d97cc 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Console.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Console.java
@@ -37,7 +37,7 @@ public class Console {
public static final String AnsiRed = "\u001B[31m"; // SystemUIHandshake
public static final String AnsiGreen = "\u001B[32m"; // MeasureAndLayout
public static final String AnsiYellow = "\u001B[33m"; // SynchronizeViewsWithModel
- public static final String AnsiBlue = "\u001B[34m"; // TouchEvents
+ public static final String AnsiBlue = "\u001B[34m"; // TouchEvents, Search
public static final String AnsiPurple = "\u001B[35m"; // Draw
public static final String AnsiCyan = "\u001B[36m"; // ClickEvents
public static final String AnsiWhite = "\u001B[37m";
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Constants.java b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
index 9b0150e..bc8ab45 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Constants.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
@@ -30,7 +30,7 @@ public class Constants {
public static final boolean EnableTaskStackClipping = false;
public static final boolean EnableTaskBarThemeColors = true;
public static final boolean EnableInfoPane = true;
- public static final boolean EnableSearchButton = false;
+ public static final boolean EnableSearchButton = true;
// This disables the bitmap and icon caches
public static final boolean DisableBackgroundCache = false;
@@ -52,6 +52,7 @@ public class Constants {
public static final boolean SystemUIHandshake = false;
public static final boolean TimeSystemCalls = false;
public static final boolean Memory = false;
+ public static final boolean Search = false;
}
public static class UI {
@@ -72,6 +73,10 @@ public class Constants {
}
public static class Values {
+ public static class App {
+ public static int AppWidgetHostId = 1024;
+ public static String Key_SearchAppWidgetId = "searchAppWidgetId";
+ }
public static class Window {
// The dark background dim is set behind the empty recents view
public static final float DarkBackgroundDim = 0.5f;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index 71c45f2..110130b 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -17,11 +17,17 @@
package com.android.systemui.recents;
import android.app.Activity;
+import android.appwidget.AppWidgetHost;
+import android.appwidget.AppWidgetHostView;
+import android.appwidget.AppWidgetManager;
+import android.appwidget.AppWidgetProviderInfo;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.SharedPreferences;
import android.os.Bundle;
+import android.util.Pair;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
@@ -33,13 +39,37 @@ import com.android.systemui.recents.views.RecentsView;
import java.util.ArrayList;
+/** Our special app widget host */
+class RecentsAppWidgetHost extends AppWidgetHost {
+ /* Callbacks to notify when an app package changes */
+ interface RecentsAppWidgetHostCallbacks {
+ public void onProviderChanged(int appWidgetId, AppWidgetProviderInfo appWidgetInfo);
+ }
+
+ RecentsAppWidgetHostCallbacks mCb;
+
+ public RecentsAppWidgetHost(Context context, int hostId, RecentsAppWidgetHostCallbacks cb) {
+ super(context, hostId);
+ mCb = cb;
+ }
+
+ @Override
+ protected void onProviderChanged(int appWidgetId, AppWidgetProviderInfo appWidget) {
+ mCb.onProviderChanged(appWidgetId, appWidget);
+ }
+}
/* Activity */
-public class RecentsActivity extends Activity implements RecentsView.RecentsViewCallbacks {
+public class RecentsActivity extends Activity implements RecentsView.RecentsViewCallbacks,
+ RecentsAppWidgetHost.RecentsAppWidgetHostCallbacks{
FrameLayout mContainerView;
RecentsView mRecentsView;
View mEmptyView;
+ AppWidgetHost mAppWidgetHost;
+ AppWidgetProviderInfo mSearchAppWidgetInfo;
+ AppWidgetHostView mSearchAppWidgetHostView;
+
boolean mVisible;
boolean mTaskLaunched;
@@ -102,6 +132,75 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
}
}
+ /** Attempts to allocate and bind the search bar app widget */
+ void bindSearchBarAppWidget() {
+ if (Constants.DebugFlags.App.EnableSearchButton) {
+ RecentsConfiguration config = RecentsConfiguration.getInstance();
+ SystemServicesProxy ssp = RecentsTaskLoader.getInstance().getSystemServicesProxy();
+
+ // Reset the host view and widget info
+ mSearchAppWidgetHostView = null;
+ mSearchAppWidgetInfo = null;
+
+ // Try and load the app widget id from the settings
+ int appWidgetId = config.searchBarAppWidgetId;
+ if (appWidgetId >= 0) {
+ mSearchAppWidgetInfo = ssp.getAppWidgetInfo(appWidgetId);
+ if (mSearchAppWidgetInfo == null) {
+ // If there is no actual widget associated with that id, then delete it and
+ // prepare to bind another app widget in its place
+ ssp.unbindSearchAppWidget(mAppWidgetHost, appWidgetId);
+ appWidgetId = -1;
+ }
+ Console.log(Constants.DebugFlags.App.SystemUIHandshake,
+ "[RecentsActivity|onCreate|settings|appWidgetId]",
+ "Id: " + appWidgetId,
+ Console.AnsiBlue);
+ }
+
+ // If there is no id, then bind a new search app widget
+ if (appWidgetId < 0) {
+ Pair<Integer, AppWidgetProviderInfo> widgetInfo =
+ ssp.bindSearchAppWidget(mAppWidgetHost);
+ if (widgetInfo != null) {
+ Console.log(Constants.DebugFlags.App.SystemUIHandshake,
+ "[RecentsActivity|onCreate|searchWidget]",
+ "Id: " + widgetInfo.first + " Info: " + widgetInfo.second,
+ Console.AnsiBlue);
+
+ // Save the app widget id into the settings
+ config.updateSearchBarAppWidgetId(this, widgetInfo.first);
+ mSearchAppWidgetInfo = widgetInfo.second;
+ }
+ }
+ }
+ }
+
+ /** Creates the search bar app widget view */
+ void addSearchBarAppWidgetView() {
+ if (Constants.DebugFlags.App.EnableSearchButton) {
+ RecentsConfiguration config = RecentsConfiguration.getInstance();
+ int appWidgetId = config.searchBarAppWidgetId;
+ if (appWidgetId >= 0) {
+ Console.log(Constants.DebugFlags.App.SystemUIHandshake,
+ "[RecentsActivity|onCreate|addSearchAppWidgetView]",
+ "Id: " + appWidgetId,
+ Console.AnsiBlue);
+ mSearchAppWidgetHostView = mAppWidgetHost.createView(this, appWidgetId,
+ mSearchAppWidgetInfo);
+ Bundle opts = new Bundle();
+ opts.putInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY,
+ AppWidgetProviderInfo.WIDGET_CATEGORY_RECENTS);
+ mSearchAppWidgetHostView.updateAppWidgetOptions(opts);
+ // Set the padding to 0 for this search widget
+ mSearchAppWidgetHostView.setPadding(0, 0, 0, 0);
+ mRecentsView.setSearchBar(mSearchAppWidgetHostView);
+ } else {
+ mRecentsView.setSearchBar(null);
+ }
+ }
+ }
+
/** Dismisses recents if we are already visible and the intent is to toggle the recents view */
boolean dismissRecentsIfVisible() {
if (mVisible) {
@@ -127,6 +226,9 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
RecentsTaskLoader.initialize(this);
RecentsConfiguration.reinitialize(this);
+ // Initialize the widget host (the host id is static and does not change)
+ mAppWidgetHost = new RecentsAppWidgetHost(this, Constants.Values.App.AppWidgetHostId, this);
+
// Create the view hierarchy
mRecentsView = new RecentsView(this);
mRecentsView.setCallbacks(this);
@@ -145,6 +247,11 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
// Update the recent tasks
updateRecentsTasks(getIntent());
+
+ // Bind the search app widget when we first start up
+ bindSearchBarAppWidget();
+ // Add the search bar layout
+ addSearchBarAppWidgetView();
}
@Override
@@ -165,6 +272,9 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
// Update the recent tasks
updateRecentsTasks(intent);
+
+ // Don't attempt to rebind the search bar widget, but just add the search bar layout
+ addSearchBarAppWidgetView();
}
@Override
@@ -172,6 +282,7 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
Console.log(Constants.DebugFlags.App.SystemUIHandshake, "[RecentsActivity|onStart]", "",
Console.AnsiRed);
super.onStart();
+ mAppWidgetHost.startListening();
mVisible = true;
}
@@ -225,6 +336,7 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
Console.AnsiRed);
super.onStop();
+ mAppWidgetHost.stopListening();
mVisible = false;
mTaskLaunched = false;
}
@@ -265,4 +377,18 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
public void onTaskLaunching() {
mTaskLaunched = true;
}
+
+ @Override
+ public void onProviderChanged(int appWidgetId, AppWidgetProviderInfo appWidgetInfo) {
+ RecentsConfiguration config = RecentsConfiguration.getInstance();
+ SystemServicesProxy ssp = RecentsTaskLoader.getInstance().getSystemServicesProxy();
+ if (appWidgetId > -1 && appWidgetId == config.searchBarAppWidgetId) {
+ // The search provider may have changed, so just delete the old widget and bind it again
+ ssp.unbindSearchAppWidget(mAppWidgetHost, appWidgetId);
+ config.updateSearchBarAppWidgetId(this, -1);
+ // Load the widget again
+ bindSearchBarAppWidget();
+ addSearchBarAppWidgetView();
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
index aac0bd5..5a1dc8d 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
@@ -17,6 +17,7 @@
package com.android.systemui.recents;
import android.content.Context;
+import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Rect;
@@ -35,6 +36,9 @@ public class RecentsConfiguration {
public Rect systemInsets = new Rect();
public Rect displayRect = new Rect();
+ boolean isLandscape;
+ int searchBarAppWidgetId = -1;
+
public float animationPxMovementPerSecond;
public int filteringCurrentViewsMinAnimDuration;
@@ -46,7 +50,6 @@ public class RecentsConfiguration {
public int taskViewInfoPaneAnimDuration;
public int taskViewRoundedCornerRadiusPx;
public int searchBarSpaceHeightPx;
- public int searchBarSpaceEdgeMarginsPx;
public int taskBarViewDefaultBackgroundColor;
public int taskBarViewDefaultTextColor;
@@ -78,7 +81,7 @@ public class RecentsConfiguration {
DisplayMetrics dm = res.getDisplayMetrics();
mDisplayMetrics = dm;
- boolean isLandscape = res.getConfiguration().orientation ==
+ isLandscape = res.getConfiguration().orientation ==
Configuration.ORIENTATION_LANDSCAPE;
Console.log(Constants.DebugFlags.UI.MeasureAndLayout,
"[RecentsConfiguration|orientation]", isLandscape ? "Landscape" : "Portrait",
@@ -103,8 +106,7 @@ public class RecentsConfiguration {
taskViewRoundedCornerRadiusPx =
res.getDimensionPixelSize(R.dimen.recents_task_view_rounded_corners_radius);
searchBarSpaceHeightPx = res.getDimensionPixelSize(R.dimen.recents_search_bar_space_height);
- searchBarSpaceEdgeMarginsPx =
- res.getDimensionPixelSize(R.dimen.recents_search_bar_space_edge_margins);
+
taskBarViewDefaultBackgroundColor =
res.getColor(R.color.recents_task_bar_default_background_color);
@@ -114,6 +116,10 @@ public class RecentsConfiguration {
res.getColor(R.color.recents_task_bar_light_text_color);
taskBarViewDarkTextColor =
res.getColor(R.color.recents_task_bar_dark_text_color);
+
+ // Update the search widget id
+ SharedPreferences settings = context.getSharedPreferences(context.getPackageName(), 0);
+ searchBarAppWidgetId = settings.getInt(Constants.Values.App.Key_SearchAppWidgetId, -1);
}
/** Updates the system insets */
@@ -121,24 +127,57 @@ public class RecentsConfiguration {
systemInsets.set(insets);
}
- /** Returns the search bar bounds in the specified orientation */
- public void getSearchBarBounds(int width, int height,
- Rect searchBarSpaceBounds, Rect searchBarBounds) {
+ /** Updates the search bar app widget */
+ public void updateSearchBarAppWidgetId(Context context, int appWidgetId) {
+ searchBarAppWidgetId = appWidgetId;
+ SharedPreferences settings = context.getSharedPreferences(context.getPackageName(), 0);
+ settings.edit().putInt(Constants.Values.App.Key_SearchAppWidgetId,
+ appWidgetId).apply();
+ }
+
+ /** Returns whether the search bar app widget exists */
+ public boolean hasSearchBarAppWidget() {
+ return searchBarAppWidgetId >= 0;
+ }
+
+ /**
+ * Returns the task stack bounds in the current orientation. These bounds do not account for
+ * the system insets.
+ */
+ public void getTaskStackBounds(int width, int height, Rect taskStackBounds) {
+ if (hasSearchBarAppWidget()) {
+ Rect searchBarBounds = new Rect();
+ getSearchBarBounds(width, height, searchBarBounds);
+ if (isLandscape) {
+ // In landscape, the search bar appears on the left, so shift the task rect right
+ taskStackBounds.set(searchBarBounds.width(), 0, width, height);
+ } else {
+ // In portrait, the search bar appears on the top, so shift the task rect below
+ taskStackBounds.set(0, searchBarBounds.height(), width, height);
+ }
+ } else {
+ taskStackBounds.set(0, 0, width, height);
+ }
+ }
+
+ /**
+ * Returns the search bar bounds in the current orientation. These bounds do not account for
+ * the system insets.
+ */
+ public void getSearchBarBounds(int width, int height, Rect searchBarSpaceBounds) {
// Return empty rects if search is not enabled
if (!Constants.DebugFlags.App.EnableSearchButton) {
searchBarSpaceBounds.set(0, 0, 0, 0);
- searchBarBounds.set(0, 0, 0, 0);
return;
}
- // Calculate the search bar bounds, and account for the system insets
- int edgeMarginPx = searchBarSpaceEdgeMarginsPx;
- int availableWidth = width - systemInsets.left - systemInsets.right;
- searchBarSpaceBounds.set(0, 0, availableWidth, 2 * edgeMarginPx + searchBarSpaceHeightPx);
-
- // Inset from the search bar space to get the search bar bounds
- searchBarBounds.set(searchBarSpaceBounds);
- searchBarBounds.inset(edgeMarginPx, edgeMarginPx);
+ if (isLandscape) {
+ // In landscape, the search bar appears on the left
+ searchBarSpaceBounds.set(0, 0, searchBarSpaceHeightPx, height);
+ } else {
+ // In portrait, the search bar appears on the top
+ searchBarSpaceBounds.set(0, 0, width, searchBarSpaceHeightPx);
+ }
}
/** Converts from DPs to PXs */
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java
index 36b761e..0c6ed84 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java
@@ -60,39 +60,41 @@ class SystemUIMessageHandler extends Handler {
Rect windowRect = data.getParcelable(AlternateRecentsComponent.KEY_WINDOW_RECT);
Rect systemInsets = data.getParcelable(AlternateRecentsComponent.KEY_SYSTEM_INSETS);
+ // NOTE: None of the rects computed below need to be offset for the status bar,
+ // since that is done when we compute the animation itself in the Recents component
+
// Create a dummy task stack & compute the rect for the thumbnail to animate to
TaskStack stack = new TaskStack(context);
TaskStackView tsv = new TaskStackView(context, stack);
Bundle replyData = new Bundle();
TaskViewTransform transform;
- // Get the search bar bounds so that we can account for its height in the children
- Rect searchBarSpaceBounds = new Rect();
- Rect searchBarBounds = new Rect();
+ // Get the task stack and search bar bounds
+ Rect taskStackBounds = new Rect();
RecentsConfiguration config = RecentsConfiguration.getInstance();
- config.getSearchBarBounds(windowRect.width(), windowRect.height(),
- searchBarSpaceBounds, searchBarBounds);
+ config.getTaskStackBounds(windowRect.width(), windowRect.height(), taskStackBounds);
+
+ // Calculate the target task rect for when there is one task.
- // Calculate the target task rect for when there is one task
// NOTE: Since the nav bar height is already accounted for in the windowRect, don't
- // pass in a bottom inset
+ // pass in a left or bottom inset
stack.addTask(new Task());
- tsv.computeRects(windowRect.width(), windowRect.height() - systemInsets.top -
- systemInsets.bottom - searchBarSpaceBounds.height(), 0);
+ tsv.computeRects(taskStackBounds.width(), taskStackBounds.height() -
+ systemInsets.top - systemInsets.bottom, 0, 0);
tsv.boundScroll();
transform = tsv.getStackTransform(0, tsv.getStackScroll());
- transform.rect.offset(0, searchBarSpaceBounds.height());
+ transform.rect.offset(taskStackBounds.left, taskStackBounds.top);
replyData.putParcelable(AlternateRecentsComponent.KEY_SINGLE_TASK_STACK_RECT,
new Rect(transform.rect));
- // Also calculate the target task rect when there are multiple tasks
+ // Also calculate the target task rect when there are multiple tasks.
stack.addTask(new Task());
- tsv.computeRects(windowRect.width(), windowRect.height() - systemInsets.top -
- systemInsets.bottom - searchBarSpaceBounds.height(), 0);
+ tsv.computeRects(taskStackBounds.width(), taskStackBounds.height() -
+ systemInsets.top - systemInsets.bottom, 0, 0);
tsv.setStackScrollRaw(Integer.MAX_VALUE);
tsv.boundScroll();
transform = tsv.getStackTransform(1, tsv.getStackScroll());
- transform.rect.offset(0, searchBarSpaceBounds.height());
+ transform.rect.offset(taskStackBounds.left, taskStackBounds.top);
replyData.putParcelable(AlternateRecentsComponent.KEY_MULTIPLE_TASK_STACK_RECT,
new Rect(transform.rect));
diff --git a/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java
index a8bf2fb..68af663 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java
@@ -20,6 +20,9 @@ import android.app.ActivityManager;
import android.app.ActivityOptions;
import android.app.AppGlobals;
import android.app.SearchManager;
+import android.appwidget.AppWidgetHost;
+import android.appwidget.AppWidgetManager;
+import android.appwidget.AppWidgetProviderInfo;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -34,6 +37,7 @@ import android.os.Bundle;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
+import android.util.Pair;
import java.util.ArrayList;
import java.util.List;
@@ -45,6 +49,7 @@ import java.util.Random;
*/
public class SystemServicesProxy {
ActivityManager mAm;
+ AppWidgetManager mAwm;
PackageManager mPm;
IPackageManager mIpm;
UserManager mUm;
@@ -56,6 +61,7 @@ public class SystemServicesProxy {
/** Private constructor */
public SystemServicesProxy(Context context) {
mAm = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+ mAwm = AppWidgetManager.getInstance(context);
mPm = context.getPackageManager();
mUm = (UserManager) context.getSystemService(Context.USER_SERVICE);
mIpm = AppGlobals.getPackageManager();
@@ -103,7 +109,7 @@ public class SystemServicesProxy {
return mAm.getRecentTasksForUser(numTasks,
ActivityManager.RECENT_IGNORE_UNAVAILABLE |
- ActivityManager.RECENT_INCLUDE_PROFILES, userId);
+ ActivityManager.RECENT_INCLUDE_PROFILES, userId);
}
/** Returns a list of the running tasks */
@@ -162,7 +168,7 @@ public class SystemServicesProxy {
/**
* Returns the activity info for a given component name.
*
- * @param ComponentName The component name of the activity.
+ * @param cn The component name of the activity.
* @param userId The userId of the user that this is for.
*/
public ActivityInfo getActivityInfo(ComponentName cn, int userId) {
@@ -177,6 +183,23 @@ public class SystemServicesProxy {
}
}
+ /**
+ * Returns the activity info for a given component name.
+ *
+ * @param cn The component name of the activity.
+ */
+ public ActivityInfo getActivityInfo(ComponentName cn) {
+ if (mPm == null) return null;
+ if (Constants.DebugFlags.App.EnableSystemServicesProxy) return null;
+
+ try {
+ return mPm.getActivityInfo(cn, PackageManager.GET_META_DATA);
+ } catch (PackageManager.NameNotFoundException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
/** Returns the activity label */
public String getActivityLabel(ActivityInfo info) {
if (mPm == null) return null;
@@ -208,27 +231,70 @@ public class SystemServicesProxy {
return icon;
}
-
/**
- * Composes an intent to launch the global search activity.
+ * Resolves and binds the search app widget that is to appear in the recents.
*/
- public Intent getGlobalSearchIntent(Rect sourceBounds) {
- if (mSm == null) return null;
+ public Pair<Integer, AppWidgetProviderInfo> bindSearchAppWidget(AppWidgetHost host) {
+ if (mAwm == null) return null;
- // Try and get the global search activity
+ // Ensure we have a global search activity
ComponentName globalSearchActivity = mSm.getGlobalSearchActivity();
if (globalSearchActivity == null) return null;
- // Bundle the source of the search
- Bundle appSearchData = new Bundle();
- appSearchData.putString("source", mPackage);
-
- // Compose the intent and Start the search activity
- Intent intent = new Intent(SearchManager.INTENT_ACTION_GLOBAL_SEARCH);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- intent.setComponent(globalSearchActivity);
- intent.putExtra(SearchManager.APP_DATA, appSearchData);
- intent.setSourceBounds(sourceBounds);
- return intent;
+ // Resolve the search widget provider from the search activity
+ ActivityInfo searchActivityInfo = getActivityInfo(globalSearchActivity);
+ if (searchActivityInfo == null) return null;
+
+ String key = "com.android.recents.search_widget_provider";
+ ComponentName searchWidgetCn = null;
+ Bundle searchMetaData = searchActivityInfo.metaData;
+ String searchWidgetProvider = searchMetaData.getString(key, "");
+ if (searchWidgetProvider.length() != 0) {
+ searchWidgetCn = ComponentName.unflattenFromString(searchWidgetProvider);
+ } else {
+ return null;
+ }
+
+ // Find the first Recents widget from the same package as the global search activity
+ List<AppWidgetProviderInfo> widgets = mAwm.getInstalledProviders();
+ AppWidgetProviderInfo searchWidgetInfo = null;
+ for (AppWidgetProviderInfo info : widgets) {
+ if (info.provider.equals(searchWidgetCn)) {
+ searchWidgetInfo = info;
+ break;
+ }
+ }
+
+ // Return early if there is no search widget
+ if (searchWidgetInfo == null) return null;
+
+ // Allocate a new widget id and try and bind the app widget (if that fails, then just skip)
+ int searchWidgetId = host.allocateAppWidgetId();
+ Bundle opts = new Bundle();
+ opts.putInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY,
+ AppWidgetProviderInfo.WIDGET_CATEGORY_RECENTS);
+ if (!mAwm.bindAppWidgetIdIfAllowed(searchWidgetId, searchWidgetInfo.provider, opts)) {
+ return null;
+ }
+ return new Pair<Integer, AppWidgetProviderInfo>(searchWidgetId, searchWidgetInfo);
+ }
+
+ /**
+ * Returns the app widget info for the specified app widget id.
+ */
+ public AppWidgetProviderInfo getAppWidgetInfo(int appWidgetId) {
+ if (mAwm == null) return null;
+
+ return mAwm.getAppWidgetInfo(appWidgetId);
+ }
+
+ /**
+ * Destroys the specified app widget.
+ */
+ public void unbindSearchAppWidget(AppWidgetHost host, int appWidgetId) {
+ if (mAwm == null) return;
+
+ // Delete the app widget
+ host.deleteAppWidgetId(appWidgetId);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index a04cd3e..c2e8275 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -27,11 +27,9 @@ import android.graphics.Rect;
import android.net.Uri;
import android.os.UserHandle;
import android.provider.Settings;
-import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.FrameLayout;
-import android.widget.TextView;
import com.android.systemui.recents.Console;
import com.android.systemui.recents.Constants;
import com.android.systemui.recents.RecentsConfiguration;
@@ -39,7 +37,6 @@ import com.android.systemui.recents.RecentsTaskLoader;
import com.android.systemui.recents.model.SpaceNode;
import com.android.systemui.recents.model.Task;
import com.android.systemui.recents.model.TaskStack;
-import com.android.systemui.R;
import java.util.ArrayList;
@@ -57,6 +54,8 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
// The space partitioning root of this container
SpaceNode mBSP;
+ // Whether there are any tasks
+ boolean mHasTasks;
// Search bar view
View mSearchBar;
// Recents view callbacks
@@ -80,22 +79,14 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
mBSP = n;
// Create and add all the stacks for this partition of space.
- boolean hasTasks = false;
+ mHasTasks = false;
removeAllViews();
ArrayList<TaskStack> stacks = mBSP.getStacks();
for (TaskStack stack : stacks) {
TaskStackView stackView = new TaskStackView(getContext(), stack);
stackView.setCallbacks(this);
addView(stackView);
- hasTasks |= (stack.getTaskCount() > 0);
- }
-
- // Create the search bar (and hide it if we have no recent tasks)
- if (Constants.DebugFlags.App.EnableSearchButton) {
- createSearchBar();
- if (!hasTasks) {
- mSearchBar.setVisibility(View.GONE);
- }
+ mHasTasks |= (stack.getTaskCount() > 0);
}
}
@@ -130,19 +121,30 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
return false;
}
- /** Creates and adds the search bar */
- void createSearchBar() {
- // Create a temporary search bar
- mSearchBar = mInflater.inflate(R.layout.recents_search_bar, this, false);
- mSearchBar.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- onSearchTriggered();
+ /** Adds the search bar */
+ public void setSearchBar(View searchBar) {
+ // Create the search bar (and hide it if we have no recent tasks)
+ if (Constants.DebugFlags.App.EnableSearchButton) {
+ // Remove the previous search bar if one exists
+ if (mSearchBar != null && indexOfChild(mSearchBar) > -1) {
+ removeView(mSearchBar);
}
- });
- addView(mSearchBar);
+ // Add the new search bar
+ if (searchBar != null) {
+ mSearchBar = searchBar;
+ mSearchBar.setVisibility(mHasTasks ? View.VISIBLE : View.GONE);
+ addView(mSearchBar);
+
+ Console.log(Constants.DebugFlags.App.SystemUIHandshake, "[RecentsView|setSearchBar]",
+ "" + (mSearchBar.getVisibility() == View.VISIBLE),
+ Console.AnsiBlue);
+ }
+ }
}
+ /**
+ * This is called with the full size of the window since we are handling our own insets.
+ */
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = MeasureSpec.getSize(widthMeasureSpec);
@@ -155,22 +157,26 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
Console.logTraceTime(Constants.DebugFlags.App.TimeRecentsStartup,
Constants.DebugFlags.App.TimeRecentsStartupKey, "RecentsView.onMeasure");
- // Get the search bar bounds so that we can account for its height in the children
- Rect searchBarSpaceBounds = new Rect();
- Rect searchBarBounds = new Rect();
+ // Get the search bar bounds and measure the search bar layout
RecentsConfiguration config = RecentsConfiguration.getInstance();
- config.getSearchBarBounds(getMeasuredWidth(), getMeasuredHeight(),
- searchBarSpaceBounds, searchBarBounds);
if (mSearchBar != null) {
- mSearchBar.measure(MeasureSpec.makeMeasureSpec(searchBarSpaceBounds.width(), widthMode),
- MeasureSpec.makeMeasureSpec(searchBarSpaceBounds.height(), heightMode));
+ Rect searchBarSpaceBounds = new Rect();
+ config.getSearchBarBounds(width, height - config.systemInsets.top, searchBarSpaceBounds);
+ mSearchBar.measure(
+ MeasureSpec.makeMeasureSpec(searchBarSpaceBounds.width(), MeasureSpec.EXACTLY),
+ MeasureSpec.makeMeasureSpec(searchBarSpaceBounds.height(), MeasureSpec.EXACTLY));
}
- // We measure our stack views sans the status bar. It will handle the nav bar itself.
+ // We give the full width of the space, not including the right nav bar insets in landscape,
+ // to the stack view, since we want the tasks to render under the search bar in landscape.
+ // In addition, we give it the full height, not including the top inset or search bar space,
+ // since we want the tasks to render under the navigation buttons in portrait.
+ Rect taskStackBounds = new Rect();
+ config.getTaskStackBounds(width, height, taskStackBounds);
int childWidth = width - config.systemInsets.right;
- int childHeight = height - config.systemInsets.top - searchBarSpaceBounds.height();
+ int childHeight = taskStackBounds.height() - config.systemInsets.top;
- // Measure each child
+ // Measure each TaskStackView
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
@@ -183,6 +189,9 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
setMeasuredDimension(width, height);
}
+ /**
+ * This is called with the full size of the window since we are handling our own insets.
+ */
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
Console.log(Constants.DebugFlags.UI.MeasureAndLayout, "[RecentsView|layout]",
@@ -190,21 +199,24 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
Console.logTraceTime(Constants.DebugFlags.App.TimeRecentsStartup,
Constants.DebugFlags.App.TimeRecentsStartupKey, "RecentsView.onLayout");
- // Get the search bar bounds so that we can account for its height in the children
- Rect searchBarSpaceBounds = new Rect();
- Rect searchBarBounds = new Rect();
+ // Get the search bar bounds so that we lay it out
RecentsConfiguration config = RecentsConfiguration.getInstance();
- config.getSearchBarBounds(getMeasuredWidth(), getMeasuredHeight(),
- searchBarSpaceBounds, searchBarBounds);
if (mSearchBar != null) {
+ Rect searchBarSpaceBounds = new Rect();
+ config.getSearchBarBounds(getMeasuredWidth(), getMeasuredHeight(), searchBarSpaceBounds);
mSearchBar.layout(config.systemInsets.left + searchBarSpaceBounds.left,
config.systemInsets.top + searchBarSpaceBounds.top,
config.systemInsets.left + mSearchBar.getMeasuredWidth(),
config.systemInsets.top + mSearchBar.getMeasuredHeight());
}
- // We offset our stack views by the status bar height. It will handle the nav bar itself.
- top += config.systemInsets.top + searchBarSpaceBounds.height();
+ // We offset the stack view by the left inset (if any), but lay it out under the search bar.
+ // In addition, we offset our stack views by the top inset and search bar height, but not
+ // the bottom insets because we want it to render under the navigation buttons.
+ Rect taskStackBounds = new Rect();
+ config.getTaskStackBounds(getMeasuredWidth(), getMeasuredHeight(), taskStackBounds);
+ left += config.systemInsets.left;
+ top += config.systemInsets.top + taskStackBounds.top;
// Layout each child
// XXX: Based on the space node for that task view
@@ -212,9 +224,8 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
if (child instanceof TaskStackView && child.getVisibility() != GONE) {
- int width = child.getMeasuredWidth();
- int height = child.getMeasuredHeight();
- child.layout(left, top, left + width, top + height);
+ TaskStackView tsv = (TaskStackView) child;
+ child.layout(left, top, left + tsv.getMeasuredWidth(), top + tsv.getMeasuredHeight());
}
}
}
@@ -374,24 +385,4 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
TaskStackBuilder.create(getContext())
.addNextIntentWithParentStack(intent).startActivities();
}
-
- public void onSearchTriggered() {
- // Get the search bar source bounds
- Rect searchBarSpaceBounds = new Rect();
- Rect searchBarBounds = new Rect();
- RecentsConfiguration config = RecentsConfiguration.getInstance();
- config.getSearchBarBounds(getMeasuredWidth(), getMeasuredHeight(),
- searchBarSpaceBounds, searchBarBounds);
-
- // Get the search intent and start it
- Intent searchIntent = RecentsTaskLoader.getInstance().getSystemServicesProxy()
- .getGlobalSearchIntent(searchBarBounds);
- if (searchIntent != null) {
- try {
- getContext().startActivity(searchIntent);
- } catch (ActivityNotFoundException anfe) {
- Console.logError(getContext(), "Could not start Search activity");
- }
- }
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index 0a8e76f..e273ecf 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -547,7 +547,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
}
/** Computes the stack and task rects */
- public void computeRects(int width, int height, int insetBottom) {
+ public void computeRects(int width, int height, int insetLeft, int insetBottom) {
// Note: We let the stack view be the full height because we want the cards to go under the
// navigation bar if possible. However, the stack rects which we use to calculate
// max scroll, etc. need to take the nav bar into account
@@ -555,6 +555,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
// Compute the stack rects
mRect.set(0, 0, width, height);
mStackRect.set(mRect);
+ mStackRect.left += insetLeft;
mStackRect.bottom -= insetBottom;
int smallestDimension = Math.min(width, height);
@@ -582,6 +583,11 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
updateMinMaxScroll(false);
}
+ /**
+ * This is called with the size of the space not including the top or right insets, or the
+ * search bar height in portrait (but including the search bar width in landscape, since we want
+ * to draw under it.
+ */
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = MeasureSpec.getSize(widthMeasureSpec);
@@ -592,7 +598,9 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
// Compute our stack/task rects
RecentsConfiguration config = RecentsConfiguration.getInstance();
- computeRects(width, height, config.systemInsets.bottom);
+ Rect taskStackBounds = new Rect();
+ config.getTaskStackBounds(width, height, taskStackBounds);
+ computeRects(width, height, taskStackBounds.left, config.systemInsets.bottom);
// Debug logging
if (Constants.DebugFlags.UI.MeasureAndLayout) {
@@ -630,6 +638,11 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
setMeasuredDimension(width, height);
}
+ /**
+ * This is called with the size of the space not including the top or right insets, or the
+ * search bar height in portrait (but including the search bar width in landscape, since we want
+ * to draw under it.
+ */
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
Console.log(Constants.DebugFlags.UI.MeasureAndLayout, "[TaskStackView|layout]",