diff options
author | Winson Chung <winsonc@winsonc-macpro.mtv.corp.google.com> | 2014-04-30 17:11:13 -0700 |
---|---|---|
committer | Winson Chung <winsonc@google.com> | 2014-05-02 18:45:40 -0700 |
commit | f7bca430d9356c26d6df222d2c90bc7668262f6b (patch) | |
tree | b5eedce7233d680f86461839bfb1bfc2dec3b36c /packages | |
parent | f5e22e71cb5f8699a4312c797af068f655cbe629 (diff) | |
download | frameworks_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')
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]", |