Change SWE app properties back to stock Android

- Changed project package name from com.android.swe.browser
back to com.android.browser along with code references to
old package name.
- Changes to AndroidManifest making it conform closer to stock
browser manifest.
- Changed app and apk name back to Browser.

Change-Id: I778ee1d1197bd50bd4a4850eef6d1d7f4ef0ad0b
diff --git a/src/com/android/browser/SuggestionsAdapter.java b/src/com/android/browser/SuggestionsAdapter.java
new file mode 100644
index 0000000..41d2b74
--- /dev/null
+++ b/src/com/android/browser/SuggestionsAdapter.java
@@ -0,0 +1,572 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.browser;
+
+import android.app.SearchManager;
+import android.content.Context;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.AsyncTask;
+
+import com.android.browser.R;
+import com.android.browser.platformsupport.BrowserContract;
+import com.android.browser.provider.BrowserProvider2.OmniboxSuggestions;
+import com.android.browser.search.SearchEngine;
+
+import android.text.Html;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.Filter;
+import android.widget.Filterable;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * adapter to wrap multiple cursors for url/search completions
+ */
+public class SuggestionsAdapter extends BaseAdapter implements Filterable,
+        OnClickListener {
+
+    public static final int TYPE_BOOKMARK = 0;
+    public static final int TYPE_HISTORY = 1;
+    public static final int TYPE_SUGGEST_URL = 2;
+    public static final int TYPE_SEARCH = 3;
+    public static final int TYPE_SUGGEST = 4;
+
+    private static final String[] COMBINED_PROJECTION = {
+            OmniboxSuggestions._ID,
+            OmniboxSuggestions.TITLE,
+            OmniboxSuggestions.URL,
+            OmniboxSuggestions.IS_BOOKMARK
+            };
+
+    private static final String COMBINED_SELECTION =
+            "(url LIKE ? OR url LIKE ? OR url LIKE ? OR url LIKE ? OR title LIKE ?)";
+
+    final Context mContext;
+    final Filter mFilter;
+    SuggestionResults mMixedResults;
+    List<SuggestItem> mSuggestResults, mFilterResults;
+    List<CursorSource> mSources;
+    boolean mLandscapeMode;
+    final CompletionListener mListener;
+    final int mLinesPortrait;
+    final int mLinesLandscape;
+    final Object mResultsLock = new Object();
+    boolean mIncognitoMode;
+    BrowserSettings mSettings;
+
+    interface CompletionListener {
+
+        public void onSearch(String txt);
+
+        public void onSelect(String txt, int type, String extraData);
+
+    }
+
+    public SuggestionsAdapter(Context ctx, CompletionListener listener) {
+        mContext = ctx;
+        mSettings = BrowserSettings.getInstance();
+        mListener = listener;
+        mLinesPortrait = mContext.getResources().
+                getInteger(R.integer.max_suggest_lines_portrait);
+        mLinesLandscape = mContext.getResources().
+                getInteger(R.integer.max_suggest_lines_landscape);
+
+        mFilter = new SuggestFilter();
+        addSource(new CombinedCursor());
+    }
+
+    public void setLandscapeMode(boolean mode) {
+        mLandscapeMode = mode;
+        notifyDataSetChanged();
+    }
+
+    public void addSource(CursorSource c) {
+        if (mSources == null) {
+            mSources = new ArrayList<CursorSource>(5);
+        }
+        mSources.add(c);
+    }
+
+    @Override
+    public void onClick(View v) {
+        SuggestItem item = (SuggestItem) ((View) v.getParent()).getTag();
+
+        if (R.id.icon2 == v.getId()) {
+            // replace input field text with suggestion text
+            mListener.onSearch(getSuggestionUrl(item));
+        } else {
+            mListener.onSelect(getSuggestionUrl(item), item.type, item.extra);
+        }
+    }
+
+    @Override
+    public Filter getFilter() {
+        return mFilter;
+    }
+
+    @Override
+    public int getCount() {
+        return (mMixedResults == null) ? 0 : mMixedResults.getLineCount();
+    }
+
+    @Override
+    public SuggestItem getItem(int position) {
+        if (mMixedResults == null) {
+            return null;
+        }
+        return mMixedResults.items.get(position);
+    }
+
+    @Override
+    public long getItemId(int position) {
+        return position;
+    }
+
+    @Override
+    public View getView(int position, View convertView, ViewGroup parent) {
+        final LayoutInflater inflater = LayoutInflater.from(mContext);
+        View view = convertView;
+        if (view == null) {
+            view = inflater.inflate(R.layout.suggestion_item, parent, false);
+        }
+        bindView(view, getItem(position));
+        return view;
+    }
+
+    private void bindView(View view, SuggestItem item) {
+        // store item for click handling
+        view.setTag(item);
+        TextView tv1 = (TextView) view.findViewById(android.R.id.text1);
+        TextView tv2 = (TextView) view.findViewById(android.R.id.text2);
+        ImageView ic1 = (ImageView) view.findViewById(R.id.icon1);
+        View ic2 = view.findViewById(R.id.icon2);
+        View div = view.findViewById(R.id.divider);
+        tv1.setText(Html.fromHtml(item.title));
+        if (TextUtils.isEmpty(item.url)) {
+            tv2.setVisibility(View.GONE);
+            tv1.setMaxLines(2);
+        } else {
+            tv2.setVisibility(View.VISIBLE);
+            tv2.setText(item.url);
+            tv1.setMaxLines(1);
+        }
+        int id = -1;
+        switch (item.type) {
+            case TYPE_SUGGEST:
+            case TYPE_SEARCH:
+                id = R.drawable.ic_search_category_suggest;
+                break;
+            case TYPE_BOOKMARK:
+                id = R.drawable.ic_search_category_bookmark;
+                break;
+            case TYPE_HISTORY:
+                id = R.drawable.ic_search_category_history;
+                break;
+            case TYPE_SUGGEST_URL:
+                id = R.drawable.ic_search_category_browser;
+                break;
+            default:
+                id = -1;
+        }
+        if (id != -1) {
+            ic1.setImageDrawable(mContext.getResources().getDrawable(id));
+        }
+        ic2.setVisibility(((TYPE_SUGGEST == item.type)
+                || (TYPE_SEARCH == item.type))
+                ? View.VISIBLE : View.GONE);
+        div.setVisibility(ic2.getVisibility());
+        ic2.setOnClickListener(this);
+        view.findViewById(R.id.suggestion).setOnClickListener(this);
+    }
+
+    class SlowFilterTask extends AsyncTask<CharSequence, Void, List<SuggestItem>> {
+
+        @Override
+        protected List<SuggestItem> doInBackground(CharSequence... params) {
+            SuggestCursor cursor = new SuggestCursor();
+            cursor.runQuery(params[0]);
+            List<SuggestItem> results = new ArrayList<SuggestItem>();
+            int count = cursor.getCount();
+            for (int i = 0; i < count; i++) {
+                results.add(cursor.getItem());
+                cursor.moveToNext();
+            }
+            cursor.close();
+            return results;
+        }
+
+        @Override
+        protected void onPostExecute(List<SuggestItem> items) {
+            mSuggestResults = items;
+            mMixedResults = buildSuggestionResults();
+            notifyDataSetChanged();
+        }
+    }
+
+    SuggestionResults buildSuggestionResults() {
+        SuggestionResults mixed = new SuggestionResults();
+        List<SuggestItem> filter, suggest;
+        synchronized (mResultsLock) {
+            filter = mFilterResults;
+            suggest = mSuggestResults;
+        }
+        if (filter != null) {
+            for (SuggestItem item : filter) {
+                mixed.addResult(item);
+            }
+        }
+        if (suggest != null) {
+            for (SuggestItem item : suggest) {
+                mixed.addResult(item);
+            }
+        }
+        return mixed;
+    }
+
+    class SuggestFilter extends Filter {
+
+        @Override
+        public CharSequence convertResultToString(Object item) {
+            if (item == null) {
+                return "";
+            }
+            SuggestItem sitem = (SuggestItem) item;
+            if (sitem.title != null) {
+                return sitem.title;
+            } else {
+                return sitem.url;
+            }
+        }
+
+        void startSuggestionsAsync(final CharSequence constraint) {
+            if (!mIncognitoMode) {
+                new SlowFilterTask().execute(constraint);
+            }
+        }
+
+        private boolean shouldProcessEmptyQuery() {
+            final SearchEngine searchEngine = mSettings.getSearchEngine();
+            return searchEngine.wantsEmptyQuery();
+        }
+
+        @Override
+        protected FilterResults performFiltering(CharSequence constraint) {
+            FilterResults res = new FilterResults();
+            if (TextUtils.isEmpty(constraint) && !shouldProcessEmptyQuery()) {
+                res.count = 0;
+                res.values = null;
+                return res;
+            }
+            startSuggestionsAsync(constraint);
+            List<SuggestItem> filterResults = new ArrayList<SuggestItem>();
+            if (constraint != null) {
+                for (CursorSource sc : mSources) {
+                    sc.runQuery(constraint);
+                }
+                mixResults(filterResults);
+            }
+            synchronized (mResultsLock) {
+                mFilterResults = filterResults;
+            }
+            SuggestionResults mixed = buildSuggestionResults();
+            res.count = mixed.getLineCount();
+            res.values = mixed;
+            return res;
+        }
+
+        void mixResults(List<SuggestItem> results) {
+            int maxLines = getMaxLines();
+            for (int i = 0; i < mSources.size(); i++) {
+                CursorSource s = mSources.get(i);
+                int n = Math.min(s.getCount(), maxLines);
+                maxLines -= n;
+                boolean more = false;
+                for (int j = 0; j < n; j++) {
+                    results.add(s.getItem());
+                    more = s.moveToNext();
+                }
+            }
+        }
+
+        @Override
+        protected void publishResults(CharSequence constraint, FilterResults fresults) {
+            if (fresults.values instanceof SuggestionResults) {
+                mMixedResults = (SuggestionResults) fresults.values;
+                notifyDataSetChanged();
+            }
+        }
+    }
+
+    private int getMaxLines() {
+        int maxLines = mLandscapeMode ? mLinesLandscape : mLinesPortrait;
+        maxLines = (int) Math.ceil(maxLines / 2.0);
+        return maxLines;
+    }
+
+    /**
+     * sorted list of results of a suggestion query
+     *
+     */
+    class SuggestionResults {
+
+        ArrayList<SuggestItem> items;
+        // count per type
+        int[] counts;
+
+        SuggestionResults() {
+            items = new ArrayList<SuggestItem>(24);
+            // n of types:
+            counts = new int[5];
+        }
+
+        int getTypeCount(int type) {
+            return counts[type];
+        }
+
+        void addResult(SuggestItem item) {
+            int ix = 0;
+            while ((ix < items.size()) && (item.type >= items.get(ix).type))
+                ix++;
+            items.add(ix, item);
+            counts[item.type]++;
+        }
+
+        int getLineCount() {
+            return Math.min((mLandscapeMode ? mLinesLandscape : mLinesPortrait), items.size());
+        }
+
+        @Override
+        public String toString() {
+            if (items == null) return null;
+            if (items.size() == 0) return "[]";
+            StringBuilder sb = new StringBuilder();
+            for (int i = 0; i < items.size(); i++) {
+                SuggestItem item = items.get(i);
+                sb.append(item.type + ": " + item.title);
+                if (i < items.size() - 1) {
+                    sb.append(", ");
+                }
+            }
+            return sb.toString();
+        }
+    }
+
+    /**
+     * data object to hold suggestion values
+     */
+    public class SuggestItem {
+        public String title;
+        public String url;
+        public int type;
+        public String extra;
+
+        public SuggestItem(String text, String u, int t) {
+            title = text;
+            url = u;
+            type = t;
+        }
+
+    }
+
+    abstract class CursorSource {
+
+        Cursor mCursor;
+
+        boolean moveToNext() {
+            return mCursor.moveToNext();
+        }
+
+        public abstract void runQuery(CharSequence constraint);
+
+        public abstract SuggestItem getItem();
+
+        public int getCount() {
+            return (mCursor != null) ? mCursor.getCount() : 0;
+        }
+
+        public void close() {
+            if (mCursor != null) {
+                mCursor.close();
+            }
+        }
+    }
+
+    /**
+     * combined bookmark & history source
+     */
+    class CombinedCursor extends CursorSource {
+
+        @Override
+        public SuggestItem getItem() {
+            if ((mCursor != null) && (!mCursor.isAfterLast())) {
+                String title = mCursor.getString(1);
+                String url = mCursor.getString(2);
+                boolean isBookmark = (mCursor.getInt(3) == 1);
+                return new SuggestItem(getTitle(title, url), getUrl(title, url),
+                        isBookmark ? TYPE_BOOKMARK : TYPE_HISTORY);
+            }
+            return null;
+        }
+
+        @Override
+        public void runQuery(CharSequence constraint) {
+            // constraint != null
+            if (mCursor != null) {
+                mCursor.close();
+            }
+            String like = constraint + "%";
+            String[] args = null;
+            String selection = null;
+            if (like.startsWith("http") || like.startsWith("file")) {
+                args = new String[1];
+                args[0] = like;
+                selection = "url LIKE ?";
+            } else {
+                args = new String[5];
+                args[0] = "http://" + like;
+                args[1] = "http://www." + like;
+                args[2] = "https://" + like;
+                args[3] = "https://www." + like;
+                // To match against titles.
+                args[4] = like;
+                selection = COMBINED_SELECTION;
+            }
+            Uri.Builder ub = OmniboxSuggestions.CONTENT_URI.buildUpon();
+            ub.appendQueryParameter(BrowserContract.PARAM_LIMIT,
+                    Integer.toString(Math.max(mLinesLandscape, mLinesPortrait)));
+            mCursor =
+                    mContext.getContentResolver().query(ub.build(), COMBINED_PROJECTION,
+                            selection, (constraint != null) ? args : null, null);
+            if (mCursor != null) {
+                mCursor.moveToFirst();
+            }
+        }
+
+        /**
+         * Provides the title (text line 1) for a browser suggestion, which should be the
+         * webpage title. If the webpage title is empty, returns the stripped url instead.
+         *
+         * @return the title string to use
+         */
+        private String getTitle(String title, String url) {
+            if (TextUtils.isEmpty(title) || TextUtils.getTrimmedLength(title) == 0) {
+                title = UrlUtils.stripUrl(url);
+            }
+            return title;
+        }
+
+        /**
+         * Provides the subtitle (text line 2) for a browser suggestion, which should be the
+         * webpage url. If the webpage title is empty, then the url should go in the title
+         * instead, and the subtitle should be empty, so this would return null.
+         *
+         * @return the subtitle string to use, or null if none
+         */
+        private String getUrl(String title, String url) {
+            if (TextUtils.isEmpty(title)
+                    || TextUtils.getTrimmedLength(title) == 0
+                    || title.equals(url)) {
+                return null;
+            } else {
+                return UrlUtils.stripUrl(url);
+            }
+        }
+    }
+
+    class SuggestCursor extends CursorSource {
+
+        @Override
+        public SuggestItem getItem() {
+            if (mCursor != null) {
+                String title = mCursor.getString(
+                        mCursor.getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_1));
+                String text2 = mCursor.getString(
+                        mCursor.getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_2));
+                String url = mCursor.getString(
+                        mCursor.getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_2_URL));
+                String uri = mCursor.getString(
+                        mCursor.getColumnIndex(SearchManager.SUGGEST_COLUMN_INTENT_DATA));
+                int type = (TextUtils.isEmpty(url)) ? TYPE_SUGGEST : TYPE_SUGGEST_URL;
+                SuggestItem item = new SuggestItem(title, url, type);
+                item.extra = mCursor.getString(
+                        mCursor.getColumnIndex(SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA));
+                return item;
+            }
+            return null;
+        }
+
+        @Override
+        public void runQuery(CharSequence constraint) {
+            if (mCursor != null) {
+                mCursor.close();
+            }
+            SearchEngine searchEngine = mSettings.getSearchEngine();
+            if (!TextUtils.isEmpty(constraint)) {
+                if (searchEngine != null && searchEngine.supportsSuggestions()) {
+                    mCursor = searchEngine.getSuggestions(mContext, constraint.toString());
+                    if (mCursor != null) {
+                        mCursor.moveToFirst();
+                    }
+                }
+            } else {
+                if (searchEngine.wantsEmptyQuery()) {
+                    mCursor = searchEngine.getSuggestions(mContext, "");
+                }
+                mCursor = null;
+            }
+        }
+
+    }
+
+    public void clearCache() {
+        mFilterResults = null;
+        mSuggestResults = null;
+        notifyDataSetInvalidated();
+    }
+
+    public void setIncognitoMode(boolean incognito) {
+        mIncognitoMode = incognito;
+        clearCache();
+    }
+
+    static String getSuggestionTitle(SuggestItem item) {
+        // There must be a better way to strip HTML from things.
+        // This method is used in multiple places. It is also more
+        // expensive than a standard html escaper.
+        return (item.title != null) ? Html.fromHtml(item.title).toString() : null;
+    }
+
+    static String getSuggestionUrl(SuggestItem item) {
+        final String title = SuggestionsAdapter.getSuggestionTitle(item);
+
+        if (TextUtils.isEmpty(item.url)) {
+            return title;
+        }
+
+        return item.url;
+    }
+}