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;
import com.farmerbb.taskbar.activity.ContextMenuActivity;
import com.farmerbb.taskbar.activity.DummyActivity;
import com.farmerbb.taskbar.activity.InvisibleActivityFreeform;
+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;
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;
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);
}
public static void showPermissionDialog(Context context) {
- R
showPermissionDialog(context, null, null);
}
- @TargetApi(Build.VERSION_CODES.M)
public static AlertDialog showPermissionDialog(Context context, Runnable onError, Runnable onFinish) {
Runnable finalOnFinish = onFinish == null
? () -> {}
? () -> showErrorDialog(context, "SYSTEM_ALERT_WINDOW", finalOnFinish)
: onError;
- AlertDialog.Builder builder = new AlertDialog.Builder(context);
- builder.setTitle(R.string.tb_permission_dialog_title)
+ 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:" + 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) {
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);
}
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(),
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 {
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 */ }
});
}
null,
false,
false,
+ false,
shortcut,
- view);
+ view,
+ null);
}
public static void launchApp(final Context context,
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();
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);
}
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);
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()));
}
}
- ApplicationType type = getApplicationType(context, entry.getPackageName());
+ ApplicationType type = getApplicationType(context, entry);
if(windowSize == null)
windowSize = SavedWindowSizes.getInstance(context).getWindowSize(context, entry.getPackageName());
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);
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.tb_phone_size_width) / 2;
+ int width2 = context.getResources().getDimensionPixelSize(widthDimen) / 2;
int height1 = display.height / 2;
- int height2 = context.getResources().getDimensionPixelSize(R.dimen.tb_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, boolean openInNewWindow, Runnable runnable) {
- LocalBroadcastManager.getInstance(context).sendBroadcast(new Intent("com.farmerbb.taskbar.HIDE_CONTEXT_MENU"));
+ sendBroadcast(context, TaskbarIntent.ACTION_HIDE_CONTEXT_MENU);
if(!FreeformHackHelper.getInstance().isTouchAbsorberActive()
&& shouldLaunchTouchAbsorber(context)) {
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);
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 */ }
}
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);
}
}
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() {
return pref.getInt("accent_color", context.getResources().getInteger(R.integer.tb_translucent_white));
}
- @TargetApi(Build.VERSION_CODES.M)
public static boolean canDrawOverlays(Context context) {
return Build.VERSION.SDK_INT < Build.VERSION_CODES.M || Settings.canDrawOverlays(context);
}
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<ActivityOptions> constructor = ActivityOptions.class.getDeclaredConstructor();
+ constructor.setAccessible(true);
+ options = constructor.newInstance();
+ } catch (Exception e) {
+ return null;
+ }
+ }
if(applicationType == null)
return options;
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:
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":
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) {
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, context.getPackageName()) == PackageManager.SIGNATURE_MATCH
+ 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) {
startTaskbarService(context, false);
}
- LocalBroadcastManager.getInstance(context).sendBroadcast(new Intent("com.farmerbb.taskbar.RESTART"));
+ sendBroadcast(context, TaskbarIntent.ACTION_RESTART);
}
public static void restartNotificationService(Context context) {
}
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);
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("auto_hide_navbar", true);
+ editor.putBoolean("shortcut_icon", false);
editor.putBoolean("bliss_os_prefs", true);
editor.apply();
}
public static DisplayInfo getDisplayInfo(Context context, boolean fromTaskbar) {
context = context.getApplicationContext();
-
- LauncherHelper helper = LauncherHelper.getInstance();
- int displayID;
-
- if(helper.isOnSecondaryHomeScreen())
- displayID = helper.getSecondaryDisplayId();
- else
- displayID = Display.DEFAULT_DISPLAY;
+ int displayID = getDisplayID();
DisplayManager dm = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
Display currentDisplay = null;
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) {
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
ShortcutManager mShortcutManager = context.getSystemService(ShortcutManager.class);
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();
}
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));
}
}
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<String> packageNames) {
if(packageNames == null || packageNames.isEmpty())
return null;
}
}
- public static boolean visualFeedbackEnabled(Context context) {
- SharedPreferences pref = getSharedPreferences(context);
- return (getCurrentApiVersion() < 26.0f || getCurrentApiVersion() >= 28.0f)
- && pref.getBoolean("visual_feedback", true)
- && !isNvidiaDevice();
- }
-
public static void showRecentAppsDialog(Context context) {
showRecentAppsDialog(context, null, null);
}
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.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);
-
- finalOnFinish.run();
- } catch (ActivityNotFoundException e) {
- finalOnError.run();
- }
- })
- .setNegativeButton(R.string.tb_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();
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);
}
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);
}
}
public static boolean isDesktopIconsEnabled(Context context) {
- return !canBootToFreeform(context) && !shouldLaunchTouchAbsorber(context);
+ return !canBootToFreeform(context, false) && !shouldLaunchTouchAbsorber(context);
}
public static boolean isSystemTrayEnabled(Context context) {
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);
+ }
}