X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=app%2Fsrc%2Fmain%2Fjava%2Fcom%2Ffarmerbb%2Ftaskbar%2Futil%2FU.java;h=4d922d6ad68b6bbf821cb3375c64d180382e335f;hb=a42891dd10be0b3bcc3ba5db0b00f2f77f1557dd;hp=7cd85d40629a69bbe6047e045ef4ca57a8852249;hpb=90a091ad18c5069d125dc73fafb124bf5b67e852;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 7cd85d40..4d922d6a 100644 --- a/app/src/main/java/com/farmerbb/taskbar/util/U.java +++ b/app/src/main/java/com/farmerbb/taskbar/util/U.java @@ -16,17 +16,21 @@ package com.farmerbb.taskbar.util; import android.Manifest; +import android.accessibilityservice.AccessibilityService; 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.content.ActivityNotFoundException; +import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; import android.content.SharedPreferences; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; @@ -41,6 +45,7 @@ import android.content.pm.Signature; import android.content.res.Configuration; import android.graphics.Color; import android.graphics.Rect; +import android.hardware.display.DisplayManager; import android.net.Uri; import android.os.Build; import android.os.Bundle; @@ -49,8 +54,8 @@ import android.os.Process; 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 androidx.localbroadcastmanager.content.LocalBroadcastManager; +import androidx.appcompat.view.ContextThemeWrapper; import android.util.DisplayMetrics; import android.view.Display; import android.view.Surface; @@ -63,10 +68,10 @@ 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.MainActivity; import com.farmerbb.taskbar.activity.TouchAbsorberActivity; import com.farmerbb.taskbar.activity.dark.ContextMenuActivityDark; +import com.farmerbb.taskbar.content.TaskbarIntent; import com.farmerbb.taskbar.service.DashboardService; import com.farmerbb.taskbar.service.NotificationService; import com.farmerbb.taskbar.service.PowerMenuService; @@ -78,6 +83,7 @@ import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; +import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; @@ -104,6 +110,10 @@ public class U { private static final int WINDOWING_MODE_FULLSCREEN = 1; private static final int WINDOWING_MODE_FREEFORM = 5; + public static final int EXPORT = 123; + public static final int IMPORT = 456; + + @SuppressWarnings("deprecation") public static SharedPreferences getSharedPreferences(Context context) { return context.getSharedPreferences(BuildConfig.APPLICATION_ID + "_preferences", Context.MODE_PRIVATE); } @@ -112,7 +122,6 @@ public class U { showPermissionDialog(context, null, null); } - @TargetApi(Build.VERSION_CODES.M) public static AlertDialog showPermissionDialog(Context context, Runnable onError, Runnable onFinish) { Runnable finalOnFinish = onFinish == null ? () -> {} @@ -122,25 +131,48 @@ public class U { ? () -> 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) - .setPositiveButton(R.string.action_grant_permission, (dialog, which) -> { + AlertDialog.Builder builder; + if(hasAndroidTVSettings(context)) + builder = buildPermissionDialogAndroidTV(context, finalOnError, finalOnFinish); + else + builder = buildPermissionDialogStandard(context, finalOnError, finalOnFinish); + + AlertDialog dialog = builder.create(); + dialog.show(); + dialog.setCancelable(false); + + return dialog; + } + + @TargetApi(Build.VERSION_CODES.M) + private static AlertDialog.Builder buildPermissionDialogStandard(Context context, Runnable onError, Runnable onFinish) { + return new AlertDialog.Builder(context) + .setTitle(R.string.tb_permission_dialog_title) + .setMessage(R.string.tb_permission_dialog_message) + .setPositiveButton(R.string.tb_action_grant_permission, (dialog, which) -> { try { context.startActivity(new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, - Uri.parse("package:" + BuildConfig.APPLICATION_ID))); + Uri.parse("package:" + context.getPackageName()))); - finalOnFinish.run(); + onFinish.run(); } catch (ActivityNotFoundException e) { - finalOnError.run(); + onError.run(); } }); + } - AlertDialog dialog = builder.create(); - dialog.show(); - dialog.setCancelable(false); - - return dialog; + private static AlertDialog.Builder buildPermissionDialogAndroidTV(Context context, Runnable onError, Runnable onFinish) { + return new AlertDialog.Builder(context) + .setTitle(R.string.tb_permission_dialog_title) + .setMessage(R.string.tb_permission_dialog_message_alt) + .setPositiveButton(R.string.tb_action_open_settings, (dialog, which) -> { + try { + context.startActivity(new Intent(Settings.ACTION_MANAGE_APPLICATIONS_SETTINGS)); + onFinish.run(); + } catch (ActivityNotFoundException e) { + onError.run(); + } + }); } public static AlertDialog showErrorDialog(Context context, String appopCmd) { @@ -153,9 +185,9 @@ public class U { : 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, (dialog, which) -> finalOnFinish.run()); + builder.setTitle(R.string.tb_error_dialog_title) + .setMessage(context.getString(R.string.tb_error_dialog_message, context.getPackageName(), appopCmd)) + .setPositiveButton(R.string.tb_action_ok, (dialog, which) -> finalOnFinish.run()); AlertDialog dialog = builder.create(); dialog.show(); @@ -164,14 +196,17 @@ public class U { return dialog; } + @TargetApi(Build.VERSION_CODES.P) + public static void lockDevice(Context context) { + sendAccessibilityAction(context, AccessibilityService.GLOBAL_ACTION_LOCK_SCREEN); + } + 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); + setComponentEnabled(context, PowerMenuService.class, true); boolean isAccessibilityServiceEnabled = isAccessibilityServiceEnabled(context); @@ -195,9 +230,9 @@ public class U { } new Handler().postDelayed(() -> { - Intent intent = new Intent("com.farmerbb.taskbar.ACCESSIBILITY_ACTION"); + Intent intent = new Intent(TaskbarIntent.ACTION_ACCESSIBILITY_ACTION); intent.putExtra("action", action); - LocalBroadcastManager.getInstance(context).sendBroadcast(intent); + sendBroadcast(context, intent); try { Settings.Secure.putString(context.getContentResolver(), @@ -208,9 +243,9 @@ public class U { if(onComplete != null) onComplete.run(); }, 100); } else if(isAccessibilityServiceEnabled) { - Intent intent = new Intent("com.farmerbb.taskbar.ACCESSIBILITY_ACTION"); + Intent intent = new Intent(TaskbarIntent.ACTION_ACCESSIBILITY_ACTION); intent.putExtra("action", action); - LocalBroadcastManager.getInstance(context).sendBroadcast(intent); + sendBroadcast(context, intent); if(onComplete != null) onComplete.run(); } else { @@ -220,7 +255,7 @@ public class U { intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_NO_ANIMATION); try { - context.startActivity(intent, getActivityOptionsBundle(context, ApplicationType.APPLICATION, null)); + context.startActivity(intent, getActivityOptionsBundle(context, ApplicationType.APP_PORTRAIT, null)); } catch (IllegalArgumentException | SecurityException e) { /* Gracefully fail */ } }); } @@ -268,8 +303,10 @@ public class U { null, false, false, + false, shortcut, - view); + view, + null); } public static void launchApp(final Context context, @@ -282,27 +319,47 @@ public class U { entry, windowSize, launchedFromTaskbar, + false, openInNewWindow, null, - view); + view, + null); + } + + public static void launchApp(final Context context, + final AppEntry entry, + final String windowSize, + final Runnable onError) { + launchApp(context, + entry, + windowSize, + false, + true, + false, + null, + null, + onError); } private static void launchApp(final Context context, final AppEntry entry, final String windowSize, final boolean launchedFromTaskbar, + final boolean isPersistentShortcut, final boolean openInNewWindow, final ShortcutInfo shortcut, - final View view) { - launchApp(context, launchedFromTaskbar, () -> continueLaunchingApp(context, entry, - windowSize, openInNewWindow, shortcut, view)); + final View view, + final Runnable onError) { + launchApp(context, launchedFromTaskbar, isPersistentShortcut, () -> + continueLaunchingApp(context, entry, windowSize, openInNewWindow, shortcut, view, onError) + ); } public static void launchApp(Context context, Runnable runnable) { - launchApp(context, true, runnable); + launchApp(context, true, false, runnable); } - private static void launchApp(Context context, boolean launchedFromTaskbar, Runnable runnable) { + private static void launchApp(Context context, boolean launchedFromTaskbar, boolean isPersistentShortcut, Runnable runnable) { SharedPreferences pref = getSharedPreferences(context); FreeformHackHelper helper = FreeformHackHelper.getInstance(); @@ -313,7 +370,7 @@ public class U { boolean noAnimation = pref.getBoolean("disable_animations", false); if(hasFreeformSupport(context) - && pref.getBoolean("freeform_hack", false) + && (pref.getBoolean("freeform_hack", false) || isPersistentShortcut) && (!helper.isInFreeformWorkspace() || specialLaunch)) { new Handler().postDelayed(() -> { startFreeformHack(context, true); @@ -338,14 +395,14 @@ public class U { if(checkMultiWindow) freeformHackIntent.putExtra("check_multiwindow", true); - if(canDrawOverlays(context, false)) + if(canDrawOverlays(context)) startActivityLowerRight(context, freeformHackIntent); } public static void stopFreeformHack(Context context) { - LocalBroadcastManager.getInstance(context).sendBroadcast(new Intent("com.farmerbb.taskbar.FINISH_FREEFORM_ACTIVITY")); + sendBroadcast(context, TaskbarIntent.ACTION_FINISH_FREEFORM_ACTIVITY); - if(isOverridingFreeformHack(context)) { + if(isOverridingFreeformHack(context, false)) { FreeformHackHelper helper = FreeformHackHelper.getInstance(); helper.setFreeformHackActive(false); helper.setInFreeformWorkspace(false); @@ -358,7 +415,8 @@ public class U { String windowSize, boolean openInNewWindow, ShortcutInfo shortcut, - View view) { + View view, + Runnable onError) { SharedPreferences pref = getSharedPreferences(context); Intent intent = new Intent(); intent.setComponent(ComponentName.unflattenFromString(entry.getComponentName())); @@ -374,7 +432,8 @@ public class U { if(pref.getBoolean("disable_animations", false)) intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION); - if(openInNewWindow || pref.getBoolean("force_new_window", false)) { + boolean realOpenInNewWindow = openInNewWindow || pref.getBoolean("force_new_window", false); + if(realOpenInNewWindow) { intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK); ActivityInfo activityInfo = intent.resolveActivityInfo(context.getPackageManager(), 0); @@ -388,52 +447,51 @@ public class U { } } - ApplicationType type = getApplicationType(context, entry.getPackageName()); + ApplicationType type = getApplicationType(context, entry); if(windowSize == null) windowSize = SavedWindowSizes.getInstance(context).getWindowSize(context, entry.getPackageName()); Bundle bundle = getActivityOptionsBundle(context, type, windowSize, view); - prepareToStartActivity(context, () -> { + prepareToStartActivity(context, realOpenInNewWindow, () -> { if(shortcut == null) { UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE); if(entry.getUserId(context) == userManager.getSerialNumberForUser(Process.myUserHandle())) { try { context.startActivity(intent, bundle); } catch (ActivityNotFoundException e) { - launchAndroidForWork(context, intent.getComponent(), bundle, entry.getUserId(context)); + launchAndroidForWork(context, intent.getComponent(), bundle, entry.getUserId(context), onError); } catch (IllegalArgumentException | SecurityException e) { /* Gracefully fail */ } } else - launchAndroidForWork(context, intent.getComponent(), bundle, entry.getUserId(context)); + launchAndroidForWork(context, intent.getComponent(), bundle, entry.getUserId(context), onError); } else - launchShortcut(context, shortcut, bundle); + launchShortcut(context, shortcut, bundle, onError); }); - 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")); + if(shouldCollapse(context, true)) { + sendBroadcast(context, TaskbarIntent.ACTION_HIDE_TASKBAR); + } else { + sendBroadcast(context, TaskbarIntent.ACTION_HIDE_START_MENU); + } } - @TargetApi(Build.VERSION_CODES.N) - private static Bundle launchMode1(Context context, ApplicationType type, View view) { + private static Bundle launchMode1(Context context, ApplicationType type, View view, int factor) { DisplayInfo display = getDisplayInfo(context); - int width1 = display.width / 8; + int width1 = display.width / factor; int width2 = display.width - width1; - int height1 = display.height / 8; + int height1 = display.height / factor; int height2 = display.height - height1; - return getActivityOptions(context, type, view).setLaunchBounds(new Rect( + return getActivityOptionsBundle(context, type, view, width1, height1, width2, height2 - )).toBundle(); + ); } - @TargetApi(Build.VERSION_CODES.N) private static Bundle launchMode2(Context context, int launchType, ApplicationType type, View view) { DisplayInfo display = getDisplayInfo(context); @@ -450,7 +508,7 @@ public class U { int iconSize = isOverridingFreeformHack(context) && !LauncherHelper.getInstance().isOnHomeScreen() ? 0 - : context.getResources().getDimensionPixelSize(R.dimen.icon_size); + : context.getResources().getDimensionPixelSize(R.dimen.tb_icon_size); if(position.contains("vertical_left")) left = left + iconSize; @@ -473,79 +531,92 @@ public class U { else if(launchType == LEFT && isPortrait) bottom = halfPortrait; - return getActivityOptions(context, type, view) - .setLaunchBounds(new Rect(left, top, right, bottom)).toBundle(); + return getActivityOptionsBundle(context, type, view, left, top, right, bottom); } - @TargetApi(Build.VERSION_CODES.N) private static Bundle launchMode3(Context context, ApplicationType type, View view) { DisplayInfo display = getDisplayInfo(context); + boolean isLandscape = type == ApplicationType.APP_LANDSCAPE; + int widthDimen = isLandscape ? R.dimen.tb_phone_size_height : R.dimen.tb_phone_size_width; + int heightDimen = isLandscape ? R.dimen.tb_phone_size_width : R.dimen.tb_phone_size_height; + int width1 = display.width / 2; - int width2 = context.getResources().getDimensionPixelSize(R.dimen.phone_size_width) / 2; + int width2 = context.getResources().getDimensionPixelSize(widthDimen) / 2; int height1 = display.height / 2; - int height2 = context.getResources().getDimensionPixelSize(R.dimen.phone_size_height) / 2; + int height2 = context.getResources().getDimensionPixelSize(heightDimen) / 2; - return getActivityOptions(context, type, view).setLaunchBounds(new Rect( + return getActivityOptionsBundle(context, type, view, width1 - width2, height1 - height2, width1 + width2, height1 + height2 - )).toBundle(); + ); } - private static void launchAndroidForWork(Context context, ComponentName componentName, Bundle bundle, long userId) { + private static void launchAndroidForWork(Context context, ComponentName componentName, Bundle bundle, long userId, Runnable onError) { UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE); LauncherApps launcherApps = (LauncherApps) context.getSystemService(Context.LAUNCHER_APPS_SERVICE); try { launcherApps.startMainActivity(componentName, userManager.getUserForSerialNumber(userId), null, bundle); - } catch (ActivityNotFoundException | NullPointerException e) { /* Gracefully fail */ } + } catch (ActivityNotFoundException | NullPointerException + | IllegalStateException | SecurityException e) { + if(onError != null) launchApp(context, onError); + } } @TargetApi(Build.VERSION_CODES.N_MR1) - private static void launchShortcut(Context context, ShortcutInfo shortcut, Bundle bundle) { + private static void launchShortcut(Context context, ShortcutInfo shortcut, Bundle bundle, Runnable onError) { LauncherApps launcherApps = (LauncherApps) context.getSystemService(Context.LAUNCHER_APPS_SERVICE); if(launcherApps.hasShortcutHostPermission()) { try { launcherApps.startShortcut(shortcut, null, bundle); - } catch (ActivityNotFoundException | NullPointerException e) { /* Gracefully fail */ } + } catch (ActivityNotFoundException | NullPointerException + | IllegalStateException | SecurityException e) { + if(onError != null) launchApp(context, onError); + } } } - private static void prepareToStartActivity(Context context, Runnable runnable) { - LocalBroadcastManager.getInstance(context).sendBroadcast(new Intent("com.farmerbb.taskbar.HIDE_CONTEXT_MENU")); + private static void prepareToStartActivity(Context context, boolean openInNewWindow, Runnable runnable) { + sendBroadcast(context, TaskbarIntent.ACTION_HIDE_CONTEXT_MENU); if(!FreeformHackHelper.getInstance().isTouchAbsorberActive() && shouldLaunchTouchAbsorber(context)) { startTouchAbsorberActivity(context); new Handler().postDelayed(runnable, 100); + } else if(openInNewWindow) { + Intent intent = new Intent(context, DummyActivity.class); + intent.putExtra("finish_on_pause", true); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK + | Intent.FLAG_ACTIVITY_NO_ANIMATION); + startActivityLowerRight(context, intent); + + new Handler().postDelayed(runnable, 100); } else runnable.run(); } public static void startActivityMaximized(Context context, Intent intent) { Bundle bundle = launchMode2(context, MAXIMIZED, ApplicationType.CONTEXT_MENU, null); - prepareToStartActivity(context, () -> context.startActivity(intent, bundle)); + prepareToStartActivity(context, false, () -> context.startActivity(intent, bundle)); } - @TargetApi(Build.VERSION_CODES.N) public static void startActivityLowerRight(Context context, Intent intent) { DisplayInfo display = getDisplayInfo(context); try { context.startActivity(intent, - getActivityOptions(context, ApplicationType.FREEFORM_HACK, null) - .setLaunchBounds(new Rect( - display.width, - display.height, - display.width + 1, - display.height + 1 - )).toBundle()); + getActivityOptionsBundle(context, ApplicationType.FREEFORM_HACK, null, + display.width, + display.height, + display.width + 1, + display.height + 1 + )); } catch (IllegalArgumentException | SecurityException e) { /* Gracefully fail */ } } - @TargetApi(Build.VERSION_CODES.N) public static void startTouchAbsorberActivity(Context context) { String position = getTaskbarPosition(context); DisplayInfo display = getDisplayInfo(context); @@ -555,7 +626,7 @@ public class U { int right = display.width; int bottom = display.height; - int iconSize = context.getResources().getDimensionPixelSize(R.dimen.icon_size); + int iconSize = context.getResources().getDimensionPixelSize(R.dimen.tb_icon_size); if(position.contains("vertical_left")) right = iconSize; @@ -572,8 +643,8 @@ public class U { try { context.startActivity(intent, - getActivityOptions(context, ApplicationType.FREEFORM_HACK, null) - .setLaunchBounds(new Rect(left, top, right, bottom)).toBundle()); + getActivityOptionsBundle(context, ApplicationType.FREEFORM_HACK, null, + left, top, right, bottom)); } catch (IllegalArgumentException | SecurityException e) { /* Gracefully fail */ } } @@ -602,10 +673,8 @@ public class U { intent.putExtra("context_menu_fix", true); context.startActivity(intent, - getActivityOptions(context, ApplicationType.CONTEXT_MENU, null) - .setLaunchBounds( - new Rect(0, 0, display.width, display.height) - ).toBundle()); + getActivityOptionsBundle(context, ApplicationType.CONTEXT_MENU, null, + 0, 0, display.width, display.height)); } else context.startActivity(intent); } @@ -613,13 +682,13 @@ public class U { public static void checkForUpdates(Context context) { String url; if(isPlayStoreRelease(context)) { - if(BuildConfig.APPLICATION_ID.equals(BuildConfig.BASE_APPLICATION_ID) + if(context.getPackageName().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; + url = "https://play.google.com/store/apps/details?id=" + context.getPackageName(); } else - url = "https://f-droid.org/repository/browse/?fdid=" + BuildConfig.APPLICATION_ID; + url = "https://f-droid.org/repository/browse/?fdid=" + context.getPackageName(); Intent intent = new Intent(Intent.ACTION_VIEW); intent.setData(Uri.parse(url)); @@ -635,7 +704,7 @@ public class U { homeIntent.addCategory(Intent.CATEGORY_HOME); ResolveInfo defaultLauncher = context.getPackageManager().resolveActivity(homeIntent, PackageManager.MATCH_DEFAULT_ONLY); - return defaultLauncher.activityInfo.packageName.equals(BuildConfig.APPLICATION_ID); + return defaultLauncher.activityInfo.packageName.equals(context.getPackageName()); } public static void setCachedRotation(int cachedRotation) { @@ -764,7 +833,7 @@ public class U { ? (display.height - getStatusBarHeight(context)) / density : display.width / density; - float iconSize = context.getResources().getDimension(R.dimen.icon_size) / density; + float iconSize = context.getResources().getDimension(R.dimen.tb_icon_size) / density; int userMaxNumOfColumns = Integer.valueOf(pref.getString("max_num_of_recents", "10")); @@ -858,32 +927,6 @@ public class U { } } - public static Intent getShortcutIntent(Context context) { - Intent shortcutIntent = new Intent(context, ShortcutActivity.class); - shortcutIntent.setAction(Intent.ACTION_MAIN); - shortcutIntent.putExtra("is_launching_shortcut", true); - - Intent intent = new Intent(); - intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent); - intent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, Intent.ShortcutIconResource.fromContext(context, R.mipmap.ic_freeform_mode)); - intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, context.getString(R.string.pref_header_freeform)); - - return intent; - } - - public static Intent getStartStopIntent(Context context) { - Intent shortcutIntent = new Intent(context, StartTaskbarActivity.class); - shortcutIntent.setAction(Intent.ACTION_MAIN); - shortcutIntent.putExtra("is_launching_shortcut", true); - - Intent intent = new Intent(); - intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent); - intent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, Intent.ShortcutIconResource.fromContext(context, R.mipmap.ic_launcher)); - intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, context.getString(R.string.start_taskbar)); - - return intent; - } - public static boolean canEnableFreeform() { return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N; } @@ -898,10 +941,11 @@ public class U { } public static boolean canBootToFreeform(Context context) { - SharedPreferences pref = getSharedPreferences(context); - return hasFreeformSupport(context) - && pref.getBoolean("freeform_hack", false) - && !isOverridingFreeformHack(context); + return canBootToFreeform(context, true); + } + + private static boolean canBootToFreeform(Context context, boolean checkPref) { + return hasFreeformSupport(context) && !isOverridingFreeformHack(context, checkPref); } public static boolean isSamsungDevice() { @@ -913,8 +957,7 @@ public class U { } public static boolean isServiceRunning(Context context, Class cls) { - if(LauncherHelper.getInstance().isOnHomeScreen() - && FeatureFlags.homeActivityUIHost + if(LauncherHelper.getInstance().isOnSecondaryHomeScreen() && (cls.equals(TaskbarService.class) || cls.equals(StartMenuService.class) || cls.equals(DashboardService.class))) @@ -947,19 +990,16 @@ public class U { editor.apply(); } - return pref.getInt("background_tint", context.getResources().getInteger(R.integer.translucent_gray)); + return pref.getInt("background_tint", context.getResources().getInteger(R.integer.tb_translucent_gray)); } public static int getAccentColor(Context context) { SharedPreferences pref = getSharedPreferences(context); - return pref.getInt("accent_color", context.getResources().getInteger(R.integer.translucent_white)); + return pref.getInt("accent_color", context.getResources().getInteger(R.integer.tb_translucent_white)); } - @TargetApi(Build.VERSION_CODES.M) - public static boolean canDrawOverlays(Context context, boolean forHomeScreen) { - return (forHomeScreen && FeatureFlags.homeActivityUIHost && !canBootToFreeform(context)) - || Build.VERSION.SDK_INT < Build.VERSION_CODES.M - || Settings.canDrawOverlays(context); + public static boolean canDrawOverlays(Context context) { + return Build.VERSION.SDK_INT < Build.VERSION_CODES.M || Settings.canDrawOverlays(context); } public static boolean isGame(Context context, String packageName) { @@ -981,13 +1021,21 @@ public class U { return getActivityOptions(null, null, view); } - @TargetApi(Build.VERSION_CODES.N) - private static ActivityOptions getActivityOptions(Context context, ApplicationType applicationType, View view) { + public static ActivityOptions getActivityOptions(Context context, ApplicationType applicationType, View view) { ActivityOptions options; if(view != null) options = ActivityOptions.makeScaleUpAnimation(view, 0, 0, view.getWidth(), view.getHeight()); - else + else if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) options = ActivityOptions.makeBasic(); + else { + try { + Constructor constructor = ActivityOptions.class.getDeclaredConstructor(); + constructor.setAccessible(true); + options = constructor.newInstance(); + } catch (Exception e) { + return null; + } + } if(applicationType == null) return options; @@ -995,13 +1043,14 @@ public class U { int stackId = -1; switch(applicationType) { - case APPLICATION: + case APP_PORTRAIT: + case APP_LANDSCAPE: if(FreeformHackHelper.getInstance().isFreeformHackActive()) stackId = getFreeformWindowModeId(); else stackId = getFullscreenWindowModeId(); break; - case GAME: + case APP_FULLSCREEN: stackId = getFullscreenWindowModeId(); break; case FREEFORM_HACK: @@ -1019,6 +1068,12 @@ public class U { method.invoke(options, stackId); } catch (Exception e) { /* Gracefully fail */ } + if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + int launchDisplayId = LauncherHelper.getInstance().getSecondaryDisplayId(); + if(launchDisplayId != -1) + options.setLaunchDisplayId(launchDisplayId); + } + return options; } @@ -1046,7 +1101,7 @@ public class U { public static Bundle getActivityOptionsBundle(Context context, ApplicationType type, View view) { SharedPreferences pref = getSharedPreferences(context); - return getActivityOptionsBundle(context, type, pref.getString("window_size", "standard"), view); + return getActivityOptionsBundle(context, type, pref.getString("window_size", context.getString(R.string.tb_def_window_size)), view); } private static Bundle getActivityOptionsBundle(Context context, ApplicationType type, String windowSize, View view) { @@ -1055,8 +1110,12 @@ public class U { return getActivityOptions(view).toBundle(); switch(windowSize) { + case "standard": + if(getCurrentApiVersion() > 29.0f) + return launchMode1(context, type, view, 4); + break; case "large": - return launchMode1(context, type, view); + return launchMode1(context, type, view, 8); case "fullscreen": return launchMode2(context, MAXIMIZED, type, view); case "half_left": @@ -1070,13 +1129,52 @@ public class U { return getActivityOptions(context, type, view).toBundle(); } - private static ApplicationType getApplicationType(Context context, String packageName) { - return isGame(context, packageName) ? ApplicationType.GAME : ApplicationType.APPLICATION; + private static Bundle getActivityOptionsBundle(Context context, ApplicationType applicationType, View view, + int left, int top, int right, int bottom) { + ActivityOptions options = getActivityOptions(context, applicationType, view); + if(options == null) + return null; + + if(Build.VERSION.SDK_INT < Build.VERSION_CODES.N) + return options.toBundle(); + + return options.setLaunchBounds(new Rect(left, top, right, bottom)).toBundle(); + } + + @SuppressLint("SwitchIntDef") + private static ApplicationType getApplicationType(Context context, AppEntry entry) { + if(isGame(context, entry.getPackageName())) + return ApplicationType.APP_FULLSCREEN; + + try { + ActivityInfo info = context.getPackageManager().getActivityInfo( + ComponentName.unflattenFromString(entry.getComponentName()), + 0 + ); + + switch(info.screenOrientation) { + case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE: + case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE: + case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE: + case ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE: + return ApplicationType.APP_LANDSCAPE; + + case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT: + case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT: + case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT: + case ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT: + return ApplicationType.APP_PORTRAIT; + } + } catch (PackageManager.NameNotFoundException e) { /* Gracefully fail */ } + + return context.getPackageName().equals(BuildConfig.ANDROIDX86_APPLICATION_ID) + ? ApplicationType.APP_LANDSCAPE + : ApplicationType.APP_PORTRAIT; } public static boolean isSystemApp(Context context) { try { - ApplicationInfo info = context.getPackageManager().getApplicationInfo(BuildConfig.APPLICATION_ID, 0); + ApplicationInfo info = context.getPackageManager().getApplicationInfo(context.getPackageName(), 0); int mask = ApplicationInfo.FLAG_SYSTEM | ApplicationInfo.FLAG_UPDATED_SYSTEM_APP; return (info.flags & mask) != 0; } catch (PackageManager.NameNotFoundException e) { @@ -1100,19 +1198,24 @@ public class U { validBlissOsBuildProp = true; return validBlissOsBuildProp - && BuildConfig.APPLICATION_ID.equals(BuildConfig.BASE_APPLICATION_ID) + && context.getPackageName().equals(BuildConfig.BASE_APPLICATION_ID) && isSystemApp(context); } public static boolean isLauncherPermanentlyEnabled(Context context) { - if(BuildConfig.APPLICATION_ID.equals(BuildConfig.ANDROIDX86_APPLICATION_ID)) + if(context.getPackageName().equals(BuildConfig.ANDROIDX86_APPLICATION_ID)) return true; + return hasSupportLibrary(context, 0); + } + + public static boolean hasSupportLibrary(Context context, int minVersion) { PackageManager pm = context.getPackageManager(); try { - pm.getPackageInfo(BuildConfig.SUPPORT_APPLICATION_ID, 0); - return pm.checkSignatures(BuildConfig.SUPPORT_APPLICATION_ID, BuildConfig.APPLICATION_ID) == PackageManager.SIGNATURE_MATCH - && BuildConfig.APPLICATION_ID.equals(BuildConfig.BASE_APPLICATION_ID) + PackageInfo pInfo = pm.getPackageInfo(BuildConfig.SUPPORT_APPLICATION_ID, 0); + return pInfo.versionCode >= minVersion + && pm.checkSignatures(BuildConfig.SUPPORT_APPLICATION_ID, context.getPackageName()) == PackageManager.SIGNATURE_MATCH + && context.getPackageName().equals(BuildConfig.BASE_APPLICATION_ID) && isSystemApp(context); } catch (PackageManager.NameNotFoundException e) { return false; @@ -1125,29 +1228,32 @@ public class U { private static float getBaseTaskbarSizeFloat(Context context) { SharedPreferences pref = getSharedPreferences(context); - float baseTaskbarSize = context.getResources().getDimension(R.dimen.base_taskbar_size); + float baseTaskbarSize = context.getResources().getDimension(R.dimen.tb_base_taskbar_size); boolean navbarButtonsEnabled = false; - if(pref.getBoolean("dashboard", false)) - baseTaskbarSize += context.getResources().getDimension(R.dimen.dashboard_button_size); + if(pref.getBoolean("dashboard", context.getResources().getBoolean(R.bool.tb_def_dashboard))) + baseTaskbarSize += context.getResources().getDimension(R.dimen.tb_dashboard_button_size); if(pref.getBoolean("button_back", false)) { navbarButtonsEnabled = true; - baseTaskbarSize += context.getResources().getDimension(R.dimen.icon_size); + baseTaskbarSize += context.getResources().getDimension(R.dimen.tb_icon_size); } if(pref.getBoolean("button_home", false)) { navbarButtonsEnabled = true; - baseTaskbarSize += context.getResources().getDimension(R.dimen.icon_size); + baseTaskbarSize += context.getResources().getDimension(R.dimen.tb_icon_size); } if(pref.getBoolean("button_recents", false)) { navbarButtonsEnabled = true; - baseTaskbarSize += context.getResources().getDimension(R.dimen.icon_size); + baseTaskbarSize += context.getResources().getDimension(R.dimen.tb_icon_size); } if(navbarButtonsEnabled) - baseTaskbarSize += context.getResources().getDimension(R.dimen.navbar_buttons_margin); + baseTaskbarSize += context.getResources().getDimension(R.dimen.tb_navbar_buttons_margin); + + if(isSystemTrayEnabled(context)) + baseTaskbarSize += context.getResources().getDimension(R.dimen.tb_systray_size); return baseTaskbarSize; } @@ -1183,7 +1289,7 @@ public class U { startTaskbarService(context, false); } - LocalBroadcastManager.getInstance(context).sendBroadcast(new Intent("com.farmerbb.taskbar.RESTART")); + sendBroadcast(context, TaskbarIntent.ACTION_RESTART); } public static void restartNotificationService(Context context) { @@ -1198,7 +1304,38 @@ public class U { } public static void showHideNavigationBar(Context context, boolean show) { + if(!isDesktopModeActive(context) + && !isBlissOs(context) + && !hasSupportLibrary(context, 7)) { + return; + } + + int displayID = getDisplayID(); + int value = show ? 0 : getNavbarHeight(context) * -1; + + if(hasWriteSecureSettingsPermission(context)) { + try { + setOverscan(displayID, value); + return; + } catch (Exception e) { + // Fallback to next method + } + } + + if(hasSupportLibrary(context, 7)) { + Intent intent = new Intent(BuildConfig.SUPPORT_APPLICATION_ID + ".CHANGE_OVERSCAN"); + intent.setPackage(BuildConfig.SUPPORT_APPLICATION_ID); + + intent.putExtra("display_id", displayID); + intent.putExtra("value", value); + + context.sendBroadcast(intent); + return; + } + // Show or hide the system navigation bar on Bliss-x86 + if(!isBlissOs(context)) return; + try { if(getCurrentApiVersion() >= 28.0f) Settings.Secure.putInt(context.getContentResolver(), "navigation_bar_visible", show ? 1 : 0); @@ -1208,14 +1345,8 @@ 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 < 720 - && pref.getString("start_menu_layout", "null").equals("null")) { - pref.edit().putString("start_menu_layout", "grid").apply(); - } - // Enable freeform hack automatically on supported devices + SharedPreferences pref = getSharedPreferences(context); if(canEnableFreeform()) { if(!pref.getBoolean("freeform_hack_override", false)) { pref.edit() @@ -1254,21 +1385,18 @@ public class U { editor.putString("refresh_frequency", "0"); editor.putString("max_num_of_recents", "2147483647"); editor.putString("sort_order", "true"); - editor.putString("window_size", "phone_size"); editor.putString("start_button_image", "app_logo"); - editor.putBoolean("full_length", true); - editor.putBoolean("dashboard", true); editor.putBoolean("button_back", true); editor.putBoolean("button_home", true); editor.putBoolean("button_recents", true); editor.putBoolean("auto_hide_navbar", true); - // editor.putBoolean("shortcut_icon", false); + editor.putBoolean("shortcut_icon", false); editor.putBoolean("bliss_os_prefs", true); editor.apply(); } // Customizations for Android-x86 devices (non-Bliss) - if(BuildConfig.APPLICATION_ID.equals(BuildConfig.ANDROIDX86_APPLICATION_ID) + if(context.getPackageName().equals(BuildConfig.ANDROIDX86_APPLICATION_ID) && isSystemApp(context) && !pref.getBoolean("android_x86_prefs", false)) { pref.edit() @@ -1276,10 +1404,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("shortcut_icon", false) + .putBoolean("shortcut_icon", false) .putBoolean("android_x86_prefs", true) .apply(); } @@ -1291,46 +1416,66 @@ public class U { public static DisplayInfo getDisplayInfo(Context context, boolean fromTaskbar) { context = context.getApplicationContext(); + int displayID = getDisplayID(); - WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); - Display disp = wm.getDefaultDisplay(); + DisplayManager dm = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE); + Display currentDisplay = null; + + for(Display display : dm.getDisplays()) { + if(display.getDisplayId() == displayID) { + currentDisplay = display; + break; + } + } + + if(currentDisplay == null) + return new DisplayInfo(0, 0, 0); DisplayMetrics metrics = new DisplayMetrics(); - disp.getMetrics(metrics); + currentDisplay.getMetrics(metrics); DisplayMetrics realMetrics = new DisplayMetrics(); - disp.getRealMetrics(realMetrics); + currentDisplay.getRealMetrics(realMetrics); - DisplayInfo display = new DisplayInfo(metrics.widthPixels, metrics.heightPixels, metrics.densityDpi); + DisplayInfo info = 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; + info.width = realMetrics.widthPixels; + info.height = realMetrics.heightPixels; } - return display; + return info; } // Workaround for incorrect display size on devices with notches in landscape mode if(fromTaskbar && context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) - return display; + return info; 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); + info.width = realMetrics.widthPixels; + info.height = realMetrics.heightPixels - getNavbarHeight(context); } if(!sameWidth && sameHeight) { - display.width = realMetrics.widthPixels - getNavbarHeight(context); - display.height = realMetrics.heightPixels; + info.width = realMetrics.widthPixels - getNavbarHeight(context); + info.height = realMetrics.heightPixels; } - return display; + return info; + } + + private static int getDisplayID() { + LauncherHelper helper = LauncherHelper.getInstance(); + + if(helper.isOnSecondaryHomeScreen()) + return helper.getSecondaryDisplayId(); + else + return Display.DEFAULT_DISPLAY; } public static void pinAppShortcut(Context context) { @@ -1342,9 +1487,9 @@ public class U { mShortcutManager.requestPinShortcut(pinShortcutInfo, null); } else - showToastLong(context, R.string.pin_shortcut_not_supported); + showToastLong(context, R.string.tb_pin_shortcut_not_supported); } else { - Intent intent = getShortcutIntent(context); + Intent intent = ShortcutUtils.getShortcutIntent(context); intent.setAction("com.android.launcher.action.INSTALL_SHORTCUT"); intent.putExtra("duplicate", false); @@ -1355,14 +1500,15 @@ public class U { intent.setPackage(defaultLauncher.activityInfo.packageName); context.sendBroadcast(intent); - showToast(context, R.string.shortcut_created); + showToast(context, R.string.tb_shortcut_created); } } public static boolean shouldCollapse(Context context, boolean pendingAppLaunch) { SharedPreferences pref = getSharedPreferences(context); if(pref.getBoolean("hide_taskbar", true)) { - if(isOverridingFreeformHack(context)) + if(!pref.getBoolean("freeform_hack", false) + || isOverridingFreeformHack(context, false)) return !LauncherHelper.getInstance().isOnHomeScreen(); else { FreeformHackHelper helper = FreeformHackHelper.getInstance(); @@ -1376,8 +1522,12 @@ public class U { } public static boolean isOverridingFreeformHack(Context context) { + return isOverridingFreeformHack(context, true); + } + + public static boolean isOverridingFreeformHack(Context context, boolean checkPref) { SharedPreferences pref = getSharedPreferences(context); - return pref.getBoolean("freeform_hack", false) + return (!checkPref || pref.getBoolean("freeform_hack", false)) && ((isChromeOs(context) && pref.getBoolean("chrome_os_context_menu_fix", true)) || (!isChromeOs(context) && getCurrentApiVersion() >= 28.0f)); } @@ -1391,7 +1541,7 @@ public class U { } } - private static float getCurrentApiVersion() { + public 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 @@ -1406,12 +1556,16 @@ public class U { } public static String getSecondScreenPackageName(Context context) { - return getInstalledPackage(context, Arrays.asList( + return getInstalledPackage(context, "com.farmerbb.secondscreen.free", - "com.farmerbb.secondscreen")); + "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, String... packageNames) { + return getInstalledPackage(context, Arrays.asList(packageNames)); + } + private static String getInstalledPackage(Context context, List packageNames) { if(packageNames == null || packageNames.isEmpty()) return null; @@ -1428,12 +1582,6 @@ public class U { } } - public static boolean visualFeedbackEnabled(Context context) { - SharedPreferences pref = getSharedPreferences(context); - return (getCurrentApiVersion() < 26.0f || getCurrentApiVersion() >= 28.0f) - && pref.getBoolean("visual_feedback", true); - } - public static void showRecentAppsDialog(Context context) { showRecentAppsDialog(context, null, null); } @@ -1450,7 +1598,7 @@ public class U { if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !isSystemApp(context)) { ApplicationInfo applicationInfo = null; try { - applicationInfo = context.getPackageManager().getApplicationInfo(BuildConfig.APPLICATION_ID, 0); + applicationInfo = context.getPackageManager().getApplicationInfo(context.getPackageName(), 0); } catch (PackageManager.NameNotFoundException e) { /* Gracefully fail */ } if(applicationInfo != null) { @@ -1458,20 +1606,11 @@ public class U { 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.Builder builder; + if(hasAndroidTVSettings(context)) + builder = buildRecentAppsDialogAndroidTV(context, finalOnError, finalOnFinish); + else + builder = buildRecentAppsDialogStandard(context, finalOnError, finalOnFinish); AlertDialog dialog = builder.create(); dialog.show(); @@ -1486,16 +1625,48 @@ public class U { return null; } + private static AlertDialog.Builder buildRecentAppsDialogStandard(Context context, Runnable onError, Runnable onFinish) { + return new AlertDialog.Builder(context) + .setTitle(R.string.tb_pref_header_recent_apps) + .setMessage(R.string.tb_enable_recent_apps) + .setPositiveButton(R.string.tb_action_ok, (dialog, which) -> { + try { + context.startActivity(new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS)); + showToastLong(context, R.string.tb_usage_stats_message); + + onFinish.run(); + } catch (ActivityNotFoundException e) { + onError.run(); + } + }) + .setNegativeButton(R.string.tb_action_cancel, (dialog, which) -> onFinish.run()); + } + + private static AlertDialog.Builder buildRecentAppsDialogAndroidTV(Context context, Runnable onError, Runnable onFinish) { + return new AlertDialog.Builder(context) + .setTitle(R.string.tb_pref_header_recent_apps) + .setMessage(R.string.tb_enable_recent_apps_alt) + .setPositiveButton(R.string.tb_action_open_settings, (dialog, which) -> { + try { + context.startActivity(new Intent(Settings.ACTION_MANAGE_APPLICATIONS_SETTINGS)); + onFinish.run(); + } catch (ActivityNotFoundException e) { + onError.run(); + } + }) + .setNegativeButton(R.string.tb_action_cancel, (dialog, which) -> onFinish.run()); + } + public static Context wrapContext(Context context) { SharedPreferences pref = getSharedPreferences(context); int theme = -1; switch(pref.getString("theme", "light")) { case "light": - theme = R.style.AppTheme; + theme = R.style.Taskbar; break; case "dark": - theme = R.style.AppTheme_Dark; + theme = R.style.Taskbar_Dark; break; } @@ -1503,12 +1674,12 @@ public class U { } public static boolean isPlayStoreRelease(Context context) { - return isPlayStoreRelease(context, BuildConfig.APPLICATION_ID); + return isPlayStoreRelease(context, context.getPackageName()); } @SuppressLint("PackageManagerGetSignatures") public static boolean isPlayStoreRelease(Context context, String packageName) { - Signature playStoreSignature = new Signature(context.getString(R.string.signature)); + Signature playStoreSignature = new Signature(context.getString(R.string.tb_signature)); try { PackageManager pm = context.getPackageManager(); PackageInfo info = pm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES); @@ -1522,13 +1693,15 @@ public class U { } public static boolean isExternalAccessDisabled(Context context) { + if(isLibrary(context)) return true; + SharedPreferences pref = getSharedPreferences(context); return !pref.getBoolean("tasker_enabled", true); } public static boolean enableFreeformModeShortcut(Context context) { return canEnableFreeform() - && !isOverridingFreeformHack(context) + && !isOverridingFreeformHack(context, false) && !isChromeOs(context); } @@ -1572,7 +1745,7 @@ public class U { @SuppressWarnings("ResultOfMethodCallIgnored") public static boolean importCustomStartButtonImage(Context context, Uri uri) { try { - File imagesDir = new File(context.getFilesDir(), "images"); + File imagesDir = new File(context.getFilesDir(), "tb_images"); imagesDir.mkdirs(); File importedFile = new File(imagesDir, "custom_image_new"); @@ -1611,6 +1784,152 @@ public class U { } public static boolean isDesktopIconsEnabled(Context context) { - return !canBootToFreeform(context) && !shouldLaunchTouchAbsorber(context); + return !canBootToFreeform(context, false) && !shouldLaunchTouchAbsorber(context); + } + + public static boolean isSystemTrayEnabled(Context context) { + SharedPreferences pref = getSharedPreferences(context); + + return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M + && pref.getBoolean("sys_tray", context.getResources().getBoolean(R.bool.tb_def_sys_tray)) + && pref.getBoolean("full_length", context.getResources().getBoolean(R.bool.tb_def_full_length)) + && !getTaskbarPosition(context).contains("vertical"); + } + + @SuppressWarnings("deprecation") + public static boolean isLibrary(Context context) { + return !context.getPackageName().equals(BuildConfig.APPLICATION_ID); + } + + public static boolean applyDisplayCutoutModeTo(WindowManager.LayoutParams params) { + if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + params.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES; + return true; + } + + return false; + } + + private static boolean hasAndroidTVSettings(Context context) { + return getInstalledPackage(context, "com.android.tv.settings") != null + && Build.VERSION.SDK_INT >= Build.VERSION_CODES.P; + } + + public static void restartApp(Activity activity, boolean shouldFade) { + Intent restartIntent = new Intent(activity, MainActivity.class); + restartIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK); + activity.startActivity(restartIntent); + + activity.overridePendingTransition( + shouldFade ? android.R.anim.fade_in : 0, + shouldFade ? android.R.anim.fade_out : 0 + ); + + System.exit(0); + } + + public static boolean isDesktopModeSupported(Context context) { + if(isLauncherPermanentlyEnabled(context) + || isLibrary(context) + || !BuildConfig.DEBUG // TODO remove this line + || isChromeOs(context)) + return false; + + return Build.VERSION.SDK_INT > Build.VERSION_CODES.P + && context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_ACTIVITIES_ON_SECONDARY_DISPLAYS); + } + + public static boolean isDesktopModeActive(Context context) { + if(!isDesktopModeSupported(context)) return false; + + boolean desktopModePrefEnabled; + + try { + desktopModePrefEnabled = Settings.Global.getInt(context.getContentResolver(), "force_desktop_mode_on_external_displays") == 1; + } catch (Settings.SettingNotFoundException e) { + desktopModePrefEnabled = false; + } + + return desktopModePrefEnabled && getExternalDisplayID(context) != Display.DEFAULT_DISPLAY; + } + + public static boolean shouldStartDesktopMode(Context context) { + SharedPreferences pref = getSharedPreferences(context); + + return isDesktopModeSupported(context) + && pref.getBoolean("desktop_mode", false) + && !pref.getBoolean("launcher", false); + } + + // TODO remove this in favor of the existing getDisplayID method? + public static int getExternalDisplayID(Context context) { + DisplayManager dm = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE); + Display[] displays = dm.getDisplays(); + + return displays[displays.length - 1].getDisplayId(); + } + + @SuppressLint("PrivateApi") + private static Object getWindowManagerService() throws Exception { + return Class.forName("android.view.WindowManagerGlobal") + .getMethod("getWindowManagerService") + .invoke(null); + } + + @SuppressLint("PrivateApi") + private static void setDensity(int displayID, String value) throws Exception { + // From android.os.UserHandle + final int USER_CURRENT_OR_SELF = -3; + + if(value.equals("reset")) { + Class.forName("android.view.IWindowManager") + .getMethod("clearForcedDisplayDensityForUser", int.class, int.class) + .invoke(getWindowManagerService(), displayID, USER_CURRENT_OR_SELF); + } else { + int density = Integer.parseInt(value); + + Class.forName("android.view.IWindowManager") + .getMethod("setForcedDisplayDensityForUser", int.class, int.class, int.class) + .invoke(getWindowManagerService(), displayID, density, USER_CURRENT_OR_SELF); + } + } + + @SuppressLint("PrivateApi") + private static void setOverscan(int displayID, int value) throws Exception { + Class.forName("android.view.IWindowManager") + .getMethod("setOverscan", int.class, int.class, int.class, int.class, int.class) + .invoke(getWindowManagerService(), displayID, 0, 0, 0, value); + } + + public static void registerReceiver(Context context, BroadcastReceiver receiver, String... actions) { + unregisterReceiver(context, receiver); + + IntentFilter intentFilter = new IntentFilter(); + for(String action : actions) { + intentFilter.addAction(action); + } + + LocalBroadcastManager.getInstance(context).registerReceiver(receiver, intentFilter); + } + + public static void unregisterReceiver(Context context, BroadcastReceiver receiver) { + LocalBroadcastManager.getInstance(context).unregisterReceiver(receiver); + } + + public static void sendBroadcast(Context context, String action) { + sendBroadcast(context, new Intent(action)); + } + + public static void sendBroadcast(Context context, Intent intent) { + LocalBroadcastManager.getInstance(context).sendBroadcast(intent); + } + + @SuppressWarnings("rawtypes") + public static void setComponentEnabled(Context context, Class clazz, boolean enabled) { + ComponentName component = new ComponentName(context, clazz); + context.getPackageManager().setComponentEnabledSetting(component, + enabled ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED + : PackageManager.COMPONENT_ENABLED_STATE_DISABLED, + PackageManager.DONT_KILL_APP); } }