Bug 1526926 Search Widget for Fennec Part 1 - Add search widget code base r=petru
authorAndrei Lazar <andrei.a.lazar@softvision.ro>
Fri, 08 Mar 2019 15:03:52 +0000
changeset 524244 bde7ebdef8a4c2e9e6ecf4cee209a0fae520c509
parent 524243 0d1df88e93f656a5eff4e1105902b2f3015cccdb
child 524245 0368c4ca4ecec9d8ce18d9e474731f2faeb92f00
push id2032
push userffxbld-merge
push dateMon, 13 May 2019 09:36:57 +0000
treeherdermozilla-release@455c1065dcbe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspetru
bugs1526926
milestone67.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1526926 Search Widget for Fennec Part 1 - Add search widget code base r=petru Added Search widget provider class, declared the provider in the manifest and created mock layout for it. Differential Revision: https://phabricator.services.mozilla.com/D20149
mobile/android/app/src/main/res/values/dimens.xml
mobile/android/app/src/main/res/xml/search_widget_info.xml
mobile/android/base/AndroidManifest.xml.in
mobile/android/base/java/org/mozilla/gecko/search/SearchWidgetConfigurationActivity.java
mobile/android/base/java/org/mozilla/gecko/search/SearchWidgetProvider.java
mobile/android/base/locales/en-US/android_strings.dtd
mobile/android/base/strings.xml.in
mobile/android/services/src/main/res/layout/widget_search_1_col_layout.xml
mobile/android/services/src/main/res/layout/widget_search_2_col_layout.xml
mobile/android/services/src/main/res/layout/widget_search_3_col_layout.xml
mobile/android/services/src/main/res/layout/widget_search_4_col_layout.xml
mobile/android/services/src/main/res/layout/widget_search_5_col_layout.xml
--- a/mobile/android/app/src/main/res/values/dimens.xml
+++ b/mobile/android/app/src/main/res/values/dimens.xml
@@ -110,16 +110,32 @@
     <dimen name="home_remote_tabs_hidden_footer_height">40dp</dimen>
 
     <!-- Search Engine Row height -->
     <dimen name="search_engine_row_min_height">42dp</dimen>
     <dimen name="search_suggestion_item_min_height">30dp</dimen>
     <dimen name="search_suggestion_item_padding_horizontal">8dp</dimen>
     <dimen name="search_suggestion_item_padding_vertical">7dp</dimen>
 
+    <!-- Search Widget -->
+    <dimen name="search_widget_height">50dp</dimen>
+    <dimen name="search_widget_1_col_width">50dp</dimen>
+    <dimen name="search_widget_2_col_width">100dp</dimen>
+    <dimen name="search_widget_3_col_width">192dp</dimen>
+    <dimen name="search_widget_4_col_width">256dp</dimen>
+    <dimen name="search_widget_5_col_width">360dp</dimen>
+    <dimen name="search_widget_logo_width">32dp</dimen>
+    <dimen name="search_widget_logo_height">32dp</dimen>
+    <dimen name="search_widget_logo_margin">9dp</dimen>
+    <dimen name="search_widget_3_col_text_width">89dp</dimen>
+    <dimen name="search_widget_4_col_text_width">153dp</dimen>
+    <dimen name="search_widget_5_col_text_width">257dp</dimen>
+    <dimen name="search_widget_text_height">32dp</dimen>
+    <dimen name="search_widget_text_margin">9dp</dimen>
+
     <!-- Search Home Item Row height -->
     <dimen name="search_item_min_height">64dp</dimen>
 
     <dimen name="doorhanger_width">300dp</dimen>
     <dimen name="doorhanger_input_width">250dp</dimen>
     <dimen name="doorhanger_offsetX">12dp</dimen>
     <dimen name="doorhanger_offsetY">67dp</dimen>
     <dimen name="doorhanger_drawable_padding">5dp</dimen>
