diff options
Diffstat (limited to 'src/com/android/launcher3/Launcher.java')
-rw-r--r-- | src/com/android/launcher3/Launcher.java | 1477 |
1 files changed, 821 insertions, 656 deletions
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 416c80641..ab3f1daa0 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -17,8 +17,6 @@ package com.android.launcher3; -import android.accounts.Account; -import android.accounts.AccountManager; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; @@ -29,8 +27,10 @@ import android.animation.ValueAnimator.AnimatorUpdateListener; import android.app.Activity; import android.app.ActivityManager; import android.app.ActivityOptions; -import android.app.AlertDialog; import android.app.Dialog; +import android.app.Fragment; +import android.app.FragmentManager; +import android.app.FragmentTransaction; import android.app.SearchManager; import android.appwidget.AppWidgetHostView; import android.appwidget.AppWidgetManager; @@ -41,13 +41,14 @@ import android.content.ComponentCallbacks2; import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; -import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; import android.content.pm.ActivityInfo; +import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; +import android.content.pm.ResolveInfo; import android.content.res.Configuration; import android.content.res.Resources; import android.database.ContentObserver; @@ -55,6 +56,7 @@ import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Point; import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.net.Uri; @@ -65,7 +67,6 @@ import android.os.Handler; import android.os.Message; import android.os.StrictMode; import android.os.SystemClock; -import android.provider.Settings; import android.speech.RecognizerIntent; import android.text.Selection; import android.text.SpannableStringBuilder; @@ -83,14 +84,12 @@ import android.view.MenuItem; import android.view.MotionEvent; import android.view.Surface; import android.view.View; -import android.view.View.OnClickListener; import android.view.View.OnLongClickListener; import android.view.ViewGroup; import android.view.ViewTreeObserver; import android.view.ViewTreeObserver.OnGlobalLayoutListener; import android.view.WindowManager; import android.view.accessibility.AccessibilityEvent; -import android.view.accessibility.AccessibilityManager; import android.view.animation.AccelerateDecelerateInterpolator; import android.view.animation.DecelerateInterpolator; import android.view.inputmethod.InputMethodManager; @@ -101,8 +100,9 @@ import android.widget.PopupMenu; import android.widget.TextView; import android.widget.Toast; +import com.android.launcher.home.Home; import com.android.launcher3.DropTarget.DragObject; -import com.android.launcher3.settings.SettingsActivity; +import com.android.launcher3.PagedView.TransitionEffect; import com.android.launcher3.settings.SettingsProvider; import java.io.DataInputStream; @@ -119,6 +119,8 @@ import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; + /** * Default launcher application. @@ -129,12 +131,16 @@ public class Launcher extends Activity static final String TAG = "Launcher"; static final boolean LOGD = false; + DeviceProfile mGrid; + static final boolean PROFILE_STARTUP = false; static final boolean DEBUG_WIDGETS = false; static final boolean DEBUG_STRICT_MODE = false; static final boolean DEBUG_RESUME_TIME = false; static final boolean DEBUG_DUMP_LOG = false; + static final boolean ENABLE_DEBUG_INTENTS = false; // allow DebugIntents to run + private static final int REQUEST_CREATE_SHORTCUT = 1; private static final int REQUEST_CREATE_APPWIDGET = 5; private static final int REQUEST_PICK_APPLICATION = 6; @@ -143,8 +149,11 @@ public class Launcher extends Activity private static final int REQUEST_PICK_WALLPAPER = 10; private static final int REQUEST_BIND_APPWIDGET = 11; + static final int REQUEST_PICK_ICON = 13; + private static final int REQUEST_LOCK_PATTERN = 14; + /** * IntentStarter uses request codes starting with this. This must be greater than all activity * request codes used internally. @@ -161,6 +170,7 @@ public class Launcher extends Activity // adb shell setprop log.tag.PROPERTY_NAME [VERBOSE | SUPPRESS] static final String FORCE_ENABLE_ROTATION_PROPERTY = "launcher_force_rotate"; static final String DUMP_STATE_PROPERTY = "launcher_dump_state"; + static final String DISABLE_ALL_APPS_PROPERTY = "launcher_noallapps"; // The Intent extra that defines whether to ignore the launch animation static final String INTENT_EXTRA_IGNORE_LAUNCH_ANIMATION = @@ -188,6 +198,13 @@ public class Launcher extends Activity private static final String RUNTIME_STATE_PENDING_ADD_SPAN_Y = "launcher.add_span_y"; // Type: parcelable private static final String RUNTIME_STATE_PENDING_ADD_WIDGET_INFO = "launcher.add_widget_info"; + // Type: parcelable + private static final String RUNTIME_STATE_PENDING_ADD_WIDGET_ID = "launcher.add_widget_id"; + // Type: int[] + private static final String RUNTIME_STATE_VIEW_IDS = "launcher.view_ids"; + + + static final String FIRST_RUN_ACTIVITY_DISPLAYED = "launcher.first_run_activity_displayed"; private static final String TOOLBAR_ICON_METADATA_NAME = "com.android.launcher.toolbar_icon"; private static final String TOOLBAR_SEARCH_ICON_METADATA_NAME = @@ -203,25 +220,31 @@ public class Launcher extends Activity public static final String SHOW_WEIGHT_WATCHER = "debug.show_mem"; public static final boolean SHOW_WEIGHT_WATCHER_DEFAULT = false; + public static final String USER_HAS_MIGRATED = "launcher.user_migrated_from_old_data"; + /** The different states that Launcher can be in. */ private enum State { NONE, WORKSPACE, APPS_CUSTOMIZE, APPS_CUSTOMIZE_SPRING_LOADED }; private State mState = State.WORKSPACE; private AnimatorSet mStateAnimation; static final int APPWIDGET_HOST_ID = 1024; - private static final int EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT = 300; - private static final int EXIT_SPRINGLOADED_MODE_LONG_TIMEOUT = 600; - private static final int SHOW_CLING_DURATION = 250; - private static final int DISMISS_CLING_DURATION = 200; + public static final int EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT = 300; + public static final int EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT_FOLDER_CLOSE = 400; + private static final int ON_ACTIVITY_RESULT_ANIMATION_DELAY = 500; private static final Object sLock = new Object(); private static int sScreen = DEFAULT_SCREEN; + private HashMap<Integer, Integer> mItemIdToViewId = new HashMap<Integer, Integer>(); + private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1); + // How long to wait before the new-shortcut animation automatically pans the workspace private static int NEW_APPS_PAGE_MOVE_DELAY = 500; private static int NEW_APPS_ANIMATION_INACTIVE_TIMEOUT_SECONDS = 5; private static int NEW_APPS_ANIMATION_DELAY = 500; + private boolean mGelIntegrationEnabled = false; + private final BroadcastReceiver mCloseSystemDialogsReceiver = new CloseSystemDialogsIntentReceiver(); private final ContentObserver mWidgetObserver = new AppWidgetResetObserver(); @@ -230,22 +253,37 @@ public class Launcher extends Activity private Workspace mWorkspace; private View mLauncherView; + private View mPageIndicators; private DragLayer mDragLayer; private DragController mDragController; private View mWeightWatcher; + private TransitionEffectsFragment mTransitionEffectsFragment; + private DynamicGridSizeFragment mDynamicGridSizeFragment; + private LauncherClings mLauncherClings; + protected HiddenFolderFragment mHiddenFolderFragment; + private AppWidgetManager mAppWidgetManager; private LauncherAppWidgetHost mAppWidgetHost; private ItemInfo mPendingAddInfo = new ItemInfo(); private AppWidgetProviderInfo mPendingAddWidgetInfo; + private int mPendingAddWidgetId = -1; private int[] mTmpAddItemCellCoordinates = new int[2]; private FolderInfo mFolderInfo; + protected FolderIcon mHiddenFolderIcon; + private boolean mHiddenFolderAuth = false; + private Hotseat mHotseat; + private View mOverviewPanel; + private View mDarkPanel; + OverviewSettingsPanel mOverviewSettingsPanel; + +// private ViewGroup mOverviewPanel; private View mAllAppsButton; @@ -253,7 +291,10 @@ public class Launcher extends Activity private AppsCustomizeLayout mAppsCustomizeLayout; private AppsCustomizePagedView mAppsCustomizeContent; private boolean mAutoAdvanceRunning = false; + private View mQsb; private View mQsbBar; + private ImageView mQsbBarSearch; + private ImageView mQsbBarVoice; private Bundle mSavedState; // We set the state in both onCreate and then onNewIntent in some cases, which causes both @@ -280,14 +321,12 @@ public class Launcher extends Activity private Dialog mTransitionEffectDialog; - private LauncherModel mModel; + protected LauncherModel mModel; private IconCache mIconCache; private boolean mUserPresent = true; private boolean mVisible = false; private boolean mHasFocus = false; private boolean mAttached = false; - private static final boolean DISABLE_CLINGS = false; - private static final boolean DISABLE_CUSTOM_CLINGS = true; private static LocaleConfiguration sLocaleConfiguration = null; @@ -315,6 +354,7 @@ public class Launcher extends Activity private Drawable mWorkspaceBackgroundDrawable; private final ArrayList<Integer> mSynchronouslyBoundPages = new ArrayList<Integer>(); + private static final boolean DISABLE_SYNCHRONOUS_BINDING_CURRENT_PAGE = false; static final ArrayList<String> sDumpLogs = new ArrayList<String>(); static Date sDateStamp = new Date(); @@ -338,9 +378,6 @@ public class Launcher extends Activity private BubbleTextView mWaitingForResume; - private HideFromAccessibilityHelper mHideFromAccessibilityHelper - = new HideFromAccessibilityHelper(); - // Preferences private boolean mHideIconLabels; @@ -368,10 +405,33 @@ public class Launcher extends Activity private Stats mStats; - private static boolean isPropertyEnabled(String propertyName) { + public Animator.AnimatorListener mAnimatorListener = new Animator.AnimatorListener() { + @Override + public void onAnimationStart(Animator arg0) {} + @Override + public void onAnimationRepeat(Animator arg0) {} + @Override + public void onAnimationEnd(Animator arg0) { + mDarkPanel.setVisibility(View.GONE); + } + @Override + public void onAnimationCancel(Animator arg0) {} + }; + + static boolean isPropertyEnabled(String propertyName) { return Log.isLoggable(propertyName, Log.VERBOSE); } + private BroadcastReceiver protectedAppsChangedReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + // Update the workspace + updateDynamicGrid(); + mWorkspace.hideOutlines(); + mSearchDropTargetBar.showSearchBar(false); + } + }; + @Override protected void onCreate(Bundle savedInstanceState) { if (DEBUG_STRICT_MODE) { @@ -391,36 +451,14 @@ public class Launcher extends Activity super.onCreate(savedInstanceState); - LauncherAppState.setApplicationContext(getApplicationContext()); - LauncherAppState app = LauncherAppState.getInstance(); - - mHideIconLabels = SettingsProvider.getBoolean(this, - SettingsProvider.SETTINGS_UI_HOMESCREEN_HIDE_ICON_LABELS, - R.bool.preferences_interface_homescreen_hide_icon_labels_default); - - // Determine the dynamic grid properties - Point smallestSize = new Point(); - Point largestSize = new Point(); - Point realSize = new Point(); - Display display = getWindowManager().getDefaultDisplay(); - display.getCurrentSizeRange(smallestSize, largestSize); - display.getRealSize(realSize); - DisplayMetrics dm = new DisplayMetrics(); - display.getMetrics(dm); - // Lazy-initialize the dynamic grid - DeviceProfile grid = app.initDynamicGrid(this, - Math.min(smallestSize.x, smallestSize.y), - Math.min(largestSize.x, largestSize.y), - realSize.x, realSize.y, - dm.widthPixels, dm.heightPixels); + initializeDynamicGrid(); // the LauncherApplication should call this, but in case of Instrumentation it might not be present yet mSharedPrefs = getSharedPreferences(LauncherAppState.getSharedPreferencesKey(), Context.MODE_PRIVATE); - mModel = app.setLauncher(this); - mIconCache = app.getIconCache(); - mIconCache.flushInvalidIcons(grid); + mDragController = new DragController(this); + mLauncherClings = new LauncherClings(this); mInflater = getLayoutInflater(); mStats = new Stats(this); @@ -445,7 +483,7 @@ public class Launcher extends Activity setContentView(R.layout.launcher); setupViews(); - grid.layout(this); + mGrid.layout(this); registerContentObservers(); @@ -454,25 +492,21 @@ public class Launcher extends Activity mSavedState = savedInstanceState; restoreState(mSavedState); - // Update customization drawer _after_ restoring the states - if (mAppsCustomizeContent != null) { - mAppsCustomizeContent.onPackagesUpdated( - LauncherModel.getSortedWidgetsAndShortcuts(this)); - } + restoreGelSetting(); if (PROFILE_STARTUP) { android.os.Debug.stopMethodTracing(); } if (!mRestoring) { - if (sPausedFromUserAction) { + if (DISABLE_SYNCHRONOUS_BINDING_CURRENT_PAGE || sPausedFromUserAction) { // If the user leaves launcher, then we should just load items asynchronously when // they return. - mModel.startLoader(true, -1); + mModel.startLoader(true, PagedView.INVALID_RESTORE_PAGE); } else { // We only load the page synchronously if the user rotates (or triggers a // configuration change) while launcher is in the foreground - mModel.startLoader(true, mWorkspace.getCurrentPage()); + mModel.startLoader(true, mWorkspace.getRestorePage()); } } @@ -488,7 +522,60 @@ public class Launcher extends Activity // On large interfaces, we want the screen to auto-rotate based on the current orientation unlockScreenOrientation(true); - showFirstRunCling(); + // The two first run cling paths are mutually exclusive, if the launcher is preinstalled + // on the device, then we always show the first run cling experience (or if there is no + // launcher2). Otherwise, we prompt the user upon started for migration + showFirstRunActivity(); + if (mLauncherClings.shouldShowFirstRunOrMigrationClings()) { + if (mModel.canMigrateFromOldLauncherDb(this)) { + mLauncherClings.showMigrationCling(); + } else { + mLauncherClings.showFirstRunCling(); + } + } else { + mLauncherClings.removeFirstRunAndMigrationClings(); + } + IntentFilter protectedAppsFilter = new IntentFilter( + "cyanogenmod.intent.action.PROTECTED_COMPONENT_UPDATE"); + registerReceiver(protectedAppsChangedReceiver, protectedAppsFilter, + "cyanogenmod.permission.PROTECTED_APP", null); + } + + public void restoreGelSetting() { + mGelIntegrationEnabled = SettingsProvider.getBoolean(this, + SettingsProvider.SETTINGS_UI_HOMESCREEN_SEARCH_SCREEN_LEFT, + R.bool.preferences_interface_homescreen_search_screen_left_default); + } + + void initializeDynamicGrid() { + LauncherAppState.setApplicationContext(getApplicationContext()); + LauncherAppState app = LauncherAppState.getInstance(); + + mHideIconLabels = SettingsProvider.getBoolean(this, + SettingsProvider.SETTINGS_UI_HOMESCREEN_HIDE_ICON_LABELS, + R.bool.preferences_interface_homescreen_hide_icon_labels_default); + + restoreGelSetting(); + + // Determine the dynamic grid properties + Point smallestSize = new Point(); + Point largestSize = new Point(); + Point realSize = new Point(); + Display display = getWindowManager().getDefaultDisplay(); + display.getCurrentSizeRange(smallestSize, largestSize); + display.getRealSize(realSize); + DisplayMetrics dm = new DisplayMetrics(); + display.getMetrics(dm); + // Lazy-initialize the dynamic grid + mGrid = app.initDynamicGrid(this, + Math.min(smallestSize.x, smallestSize.y), + Math.min(largestSize.x, largestSize.y), + realSize.x, realSize.y, + dm.widthPixels, dm.heightPixels); + + mModel = app.setLauncher(this); + mIconCache = app.getIconCache(); + mIconCache.flushInvalidIcons(mGrid); } protected void onUserLeaveHint() { @@ -496,17 +583,64 @@ public class Launcher extends Activity sPausedFromUserAction = true; } - /** To be overriden by subclasses to hint to Launcher that we have custom content */ - protected boolean hasCustomContentToLeft() { + /** To be overridden by subclasses to hint to Launcher that we have custom content */ + protected boolean hasCustomSearchSupport() { return false; } + protected boolean hasCustomContentToLeft() { + return isGelIntegrationSupported() && isGelIntegrationEnabled(); + } + + public boolean isGelIntegrationSupported() { + final SearchManager searchManager = + (SearchManager) getSystemService(Context.SEARCH_SERVICE); + ComponentName globalSearchActivity = searchManager.getGlobalSearchActivity(); + + // Currently the only custom content available is the GEL launcher integration, + // only supported on CyanogenMod. + return globalSearchActivity != null && isCM(); + } + + public boolean isGelIntegrationEnabled() { + return mGelIntegrationEnabled; + } + + public void onCustomContentLaunch() { + if(isGelIntegrationEnabled() && isGelIntegrationSupported()) { + GelIntegrationHelper.getInstance().registerSwipeBackGestureListenerAndStartGel(this, mWorkspace.isLayoutRtl()); + } + } + + /** + * Check if the device running this application is running CyanogenMod. + * @return true if this device is running CM. + */ + protected boolean isCM() { + return getPackageManager().hasSystemFeature("com.cyanogenmod.android"); + } + /** * To be overridden by subclasses to create the custom content and call * {@link #addToCustomContentPage}. This will only be invoked if * {@link #hasCustomContentToLeft()} is {@code true}. */ - protected void addCustomContentToLeft() { + protected void populateCustomContentContainer() { + } + + /** + * To be overridden by subclasses to indicate that there is an activity to launch + * before showing the standard launcher experience. + */ + protected boolean hasFirstRunActivity() { + return false; + } + + /** + * To be overridden by subclasses to launch any first run activity + */ + protected Intent getFirstRunActivity() { + return null; } /** @@ -521,13 +655,22 @@ public class Launcher extends Activity if (!mWorkspace.hasCustomContent() && hasCustomContentToLeft()) { // Create the custom content page and call the subclass to populate it. - mWorkspace.createCustomContentPage(); - addCustomContentToLeft(); + mWorkspace.createCustomContentContainer(); + populateCustomContentContainer(); } else if (mWorkspace.hasCustomContent() && !hasCustomContentToLeft()) { mWorkspace.removeCustomContentPage(); } } + /** To be overriden by subclasses to hint to Launcher that we have custom content and + * support {@link #hasCustomSearchSupport()} + * @see com.android.launcher.home.Home#MODE_SEARCH_TEXT + * @see com.android.launcher.home.Home#MODE_SEARCH_VOICE + * */ + protected void requestSearch(int mode) { + // To be implemented + } + private void updateGlobalIcons() { boolean searchVisible = false; boolean voiceVisible = false; @@ -590,12 +733,12 @@ public class Launcher extends Activity mIconCache.flush(); final LocaleConfiguration localeConfiguration = sLocaleConfiguration; - new Thread("WriteLocaleConfiguration") { - @Override - public void run() { + new AsyncTask<Void, Void, Void>() { + public Void doInBackground(Void ... args) { writeConfiguration(Launcher.this, localeConfiguration); + return null; } - }.start(); + }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void) null); } } @@ -659,10 +802,6 @@ public class Launcher extends Activity return mInflater; } - public DragLayer getDragLayer() { - return mDragLayer; - } - boolean isDraggingEnabled() { // We prevent dragging when we are loading the workspace as it is possible to pick up a view // that is subsequently removed from the workspace in startBinding(). @@ -682,6 +821,34 @@ public class Launcher extends Activity } /** + * Copied from View -- the View version of the method isn't called + * anywhere else in our process and only exists for API level 17+, + * so it's ok to keep our own version with no API requirement. + */ + public static int generateViewId() { + for (;;) { + final int result = sNextGeneratedId.get(); + // aapt-generated IDs have the high byte nonzero; clamp to the range under that. + int newValue = result + 1; + if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0. + if (sNextGeneratedId.compareAndSet(result, newValue)) { + return result; + } + } + } + + public int getViewIdForItem(ItemInfo info) { + // This cast is safe given the > 2B range for int. + int itemId = (int) info.id; + if (mItemIdToViewId.containsKey(itemId)) { + return mItemIdToViewId.get(itemId); + } + int viewId = generateViewId(); + mItemIdToViewId.put(itemId, viewId); + return viewId; + } + + /** * Returns whether we should delay spring loaded mode -- for shortcuts and widgets that have * a configuration step, this allows the proper animations to run after other transitions. */ @@ -718,14 +885,27 @@ public class Launcher extends Activity final int requestCode, final int resultCode, final Intent data) { // Reset the startActivity waiting flag mWaitingForResult = false; + int pendingAddWidgetId = mPendingAddWidgetId; + mPendingAddWidgetId = -1; + + Runnable exitSpringLoaded = new Runnable() { + @Override + public void run() { + exitSpringLoadedDragModeDelayed((resultCode != RESULT_CANCELED), + EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT, null); + } + }; if (requestCode == REQUEST_BIND_APPWIDGET) { - int appWidgetId = data != null ? + final int appWidgetId = data != null ? data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1) : -1; if (resultCode == RESULT_CANCELED) { completeTwoStageWidgetDrop(RESULT_CANCELED, appWidgetId); + mWorkspace.removeExtraEmptyScreen(true, exitSpringLoaded, + ON_ACTIVITY_RESULT_ANIMATION_DELAY, false); } else if (resultCode == RESULT_OK) { - addAppWidgetImpl(appWidgetId, mPendingAddInfo, null, mPendingAddWidgetInfo); + addAppWidgetImpl(appWidgetId, mPendingAddInfo, null, + mPendingAddWidgetInfo, ON_ACTIVITY_RESULT_ANIMATION_DELAY); } return; } else if (requestCode == REQUEST_PICK_WALLPAPER) { @@ -733,24 +913,67 @@ public class Launcher extends Activity mWorkspace.exitOverviewMode(false); } return; + } else if (requestCode == REQUEST_LOCK_PATTERN) { + mHiddenFolderAuth = true; + switch (resultCode) { + case RESULT_OK: + FragmentManager fragmentManager = getFragmentManager(); + FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); + + fragmentTransaction.setCustomAnimations(0, 0); + fragmentTransaction.replace(R.id.launcher, mHiddenFolderFragment, + HiddenFolderFragment.HIDDEN_FOLDER_FRAGMENT); + fragmentTransaction.commit(); + break; + case RESULT_CANCELED: + // User failed to enter/confirm a lock pattern, back out + break; + } + return; } - boolean delayExitSpringLoadedMode = false; boolean isWidgetDrop = (requestCode == REQUEST_PICK_APPWIDGET || requestCode == REQUEST_CREATE_APPWIDGET); // We have special handling for widgets if (isWidgetDrop) { - int appWidgetId = data != null ? - data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1) : -1; - if (appWidgetId < 0) { + final int appWidgetId; + int widgetId = data != null ? data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1) + : -1; + if (widgetId < 0) { + appWidgetId = pendingAddWidgetId; + } else { + appWidgetId = widgetId; + } + + final int result; + final Runnable onComplete; + if (appWidgetId < 0 || resultCode == RESULT_CANCELED) { Log.e(TAG, "Error: appWidgetId (EXTRA_APPWIDGET_ID) was not returned from the \\" + "widget configuration activity."); - completeTwoStageWidgetDrop(RESULT_CANCELED, appWidgetId); - mWorkspace.stripEmptyScreens(); + result = RESULT_CANCELED; + completeTwoStageWidgetDrop(result, appWidgetId); + onComplete = new Runnable() { + @Override + public void run() { + exitSpringLoadedDragModeDelayed(false, 0, null); + } + }; } else { - completeTwoStageWidgetDrop(resultCode, appWidgetId); + result = resultCode; + final CellLayout dropLayout = + (CellLayout) mWorkspace.getScreenWithId(mPendingAddInfo.screenId); + dropLayout.setDropPending(true); + onComplete = new Runnable() { + @Override + public void run() { + completeTwoStageWidgetDrop(result, appWidgetId); + dropLayout.setDropPending(false); + } + }; } + mWorkspace.removeExtraEmptyScreen(true, onComplete, ON_ACTIVITY_RESULT_ANIMATION_DELAY, + false); return; } @@ -770,15 +993,15 @@ public class Launcher extends Activity if (isWorkspaceLocked()) { sPendingAddList.add(args); } else { - delayExitSpringLoadedMode = completeAdd(args); + completeAdd(args); } + mWorkspace.removeExtraEmptyScreen(true, exitSpringLoaded, + ON_ACTIVITY_RESULT_ANIMATION_DELAY, false); } else if (resultCode == RESULT_CANCELED) { - mWorkspace.stripEmptyScreens(); + mWorkspace.removeExtraEmptyScreen(true, exitSpringLoaded, + ON_ACTIVITY_RESULT_ANIMATION_DELAY, false); } mDragLayer.clearAnimatedView(); - // Exit spring loaded mode if necessary after cancelling the configuration of a widget - exitSpringLoadedDragModeDelayed((resultCode != RESULT_CANCELED), delayExitSpringLoadedMode, - null); } private void completeTwoStageWidgetDrop(final int resultCode, final int appWidgetId) { @@ -798,25 +1021,19 @@ public class Launcher extends Activity public void run() { completeAddAppWidget(appWidgetId, mPendingAddInfo.container, mPendingAddInfo.screenId, layout, null); - exitSpringLoadedDragModeDelayed((resultCode != RESULT_CANCELED), false, - null); + exitSpringLoadedDragModeDelayed((resultCode != RESULT_CANCELED), + EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT, null); } }; } else if (resultCode == RESULT_CANCELED) { + mAppWidgetHost.deleteAppWidgetId(appWidgetId); animationType = Workspace.CANCEL_TWO_STAGE_WIDGET_DROP_ANIMATION; - onCompleteRunnable = new Runnable() { - @Override - public void run() { - exitSpringLoadedDragModeDelayed((resultCode != RESULT_CANCELED), false, - null); - } - }; } if (mDragLayer.getAnimatedView() != null) { mWorkspace.animateWidgetDrop(mPendingAddInfo, cellLayout, (DragView) mDragLayer.getAnimatedView(), onCompleteRunnable, animationType, boundWidget, true); - } else { + } else if (onCompleteRunnable != null) { // The animated view may be null in the case of a rotation during widget configuration onCompleteRunnable.run(); } @@ -843,15 +1060,15 @@ public class Launcher extends Activity } super.onResume(); - if (settingsChanged()) { - android.os.Process.killProcess(android.os.Process.myPid()); + if(isGelIntegrationEnabled() && isGelIntegrationSupported()) { + GelIntegrationHelper.getInstance().handleGelResume(); } // Restore the previous launcher state if (mOnResumeState == State.WORKSPACE) { showWorkspace(false); } else if (mOnResumeState == State.APPS_CUSTOMIZE) { - showAllApps(false, AppsCustomizePagedView.ContentType.Applications, false); + showAllApps(false, mAppsCustomizeContent.getContentType(), false); } mOnResumeState = State.NONE; @@ -862,7 +1079,7 @@ public class Launcher extends Activity sPausedFromUserAction = false; if (mRestoring || mOnResumeNeedsLoad) { mWorkspaceLoading = true; - mModel.startLoader(true, -1); + mModel.startLoader(true, PagedView.INVALID_RESTORE_PAGE); mRestoring = false; mOnResumeNeedsLoad = false; } @@ -937,6 +1154,29 @@ public class Launcher extends Activity mWorkspace.updateInteractionForState(); mWorkspace.onResume(); mAppsCustomizeContent.onResume(); + + //Close out Fragments + Fragment f = getFragmentManager().findFragmentByTag( + TransitionEffectsFragment.TRANSITION_EFFECTS_FRAGMENT); + if (f != null) { + mTransitionEffectsFragment.setEffect(); + } + f = getFragmentManager().findFragmentByTag( + DynamicGridSizeFragment.DYNAMIC_GRID_SIZE_FRAGMENT); + if (f != null) { + mDynamicGridSizeFragment.setSize(); + mWorkspace.hideOutlines(); + } + Fragment f1 = getFragmentManager().findFragmentByTag( + HiddenFolderFragment.HIDDEN_FOLDER_FRAGMENT); + if (f1 != null && !mHiddenFolderAuth) { + mHiddenFolderFragment.saveHiddenFolderStatus(-1); + FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction(); + fragmentTransaction + .remove(mHiddenFolderFragment).commit(); + } else { + mHiddenFolderAuth = false; + } } @Override @@ -954,12 +1194,9 @@ public class Launcher extends Activity if (mWorkspace.getCustomContentCallbacks() != null) { mWorkspace.getCustomContentCallbacks().onHide(); } - } - protected void onFinishBindingItems() { - if (mWorkspace != null && hasCustomContentToLeft() && mWorkspace.hasCustomContent()) { - addCustomContentToLeft(); - } + //Reset the OverviewPanel position + ((SlidingUpPanelLayout) mOverviewPanel).collapsePane(); } QSBScroller mQsbScroller = new QSBScroller() { @@ -969,6 +1206,7 @@ public class Launcher extends Activity public void setScrollY(int scroll) { scrollY = scroll; + // Be careful of feature check isSearchBarEnabled if (mWorkspace.isOnOrMovingToCustomContent()) { mSearchDropTargetBar.setTranslationY(- scrollY); getQsbBar().setTranslationY(-scrollY); @@ -978,7 +1216,9 @@ public class Launcher extends Activity public void resetQSBScroll() { mSearchDropTargetBar.animate().translationY(0).start(); - getQsbBar().animate().translationY(0).start(); + if (isSearchBarEnabled()) { + getQsbBar().animate().translationY(0).start(); + } } public interface CustomContentCallbacks { @@ -992,17 +1232,11 @@ public class Launcher extends Activity public void onScrollProgressChanged(float progress); } - protected void startSettings() { - Intent settings; - // If we are on CyanogenMod the launcher settings are accessed from system settings. - if (!getPackageManager().hasSystemFeature("com.cyanogenmod.android")) { - settings = new Intent().setClass(this, SettingsActivity.class); - settings.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK - | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); - } else { - settings = new Intent(android.provider.Settings.ACTION_SETTINGS); - } + protected void startThemeSettings() { + Intent settings = new Intent().setClassName(OverviewSettingsPanel.ANDROID_SETTINGS, + OverviewSettingsPanel.THEME_SETTINGS); startActivity(settings); + if (mWorkspace.isInOverviewMode()) { mWorkspace.exitOverviewMode(false); } else if (mAppsCustomizeContent.isInOverviewMode()) { @@ -1038,89 +1272,88 @@ public class Launcher extends Activity mAppsCustomizeContent.setSortMode(AppsCustomizePagedView.SortMode.LaunchCount); break; } + mOverviewSettingsPanel.notifyDataSetInvalidated(); + SettingsProvider.putInt(getBaseContext(), SettingsProvider.SETTINGS_UI_DRAWER_SORT_MODE, + mAppsCustomizeContent.getSortMode().getValue()); return true; } }); popupMenu.show(); } - public void onClickTransitionEffectButton(View v) { - AlertDialog.Builder builder = new AlertDialog.Builder(this); + public void onClickDynamicGridSizeButton() { + FragmentManager fragmentManager = getFragmentManager(); + FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); - // Load values - final PagedView pagedView = isAllAppsVisible() ? mAppsCustomizeContent : mWorkspace; - final PagedView.TransitionEffect oldEffect = pagedView.getTransitionEffect(); - final String oldEffectName = oldEffect != null ? oldEffect.getName() : - PagedView.TransitionEffect.TRANSITION_EFFECT_NONE; + mDynamicGridSizeFragment = new DynamicGridSizeFragment(); + fragmentTransaction.replace(R.id.launcher, mDynamicGridSizeFragment, + DynamicGridSizeFragment.DYNAMIC_GRID_SIZE_FRAGMENT); + fragmentTransaction.commit(); + } - final String[] titles = getResources().getStringArray(R.array.transition_effect_entries); - final String[] values = getResources().getStringArray(R.array.transition_effect_values); + public void setDynamicGridSize(DeviceProfile.GridSize size) { + SettingsProvider.putInt(this, + SettingsProvider.SETTINGS_UI_DYNAMIC_GRID_SIZE, size.getValue()); - int selected = -1; - for (int i = values.length - 1; i >= 0; i--) { - if (values[i].equals(oldEffectName)) { - selected = i; - break; - } - } + updateDynamicGrid(); - // Create title view with overflow menu - View customTitle = getLayoutInflater().inflate(R.layout.dialog_title_overflow_menu, null); - TextView title = (TextView) customTitle.findViewById(android.R.id.title); - title.setText(R.string.transition_effect_button_text); + mOverviewSettingsPanel.notifyDataSetInvalidated(); - View overflowMenu = customTitle.findViewById(R.id.overflow_menu_button); - overflowMenu.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - onClickTransitionEffectOverflowMenuButton(v); - } - }); + FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction(); + fragmentTransaction + .setCustomAnimations(0, R.anim.exit_out_right); + fragmentTransaction + .remove(mDynamicGridSizeFragment).commit(); - builder.setCustomTitle(customTitle); + mDarkPanel.setVisibility(View.VISIBLE); + ObjectAnimator anim = ObjectAnimator.ofFloat( + mDarkPanel, "alpha", 0.3f, 0.0f); + anim.start(); + anim.addListener(mAnimatorListener); - builder.setSingleChoiceItems(titles, selected, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - String effect = values[which]; - PagedView.TransitionEffect.setFromString(pagedView, effect); - - // Show the changes immediately - final int currentPage = pagedView.getNextPage(); - final int nextPage = currentPage + (currentPage != pagedView.getPageCount() - 1 ? 1 : -1); - pagedView.snapToPageImmediately(currentPage); - pagedView.snapToPage(nextPage, new Runnable() { - @Override - public void run() { - pagedView.snapToPage(currentPage); - } - }); + } - SettingsProvider.get(Launcher.this).edit() - .putString(!isAllAppsVisible() ? - SettingsProvider.SETTINGS_UI_HOMESCREEN_SCROLLING_TRANSITION_EFFECT : - SettingsProvider.SETTINGS_UI_DRAWER_SCROLLING_TRANSITION_EFFECT, effect) - .commit(); - } - }); + public void onClickTransitionEffectButton(View v, final boolean pageOrDrawer) { + Bundle bundle = new Bundle(); + bundle.putBoolean(TransitionEffectsFragment.PAGE_OR_DRAWER_SCROLL_SELECT, + pageOrDrawer); + FragmentManager fragmentManager = getFragmentManager(); + FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); - if (isAllAppsVisible()) { - mAppsCustomizeContent.exitOverviewMode(true); - } else { - mWorkspace.exitOverviewMode(true); - } + mTransitionEffectsFragment = new TransitionEffectsFragment(); + mTransitionEffectsFragment.setArguments(bundle); + fragmentTransaction.setCustomAnimations(0, 0); + fragmentTransaction.replace(R.id.launcher, mTransitionEffectsFragment, + TransitionEffectsFragment.TRANSITION_EFFECTS_FRAGMENT); + fragmentTransaction.commit(); + } - builder.setPositiveButton(android.R.string.ok, null) - .setOnDismissListener(new DialogInterface.OnDismissListener() { - @Override - public void onDismiss(DialogInterface dialog) { - mTransitionEffectDialog = null; - } - }); - mTransitionEffectDialog = builder.create(); - mTransitionEffectDialog.show(); - mTransitionEffectDialog.setCanceledOnTouchOutside(true); - mTransitionEffectDialog.getWindow().getDecorView().setAlpha(0.6f); + public void setTransitionEffect(boolean pageOrDrawer, String newTransitionEffect) { + String mSettingsProviderValue = pageOrDrawer ? + SettingsProvider.SETTINGS_UI_DRAWER_SCROLLING_TRANSITION_EFFECT + : SettingsProvider.SETTINGS_UI_HOMESCREEN_SCROLLING_TRANSITION_EFFECT; + PagedView pagedView = pageOrDrawer ? mAppsCustomizeContent : mWorkspace; + + SettingsProvider + .get(getApplicationContext()) + .edit() + .putString(mSettingsProviderValue, + newTransitionEffect).commit(); + TransitionEffect.setFromString(pagedView, newTransitionEffect); + + mOverviewSettingsPanel.notifyDataSetInvalidated(); + + FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction(); + fragmentTransaction + .setCustomAnimations(0, R.anim.exit_out_right); + fragmentTransaction + .remove(mTransitionEffectsFragment).commit(); + + mDarkPanel.setVisibility(View.VISIBLE); + ObjectAnimator anim = ObjectAnimator.ofFloat( + mDarkPanel, "alpha", 0.3f, 0.0f); + anim.start(); + anim.addListener(mAnimatorListener); } public void onClickTransitionEffectOverflowMenuButton(View v) { @@ -1175,6 +1408,13 @@ public class Launcher extends Activity popupMenu.show(); } + protected boolean hasSettings() { + return false; + } + + protected void startSettings() { + } + public interface QSBScroller { public void setScrollY(int scrollY); } @@ -1271,6 +1511,7 @@ public class Launcher extends Activity * * @param savedState The previous state. */ + @SuppressWarnings("unchecked") private void restoreState(Bundle savedState) { if (savedState == null) { return; @@ -1298,6 +1539,7 @@ public class Launcher extends Activity mPendingAddInfo.spanX = savedState.getInt(RUNTIME_STATE_PENDING_ADD_SPAN_X); mPendingAddInfo.spanY = savedState.getInt(RUNTIME_STATE_PENDING_ADD_SPAN_Y); mPendingAddWidgetInfo = savedState.getParcelable(RUNTIME_STATE_PENDING_ADD_WIDGET_INFO); + mPendingAddWidgetId = savedState.getInt(RUNTIME_STATE_PENDING_ADD_WIDGET_ID); mWaitingForResult = true; mRestoring = true; } @@ -1321,6 +1563,8 @@ public class Launcher extends Activity int currentIndex = savedState.getInt("apps_customize_currentIndex"); mAppsCustomizeContent.restorePageForIndex(currentIndex); } + mItemIdToViewId = (HashMap<Integer, Integer>) + savedState.getSerializable(RUNTIME_STATE_VIEW_IDS); } /** @@ -1332,6 +1576,7 @@ public class Launcher extends Activity mLauncherView = findViewById(R.id.launcher); mDragLayer = (DragLayer) findViewById(R.id.drag_layer); mWorkspace = (Workspace) mDragLayer.findViewById(R.id.workspace); + mPageIndicators = mDragLayer.findViewById(R.id.page_indicator); mLauncherView.setSystemUiVisibility( View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION); @@ -1348,78 +1593,11 @@ public class Launcher extends Activity } mOverviewPanel = findViewById(R.id.overview_panel); - mOverviewPanel.setAlpha(0f); - View widgetButton = findViewById(R.id.widget_button); - widgetButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View arg0) { - showAllApps(true, AppsCustomizePagedView.ContentType.Widgets, true); - } - }); - widgetButton.setOnTouchListener(getHapticFeedbackTouchListener()); - - View wallpaperButton = findViewById(R.id.wallpaper_button); - wallpaperButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View arg0) { - startWallpaper(); - } - }); - wallpaperButton.setOnTouchListener(getHapticFeedbackTouchListener()); - - View settingsButton = findViewById(R.id.settings_button); - settingsButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View arg0) { - startSettings(); - } - }); - settingsButton.setOnTouchListener(getHapticFeedbackTouchListener()); - - View defaultScreenButton = findViewById(R.id.default_screen_button); - defaultScreenButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View arg0) { - mWorkspace.onClickDefaultScreenButton(); - } - }); - defaultScreenButton.setOnTouchListener(getHapticFeedbackTouchListener()); - - View transitionEffectButton = findViewById(R.id.transition_effect_button); - transitionEffectButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View arg0) { - onClickTransitionEffectButton(arg0); - } - }); - transitionEffectButton.setOnTouchListener(getHapticFeedbackTouchListener()); - - View iconPackButton = findViewById(R.id.icon_pack_button); - iconPackButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View arg0) { - IconPackHelper.pickIconPack(Launcher.this, false); - } - }); - iconPackButton.setOnTouchListener(getHapticFeedbackTouchListener()); - - View sortButton = findViewById(R.id.sort_button); - sortButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View arg0) { - onClickSortModeButton(arg0); - } - }); - sortButton.setOnTouchListener(getHapticFeedbackTouchListener()); - - View filterButton = findViewById(R.id.filter_button); - filterButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - - } - }); - filterButton.setOnTouchListener(getHapticFeedbackTouchListener()); + mOverviewSettingsPanel = new OverviewSettingsPanel( + this, mOverviewPanel); + mOverviewSettingsPanel.initializeAdapter(); + mOverviewSettingsPanel.initializeViews(); + mDarkPanel = ((SlidingUpPanelLayout) mOverviewPanel).findViewById(R.id.dark_panel); // Setup the workspace mWorkspace.setHapticFeedbackEnabled(false); @@ -1428,7 +1606,8 @@ public class Launcher extends Activity dragController.addDragListener(mWorkspace); // Get the search/delete bar - mSearchDropTargetBar = (SearchDropTargetBar) mDragLayer.findViewById(R.id.qsb_bar); + mSearchDropTargetBar = (SearchDropTargetBar) + mDragLayer.findViewById(R.id.search_drop_target_bar); // Setup AppsCustomize mAppsCustomizeLayout = (AppsCustomizeLayout) findViewById(R.id.apps_customize_pane); @@ -1494,7 +1673,6 @@ public class Launcher extends Activity favorite.setCompoundDrawables(null, d, null, null); favorite.setOnTouchListener(getHapticFeedbackTouchListener()); } - Utilities.applyTypeface(favorite); return favorite; } @@ -1662,11 +1840,12 @@ public class Launcher extends Activity if (appWidgetId != -1) { // Deleting an app widget ID is a void call but writes to disk before returning // to the caller... - new Thread("deleteAppWidgetId") { - public void run() { + new AsyncTask<Void, Void, Void>() { + public Void doInBackground(Void ... args) { mAppWidgetHost.deleteAppWidgetId(appWidgetId); + return null; } - }.start(); + }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void) null); } showOutOfSpaceMessage(isHotseatLayout(layout)); return; @@ -1722,6 +1901,15 @@ public class Launcher extends Activity } else if (Intent.ACTION_USER_PRESENT.equals(action)) { mUserPresent = true; updateRunning(); + } else if (ENABLE_DEBUG_INTENTS && DebugIntents.DELETE_DATABASE.equals(action)) { + mModel.resetLoadedState(false, true); + mModel.startLoader(false, PagedView.INVALID_RESTORE_PAGE, + LauncherModel.LOADER_FLAG_CLEAR_WORKSPACE); + } else if (ENABLE_DEBUG_INTENTS && DebugIntents.MIGRATE_DATABASE.equals(action)) { + mModel.resetLoadedState(false, true); + mModel.startLoader(false, PagedView.INVALID_RESTORE_PAGE, + LauncherModel.LOADER_FLAG_CLEAR_WORKSPACE + | LauncherModel.LOADER_FLAG_MIGRATE_SHORTCUTS); } } }; @@ -1734,6 +1922,10 @@ public class Launcher extends Activity final IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_SCREEN_OFF); filter.addAction(Intent.ACTION_USER_PRESENT); + if (ENABLE_DEBUG_INTENTS) { + filter.addAction(DebugIntents.DELETE_DATABASE); + filter.addAction(DebugIntents.MIGRATE_DATABASE); + } registerReceiver(mReceiver, filter); FirstFrameAnimatorHelper.initializeDrawListener(getWindow().getDecorView()); mAttached = true; @@ -1869,6 +2061,30 @@ public class Launcher extends Activity Toast.makeText(this, getString(strId), Toast.LENGTH_SHORT).show(); } + public DragLayer getDragLayer() { + return mDragLayer; + } + + public Workspace getWorkspace() { + return mWorkspace; + } + + public Hotseat getHotseat() { + return mHotseat; + } + + public View getDarkPanel() { + return mDarkPanel; + } + + public View getOverviewPanel() { + return mOverviewPanel; + } + + public SearchDropTargetBar getSearchBar() { + return mSearchDropTargetBar; + } + public LauncherAppWidgetHost getAppWidgetHost() { return mAppWidgetHost; } @@ -1877,6 +2093,14 @@ public class Launcher extends Activity return mModel; } + public LauncherClings getLauncherClings() { + return mLauncherClings; + } + + protected SharedPreferences getSharedPrefs() { + return mSharedPrefs; + } + public void closeSystemDialogs() { getWindow().closeAllPanels(); @@ -1913,7 +2137,7 @@ public class Launcher extends Activity // In all these cases, only animate if we're already on home mWorkspace.exitWidgetResizeMode(); if (alreadyOnHome && mState == State.WORKSPACE && !mWorkspace.isTouchActive() && - openFolder == null) { + openFolder == null && shouldMoveToDefaultScreenOnHomeIntent()) { mWorkspace.moveToDefaultScreen(true); } @@ -1936,9 +2160,11 @@ public class Launcher extends Activity } // Reset the apps customize page - if (mAppsCustomizeLayout != null) { + if (!alreadyOnHome && mAppsCustomizeLayout != null) { mAppsCustomizeLayout.reset(); } + + onHomeIntent(); } if (DEBUG_RESUME_TIME) { @@ -1946,6 +2172,21 @@ public class Launcher extends Activity } } + /** + * Override point for subclasses to prevent movement to the default screen when the home + * button is pressed. Used (for example) in GEL, to prevent movement during a search. + */ + protected boolean shouldMoveToDefaultScreenOnHomeIntent() { + return true; + } + + /** + * Override point for subclasses to provide custom behaviour for when a home intent is fired. + */ + protected void onHomeIntent() { + // Do nothing + } + @Override public void onRestoreInstanceState(Bundle state) { super.onRestoreInstanceState(state); @@ -1957,7 +2198,8 @@ public class Launcher extends Activity @Override protected void onSaveInstanceState(Bundle outState) { if (mWorkspace.getChildCount() > 0) { - outState.putInt(RUNTIME_STATE_CURRENT_SCREEN, mWorkspace.getRestorePage()); + outState.putInt(RUNTIME_STATE_CURRENT_SCREEN, + mWorkspace.getCurrentPageOffsetFromCustomContent()); } super.onSaveInstanceState(outState); @@ -1975,6 +2217,7 @@ public class Launcher extends Activity outState.putInt(RUNTIME_STATE_PENDING_ADD_SPAN_X, mPendingAddInfo.spanX); outState.putInt(RUNTIME_STATE_PENDING_ADD_SPAN_Y, mPendingAddInfo.spanY); outState.putParcelable(RUNTIME_STATE_PENDING_ADD_WIDGET_INFO, mPendingAddWidgetInfo); + outState.putInt(RUNTIME_STATE_PENDING_ADD_WIDGET_ID, mPendingAddWidgetId); } if (mFolderInfo != null && mWaitingForResult) { @@ -1984,6 +2227,7 @@ public class Launcher extends Activity // Save the current AppsCustomize tab if (mAppsCustomizeLayout != null) { + AppsCustomizePagedView.ContentType type = mAppsCustomizeContent.getContentType(); String currentTabTag = mAppsCustomizeContent.getContentType().name(); if (currentTabTag != null) { outState.putString("apps_customize_currentContentType", currentTabTag); @@ -1991,6 +2235,7 @@ public class Launcher extends Activity int currentIndex = mAppsCustomizeContent.getSaveInstanceStateIndex(); outState.putInt("apps_customize_currentIndex", currentIndex); } + outState.putSerializable(RUNTIME_STATE_VIEW_IDS, mItemIdToViewId); } @Override @@ -2029,17 +2274,33 @@ public class Launcher extends Activity mDragLayer.clearAllResizeFrames(); ((ViewGroup) mWorkspace.getParent()).removeAllViews(); - mWorkspace.removeAllViews(); + mWorkspace.removeAllWorkspaceScreens(); mWorkspace = null; mDragController = null; LauncherAnimUtils.onDestroyActivity(); + + unregisterReceiver(protectedAppsChangedReceiver); } public DragController getDragController() { return mDragController; } + public void validateLockForHiddenFolders(Bundle bundle, FolderIcon info) { + // Validate Lock Pattern + Intent lockPatternActivity = new Intent(); + lockPatternActivity.setClassName( + "com.android.settings", + "com.android.settings.applications.LockPatternActivity"); + startActivityForResult(lockPatternActivity, REQUEST_LOCK_PATTERN); + mHiddenFolderAuth = false; + + mHiddenFolderIcon = info; + mHiddenFolderFragment = new HiddenFolderFragment(); + mHiddenFolderFragment.setArguments(bundle); + } + @Override public void startActivityForResult(Intent intent, int requestCode) { if (requestCode >= 0) mWaitingForResult = true; @@ -2119,29 +2380,28 @@ public class Launcher extends Activity } } + public boolean isOnCustomContent() { + return mWorkspace.isOnOrMovingToCustomContent(); + } + @Override public boolean onPrepareOptionsMenu(Menu menu) { super.onPrepareOptionsMenu(menu); - if (!isAllAppsVisible()) { + if (!isOnCustomContent()) { + // Close any open folders + closeFolder(); + // Stop resizing any widgets + mWorkspace.exitWidgetResizeMode(); if (!mWorkspace.isInOverviewMode()) { - mWorkspace.enterOverviewMode(); - } else { - mWorkspace.exitOverviewMode(true); - } - } else { - if (!mAppsCustomizeContent.isInOverviewMode()) { - mAppsCustomizeContent.enterOverviewMode(); + // Show the overview mode + showOverviewMode(true); } else { - mAppsCustomizeContent.exitOverviewMode(true); + showWorkspace(true); } } return false; } - void enterAllAppsOverviewMode() { - mAppsCustomizeContent.enterOverviewMode(); - } - @Override public boolean onSearchRequested() { startSearch(null, false, null, true); @@ -2153,6 +2413,10 @@ public class Launcher extends Activity return mWorkspaceLoading || mWaitingForResult; } + public boolean isWorkspaceLoading() { + return mWorkspaceLoading; + } + private void resetAddInfo() { mPendingAddInfo.container = ItemInfo.NO_ID; mPendingAddInfo.screenId = -1; @@ -2162,10 +2426,17 @@ public class Launcher extends Activity mPendingAddInfo.dropPos = null; } - void addAppWidgetImpl(final int appWidgetId, ItemInfo info, AppWidgetHostView boundWidget, - AppWidgetProviderInfo appWidgetInfo) { + void addAppWidgetImpl(final int appWidgetId, final ItemInfo info, + final AppWidgetHostView boundWidget, final AppWidgetProviderInfo appWidgetInfo) { + addAppWidgetImpl(appWidgetId, info, boundWidget, appWidgetInfo, 0); + } + + void addAppWidgetImpl(final int appWidgetId, final ItemInfo info, + final AppWidgetHostView boundWidget, final AppWidgetProviderInfo appWidgetInfo, int + delay) { if (appWidgetInfo.configure != null) { mPendingAddWidgetInfo = appWidgetInfo; + mPendingAddWidgetId = appWidgetId; // Launch over to configure widget, if needed Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_CONFIGURE); @@ -2174,10 +2445,17 @@ public class Launcher extends Activity Utilities.startActivityForResultSafely(this, intent, REQUEST_CREATE_APPWIDGET); } else { // Otherwise just add it + Runnable onComplete = new Runnable() { + @Override + public void run() { + // Exit spring loaded mode if necessary after adding the widget + exitSpringLoadedDragModeDelayed(true, EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT, + null); + } + }; completeAddAppWidget(appWidgetId, info.container, info.screenId, boundWidget, appWidgetInfo); - // Exit spring loaded mode if necessary after adding the widget - exitSpringLoadedDragModeDelayed(true, false, null); + mWorkspace.removeExtraEmptyScreen(true, onComplete, delay, false); } } @@ -2327,7 +2605,7 @@ public class Launcher extends Activity } protected ComponentName getWallpaperPickerComponent() { - return new ComponentName(WALLPAPER_PICKER_PACKAGE, WALLPAPER_PICKER_ACTIVITY); + return new ComponentName(getPackageName(), LauncherWallpaperPickerActivity.class.getName()); } /** @@ -2365,10 +2643,15 @@ public class Launcher extends Activity @Override public void onBackPressed() { + Fragment f1 = getFragmentManager().findFragmentByTag( + HiddenFolderFragment.HIDDEN_FOLDER_FRAGMENT); + if (f1 != null) { + mHiddenFolderFragment.saveHiddenFolderStatus(-1); + FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction(); + fragmentTransaction + .remove(mHiddenFolderFragment).commit(); + } if (isAllAppsVisible()) { - if (isClingsEnabled()) { - dismissAllAppsCling(null); - } if (mAppsCustomizeContent.isInOverviewMode()) { mAppsCustomizeContent.exitOverviewMode(true); } else { @@ -2380,7 +2663,17 @@ public class Launcher extends Activity } } } else if (mWorkspace.isInOverviewMode()) { - mWorkspace.exitOverviewMode(true); + Fragment f = getFragmentManager().findFragmentByTag( + TransitionEffectsFragment.TRANSITION_EFFECTS_FRAGMENT); + Fragment f2 = getFragmentManager().findFragmentByTag( + DynamicGridSizeFragment.DYNAMIC_GRID_SIZE_FRAGMENT); + if (f != null) { + mTransitionEffectsFragment.setEffect(); + } else if (f2 != null) { + mDynamicGridSizeFragment.setSize(); + } else { + mWorkspace.exitOverviewMode(true); + } } else if (mWorkspace.getOpenFolder() != null) { Folder openFolder = mWorkspace.getOpenFolder(); if (openFolder.isEditingName()) { @@ -2454,7 +2747,7 @@ public class Launcher extends Activity final String shortcutClass = intent.getComponent().getClassName(); if (shortcutClass.equals(WidgetAdder.class.getName())) { - showAllApps(true, AppsCustomizePagedView.ContentType.Widgets, true); + onClickAddWidgetButton(); return; } else if (shortcutClass.equals(MemoryDumpActivity.class.getName())) { MemoryDumpActivity.startDump(this); @@ -2504,8 +2797,12 @@ public class Launcher extends Activity * @param v The view that was clicked. */ public void onClickSearchButton(View v) { - v.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY); + if (hasCustomSearchSupport()) { + requestSearch(Home.MODE_SEARCH_TEXT); + return; + } + v.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY); onSearchRequested(); } @@ -2515,8 +2812,12 @@ public class Launcher extends Activity * @param v The view that was clicked. */ public void onClickVoiceButton(View v) { - v.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY); + if (hasCustomSearchSupport()) { + requestSearch(Home.MODE_SEARCH_VOICE); + return; + } + v.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY); startVoice(); } @@ -2545,7 +2846,15 @@ public class Launcher extends Activity * @param v The view that was clicked. */ public void onClickAllAppsButton(View v) { - showAllApps(true, AppsCustomizePagedView.ContentType.Applications, true); + showAllApps(true, AppsCustomizePagedView.ContentType.Applications, false); + } + + /** + * Event handler for the (Add) Widgets button that appears after a long press + * on the home screen. + */ + protected void onClickAddWidgetButton() { + showAllApps(true, AppsCustomizePagedView.ContentType.Widgets, true); } public void onTouchDownAllAppsButton(View v) { @@ -2592,9 +2901,10 @@ public class Launcher extends Activity void startApplicationDetailsActivity(ComponentName componentName) { String packageName = componentName.getPackageName(); - Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, + Intent intent = new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.fromParts("package", packageName, null)); - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK | + Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); startActivitySafely(null, intent, "startApplicationDetailsActivity"); } @@ -2804,6 +3114,11 @@ public class Launcher extends Activity Folder folder = folderIcon.getFolder(); FolderInfo info = folder.mInfo; + if (info.hidden) { + folder.startHiddenFolderManager(); + return; + } + info.opened = true; // Just verify that the folder hasn't already been added to the DragLayer. @@ -2825,7 +3140,7 @@ public class Launcher extends Activity } public void closeFolder() { - Folder folder = mWorkspace.getOpenFolder(); + Folder folder = mWorkspace != null ? mWorkspace.getOpenFolder() : null; if (folder != null) { if (folder.isEditingName()) { folder.dismissEditingName(); @@ -2833,7 +3148,7 @@ public class Launcher extends Activity closeFolder(folder); // Dismiss the folder cling - dismissFolderCling(null); + mLauncherClings.dismissFolderCling(null); } } @@ -2883,7 +3198,8 @@ public class Launcher extends Activity // The hotseat touch handling does not go through Workspace, and we always allow long press // on hotseat items. final View itemUnderLongClick = longClickCellInfo.cell; - boolean allowLongPress = isHotseatLayout(v) || mWorkspace.allowLongPress(); + final boolean inHotseat = isHotseatLayout(v); + boolean allowLongPress = inHotseat || mWorkspace.allowLongPress(); if (allowLongPress && !mDragController.isDragging()) { if (itemUnderLongClick == null) { // User long pressed on empty space @@ -2909,15 +3225,6 @@ public class Launcher extends Activity return mHotseat != null && layout != null && (layout instanceof CellLayout) && (layout == mHotseat.getLayout()); } - Hotseat getHotseat() { - return mHotseat; - } - View getOverviewPanel() { - return mOverviewPanel; - } - SearchDropTargetBar getSearchBar() { - return mSearchDropTargetBar; - } /** * Returns the CellLayout of the specified container at the specified screen. @@ -2934,39 +3241,12 @@ public class Launcher extends Activity } } - protected Workspace getWorkspace() { - return mWorkspace; + public AppsCustomizePagedView getAppsCustomizeContent() { + return mAppsCustomizeContent; } public void updateOverviewPanel() { - View defaultScreenButton = mOverviewPanel.findViewById(R.id.default_screen_button); - View transitionEffectButton = mOverviewPanel.findViewById(R.id.transition_effect_button); - View widgetButton = mOverviewPanel.findViewById(R.id.widget_button); - View wallpaperButton = mOverviewPanel.findViewById(R.id.wallpaper_button); - View sortButton = mOverviewPanel.findViewById(R.id.sort_button); - View filterButton = mOverviewPanel.findViewById(R.id.filter_button); - View iconPackButton = findViewById(R.id.icon_pack_button); - - PagedView pagedView = !isAllAppsVisible() ? mWorkspace : mAppsCustomizeContent; - - defaultScreenButton.setVisibility((!isAllAppsVisible() && pagedView.getPageCount() > 1) ? View.VISIBLE : View.GONE); - transitionEffectButton.setVisibility(pagedView.getPageCount() > 1 ? View.VISIBLE : View.GONE); - widgetButton.setVisibility(!isAllAppsVisible() ? View.VISIBLE : View.GONE); - wallpaperButton.setVisibility(!isAllAppsVisible() ? View.VISIBLE : View.GONE); - sortButton.setVisibility(isAllAppsVisible() ? View.VISIBLE : View.GONE); - // TODO: implement filtering - // filterButton.setVisibility(isAllAppsVisible() ? View.VISIBLE : View.GONE); - filterButton.setVisibility(View.GONE); - - boolean isVisible = !isAllAppsVisible(); - if (isVisible) { - int numIconPacks = IconPackHelper.getSupportedPackages(this).size(); - isVisible = numIconPacks > 0; - } - iconPackButton.setVisibility(isVisible ? View.VISIBLE : View.GONE); - - // Make sure overview panel is drawn above apps customize - mOverviewPanel.bringToFront(); + mOverviewSettingsPanel.update(); } public boolean isAllAppsVisible() { @@ -3077,23 +3357,6 @@ public class Launcher extends Activity AppsCustomizePagedView.ContentType contentType = mAppsCustomizeContent.getContentType(); showAppsCustomizeHelper(animated, springLoaded, contentType); } - - public void showAllAppsCling() { - if (isClingsEnabled() && - !mSharedPrefs.getBoolean(Cling.ALL_APPS_CLING_DISMISSED_KEY, false) && - !skipCustomClingIfNoAccounts() ) { - Cling cling = (Cling) findViewById(R.id.all_apps_cling); - View pageIndicator = mAppsCustomizeLayout.findViewById(R.id.page_indicator); - cling.setPunchThroughForView(pageIndicator); - if (cling != null) { - cling.bringToFront(); - } - initCling(R.id.all_apps_cling, 0, true, true); - } else { - removeCling(R.id.all_apps_cling); - } - } - private void showAppsCustomizeHelper(final boolean animated, final boolean springLoaded, final AppsCustomizePagedView.ContentType contentType) { if (mStateAnimation != null) { @@ -3116,8 +3379,9 @@ public class Launcher extends Activity // Shrink workspaces away if going to AppsCustomize from workspace Animator workspaceAnim = mWorkspace.getChangeStateAnimation(Workspace.State.SMALL, animated); - if (!AppsCustomizePagedView.DISABLE_ALL_APPS) { - // Set the content type for the all apps space + if (!LauncherAppState.isDisableAllApps() + || contentType == AppsCustomizePagedView.ContentType.Widgets) { + // Set the content type for the all apps/widgets space mAppsCustomizeContent.setContentType(contentType); } @@ -3173,10 +3437,6 @@ public class Launcher extends Activity if (mSearchDropTargetBar != null) { mSearchDropTargetBar.hideSearchBar(false); } - - if (contentType == AppsCustomizePagedView.ContentType.Applications) { - showAllAppsCling(); - } } }); @@ -3304,7 +3564,7 @@ public class Launcher extends Activity dispatchOnLauncherTransitionPrepare(fromView, animated, true); dispatchOnLauncherTransitionPrepare(toView, animated, true); - mAppsCustomizeContent.pauseScrolling(); + mAppsCustomizeContent.stopScrolling(); mStateAnimation.addListener(new AnimatorListenerAdapter() { @Override @@ -3316,7 +3576,6 @@ public class Launcher extends Activity onCompleteRunnable.run(); } mAppsCustomizeContent.updateCurrentPageScroll(); - mAppsCustomizeContent.resumeScrolling(); } }); @@ -3433,7 +3692,7 @@ public class Launcher extends Activity } } - void exitSpringLoadedDragModeDelayed(final boolean successfulDrop, boolean extendedDelay, + void exitSpringLoadedDragModeDelayed(final boolean successfulDrop, int delay, final Runnable onCompleteRunnable) { if (mState != State.APPS_CUSTOMIZE_SPRING_LOADED) return; @@ -3450,9 +3709,8 @@ public class Launcher extends Activity exitSpringLoadedDragMode(); } } - }, (extendedDelay ? - EXIT_SPRINGLOADED_MODE_LONG_TIMEOUT : - EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT)); + }, delay); + } void exitSpringLoadedDragMode() { @@ -3626,11 +3884,25 @@ public class Launcher extends Activity } public View getQsbBar() { - if (mQsbBar == null) { - mQsbBar = mInflater.inflate(R.layout.search_bar, mSearchDropTargetBar, false); - mSearchDropTargetBar.addView(mQsbBar); + if (mQsb == null) { + mQsb = mInflater.inflate(R.layout.qsb, mSearchDropTargetBar, false); + mSearchDropTargetBar.addView(mQsb); + } + return mQsb; + } + + public ImageView getQsbBarSearchButton() { + if (mQsbBarSearch == null && getQsbBar() != null) { + return (ImageView) getQsbBar().findViewById(R.id.search_button); } - return mQsbBar; + return mQsbBarSearch; + } + + public ImageView getQsbBarVoiceButton() { + if (mQsbBarVoice == null && getQsbBar() != null) { + return (ImageView) getQsbBar().findViewById(R.id.voice_button); + } + return mQsbBarVoice; } protected boolean updateGlobalSearchIcon() { @@ -3887,14 +4159,18 @@ public class Launcher extends Activity // Create the custom content page (this call updates mDefaultScreen which calls // setCurrentPage() so ensure that all pages are added before calling this). - // The actual content of the custom page will be added during onFinishBindingItems(). - if (!mWorkspace.hasCustomContent() && hasCustomContentToLeft()) { - mWorkspace.createCustomContentPage(); + if (hasCustomContentToLeft()) { + mWorkspace.createCustomContentContainer(); + populateCustomContentContainer(); } } @Override public void bindAddScreens(ArrayList<Long> orderedScreenIds) { + // Log to disk + Launcher.addDumpLog(TAG, "11683562 - bindAddScreens()", true); + Launcher.addDumpLog(TAG, "11683562 - orderedScreenIds: " + + TextUtils.join(", ", orderedScreenIds), true); int count = orderedScreenIds.size(); for (int i = 0; i < count; i++) { mWorkspace.insertNewWorkspaceScreenBeforeEmptyScreen(orderedScreenIds.get(i)); @@ -3939,23 +4215,25 @@ public class Launcher extends Activity } // Add the new screens - bindAddScreens(newScreens); + if (newScreens != null) { + bindAddScreens(newScreens); + } // We add the items without animation on non-visible pages, and with // animations on the new page (which we will try and snap to). - if (!addNotAnimated.isEmpty()) { + if (addNotAnimated != null && !addNotAnimated.isEmpty()) { bindItems(addNotAnimated, 0, addNotAnimated.size(), false); } - if (!addAnimated.isEmpty()) { + if (addAnimated != null && !addAnimated.isEmpty()) { bindItems(addAnimated, 0, addAnimated.size(), true); } // Remove the extra empty screen - mWorkspace.removeExtraEmptyScreens(); + mWorkspace.removeExtraEmptyScreen(false, null); - if (!AppsCustomizePagedView.DISABLE_ALL_APPS && + if (!LauncherAppState.isDisableAllApps() && addedApps != null && mAppsCustomizeContent != null) { mAppsCustomizeContent.addApps(addedApps); } @@ -4053,9 +4331,11 @@ public class Launcher extends Activity // when we are loading right after we return to launcher. mWorkspace.postDelayed(new Runnable() { public void run() { - mWorkspace.snapToPage(newScreenIndex); - mWorkspace.postDelayed(startBounceAnimRunnable, - NEW_APPS_ANIMATION_DELAY); + if (mWorkspace != null) { + mWorkspace.snapToPage(newScreenIndex); + mWorkspace.postDelayed(startBounceAnimRunnable, + NEW_APPS_ANIMATION_DELAY); + } } }, NEW_APPS_PAGE_MOVE_DELAY); } else { @@ -4165,13 +4445,6 @@ public class Launcher extends Activity mWorkspace.getUniqueComponents(true, null); mIntentsOnWorkspaceFromUpgradePath = mWorkspace.getUniqueComponents(true, null); } - - mWorkspace.post(new Runnable() { - @Override - public void run() { - onFinishBindingItems(); - } - }); } private boolean canRunNewAppsAnimation() { @@ -4190,6 +4463,16 @@ public class Launcher extends Activity return bounceAnim; } + public boolean useVerticalBarLayout() { + return LauncherAppState.getInstance().getDynamicGrid(). + getDeviceProfile().isVerticalBarLayout(); + } + + protected Rect getSearchBarBounds() { + return LauncherAppState.getInstance().getDynamicGrid(). + getDeviceProfile().getSearchBarBounds(); + } + @Override public void bindSearchablesChanged() { boolean searchVisible = updateGlobalSearchIcon(); @@ -4205,7 +4488,7 @@ public class Launcher extends Activity * Implementation of the method from LauncherModel.Callbacks. */ public void bindAllApplications(final ArrayList<AppInfo> apps) { - if (AppsCustomizePagedView.DISABLE_ALL_APPS) { + if (LauncherAppState.isDisableAllApps()) { if (mIntentsOnWorkspaceFromUpgradePath != null) { if (LauncherModel.UPGRADE_USE_MORE_APPS_FOLDER) { getHotseat().addAllAppsFolder(mIconCache, apps, @@ -4213,9 +4496,15 @@ public class Launcher extends Activity } mIntentsOnWorkspaceFromUpgradePath = null; } + if (mAppsCustomizeContent != null) { + mAppsCustomizeContent.onPackagesUpdated( + LauncherModel.getSortedWidgetsAndShortcuts(this)); + } } else { if (mAppsCustomizeContent != null) { mAppsCustomizeContent.setApps(apps); + mAppsCustomizeContent.onPackagesUpdated( + LauncherModel.getSortedWidgetsAndShortcuts(this)); } } } @@ -4239,7 +4528,7 @@ public class Launcher extends Activity mWorkspace.updateShortcuts(apps); } - if (!AppsCustomizePagedView.DISABLE_ALL_APPS && + if (!LauncherAppState.isDisableAllApps() && mAppsCustomizeContent != null) { mAppsCustomizeContent.updateApps(apps); } @@ -4255,27 +4544,28 @@ public class Launcher extends Activity * Implementation of the method from LauncherModel.Callbacks. */ public void bindComponentsRemoved(final ArrayList<String> packageNames, - final ArrayList<AppInfo> appInfos, - final boolean packageRemoved) { + final ArrayList<AppInfo> appInfos) { Runnable r = new Runnable() { public void run() { - bindComponentsRemoved(packageNames, appInfos, packageRemoved); + bindComponentsRemoved(packageNames, appInfos); } }; if (waitUntilResume(r)) { return; } - if (packageRemoved) { + if (!packageNames.isEmpty()) { mWorkspace.removeItemsByPackageName(packageNames); - } else { + } + if (!appInfos.isEmpty()) { mWorkspace.removeItemsByApplicationInfo(appInfos); } // Notify the drag controller - mDragController.onAppsRemoved(appInfos, this); + mDragController.onAppsRemoved(packageNames, appInfos); - if (!AppsCustomizePagedView.DISABLE_ALL_APPS && + // Update AllApps + if (!LauncherAppState.isDisableAllApps() && mAppsCustomizeContent != null) { mAppsCustomizeContent.removeApps(appInfos); } @@ -4291,7 +4581,6 @@ public class Launcher extends Activity mWidgetsAndShortcuts = null; } }; - public void bindPackagesUpdated(final ArrayList<Object> widgetsAndShortcuts) { if (waitUntilResume(mBindPackagesUpdatedRunnable, true)) { mWidgetsAndShortcuts = widgetsAndShortcuts; @@ -4299,8 +4588,7 @@ public class Launcher extends Activity } // Update the widgets pane - if (!AppsCustomizePagedView.DISABLE_ALL_APPS && - mAppsCustomizeContent != null) { + if (mAppsCustomizeContent != null) { mAppsCustomizeContent.onPackagesUpdated(widgetsAndShortcuts); } } @@ -4362,202 +4650,27 @@ public class Launcher extends Activity } } - /* Cling related */ - private boolean isClingsEnabled() { - if (DISABLE_CLINGS) { - return false; - } - - // disable clings when running in a test harness - if(ActivityManager.isRunningInTestHarness()) return false; - - // Disable clings for accessibility when explore by touch is enabled - final AccessibilityManager a11yManager = (AccessibilityManager) getSystemService( - ACCESSIBILITY_SERVICE); - if (a11yManager.isTouchExplorationEnabled()) { - return false; - } - - // Restricted secondary users (child mode) will potentially have very few apps - // seeded when they start up for the first time. Clings won't work well with that -// boolean supportsLimitedUsers = -// android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2; -// Account[] accounts = AccountManager.get(this).getAccounts(); -// if (supportsLimitedUsers && accounts.length == 0) { -// UserManager um = (UserManager) getSystemService(Context.USER_SERVICE); -// Bundle restrictions = um.getUserRestrictions(); -// if (restrictions.getBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS, false)) { -// return false; -// } -// } - return true; - } - - private Cling initCling(int clingId, int scrimId, boolean animate, - boolean dimNavBarVisibilty) { - Cling cling = (Cling) findViewById(clingId); - View scrim = null; - if (scrimId > 0) { - scrim = findViewById(R.id.cling_scrim); - } - if (cling != null) { - cling.init(this, scrim); - cling.show(animate, SHOW_CLING_DURATION); - - if (dimNavBarVisibilty) { - cling.setSystemUiVisibility(cling.getSystemUiVisibility() | - View.SYSTEM_UI_FLAG_LOW_PROFILE); - } - } - return cling; - } - - private void dismissCling(final Cling cling, final Runnable postAnimationCb, - final String flag, int duration, boolean restoreNavBarVisibilty) { - // To catch cases where siblings of top-level views are made invisible, just check whether - // the cling is directly set to GONE before dismissing it. - if (cling != null && cling.getVisibility() != View.GONE) { - final Runnable cleanUpClingCb = new Runnable() { - public void run() { - cling.cleanup(); - // We should update the shared preferences on a background thread - new Thread("dismissClingThread") { - public void run() { - SharedPreferences.Editor editor = mSharedPrefs.edit(); - editor.putBoolean(flag, true); - editor.commit(); - } - }.start(); - if (postAnimationCb != null) { - postAnimationCb.run(); - } - } - }; - if (duration <= 0) { - cleanUpClingCb.run(); - } else { - cling.hide(duration, cleanUpClingCb); - } - mHideFromAccessibilityHelper.restoreImportantForAccessibility(mDragLayer); - - if (restoreNavBarVisibilty) { - cling.setSystemUiVisibility(cling.getSystemUiVisibility() & - ~View.SYSTEM_UI_FLAG_LOW_PROFILE); - } - } - } - - private void removeCling(int id) { - final View cling = findViewById(id); - if (cling != null) { - final ViewGroup parent = (ViewGroup) cling.getParent(); - parent.post(new Runnable() { - @Override - public void run() { - parent.removeView(cling); - } - }); - mHideFromAccessibilityHelper.restoreImportantForAccessibility(mDragLayer); - } - } - - private boolean skipCustomClingIfNoAccounts() { - Cling cling = (Cling) findViewById(R.id.workspace_cling); - boolean customCling = cling.getDrawIdentifier().equals("workspace_custom"); - if (customCling) { - AccountManager am = AccountManager.get(this); - if (am == null) return false; - Account[] accounts = am.getAccountsByType("com.google"); - return accounts.length == 0; - } - return false; - } - - public void updateCustomContentHintVisibility() { - Cling cling = (Cling) findViewById(R.id.first_run_cling); - String ccHintStr = getFirstRunCustomContentHint(); - - if (mWorkspace.hasCustomContent()) { - // Show the custom content hint if ccHintStr is not empty - if (cling != null) { - setCustomContentHintVisibility(cling, ccHintStr, true, true); - } - } else { - // Hide the custom content hint - if (cling != null) { - setCustomContentHintVisibility(cling, ccHintStr, false, true); - } - } + /** + * Called when the SearchBar hint should be changed. + * + * @param hint the hint to be displayed in the search bar. + */ + protected void onSearchBarHintChanged(String hint) { + mLauncherClings.updateSearchBarHint(hint); } - private void setCustomContentHintVisibility(Cling cling, String ccHintStr, boolean visible, - boolean animate) { - final TextView ccHint = (TextView) cling.findViewById(R.id.custom_content_hint); - if (ccHint != null) { - if (visible && !ccHintStr.isEmpty()) { - ccHint.setText(ccHintStr); - ccHint.setVisibility(View.VISIBLE); - if (animate) { - ccHint.setAlpha(0f); - ccHint.animate().alpha(1f) - .setDuration(SHOW_CLING_DURATION) - .start(); - } else { - ccHint.setAlpha(1f); - } + protected boolean isLauncherPreinstalled() { + PackageManager pm = getPackageManager(); + try { + ApplicationInfo ai = pm.getApplicationInfo(getComponentName().getPackageName(), 0); + if ((ai.flags & ApplicationInfo.FLAG_SYSTEM) != 0) { + return true; } else { - if (animate) { - ccHint.animate().alpha(0f) - .setDuration(SHOW_CLING_DURATION) - .setListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - ccHint.setVisibility(View.GONE); - } - }) - .start(); - } else { - ccHint.setAlpha(0f); - ccHint.setVisibility(View.GONE); - } + return false; } - } - } - - public void showFirstRunCling() { - if (isClingsEnabled() && - !mSharedPrefs.getBoolean(Cling.FIRST_RUN_CLING_DISMISSED_KEY, false) && - !skipCustomClingIfNoAccounts() ) { - // If we're not using the default workspace layout, replace workspace cling - // with a custom workspace cling (usually specified in an overlay) - // For now, only do this on tablets - if (!DISABLE_CUSTOM_CLINGS) { - if (mSharedPrefs.getInt(LauncherProvider.DEFAULT_WORKSPACE_RESOURCE_ID, 0) != 0 && - getResources().getBoolean(R.bool.config_useCustomClings)) { - // Use a custom cling - View cling = findViewById(R.id.workspace_cling); - ViewGroup clingParent = (ViewGroup) cling.getParent(); - int clingIndex = clingParent.indexOfChild(cling); - clingParent.removeViewAt(clingIndex); - View customCling = mInflater.inflate(R.layout.custom_workspace_cling, clingParent, false); - clingParent.addView(customCling, clingIndex); - customCling.setId(R.id.workspace_cling); - } - } - Cling cling = (Cling) findViewById(R.id.first_run_cling); - if (cling != null) { - String sbHintStr = getFirstRunClingSearchBarHint(); - String ccHintStr = getFirstRunCustomContentHint(); - if (!sbHintStr.isEmpty()) { - TextView sbHint = (TextView) cling.findViewById(R.id.search_bar_hint); - sbHint.setText(sbHintStr); - sbHint.setVisibility(View.VISIBLE); - } - setCustomContentHintVisibility(cling, ccHintStr, true, false); - } - initCling(R.id.first_run_cling, 0, false, true); - } else { - removeCling(R.id.first_run_cling); + } catch (NameNotFoundException e) { + e.printStackTrace(); + return false; } } @@ -4583,83 +4696,79 @@ public class Launcher extends Activity return ""; } - public void showFirstRunWorkspaceCling() { - // Enable the clings only if they have not been dismissed before - if (isClingsEnabled() && - !mSharedPrefs.getBoolean(Cling.WORKSPACE_CLING_DISMISSED_KEY, false)) { - Cling c = initCling(R.id.workspace_cling, 0, false, true); + public void dismissFirstRunCling(View v) { + mLauncherClings.dismissFirstRunCling(v); + } + public void dismissMigrationClingCopyApps(View v) { + mLauncherClings.dismissMigrationClingCopyApps(v); + } + public void dismissMigrationClingUseDefault(View v) { + mLauncherClings.dismissMigrationClingUseDefault(v); + } + public void dismissMigrationWorkspaceCling(View v) { + mLauncherClings.dismissMigrationWorkspaceCling(v); + } + public void dismissWorkspaceCling(View v) { + mLauncherClings.dismissWorkspaceCling(v); + } + public void dismissFolderCling(View v) { + mLauncherClings.dismissFolderCling(v); + } - // Set the focused hotseat app if there is one - c.setFocusedHotseatApp(getFirstRunFocusedHotseatAppDrawableId(), - getFirstRunFocusedHotseatAppRank(), - getFirstRunFocusedHotseatAppComponentName(), - getFirstRunFocusedHotseatAppBubbleTitle(), - getFirstRunFocusedHotseatAppBubbleDescription()); - } else { - removeCling(R.id.workspace_cling); - } + private boolean shouldRunFirstRunActivity() { + return !ActivityManager.isRunningInTestHarness() && + !mSharedPrefs.getBoolean(FIRST_RUN_ACTIVITY_DISPLAYED, false); } - public Cling showFirstRunFoldersCling() { - // Enable the clings only if they have not been dismissed before - if (isClingsEnabled() && - !mSharedPrefs.getBoolean(Cling.FOLDER_CLING_DISMISSED_KEY, false)) { - Cling cling = initCling(R.id.folder_cling, R.id.cling_scrim, - true, true); - return cling; - } else { - removeCling(R.id.folder_cling); - return null; + + public void showFirstRunActivity() { + if (shouldRunFirstRunActivity() && + hasFirstRunActivity()) { + Intent firstRunIntent = getFirstRunActivity(); + if (firstRunIntent != null) { + startActivity(firstRunIntent); + markFirstRunActivityShown(); + } } } - protected SharedPreferences getSharedPrefs() { - return mSharedPrefs; + + private void markFirstRunActivityShown() { + SharedPreferences.Editor editor = mSharedPrefs.edit(); + editor.putBoolean(FIRST_RUN_ACTIVITY_DISPLAYED, true); + editor.apply(); } - public boolean isFolderClingVisible() { - Cling cling = (Cling) findViewById(R.id.folder_cling); - if (cling != null) { - return cling.getVisibility() == View.VISIBLE; - } - return false; + + void showWorkspaceSearchAndHotseat() { + if (mWorkspace != null) mWorkspace.setAlpha(1f); + if (mHotseat != null) mHotseat.setAlpha(1f); + if (mPageIndicators != null) mPageIndicators.setAlpha(1f); + if (mSearchDropTargetBar != null) mSearchDropTargetBar.showSearchBar(false); } - public void dismissFirstRunCling(View v) { - Cling cling = (Cling) findViewById(R.id.first_run_cling); - Runnable cb = new Runnable() { - public void run() { - // Show the workspace cling next - showFirstRunWorkspaceCling(); - } - }; - dismissCling(cling, cb, Cling.FIRST_RUN_CLING_DISMISSED_KEY, - DISMISS_CLING_DURATION, false); - // Fade out the search bar for the workspace cling coming up - mSearchDropTargetBar.hideSearchBar(true); + void hideWorkspaceSearchAndHotseat() { + if (mWorkspace != null) mWorkspace.setAlpha(0f); + if (mHotseat != null) mHotseat.setAlpha(0f); + if (mPageIndicators != null) mPageIndicators.setAlpha(0f); + if (mSearchDropTargetBar != null) mSearchDropTargetBar.hideSearchBar(false); } - public void dismissWorkspaceCling(View v) { - Cling cling = (Cling) findViewById(R.id.workspace_cling); - Runnable cb = null; - if (v == null) { - cb = new Runnable() { - public void run() { - mWorkspace.enterOverviewMode(); - } - }; - } - dismissCling(cling, cb, Cling.WORKSPACE_CLING_DISMISSED_KEY, - DISMISS_CLING_DURATION, true); - // Fade in the search bar - mSearchDropTargetBar.showSearchBar(true); + + public ItemInfo createAppDragInfo(Intent appLaunchIntent) { + ResolveInfo ri = getPackageManager().resolveActivity(appLaunchIntent, 0); + if (ri == null) { + return null; + } + return new AppInfo(getPackageManager(), ri, mIconCache, null); } - public void dismissFolderCling(View v) { - Cling cling = (Cling) findViewById(R.id.folder_cling); - dismissCling(cling, null, Cling.FOLDER_CLING_DISMISSED_KEY, - DISMISS_CLING_DURATION, true); + + public ItemInfo createShortcutDragInfo(Intent shortcutIntent, CharSequence caption, + Bitmap icon) { + return new ShortcutInfo(shortcutIntent, caption, icon); } - public void dismissAllAppsCling(View v) { - Cling cling = (Cling) findViewById(R.id.all_apps_cling); - dismissCling(cling, null, Cling.ALL_APPS_CLING_DISMISSED_KEY, - DISMISS_CLING_DURATION, true); + + public void startDrag(View dragView, ItemInfo dragInfo, DragSource source) { + dragView.setTag(dragInfo); + mWorkspace.onDragStartedWithItem(dragView); + mWorkspace.beginDragShared(dragView, source); } /** @@ -4725,22 +4834,30 @@ public class Launcher extends Activity } public static void addDumpLog(String tag, String log, boolean debugLog) { + addDumpLog(tag, log, null, debugLog); + } + + public static void addDumpLog(String tag, String log, Exception e, boolean debugLog) { if (debugLog) { - Log.d(tag, log); + if (e != null) { + Log.d(tag, log, e); + } else { + Log.d(tag, log); + } } if (DEBUG_DUMP_LOG) { sDateStamp.setTime(System.currentTimeMillis()); synchronized (sDumpLogs) { - sDumpLogs.add(sDateFormat.format(sDateStamp) + ": " + tag + ", " + log); + sDumpLogs.add(sDateFormat.format(sDateStamp) + ": " + tag + ", " + log + + (e == null ? "" : (", Exception: " + e))); } } } public void dumpLogsToLocalData() { if (DEBUG_DUMP_LOG) { - new Thread("DumpLogsToLocalData") { - @Override - public void run() { + new AsyncTask<Void, Void, Void>() { + public Void doInBackground(Void ... args) { boolean success = false; sDateStamp.setTime(sRunStart); String FILENAME = sDateStamp.getMonth() + "-" @@ -4778,10 +4895,53 @@ public class Launcher extends Activity } catch (IOException e) { e.printStackTrace(); } + return null; } - }.start(); + }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void) null); } } + + public AppsCustomizePagedView.SortMode getAppsCustomizeContentSortMode () { + return mAppsCustomizeContent.getSortMode(); + } + + public boolean shouldShowSearchBar() { + return mWorkspace.getShowSearchBar(); + } + + public boolean shouldHideWorkspaceIconLables() { + return mWorkspace.getHideIconLables(); + } + + public String getWorkspaceTransitionEffect() { + TransitionEffect effect = mWorkspace.getTransitionEffect(); + return effect == null ? TransitionEffect.TRANSITION_EFFECT_NONE : effect.getName(); + } + + public String getAppsCustomizeTransitionEffect() { + TransitionEffect effect = mAppsCustomizeContent.getTransitionEffect(); + return effect == null ? TransitionEffect.TRANSITION_EFFECT_NONE : effect.getName(); + } + + public void updateDynamicGrid() { + mSearchDropTargetBar.setupQSB(this); + mSearchDropTargetBar.hideSearchBar(false); + + initializeDynamicGrid(); + + mGrid.layout(this); + mWorkspace.showOutlines(); + + // Synchronized reload + mModel.startLoader(true, mWorkspace.getCurrentPage()); + mWorkspace.updateCustomContentVisibility(); + } + + public boolean isSearchBarEnabled() { + return SettingsProvider.getBoolean(this, + SettingsProvider.SETTINGS_UI_HOMESCREEN_SEARCH, + R.bool.preferences_interface_homescreen_search_default); + } } interface LauncherTransitionable { @@ -4791,3 +4951,8 @@ interface LauncherTransitionable { void onLauncherTransitionStep(Launcher l, float t); void onLauncherTransitionEnd(Launcher l, boolean animated, boolean toWorkspace); } + +interface DebugIntents { + static final String DELETE_DATABASE = "com.android.launcher3.action.DELETE_DATABASE"; + static final String MIGRATE_DATABASE = "com.android.launcher3.action.MIGRATE_DATABASE"; +} |