From b4b01cdc995309f0b850c5de928d147b83e97fbd Mon Sep 17 00:00:00 2001 From: Raj Yengisetty Date: Sat, 14 Mar 2015 11:44:12 -0700 Subject: Trebuchet: fix live settings bug Repro: - On fresh boot, long press on workspace and open settings panel - Toggle a setting (e.g. Large icons) that triggers a grid refresh - Quickly close the panel and click into a workspace page - Observe sometimes the background of the workspace page is still outlined as if in Overview mode Change-Id: I89492aa9eed269dac18027fa43d1d86597370502 --- src/com/android/launcher3/OverviewSettingsPanel.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/com') diff --git a/src/com/android/launcher3/OverviewSettingsPanel.java b/src/com/android/launcher3/OverviewSettingsPanel.java index acc700ad3..fef164383 100644 --- a/src/com/android/launcher3/OverviewSettingsPanel.java +++ b/src/com/android/launcher3/OverviewSettingsPanel.java @@ -209,8 +209,9 @@ public class OverviewSettingsPanel { frameAnimation.start(); if (mLauncher.updateGridIfNeeded()) { - if (mLauncher.getWorkspace().isInOverviewMode()) { - mLauncher.getWorkspace().showOutlines(); + Workspace workspace = mLauncher.getWorkspace(); + if (workspace.isInOverviewMode()) { + workspace.setChildrenOutlineAlpha(1.0f); mLauncher.mSearchDropTargetBar.hideSearchBar(false); } } -- cgit v1.2.3 From 5482c2f488e7ce312a85e7440b72865d1f2cf598 Mon Sep 17 00:00:00 2001 From: Raj Yengisetty Date: Tue, 17 Mar 2015 15:59:06 -0700 Subject: Trebuchet: disable search bar when there are no search activities - On non-GMS devices, there are no Search apps which can support the search bar implementation. - Disable the search bar entirely if there is no search activity - Add a new utility method in SettingsProvider Change-Id: I3bcbceae4ceab308e4d797dad107e0a2ab72d673 --- src/com/android/launcher3/DeviceProfile.java | 26 +++++++++++--- src/com/android/launcher3/Utilities.java | 9 +++++ .../list/SettingsPinnedHeaderAdapter.java | 40 ++++++++++++++-------- .../launcher3/settings/SettingsProvider.java | 4 +++ 4 files changed, 60 insertions(+), 19 deletions(-) (limited to 'src/com') diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java index 9bdfcf41b..d6c401d4f 100644 --- a/src/com/android/launcher3/DeviceProfile.java +++ b/src/com/android/launcher3/DeviceProfile.java @@ -315,8 +315,7 @@ public class DeviceProfile { updateAvailableDimensions(context); computeAllAppsButtonSize(context); // Search Bar - searchBarVisible = SettingsProvider.getBoolean(context, SettingsProvider.SETTINGS_UI_HOMESCREEN_SEARCH, - R.bool.preferences_interface_homescreen_search_default); + searchBarVisible = isSearchBarEnabled(context); searchBarSpaceWidthPx = Math.min(searchBarSpaceMaxWidthPx, widthPx); searchBarSpaceHeightPx = 2 * edgeMarginPx + (searchBarVisible ? searchBarHeightPx : 3 * edgeMarginPx); } @@ -780,8 +779,7 @@ public class DeviceProfile { public void layout(Launcher launcher) { // Update search bar for live settings - searchBarVisible = SettingsProvider.getBoolean(launcher, SettingsProvider.SETTINGS_UI_HOMESCREEN_SEARCH, - R.bool.preferences_interface_homescreen_search_default); + searchBarVisible = isSearchBarEnabled(launcher); searchBarSpaceHeightPx = 2 * edgeMarginPx + (searchBarVisible ? searchBarHeightPx : 3 * edgeMarginPx); FrameLayout.LayoutParams lp; Resources res = launcher.getResources(); @@ -960,4 +958,24 @@ public class DeviceProfile { } } } + + private boolean isSearchBarEnabled(Context context) { + boolean searchActivityExists = Utilities.searchActivityExists(context); + + boolean isSearchEnabled = SettingsProvider.getBoolean(context, + SettingsProvider.SETTINGS_UI_HOMESCREEN_SEARCH, + R.bool.preferences_interface_homescreen_search_default); + + if (searchActivityExists) { + return isSearchEnabled; + } else { + if (isSearchEnabled) { + // Disable search bar + SettingsProvider.putBoolean(context, + SettingsProvider.SETTINGS_UI_HOMESCREEN_SEARCH, false); + } + + return false; + } + } } diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java index fcd4b8587..a594fd9f9 100644 --- a/src/com/android/launcher3/Utilities.java +++ b/src/com/android/launcher3/Utilities.java @@ -17,6 +17,7 @@ package com.android.launcher3; import android.app.Activity; +import android.app.SearchManager; import android.content.ActivityNotFoundException; import android.content.ComponentName; import android.content.Context; @@ -566,4 +567,12 @@ public final class Utilities { float px = dp * (metrics.densityDpi / (float) DisplayMetrics.DENSITY_DEFAULT); return px; } + + public static boolean searchActivityExists(Context context) { + SearchManager searchManager = + (SearchManager) context.getSystemService(Context.SEARCH_SERVICE); + ComponentName activityName = searchManager.getGlobalSearchActivity(); + + return activityName != null; + } } diff --git a/src/com/android/launcher3/list/SettingsPinnedHeaderAdapter.java b/src/com/android/launcher3/list/SettingsPinnedHeaderAdapter.java index 93b34b47e..9882c7625 100644 --- a/src/com/android/launcher3/list/SettingsPinnedHeaderAdapter.java +++ b/src/com/android/launcher3/list/SettingsPinnedHeaderAdapter.java @@ -16,12 +16,14 @@ import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.TextView; +import android.widget.Toast; import com.android.launcher3.AppDrawerListAdapter; import com.android.launcher3.AppsCustomizePagedView; import com.android.launcher3.DeviceProfile; import com.android.launcher3.Launcher; import com.android.launcher3.OverviewSettingsPanel; import com.android.launcher3.R; +import com.android.launcher3.Utilities; import com.android.launcher3.settings.SettingsProvider; public class SettingsPinnedHeaderAdapter extends PinnedHeaderListAdapter { @@ -285,9 +287,7 @@ public class SettingsPinnedHeaderAdapter extends PinnedHeaderListAdapter { case OverviewSettingsPanel.HOME_SETTINGS_POSITION: switch (position) { case 0: - onSettingsBooleanChanged(v, - SettingsProvider.SETTINGS_UI_HOMESCREEN_SEARCH, - R.bool.preferences_interface_homescreen_search_default); + updateSearchBarVisibility(v); mLauncher.setUpdateDynamicGrid(); break; case 1: @@ -354,17 +354,31 @@ public class SettingsPinnedHeaderAdapter extends PinnedHeaderListAdapter { } }; + private void updateSearchBarVisibility(View v) { + boolean isSearchEnabled = SettingsProvider.getBoolean(mContext, + SettingsProvider.SETTINGS_UI_HOMESCREEN_SEARCH, + R.bool.preferences_interface_homescreen_search_default); + + if (!isSearchEnabled) { + if (!Utilities.searchActivityExists(mContext)) { + Toast.makeText(mContext, mContext.getString(R.string.search_activity_not_found), + Toast.LENGTH_SHORT).show(); + return; + } + } + + onSettingsBooleanChanged(v, + SettingsProvider.SETTINGS_UI_HOMESCREEN_SEARCH, + R.bool.preferences_interface_homescreen_search_default); + } + private void onSettingsBooleanChanged(View v, String key, int res) { boolean current = SettingsProvider.getBoolean( mContext, key, res); // Set new state - SharedPreferences sharedPref = SettingsProvider - .get(mContext); - sharedPref.edit().putBoolean(key, !current).commit(); - sharedPref.edit() - .putBoolean(SettingsProvider.SETTINGS_CHANGED, true) - .commit(); + SettingsProvider.putBoolean(mContext, key, !current); + SettingsProvider.putBoolean(mContext, SettingsProvider.SETTINGS_CHANGED, true); String state = current ? mLauncher.getResources().getString( R.string.setting_state_off) : mLauncher.getResources().getString( @@ -377,12 +391,8 @@ public class SettingsPinnedHeaderAdapter extends PinnedHeaderListAdapter { mContext, key, res); // Set new state - SharedPreferences sharedPref = SettingsProvider - .get(mContext); - sharedPref.edit().putBoolean(key, !current).commit(); - sharedPref.edit() - .putBoolean(SettingsProvider.SETTINGS_CHANGED, true) - .commit(); + SettingsProvider.putBoolean(mContext, key, !current); + SettingsProvider.putBoolean(mContext, SettingsProvider.SETTINGS_CHANGED, true); String state = current ? mLauncher.getResources().getString( R.string.icon_labels_show) : mLauncher.getResources().getString( diff --git a/src/com/android/launcher3/settings/SettingsProvider.java b/src/com/android/launcher3/settings/SettingsProvider.java index 4d09ed9ce..042053cef 100644 --- a/src/com/android/launcher3/settings/SettingsProvider.java +++ b/src/com/android/launcher3/settings/SettingsProvider.java @@ -88,4 +88,8 @@ public final class SettingsProvider { public static void putInt(Context context, String key, int value) { get(context).edit().putInt(key, value).commit(); } + + public static void putBoolean(Context context, String key, boolean value) { + get(context).edit().putBoolean(key, value).commit(); + } } -- cgit v1.2.3 From 368c91bd821cdd114025fa41b99f2d42c915b2f5 Mon Sep 17 00:00:00 2001 From: Raj Yengisetty Date: Tue, 17 Mar 2015 10:31:41 -0700 Subject: Trebuchet: protect update path for widgetpreviews db After the update path is called, calling getWritableDatabase always results in a SQLiteReadOnlyDatabaseException. Looks to be a Lollipop bug, protecting the code path till we have a better solution. Change-Id: Ic0487e2d588a341d42e046fb97e8f041622d6450 --- src/com/android/launcher3/WidgetPreviewLoader.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src/com') diff --git a/src/com/android/launcher3/WidgetPreviewLoader.java b/src/com/android/launcher3/WidgetPreviewLoader.java index d496c1c08..7fcb9f9ad 100644 --- a/src/com/android/launcher3/WidgetPreviewLoader.java +++ b/src/com/android/launcher3/WidgetPreviewLoader.java @@ -378,9 +378,13 @@ public class WidgetPreviewLoader { // Delete everything try { db.delete(CacheDb.TABLE_NAME, null, null); + } catch (SQLiteReadOnlyDatabaseException e) { + // After a DB update subsequent calls to getWritableDatabase seems always result in + // a SQLiteReadOnlyDatabaseException. Protect this code path for the time being to + // prevent FC + return; } catch (SQLiteDiskIOException e) { } catch (SQLiteCantOpenDatabaseException e) { - } catch (SQLiteReadOnlyDatabaseException e) { dumpOpenFiles(); throw e; } -- cgit v1.2.3 From 42427c9b63936e82f9fbe934bddb376074a8e331 Mon Sep 17 00:00:00 2001 From: Raj Yengisetty Date: Wed, 25 Mar 2015 09:48:36 -0700 Subject: ProtectedApps: Fix protecting shortcuts with no ComponentNames Repro: - Create a shortcut using the contacts widget - Add to a folder and open app protection screen - Observe: Trebuchet force closes Change-Id: I76f6a8b1d024beb36fa804bb3a866913edc335c1 (cherry picked from commit d8bdb0eef3f1799e8b829bcf114f1c3573bce8d6) --- src/com/android/launcher3/Folder.java | 4 +++- src/com/android/launcher3/HiddenFolderFragment.java | 10 +++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) (limited to 'src/com') diff --git a/src/com/android/launcher3/Folder.java b/src/com/android/launcher3/Folder.java index e4f935cf3..692526062 100644 --- a/src/com/android/launcher3/Folder.java +++ b/src/com/android/launcher3/Folder.java @@ -299,7 +299,9 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList public void modifyProtectedApps(boolean protect) { ArrayList components = new ArrayList(); for (Pair item : getComponents()) { - components.add(item.first); + if (item.first != null) { + components.add(item.first); + } } Intent intent = new Intent(); diff --git a/src/com/android/launcher3/HiddenFolderFragment.java b/src/com/android/launcher3/HiddenFolderFragment.java index 94e1d2dbf..db5e51fb1 100644 --- a/src/com/android/launcher3/HiddenFolderFragment.java +++ b/src/com/android/launcher3/HiddenFolderFragment.java @@ -227,7 +227,10 @@ public class HiddenFolderFragment extends Fragment { viewHolder.title.setText(app.title); - Drawable icon = mIcons.get(app.componentName.getPackageName()); + Drawable icon = null; + if (app.componentName != null) { + icon = mIcons.get(app.componentName.getPackageName()); + } viewHolder.icon.setImageDrawable(icon != null ? icon : mDefaultImg); viewHolder.remove.setOnClickListener(new OnClickListener() { @Override @@ -284,8 +287,9 @@ public class HiddenFolderFragment extends Fragment { protected Void doInBackground(AppEntry... apps) { for (AppEntry app : apps) { try { - if (mIcons.containsKey(app.componentName - .getPackageName())) { + // Widget icons do not have a + if (app.componentName == null || + mIcons.containsKey(app.componentName.getPackageName())) { continue; } Drawable icon = mPackageManager -- cgit v1.2.3 From 19ee2fd1fdca875b734c44a40ea87b5a50f14e37 Mon Sep 17 00:00:00 2001 From: Raj Yengisetty Date: Tue, 24 Mar 2015 14:05:40 -0700 Subject: Protected Apps: fix insets so that views stay above navbar Change-Id: I78b5a212b66aa31b22d72a65af40452dd114fc35 --- src/com/android/launcher3/HiddenFolderFragment.java | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'src/com') diff --git a/src/com/android/launcher3/HiddenFolderFragment.java b/src/com/android/launcher3/HiddenFolderFragment.java index db5e51fb1..4a847e0f3 100644 --- a/src/com/android/launcher3/HiddenFolderFragment.java +++ b/src/com/android/launcher3/HiddenFolderFragment.java @@ -20,7 +20,9 @@ import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputMethodManager; import android.widget.ArrayAdapter; import android.widget.EditText; +import android.widget.FrameLayout; import android.widget.ImageView; +import android.widget.LinearLayout; import android.widget.ListView; import android.widget.TextView; @@ -115,6 +117,14 @@ public class HiddenFolderFragment extends Fragment { mListView = (ListView) v.findViewById(R.id.hidden_apps_list); mListView.setAdapter(mAppsAdapter); + // Apply insets + Launcher launcher = (Launcher) getActivity(); + LinearLayout.LayoutParams llp = + (LinearLayout.LayoutParams) mListView.getLayoutParams(); + llp.bottomMargin += ((FrameLayout.LayoutParams) launcher.getOverviewPanel() + .findViewById(R.id.settings_container).getLayoutParams()).bottomMargin; + mListView.setLayoutParams(llp); + return v; } -- cgit v1.2.3 From 660761014f5ab0d6ebada8a1579db4da910643fe Mon Sep 17 00:00:00 2001 From: Raj Yengisetty Date: Thu, 26 Mar 2015 09:28:56 -0700 Subject: ProtectedApps: map items without componentNames by position Repro: - Add a contact widget to a folder - Open the hidden apps fragment - Attempt to remove an entry from the fragment - Observe: Force close Change-Id: I3ca2c62283af5232534b766d7579413c060a5403 (cherry picked from commit f963b11485ceef70bbce7a9a4b98415ac2672b5b) --- src/com/android/launcher3/Folder.java | 12 ++++++++++++ src/com/android/launcher3/HiddenFolderFragment.java | 21 ++++++++++++++++----- 2 files changed, 28 insertions(+), 5 deletions(-) (limited to 'src/com') diff --git a/src/com/android/launcher3/Folder.java b/src/com/android/launcher3/Folder.java index 692526062..7267f327c 100644 --- a/src/com/android/launcher3/Folder.java +++ b/src/com/android/launcher3/Folder.java @@ -1492,6 +1492,18 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList return null; } + public ShortcutInfo getShortcutForPosition(int position) { + if (position < 0 || position >= mItemsInReadingOrder.size()) { + return null; + } + View v = mItemsInReadingOrder.get(position); + Object tag = v.getTag(); + if (tag instanceof ShortcutInfo) { + return (ShortcutInfo) tag; + } + return null; + } + public void getLocationInDragLayer(int[] loc) { mLauncher.getDragLayer().getLocationInDragLayer(this, loc); } diff --git a/src/com/android/launcher3/HiddenFolderFragment.java b/src/com/android/launcher3/HiddenFolderFragment.java index 4a847e0f3..279448cdb 100644 --- a/src/com/android/launcher3/HiddenFolderFragment.java +++ b/src/com/android/launcher3/HiddenFolderFragment.java @@ -138,16 +138,25 @@ public class HiddenFolderFragment extends Fragment { private ArrayList loadApps(List> items) { ArrayList apps = new ArrayList(); + int pos = 0; for (Pair item : items) { - apps.add(new AppEntry(item.first, item.second)); + apps.add(new AppEntry(item.first, item.second, pos)); + pos++; } return apps; } private void removeComponentFromFolder(AppEntry app) { - mLauncher.mHiddenFolderIcon.getFolderInfo().remove( - mLauncher.mHiddenFolderIcon.getFolder() - .getShortcutForComponent(app.componentName)); + ShortcutInfo info; + if (app.componentName != null) { + info = mLauncher.mHiddenFolderIcon.getFolder() + .getShortcutForComponent(app.componentName); + } else { + // Shortcut does not have componentName, use position since it maps to + // reading order position in the folder + info = mLauncher.mHiddenFolderIcon.getFolder().getShortcutForPosition(app.position); + } + mLauncher.mHiddenFolderIcon.getFolderInfo().remove(info); mAppEntries.remove(app); mAppsAdapter.remove(app); @@ -325,10 +334,12 @@ public class HiddenFolderFragment extends Fragment { private final class AppEntry { public final ComponentName componentName; public final CharSequence title; + public final int position; - public AppEntry(ComponentName component, CharSequence title) { + public AppEntry(ComponentName component, CharSequence title, int position) { this.componentName = component; this.title = title; + this.position = position; } } -- cgit v1.2.3 From e423f8abb9462d0063e4504ff1386b127875e23b Mon Sep 17 00:00:00 2001 From: Linus Lee Date: Mon, 30 Mar 2015 18:06:29 -0700 Subject: Trebuchet: Fix bad ui state when backing twice quickly If a user enters the widget add screen and quickly backs up twice, the widget panel stays around and captures touch, but the ui thinks it is in the homescreen. Change-Id: I52a920fd633f3ab690ca1c959fbc8935c2d0bb69 --- src/com/android/launcher3/Launcher.java | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src/com') diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index b1bafb189..5d857ce8c 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -2781,6 +2781,14 @@ public class Launcher extends Activity } else if (f2 != null) { mDynamicGridSizeFragment.setSize(); } else { + // if a user backs up twice very quickly from the widget add screen to the + // homescreen, the UI can get into a messed up state and mStateAnimation never + // completes or gets cancelled. Cancelling mStateAnimation here fixes this bug + if (mStateAnimation != null && mStateAnimation.isRunning()) { + mStateAnimation.cancel(); + mStateAnimation = null; + } + mWorkspace.exitOverviewMode(true); } } else if (mWorkspace.getOpenFolder() != null) { -- cgit v1.2.3