new file mode 100644
--- /dev/null
+++ b/mobile/android/app/src/main/res/xml/search_widget_info.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+   - License, v. 2.0. If a copy of the MPL was not distributed with this
+   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
+    android:configure="org.mozilla.gecko.search.SearchWidgetConfigurationActivity"
+    android:initialLayout="@layout/widget_search_5_col_layout"
+    android:minWidth="360dp"
+    android:minHeight="50dp"
+    android:minResizeWidth="64dp"
+    android:minResizeHeight="50dp"
+    android:resizeMode="horizontal"
+    android:updatePeriodMillis="300000">
+
+</appwidget-provider>
+
--- a/mobile/android/base/AndroidManifest.xml.in
+++ b/mobile/android/base/AndroidManifest.xml.in
@@ -223,16 +223,33 @@
                   android:theme="@style/OverlayActivity" />
 
         <receiver android:name="org.mozilla.gecko.restrictions.RestrictionProvider">
           <intent-filter>
             <action android:name="android.intent.action.GET_RESTRICTION_ENTRIES" />
           </intent-filter>
         </receiver>
 
+         <receiver android:name="org.mozilla.gecko.search.SearchWidgetProvider">
+             <intent-filter>
+                 <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
+             </intent-filter>
+
+             <meta-data
+                 android:name="android.appwidget.provider"
+                 android:resource="@xml/search_widget_info" />
+         </receiver>
+
+         <activity android:name="org.mozilla.gecko.search.SearchWidgetConfigurationActivity"
+                   android:theme="@style/OverlayActivity">
+             <intent-filter>
+                 <action android:name="android.appwidget.action.APPWIDGET_CONFIGURE"/>
+             </intent-filter>
+         </activity>
+
         <!-- Masquerade as the Resolver so that we can be opened from the Marketplace. -->
         <activity-alias
             android:name="com.android.internal.app.ResolverActivity"
             android:targetActivity="@MOZ_ANDROID_BROWSER_INTENT_CLASS@"
             android:exported="true" />
 
         <receiver android:name="org.mozilla.gecko.GeckoUpdateReceiver">
             <intent-filter>
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/java/org/mozilla/gecko/search/SearchWidgetConfigurationActivity.java
@@ -0,0 +1,34 @@
+package org.mozilla.gecko.search;
+
+/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+import android.appwidget.AppWidgetManager;
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.v7.app.AppCompatActivity;
+import android.widget.RemoteViews;
+
+import org.mozilla.gecko.R;
+
+public final class SearchWidgetConfigurationActivity extends AppCompatActivity {
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        if (getIntent() != null && getIntent().getExtras() != null) {
+            final int widgetId = getIntent().getExtras().getInt(AppWidgetManager.EXTRA_APPWIDGET_ID);
+            final AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(this);
+
+            RemoteViews views = new RemoteViews(getPackageName(), R.layout.widget_search_5_col_layout);
+            appWidgetManager.updateAppWidget(widgetId, views);
+
+            final Intent resultValue = new Intent();
+            resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId);
+            setResult(RESULT_OK, resultValue);
+        }
+        finish();
+    }
+}
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/java/org/mozilla/gecko/search/SearchWidgetProvider.java
@@ -0,0 +1,121 @@
+package org.mozilla.gecko.search;
+
+/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+import android.app.PendingIntent;
+import android.appwidget.AppWidgetManager;
+import android.appwidget.AppWidgetProvider;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.widget.RemoteViews;
+
+import org.mozilla.gecko.LauncherActivity;
+import org.mozilla.gecko.R;
+
+public final class SearchWidgetProvider extends AppWidgetProvider {
+    private static final int VOICE_INTENT_RC = 1;
+    private static final int TEXT_INTENT_RC = 0;
+    public static String INPUT_TYPE_KEY = "input";
+
+    public enum InputType {
+        VOICE,
+        TEXT
+    }
+
+    @Override
+    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
+        final ComponentName searchWidgetName = new ComponentName(context, SearchWidgetProvider.class);
+        int[] allWidgetIds = appWidgetManager.getAppWidgetIds(searchWidgetName);
+
+        for (int widgetId : allWidgetIds) {
+            final RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_search_5_col_layout);
+
+            setVoicePendingIntent(context, remoteViews);
+            setTextPendingIntent(context, remoteViews);
+
+            appWidgetManager.updateAppWidget(widgetId, remoteViews);
+        }
+    }
+
+    @Override
+    public void onAppWidgetOptionsChanged(Context context, AppWidgetManager appWidgetManager, int appWidgetId, Bundle newOptions) {
+        final Bundle options = appWidgetManager.getAppWidgetOptions(appWidgetId);
+        final int minWidth = options.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH);
+
+        // Obtain appropriate widget and update it.
+        appWidgetManager.updateAppWidget(appWidgetId, getRemoteViews(context, minWidth));
+        super.onAppWidgetOptionsChanged(context, appWidgetManager, appWidgetId, newOptions);
+    }
+
+    private RemoteViews getRemoteViews(Context context, int minWidth) {
+        final int columns = getCellsForSize(minWidth);
+        RemoteViews remoteViews;
+        switch (columns) {
+            case 1:
+                remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_search_1_col_layout);
+                break;
+            case 2:
+                remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_search_2_col_layout);
+                break;
+            case 3:
+                remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_search_3_col_layout);
+                break;
+            case 4:
+                remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_search_4_col_layout);
+                break;
+            default:
+                remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_search_5_col_layout);
+                break;
+        }
+
+        setVoicePendingIntent(context, remoteViews);
+        setTextPendingIntent(context, remoteViews);
+
+        return remoteViews;
+    }
+
+    /**
+     * Returns number of cells needed for given size of the widget.
+     *
+     * @param size Widget size in dp.
+     * @return Size in number of cells.
+     */
+    private static int getCellsForSize(int size) {
+        int n = 0;
+
+        while (70 * n - 30 < size) {
+            n++;
+        }
+
+        return n - 1;
+    }
+
+    private static Intent makeSearchIntent(Context context, InputType inputType) {
+        final Intent intent = new Intent(context, LauncherActivity.class);
+
+        intent.putExtra(INPUT_TYPE_KEY, inputType);
+        intent.setAction(Intent.ACTION_VIEW);
+        intent.setData(Uri.parse("about:home"));
+
+        return intent;
+    }
+
+    private static void setVoicePendingIntent(Context context, RemoteViews remoteViews) {
+        final PendingIntent pendingIntent = PendingIntent.getActivity(context, VOICE_INTENT_RC,
+                makeSearchIntent(context, InputType.VOICE), 0);
+        remoteViews.setOnClickPendingIntent(R.id.iv_search_voice, pendingIntent);
+    }
+
+    private static void setTextPendingIntent(Context context, RemoteViews remoteViews) {
+        final PendingIntent pendingIntent = PendingIntent.getActivity(context, TEXT_INTENT_RC,
+                makeSearchIntent(context, InputType.TEXT), 0);
+        remoteViews.setOnClickPendingIntent(R.id.tv_search_text, pendingIntent);
+        remoteViews.setOnClickPendingIntent(R.id.iv_logo, pendingIntent);
+    }
+}
\ No newline at end of file
--- a/mobile/android/base/locales/en-US/android_strings.dtd
+++ b/mobile/android/base/locales/en-US/android_strings.dtd
@@ -58,16 +58,22 @@
 <!ENTITY  crash_allow_contact2 "Allow &vendorShortName; to contact me about this report">
 <!ENTITY  crash_email "Your email">
 <!ENTITY  crash_closing_alert "Exit without sending a crash report?">
 <!ENTITY  sending_crash_report "Sending crash report\u2026">
 <!ENTITY  crash_close_label "Close">
 <!ENTITY  crash_restart_label "Restart &brandShortName;">
 
 <!ENTITY url_bar_default_text2 "Search or enter address">
