OSDN Git Service

Taskbar 3.0.7
[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.ActivityManager;
20 import android.app.ActivityOptions;
21 import android.app.AlertDialog;
22 import android.app.Service;
23 import android.app.admin.DevicePolicyManager;
24 import android.content.ActivityNotFoundException;
25 import android.content.ComponentName;
26 import android.content.Context;
27 import android.content.Intent;
28 import android.content.SharedPreferences;
29 import android.content.pm.ActivityInfo;
30 import android.content.pm.LauncherActivityInfo;
31 import android.content.pm.LauncherApps;
32 import android.content.pm.PackageManager;
33 import android.content.pm.ResolveInfo;
34 import android.content.pm.ShortcutInfo;
35 import android.content.res.Configuration;
36 import android.graphics.Rect;
37 import android.graphics.drawable.BitmapDrawable;
38 import android.hardware.display.DisplayManager;
39 import android.net.Uri;
40 import android.os.Build;
41 import android.os.Bundle;
42 import android.os.Handler;
43 import android.os.Process;
44 import android.os.UserHandle;
45 import android.os.UserManager;
46 import android.provider.Settings;
47 import android.support.v4.content.LocalBroadcastManager;
48 import android.util.DisplayMetrics;
49 import android.view.Display;
50 import android.view.Surface;
51 import android.view.WindowManager;
52 import android.widget.Toast;
53
54 import com.farmerbb.taskbar.BuildConfig;
55 import com.farmerbb.taskbar.R;
56 import com.farmerbb.taskbar.activity.DummyActivity;
57 import com.farmerbb.taskbar.activity.InvisibleActivityFreeform;
58 import com.farmerbb.taskbar.activity.ShortcutActivity;
59 import com.farmerbb.taskbar.activity.StartTaskbarActivity;
60 import com.farmerbb.taskbar.receiver.LockDeviceReceiver;
61 import com.farmerbb.taskbar.service.PowerMenuService;
62
63 import java.util.ArrayList;
64 import java.util.List;
65
66 import moe.banana.support.ToastCompat;
67
68 public class U {
69
70     private U() {}
71
72     private static SharedPreferences pref;
73     private static Integer cachedRotation;
74     private static ToastCompat toast;
75
76     private static final int FULLSCREEN = 0;
77     private static final int LEFT = -1;
78     private static final int RIGHT = 1;
79
80     public static final int HIDDEN = 0;
81     public static final int TOP_APPS = 1;
82
83     public static SharedPreferences getSharedPreferences(Context context) {
84         if(pref == null) pref = context.getSharedPreferences(BuildConfig.APPLICATION_ID + "_preferences", Context.MODE_PRIVATE);
85         return pref;
86     }
87
88     @TargetApi(Build.VERSION_CODES.M)
89     public static void showPermissionDialog(final Context context) {
90         AlertDialog.Builder builder = new AlertDialog.Builder(context);
91         builder.setTitle(R.string.permission_dialog_title)
92                 .setMessage(R.string.permission_dialog_message)
93                 .setPositiveButton(R.string.action_grant_permission, (dialog, which) -> {
94                     try {
95                         context.startActivity(new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
96                                 Uri.parse("package:" + BuildConfig.APPLICATION_ID)));
97                     } catch (ActivityNotFoundException e) {
98                         showErrorDialog(context, "SYSTEM_ALERT_WINDOW");
99                     }
100                 });
101
102         AlertDialog dialog = builder.create();
103         dialog.show();
104         dialog.setCancelable(false);
105     }
106
107     public static void showErrorDialog(final Context context, String appopCmd) {
108         AlertDialog.Builder builder = new AlertDialog.Builder(context);
109         builder.setTitle(R.string.error_dialog_title)
110                 .setMessage(context.getString(R.string.error_dialog_message, BuildConfig.APPLICATION_ID, appopCmd))
111                 .setPositiveButton(R.string.action_ok, null);
112
113         AlertDialog dialog = builder.create();
114         dialog.show();
115     }
116
117     public static void lockDevice(Context context) {
118         ComponentName component = new ComponentName(context, LockDeviceReceiver.class);
119         context.getPackageManager().setComponentEnabledSetting(component, PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
120                 PackageManager.DONT_KILL_APP);
121
122         DevicePolicyManager mDevicePolicyManager = (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
123         if(mDevicePolicyManager.isAdminActive(component))
124             mDevicePolicyManager.lockNow();
125         else {
126             Intent intent = new Intent(context, DummyActivity.class);
127             intent.putExtra("device_admin", true);
128             intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
129             context.startActivity(intent);
130         }
131     }
132
133     public static void showPowerMenu(Context context) {
134         ComponentName component = new ComponentName(context, PowerMenuService.class);
135         context.getPackageManager().setComponentEnabledSetting(component, PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
136                 PackageManager.DONT_KILL_APP);
137
138         if(isAccessibilityServiceEnabled(context))
139             LocalBroadcastManager.getInstance(context).sendBroadcast(new Intent("com.farmerbb.taskbar.SHOW_POWER_MENU"));
140         else {
141             Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
142             intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
143
144             try {
145                 context.startActivity(intent);
146                 showToastLong(context, R.string.enable_accessibility);
147             } catch (ActivityNotFoundException e) {
148                 showToast(context, R.string.lock_device_not_supported);
149             }
150         }
151     }
152
153     private static boolean isAccessibilityServiceEnabled(Context context) {
154         String accessibilityServices = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
155         ComponentName component = new ComponentName(context, PowerMenuService.class);
156
157         return accessibilityServices != null
158                 && (accessibilityServices.contains(component.flattenToString())
159                 || accessibilityServices.contains(component.flattenToShortString()));
160     }
161
162     public static void showToast(Context context, int message) {
163         showToast(context, context.getString(message), Toast.LENGTH_SHORT);
164     }
165
166     public static void showToastLong(Context context, int message) {
167         showToast(context, context.getString(message), Toast.LENGTH_LONG);
168     }
169
170     public static void showToast(Context context, String message, int length) {
171         cancelToast();
172
173         toast = ToastCompat.makeText(context, message, length);
174         toast.show();
175     }
176
177     public static void cancelToast() {
178         if(toast != null) toast.cancel();
179     }
180
181     public static void startShortcut(Context context, String packageName, String componentName, ShortcutInfo shortcut) {
182         launchApp(context,
183                 packageName,
184                 componentName,
185                 0,
186                 null,
187                 false,
188                 false,
189                 shortcut);
190     }
191
192     public static void launchApp(final Context context,
193                                  final String packageName,
194                                  final String componentName,
195                                  final long userId, final String windowSize,
196                                  final boolean launchedFromTaskbar,
197                                  final boolean openInNewWindow) {
198         launchApp(context,
199                 packageName,
200                 componentName,
201                 userId,
202                 windowSize,
203                 launchedFromTaskbar,
204                 openInNewWindow,
205                 null);
206     }
207
208     private static void launchApp(final Context context,
209                                  final String packageName,
210                                  final String componentName,
211                                  final long userId, final String windowSize,
212                                  final boolean launchedFromTaskbar,
213                                  final boolean openInNewWindow,
214                                  final ShortcutInfo shortcut) {
215         boolean shouldDelay = false;
216
217         SharedPreferences pref = getSharedPreferences(context);
218         FreeformHackHelper helper = FreeformHackHelper.getInstance();
219         boolean openInFullscreen = pref.getBoolean("open_in_fullscreen", true);
220         boolean freeformHackActive = openInNewWindow
221                 ? helper.isInFreeformWorkspace()
222                 : (openInFullscreen
223                     ? helper.isInFreeformWorkspace()
224                     : helper.isFreeformHackActive());
225
226         if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N
227                 && pref.getBoolean("freeform_hack", false)
228                 && !freeformHackActive) {
229             shouldDelay = true;
230
231             new Handler().postDelayed(() -> {
232                 startFreeformHack(context, true, launchedFromTaskbar);
233
234                 new Handler().postDelayed(() -> continueLaunchingApp(context, packageName, componentName, userId,
235                         windowSize, launchedFromTaskbar, openInNewWindow, shortcut), 100);
236             }, launchedFromTaskbar ? 0 : 100);
237         }
238
239         if(!helper.isFreeformHackActive()) {
240             if(!shouldDelay)
241                 continueLaunchingApp(context, packageName, componentName, userId,
242                         windowSize, launchedFromTaskbar, openInNewWindow, shortcut);
243         } else if(helper.isInFreeformWorkspace() || !openInFullscreen)
244             continueLaunchingApp(context, packageName, componentName, userId,
245                     windowSize, launchedFromTaskbar, openInNewWindow, shortcut);
246     }
247
248     @SuppressWarnings("deprecation")
249     @TargetApi(Build.VERSION_CODES.N)
250     public static void startFreeformHack(Context context, boolean checkMultiWindow, boolean launchedFromTaskbar) {
251         Intent freeformHackIntent = new Intent(context, InvisibleActivityFreeform.class);
252         freeformHackIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT);
253
254         if(checkMultiWindow)
255             freeformHackIntent.putExtra("check_multiwindow", true);
256
257         if(launchedFromTaskbar) {
258             SharedPreferences pref = getSharedPreferences(context);
259             if(pref.getBoolean("disable_animations", false))
260                 freeformHackIntent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
261         }
262
263         launchAppLowerRight(context, freeformHackIntent);
264     }
265
266     @TargetApi(Build.VERSION_CODES.N)
267     private static void continueLaunchingApp(Context context,
268                                              String packageName,
269                                              String componentName,
270                                              long userId,
271                                              String windowSize,
272                                              boolean launchedFromTaskbar,
273                                              boolean openInNewWindow,
274                                              ShortcutInfo shortcut) {
275         SharedPreferences pref = getSharedPreferences(context);
276         Intent intent = new Intent();
277         intent.setComponent(ComponentName.unflattenFromString(componentName));
278         intent.setAction(Intent.ACTION_MAIN);
279         intent.addCategory(Intent.CATEGORY_LAUNCHER);
280         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
281         intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
282
283         if(FreeformHackHelper.getInstance().isInFreeformWorkspace())
284             intent.addFlags(Intent.FLAG_ACTIVITY_TASK_ON_HOME);
285
286         if(launchedFromTaskbar) {
287             if(pref.getBoolean("disable_animations", false))
288                 intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
289         }
290
291         if(openInNewWindow || pref.getBoolean("force_new_window", false)) {
292             intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
293
294             ActivityInfo activityInfo = intent.resolveActivityInfo(context.getPackageManager(), 0);
295             if(activityInfo != null) {
296                 switch(activityInfo.launchMode) {
297                     case ActivityInfo.LAUNCH_SINGLE_TASK:
298                     case ActivityInfo.LAUNCH_SINGLE_INSTANCE:
299                         intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT);
300                         break;
301                 }
302             }
303         }
304
305         if(windowSize == null) {
306             if(pref.getBoolean("save_window_sizes", true))
307                 windowSize = SavedWindowSizes.getInstance(context).getWindowSize(context, packageName);
308             else
309                 windowSize = pref.getString("window_size", "standard");
310         }
311
312         if(Build.VERSION.SDK_INT < Build.VERSION_CODES.N || !pref.getBoolean("freeform_hack", false)) {
313             if(shortcut == null) {
314                 UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
315                 if(userId == userManager.getSerialNumberForUser(Process.myUserHandle())) {
316                     try {
317                         context.startActivity(intent, null);
318                     } catch (ActivityNotFoundException e) {
319                         launchAndroidForWork(context, intent.getComponent(), null, userId);
320                     } catch (IllegalArgumentException e) { /* Gracefully fail */ }
321                 } else
322                     launchAndroidForWork(context, intent.getComponent(), null, userId);
323             } else
324                 launchShortcut(context, shortcut, null);
325         } else switch(windowSize) {
326             case "standard":
327                 if(FreeformHackHelper.getInstance().isInFreeformWorkspace()) {
328                     if(shortcut == null) {
329                         UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
330                         if(userId == userManager.getSerialNumberForUser(Process.myUserHandle())) {
331                             try {
332                                 context.startActivity(intent);
333                             } catch (ActivityNotFoundException e) {
334                                 launchAndroidForWork(context, intent.getComponent(), null, userId);
335                             } catch (IllegalArgumentException e) { /* Gracefully fail */ }
336                         } else
337                             launchAndroidForWork(context, intent.getComponent(), null, userId);
338                     } else
339                         launchShortcut(context, shortcut, null);
340                 } else
341                     launchMode1(context, intent, 1, userId, shortcut);
342                 break;
343             case "large":
344                 launchMode1(context, intent, 2, userId, shortcut);
345                 break;
346             case "fullscreen":
347                 launchMode2(context, intent, FULLSCREEN, userId, shortcut);
348                 break;
349             case "half_left":
350                 launchMode2(context, intent, LEFT, userId, shortcut);
351                 break;
352             case "half_right":
353                 launchMode2(context, intent, RIGHT, userId, shortcut);
354                 break;
355             case "phone_size":
356                 launchMode3(context, intent, userId, shortcut);
357                 break;
358         }
359
360         if(pref.getBoolean("hide_taskbar", true) && !FreeformHackHelper.getInstance().isInFreeformWorkspace())
361             LocalBroadcastManager.getInstance(context).sendBroadcast(new Intent("com.farmerbb.taskbar.HIDE_TASKBAR"));
362         else
363             LocalBroadcastManager.getInstance(context).sendBroadcast(new Intent("com.farmerbb.taskbar.HIDE_START_MENU"));
364     }
365     
366     @SuppressWarnings("deprecation")
367     @TargetApi(Build.VERSION_CODES.N)
368     private static void launchMode1(Context context, Intent intent, int factor, long userId, ShortcutInfo shortcut) {
369         DisplayManager dm = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
370         Display display = dm.getDisplay(Display.DEFAULT_DISPLAY);
371
372         int width1 = display.getWidth() / (4 * factor);
373         int width2 = display.getWidth() - width1;
374         int height1 = display.getHeight() / (4 * factor);
375         int height2 = display.getHeight() - height1;
376
377         Bundle bundle = ActivityOptions.makeBasic().setLaunchBounds(new Rect(
378                 width1,
379                 height1,
380                 width2,
381                 height2
382         )).toBundle();
383
384         if(shortcut == null) {
385             UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
386             if(userId == userManager.getSerialNumberForUser(Process.myUserHandle())) {
387                 try {
388                     context.startActivity(intent, bundle);
389                 } catch (ActivityNotFoundException e) {
390                     launchAndroidForWork(context, intent.getComponent(), bundle, userId);
391                 } catch (IllegalArgumentException e) { /* Gracefully fail */ }
392             } else
393                 launchAndroidForWork(context, intent.getComponent(), bundle, userId);
394         } else
395             launchShortcut(context, shortcut, bundle);
396     }
397
398     @SuppressWarnings("deprecation")
399     @TargetApi(Build.VERSION_CODES.N)
400     private static void launchMode2(Context context, Intent intent, int launchType, long userId, ShortcutInfo shortcut) {
401         DisplayManager dm = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
402         Display display = dm.getDisplay(Display.DEFAULT_DISPLAY);
403
404         int statusBarHeight = getStatusBarHeight(context);
405         String position = getTaskbarPosition(context);
406
407         boolean isPortrait = context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT;
408         boolean isLandscape = context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE;
409
410         int left = launchType == RIGHT && isLandscape
411                 ? display.getWidth() / 2
412                 : 0;
413
414         int top = launchType == RIGHT && isPortrait
415                 ? display.getHeight() / 2
416                 : statusBarHeight;
417
418         int right = launchType == LEFT && isLandscape
419                 ? display.getWidth() / 2
420                 : display.getWidth();
421
422         int bottom = launchType == LEFT && isPortrait
423                 ? display.getHeight() / 2
424                 : display.getHeight();
425
426         int iconSize = context.getResources().getDimensionPixelSize(R.dimen.icon_size);
427
428         if(position.contains("vertical_left")) {
429             if(launchType != RIGHT || isPortrait) left = left + iconSize;
430         } else if(position.contains("vertical_right")) {
431             if(launchType != LEFT || isPortrait) right = right - iconSize;
432         } else if(position.contains("bottom")) {
433             if(isLandscape || (launchType != LEFT && isPortrait))
434                 bottom = bottom - iconSize;
435         } else if(isLandscape || (launchType != RIGHT && isPortrait))
436             top = top + iconSize;
437
438         Bundle bundle = ActivityOptions.makeBasic().setLaunchBounds(new Rect(
439                 left,
440                 top,
441                 right,
442                 bottom
443         )).toBundle();
444
445         if(shortcut == null) {
446             UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
447             if(userId == userManager.getSerialNumberForUser(Process.myUserHandle())) {
448                 try {
449                     context.startActivity(intent, bundle);
450                 } catch (ActivityNotFoundException e) {
451                     launchAndroidForWork(context, intent.getComponent(), bundle, userId);
452                 } catch (IllegalArgumentException e) { /* Gracefully fail */ }
453             } else
454                 launchAndroidForWork(context, intent.getComponent(), bundle, userId);
455         } else
456             launchShortcut(context, shortcut, bundle);
457     }
458
459     @SuppressWarnings("deprecation")
460     @TargetApi(Build.VERSION_CODES.N)
461     private static void launchMode3(Context context, Intent intent, long userId, ShortcutInfo shortcut) {
462         DisplayManager dm = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
463         Display display = dm.getDisplay(Display.DEFAULT_DISPLAY);
464
465         int width1 = display.getWidth() / 2;
466         int width2 = context.getResources().getDimensionPixelSize(R.dimen.phone_size_width) / 2;
467         int height1 = display.getHeight() / 2;
468         int height2 = context.getResources().getDimensionPixelSize(R.dimen.phone_size_height) / 2;
469
470         Bundle bundle = ActivityOptions.makeBasic().setLaunchBounds(new Rect(
471                 width1 - width2,
472                 height1 - height2,
473                 width1 + width2,
474                 height1 + height2
475         )).toBundle();
476
477         if(shortcut == null) {
478             UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
479             if(userId == userManager.getSerialNumberForUser(Process.myUserHandle())) {
480                 try {
481                     context.startActivity(intent, bundle);
482                 } catch (ActivityNotFoundException e) {
483                     launchAndroidForWork(context, intent.getComponent(), bundle, userId);
484                 } catch (IllegalArgumentException e) { /* Gracefully fail */ }
485             } else
486                 launchAndroidForWork(context, intent.getComponent(), bundle, userId);
487         } else
488             launchShortcut(context, shortcut, bundle);
489     }
490
491     private static void launchAndroidForWork(Context context, ComponentName componentName, Bundle bundle, long userId) {
492         UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
493         LauncherApps launcherApps = (LauncherApps) context.getSystemService(Context.LAUNCHER_APPS_SERVICE);
494
495         try {
496             launcherApps.startMainActivity(componentName, userManager.getUserForSerialNumber(userId), null, bundle);
497         } catch (ActivityNotFoundException | NullPointerException e) { /* Gracefully fail */ }
498     }
499
500     @TargetApi(Build.VERSION_CODES.N_MR1)
501     private static void launchShortcut(Context context, ShortcutInfo shortcut, Bundle bundle) {
502         LauncherApps launcherApps = (LauncherApps) context.getSystemService(Context.LAUNCHER_APPS_SERVICE);
503
504         try {
505             launcherApps.startShortcut(shortcut, null, bundle);
506         } catch (ActivityNotFoundException | NullPointerException e) { /* Gracefully fail */ }
507     }
508
509     public static void launchAppFullscreen(Context context, Intent intent) {
510         UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
511         long userId = userManager.getSerialNumberForUser(Process.myUserHandle());
512
513         launchMode2(context, intent, FULLSCREEN, userId, null);
514     }
515
516     @SuppressWarnings("deprecation")
517     @TargetApi(Build.VERSION_CODES.N)
518     public static void launchAppLowerRight(Context context, Intent intent) {
519         DisplayManager dm = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
520         Display display = dm.getDisplay(Display.DEFAULT_DISPLAY);
521         try {
522             context.startActivity(intent, ActivityOptions.makeBasic().setLaunchBounds(new Rect(
523                     display.getWidth(),
524                     display.getHeight(),
525                     display.getWidth() + 1,
526                     display.getHeight() + 1
527             )).toBundle());
528         } catch (IllegalArgumentException e) { /* Gracefully fail */ }
529     }
530
531     public static void checkForUpdates(Context context) {
532         if(!BuildConfig.DEBUG) {
533             String url;
534             try {
535                 context.getPackageManager().getPackageInfo("com.android.vending", 0);
536                 url = "https://play.google.com/store/apps/details?id=" + BuildConfig.APPLICATION_ID;
537             } catch (PackageManager.NameNotFoundException e) {
538                 url = "https://f-droid.org/repository/browse/?fdid=" + BuildConfig.BASE_APPLICATION_ID;
539             }
540
541             Intent intent = new Intent(Intent.ACTION_VIEW);
542             intent.setData(Uri.parse(url));
543             intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
544
545             try {
546                 context.startActivity(intent);
547             } catch (ActivityNotFoundException e) { /* Gracefully fail */ }
548         } else
549             showToast(context, R.string.debug_build);
550     }
551
552     public static boolean launcherIsDefault(Context context) {
553         Intent homeIntent = new Intent(Intent.ACTION_MAIN);
554         homeIntent.addCategory(Intent.CATEGORY_HOME);
555         ResolveInfo defaultLauncher = context.getPackageManager().resolveActivity(homeIntent, PackageManager.MATCH_DEFAULT_ONLY);
556
557         return defaultLauncher.activityInfo.packageName.equals(BuildConfig.APPLICATION_ID);
558     }
559
560     public static void setCachedRotation(int cachedRotation) {
561         U.cachedRotation = cachedRotation;
562     }
563
564     public static String getTaskbarPosition(Context context) {
565         SharedPreferences pref = getSharedPreferences(context);
566         String position = pref.getString("position", "bottom_left");
567
568         if(pref.getBoolean("anchor", false)) {
569             WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
570             int rotation = cachedRotation != null ? cachedRotation : windowManager.getDefaultDisplay().getRotation();
571
572             switch(position) {
573                 case "bottom_left":
574                     switch(rotation) {
575                         case Surface.ROTATION_0:
576                             return "bottom_left";
577                         case Surface.ROTATION_90:
578                             return "bottom_vertical_right";
579                         case Surface.ROTATION_180:
580                             return "top_right";
581                         case Surface.ROTATION_270:
582                             return "top_vertical_left";
583                     }
584                     break;
585                 case "bottom_vertical_left":
586                     switch(rotation) {
587                         case Surface.ROTATION_0:
588                             return "bottom_vertical_left";
589                         case Surface.ROTATION_90:
590                             return "bottom_right";
591                         case Surface.ROTATION_180:
592                             return "top_vertical_right";
593                         case Surface.ROTATION_270:
594                             return "top_left";
595                     }
596                     break;
597                 case "bottom_right":
598                     switch(rotation) {
599                         case Surface.ROTATION_0:
600                             return "bottom_right";
601                         case Surface.ROTATION_90:
602                             return "top_vertical_right";
603                         case Surface.ROTATION_180:
604                             return "top_left";
605                         case Surface.ROTATION_270:
606                             return "bottom_vertical_left";
607                     }
608                     break;
609                 case "bottom_vertical_right":
610                     switch(rotation) {
611                         case Surface.ROTATION_0:
612                             return "bottom_vertical_right";
613                         case Surface.ROTATION_90:
614                             return "top_right";
615                         case Surface.ROTATION_180:
616                             return "top_vertical_left";
617                         case Surface.ROTATION_270:
618                             return "bottom_left";
619                     }
620                     break;
621                 case "top_left":
622                     switch(rotation) {
623                         case Surface.ROTATION_0:
624                             return "top_left";
625                         case Surface.ROTATION_90:
626                             return "bottom_vertical_left";
627                         case Surface.ROTATION_180:
628                             return "bottom_right";
629                         case Surface.ROTATION_270:
630                             return "top_vertical_right";
631                     }
632                     break;
633                 case "top_vertical_left":
634                     switch(rotation) {
635                         case Surface.ROTATION_0:
636                             return "top_vertical_left";
637                         case Surface.ROTATION_90:
638                             return "bottom_left";
639                         case Surface.ROTATION_180:
640                             return "bottom_vertical_right";
641                         case Surface.ROTATION_270:
642                             return "top_right";
643                     }
644                     break;
645                 case "top_right":
646                     switch(rotation) {
647                         case Surface.ROTATION_0:
648                             return "top_right";
649                         case Surface.ROTATION_90:
650                             return "top_vertical_left";
651                         case Surface.ROTATION_180:
652                             return "bottom_left";
653                         case Surface.ROTATION_270:
654                             return "bottom_vertical_right";
655                     }
656                     break;
657                 case "top_vertical_right":
658                     switch(rotation) {
659                         case Surface.ROTATION_0:
660                             return "top_vertical_right";
661                         case Surface.ROTATION_90:
662                             return "top_left";
663                         case Surface.ROTATION_180:
664                             return "bottom_vertical_left";
665                         case Surface.ROTATION_270:
666                             return "bottom_right";
667                     }
668                     break;
669             }
670         }
671
672         return position;
673     }
674
675     private static int getMaxNumOfColumns(Context context) {
676         SharedPreferences pref = getSharedPreferences(context);
677         DisplayMetrics metrics = context.getResources().getDisplayMetrics();
678         float baseTaskbarSize = context.getResources().getDimension(pref.getBoolean("dashboard", false) ? R.dimen.base_taskbar_size_dashboard : R.dimen.base_taskbar_size) / metrics.density;
679         int numOfColumns = 0;
680
681         float maxScreenSize = getTaskbarPosition(context).contains("vertical")
682                 ? (metrics.heightPixels - getStatusBarHeight(context)) / metrics.density
683                 : metrics.widthPixels / metrics.density;
684
685         float iconSize = context.getResources().getDimension(R.dimen.icon_size) / metrics.density;
686
687         int userMaxNumOfColumns = Integer.valueOf(pref.getString("max_num_of_recents", "10"));
688
689         while(baseTaskbarSize + iconSize < maxScreenSize
690                 && numOfColumns < userMaxNumOfColumns) {
691             baseTaskbarSize = baseTaskbarSize + iconSize;
692             numOfColumns++;
693         }
694
695         return numOfColumns;
696     }
697
698     public static int getMaxNumOfEntries(Context context) {
699         SharedPreferences pref = getSharedPreferences(context);
700         return pref.getBoolean("disable_scrolling_list", false)
701                 ? getMaxNumOfColumns(context)
702                 : Integer.valueOf(pref.getString("max_num_of_recents", "10"));
703     }
704
705     public static int getStatusBarHeight(Context context) {
706         int statusBarHeight = 0;
707         int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
708         if(resourceId > 0)
709             statusBarHeight = context.getResources().getDimensionPixelSize(resourceId);
710
711         return statusBarHeight;
712     }
713
714     public static void refreshPinnedIcons(Context context) {
715         IconCache.getInstance(context).clearCache();
716
717         PinnedBlockedApps pba = PinnedBlockedApps.getInstance(context);
718         List<AppEntry> pinnedAppsList = new ArrayList<>(pba.getPinnedApps());
719         List<AppEntry> blockedAppsList = new ArrayList<>(pba.getBlockedApps());
720         PackageManager pm = context.getPackageManager();
721
722         pba.clear(context);
723
724         for(AppEntry entry : pinnedAppsList) {
725             UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
726             LauncherApps launcherApps = (LauncherApps) context.getSystemService(Context.LAUNCHER_APPS_SERVICE);
727
728             final List<UserHandle> userHandles = userManager.getUserProfiles();
729             LauncherActivityInfo appInfo = null;
730
731             for(UserHandle handle : userHandles) {
732                 List<LauncherActivityInfo> list = launcherApps.getActivityList(entry.getPackageName(), handle);
733                 if(!list.isEmpty()) {
734                     // Google App workaround
735                     if(!entry.getPackageName().equals("com.google.android.googlequicksearchbox"))
736                         appInfo = list.get(0);
737                     else {
738                         boolean added = false;
739                         for(LauncherActivityInfo info : list) {
740                             if(info.getName().equals("com.google.android.googlequicksearchbox.SearchActivity")) {
741                                 appInfo = info;
742                                 added = true;
743                             }
744                         }
745
746                         if(!added) appInfo = list.get(0);
747                     }
748
749                     break;
750                 }
751             }
752
753             if(appInfo != null) {
754                 AppEntry newEntry = new AppEntry(
755                         entry.getPackageName(),
756                         entry.getComponentName(),
757                         entry.getLabel(),
758                         IconCache.getInstance(context).getIcon(context, pm, appInfo),
759                         true);
760
761                 newEntry.setUserId(entry.getUserId(context));
762                 pba.addPinnedApp(context, newEntry);
763             }
764         }
765
766         for(AppEntry entry : blockedAppsList) {
767             pba.addBlockedApp(context, entry);
768         }
769     }
770
771     public static Intent getShortcutIntent(Context context) {
772         Intent shortcutIntent = new Intent(context, ShortcutActivity.class);
773         shortcutIntent.setAction(Intent.ACTION_MAIN);
774         shortcutIntent.putExtra("is_launching_shortcut", true);
775
776         BitmapDrawable drawable = (BitmapDrawable) context.getDrawable(R.mipmap.ic_freeform_mode);
777
778         Intent intent = new Intent();
779         intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
780         if(drawable != null) intent.putExtra(Intent.EXTRA_SHORTCUT_ICON, drawable.getBitmap());
781         intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, context.getString(R.string.pref_header_freeform));
782
783         return intent;
784     }
785
786     public static Intent getStartStopIntent(Context context) {
787         Intent shortcutIntent = new Intent(context, StartTaskbarActivity.class);
788         shortcutIntent.setAction(Intent.ACTION_MAIN);
789         shortcutIntent.putExtra("is_launching_shortcut", true);
790
791         BitmapDrawable drawable = (BitmapDrawable) context.getDrawable(R.mipmap.ic_launcher);
792
793         Intent intent = new Intent();
794         intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
795         if(drawable != null) intent.putExtra(Intent.EXTRA_SHORTCUT_ICON, drawable.getBitmap());
796         intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, context.getString(R.string.start_taskbar));
797
798         return intent;
799     }
800
801     public static boolean hasFreeformSupport(Context context) {
802         return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N
803                 && (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT)
804                 || Settings.Global.getInt(context.getContentResolver(), "enable_freeform_support", -1) == 1
805                 || Settings.Global.getInt(context.getContentResolver(), "force_resizable_activities", -1) == 1);
806     }
807
808     public static boolean isServiceRunning(Context context, Class<? extends Service> cls) {
809         ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
810         for(ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
811             if(cls.getName().equals(service.service.getClassName()))
812                 return true;
813         }
814
815         return false;
816     }
817
818     public static int getBackgroundTint(Context context) {
819         SharedPreferences pref = getSharedPreferences(context);
820
821         // Import old background tint preference
822         if(pref.contains("show_background")) {
823             SharedPreferences.Editor editor = pref.edit();
824
825             if(!pref.getBoolean("show_background", true))
826                 editor.putInt("background_tint", 0).apply();
827
828             editor.remove("show_background");
829             editor.apply();
830         }
831
832         return pref.getInt("background_tint", context.getResources().getInteger(R.integer.translucent_gray));
833     }
834
835     public static int getAccentColor(Context context) {
836         SharedPreferences pref = getSharedPreferences(context);
837         return pref.getInt("accent_color", context.getResources().getInteger(R.integer.translucent_white));
838     }
839
840     @TargetApi(Build.VERSION_CODES.M)
841     public static boolean canDrawOverlays(Context context) {
842         return Build.VERSION.SDK_INT < Build.VERSION_CODES.M || Settings.canDrawOverlays(context);
843     }
844 }