1b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Songpackage com.android.launcher3.widget; 2b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song 3b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Songimport android.appwidget.AppWidgetHostView; 4b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Songimport android.appwidget.AppWidgetManager; 5b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Songimport android.content.Context; 6b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Songimport android.graphics.Rect; 7b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Songimport android.os.Bundle; 8b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Songimport android.os.Handler; 9a0628cc521614835933db74ba5a2536a936629c5Tony Wickhamimport android.util.Log; 10b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Songimport android.view.View; 11b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song 12b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Songimport com.android.launcher3.AppWidgetResizeFrame; 1394b510cc683a6436ae82c6d323cbd8b429561b06Sunny Goyalimport com.android.launcher3.DropTarget; 14b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Songimport com.android.launcher3.Launcher; 15b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Songimport com.android.launcher3.LauncherAppWidgetProviderInfo; 16b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Songimport com.android.launcher3.compat.AppWidgetManagerCompat; 179ccb94b6e4613ee717550416db2b456d9f17702eTony Wickhamimport com.android.launcher3.dragndrop.DragController; 18fedca43d396d6fd7c46fbb2f37dfa7cfe3b31834Vadim Tryshevimport com.android.launcher3.dragndrop.DragLayer; 1994b510cc683a6436ae82c6d323cbd8b429561b06Sunny Goyalimport com.android.launcher3.dragndrop.DragOptions; 20316490e636aad788fcfbfc2e04dd4f0e145bdd00Sunny Goyalimport com.android.launcher3.util.Thunk; 21b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song 22a0628cc521614835933db74ba5a2536a936629c5Tony Wickhampublic class WidgetHostViewLoader implements DragController.DragListener { 23a0628cc521614835933db74ba5a2536a936629c5Tony Wickham private static final String TAG = "WidgetHostViewLoader"; 24a0628cc521614835933db74ba5a2536a936629c5Tony Wickham private static final boolean LOGD = false; 25b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song 26b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song /* Runnables to handle inflation and binding. */ 275b9ebcab3c6c55dcb7575fdbcb77020a5ad274d4Sunny Goyal @Thunk Runnable mInflateWidgetRunnable = null; 28b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song private Runnable mBindWidgetRunnable = null; 29b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song 30b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song // TODO: technically, this class should not have to know the existence of the launcher. 31316490e636aad788fcfbfc2e04dd4f0e145bdd00Sunny Goyal @Thunk Launcher mLauncher; 325b9ebcab3c6c55dcb7575fdbcb77020a5ad274d4Sunny Goyal @Thunk Handler mHandler; 335b9ebcab3c6c55dcb7575fdbcb77020a5ad274d4Sunny Goyal @Thunk final View mView; 345b9ebcab3c6c55dcb7575fdbcb77020a5ad274d4Sunny Goyal @Thunk final PendingAddWidgetInfo mInfo; 355b9ebcab3c6c55dcb7575fdbcb77020a5ad274d4Sunny Goyal 365b9ebcab3c6c55dcb7575fdbcb77020a5ad274d4Sunny Goyal // Widget id generated for binding a widget host view or -1 for invalid id. The id is 375b9ebcab3c6c55dcb7575fdbcb77020a5ad274d4Sunny Goyal // not is use as long as it is stored here and can be deleted safely. Once its used, this value 385b9ebcab3c6c55dcb7575fdbcb77020a5ad274d4Sunny Goyal // to be set back to -1. 395b9ebcab3c6c55dcb7575fdbcb77020a5ad274d4Sunny Goyal @Thunk int mWidgetLoadingId = -1; 40b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song 415b9ebcab3c6c55dcb7575fdbcb77020a5ad274d4Sunny Goyal public WidgetHostViewLoader(Launcher launcher, View view) { 42b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song mLauncher = launcher; 43b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song mHandler = new Handler(); 445b9ebcab3c6c55dcb7575fdbcb77020a5ad274d4Sunny Goyal mView = view; 455b9ebcab3c6c55dcb7575fdbcb77020a5ad274d4Sunny Goyal mInfo = (PendingAddWidgetInfo) view.getTag(); 46b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song } 47b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song 485b9ebcab3c6c55dcb7575fdbcb77020a5ad274d4Sunny Goyal @Override 498a0dc38aebdc7624db3de2cdfecb9d11e2baee04Sunny Goyal public void onDragStart(DropTarget.DragObject dragObject, DragOptions options) { 508a0dc38aebdc7624db3de2cdfecb9d11e2baee04Sunny Goyal preloadWidget(); 518a0dc38aebdc7624db3de2cdfecb9d11e2baee04Sunny Goyal } 52b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song 535b9ebcab3c6c55dcb7575fdbcb77020a5ad274d4Sunny Goyal @Override 545b9ebcab3c6c55dcb7575fdbcb77020a5ad274d4Sunny Goyal public void onDragEnd() { 55a0628cc521614835933db74ba5a2536a936629c5Tony Wickham if (LOGD) { 56a0628cc521614835933db74ba5a2536a936629c5Tony Wickham Log.d(TAG, "Cleaning up in onDragEnd()..."); 57a0628cc521614835933db74ba5a2536a936629c5Tony Wickham } 58a0628cc521614835933db74ba5a2536a936629c5Tony Wickham 595b9ebcab3c6c55dcb7575fdbcb77020a5ad274d4Sunny Goyal // Cleanup up preloading state. 605b9ebcab3c6c55dcb7575fdbcb77020a5ad274d4Sunny Goyal mLauncher.getDragController().removeDragListener(this); 61b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song 625b9ebcab3c6c55dcb7575fdbcb77020a5ad274d4Sunny Goyal mHandler.removeCallbacks(mBindWidgetRunnable); 635b9ebcab3c6c55dcb7575fdbcb77020a5ad274d4Sunny Goyal mHandler.removeCallbacks(mInflateWidgetRunnable); 64b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song 655b9ebcab3c6c55dcb7575fdbcb77020a5ad274d4Sunny Goyal // Cleanup widget id 665b9ebcab3c6c55dcb7575fdbcb77020a5ad274d4Sunny Goyal if (mWidgetLoadingId != -1) { 675b9ebcab3c6c55dcb7575fdbcb77020a5ad274d4Sunny Goyal mLauncher.getAppWidgetHost().deleteAppWidgetId(mWidgetLoadingId); 685b9ebcab3c6c55dcb7575fdbcb77020a5ad274d4Sunny Goyal mWidgetLoadingId = -1; 695b9ebcab3c6c55dcb7575fdbcb77020a5ad274d4Sunny Goyal } 70b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song 715b9ebcab3c6c55dcb7575fdbcb77020a5ad274d4Sunny Goyal // The widget was inflated and added to the DragLayer -- remove it. 725b9ebcab3c6c55dcb7575fdbcb77020a5ad274d4Sunny Goyal if (mInfo.boundWidget != null) { 73a0628cc521614835933db74ba5a2536a936629c5Tony Wickham if (LOGD) { 74a0628cc521614835933db74ba5a2536a936629c5Tony Wickham Log.d(TAG, "...removing widget from drag layer"); 75a0628cc521614835933db74ba5a2536a936629c5Tony Wickham } 765b9ebcab3c6c55dcb7575fdbcb77020a5ad274d4Sunny Goyal mLauncher.getDragLayer().removeView(mInfo.boundWidget); 775b9ebcab3c6c55dcb7575fdbcb77020a5ad274d4Sunny Goyal mLauncher.getAppWidgetHost().deleteAppWidgetId(mInfo.boundWidget.getAppWidgetId()); 785b9ebcab3c6c55dcb7575fdbcb77020a5ad274d4Sunny Goyal mInfo.boundWidget = null; 79b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song } 80b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song } 81b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song 825b9ebcab3c6c55dcb7575fdbcb77020a5ad274d4Sunny Goyal /** 835b9ebcab3c6c55dcb7575fdbcb77020a5ad274d4Sunny Goyal * Start preloading the widget. 845b9ebcab3c6c55dcb7575fdbcb77020a5ad274d4Sunny Goyal */ 858a0dc38aebdc7624db3de2cdfecb9d11e2baee04Sunny Goyal private boolean preloadWidget() { 865b9ebcab3c6c55dcb7575fdbcb77020a5ad274d4Sunny Goyal final LauncherAppWidgetProviderInfo pInfo = mInfo.info; 87b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song 885b9ebcab3c6c55dcb7575fdbcb77020a5ad274d4Sunny Goyal if (pInfo.isCustomWidget) { 895b9ebcab3c6c55dcb7575fdbcb77020a5ad274d4Sunny Goyal return false; 905b9ebcab3c6c55dcb7575fdbcb77020a5ad274d4Sunny Goyal } 915b9ebcab3c6c55dcb7575fdbcb77020a5ad274d4Sunny Goyal final Bundle options = getDefaultOptionsForWidget(mLauncher, mInfo); 92b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song 93b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song // If there is a configuration activity, do not follow thru bound and inflate. 948a0dc38aebdc7624db3de2cdfecb9d11e2baee04Sunny Goyal if (mInfo.getHandler().needsConfigure()) { 955b9ebcab3c6c55dcb7575fdbcb77020a5ad274d4Sunny Goyal mInfo.bindOptions = options; 96b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song return false; 97b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song } 985b9ebcab3c6c55dcb7575fdbcb77020a5ad274d4Sunny Goyal 99b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song mBindWidgetRunnable = new Runnable() { 100b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song @Override 101b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song public void run() { 102b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song mWidgetLoadingId = mLauncher.getAppWidgetHost().allocateAppWidgetId(); 103a0628cc521614835933db74ba5a2536a936629c5Tony Wickham if (LOGD) { 104a0628cc521614835933db74ba5a2536a936629c5Tony Wickham Log.d(TAG, "Binding widget, id: " + mWidgetLoadingId); 105a0628cc521614835933db74ba5a2536a936629c5Tony Wickham } 106b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song if(AppWidgetManagerCompat.getInstance(mLauncher).bindAppWidgetIdIfAllowed( 107b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song mWidgetLoadingId, pInfo, options)) { 1085b9ebcab3c6c55dcb7575fdbcb77020a5ad274d4Sunny Goyal 1095b9ebcab3c6c55dcb7575fdbcb77020a5ad274d4Sunny Goyal // Widget id bound. Inflate the widget. 1105b9ebcab3c6c55dcb7575fdbcb77020a5ad274d4Sunny Goyal mHandler.post(mInflateWidgetRunnable); 111b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song } 112b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song } 113b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song }; 114b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song 115b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song mInflateWidgetRunnable = new Runnable() { 116b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song @Override 117b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song public void run() { 118a0628cc521614835933db74ba5a2536a936629c5Tony Wickham if (LOGD) { 119a0628cc521614835933db74ba5a2536a936629c5Tony Wickham Log.d(TAG, "Inflating widget, id: " + mWidgetLoadingId); 120a0628cc521614835933db74ba5a2536a936629c5Tony Wickham } 1215b9ebcab3c6c55dcb7575fdbcb77020a5ad274d4Sunny Goyal if (mWidgetLoadingId == -1) { 122b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song return; 123b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song } 124b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song AppWidgetHostView hostView = mLauncher.getAppWidgetHost().createView( 125b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song (Context) mLauncher, mWidgetLoadingId, pInfo); 1265b9ebcab3c6c55dcb7575fdbcb77020a5ad274d4Sunny Goyal mInfo.boundWidget = hostView; 1275b9ebcab3c6c55dcb7575fdbcb77020a5ad274d4Sunny Goyal 1285b9ebcab3c6c55dcb7575fdbcb77020a5ad274d4Sunny Goyal // We used up the widget Id in binding the above view. 1295b9ebcab3c6c55dcb7575fdbcb77020a5ad274d4Sunny Goyal mWidgetLoadingId = -1; 130b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song 1315b9ebcab3c6c55dcb7575fdbcb77020a5ad274d4Sunny Goyal hostView.setVisibility(View.INVISIBLE); 132e96798e885e3ac97b6de0a1c598eb09cf62349afJon Miranda int[] unScaledSize = mLauncher.getWorkspace().estimateItemSize(mInfo, false, true); 133b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song // We want the first widget layout to be the correct size. This will be important 134b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song // for width size reporting to the AppWidgetManager. 135b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song DragLayer.LayoutParams lp = new DragLayer.LayoutParams(unScaledSize[0], 136b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song unScaledSize[1]); 137b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song lp.x = lp.y = 0; 138b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song lp.customPosition = true; 139b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song hostView.setLayoutParams(lp); 140a0628cc521614835933db74ba5a2536a936629c5Tony Wickham if (LOGD) { 141a0628cc521614835933db74ba5a2536a936629c5Tony Wickham Log.d(TAG, "Adding host view to drag layer"); 142a0628cc521614835933db74ba5a2536a936629c5Tony Wickham } 143b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song mLauncher.getDragLayer().addView(hostView); 1445b9ebcab3c6c55dcb7575fdbcb77020a5ad274d4Sunny Goyal mView.setTag(mInfo); 145b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song } 146b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song }; 1475b9ebcab3c6c55dcb7575fdbcb77020a5ad274d4Sunny Goyal 148a0628cc521614835933db74ba5a2536a936629c5Tony Wickham if (LOGD) { 149a0628cc521614835933db74ba5a2536a936629c5Tony Wickham Log.d(TAG, "About to bind/inflate widget"); 150a0628cc521614835933db74ba5a2536a936629c5Tony Wickham } 1515b9ebcab3c6c55dcb7575fdbcb77020a5ad274d4Sunny Goyal mHandler.post(mBindWidgetRunnable); 152b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song return true; 153b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song } 154b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song 15516466f1bbb935d56c01b10551ead416feb7fc943Sunny Goyal public static Bundle getDefaultOptionsForWidget(Context context, PendingAddWidgetInfo info) { 156a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal Rect rect = new Rect(); 157a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal AppWidgetResizeFrame.getWidgetSizeRanges(context, info.spanX, info.spanY, rect); 158a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal Rect padding = AppWidgetHostView.getDefaultPaddingForWidget(context, 159a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal info.componentName, null); 160a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal 161a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal float density = context.getResources().getDisplayMetrics().density; 162a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal int xPaddingDips = (int) ((padding.left + padding.right) / density); 163a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal int yPaddingDips = (int) ((padding.top + padding.bottom) / density); 164a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal 165a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal Bundle options = new Bundle(); 166a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal options.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH, 167a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal rect.left - xPaddingDips); 168a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal options.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT, 169a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal rect.top - yPaddingDips); 170a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal options.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH, 171a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal rect.right - xPaddingDips); 172a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal options.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT, 173a52ecb0390c85afb385371bb844bb496c59ddf87Sunny Goyal rect.bottom - yPaddingDips); 174b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song return options; 175b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song } 176b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song} 177