OSDN Git Service

Taskbar 3.0.3
[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
75     private static final int FULLSCREEN = 0;
76     private static final int LEFT = -1;
77     private static final int RIGHT = 1;
78
79     public static final int HIDDEN = 0;
80     public static final int TOP_APPS = 1;
81
82     public static SharedPreferences getSharedPreferences(Context context) {
83         if(pref == null) pref = context.getSharedPreferences(BuildConfig.APPLICATION_ID + "_preferences", Context.MODE_PRIVATE);
84         return pref;
85     }
86
87     @TargetApi(Build.VERSION_CODES.M)
88     public static void showPermissionDialog(final Context context) {
89         AlertDialog.Builder builder = new AlertDialog.Builder(context);
90         builder.setTitle(R.string.permission_dialog_title)
91                 .setMessage(R.string.permission_dialog_message)
92                 .setPositiveButton(R.string.action_grant_permission, (dialog, which) -> {
93                     try {
94                         context.startActivity(new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
95                                 Uri.parse("package:" + BuildConfig.APPLICATION_ID)));
96                     } catch (ActivityNotFoundException e) {
97                         showErrorDialog(context, "SYSTEM_ALERT_WINDOW");
98                     }
99                 });
100
101         AlertDialog dialog = builder.create();
102         dialog.show();
103         dialog.setCancelable(false);
104     }
105
106     public static void showErrorDialog(final Context context, String appopCmd) {
107         AlertDialog.Builder builder = new AlertDialog.Builder(context);
108         builder.setTitle(R.string.error_dialog_title)
109                 .setMessage(context.getString(R.string.error_dialog_message, BuildConfig.APPLICATION_ID, appopCmd))
110                 .setPositiveButton(R.string.action_ok, null);
111
112         AlertDialog dialog = builder.create();
113         dialog.show();
114     }
115
116     public static void lockDevice(Context context) {
117         ComponentName component = new ComponentName(context, LockDeviceReceiver.class);
118         context.getPackageManager().setComponentEnabledSetting(component, PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
119                 PackageManager.DONT_KILL_APP);
120
121         DevicePolicyManager mDevicePolicyManager = (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
122         if(mDevicePolicyManager.isAdminActive(component))
123             mDevicePolicyManager.lockNow();
124         else {
125             Intent intent = new Intent(context, DummyActivity.class);
126             intent.putExtra("device_admin", true);
127             intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
128             context.startActivity(intent);
129         }
130     }
131
132     public static void showPowerMenu(Context context) {
133         ComponentName component = new ComponentName(context, PowerMenuService.class);
134         context.getPackageManager().setComponentEnabledSetting(component, PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
135                 PackageManager.DONT_KILL_APP);
136
137         if(isAccessibilityServiceEnabled(context))
138             LocalBroadcastManager.getInstance(context).sendBroadcast(new Intent("com.farmerbb.taskbar.SHOW_POWER_MENU"));
139         else {
140             Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
141             intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
142
143             try {
144                 context.startActivity(intent);
145                 showToastLong(context, R.string.enable_accessibility);
146             } catch (ActivityNotFoundException e) {
147                 showToast(context, R.string.lock_device_not_supported);
148             }
149         }
150     }
151
152     private static boolean isAccessibilityServiceEnabled(Context context) {
153         String accessibilityServices = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
154         ComponentName component = new ComponentName(context, PowerMenuService.class);
155
156         return accessibilityServices != null
157                 && (accessibilityServices.contains(component.flattenToString())
158                 || accessibilityServices.contains(component.flattenToShortString()));
159     }
160
161     public static void showToast(Context context, int message) {
162         showToast(context, context.getString(message), Toast.LENGTH_SHORT);
163     }
164
165     public static void showToastLong(Context context, int message) {
166         showToast(context, context.getString(message), Toast.LENGTH_LONG);
167     }
168
169     public static void showToast(Context context, String message, int length) {
170         ToastCompat.makeText(context, message, length).show();
171     }
172
173     public static void startShortcut(Context context, String packageName, String componentName, ShortcutInfo shortcut) {
174         launchApp(context,
175                 packageName,
176                 componentName,
177                 0,
178                 null,
179                 false,
180                 false,
181                 shortcut);
182     }
183
184     public static void launchApp(final Context context,
185                                  final String packageName,
186                                  final String componentName,
187                                  final long userId, final String windowSize,
188                                  final boolean launchedFromTaskbar,
189                                  final boolean openInNewWindow) {
190         launchApp(context,
191                 packageName,
192                 componentName,
193                 userId,
194                 windowSize,
195                 launchedFromTaskbar,
196                 openInNewWindow,
197                 null);
198     }
199
200     private static void launchApp(final Context context,
201                                  final String packageName,
202                                  final String componentName,
203                                  final long userId, final String windowSize,
204                                  final boolean launchedFromTaskbar,
205                                  final boolean openInNewWindow,
206                                  final ShortcutInfo shortcut) {
207         boolean shouldDelay = false;
208
209         SharedPreferences pref = getSharedPreferences(context);
210         boolean openInFullscreen = pref.getBoolean("open_in_fullscreen", true);
211         boolean freeformHackActive = openInNewWindow
212                 ? FreeformHackHelper.getInstance().isInFreeformWorkspace()
213                 : (openInFullscreen
214                     ? FreeformHackHelper.getInstance().isInFreeformWorkspace()
215                     : FreeformHackHelper.getInstance().isFreeformHackActive());
216
217         if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N
218                 && pref.getBoolean("freeform_hack", false)
219                 && !freeformHackActive) {
220             shouldDelay = true;
221
222             new Handler().postDelayed(() -> {
223                 startFreeformHack(context, true, launchedFromTaskbar);
224
225                 new Handler().postDelayed(() -> continueLaunchingApp(context, packageName, componentName, userId,
226                         windowSize, launchedFromTaskbar, openInNewWindow, shortcut), 100);
227             }, launchedFromTaskbar ? 0 : 100);
228         }
229
230         if(!FreeformHackHelper.getInstance().isFreeformHackActive()) {
231             if(!shouldDelay)
232                 continueLaunchingApp(context, packageName, componentName, userId,
233                         windowSize, launchedFromTaskbar, openInNewWindow, shortcut);
234         } else if(FreeformHackHelper.getInstance().isInFreeformWorkspace() || !openInFullscreen)
235             continueLaunchingApp(context, packageName, componentName, userId,
236                     windowSize, launchedFromTaskbar, openInNewWindow, shortcut);
237     }
238
239     @SuppressWarnings("deprecation")
240     @TargetApi(Build.VERSION_CODES.N)
241     public static void startFreeformHack(Context context, boolean checkMultiWindow, boolean launchedFromTaskbar) {
242         Intent freeformHackIntent = new Intent(context, InvisibleActivityFreeform.class);
243         freeformHackIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT);
244
245         if(checkMultiWindow)
246             freeformHackIntent.putExtra("check_multiwindow", true);
247
248         if(launchedFromTaskbar) {
249             SharedPreferences pref = getSharedPreferences(context);
250             if(pref.getBoolean("disable_animations", false))
251                 freeformHackIntent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
252         }
253
254         DisplayManager dm = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
255         Display display = dm.getDisplay(Display.DEFAULT_DISPLAY);
256         try {
257             context.startActivity(freeformHackIntent, ActivityOptions.makeBasic().setLaunchBounds(new Rect(
258                     display.getWidth(),
259                     display.getHeight(),
260                     display.getWidth() + 1,
261                     display.getHeight() + 1
262             )).toBundle());
263         } catch (IllegalArgumentException e) { /* Gracefully fail */ }
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     public static void checkForUpdates(Context context) {
517         String url;
518         try {
519             context.getPackageManager().getPackageInfo("com.android.vending", 0);
520             url = "https://play.google.com/store/apps/details?id=" + BuildConfig.APPLICATION_ID;
521         } catch (PackageManager.NameNotFoundException e) {
522             url = "https://f-droid.org/repository/browse/?fdid=" + BuildConfig.BASE_APPLICATION_ID;
523         }
524
525         Intent intent = new Intent(Intent.ACTION_VIEW);
526         intent.setData(Uri.parse(url));
527         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
528
529         try {
530             context.startActivity(intent);
531         } catch (ActivityNotFoundException e) { /* Gracefully fail */ }
532     }
533
534     public static boolean launcherIsDefault(Context context) {
535         Intent homeIntent = new Intent(Intent.ACTION_MAIN);
536         homeIntent.addCategory(Intent.CATEGORY_HOME);
537         ResolveInfo defaultLauncher = context.getPackageManager().resolveActivity(homeIntent, PackageManager.MATCH_DEFAULT_ONLY);
538
539         return defaultLauncher.activityInfo.packageName.equals(BuildConfig.APPLICATION_ID);
540     }
541
542     public static void setCachedRotation(int cachedRotation) {
543         U.cachedRotation = cachedRotation;
544     }
545
546     public static String getTaskbarPosition(Context context) {
547         SharedPreferences pref = getSharedPreferences(context);
548         String position = pref.getString("position", "bottom_left");
549
550         if(pref.getBoolean("anchor", false)) {
551             WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
552             int rotation = cachedRotation != null ? cachedRotation : windowManager.getDefaultDisplay().getRotation();
553
554             switch(position) {
555                 case "bottom_left":
556                     switch(rotation) {
557                         case Surface.ROTATION_0:
558                             return "bottom_left";
559                         case Surface.ROTATION_90:
560                             return "bottom_vertical_right";
561                         case Surface.ROTATION_180:
562                             return "top_right";
563                         case Surface.ROTATION_270:
564                             return "top_vertical_left";
565                     }
566                     break;
567                 case "bottom_vertical_left":
568                     switch(rotation) {
569                         case Surface.ROTATION_0:
570                             return "bottom_vertical_left";
571                         case Surface.ROTATION_90:
572                             return "bottom_right";
573                         case Surface.ROTATION_180:
574                             return "top_vertical_right";
575                         case Surface.ROTATION_270:
576                             return "top_left";
577                     }
578                     break;
579                 case "bottom_right":
580                     switch(rotation) {
581                         case Surface.ROTATION_0:
582                             return "bottom_right";
583                         case Surface.ROTATION_90:
584                             return "top_vertical_right";
585                         case Surface.ROTATION_180:
586                             return "top_left";
587                         case Surface.ROTATION_270:
588                             return "bottom_vertical_left";
589                     }
590                     break;
591                 case "bottom_vertical_right":
592                     switch(rotation) {
593                         case Surface.ROTATION_0:
594                             return "bottom_vertical_right";
595                         case Surface.ROTATION_90:
596                             return "top_right";
597                         case Surface.ROTATION_180:
598                             return "top_vertical_left";
599                         case Surface.ROTATION_270:
600                             return "bottom_left";
601                     }
602                     break;
603                 case "top_left":
604                     switch(rotation) {
605                         case Surface.ROTATION_0:
606                             return "top_left";
607                         case Surface.ROTATION_90:
608                             return "bottom_vertical_left";
609                         case Surface.ROTATION_180:
610                             return "bottom_right";
611                         case Surface.ROTATION_270:
612                             return "top_vertical_right";
613                     }
614                     break;
615                 case "top_vertical_left":
616                     switch(rotation) {
617                         case Surface.ROTATION_0:
618                             return "top_vertical_left";
619                         case Surface.ROTATION_90:
620                             return "bottom_left";
621                         case Surface.ROTATION_180:
622                             return "bottom_vertical_right";
623                         case Surface.ROTATION_270:
624                             return "top_right";
625                     }
626                     break;
627                 case "top_right":
628                     switch(rotation) {
629                         case Surface.ROTATION_0:
630                             return "top_right";
631                         case Surface.ROTATION_90:
632                             return "top_vertical_left";
633                         case Surface.ROTATION_180:
634                             return "bottom_left";
635                         case Surface.ROTATION_270:
636                             return "bottom_vertical_right";
637                     }
638                     break;
639                 case "top_vertical_right":
640                     switch(rotation) {
641                         case Surface.ROTATION_0:
642                             return "top_vertical_right";
643                         case Surface.ROTATION_90:
644                             return "top_left";
645                         case Surface.ROTATION_180:
646                             return "bottom_vertical_left";
647                         case Surface.ROTATION_270:
648                             return "bottom_right";
649                     }
650                     break;
651             }
652         }
653
654         return position;
655     }
656
657     private static int getMaxNumOfColumns(Context context) {
658         SharedPreferences pref = getSharedPreferences(context);
659         DisplayMetrics metrics = context.getResources().getDisplayMetrics();
660         float baseTaskbarSize = context.getResources().getDimension(pref.getBoolean("dashboard", false) ? R.dimen.base_taskbar_size_dashboard : R.dimen.base_taskbar_size) / metrics.density;
661         int numOfColumns = 0;
662
663         float maxScreenSize = getTaskbarPosition(context).contains("vertical")
664                 ? (metrics.heightPixels - getStatusBarHeight(context)) / metrics.density
665                 : metrics.widthPixels / metrics.density;
666
667         float iconSize = context.getResources().getDimension(R.dimen.icon_size) / metrics.density;
668
669         int userMaxNumOfColumns = Integer.valueOf(pref.getString("max_num_of_recents", "10"));
670
671         while(baseTaskbarSize + iconSize < maxScreenSize
672                 && numOfColumns < userMaxNumOfColumns) {
673             baseTaskbarSize = baseTaskbarSize + iconSize;
674             numOfColumns++;
675         }
676
677         return numOfColumns;
678     }
679
680     public static int getMaxNumOfEntries(Context context) {
681         SharedPreferences pref = getSharedPreferences(context);
682         return pref.getBoolean("disable_scrolling_list", false)
683                 ? getMaxNumOfColumns(context)
684                 : Integer.valueOf(pref.getString("max_num_of_recents", "10"));
685     }
686
687     public static int getStatusBarHeight(Context context) {
688         int statusBarHeight = 0;
689         int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
690         if(resourceId > 0)
691             statusBarHeight = context.getResources().getDimensionPixelSize(resourceId);
692
693         return statusBarHeight;
694     }
695
696     public static void refreshPinnedIcons(Context context) {
697         IconCache.getInstance(context).clearCache();
698
699         PinnedBlockedApps pba = PinnedBlockedApps.getInstance(context);
700         List<AppEntry> pinnedAppsList = new ArrayList<>(pba.getPinnedApps());
701         List<AppEntry> blockedAppsList = new ArrayList<>(pba.getBlockedApps());
702         PackageManager pm = context.getPackageManager();
703
704         pba.clear(context);
705
706         for(AppEntry entry : pinnedAppsList) {
707             UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
708             LauncherApps launcherApps = (LauncherApps) context.getSystemService(Context.LAUNCHER_APPS_SERVICE);
709
710             final List<UserHandle> userHandles = userManager.getUserProfiles();
711             LauncherActivityInfo appInfo = null;
712
713             for(UserHandle handle : userHandles) {
714                 List<LauncherActivityInfo> list = launcherApps.getActivityList(entry.getPackageName(), handle);
715                 if(!list.isEmpty()) {
716                     // Google App workaround
717                     if(!entry.getPackageName().equals("com.google.android.googlequicksearchbox"))
718                         appInfo = list.get(0);
719                     else {
720                         boolean added = false;
721                         for(LauncherActivityInfo info : list) {
722                             if(info.getName().equals("com.google.android.googlequicksearchbox.SearchActivity")) {
723                                 appInfo = info;
724                                 added = true;
725                             }
726                         }
727
728                         if(!added) appInfo = list.get(0);
729                     }
730
731                     break;
732                 }
733             }
734
735             if(appInfo != null) {
736                 AppEntry newEntry = new AppEntry(
737                         entry.getPackageName(),
738                         entry.getComponentName(),
739                         entry.getLabel(),
740                         IconCache.getInstance(context).getIcon(context, pm, appInfo),
741                         true);
742
743                 newEntry.setUserId(entry.getUserId(context));
744                 pba.addPinnedApp(context, newEntry);
745             }
746         }
747
748         for(AppEntry entry : blockedAppsList) {
749             pba.addBlockedApp(context, entry);
750         }
751     }
752
753     public static Intent getShortcutIntent(Context context) {
754         Intent shortcutIntent = new Intent(context, ShortcutActivity.class);
755         shortcutIntent.setAction(Intent.ACTION_MAIN);
756         shortcutIntent.putExtra("is_launching_shortcut", true);
757
758         BitmapDrawable drawable = (BitmapDrawable) context.getDrawable(R.mipmap.ic_freeform_mode);
759
760         Intent intent = new Intent();
761         intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
762         if(drawable != null) intent.putExtra(Intent.EXTRA_SHORTCUT_ICON, drawable.getBitmap());
763         intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, context.getString(R.string.pref_header_freeform));
764
765         return intent;
766     }
767
768     public static Intent getStartStopIntent(Context context) {
769         Intent shortcutIntent = new Intent(context, StartTaskbarActivity.class);
770         shortcutIntent.setAction(Intent.ACTION_MAIN);
771         shortcutIntent.putExtra("is_launching_shortcut", true);
772
773         BitmapDrawable drawable = (BitmapDrawable) context.getDrawable(R.mipmap.ic_launcher);
774
775         Intent intent = new Intent();
776         intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
777         if(drawable != null) intent.putExtra(Intent.EXTRA_SHORTCUT_ICON, drawable.getBitmap());
778         intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, context.getString(R.string.start_taskbar));
779
780         return intent;
781     }
782
783     public static boolean hasFreeformSupport(Context context) {
784         return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N
785                 && (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT)
786                 || Settings.Global.getInt(context.getContentResolver(), "enable_freeform_support", -1) == 1
787                 || Settings.Global.getInt(context.getContentResolver(), "force_resizable_activities", -1) == 1);
788     }
789
790     public static boolean isServiceRunning(Context context, Class<? extends Service> cls) {
791         ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
792         for(ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
793             if(cls.getName().equals(service.service.getClassName()))
794                 return true;
795         }
796
797         return false;
798     }
799
800     public static int getBackgroundTint(Context context) {
801         SharedPreferences pref = getSharedPreferences(context);
802
803         // Import old background tint preference
804         if(pref.contains("show_background")) {
805             SharedPreferences.Editor editor = pref.edit();
806
807             if(!pref.getBoolean("show_background", true))
808                 editor.putInt("background_tint", 0).apply();
809
810             editor.remove("show_background");
811             editor.apply();
812         }
813
814         return pref.getInt("background_tint", context.getResources().getInteger(R.integer.translucent_gray));
815     }
816
817     public static int getAccentColor(Context context) {
818         SharedPreferences pref = getSharedPreferences(context);
819         return pref.getInt("accent_color", context.getResources().getInteger(R.integer.translucent_white));
820     }
821
822     @TargetApi(Build.VERSION_CODES.M)
823     public static boolean canDrawOverlays(Context context) {
824         return Build.VERSION.SDK_INT < Build.VERSION_CODES.M || Settings.canDrawOverlays(context);
825     }
826 }