OSDN Git Service

Make Taskbar full-width
[android-x86/packages-apps-Taskbar.git] / app / src / main / java / com / farmerbb / taskbar / util / U.java
1 /* Copyright 2016 Braden Farmer
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15
16 package com.farmerbb.taskbar.util;
17
18 import android.annotation.TargetApi;
19 import android.app.ActivityOptions;
20 import android.app.AlertDialog;
21 import android.app.admin.DevicePolicyManager;
22 import android.content.ActivityNotFoundException;
23 import android.content.ComponentName;
24 import android.content.Context;
25 import android.content.DialogInterface;
26 import android.content.Intent;
27 import android.content.SharedPreferences;
28 import android.content.pm.ActivityInfo;
29 import android.content.pm.LauncherActivityInfo;
30 import android.content.pm.LauncherApps;
31 import android.content.pm.PackageManager;
32 import android.content.pm.ResolveInfo;
33 import android.content.res.Configuration;
34 import android.graphics.Rect;
35 import android.graphics.drawable.BitmapDrawable;
36 import android.hardware.display.DisplayManager;
37 import android.net.Uri;
38 import android.os.Build;
39 import android.os.Bundle;
40 import android.os.Handler;
41 import android.os.Process;
42 import android.os.UserHandle;
43 import android.os.UserManager;
44 import android.provider.Settings;
45 import android.support.v4.content.LocalBroadcastManager;
46 import android.util.DisplayMetrics;
47 import android.view.Display;
48 import android.view.Surface;
49 import android.view.WindowManager;
50 import android.widget.Toast;
51
52 import com.farmerbb.taskbar.BuildConfig;
53 import com.farmerbb.taskbar.R;
54 import com.farmerbb.taskbar.activity.DummyActivity;
55 import com.farmerbb.taskbar.activity.InvisibleActivityFreeform;
56 import com.farmerbb.taskbar.activity.ShortcutActivity;
57 import com.farmerbb.taskbar.receiver.LockDeviceReceiver;
58
59 import java.util.ArrayList;
60 import java.util.List;
61
62 public class U {
63
64     private U() {}
65
66     private static SharedPreferences pref;
67     private static Toast toast;
68     private static Integer cachedRotation;
69
70     private static final int FULLSCREEN = 0;
71     private static final int LEFT = -1;
72     private static final int RIGHT = 1;
73
74     public static final int HIDDEN = 0;
75     public static final int TOP_APPS = 1;
76
77     public static SharedPreferences getSharedPreferences(Context context) {
78         if(pref == null) pref = context.getSharedPreferences(BuildConfig.APPLICATION_ID + "_preferences", Context.MODE_PRIVATE);
79         return pref;
80     }
81
82     @TargetApi(Build.VERSION_CODES.M)
83     public static void showPermissionDialog(final Context context) {
84         AlertDialog.Builder builder = new AlertDialog.Builder(context);
85         builder.setTitle(R.string.permission_dialog_title)
86                 .setMessage(R.string.permission_dialog_message)
87                 .setPositiveButton(R.string.action_grant_permission, new DialogInterface.OnClickListener() {
88                     @Override
89                     public void onClick(DialogInterface dialog, int which) {
90                         try {
91                             context.startActivity(new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION));
92                         } catch (ActivityNotFoundException e) {
93                             showErrorDialog(context, "SYSTEM_ALERT_WINDOW");
94                         }
95                     }
96                 });
97
98         AlertDialog dialog = builder.create();
99         dialog.show();
100         dialog.setCancelable(false);
101     }
102
103     public static void showErrorDialog(final Context context, String appopCmd) {
104         AlertDialog.Builder builder = new AlertDialog.Builder(context);
105         builder.setTitle(R.string.error_dialog_title)
106                 .setMessage(context.getString(R.string.error_dialog_message, BuildConfig.APPLICATION_ID, appopCmd))
107                 .setPositiveButton(R.string.action_ok, null);
108
109         AlertDialog dialog = builder.create();
110         dialog.show();
111     }
112
113     public static void lockDevice(Context context) {
114         ComponentName component = new ComponentName(BuildConfig.APPLICATION_ID, LockDeviceReceiver.class.getName());
115         context.getPackageManager().setComponentEnabledSetting(component, PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
116                 PackageManager.DONT_KILL_APP);
117
118         DevicePolicyManager mDevicePolicyManager = (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
119         if(mDevicePolicyManager.isAdminActive(component))
120             mDevicePolicyManager.lockNow();
121         else {
122             Intent intent = new Intent(context, DummyActivity.class);
123             intent.putExtra("device_admin", true);
124             intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
125             context.startActivity(intent);
126         }
127     }
128
129     public static void showToast(Context context, int message) {
130         showToast(context, context.getString(message), Toast.LENGTH_SHORT);
131     }
132
133     public static void showToastLong(Context context, int message) {
134         showToast(context, context.getString(message), Toast.LENGTH_LONG);
135     }
136
137     public static void showToast(Context context, String message, int length) {
138         if(toast != null) toast.cancel();
139
140         toast = Toast.makeText(context, message, length);
141         toast.show();
142     }
143
144     public static void launchApp(final Context context,
145                                  final String packageName,
146                                  final String componentName,
147                                  final long userId, final String windowSize,
148                                  final boolean launchedFromTaskbar,
149                                  final boolean padStatusBar,
150                                  final boolean openInNewWindow) {
151         boolean shouldDelay = false;
152
153         SharedPreferences pref = getSharedPreferences(context);
154         boolean openInFullscreen = pref.getBoolean("open_in_fullscreen", true);
155         boolean freeformHackActive = openInNewWindow
156                 ? FreeformHackHelper.getInstance().isInFreeformWorkspace()
157                 : (openInFullscreen
158                     ? FreeformHackHelper.getInstance().isInFreeformWorkspace()
159                     : FreeformHackHelper.getInstance().isFreeformHackActive());
160
161         if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N
162                 && pref.getBoolean("freeform_hack", false)
163                 && !freeformHackActive) {
164             shouldDelay = true;
165
166             new Handler().postDelayed(new Runnable() {
167                 @Override
168                 public void run() {
169                     startFreeformHack(context, launchedFromTaskbar);
170
171                     new Handler().postDelayed(new Runnable() {
172                         @Override
173                         public void run() {
174                             continueLaunchingApp(context, packageName, componentName, userId,
175                                     windowSize, launchedFromTaskbar, padStatusBar, openInNewWindow);
176                         }
177                     }, 100);
178                 }
179             }, launchedFromTaskbar ? 0 : 100);
180         }
181
182         if(!FreeformHackHelper.getInstance().isFreeformHackActive()) {
183             if(!shouldDelay)
184                 continueLaunchingApp(context, packageName, componentName, userId,
185                         windowSize, launchedFromTaskbar, padStatusBar, openInNewWindow);
186         } else if(FreeformHackHelper.getInstance().isInFreeformWorkspace() || !openInFullscreen)
187             continueLaunchingApp(context, packageName, componentName, userId,
188                     windowSize, launchedFromTaskbar, padStatusBar, openInNewWindow);
189     }
190
191     @SuppressWarnings("deprecation")
192     @TargetApi(Build.VERSION_CODES.N)
193     public static void startFreeformHack(Context context, boolean launchedFromTaskbar) {
194         Intent freeformHackIntent = new Intent(context, InvisibleActivityFreeform.class);
195         freeformHackIntent.putExtra("check_multiwindow", true);
196         freeformHackIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT);
197
198         if(launchedFromTaskbar) {
199             SharedPreferences pref = getSharedPreferences(context);
200             if(pref.getBoolean("disable_animations", false))
201                 freeformHackIntent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
202         }
203
204         DisplayManager dm = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
205         Display display = dm.getDisplay(Display.DEFAULT_DISPLAY);
206         try {
207             context.startActivity(freeformHackIntent, ActivityOptions.makeBasic().setLaunchBounds(new Rect(
208                     display.getWidth(),
209                     display.getHeight(),
210                     display.getWidth() + 1,
211                     display.getHeight() + 1
212             )).toBundle());
213         } catch (IllegalArgumentException e) { /* Gracefully fail */ }
214     }
215
216     @TargetApi(Build.VERSION_CODES.N)
217     private static void continueLaunchingApp(Context context,
218                                              String packageName,
219                                              String componentName,
220                                              long userId,
221                                              String windowSize,
222                                              boolean launchedFromTaskbar,
223                                              boolean padStatusBar,
224                                              boolean openInNewWindow) {
225         SharedPreferences pref = getSharedPreferences(context);
226         Intent intent = new Intent();
227         intent.setComponent(ComponentName.unflattenFromString(componentName));
228         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
229         intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
230
231         if(launchedFromTaskbar) {
232             if(pref.getBoolean("disable_animations", false))
233                 intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
234         }
235
236         if(openInNewWindow) {
237             intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
238
239             ActivityInfo activityInfo = intent.resolveActivityInfo(context.getPackageManager(), 0);
240             if(activityInfo != null) {
241                 switch(activityInfo.launchMode) {
242                     case ActivityInfo.LAUNCH_SINGLE_TASK:
243                     case ActivityInfo.LAUNCH_SINGLE_INSTANCE:
244                         intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT);
245                         break;
246                 }
247             }
248         }
249
250         if(windowSize == null) {
251             if(pref.getBoolean("save_window_sizes", true))
252                 windowSize = SavedWindowSizes.getInstance(context).getWindowSize(context, packageName);
253             else
254                 windowSize = pref.getString("window_size", "standard");
255         }
256
257         if(Build.VERSION.SDK_INT < Build.VERSION_CODES.N || !pref.getBoolean("freeform_hack", false)) {
258             UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
259             if(userId == userManager.getSerialNumberForUser(Process.myUserHandle())) {
260                 try {
261                     context.startActivity(intent, null);
262                 } catch (ActivityNotFoundException e) {
263                     launchAndroidForWork(context, intent.getComponent(), null, userId);
264                 } catch (IllegalArgumentException e) { /* Gracefully fail */ }
265             } else
266                 launchAndroidForWork(context, intent.getComponent(), null, userId);
267         } else switch(windowSize) {
268             case "standard":
269                 if(FreeformHackHelper.getInstance().isInFreeformWorkspace()) {
270                     UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
271                     if(userId == userManager.getSerialNumberForUser(Process.myUserHandle())) {
272                         try {
273                             context.startActivity(intent);
274                         } catch (ActivityNotFoundException e) {
275                             launchAndroidForWork(context, intent.getComponent(), null, userId);
276                         } catch (IllegalArgumentException e) { /* Gracefully fail */ }
277                     } else
278                         launchAndroidForWork(context, intent.getComponent(), null, userId);
279                 } else
280                     launchMode1(context, intent, 1, userId);
281                 break;
282             case "large":
283                 launchMode1(context, intent, 2, userId);
284                 break;
285             case "fullscreen":
286                 launchMode2(context, intent, padStatusBar, FULLSCREEN, userId);
287                 break;
288             case "half_left":
289                 launchMode2(context, intent, padStatusBar, LEFT, userId);
290                 break;
291             case "half_right":
292                 launchMode2(context, intent, padStatusBar, RIGHT, userId);
293                 break;
294             case "phone_size":
295                 launchMode3(context, intent, userId);
296                 break;
297         }
298
299         if(pref.getBoolean("hide_taskbar", true) && !FreeformHackHelper.getInstance().isInFreeformWorkspace())
300             LocalBroadcastManager.getInstance(context).sendBroadcast(new Intent("com.farmerbb.taskbar.HIDE_TASKBAR"));
301         else
302             LocalBroadcastManager.getInstance(context).sendBroadcast(new Intent("com.farmerbb.taskbar.HIDE_START_MENU"));
303     }
304     
305     @SuppressWarnings("deprecation")
306     @TargetApi(Build.VERSION_CODES.N)
307     private static void launchMode1(Context context, Intent intent, int factor, long userId) {
308         DisplayManager dm = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
309         Display display = dm.getDisplay(Display.DEFAULT_DISPLAY);
310
311         int width1 = display.getWidth() / (4 * factor);
312         int width2 = display.getWidth() - width1;
313         int height1 = display.getHeight() / (4 * factor);
314         int height2 = display.getHeight() - height1;
315
316         Bundle bundle = ActivityOptions.makeBasic().setLaunchBounds(new Rect(
317                 width1,
318                 height1,
319                 width2,
320                 height2
321         )).toBundle();
322
323         UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
324         if(userId == userManager.getSerialNumberForUser(Process.myUserHandle())) {
325             try {
326                 context.startActivity(intent, bundle);
327             } catch (ActivityNotFoundException e) {
328                 launchAndroidForWork(context, intent.getComponent(), bundle, userId);
329             } catch (IllegalArgumentException e) { /* Gracefully fail */ }
330         } else
331             launchAndroidForWork(context, intent.getComponent(), bundle, userId);
332     }
333
334     @SuppressWarnings("deprecation")
335     @TargetApi(Build.VERSION_CODES.N)
336     private static void launchMode2(Context context, Intent intent, boolean padStatusBar, int launchType, long userId) {
337         DisplayManager dm = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
338         Display display = dm.getDisplay(Display.DEFAULT_DISPLAY);
339
340         int statusBarHeight = getStatusBarHeight(context);
341
342         String position = getTaskbarPosition(context);
343         boolean overridePad = position.equals("top_left") || position.equals("top_right");
344
345         boolean isPortrait = context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT;
346         boolean isLandscape = context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE;
347
348         int left = launchType == RIGHT && isLandscape
349                 ? display.getWidth() / 2
350                 : 0;
351
352         int top;
353         if(launchType == RIGHT && isPortrait) {
354             top = (display.getHeight() / 2)
355                     + (!padStatusBar && overridePad ? statusBarHeight / 2 : 0)
356                     + (!padStatusBar && !overridePad ? statusBarHeight / 2 : 0);
357         } else {
358             top = padStatusBar || overridePad ? statusBarHeight : 0;
359         }
360
361         int right = launchType == LEFT && isLandscape
362                 ? display.getWidth() / 2
363                 : display.getWidth();
364
365         int bottom;
366         if(launchType == LEFT && isPortrait) {
367             bottom = display.getHeight() / 2
368                     + (!padStatusBar && overridePad ? statusBarHeight / 2 : 0)
369                     - (!padStatusBar && !overridePad ? statusBarHeight / 2 : 0);
370         } else {
371             bottom = display.getHeight()
372                     + ((!padStatusBar && overridePad) || (!padStatusBar && launchType == RIGHT && isPortrait)
373                     ? statusBarHeight
374                     : 0);
375         }
376
377         int iconSize = context.getResources().getDimensionPixelSize(R.dimen.icon_size);
378
379         if(position.contains("vertical_left")) {
380             if(launchType != RIGHT || isPortrait) left = left + iconSize;
381         } else if(position.contains("vertical_right")) {
382             if(launchType != LEFT || isPortrait) right = right - iconSize;
383         } else if(position.contains("bottom")) {
384             if(isLandscape || (launchType != LEFT && isPortrait))
385                 bottom = bottom - iconSize;
386         } else if(isLandscape || (launchType != RIGHT && isPortrait))
387             top = top + iconSize;
388
389         Bundle bundle = ActivityOptions.makeBasic().setLaunchBounds(new Rect(
390                 left,
391                 top,
392                 right,
393                 bottom
394         )).toBundle();
395
396         UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
397         if(userId == userManager.getSerialNumberForUser(Process.myUserHandle())) {
398             try {
399                 context.startActivity(intent, bundle);
400             } catch (ActivityNotFoundException e) {
401                 launchAndroidForWork(context, intent.getComponent(), bundle, userId);
402             } catch (IllegalArgumentException e) { /* Gracefully fail */ }
403         } else
404             launchAndroidForWork(context, intent.getComponent(), bundle, userId);
405     }
406
407     @SuppressWarnings("deprecation")
408     @TargetApi(Build.VERSION_CODES.N)
409     private static void launchMode3(Context context, Intent intent, long userId) {
410         DisplayManager dm = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
411         Display display = dm.getDisplay(Display.DEFAULT_DISPLAY);
412
413         int width1 = display.getWidth() / 2;
414         int width2 = context.getResources().getDimensionPixelSize(R.dimen.phone_size_width) / 2;
415         int height1 = display.getHeight() / 2;
416         int height2 = context.getResources().getDimensionPixelSize(R.dimen.phone_size_height) / 2;
417
418         Bundle bundle = ActivityOptions.makeBasic().setLaunchBounds(new Rect(
419                 width1 - width2,
420                 height1 - height2,
421                 width1 + width2,
422                 height1 + height2
423         )).toBundle();
424
425         UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
426         if(userId == userManager.getSerialNumberForUser(Process.myUserHandle())) {
427             try {
428                 context.startActivity(intent, bundle);
429             } catch (ActivityNotFoundException e) {
430                 launchAndroidForWork(context, intent.getComponent(), bundle, userId);
431             } catch (IllegalArgumentException e) { /* Gracefully fail */ }
432         } else
433             launchAndroidForWork(context, intent.getComponent(), bundle, userId);
434     }
435
436     private static void launchAndroidForWork(Context context, ComponentName componentName, Bundle bundle, long userId) {
437         UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
438         LauncherApps launcherApps = (LauncherApps) context.getSystemService(Context.LAUNCHER_APPS_SERVICE);
439
440         launcherApps.startMainActivity(componentName, userManager.getUserForSerialNumber(userId), null, bundle);
441     }
442
443     public static void checkForUpdates(Context context) {
444         String url;
445         try {
446             context.getPackageManager().getPackageInfo("com.android.vending", 0);
447             url = "https://play.google.com/store/apps/details?id=" + BuildConfig.APPLICATION_ID;
448         } catch (PackageManager.NameNotFoundException e) {
449             url = "https://f-droid.org/repository/browse/?fdid=" + BuildConfig.BASE_APPLICATION_ID;
450         }
451
452         Intent intent = new Intent(Intent.ACTION_VIEW);
453         intent.setData(Uri.parse(url));
454         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
455
456         try {
457             context.startActivity(intent);
458         } catch (ActivityNotFoundException e) { /* Gracefully fail */ }
459     }
460
461     public static boolean launcherIsDefault(Context context) {
462         Intent homeIntent = new Intent(Intent.ACTION_MAIN);
463         homeIntent.addCategory(Intent.CATEGORY_HOME);
464         ResolveInfo defaultLauncher = context.getPackageManager().resolveActivity(homeIntent, PackageManager.MATCH_DEFAULT_ONLY);
465
466         return defaultLauncher.activityInfo.packageName.equals(BuildConfig.APPLICATION_ID);
467     }
468
469     public static void setCachedRotation(int cachedRotation) {
470         U.cachedRotation = cachedRotation;
471     }
472
473     public static String getTaskbarPosition(Context context) {
474         SharedPreferences pref = getSharedPreferences(context);
475         String position = pref.getString("position", "bottom_left");
476
477         if(pref.getBoolean("anchor", false)) {
478             WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
479             int rotation = cachedRotation != null ? cachedRotation : windowManager.getDefaultDisplay().getRotation();
480
481             switch(position) {
482                 case "bottom_left":
483                     switch(rotation) {
484                         case Surface.ROTATION_0:
485                             return "bottom_left";
486                         case Surface.ROTATION_90:
487                             return "bottom_vertical_right";
488                         case Surface.ROTATION_180:
489                             return "top_right";
490                         case Surface.ROTATION_270:
491                             return "top_vertical_left";
492                     }
493                     break;
494                 case "bottom_vertical_left":
495                     switch(rotation) {
496                         case Surface.ROTATION_0:
497                             return "bottom_vertical_left";
498                         case Surface.ROTATION_90:
499                             return "bottom_right";
500                         case Surface.ROTATION_180:
501                             return "top_vertical_right";
502                         case Surface.ROTATION_270:
503                             return "top_left";
504                     }
505                     break;
506                 case "bottom_right":
507                     switch(rotation) {
508                         case Surface.ROTATION_0:
509                             return "bottom_right";
510                         case Surface.ROTATION_90:
511                             return "top_vertical_right";
512                         case Surface.ROTATION_180:
513                             return "top_left";
514                         case Surface.ROTATION_270:
515                             return "bottom_vertical_left";
516                     }
517                     break;
518                 case "bottom_vertical_right":
519                     switch(rotation) {
520                         case Surface.ROTATION_0:
521                             return "bottom_vertical_right";
522                         case Surface.ROTATION_90:
523                             return "top_right";
524                         case Surface.ROTATION_180:
525                             return "top_vertical_left";
526                         case Surface.ROTATION_270:
527                             return "bottom_left";
528                     }
529                     break;
530                 case "top_left":
531                     switch(rotation) {
532                         case Surface.ROTATION_0:
533                             return "top_left";
534                         case Surface.ROTATION_90:
535                             return "bottom_vertical_left";
536                         case Surface.ROTATION_180:
537                             return "bottom_right";
538                         case Surface.ROTATION_270:
539                             return "top_vertical_right";
540                     }
541                     break;
542                 case "top_vertical_left":
543                     switch(rotation) {
544                         case Surface.ROTATION_0:
545                             return "top_vertical_left";
546                         case Surface.ROTATION_90:
547                             return "bottom_left";
548                         case Surface.ROTATION_180:
549                             return "bottom_vertical_right";
550                         case Surface.ROTATION_270:
551                             return "top_right";
552                     }
553                     break;
554                 case "top_right":
555                     switch(rotation) {
556                         case Surface.ROTATION_0:
557                             return "top_right";
558                         case Surface.ROTATION_90:
559                             return "top_vertical_left";
560                         case Surface.ROTATION_180:
561                             return "bottom_left";
562                         case Surface.ROTATION_270:
563                             return "bottom_vertical_right";
564                     }
565                     break;
566                 case "top_vertical_right":
567                     switch(rotation) {
568                         case Surface.ROTATION_0:
569                             return "top_vertical_right";
570                         case Surface.ROTATION_90:
571                             return "top_left";
572                         case Surface.ROTATION_180:
573                             return "bottom_vertical_left";
574                         case Surface.ROTATION_270:
575                             return "bottom_right";
576                     }
577                     break;
578             }
579         }
580
581         return position;
582     }
583
584     public static int getMaxNumOfColumns(Context context) {
585         // The base Taskbar size without any recent apps added.
586         // Someday this might be automatically calculated, but today is not that day.
587         float baseTaskbarSize = 92;
588         int numOfColumns = 0;
589
590         DisplayMetrics metrics = context.getResources().getDisplayMetrics();
591         float maxScreenSize = getTaskbarPosition(context).contains("vertical")
592                 ? (metrics.heightPixels - getStatusBarHeight(context)) / metrics.density
593                 : metrics.widthPixels / metrics.density;
594
595         float iconSize = context.getResources().getDimension(R.dimen.icon_size) / metrics.density;
596
597         SharedPreferences pref = getSharedPreferences(context);
598         int userMaxNumOfColumns = Integer.valueOf(pref.getString("max_num_of_recents", "10"));
599
600         while(baseTaskbarSize + iconSize < maxScreenSize
601                 && numOfColumns < userMaxNumOfColumns) {
602             baseTaskbarSize = baseTaskbarSize + iconSize;
603             numOfColumns++;
604         }
605
606         return numOfColumns;
607     }
608
609     public static int getMaxNumOfEntries(Context context) {
610         SharedPreferences pref = getSharedPreferences(context);
611         return pref.getBoolean("disable_scrolling_list", false)
612                 ? getMaxNumOfColumns(context)
613                 : Integer.valueOf(pref.getString("max_num_of_recents", "10"));
614     }
615
616     public static int getStatusBarHeight(Context context) {
617         int statusBarHeight = 0;
618         int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
619         if(resourceId > 0)
620             statusBarHeight = context.getResources().getDimensionPixelSize(resourceId);
621
622         return statusBarHeight;
623     }
624
625     public static void refreshPinnedIcons(Context context) {
626         IconCache.getInstance(context).clearCache();
627
628         PinnedBlockedApps pba = PinnedBlockedApps.getInstance(context);
629         List<AppEntry> pinnedAppsList = new ArrayList<>(pba.getPinnedApps());
630         List<AppEntry> blockedAppsList = new ArrayList<>(pba.getBlockedApps());
631         PackageManager pm = context.getPackageManager();
632
633         pba.clear(context);
634
635         for(AppEntry entry : pinnedAppsList) {
636             UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
637             LauncherApps launcherApps = (LauncherApps) context.getSystemService(Context.LAUNCHER_APPS_SERVICE);
638
639             final List<UserHandle> userHandles = userManager.getUserProfiles();
640             LauncherActivityInfo appInfo = null;
641
642             for(UserHandle handle : userHandles) {
643                 List<LauncherActivityInfo> list = launcherApps.getActivityList(entry.getPackageName(), handle);
644                 if(!list.isEmpty()) {
645                     appInfo = list.get(0);
646                     break;
647                 }
648             }
649
650             if(appInfo != null) {
651                 AppEntry newEntry = new AppEntry(
652                         entry.getPackageName(),
653                         entry.getComponentName(),
654                         entry.getLabel(),
655                         IconCache.getInstance(context).getIcon(context, pm, appInfo),
656                         true);
657
658                 newEntry.setUserId(entry.getUserId(context));
659                 pba.addPinnedApp(context, newEntry);
660             }
661         }
662
663         for(AppEntry entry : blockedAppsList) {
664             pba.addBlockedApp(context, entry);
665         }
666     }
667
668     public static Intent getShortcutIntent(Context context) {
669         Intent shortcutIntent = new Intent(context, ShortcutActivity.class);
670         shortcutIntent.setAction(Intent.ACTION_MAIN);
671         shortcutIntent.putExtra("is_launching_shortcut", true);
672
673         BitmapDrawable drawable = (BitmapDrawable) context.getDrawable(R.mipmap.ic_freeform_mode);
674
675         Intent intent = new Intent();
676         intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
677         if(drawable != null) intent.putExtra(Intent.EXTRA_SHORTCUT_ICON, drawable.getBitmap());
678         intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, context.getString(R.string.pref_header_freeform));
679
680         return intent;
681     }
682
683     public static boolean hasFreeformSupport(Context context) {
684         return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N
685                 && (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT)
686                 || Settings.Global.getInt(context.getContentResolver(), "enable_freeform_support", -1) == 1
687                 || Settings.Global.getInt(context.getContentResolver(), "force_resizable_activities", -1) == 1);
688     }
689 }