+
+<!-- Localization note: this text will be displayed in the Search Widget -->
+<!ENTITY search_widget_default_text "Search the web">
+<!ENTITY search_widget_default_cropped_text "Search">
+<!ENTITY search_widget_logo_description "Search the web with &brandShortName;">
+
 <!-- Localization note (url_bar_qrcode_text2) : This text will be
      heard by non-visual users when the focus is on the QR Code
      icon in the url bar. -->
 <!ENTITY url_bar_qrcode_text2 "Use your QR Reader to search or enter address">
 <!-- Localization note (url_bar_mic_text2) : This text will be
      heard by non-visual users when the focus is on the Microphone
      icon in the url bar. -->
 <!ENTITY url_bar_mic_text2 "Use your microphone to search or enter address">
--- a/mobile/android/base/strings.xml.in
+++ b/mobile/android/base/strings.xml.in
@@ -64,16 +64,20 @@
   <string name="sending_crash_report">&sending_crash_report;</string>
   <string name="crash_close_label">&crash_close_label;</string>
   <string name="crash_restart_label">&crash_restart_label;</string>
 
   <string name="url_bar_default_text">&url_bar_default_text2;</string>
   <string name="url_bar_qrcode_text">&url_bar_qrcode_text2;</string>
   <string name="url_bar_mic_text">&url_bar_mic_text2;</string>
 
