X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=app%2Fsrc%2Fmain%2Fjava%2Fcom%2Ffarmerbb%2Ftaskbar%2Futil%2FU.java;h=b9663a242da27c90c75ac18ae8225469a7777fff;hb=510ef3ad14e929d7de672dd2f232f60c90b44fbc;hp=f0ace82290baafd25338c387af934f5002ff533e;hpb=76ef51f9035b1495a27e8a41fb461fae9dd936b3;p=android-x86%2Fpackages-apps-Taskbar.git diff --git a/app/src/main/java/com/farmerbb/taskbar/util/U.java b/app/src/main/java/com/farmerbb/taskbar/util/U.java index f0ace822..b9663a24 100644 --- a/app/src/main/java/com/farmerbb/taskbar/util/U.java +++ b/app/src/main/java/com/farmerbb/taskbar/util/U.java @@ -15,11 +15,13 @@ package com.farmerbb.taskbar.util; +import android.Manifest; +import android.annotation.SuppressLint; import android.annotation.TargetApi; -import android.app.Activity; import android.app.ActivityManager; import android.app.ActivityOptions; import android.app.AlertDialog; +import android.app.AppOpsManager; import android.app.Service; import android.app.admin.DevicePolicyManager; import android.content.ActivityNotFoundException; @@ -31,9 +33,12 @@ import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.LauncherActivityInfo; import android.content.pm.LauncherApps; +import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.pm.ShortcutInfo; +import android.content.pm.ShortcutManager; +import android.content.pm.Signature; import android.content.res.Configuration; import android.graphics.Color; import android.graphics.Rect; @@ -46,19 +51,22 @@ import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; import android.support.v4.content.LocalBroadcastManager; +import android.support.v7.view.ContextThemeWrapper; import android.util.DisplayMetrics; import android.view.Display; import android.view.Surface; -import android.view.View; import android.view.WindowManager; import android.widget.Toast; import com.farmerbb.taskbar.BuildConfig; import com.farmerbb.taskbar.R; +import com.farmerbb.taskbar.activity.ContextMenuActivity; import com.farmerbb.taskbar.activity.DummyActivity; import com.farmerbb.taskbar.activity.InvisibleActivityFreeform; import com.farmerbb.taskbar.activity.ShortcutActivity; import com.farmerbb.taskbar.activity.StartTaskbarActivity; +import com.farmerbb.taskbar.activity.TouchAbsorberActivity; +import com.farmerbb.taskbar.activity.dark.ContextMenuActivityDark; import com.farmerbb.taskbar.receiver.LockDeviceReceiver; import com.farmerbb.taskbar.service.DashboardService; import com.farmerbb.taskbar.service.NotificationService; @@ -68,13 +76,13 @@ import com.farmerbb.taskbar.service.TaskbarService; import java.lang.reflect.Method; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; public class U { private U() {} - private static SharedPreferences pref; private static Integer cachedRotation; private static final int MAXIMIZED = 0; @@ -88,13 +96,28 @@ public class U { private static final int FULLSCREEN_WORKSPACE_STACK_ID = 1; private static final int FREEFORM_WORKSPACE_STACK_ID = 2; + // From android.app.WindowConfiguration + private static final int WINDOWING_MODE_FULLSCREEN = 1; + private static final int WINDOWING_MODE_FREEFORM = 5; + public static SharedPreferences getSharedPreferences(Context context) { - if(pref == null) pref = context.getSharedPreferences(BuildConfig.APPLICATION_ID + "_preferences", Context.MODE_PRIVATE); - return pref; + return context.getSharedPreferences(BuildConfig.APPLICATION_ID + "_preferences", Context.MODE_PRIVATE); + } + + public static void showPermissionDialog(Context context) { + showPermissionDialog(context, null, null); } @TargetApi(Build.VERSION_CODES.M) - public static AlertDialog showPermissionDialog(final Context context) { + public static AlertDialog showPermissionDialog(Context context, Runnable onError, Runnable onFinish) { + Runnable finalOnFinish = onFinish == null + ? () -> {} + : onFinish; + + Runnable finalOnError = onError == null + ? () -> showErrorDialog(context, "SYSTEM_ALERT_WINDOW", finalOnFinish) + : onError; + AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setTitle(R.string.permission_dialog_title) .setMessage(R.string.permission_dialog_message) @@ -102,8 +125,10 @@ public class U { try { context.startActivity(new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + BuildConfig.APPLICATION_ID))); + + finalOnFinish.run(); } catch (ActivityNotFoundException e) { - showErrorDialog(context, "SYSTEM_ALERT_WINDOW"); + finalOnError.run(); } }); @@ -114,14 +139,25 @@ public class U { return dialog; } - public static void showErrorDialog(final Context context, String appopCmd) { + public static AlertDialog showErrorDialog(Context context, String appopCmd) { + return showErrorDialog(context, appopCmd, null); + } + + private static AlertDialog showErrorDialog(Context context, String appopCmd, Runnable onFinish) { + Runnable finalOnFinish = onFinish == null + ? () -> {} + : onFinish; + AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setTitle(R.string.error_dialog_title) .setMessage(context.getString(R.string.error_dialog_message, BuildConfig.APPLICATION_ID, appopCmd)) - .setPositiveButton(R.string.action_ok, null); + .setPositiveButton(R.string.action_ok, (dialog, which) -> finalOnFinish.run()); AlertDialog dialog = builder.create(); dialog.show(); + dialog.setCancelable(false); + + return dialog; } public static void lockDevice(Context context) { @@ -136,38 +172,76 @@ public class U { launchApp(context, () -> { Intent intent = new Intent(context, DummyActivity.class); intent.putExtra("device_admin", true); - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - context.startActivity(intent, getActivityOptionsBundle(ApplicationType.APPLICATION)); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_NO_ANIMATION); - if(context instanceof Activity) - ((Activity) context).overridePendingTransition(0, 0); + try { + context.startActivity(intent, getActivityOptionsBundle(context, ApplicationType.APPLICATION)); + } catch (IllegalArgumentException | SecurityException e) { /* Gracefully fail */ } }); } } public static void sendAccessibilityAction(Context context, int action) { + sendAccessibilityAction(context, action, null); + } + + public static void sendAccessibilityAction(Context context, int action, Runnable onComplete) { ComponentName component = new ComponentName(context, PowerMenuService.class); context.getPackageManager().setComponentEnabledSetting(component, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP); - if(isAccessibilityServiceEnabled(context)) { + boolean isAccessibilityServiceEnabled = isAccessibilityServiceEnabled(context); + + if(!isAccessibilityServiceEnabled + && hasWriteSecureSettingsPermission(context)) { + String notificationServices = Settings.Secure.getString(context.getContentResolver(), + Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES); + + String powerMenuService = new ComponentName(context, PowerMenuService.class).flattenToString(); + + if(!notificationServices.contains(powerMenuService)) { + try { + Settings.Secure.putString(context.getContentResolver(), + Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, + notificationServices.isEmpty() + ? powerMenuService + : notificationServices + ":" + powerMenuService); + } catch (Exception e) { /* Gracefully fail */ } + } + + new Handler().postDelayed(() -> { + Intent intent = new Intent("com.farmerbb.taskbar.ACCESSIBILITY_ACTION"); + intent.putExtra("action", action); + LocalBroadcastManager.getInstance(context).sendBroadcast(intent); + + try { + Settings.Secure.putString(context.getContentResolver(), + Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, + notificationServices); + } catch (Exception e) { /* Gracefully fail */ } + + if(onComplete != null) onComplete.run(); + }, 100); + } else if(isAccessibilityServiceEnabled) { Intent intent = new Intent("com.farmerbb.taskbar.ACCESSIBILITY_ACTION"); intent.putExtra("action", action); LocalBroadcastManager.getInstance(context).sendBroadcast(intent); + + if(onComplete != null) onComplete.run(); } else { launchApp(context, () -> { Intent intent = new Intent(context, DummyActivity.class); intent.putExtra("accessibility", true); - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - context.startActivity(intent, getActivityOptionsBundle(ApplicationType.APPLICATION)); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_NO_ANIMATION); - if(context instanceof Activity) - ((Activity) context).overridePendingTransition(0, 0); + try { + context.startActivity(intent, getActivityOptionsBundle(context, ApplicationType.APPLICATION)); + } catch (IllegalArgumentException | SecurityException e) { /* Gracefully fail */ } }); } } - private static boolean isAccessibilityServiceEnabled(Context context) { + public static boolean isAccessibilityServiceEnabled(Context context) { String accessibilityServices = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES); ComponentName component = new ComponentName(context, PowerMenuService.class); @@ -176,6 +250,11 @@ public class U { || accessibilityServices.contains(component.flattenToShortString())); } + public static boolean hasWriteSecureSettingsPermission(Context context) { + return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M + && context.checkSelfPermission(Manifest.permission.WRITE_SECURE_SETTINGS) == PackageManager.PERMISSION_GRANTED; + } + public static void showToast(Context context, int message) { showToast(context, context.getString(message), Toast.LENGTH_SHORT); } @@ -226,14 +305,14 @@ public class U { } private static void launchApp(final Context context, - final String packageName, - final String componentName, - final long userId, final String windowSize, - final boolean launchedFromTaskbar, - final boolean openInNewWindow, - final ShortcutInfo shortcut) { + final String packageName, + final String componentName, + final long userId, final String windowSize, + final boolean launchedFromTaskbar, + final boolean openInNewWindow, + final ShortcutInfo shortcut) { launchApp(context, launchedFromTaskbar, () -> continueLaunchingApp(context, packageName, componentName, userId, - windowSize, launchedFromTaskbar, openInNewWindow, shortcut)); + windowSize, openInNewWindow, shortcut)); } public static void launchApp(Context context, Runnable runnable) { @@ -244,39 +323,50 @@ public class U { SharedPreferences pref = getSharedPreferences(context); FreeformHackHelper helper = FreeformHackHelper.getInstance(); - boolean specialLaunch = Build.VERSION.SDK_INT > Build.VERSION_CODES.N_MR1 - && FreeformHackHelper.getInstance().isInFreeformWorkspace() + boolean specialLaunch = hasBrokenSetLaunchBoundsApi() + && helper.isInFreeformWorkspace() && MenuHelper.getInstance().isContextMenuOpen(); - if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N + boolean noAnimation = pref.getBoolean("disable_animations", false); + + if(hasFreeformSupport(context) && pref.getBoolean("freeform_hack", false) && (!helper.isInFreeformWorkspace() || specialLaunch)) { new Handler().postDelayed(() -> { - startFreeformHack(context, true, launchedFromTaskbar); + startFreeformHack(context, true); new Handler().postDelayed(runnable, helper.isFreeformHackActive() ? 0 : 100); }, launchedFromTaskbar ? 0 : 100); } else - runnable.run(); + new Handler().postDelayed(runnable, !launchedFromTaskbar && noAnimation ? 100 : 0); + } + + public static void startFreeformHack(Context context) { + startFreeformHack(context, false); } - @SuppressWarnings("deprecation") @TargetApi(Build.VERSION_CODES.N) - public static void startFreeformHack(Context context, boolean checkMultiWindow, boolean launchedFromTaskbar) { + public static void startFreeformHack(Context context, boolean checkMultiWindow) { Intent freeformHackIntent = new Intent(context, InvisibleActivityFreeform.class); - freeformHackIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT); + freeformHackIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK + | Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT + | Intent.FLAG_ACTIVITY_NO_ANIMATION); if(checkMultiWindow) freeformHackIntent.putExtra("check_multiwindow", true); - if(launchedFromTaskbar) { - SharedPreferences pref = getSharedPreferences(context); - if(pref.getBoolean("disable_animations", false)) - freeformHackIntent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION); - } - if(canDrawOverlays(context)) - launchAppLowerRight(context, freeformHackIntent); + startActivityLowerRight(context, freeformHackIntent); + } + + public static void stopFreeformHack(Context context) { + LocalBroadcastManager.getInstance(context).sendBroadcast(new Intent("com.farmerbb.taskbar.FINISH_FREEFORM_ACTIVITY")); + + if(isOverridingFreeformHack(context)) { + FreeformHackHelper helper = FreeformHackHelper.getInstance(); + helper.setFreeformHackActive(false); + helper.setInFreeformWorkspace(false); + } } @TargetApi(Build.VERSION_CODES.N) @@ -285,7 +375,6 @@ public class U { String componentName, long userId, String windowSize, - boolean launchedFromTaskbar, boolean openInNewWindow, ShortcutInfo shortcut) { SharedPreferences pref = getSharedPreferences(context); @@ -300,10 +389,8 @@ public class U { && Build.VERSION.SDK_INT <= Build.VERSION_CODES.N_MR1) intent.addFlags(Intent.FLAG_ACTIVITY_TASK_ON_HOME); - if(launchedFromTaskbar) { - if(pref.getBoolean("disable_animations", false)) - intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION); - } + if(pref.getBoolean("disable_animations", false)) + intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION); if(openInNewWindow || pref.getBoolean("force_new_window", false)) { intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK); @@ -324,176 +411,107 @@ public class U { if(windowSize == null) windowSize = SavedWindowSizes.getInstance(context).getWindowSize(context, packageName); - if(Build.VERSION.SDK_INT < Build.VERSION_CODES.N - || !pref.getBoolean("freeform_hack", false) - || windowSize.equals("standard")) { - launchStandard(context, intent, userId, shortcut, type); - } else switch(windowSize) { - case "large": - launchMode1(context, intent, userId, shortcut, type); - break; - case "fullscreen": - launchMode2(context, intent, MAXIMIZED, userId, shortcut, type); - break; - case "half_left": - launchMode2(context, intent, LEFT, userId, shortcut, type); - break; - case "half_right": - launchMode2(context, intent, RIGHT, userId, shortcut, type); - break; - case "phone_size": - launchMode3(context, intent, userId, shortcut, type); - break; - } + Bundle bundle = getActivityOptionsBundle(context, type, windowSize); + + prepareToStartActivity(context, () -> { + if(shortcut == null) { + UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE); + if(userId == userManager.getSerialNumberForUser(Process.myUserHandle())) { + try { + context.startActivity(intent, bundle); + } catch (ActivityNotFoundException e) { + launchAndroidForWork(context, intent.getComponent(), bundle, userId); + } catch (IllegalArgumentException | SecurityException e) { /* Gracefully fail */ } + } else + launchAndroidForWork(context, intent.getComponent(), bundle, userId); + } else + launchShortcut(context, shortcut, bundle); + }); if(shouldCollapse(context, true)) LocalBroadcastManager.getInstance(context).sendBroadcast(new Intent("com.farmerbb.taskbar.HIDE_TASKBAR")); else LocalBroadcastManager.getInstance(context).sendBroadcast(new Intent("com.farmerbb.taskbar.HIDE_START_MENU")); } - - private static void launchStandard(Context context, Intent intent, long userId, ShortcutInfo shortcut, ApplicationType type) { - Bundle bundle = Build.VERSION.SDK_INT < Build.VERSION_CODES.N ? null : getActivityOptions(type).toBundle(); - if(shortcut == null) { - UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE); - if(userId == userManager.getSerialNumberForUser(Process.myUserHandle())) { - try { - context.startActivity(intent, bundle); - } catch (ActivityNotFoundException e) { - launchAndroidForWork(context, intent.getComponent(), bundle, userId); - } catch (IllegalArgumentException | SecurityException e) { /* Gracefully fail */ } - } else - launchAndroidForWork(context, intent.getComponent(), bundle, userId); - } else - launchShortcut(context, shortcut, bundle); - } @SuppressWarnings("deprecation") @TargetApi(Build.VERSION_CODES.N) - private static void launchMode1(Context context, Intent intent, long userId, ShortcutInfo shortcut, ApplicationType type) { - DisplayMetrics metrics = getRealDisplayMetrics(context); + private static Bundle launchMode1(Context context, ApplicationType type) { + DisplayInfo display = getDisplayInfo(context); - int width1 = metrics.widthPixels / 8; - int width2 = metrics.widthPixels - width1; - int height1 = metrics.heightPixels / 8; - int height2 = metrics.heightPixels - height1; + int width1 = display.width / 8; + int width2 = display.width - width1; + int height1 = display.height / 8; + int height2 = display.height - height1; - Bundle bundle = getActivityOptions(type).setLaunchBounds(new Rect( + return getActivityOptions(context, type).setLaunchBounds(new Rect( width1, height1, width2, height2 )).toBundle(); - - if(shortcut == null) { - UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE); - if(userId == userManager.getSerialNumberForUser(Process.myUserHandle())) { - try { - context.startActivity(intent, bundle); - } catch (ActivityNotFoundException e) { - launchAndroidForWork(context, intent.getComponent(), bundle, userId); - } catch (IllegalArgumentException | SecurityException e) { /* Gracefully fail */ } - } else - launchAndroidForWork(context, intent.getComponent(), bundle, userId); - } else - launchShortcut(context, shortcut, bundle); } @SuppressWarnings("deprecation") @TargetApi(Build.VERSION_CODES.N) - private static void launchMode2(Context context, Intent intent, int launchType, long userId, ShortcutInfo shortcut, ApplicationType type) { - DisplayMetrics metrics = getRealDisplayMetrics(context); - + private static Bundle launchMode2(Context context, int launchType, ApplicationType type) { + DisplayInfo display = getDisplayInfo(context); + int statusBarHeight = getStatusBarHeight(context); String position = getTaskbarPosition(context); boolean isPortrait = context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT; boolean isLandscape = context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE; - int left = launchType == RIGHT && isLandscape - ? metrics.widthPixels / 2 - : 0; - - int top = launchType == RIGHT && isPortrait - ? metrics.heightPixels / 2 - : statusBarHeight; - - int right = launchType == LEFT && isLandscape - ? metrics.widthPixels / 2 - : metrics.widthPixels; - - int bottom = launchType == LEFT && isPortrait - ? metrics.heightPixels / 2 - : metrics.heightPixels; - - SharedPreferences pref = getSharedPreferences(context); - int iconSize; - - if(isChromeOs(context) && pref.getBoolean("hide_taskbar", true)) - iconSize = 0; + int left = 0; + int top = statusBarHeight; + int right = display.width; + int bottom = display.height; + + int iconSize = isOverridingFreeformHack(context) && !LauncherHelper.getInstance().isOnHomeScreen() + ? 0 + : context.getResources().getDimensionPixelSize(R.dimen.icon_size); + + if(position.contains("vertical_left")) + left = left + iconSize; + else if(position.contains("vertical_right")) + right = right - iconSize; + else if(position.contains("bottom")) + bottom = bottom - iconSize; else - iconSize = context.getResources().getDimensionPixelSize(R.dimen.icon_size); - - if(position.contains("vertical_left")) { - if(launchType != RIGHT || isPortrait) left = left + iconSize; - } else if(position.contains("vertical_right")) { - if(launchType != LEFT || isPortrait) right = right - iconSize; - } else if(position.contains("bottom")) { - if(isLandscape || (launchType != LEFT && isPortrait)) - bottom = bottom - iconSize; - } else if(isLandscape || (launchType != RIGHT && isPortrait)) top = top + iconSize; - Bundle bundle = getActivityOptions(type).setLaunchBounds(new Rect( - left, - top, - right, - bottom - )).toBundle(); - - if(shortcut == null) { - UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE); - if(userId == userManager.getSerialNumberForUser(Process.myUserHandle())) { - try { - context.startActivity(intent, bundle); - } catch (ActivityNotFoundException e) { - launchAndroidForWork(context, intent.getComponent(), bundle, userId); - } catch (IllegalArgumentException | SecurityException e) { /* Gracefully fail */ } - } else - launchAndroidForWork(context, intent.getComponent(), bundle, userId); - } else - launchShortcut(context, shortcut, bundle); + if(launchType == RIGHT && isLandscape) + left = (right / 2) + ((iconSize / 2) * (position.contains("vertical_left") ? 1 : 0)); + else if(launchType == RIGHT && isPortrait) + top = (bottom / 2) + ((iconSize / 2) + * ((position.equals("top_left") || position.equals("top_right")) ? 1 : 0)); + else if(launchType == LEFT && isLandscape) + right = (right / 2) + ((iconSize / 2) * (position.contains("vertical_left") ? 1 : 0)); + else if(launchType == LEFT && isPortrait) + bottom = (bottom / 2) + ((iconSize / 2) + * ((position.equals("top_left") || position.equals("top_right")) ? 1 : 0)); + + return getActivityOptions(context, type) + .setLaunchBounds(new Rect(left, top, right, bottom)).toBundle(); } @SuppressWarnings("deprecation") @TargetApi(Build.VERSION_CODES.N) - private static void launchMode3(Context context, Intent intent, long userId, ShortcutInfo shortcut, ApplicationType type) { - DisplayMetrics metrics = getRealDisplayMetrics(context); + private static Bundle launchMode3(Context context, ApplicationType type) { + DisplayInfo display = getDisplayInfo(context); - int width1 = metrics.widthPixels / 2; + int width1 = display.width / 2; int width2 = context.getResources().getDimensionPixelSize(R.dimen.phone_size_width) / 2; - int height1 = metrics.heightPixels / 2; + int height1 = display.height / 2; int height2 = context.getResources().getDimensionPixelSize(R.dimen.phone_size_height) / 2; - Bundle bundle = getActivityOptions(type).setLaunchBounds(new Rect( + return getActivityOptions(context, type).setLaunchBounds(new Rect( width1 - width2, height1 - height2, width1 + width2, height1 + height2 )).toBundle(); - - if(shortcut == null) { - UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE); - if(userId == userManager.getSerialNumberForUser(Process.myUserHandle())) { - try { - context.startActivity(intent, bundle); - } catch (ActivityNotFoundException e) { - launchAndroidForWork(context, intent.getComponent(), bundle, userId); - } catch (IllegalArgumentException | SecurityException e) { /* Gracefully fail */ } - } else - launchAndroidForWork(context, intent.getComponent(), bundle, userId); - } else - launchShortcut(context, shortcut, bundle); } private static void launchAndroidForWork(Context context, ComponentName componentName, Bundle bundle, long userId) { @@ -516,48 +534,124 @@ public class U { } } - public static void launchAppMaximized(Context context, Intent intent) { - UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE); - long userId = userManager.getSerialNumberForUser(Process.myUserHandle()); + private static void prepareToStartActivity(Context context, Runnable runnable) { + boolean shouldLaunchTouchAbsorber = + !FreeformHackHelper.getInstance().isTouchAbsorberActive() + && isOverridingFreeformHack(context) + && !isChromeOs(context); - launchMode2(context, intent, MAXIMIZED, userId, null, ApplicationType.CONTEXT_MENU); + if(!shouldLaunchTouchAbsorber) { + runnable.run(); + return; + } + + startTouchAbsorberActivity(context); + new Handler().postDelayed(runnable, 100); + } + + public static void startActivityMaximized(Context context, Intent intent) { + Bundle bundle = launchMode2(context, MAXIMIZED, ApplicationType.CONTEXT_MENU); + prepareToStartActivity(context, () -> context.startActivity(intent, bundle)); } - @SuppressWarnings("deprecation") @TargetApi(Build.VERSION_CODES.N) - public static void launchAppLowerRight(Context context, Intent intent) { - DisplayMetrics metrics = getRealDisplayMetrics(context); + public static void startActivityLowerRight(Context context, Intent intent) { + DisplayInfo display = getDisplayInfo(context); try { - context.startActivity(intent, getActivityOptions(ApplicationType.FREEFORM_HACK).setLaunchBounds(new Rect( - metrics.widthPixels, - metrics.heightPixels, - metrics.widthPixels + 1, - metrics.heightPixels + 1 - )).toBundle()); + context.startActivity(intent, + getActivityOptions(context, ApplicationType.FREEFORM_HACK) + .setLaunchBounds(new Rect( + display.width, + display.height, + display.width + 1, + display.height + 1 + )).toBundle()); } catch (IllegalArgumentException | SecurityException e) { /* Gracefully fail */ } } - public static void checkForUpdates(Context context) { - if(!BuildConfig.APPLICATION_ID.equals(BuildConfig.ANDROIDX86_APPLICATION_ID)) { - if(!BuildConfig.DEBUG) { - String url; - try { - context.getPackageManager().getPackageInfo("com.android.vending", 0); - url = "https://play.google.com/store/apps/details?id=" + BuildConfig.APPLICATION_ID; - } catch (PackageManager.NameNotFoundException e) { - url = "https://f-droid.org/repository/browse/?fdid=" + BuildConfig.BASE_APPLICATION_ID; - } + @TargetApi(Build.VERSION_CODES.N) + public static void startTouchAbsorberActivity(Context context) { + String position = getTaskbarPosition(context); + DisplayInfo display = getDisplayInfo(context); - Intent intent = new Intent(Intent.ACTION_VIEW); - intent.setData(Uri.parse(url)); - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + int left = 0; + int top = 0; + int right = display.width; + int bottom = display.height; - try { - context.startActivity(intent); - } catch (ActivityNotFoundException e) { /* Gracefully fail */ } - } else - showToast(context, R.string.debug_build); + int iconSize = context.getResources().getDimensionPixelSize(R.dimen.icon_size); + + if(position.contains("vertical_left")) + right = iconSize; + else if(position.contains("vertical_right")) + left = right - iconSize; + else if(position.contains("bottom")) + top = bottom - iconSize; + else + bottom = iconSize; + + Intent intent = new Intent(context, TouchAbsorberActivity.class); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION); + + try { + context.startActivity(intent, + getActivityOptions(context, ApplicationType.FREEFORM_HACK) + .setLaunchBounds(new Rect(left, top, right, bottom)).toBundle()); + } catch (IllegalArgumentException | SecurityException e) { /* Gracefully fail */ } + } + + public static void startContextMenuActivity(Context context, Bundle args) { + SharedPreferences pref = getSharedPreferences(context); + Intent intent = null; + + switch(pref.getString("theme", "light")) { + case "light": + intent = new Intent(context, ContextMenuActivity.class); + break; + case "dark": + intent = new Intent(context, ContextMenuActivityDark.class); + break; } + + if(intent != null) { + intent.putExtra("args", args); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + } + + if(hasFreeformSupport(context) && FreeformHackHelper.getInstance().isInFreeformWorkspace()) { + DisplayInfo display = getDisplayInfo(context); + + if(intent != null && hasBrokenSetLaunchBoundsApi()) + intent.putExtra("context_menu_fix", true); + + context.startActivity(intent, + getActivityOptions(context, ApplicationType.CONTEXT_MENU) + .setLaunchBounds( + new Rect(0, 0, display.width, display.height) + ).toBundle()); + } else + context.startActivity(intent); + } + + public static void checkForUpdates(Context context) { + String url; + if(isPlayStoreRelease(context)) { + if(BuildConfig.APPLICATION_ID.equals(BuildConfig.BASE_APPLICATION_ID) + && !isPlayStoreInstalled(context)) + url = "https://github.com/farmerbb/Taskbar/releases"; + else + url = "https://play.google.com/store/apps/details?id=" + BuildConfig.APPLICATION_ID; + } else + url = "https://f-droid.org/repository/browse/?fdid=" + BuildConfig.APPLICATION_ID; + + Intent intent = new Intent(Intent.ACTION_VIEW); + intent.setData(Uri.parse(url)); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + + try { + context.startActivity(intent); + } catch (ActivityNotFoundException e) { /* Gracefully fail */ } } public static boolean launcherIsDefault(Context context) { @@ -685,15 +779,16 @@ public class U { private static int getMaxNumOfColumns(Context context) { SharedPreferences pref = getSharedPreferences(context); - DisplayMetrics metrics = getRealDisplayMetrics(context); - float baseTaskbarSize = getBaseTaskbarSizeFloat(context) / metrics.density; + DisplayInfo display = getDisplayInfo(context); + float density = display.density / 160; + float baseTaskbarSize = getBaseTaskbarSizeFloat(context) / density; int numOfColumns = 0; float maxScreenSize = getTaskbarPosition(context).contains("vertical") - ? (metrics.heightPixels - getStatusBarHeight(context)) / metrics.density - : metrics.widthPixels / metrics.density; + ? (display.height - getStatusBarHeight(context)) / density + : display.width / density; - float iconSize = context.getResources().getDimension(R.dimen.icon_size) / metrics.density; + float iconSize = context.getResources().getDimension(R.dimen.icon_size) / density; int userMaxNumOfColumns = Integer.valueOf(pref.getString("max_num_of_recents", "10")); @@ -714,12 +809,20 @@ public class U { } public static int getStatusBarHeight(Context context) { - int statusBarHeight = 0; - int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android"); + return getSystemDimen(context, "status_bar_height"); + } + + private static int getNavbarHeight(Context context) { + return getSystemDimen(context, "navigation_bar_height"); + } + + private static int getSystemDimen(Context context, String id) { + int value = 0; + int resourceId = context.getResources().getIdentifier(id, "dimen", "android"); if(resourceId > 0) - statusBarHeight = context.getResources().getDimensionPixelSize(resourceId); + value = context.getResources().getDimensionPixelSize(resourceId); - return statusBarHeight; + return value; } public static void refreshPinnedIcons(Context context) { @@ -805,23 +908,32 @@ public class U { return intent; } + public static boolean canEnableFreeform() { + return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N; + } + + @TargetApi(Build.VERSION_CODES.N) public static boolean hasFreeformSupport(Context context) { - return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N + return canEnableFreeform() && (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT) - || Settings.Global.getInt(context.getContentResolver(), "enable_freeform_support", -1) == 1 + || Settings.Global.getInt(context.getContentResolver(), "enable_freeform_support", 0) != 0 || (Build.VERSION.SDK_INT <= Build.VERSION_CODES.N_MR1 - && Settings.Global.getInt(context.getContentResolver(), "force_resizable_activities", -1) == 1)); + && Settings.Global.getInt(context.getContentResolver(), "force_resizable_activities", 0) != 0)); } - public static boolean hasPartialFreeformSupport() { - return Build.MANUFACTURER.equalsIgnoreCase("Samsung"); + public static boolean isSamsungDevice() { + return Build.MANUFACTURER.equalsIgnoreCase("Samsung"); + } + + public static boolean isNvidiaDevice() { + return Build.MANUFACTURER.equalsIgnoreCase("NVIDIA"); } public static boolean isServiceRunning(Context context, Class cls) { return isServiceRunning(context, cls.getName()); } - public static boolean isServiceRunning(Context context, String className) { + private static boolean isServiceRunning(Context context, String className) { ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); for(ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) { if(className.equals(service.service.getClassName())) @@ -874,42 +986,84 @@ public class U { } @TargetApi(Build.VERSION_CODES.N) - public static ActivityOptions getActivityOptions(ApplicationType applicationType) { + public static ActivityOptions getActivityOptions(Context context, ApplicationType applicationType) { ActivityOptions options = ActivityOptions.makeBasic(); int stackId = -1; switch(applicationType) { case APPLICATION: if(FreeformHackHelper.getInstance().isFreeformHackActive()) - stackId = FREEFORM_WORKSPACE_STACK_ID; + stackId = getFreeformWindowModeId(); else - stackId = FULLSCREEN_WORKSPACE_STACK_ID; + stackId = getFullscreenWindowModeId(); break; case GAME: - stackId = FULLSCREEN_WORKSPACE_STACK_ID; + stackId = getFullscreenWindowModeId(); break; case FREEFORM_HACK: - stackId = FREEFORM_WORKSPACE_STACK_ID; + stackId = getFreeformWindowModeId(); break; case CONTEXT_MENU: - if(Build.VERSION.SDK_INT > Build.VERSION_CODES.N_MR1) - stackId = FULLSCREEN_WORKSPACE_STACK_ID; + if(hasBrokenSetLaunchBoundsApi() + || (!isChromeOs(context) && getCurrentApiVersion() >= 28.0f)) + stackId = getFullscreenWindowModeId(); break; } try { - Method method = ActivityOptions.class.getMethod("setLaunchStackId", int.class); + Method method = ActivityOptions.class.getMethod(getWindowingModeMethodName(), int.class); method.invoke(options, stackId); } catch (Exception e) { /* Gracefully fail */ } return options; } - public static Bundle getActivityOptionsBundle(ApplicationType applicationType) { - if(Build.VERSION.SDK_INT < Build.VERSION_CODES.N) - return null; + private static int getFullscreenWindowModeId() { + if(getCurrentApiVersion() >= 28.0f) + return WINDOWING_MODE_FULLSCREEN; + else + return FULLSCREEN_WORKSPACE_STACK_ID; + } + + private static int getFreeformWindowModeId() { + if(getCurrentApiVersion() >= 28.0f) + return WINDOWING_MODE_FREEFORM; + else + return FREEFORM_WORKSPACE_STACK_ID; + } + + private static String getWindowingModeMethodName() { + if(getCurrentApiVersion() >= 28.0f) + return "setLaunchWindowingMode"; else - return getActivityOptions(applicationType).toBundle(); + return "setLaunchStackId"; + } + + public static Bundle getActivityOptionsBundle(Context context, ApplicationType type) { + SharedPreferences pref = getSharedPreferences(context); + + return getActivityOptionsBundle(context, type, pref.getString("window_size", "standard")); + } + + private static Bundle getActivityOptionsBundle(Context context, ApplicationType type, String windowSize) { + SharedPreferences pref = getSharedPreferences(context); + if(!canEnableFreeform() || !pref.getBoolean("freeform_hack", false)) + return null; + + switch(windowSize) { + case "large": + return launchMode1(context, type); + case "fullscreen": + return launchMode2(context, MAXIMIZED, type); + case "half_left": + return launchMode2(context, LEFT, type); + case "half_right": + return launchMode2(context, RIGHT, type); + case "phone_size": + return launchMode3(context, type); + } + + return getActivityOptions(context, type).toBundle(); } private static ApplicationType getApplicationType(Context context, String packageName) { @@ -930,7 +1084,26 @@ public class U { return context.getPackageManager().hasSystemFeature("org.chromium.arc"); } - public static boolean hasSupportLibrary(Context context) { + public static boolean isBlissOs(Context context) { + boolean validBlissOsBuildProp = false; + + String blissVersion = DependencyUtils.getSystemProperty("ro.bliss.version"); + if(blissVersion != null && !blissVersion.isEmpty()) + validBlissOsBuildProp = true; + + String buildUser = DependencyUtils.getSystemProperty("ro.build.user"); + if(buildUser != null && buildUser.equals("electrikjesus")) + validBlissOsBuildProp = true; + + return validBlissOsBuildProp + && BuildConfig.APPLICATION_ID.equals(BuildConfig.BASE_APPLICATION_ID) + && isSystemApp(context); + } + + public static boolean isLauncherPermanentlyEnabled(Context context) { + if(BuildConfig.APPLICATION_ID.equals(BuildConfig.ANDROIDX86_APPLICATION_ID)) + return true; + PackageManager pm = context.getPackageManager(); try { pm.getPackageInfo(BuildConfig.SUPPORT_APPLICATION_ID, 0); @@ -1028,24 +1201,60 @@ public class U { public static void initPrefs(Context context) { // On smaller-screened devices, set "Grid" as the default start menu layout SharedPreferences pref = getSharedPreferences(context); - if(context.getApplicationContext().getResources().getConfiguration().smallestScreenWidthDp < 600 + if(context.getApplicationContext().getResources().getConfiguration().smallestScreenWidthDp < 720 && pref.getString("start_menu_layout", "null").equals("null")) { pref.edit().putString("start_menu_layout", "grid").apply(); } // Enable freeform hack automatically on supported devices - if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + if(canEnableFreeform()) { if(!pref.getBoolean("freeform_hack_override", false)) { pref.edit() - .putBoolean("freeform_hack", hasFreeformSupport(context) && !hasPartialFreeformSupport()) + .putBoolean("freeform_hack", hasFreeformSupport(context) && !isSamsungDevice()) .putBoolean("save_window_sizes", false) .putBoolean("freeform_hack_override", true) .apply(); } else if(!hasFreeformSupport(context)) { pref.edit().putBoolean("freeform_hack", false).apply(); - LocalBroadcastManager.getInstance(context).sendBroadcast(new Intent("com.farmerbb.taskbar.FINISH_FREEFORM_ACTIVITY")); + stopFreeformHack(context); } + } else { + boolean freeformWasEnabled = pref.getBoolean("freeform_hack", false) + || pref.getBoolean("show_freeform_disabled_message", false); + + pref.edit() + .putBoolean("freeform_hack", false) + .putBoolean("show_freeform_disabled_message", freeformWasEnabled) + .apply(); + + SavedWindowSizes.getInstance(context).clear(context); + stopFreeformHack(context); + } + + // Customizations for BlissOS + if(isBlissOs(context) && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M + && !pref.getBoolean("bliss_os_prefs", false)) { + SharedPreferences.Editor editor = pref.edit(); + + if(hasFreeformSupport(context)) { + editor.putBoolean("freeform_hack", true); + } + + editor.putString("recents_amount", "running_apps_only"); + editor.putString("refresh_frequency", "0"); + editor.putString("max_num_of_recents", "2147483647"); + editor.putString("sort_order", "true"); + editor.putString("window_size", "phone_size"); + editor.putBoolean("full_length", true); + editor.putBoolean("dashboard", true); + editor.putBoolean("app_drawer_icon", true); + editor.putBoolean("button_back", true); + editor.putBoolean("button_home", true); + editor.putBoolean("button_recents", true); + editor.putBoolean("auto_hide_navbar", true); + editor.putBoolean("bliss_os_prefs", true); + editor.apply(); } // Customizations for Android-x86 devices (non-Bliss) @@ -1057,6 +1266,7 @@ public class U { .putString("refresh_frequency", "0") .putString("max_num_of_recents", "2147483647") .putString("sort_order", "true") + .putString("window_size", "phone_size") .putBoolean("full_length", true) .putBoolean("dashboard", true) .putBoolean("android_x86_prefs", true) @@ -1064,40 +1274,77 @@ public class U { } } - public static DisplayMetrics getRealDisplayMetrics(Context context) { - DisplayMetrics metrics = new DisplayMetrics(); + public static DisplayInfo getDisplayInfo(Context context) { + context = context.getApplicationContext(); + WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); Display disp = wm.getDefaultDisplay(); - SharedPreferences pref = getSharedPreferences(context); - if(isChromeOs(context) && !pref.getBoolean("chrome_os_context_menu_fix", true)) - disp.getRealMetrics(metrics); - else - disp.getMetrics(metrics); + DisplayMetrics metrics = new DisplayMetrics(); + disp.getMetrics(metrics); + + DisplayMetrics realMetrics = new DisplayMetrics(); + disp.getRealMetrics(realMetrics); - return metrics; + DisplayInfo display = new DisplayInfo(metrics.widthPixels, metrics.heightPixels, metrics.densityDpi); + + if(isChromeOs(context)) { + SharedPreferences pref = getSharedPreferences(context); + if(!pref.getBoolean("chrome_os_context_menu_fix", true)) { + display.width = realMetrics.widthPixels; + display.height = realMetrics.heightPixels; + } + + return display; + } + + boolean sameWidth = metrics.widthPixels == realMetrics.widthPixels; + boolean sameHeight = metrics.heightPixels == realMetrics.heightPixels; + + if(sameWidth && !sameHeight) { + display.width = realMetrics.widthPixels; + display.height = realMetrics.heightPixels - getNavbarHeight(context); + } + + if(!sameWidth && sameHeight) { + display.width = realMetrics.widthPixels - getNavbarHeight(context); + display.height = realMetrics.heightPixels; + } + + return display; } - static void pinAppShortcut(Context context) { - Intent intent = getShortcutIntent(context); - intent.setAction("com.android.launcher.action.INSTALL_SHORTCUT"); - intent.putExtra("duplicate", false); + public static void pinAppShortcut(Context context) { + if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + ShortcutManager mShortcutManager = context.getSystemService(ShortcutManager.class); - Intent homeIntent = new Intent(Intent.ACTION_MAIN); - homeIntent.addCategory(Intent.CATEGORY_HOME); - ResolveInfo defaultLauncher = context.getPackageManager().resolveActivity(homeIntent, PackageManager.MATCH_DEFAULT_ONLY); + if(mShortcutManager.isRequestPinShortcutSupported()) { + ShortcutInfo pinShortcutInfo = new ShortcutInfo.Builder(context, "freeform_mode").build(); + + mShortcutManager.requestPinShortcut(pinShortcutInfo, null); + } else + showToastLong(context, R.string.pin_shortcut_not_supported); + } else { + Intent intent = getShortcutIntent(context); + intent.setAction("com.android.launcher.action.INSTALL_SHORTCUT"); + intent.putExtra("duplicate", false); - intent.setPackage(defaultLauncher.activityInfo.packageName); - context.sendBroadcast(intent); + Intent homeIntent = new Intent(Intent.ACTION_MAIN); + homeIntent.addCategory(Intent.CATEGORY_HOME); + ResolveInfo defaultLauncher = context.getPackageManager().resolveActivity(homeIntent, PackageManager.MATCH_DEFAULT_ONLY); - showToast(context, R.string.shortcut_created); + intent.setPackage(defaultLauncher.activityInfo.packageName); + context.sendBroadcast(intent); + + showToast(context, R.string.shortcut_created); + } } public static boolean shouldCollapse(Context context, boolean pendingAppLaunch) { SharedPreferences pref = getSharedPreferences(context); if(pref.getBoolean("hide_taskbar", true)) { if(isOverridingFreeformHack(context)) - return true; + return !LauncherHelper.getInstance().isOnHomeScreen(); else { FreeformHackHelper helper = FreeformHackHelper.getInstance(); if(pendingAppLaunch) @@ -1110,17 +1357,182 @@ public class U { } public static boolean isOverridingFreeformHack(Context context) { - SharedPreferences pref = U.getSharedPreferences(context); - return isChromeOs(context) && pref.getBoolean("chrome_os_context_menu_fix", true); + SharedPreferences pref = getSharedPreferences(context); + return pref.getBoolean("freeform_hack", false) + && ((isChromeOs(context) && pref.getBoolean("chrome_os_context_menu_fix", true)) + || (!isChromeOs(context) && getCurrentApiVersion() >= 28.0f)); + } + + public static boolean isPlayStoreInstalled(Context context) { + try { + context.getPackageManager().getPackageInfo("com.android.vending", 0); + return true; + } catch (PackageManager.NameNotFoundException e) { + return false; + } + } + + private static float getCurrentApiVersion() { + if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) + return Float.valueOf(Build.VERSION.SDK_INT + "." + Build.VERSION.PREVIEW_SDK_INT); + else + return (float) Build.VERSION.SDK_INT; + } + + public static boolean hasBrokenSetLaunchBoundsApi() { + return getCurrentApiVersion() >= 26.0f + && getCurrentApiVersion() < 28.0f + && !isSamsungDevice() + && !isNvidiaDevice(); + } + + public static String getSecondScreenPackageName(Context context) { + return getInstalledPackage(context, Arrays.asList( + "com.farmerbb.secondscreen.free", + "com.farmerbb.secondscreen")); + } + + // Returns the name of an installed package from a list of package names, in order of preference + private static String getInstalledPackage(Context context, List packageNames) { + if(packageNames == null || packageNames.isEmpty()) + return null; + + List packages = packageNames instanceof ArrayList ? packageNames : new ArrayList<>(packageNames); + String packageName = packages.get(0); + + try { + context.getPackageManager().getPackageInfo(packageName, 0); + return packageName; + } catch (PackageManager.NameNotFoundException e) { + packages.remove(0); + return getInstalledPackage(context, packages); + } + } + + public static boolean visualFeedbackEnabled(Context context) { + SharedPreferences pref = getSharedPreferences(context); + return (getCurrentApiVersion() < 26.0f || getCurrentApiVersion() >= 28.0f) + && pref.getBoolean("visual_feedback", true); } - @SuppressWarnings("unchecked") - public static T findViewById(Activity target, int id) { - return (T) target.findViewById(id); + public static void showRecentAppsDialog(Context context) { + showRecentAppsDialog(context, null, null); } - @SuppressWarnings("unchecked") - public static T findViewById(View target, int id) { - return (T) target.findViewById(id); + public static AlertDialog showRecentAppsDialog(Context context, Runnable onError, Runnable onFinish) { + Runnable finalOnFinish = onFinish == null + ? () -> {} + : onFinish; + + Runnable finalOnError = onError == null + ? () -> showErrorDialog(context, "GET_USAGE_STATS", finalOnFinish) + : onError; + + if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !isSystemApp(context)) { + ApplicationInfo applicationInfo = null; + try { + applicationInfo = context.getPackageManager().getApplicationInfo(BuildConfig.APPLICATION_ID, 0); + } catch (PackageManager.NameNotFoundException e) { /* Gracefully fail */ } + + if(applicationInfo != null) { + AppOpsManager appOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); + int mode = appOpsManager.checkOpNoThrow(AppOpsManager.OPSTR_GET_USAGE_STATS, applicationInfo.uid, applicationInfo.packageName); + + if(mode != AppOpsManager.MODE_ALLOWED) { + AlertDialog.Builder builder = new AlertDialog.Builder(context); + builder.setTitle(R.string.pref_header_recent_apps) + .setMessage(R.string.enable_recent_apps) + .setPositiveButton(R.string.action_ok, (dialog, which) -> { + try { + context.startActivity(new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS)); + showToastLong(context, R.string.usage_stats_message); + + finalOnFinish.run(); + } catch (ActivityNotFoundException e) { + finalOnError.run(); + } + }) + .setNegativeButton(R.string.action_cancel, (dialog, which) -> finalOnFinish.run()); + + AlertDialog dialog = builder.create(); + dialog.show(); + dialog.setCancelable(false); + + return dialog; + } + } + } + + finalOnFinish.run(); + return null; + } + + public static Context wrapContext(Context context) { + SharedPreferences pref = getSharedPreferences(context); + + int theme = -1; + switch(pref.getString("theme", "light")) { + case "light": + theme = R.style.AppTheme; + break; + case "dark": + theme = R.style.AppTheme_Dark; + break; + } + + return theme > -1 ? new ContextThemeWrapper(context, theme) : context; + } + + @SuppressLint("PackageManagerGetSignatures") + public static boolean isPlayStoreRelease(Context context) { + Signature playStoreSignature = new Signature(context.getString(R.string.signature)); + try { + PackageManager pm = context.getPackageManager(); + PackageInfo info = pm.getPackageInfo(context.getPackageName(), PackageManager.GET_SIGNATURES); + for(Signature signature : info.signatures) { + if(signature.equals(playStoreSignature)) + return true; + } + } catch (Exception e) { /* Gracefully fail */ } + + return false; + } + + public static boolean isExternalAccessDisabled(Context context) { + SharedPreferences pref = getSharedPreferences(context); + return !pref.getBoolean("tasker_enabled", true); + } + + public static boolean enableFreeformModeShortcut(Context context) { + return canEnableFreeform() + && !U.isOverridingFreeformHack(context) + && !U.isChromeOs(context); + } + + public static void startForegroundService(Context context, Intent intent) { + if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + if(Settings.canDrawOverlays(context)) + context.startForegroundService(intent); + } else + context.startService(intent); + } + + public static int getOverlayType() { + return Build.VERSION.SDK_INT >= Build.VERSION_CODES.O + ? WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY + : WindowManager.LayoutParams.TYPE_PHONE; + } + + public static boolean isDelegatingHomeActivity(Context context) { + Intent homeIntent = new Intent(Intent.ACTION_MAIN); + homeIntent.addCategory(Intent.CATEGORY_HOME); + + final List listOfLaunchers = context.getPackageManager().queryIntentActivities(homeIntent, 0); + for(ResolveInfo launcher : listOfLaunchers) { + if(launcher.activityInfo.packageName.equals(BuildConfig.SUPPORT_APPLICATION_ID)) + return true; + } + + return false; } }