1 package com.farmerbb.taskbar.util;
3 import android.Manifest;
4 import android.accessibilityservice.AccessibilityService;
5 import android.app.ActivityOptions;
6 import android.app.AlertDialog;
7 import android.app.Application;
8 import android.content.BroadcastReceiver;
9 import android.content.ComponentName;
10 import android.content.Context;
11 import android.content.Intent;
12 import android.content.IntentFilter;
13 import android.content.SharedPreferences;
14 import android.content.pm.PackageManager;
15 import android.content.res.Resources;
16 import android.graphics.Color;
17 import android.provider.Settings;
18 import android.view.WindowManager;
19 import android.widget.Button;
20 import android.widget.Toast;
22 import androidx.appcompat.view.ContextThemeWrapper;
23 import androidx.localbroadcastmanager.content.LocalBroadcastManager;
24 import androidx.test.core.app.ApplicationProvider;
26 import com.farmerbb.taskbar.R;
27 import com.farmerbb.taskbar.helper.FreeformHackHelper;
28 import com.farmerbb.taskbar.mockito.BooleanAnswer;
29 import com.farmerbb.taskbar.mockito.IntAnswer;
30 import com.farmerbb.taskbar.service.PowerMenuService;
32 import org.junit.Before;
33 import org.junit.Rule;
34 import org.junit.Test;
35 import org.junit.runner.RunWith;
36 import org.powermock.api.mockito.PowerMockito;
37 import org.powermock.core.classloader.annotations.PowerMockIgnore;
38 import org.powermock.core.classloader.annotations.PrepareForTest;
39 import org.powermock.modules.junit4.rule.PowerMockRule;
40 import org.robolectric.RobolectricTestRunner;
41 import org.robolectric.Shadows;
42 import org.robolectric.annotation.Config;
43 import org.robolectric.annotation.LooperMode;
44 import org.robolectric.shadows.ShadowAlertDialog;
45 import org.robolectric.shadows.ShadowApplication;
46 import org.robolectric.shadows.ShadowBuild;
47 import org.robolectric.shadows.ShadowLooper;
48 import org.robolectric.shadows.ShadowPackageManager;
49 import org.robolectric.shadows.ShadowSettings;
50 import org.robolectric.shadows.ShadowToast;
51 import org.robolectric.util.ReflectionHelpers;
53 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
54 import static org.junit.Assert.assertEquals;
55 import static org.junit.Assert.assertFalse;
56 import static org.junit.Assert.assertNotNull;
57 import static org.junit.Assert.assertTrue;
58 import static org.mockito.Matchers.any;
59 import static org.powermock.api.mockito.PowerMockito.when;
60 import static org.robolectric.util.ReflectionHelpers.ClassParameter.from;
62 import static com.farmerbb.taskbar.util.Constants.*;
64 @RunWith(RobolectricTestRunner.class)
65 @PowerMockIgnore({"org.mockito.*", "org.robolectric.*", "android.*", "androidx.*"})
66 @PrepareForTest(U.class)
67 @LooperMode(LooperMode.Mode.LEGACY)
70 public PowerMockRule rule = new PowerMockRule();
72 private Context context;
76 context = ApplicationProvider.getApplicationContext();
77 assertNotNull(context);
81 public void testShowPermissionDialogWithAndroidTVSettings() throws Exception {
82 testShowPermissionDialog(
84 context.getResources().getString(R.string.tb_permission_dialog_message)
85 + context.getResources().getString(R.string.tb_permission_dialog_instructions_tv),
86 R.string.tb_action_open_settings
91 public void testShowPermissionDialogNormal() throws Exception {
92 testShowPermissionDialog(
94 context.getResources().getString(R.string.tb_permission_dialog_message)
95 + context.getResources().getString(R.string.tb_permission_dialog_instructions_phone),
96 R.string.tb_action_grant_permission
100 private void testShowPermissionDialog(boolean hasAndroidTVSettings,
102 int buttonTextResId) throws Exception {
103 RunnableHooker onError = new RunnableHooker();
104 RunnableHooker onFinish = new RunnableHooker();
105 PowerMockito.spy(U.class);
106 when(U.class, "hasAndroidTVSettings", context).thenReturn(hasAndroidTVSettings);
107 AlertDialog dialog = U.showPermissionDialog(context, new Callbacks(onError, onFinish));
108 ShadowAlertDialog shadowDialog = Shadows.shadowOf(dialog);
109 Resources resources = context.getResources();
111 resources.getString(R.string.tb_permission_dialog_title),
112 shadowDialog.getTitle()
114 assertEquals(message, shadowDialog.getMessage());
115 Button positiveButton = dialog.getButton(AlertDialog.BUTTON_POSITIVE);
116 assertEquals(resources.getString(buttonTextResId), positiveButton.getText());
117 assertFalse(shadowDialog.isCancelable());
118 positiveButton.performClick();
119 assertTrue(onFinish.hasRun());
120 assertFalse(onError.hasRun());
124 public void testShowErrorDialog() {
125 RunnableHooker onFinish = new RunnableHooker();
126 String appOpCommand = "app-op-command";
128 ReflectionHelpers.callStaticMethod(
131 from(Context.class, context),
132 from(String.class, appOpCommand),
133 from(Callbacks.class, new Callbacks(null, onFinish))
135 ShadowAlertDialog shadowDialog = Shadows.shadowOf(dialog);
136 Resources resources = context.getResources();
138 resources.getString(R.string.tb_error_dialog_title),
139 shadowDialog.getTitle()
143 R.string.tb_error_dialog_message,
144 context.getPackageName(),
147 shadowDialog.getMessage()
149 Button button = dialog.getButton(AlertDialog.BUTTON_POSITIVE);
150 assertEquals(resources.getString(R.string.tb_action_ok), button.getText());
151 assertFalse(shadowDialog.isCancelable());
152 button.performClick();
153 assertTrue(onFinish.hasRun());
157 public void testSendAccessibilityActionWithServiceNotEnabledAndGrantedPermission() {
158 testSendAccessibilityAction(false, true, true);
162 public void testSendAccessibilityActionWithServiceEnabled() {
163 testSendAccessibilityAction(true, false, true);
167 public void testSendAccessibilityActionWithServiceNotEnabledAndWithoutPermission() {
168 testSendAccessibilityAction(false, false, false);
171 private void testSendAccessibilityAction(boolean serviceEnabled,
172 boolean hasPermission,
174 PowerMockito.spy(U.class);
175 when(U.isAccessibilityServiceEnabled(context)).thenReturn(serviceEnabled);
176 when(U.hasWriteSecureSettingsPermission(context)).thenReturn(hasPermission);
177 RunnableHooker onComplete = new RunnableHooker();
178 U.sendAccessibilityAction(
179 context, AccessibilityService.GLOBAL_ACTION_LOCK_SCREEN, onComplete
181 // Run all delayed message.
182 ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
183 assertEquals(hasRun, onComplete.hasRun());
187 public void testIsAccessibilityServiceEnabled() {
188 String enabledServices =
189 Settings.Secure.getString(
190 context.getContentResolver(),
191 Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES
193 ComponentName componentName = new ComponentName(context, PowerMenuService.class);
194 String flattenString = componentName.flattenToString();
195 String flattenShortString = componentName.flattenToShortString();
196 String newEnabledService =
197 enabledServices == null ?
200 .replaceAll(":" + flattenString, "")
201 .replaceAll(":" + flattenShortString, "")
202 .replaceAll(flattenString, "")
203 .replaceAll(flattenShortString, "");
204 Settings.Secure.putString(
205 context.getContentResolver(),
206 Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
209 assertFalse(U.isAccessibilityServiceEnabled(context));
210 Settings.Secure.putString(
211 context.getContentResolver(),
212 Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
213 newEnabledService + ":" + flattenString
215 assertTrue(U.isAccessibilityServiceEnabled(context));
216 Settings.Secure.putString(
217 context.getContentResolver(),
218 Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
219 newEnabledService + ":" + flattenShortString
221 assertTrue(U.isAccessibilityServiceEnabled(context));
222 Settings.Secure.putString(
223 context.getContentResolver(),
224 Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
230 public void testHasWriteSecureSettingsPermissionForMarshmallowAndAboveVersion() {
231 assertFalse(U.hasWriteSecureSettingsPermission(context));
232 Application application = ApplicationProvider.getApplicationContext();
233 ShadowApplication shadowApplication = Shadows.shadowOf(application);
234 shadowApplication.grantPermissions(Manifest.permission.WRITE_SECURE_SETTINGS);
235 assertTrue(U.hasWriteSecureSettingsPermission(context));
240 public void testHasWriteSecureSettingsPermissionVersionBelowMarshmallow() {
241 Application application = ApplicationProvider.getApplicationContext();
242 ShadowApplication shadowApplication = Shadows.shadowOf(application);
243 shadowApplication.grantPermissions(Manifest.permission.WRITE_SECURE_SETTINGS);
244 assertFalse(U.hasWriteSecureSettingsPermission(context));
248 public void testShowToast() {
249 U.showToast(context, R.string.tb_pin_shortcut_not_supported);
250 Toast toast = ShadowToast.getLatestToast();
251 assertEquals(Toast.LENGTH_SHORT, toast.getDuration());
253 context.getResources().getString(R.string.tb_pin_shortcut_not_supported),
254 ShadowToast.getTextOfLatestToast()
259 public void testShowLongToast() {
260 U.showToastLong(context, R.string.tb_pin_shortcut_not_supported);
261 Toast toast = ShadowToast.getLatestToast();
262 assertEquals(Toast.LENGTH_LONG, toast.getDuration());
264 context.getResources().getString(R.string.tb_pin_shortcut_not_supported),
265 ShadowToast.getTextOfLatestToast()
270 public void testCancelToast() {
271 U.showToastLong(context, R.string.tb_pin_shortcut_not_supported);
272 ShadowToast shadowToast = Shadows.shadowOf(ShadowToast.getLatestToast());
273 assertFalse(shadowToast.isCancelled());
275 assertTrue(shadowToast.isCancelled());
279 public void testCanEnableFreeformWithNougatAndAboveVersion() {
280 assertTrue(U.canEnableFreeform());
285 public void testCanEnableFreeformWithMarshmallowAndBelowVersion() {
286 assertFalse(U.canEnableFreeform());
290 public void testHasFreeformSupportWithoutFreeformEnabled() {
291 PowerMockito.spy(U.class);
292 when(U.canEnableFreeform()).thenReturn(false);
293 assertFalse(U.canEnableFreeform());
297 public void testHasFreeformSupportWithFreeformEnabledAndNMR1AboveVersion() {
298 PowerMockito.spy(U.class);
299 when(U.canEnableFreeform()).thenReturn(true);
300 assertFalse(U.hasFreeformSupport(context));
301 // Case 1, system has feature freeform.
302 PackageManager packageManager = context.getPackageManager();
303 ShadowPackageManager shadowPackageManager = Shadows.shadowOf(packageManager);
305 .setSystemFeature(PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT, true);
306 assertTrue(U.hasFreeformSupport(context));
308 .setSystemFeature(PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT, false);
309 // Case 2, enable_freeform_support in Settings.Global is not 0
310 Settings.Global.putInt(context.getContentResolver(), "enable_freeform_support", 1);
311 assertTrue(U.hasFreeformSupport(context));
312 Settings.Global.putInt(context.getContentResolver(), "enable_freeform_support", 0);
317 public void testHasFreeformSupportWithFreeformEnabledAndNMR1AndBelowVersion() {
318 PowerMockito.spy(U.class);
319 when(U.canEnableFreeform()).thenReturn(true);
320 assertFalse(U.hasFreeformSupport(context));
321 // Case 3, version is less than or equal to N_MRI, and force_resizable_activities
322 // in Settings.Global is not 0
323 Settings.Global.putInt(context.getContentResolver(), "force_resizable_activities", 1);
324 assertTrue(U.hasFreeformSupport(context));
325 Settings.Global.putInt(context.getContentResolver(), "force_resizable_activities", 0);
329 public void testCanBootToFreeform() {
330 PowerMockito.spy(U.class);
331 BooleanAnswer hasFreeformSupportAnswer = new BooleanAnswer();
332 BooleanAnswer isOverridingFreeformHackAnswer = new BooleanAnswer();
333 when(U.hasFreeformSupport(context)).thenAnswer(hasFreeformSupportAnswer);
334 when(U.isOverridingFreeformHack(context, true)).thenAnswer(isOverridingFreeformHackAnswer);
335 // Case 1, all return true
336 hasFreeformSupportAnswer.answer = true;
337 isOverridingFreeformHackAnswer.answer = true;
338 assertFalse(U.canBootToFreeform(context));
339 // Case 2, true, false
340 hasFreeformSupportAnswer.answer = true;
341 isOverridingFreeformHackAnswer.answer = false;
342 assertTrue(U.canBootToFreeform(context));
343 // Case 3, false, true
344 hasFreeformSupportAnswer.answer = false;
345 isOverridingFreeformHackAnswer.answer = true;
346 assertFalse(U.canBootToFreeform(context));
347 // Case 4, false, false
348 hasFreeformSupportAnswer.answer = false;
349 isOverridingFreeformHackAnswer.answer = false;
350 assertFalse(U.canBootToFreeform(context));
354 public void testIsSamsungDevice() {
355 ShadowBuild.setManufacturer("Samsung");
356 assertTrue(U.isSamsungDevice());
357 ShadowBuild.setManufacturer("samsung");
358 assertTrue(U.isSamsungDevice());
359 ShadowBuild.setManufacturer("UnSamsung");
360 assertFalse(U.isSamsungDevice());
364 public void testGetBackgroundTint() {
365 SharedPreferences prefs = U.getSharedPreferences(context);
367 .putInt(PREF_BACKGROUND_TINT, Color.GREEN)
368 .putBoolean(PREF_SHOW_BACKGROUND, false)
370 // If the SHOW_BACKGROUND is false, it use transparent to replace origin tint.
371 assertEquals(Color.TRANSPARENT, U.getBackgroundTint(context));
373 .putInt(PREF_BACKGROUND_TINT, Color.GREEN)
375 assertEquals(Color.GREEN, U.getBackgroundTint(context));
376 prefs.edit().remove(PREF_BACKGROUND_TINT).apply();
378 context.getResources().getInteger(R.integer.tb_translucent_gray),
379 U.getBackgroundTint(context)
384 public void testAccentColor() {
385 SharedPreferences prefs = U.getSharedPreferences(context);
386 prefs.edit().remove(PREF_ACCENT_COLOR).apply();
388 context.getResources().getInteger(R.integer.tb_translucent_white),
389 U.getAccentColor(context)
391 prefs.edit().putInt(PREF_ACCENT_COLOR, Color.GREEN).apply();
392 assertEquals(Color.GREEN, U.getAccentColor(context));
396 public void testCanDrawOverlaysWithMarshmallowAndAboveVersion() {
397 ShadowSettings.setCanDrawOverlays(true);
398 assertTrue(U.canDrawOverlays(context));
399 ShadowSettings.setCanDrawOverlays(false);
400 assertFalse(U.canDrawOverlays(context));
405 public void testCanDrawOverlaysWithMarshmallowBelowVersion() {
406 assertTrue(U.canDrawOverlays(context));
410 public void testIsGame() {
411 // We only test for un-support launching games fullscreen, because of
412 // we don't have a good method to test code with ApplicationInfo.
413 SharedPreferences prefs = U.getSharedPreferences(context);
414 prefs.edit().putBoolean(PREF_LAUNCH_GAMES_FULLSCREEN, false).apply();
415 assertFalse(U.isGame(context, context.getPackageName()));
416 prefs.edit().putBoolean(PREF_LAUNCH_GAMES_FULLSCREEN, true).apply();
417 assertFalse(U.isGame(context, context.getPackageName()));
418 assertFalse(U.isGame(context, context.getPackageName() + "un-exist-package"));
422 public void testGetActivityOptionsWithPAndAboveVersion() {
423 testGetActivityOptions(0, 5, 1);
428 public void testGetActivityOptionsWithPBelowVersion() {
429 testGetActivityOptions(-1, 2, -1);
432 private void testGetActivityOptions(int defaultStackId,
434 int stackIdWithoutBrokenApi) {
435 PowerMockito.spy(U.class);
436 BooleanAnswer hasBrokenSetLaunchBoundsApiAnswer = new BooleanAnswer();
437 BooleanAnswer isChromeOsAnswer = new BooleanAnswer();
438 when(U.hasBrokenSetLaunchBoundsApi()).thenAnswer(hasBrokenSetLaunchBoundsApiAnswer);
439 when(U.isChromeOs(context)).thenAnswer(isChromeOsAnswer);
440 boolean originFreeformHackActive = FreeformHackHelper.getInstance().isFreeformHackActive();
441 checkActivityOptionsStackIdForNonContextMenu(
442 context, null, false, defaultStackId
444 checkActivityOptionsStackIdForNonContextMenu(
445 context, ApplicationType.APP_PORTRAIT, false, 1
447 checkActivityOptionsStackIdForNonContextMenu(
448 context, ApplicationType.APP_PORTRAIT, true, freeformStackId
450 checkActivityOptionsStackIdForNonContextMenu(
451 context, ApplicationType.APP_LANDSCAPE, false, 1
453 checkActivityOptionsStackIdForNonContextMenu(
454 context, ApplicationType.APP_LANDSCAPE, true, freeformStackId
456 checkActivityOptionsStackIdForNonContextMenu(
457 context, ApplicationType.APP_FULLSCREEN, false, 1
459 checkActivityOptionsStackIdForNonContextMenu(
460 context, ApplicationType.FREEFORM_HACK, false, freeformStackId
462 FreeformHackHelper.getInstance().setFreeformHackActive(originFreeformHackActive);
463 hasBrokenSetLaunchBoundsApiAnswer.answer = true;
464 checkActivityOptionsStackIdForContextMenu(context, 1);
465 hasBrokenSetLaunchBoundsApiAnswer.answer = false;
466 isChromeOsAnswer.answer = false;
467 checkActivityOptionsStackIdForContextMenu(context, stackIdWithoutBrokenApi);
468 isChromeOsAnswer.answer = true;
469 checkActivityOptionsStackIdForContextMenu(context, -1);
472 private void checkActivityOptionsStackIdForContextMenu(Context context,
474 ActivityOptions options = U.getActivityOptions(context, ApplicationType.CONTEXT_MENU, null);
475 assertEquals(stackId, getActivityOptionsStackId(options));
478 private void checkActivityOptionsStackIdForNonContextMenu(Context context,
479 ApplicationType applicationType,
480 boolean isFreeformHackActive,
482 FreeformHackHelper.getInstance().setFreeformHackActive(isFreeformHackActive);
483 ActivityOptions options = U.getActivityOptions(context, applicationType, null);
484 assertEquals(stackId, getActivityOptionsStackId(options));
487 private int getActivityOptionsStackId(ActivityOptions options) {
489 if (U.getCurrentApiVersion() >= 28.0f) {
490 methodName = "getLaunchWindowingMode";
492 methodName = "getLaunchStackId";
494 return ReflectionHelpers.callInstanceMethod(options, methodName);
498 public void testIsChromeOs() {
499 PackageManager packageManager = context.getPackageManager();
500 ShadowPackageManager shadowPackageManager = Shadows.shadowOf(packageManager);
501 shadowPackageManager.setSystemFeature("org.chromium.arc", true);
502 assertTrue(U.isChromeOs(context));
503 shadowPackageManager.setSystemFeature("org.chromium.arc", false);
504 assertFalse(U.isChromeOs(context));
508 @Config(qualifiers = "sw720dp")
509 public void testGetBaseTaskbarSizeWithSW720dp() {
510 PowerMockito.spy(U.class);
511 BooleanAnswer isSystemTrayEnabledAnswer = new BooleanAnswer();
512 when(U.isSystemTrayEnabled(context)).thenAnswer(isSystemTrayEnabledAnswer);
513 isSystemTrayEnabledAnswer.answer = false;
514 // The only difference of the different screen size, is the initial taskbar size.
515 // So we only test the different in this test method.
516 float initialSize = context.getResources().getDimension(R.dimen.tb_base_size_start_plus_divider);
517 initialSize += context.getResources().getDimension(R.dimen.tb_base_size_collapse_button);
518 initialSize += context.getResources().getDimension(R.dimen.tb_dashboard_button_size);
519 assertEquals(Math.round(initialSize), U.getBaseTaskbarSize(context, null));
523 public void testGetBaseTaskbarSizeWithNormalDimension() {
524 PowerMockito.spy(U.class);
525 BooleanAnswer isSystemTrayEnabledAnswer = new BooleanAnswer();
526 when(U.isSystemTrayEnabled(context)).thenAnswer(isSystemTrayEnabledAnswer);
527 isSystemTrayEnabledAnswer.answer = false;
528 float initialSize = context.getResources().getDimension(R.dimen.tb_base_size_start_plus_divider);
529 initialSize += context.getResources().getDimension(R.dimen.tb_base_size_collapse_button);
530 assertEquals(Math.round(initialSize), U.getBaseTaskbarSize(context, null));
531 SharedPreferences prefs = U.getSharedPreferences(context);
532 prefs.edit().putBoolean(PREF_DASHBOARD, true).apply();
533 float dashboardButtonSize =
534 context.getResources().getDimension(R.dimen.tb_dashboard_button_size);
535 assertEquals(Math.round(initialSize + dashboardButtonSize), U.getBaseTaskbarSize(context, null));
536 prefs.edit().remove(PREF_DASHBOARD).apply();
537 float navbarButtonsMargin =
538 context.getResources().getDimension(R.dimen.tb_navbar_buttons_margin);
540 context.getResources().getDimension(R.dimen.tb_icon_size);
541 prefs.edit().putBoolean(PREF_BUTTON_BACK, true).apply();
543 Math.round(initialSize + navbarButtonsMargin + iconSize),
544 U.getBaseTaskbarSize(context, null)
546 prefs.edit().remove(PREF_BUTTON_BACK).apply();
547 prefs.edit().putBoolean(PREF_BUTTON_HOME, true).apply();
549 Math.round(initialSize + navbarButtonsMargin + iconSize),
550 U.getBaseTaskbarSize(context, null)
552 prefs.edit().remove(PREF_BUTTON_HOME).apply();
553 prefs.edit().putBoolean(PREF_BUTTON_RECENTS, true).apply();
555 Math.round(initialSize + navbarButtonsMargin + iconSize),
556 U.getBaseTaskbarSize(context, null)
558 prefs.edit().remove(PREF_BUTTON_RECENTS).apply();
559 isSystemTrayEnabledAnswer.answer = true;
560 float systemTraySize = context.getResources().getDimension(R.dimen.tb_systray_size);
561 assertEquals(Math.round(initialSize + systemTraySize), U.getBaseTaskbarSize(context, null));
565 public void testInitPrefsForBlissOS() {
566 PowerMockito.spy(U.class);
567 when(U.isBlissOs(any(Context.class))).thenReturn(true);
568 assertTrue(U.isBlissOs(context));
569 SharedPreferences prefs = U.getSharedPreferences(context);
570 assertFalse(prefs.getBoolean(PREF_BLISS_OS_PREFS, false));
571 U.initPrefs(context);
573 PREF_RECENTS_AMOUNT_RUNNING_APPS_ONLY,
574 prefs.getString(PREF_RECENTS_AMOUNT, "")
576 assertEquals("0", prefs.getString(PREF_REFRESH_FREQUENCY, ""));
577 assertEquals("2147483647", prefs.getString(PREF_MAX_NUM_OF_RECENTS, ""));
578 assertEquals("true", prefs.getString(PREF_SORT_ORDER, ""));
580 PREF_START_BUTTON_IMAGE_APP_LOGO,
581 prefs.getString(PREF_START_BUTTON_IMAGE, "")
583 assertTrue(prefs.getBoolean(PREF_BUTTON_BACK, false));
584 assertTrue(prefs.getBoolean(PREF_BUTTON_HOME, false));
585 assertTrue(prefs.getBoolean(PREF_BUTTON_RECENTS, false));
586 assertTrue(prefs.getBoolean(PREF_AUTO_HIDE_NAVBAR, false));
587 assertFalse(prefs.getBoolean(PREF_SHORTCUT_ICON, true));
588 assertTrue(prefs.getBoolean(PREF_BLISS_OS_PREFS, false));
589 prefs.edit().putBoolean(PREF_BLISS_OS_PREFS, false);
593 public void testInitPrefsForNormalWithCanEnableFreeformAndHackOverrideFalse() {
594 PowerMockito.spy(U.class);
595 when(U.canEnableFreeform()).thenReturn(true);
596 SharedPreferences prefs = U.getSharedPreferences(context);
597 prefs.edit().putBoolean(PREF_FREEFORM_HACK_OVERRIDE, false).apply();
598 U.initPrefs(context);
600 U.hasFreeformSupport(context) && !U.isSamsungDevice(),
601 prefs.getBoolean(PREF_FREEFORM_HACK, false)
603 assertFalse(prefs.getBoolean(PREF_SAVE_WINDOW_SIZES, true));
604 assertTrue(prefs.getBoolean(PREF_FREEFORM_HACK_OVERRIDE, false));
608 public void testInitPrefsForNormalWithCanEnableFreeformAndHackOverrideTrueButNoSupport() {
609 PowerMockito.spy(U.class);
610 when(U.canEnableFreeform()).thenReturn(true);
611 SharedPreferences prefs = U.getSharedPreferences(context);
612 prefs.edit().putBoolean(PREF_FREEFORM_HACK_OVERRIDE, true).apply();
613 when(U.hasFreeformSupport(context)).thenReturn(false);
614 U.initPrefs(context);
615 assertFalse(prefs.getBoolean(PREF_FREEFORM_HACK, false));
619 public void testInitPrefsForNormalWithCantEnableFreeform() {
620 PowerMockito.spy(U.class);
621 when(U.canEnableFreeform()).thenReturn(false);
622 SharedPreferences prefs = U.getSharedPreferences(context);
623 U.initPrefs(context);
624 assertFalse(prefs.getBoolean(PREF_FREEFORM_HACK, false));
626 .putBoolean(PREF_FREEFORM_HACK, false)
627 .putBoolean(PREF_SHOW_FREEFORM_DISABLED_MESSAGE, false)
629 U.initPrefs(context);
630 assertFalse(prefs.getBoolean(PREF_SHOW_FREEFORM_DISABLED_MESSAGE, false));
632 .putBoolean(PREF_FREEFORM_HACK, true)
633 .putBoolean(PREF_SHOW_FREEFORM_DISABLED_MESSAGE, false)
635 U.initPrefs(context);
636 assertTrue(prefs.getBoolean(PREF_SHOW_FREEFORM_DISABLED_MESSAGE, false));
638 .putBoolean(PREF_FREEFORM_HACK, false)
639 .putBoolean(PREF_SHOW_FREEFORM_DISABLED_MESSAGE, true)
641 U.initPrefs(context);
642 assertTrue(prefs.getBoolean(PREF_SHOW_FREEFORM_DISABLED_MESSAGE, false));
644 .putBoolean(PREF_FREEFORM_HACK, true)
645 .putBoolean(PREF_SHOW_FREEFORM_DISABLED_MESSAGE, true)
647 U.initPrefs(context);
648 assertTrue(prefs.getBoolean(PREF_SHOW_FREEFORM_DISABLED_MESSAGE, false));
652 public void testIsOverridingFreeformHackForPAndAboveVersion() {
653 PowerMockito.spy(U.class);
654 when(U.isChromeOs(context)).thenReturn(false);
656 assertFalse(U.isOverridingFreeformHack(context, true));
657 SharedPreferences prefs = U.getSharedPreferences(context);
658 prefs.edit().putBoolean(PREF_FREEFORM_HACK, true).apply();
659 assertTrue(U.isOverridingFreeformHack(context, true));
660 prefs.edit().remove(PREF_FREEFORM_HACK).apply();
662 // Don't check preferences
663 assertTrue(U.isOverridingFreeformHack(context, false));
668 public void testIsOverridingFreeformHackForPBelowVersion() {
669 PowerMockito.spy(U.class);
670 when(U.isChromeOs(context)).thenReturn(false);
672 assertFalse(U.isOverridingFreeformHack(context, true));
673 SharedPreferences prefs = U.getSharedPreferences(context);
674 prefs.edit().putBoolean(PREF_FREEFORM_HACK, true).apply();
675 assertFalse(U.isOverridingFreeformHack(context, true));
676 prefs.edit().remove(PREF_FREEFORM_HACK).apply();
678 // Don't check preferences
679 assertFalse(U.isOverridingFreeformHack(context, false));
683 public void testIsOverridingFreeformHackForChromeOS() {
684 PowerMockito.spy(U.class);
685 when(U.isChromeOs(context)).thenReturn(true);
687 assertFalse(U.isOverridingFreeformHack(context, true));
688 SharedPreferences prefs = U.getSharedPreferences(context);
689 prefs.edit().putBoolean(PREF_FREEFORM_HACK, true).apply();
690 // The default PREF_CHROME_OS_CONTEXT_MENU_FIX is true
691 assertTrue(U.isOverridingFreeformHack(context, true));
692 prefs.edit().putBoolean(PREF_CHROME_OS_CONTEXT_MENU_FIX, false).apply();
693 assertFalse(U.isOverridingFreeformHack(context, true));
694 prefs.edit().putBoolean(PREF_CHROME_OS_CONTEXT_MENU_FIX, true).apply();
695 assertTrue(U.isOverridingFreeformHack(context, true));
696 prefs.edit().remove(PREF_FREEFORM_HACK).apply();
697 prefs.edit().remove(PREF_CHROME_OS_CONTEXT_MENU_FIX).apply();
699 // Don't check preferences
700 assertTrue(U.isOverridingFreeformHack(context, false));
701 prefs.edit().putBoolean(PREF_CHROME_OS_CONTEXT_MENU_FIX, false).apply();
702 assertFalse(U.isOverridingFreeformHack(context, false));
703 prefs.edit().putBoolean(PREF_CHROME_OS_CONTEXT_MENU_FIX, true).apply();
704 assertTrue(U.isOverridingFreeformHack(context, false));
705 prefs.edit().remove(PREF_CHROME_OS_CONTEXT_MENU_FIX).apply();
710 public void testHasBrokenSetLaunchBoundsApiForApi25() {
711 assertFalse(U.hasBrokenSetLaunchBoundsApi());
716 public void testHasBrokenSetLaunchBoundsApiForApi26() throws Exception {
717 testHasBrokenSetLaunchBoundsApiWithValidApiVersion();
722 public void testHasBrokenSetLaunchBoundsApiForApi27() throws Exception {
723 testHasBrokenSetLaunchBoundsApiWithValidApiVersion();
724 testHasBrokenSetLaunchBoundsApiWithValidApiVersion();
729 public void testHasBrokenSetLaunchBoundsApiForApi28() {
730 assertFalse(U.hasBrokenSetLaunchBoundsApi());
733 private void testHasBrokenSetLaunchBoundsApiWithValidApiVersion() throws Exception {
734 PowerMockito.spy(U.class);
735 BooleanAnswer isSamsungDeviceAnswer = new BooleanAnswer();
736 BooleanAnswer isNvidiaDevice = new BooleanAnswer();
737 when(U.isSamsungDevice()).thenAnswer(isSamsungDeviceAnswer);
738 when(U.class, "isNvidiaDevice").thenAnswer(isNvidiaDevice);
739 isSamsungDeviceAnswer.answer = false;
740 isNvidiaDevice.answer = false;
741 assertTrue(U.hasBrokenSetLaunchBoundsApi());
742 isSamsungDeviceAnswer.answer = false;
743 isNvidiaDevice.answer = true;
744 assertFalse(U.hasBrokenSetLaunchBoundsApi());
745 isSamsungDeviceAnswer.answer = true;
746 isNvidiaDevice.answer = false;
747 assertFalse(U.hasBrokenSetLaunchBoundsApi());
748 isSamsungDeviceAnswer.answer = true;
749 isNvidiaDevice.answer = true;
750 assertFalse(U.hasBrokenSetLaunchBoundsApi());
754 public void testWrapContext() {
755 SharedPreferences prefs = U.getSharedPreferences(context);
756 prefs.edit().putString(PREF_THEME, "light").apply();
757 Context newContext = U.wrapContext(context);
758 Integer themeResource = ReflectionHelpers.getField(newContext, "mThemeResource");
759 assertNotNull(themeResource);
760 assertEquals(R.style.Taskbar, (int) themeResource);
761 prefs.edit().putString(PREF_THEME, "dark").apply();
762 newContext = U.wrapContext(context);
763 themeResource = ReflectionHelpers.getField(newContext, "mThemeResource");
764 assertNotNull(themeResource);
765 assertEquals(R.style.Taskbar_Dark, (int) themeResource);
766 prefs.edit().putString(PREF_THEME, "non-support").apply();
767 newContext = U.wrapContext(context);
768 assertTrue(newContext instanceof ContextThemeWrapper);
769 prefs.edit().remove(PREF_THEME).apply();
770 newContext = U.wrapContext(context);
771 themeResource = ReflectionHelpers.getField(newContext, "mThemeResource");
772 assertNotNull(themeResource);
773 assertEquals(R.style.Taskbar, (int) themeResource);
777 public void testEnableFreeformModeShortcut() {
778 PowerMockito.spy(U.class);
779 BooleanAnswer canEnableFreeformAnswer = new BooleanAnswer();
780 BooleanAnswer isOverridingFreeformHackAnswer = new BooleanAnswer();
781 BooleanAnswer isChromeOsAnswer = new BooleanAnswer();
782 when(U.canEnableFreeform()).thenAnswer(canEnableFreeformAnswer);
783 when(U.isOverridingFreeformHack(context, false))
784 .thenAnswer(isOverridingFreeformHackAnswer);
785 when(U.isChromeOs(context)).thenAnswer(isChromeOsAnswer);
787 canEnableFreeformAnswer.answer = false;
788 isOverridingFreeformHackAnswer.answer = false;
789 isChromeOsAnswer.answer = false;
790 assertFalse(U.enableFreeformModeShortcut(context));
792 canEnableFreeformAnswer.answer = false;
793 isOverridingFreeformHackAnswer.answer = false;
794 isChromeOsAnswer.answer = true;
795 assertFalse(U.enableFreeformModeShortcut(context));
797 canEnableFreeformAnswer.answer = false;
798 isOverridingFreeformHackAnswer.answer = true;
799 isChromeOsAnswer.answer = false;
800 assertFalse(U.enableFreeformModeShortcut(context));
802 canEnableFreeformAnswer.answer = false;
803 isOverridingFreeformHackAnswer.answer = true;
804 isChromeOsAnswer.answer = true;
805 assertFalse(U.enableFreeformModeShortcut(context));
807 canEnableFreeformAnswer.answer = true;
808 isOverridingFreeformHackAnswer.answer = false;
809 isChromeOsAnswer.answer = false;
810 assertTrue(U.enableFreeformModeShortcut(context));
812 canEnableFreeformAnswer.answer = true;
813 isOverridingFreeformHackAnswer.answer = false;
814 isChromeOsAnswer.answer = true;
815 assertFalse(U.enableFreeformModeShortcut(context));
817 canEnableFreeformAnswer.answer = true;
818 isOverridingFreeformHackAnswer.answer = true;
819 isChromeOsAnswer.answer = false;
820 assertFalse(U.enableFreeformModeShortcut(context));
822 canEnableFreeformAnswer.answer = true;
823 isOverridingFreeformHackAnswer.answer = true;
824 isChromeOsAnswer.answer = true;
825 assertFalse(U.enableFreeformModeShortcut(context));
830 public void testGetOverlayTypeForOAndAboveVersion() {
831 assertEquals(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY, U.getOverlayType());
836 public void testGetOverlayTypeForOBelowVersion() {
837 assertEquals(WindowManager.LayoutParams.TYPE_PHONE, U.getOverlayType());
841 public void testGetDefaultStartButtonImage() {
842 SharedPreferences prefs = U.getSharedPreferences(context);
843 prefs.edit().putBoolean(PREF_APP_DRAWER_ICON, true).apply();
844 assertEquals(PREF_START_BUTTON_IMAGE_APP_LOGO, U.getDefaultStartButtonImage(context));
845 prefs.edit().putBoolean(PREF_APP_DRAWER_ICON, false).apply();
846 assertEquals(PREF_START_BUTTON_IMAGE_DEFAULT, U.getDefaultStartButtonImage(context));
847 prefs.edit().remove(PREF_APP_DRAWER_ICON).apply();
848 assertEquals(PREF_START_BUTTON_IMAGE_DEFAULT, U.getDefaultStartButtonImage(context));
852 public void testIsDesktopIconEnabled() throws Exception {
853 PowerMockito.spy(U.class);
854 BooleanAnswer canBootToFreeformAnswer = new BooleanAnswer();
855 BooleanAnswer shouldLaunchTouchAbsorberAnswer = new BooleanAnswer();
856 when(U.class, "canBootToFreeform", context, false)
857 .thenAnswer(canBootToFreeformAnswer);
858 when(U.class, "shouldLaunchTouchAbsorber", context)
859 .thenAnswer(shouldLaunchTouchAbsorberAnswer);
861 canBootToFreeformAnswer.answer = false;
862 shouldLaunchTouchAbsorberAnswer.answer = false;
863 assertTrue(U.isDesktopIconsEnabled(context));
865 canBootToFreeformAnswer.answer = false;
866 shouldLaunchTouchAbsorberAnswer.answer = true;
867 assertFalse(U.isDesktopIconsEnabled(context));
869 canBootToFreeformAnswer.answer = true;
870 shouldLaunchTouchAbsorberAnswer.answer = false;
871 assertFalse(U.isDesktopIconsEnabled(context));
873 canBootToFreeformAnswer.answer = true;
874 shouldLaunchTouchAbsorberAnswer.answer = true;
875 assertFalse(U.isDesktopIconsEnabled(context));
880 public void testIsSystemTrayEnabledForMBelowVersion() {
881 SharedPreferences prefs = U.getSharedPreferences(context);
883 .putBoolean(PREF_SYS_TRAY, true)
884 .putBoolean(PREF_FULL_LENGTH, true)
886 assertFalse(U.isSystemTrayEnabled(context));
887 prefs.edit().remove(PREF_SYS_TRAY).remove(PREF_FULL_LENGTH).apply();
891 public void testIsSystemTrayEnabledForMAndAboveVersion() {
892 SharedPreferences prefs = U.getSharedPreferences(context);
893 assertFalse(U.isSystemTrayEnabled(context));
894 prefs.edit().putBoolean(PREF_SYS_TRAY, true).apply();
895 assertTrue(U.isSystemTrayEnabled(context));
896 prefs.edit().putBoolean(PREF_FULL_LENGTH, false).apply();
897 assertFalse(U.isSystemTrayEnabled(context));
898 prefs.edit().putBoolean(PREF_FULL_LENGTH, true).apply();
899 assertTrue(U.isSystemTrayEnabled(context));
901 .putString(PREF_POSITION, POSITION_BOTTOM_VERTICAL_LEFT)
902 .putBoolean(PREF_ANCHOR, false)
904 assertFalse(U.isSystemTrayEnabled(context));
905 prefs.edit().remove(PREF_POSITION).remove(PREF_ANCHOR).apply();
909 public void testApplyDisplayCutoutModeToWithPAndAboveVersion() {
910 WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams();
911 assertTrue(U.applyDisplayCutoutModeTo(layoutParams));
913 LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES,
914 layoutParams.layoutInDisplayCutoutMode
920 public void testApplyDisplayCutoutModeToWithBelowVersion() {
921 WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams();
922 assertFalse(U.applyDisplayCutoutModeTo(layoutParams));
926 public void testIsDesktopModeActive() {
927 PowerMockito.spy(U.class);
928 BooleanAnswer isDesktopModeSupportedAnswer = new BooleanAnswer();
929 IntAnswer getExternalDisplayIdAnswer = new IntAnswer();
930 BooleanAnswer hasFreeformSupportAnswer = new BooleanAnswer();
931 when(U.isDesktopModeSupported(context)).thenAnswer(isDesktopModeSupportedAnswer);
932 when(U.getExternalDisplayID(context)).thenAnswer(getExternalDisplayIdAnswer);
933 when(U.hasFreeformSupport(context)).thenAnswer(hasFreeformSupportAnswer);
935 isDesktopModeSupportedAnswer.answer = false;
936 assertFalse(U.isDesktopModeActive(context));
938 isDesktopModeSupportedAnswer.answer = true;
939 Settings.Global.putInt(
940 context.getContentResolver(),
941 "force_desktop_mode_on_external_displays",
944 assertFalse(U.isDesktopModeActive(context));
945 Settings.Global.putInt(
946 context.getContentResolver(),
947 "force_desktop_mode_on_external_displays",
950 assertFalse(U.isDesktopModeActive(context));
951 getExternalDisplayIdAnswer.answer = 1;
952 assertFalse(U.isDesktopModeActive(context));
953 hasFreeformSupportAnswer.answer = true;
954 assertTrue(U.isDesktopModeActive(context));
955 Settings.Global.putInt(
956 context.getContentResolver(),
957 "force_desktop_mode_on_external_displays",
963 public void testSendBroadcast() {
964 TestBroadcastReceiver receiver = new TestBroadcastReceiver();
965 IntentFilter filter = new IntentFilter(TestBroadcastReceiver.ACTION);
966 LocalBroadcastManager.getInstance(context).registerReceiver(receiver, filter);
967 U.sendBroadcast(context, TestBroadcastReceiver.ACTION);
968 assertTrue(receiver.onReceived);
969 receiver.onReceived = false;
970 U.sendBroadcast(context, new Intent(TestBroadcastReceiver.ACTION));
971 assertTrue(receiver.onReceived);
974 private static final class TestBroadcastReceiver extends BroadcastReceiver {
975 private static final String ACTION = "test-broadcast-receiver-action";
976 private boolean onReceived;
979 public void onReceive(Context context, Intent intent) {
980 if (intent == null || !ACTION.equals(intent.getAction())) {