+  <string name="search_widget_default_text">&search_widget_default_text;</string>
+  <string name="search_widget_default_cropped_text">&search_widget_default_cropped_text;</string>
+  <string name="search_widget_logo_description">&search_widget_logo_description;</string>
+
   <!-- https://support.mozilla.org/1/mobile/%VERSION%/%OS%/%LOCALE%/mobile-help -->
   <string name="help_link">https://support.mozilla.org/1/mobile/&formatS1;/&formatS2;/&formatS3;/mobile-help</string>
   <string name="help_menu">&help_menu;</string>
 
   <string name="quit">&quit;</string>
   <string name="bookmark">&bookmark;</string>
   <string name="bookmark_remove">&bookmark_remove;</string>
   <string name="bookmark_added">&bookmark_added;</string>
new file mode 100644
--- /dev/null
+++ b/mobile/android/services/src/main/res/layout/widget_search_1_col_layout.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+   - License, v. 2.0. If a copy of the MPL was not distributed with this
+   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/layout"
+    android:layout_width="@dimen/search_widget_1_col_width"
+    android:layout_height="@dimen/search_widget_height"
+    android:background="@color/cardview_light_background"
+    android:baselineAligned="false">
+
+    <ImageView
+        android:id="@+id/iv_logo"
+        android:layout_width="@dimen/search_widget_logo_width"
+        android:layout_height="@dimen/search_widget_logo_height"
+        android:layout_centerInParent="true"
+        android:layout_marginLeft="@dimen/search_widget_logo_margin"
+        android:layout_marginTop="@dimen/search_widget_logo_margin"
+        android:layout_marginRight="@dimen/search_widget_logo_margin"
+        android:layout_marginBottom="@dimen/search_widget_logo_margin"
+        android:contentDescription="@string/search_widget_logo_description"
+        android:src="@drawable/icon" />
+
+</RelativeLayout>
+
+
new file mode 100644
--- /dev/null
+++ b/mobile/android/services/src/main/res/layout/widget_search_2_col_layout.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+   - License, v. 2.0. If a copy of the MPL was not distributed with this
+   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/layout"
+    android:layout_width="@dimen/search_widget_2_col_width"
+    android:layout_height="@dimen/search_widget_height"
+    android:background="@color/cardview_light_background"
+    android:baselineAligned="false">
+
+    <ImageView
+        android:id="@+id/iv_logo"
+        android:layout_width="@dimen/search_widget_logo_width"
+        android:layout_height="match_parent"
+        android:layout_alignParentLeft="true"
+        android:layout_marginLeft="@dimen/search_widget_logo_margin"
+        android:layout_marginTop="@dimen/search_widget_logo_margin"
+        android:layout_marginRight="@dimen/search_widget_logo_margin"
+        android:layout_marginBottom="@dimen/search_widget_logo_margin"
+        android:contentDescription="@string/search_widget_logo_description"
+        android:src="@drawable/icon" />
+
+    <ImageView
+        android:id="@+id/iv_search_voice"
+        android:layout_width="@dimen/search_widget_logo_width"
+        android:layout_height="@dimen/search_widget_logo_height"
+        android:layout_marginLeft="@dimen/search_widget_logo_margin"
+        android:layout_marginTop="@dimen/search_widget_logo_margin"
+        android:layout_marginRight="@dimen/search_widget_logo_margin"
+        android:layout_marginBottom="@dimen/search_widget_logo_margin"
+        android:layout_toRightOf="@+id/iv_logo"
+        android:contentDescription="@string/url_bar_mic_text"
+        android:src="@drawable/ic_mic" />
+
+</RelativeLayout>
+
+
new file mode 100644
--- /dev/null
+++ b/mobile/android/services/src/main/res/layout/widget_search_3_col_layout.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+   - License, v. 2.0. If a copy of the MPL was not distributed with this
+   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/layout"
+    android:layout_width="@dimen/search_widget_3_col_width"
+    android:layout_height="@dimen/search_widget_height"
+    android:background="@color/cardview_light_background"
+    android:baselineAligned="false">
+
+    <ImageView
+        android:id="@+id/iv_logo"
+        android:layout_width="@dimen/search_widget_logo_width"
+        android:layout_height="@dimen/search_widget_logo_height"
+        android:layout_alignParentLeft="true"
+        android:layout_marginLeft="@dimen/search_widget_logo_margin"
+        android:layout_marginTop="@dimen/search_widget_logo_margin"
+        android:layout_marginRight="@dimen/search_widget_logo_margin"
+        android:layout_marginBottom="@dimen/search_widget_logo_margin"
+        android:contentDescription="@string/search_widget_logo_description"
+        android:src="@drawable/icon" />
+
+    <TextView
+        android:id="@+id/tv_search_text"
+        style="@style/TextAppearance.SearchSuggestion"
+        android:layout_width="@dimen/search_widget_3_col_text_width"
+        android:layout_height="@dimen/search_widget_text_height"
+        android:layout_gravity="center"
+        android:layout_marginTop="@dimen/search_widget_text_margin"
+        android:layout_marginBottom="@dimen/search_widget_text_margin"
+        android:layout_toRightOf="@+id/iv_logo"
+        android:contentDescription="@string/search_widget_default_cropped_text"
+        android:gravity="left|center_vertical"
+        android:text="@string/search_widget_default_cropped_text" />
+
+    <ImageView
+        android:id="@+id/iv_search_voice"
+        android:layout_width="@dimen/search_widget_logo_width"
+        android:layout_height="@dimen/search_widget_logo_height"
+        android:layout_marginLeft="@dimen/search_widget_logo_margin"
+        android:layout_marginTop="@dimen/search_widget_logo_margin"
+        android:layout_marginRight="@dimen/search_widget_logo_margin"
+        android:layout_marginBottom="@dimen/search_widget_logo_margin"
+        android:layout_toRightOf="@+id/tv_search_text"
+        android:contentDescription="@string/url_bar_mic_text"
+        android:src="@drawable/ic_mic" />
+
+</RelativeLayout>
+
+
new file mode 100644
--- /dev/null
+++ b/mobile/android/services/src/main/res/layout/widget_search_4_col_layout.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+   - License, v. 2.0. If a copy of the MPL was not distributed with this
+   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/layout"
+    android:layout_width="@dimen/search_widget_4_col_width"
+    android:layout_height="@dimen/search_widget_height"
+    android:background="@color/cardview_light_background"
+    android:baselineAligned="false">
+
+    <ImageView
+        android:id="@+id/iv_logo"
+        android:layout_width="@dimen/search_widget_logo_width"
+        android:layout_height="@dimen/search_widget_logo_height"
+        android:layout_alignParentLeft="true"
+        android:layout_marginLeft="@dimen/search_widget_logo_margin"
+        android:layout_marginTop="@dimen/search_widget_logo_margin"
+        android:layout_marginRight="@dimen/search_widget_logo_margin"
+        android:layout_marginBottom="@dimen/search_widget_logo_margin"
+        android:contentDescription="@string/search_widget_logo_description"
+        android:src="@drawable/icon" />
+
+    <TextView
+        android:id="@+id/tv_search_text"
+        style="@style/TextAppearance.SearchSuggestion"
+        android:layout_width="@dimen/search_widget_4_col_text_width"
+        android:layout_height="@dimen/search_widget_text_height"
+        android:layout_gravity="center"
+        android:layout_marginTop="@dimen/search_widget_text_margin"
+        android:layout_marginBottom="@dimen/search_widget_text_margin"
+        android:layout_toRightOf="@+id/iv_logo"
+        android:contentDescription="@string/search_widget_default_text"
+        android:gravity="left|center_vertical"
+        android:text="@string/search_widget_default_text" />
+
+    <ImageView
+        android:id="@+id/iv_search_voice"
+        android:layout_width="@dimen/search_widget_logo_width"
+        android:layout_height="@dimen/search_widget_logo_height"
+        android:layout_marginLeft="@dimen/search_widget_logo_margin"
+        android:layout_marginTop="@dimen/search_widget_logo_margin"
+        android:layout_marginRight="@dimen/search_widget_logo_margin"
+        android:layout_marginBottom="@dimen/search_widget_logo_margin"
+        android:layout_toRightOf="@+id/tv_search_text"
+        android:contentDescription="@string/url_bar_mic_text"
+        android:src="@drawable/ic_mic" />
+
+</RelativeLayout>
+
+
new file mode 100644
--- /dev/null
+++ b/mobile/android/services/src/main/res/layout/widget_search_5_col_layout.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+   - License, v. 2.0. If a copy of the MPL was not distributed with this
+   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/layout"
+    android:layout_width="@dimen/search_widget_5_col_width"
+    android:layout_height="@dimen/search_widget_height"
+    android:background="@color/cardview_light_background"
+    android:baselineAligned="false">
+
+    <ImageView
+        android:id="@+id/iv_logo"
+        android:layout_width="@dimen/search_widget_logo_width"
+        android:layout_height="@dimen/search_widget_logo_height"
+        android:layout_alignParentLeft="true"
+        android:layout_marginLeft="@dimen/search_widget_logo_margin"
+        android:layout_marginTop="@dimen/search_widget_logo_margin"
+        android:layout_marginRight="@dimen/search_widget_logo_margin"
+        android:layout_marginBottom="@dimen/search_widget_logo_margin"
+        android:contentDescription="@string/search_widget_logo_description"
+        android:src="@drawable/icon" />
+
+    <TextView
+        android:id="@+id/tv_search_text"
+        style="@style/TextAppearance.SearchSuggestion"
+        android:layout_width="@dimen/search_widget_5_col_text_width"
+        android:layout_height="@dimen/search_widget_text_height"
+        android:layout_gravity="center"
+        android:layout_marginTop="@dimen/search_widget_text_margin"
+        android:layout_marginBottom="@dimen/search_widget_text_margin"
+        android:layout_toRightOf="@+id/iv_logo"
+        android:contentDescription="@string/search_widget_default_text"
+        android:gravity="left|center_vertical"
+        android:text="@string/search_widget_default_text" />
+
+    <ImageView
+        android:id="@+id/iv_search_voice"
+        android:layout_width="@dimen/search_widget_logo_width"
+        android:layout_height="@dimen/search_widget_logo_height"
+        android:layout_marginLeft="@dimen/search_widget_logo_margin"
+        android:layout_marginTop="@dimen/search_widget_logo_margin"
+        android:layout_marginRight="@dimen/search_widget_logo_margin"
+        android:layout_marginBottom="@dimen/search_widget_logo_margin"
+        android:layout_toRightOf="@+id/tv_search_text"
+        android:contentDescription="@string/url_bar_mic_text"
+        android:src="@drawable/ic_mic" />
+
+</RelativeLayout>
+
+