OSDN Git Service

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