OSDN Git Service

Fix expanding whitespace on certain configurations
[android-x86/packages-apps-Taskbar.git] / app / src / main / java / com / farmerbb / taskbar / service / TaskbarService.java
1 /* Copyright 2016 Braden Farmer
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15
16 package com.farmerbb.taskbar.service;
17
18 import android.accessibilityservice.AccessibilityService;
19 import android.annotation.SuppressLint;
20 import android.annotation.TargetApi;
21 import android.app.ActivityManager;
22 import android.app.AlarmManager;
23 import android.app.Service;
24 import android.app.usage.UsageEvents;
25 import android.app.usage.UsageStats;
26 import android.app.usage.UsageStatsManager;
27 import android.content.BroadcastReceiver;
28 import android.content.Context;
29 import android.content.Intent;
30 import android.content.IntentFilter;
31 import android.content.SharedPreferences;
32 import android.content.pm.LauncherActivityInfo;
33 import android.content.pm.LauncherApps;
34 import android.content.pm.PackageManager;
35 import android.content.pm.ResolveInfo;
36 import android.content.res.Configuration;
37 import android.graphics.Color;
38 import android.graphics.PixelFormat;
39 import android.graphics.Point;
40 import android.graphics.Rect;
41 import android.graphics.Typeface;
42 import android.hardware.display.DisplayManager;
43 import android.os.Build;
44 import android.os.Handler;
45 import android.os.IBinder;
46 import android.os.SystemClock;
47 import android.os.UserHandle;
48 import android.os.UserManager;
49 import android.provider.Settings;
50 import android.support.v4.content.ContextCompat;
51 import android.support.v4.graphics.ColorUtils;
52 import android.util.DisplayMetrics;
53 import android.view.ContextThemeWrapper;
54 import android.view.Display;
55 import android.view.Gravity;
56 import android.view.LayoutInflater;
57 import android.view.MotionEvent;
58 import android.view.PointerIcon;
59 import android.view.View;
60 import android.view.ViewGroup;
61 import android.view.WindowManager;
62 import android.widget.Button;
63 import android.widget.FrameLayout;
64 import android.widget.ImageView;
65
66 import java.util.ArrayList;
67 import java.util.Collections;
68 import java.util.List;
69
70 import android.support.v4.content.LocalBroadcastManager;
71 import android.widget.LinearLayout;
72 import android.widget.Space;
73
74 import com.farmerbb.taskbar.BuildConfig;
75 import com.farmerbb.taskbar.MainActivity;
76 import com.farmerbb.taskbar.R;
77 import com.farmerbb.taskbar.activity.ContextMenuActivity;
78 import com.farmerbb.taskbar.activity.dark.ContextMenuActivityDark;
79 import com.farmerbb.taskbar.activity.HomeActivity;
80 import com.farmerbb.taskbar.activity.InvisibleActivityFreeform;
81 import com.farmerbb.taskbar.util.AppEntry;
82 import com.farmerbb.taskbar.util.ApplicationType;
83 import com.farmerbb.taskbar.util.FreeformHackHelper;
84 import com.farmerbb.taskbar.util.IconCache;
85 import com.farmerbb.taskbar.util.LauncherHelper;
86 import com.farmerbb.taskbar.util.PinnedBlockedApps;
87 import com.farmerbb.taskbar.util.StartMenuHelper;
88 import com.farmerbb.taskbar.util.U;
89
90 public class TaskbarService extends Service {
91
92     private WindowManager windowManager;
93     private LinearLayout layout;
94     private ImageView startButton;
95     private LinearLayout taskbar;
96     private FrameLayout scrollView;
97     private Button button;
98     private Space space;
99     private FrameLayout dashboardButton;
100     private LinearLayout navbarButtons;
101
102     private Handler handler;
103     private Handler handler2;
104     private Thread thread;
105     private Thread thread2;
106
107     private boolean isShowingRecents = true;
108     private boolean shouldRefreshRecents = true;
109     private boolean taskbarShownTemporarily = false;
110     private boolean taskbarHiddenTemporarily = false;
111     private boolean isRefreshingRecents = false;
112     private boolean isFirstStart = true;
113
114     private boolean startThread2 = false;
115     private boolean stopThread2 = false;
116
117     private int refreshInterval = -1;
118     private long searchInterval = -1;
119     private String sortOrder = "false";
120     private boolean runningAppsOnly = false;
121
122     private int layoutId = R.layout.taskbar_left;
123     private int currentTaskbarPosition = 0;
124     private boolean showHideAutomagically = false;
125     private boolean positionIsVertical = false;
126     private boolean dashboardEnabled = false;
127     private boolean navbarButtonsEnabled = false;
128
129     private List<String> currentTaskbarIds = new ArrayList<>();
130     private int numOfPinnedApps = -1;
131
132     private View.OnClickListener ocl = view -> {
133         Intent intent = new Intent("com.farmerbb.taskbar.TOGGLE_START_MENU");
134         LocalBroadcastManager.getInstance(TaskbarService.this).sendBroadcast(intent);
135     };
136
137     private BroadcastReceiver showReceiver = new BroadcastReceiver() {
138         @Override
139         public void onReceive(Context context, Intent intent) {
140             showTaskbar(true);
141         }
142     };
143
144     private BroadcastReceiver hideReceiver = new BroadcastReceiver() {
145         @Override
146         public void onReceive(Context context, Intent intent) {
147             hideTaskbar(true);
148         }
149     };
150
151     private BroadcastReceiver tempShowReceiver = new BroadcastReceiver() {
152         @Override
153         public void onReceive(Context context, Intent intent) {
154             tempShowTaskbar();
155         }
156     };
157
158     private BroadcastReceiver tempHideReceiver = new BroadcastReceiver() {
159         @Override
160         public void onReceive(Context context, Intent intent) {
161             tempHideTaskbar(false);
162         }
163     };
164
165     @Override
166     public IBinder onBind(Intent intent) {
167         return null;
168     }
169
170     @Override
171     public int onStartCommand(Intent intent, int flags, int startId) {
172         return START_STICKY;
173     }
174
175     @TargetApi(Build.VERSION_CODES.M)
176     @Override
177     public void onCreate() {
178         super.onCreate();
179
180         SharedPreferences pref = U.getSharedPreferences(this);
181         if(pref.getBoolean("taskbar_active", false) || LauncherHelper.getInstance().isOnHomeScreen()) {
182             if(Build.VERSION.SDK_INT < Build.VERSION_CODES.M || Settings.canDrawOverlays(this))
183                 drawTaskbar();
184             else {
185                 pref.edit().putBoolean("taskbar_active", false).apply();
186
187                 stopSelf();
188             }
189         } else stopSelf();
190     }
191
192     @SuppressLint("RtlHardcoded")
193     private void drawTaskbar() {
194         IconCache.getInstance(this).clearCache();
195
196         // Initialize layout params
197         windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
198         U.setCachedRotation(windowManager.getDefaultDisplay().getRotation());
199
200         final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
201                 WindowManager.LayoutParams.WRAP_CONTENT,
202                 WindowManager.LayoutParams.WRAP_CONTENT,
203                 WindowManager.LayoutParams.TYPE_PHONE,
204                 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
205                 PixelFormat.TRANSLUCENT);
206
207         // Determine where to show the taskbar on screen
208         switch(U.getTaskbarPosition(this)) {
209             case "bottom_left":
210                 layoutId = R.layout.taskbar_left;
211                 params.gravity = Gravity.BOTTOM | Gravity.LEFT;
212                 positionIsVertical = false;
213                 break;
214             case "bottom_vertical_left":
215                 layoutId = R.layout.taskbar_vertical;
216                 params.gravity = Gravity.BOTTOM | Gravity.LEFT;
217                 positionIsVertical = true;
218                 break;
219             case "bottom_right":
220                 layoutId = R.layout.taskbar_right;
221                 params.gravity = Gravity.BOTTOM | Gravity.RIGHT;
222                 positionIsVertical = false;
223                 break;
224             case "bottom_vertical_right":
225                 layoutId = R.layout.taskbar_vertical;
226                 params.gravity = Gravity.BOTTOM | Gravity.RIGHT;
227                 positionIsVertical = true;
228                 break;
229             case "top_left":
230                 layoutId = R.layout.taskbar_left;
231                 params.gravity = Gravity.TOP | Gravity.LEFT;
232                 positionIsVertical = false;
233                 break;
234             case "top_vertical_left":
235                 layoutId = R.layout.taskbar_top_vertical;
236                 params.gravity = Gravity.TOP | Gravity.LEFT;
237                 positionIsVertical = true;
238                 break;
239             case "top_right":
240                 layoutId = R.layout.taskbar_right;
241                 params.gravity = Gravity.TOP | Gravity.RIGHT;
242                 positionIsVertical = false;
243                 break;
244             case "top_vertical_right":
245                 layoutId = R.layout.taskbar_top_vertical;
246                 params.gravity = Gravity.TOP | Gravity.RIGHT;
247                 positionIsVertical = true;
248                 break;
249         }
250
251         // Initialize views
252         int theme = 0;
253
254         SharedPreferences pref = U.getSharedPreferences(this);
255         switch(pref.getString("theme", "light")) {
256             case "light":
257                 theme = R.style.AppTheme;
258                 break;
259             case "dark":
260                 theme = R.style.AppTheme_Dark;
261                 break;
262         }
263
264         boolean altButtonConfig = pref.getBoolean("alt_button_config", false);
265
266         ContextThemeWrapper wrapper = new ContextThemeWrapper(this, theme);
267         layout = (LinearLayout) LayoutInflater.from(wrapper).inflate(layoutId, null);
268         taskbar = (LinearLayout) layout.findViewById(R.id.taskbar);
269         scrollView = (FrameLayout) layout.findViewById(R.id.taskbar_scrollview);
270
271         if(altButtonConfig) {
272             space = (Space) layout.findViewById(R.id.space_alt);
273             layout.findViewById(R.id.space).setVisibility(View.GONE);
274         } else {
275             space = (Space) layout.findViewById(R.id.space);
276             layout.findViewById(R.id.space_alt).setVisibility(View.GONE);
277         }
278
279         space.setOnClickListener(v -> toggleTaskbar());
280
281         startButton = (ImageView) layout.findViewById(R.id.start_button);
282         int padding;
283
284         if(pref.getBoolean("app_drawer_icon", false)) {
285             startButton.setImageDrawable(ContextCompat.getDrawable(this, R.mipmap.ic_launcher));
286             padding = getResources().getDimensionPixelSize(R.dimen.app_drawer_icon_padding_alt);
287         } else {
288             startButton.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.all_apps_button_icon));
289             padding = getResources().getDimensionPixelSize(R.dimen.app_drawer_icon_padding);
290         }
291
292         startButton.setPadding(padding, padding, padding, padding);
293         startButton.setOnClickListener(ocl);
294         startButton.setOnLongClickListener(view -> {
295             openContextMenu();
296             return true;
297         });
298
299         startButton.setOnGenericMotionListener((view, motionEvent) -> {
300             if(motionEvent.getAction() == MotionEvent.ACTION_BUTTON_PRESS
301                     && motionEvent.getButtonState() == MotionEvent.BUTTON_SECONDARY)
302                 openContextMenu();
303
304             return false;
305         });
306
307         refreshInterval = (int) (Float.parseFloat(pref.getString("refresh_frequency", "2")) * 1000);
308         if(refreshInterval == 0)
309             refreshInterval = 100;
310
311         sortOrder = pref.getString("sort_order", "false");
312         runningAppsOnly = pref.getString("recents_amount", "past_day").equals("running_apps_only");
313
314         switch(pref.getString("recents_amount", "past_day")) {
315             case "past_day":
316                 searchInterval = System.currentTimeMillis() - AlarmManager.INTERVAL_DAY;
317                 break;
318             case "app_start":
319                 long oneDayAgo = System.currentTimeMillis() - AlarmManager.INTERVAL_DAY;
320                 long appStartTime = pref.getLong("time_of_service_start", System.currentTimeMillis());
321                 long deviceStartTime = System.currentTimeMillis() - SystemClock.elapsedRealtime();
322                 long startTime = deviceStartTime > appStartTime ? deviceStartTime : appStartTime;
323
324                 searchInterval = startTime > oneDayAgo ? startTime : oneDayAgo;
325                 break;
326         }
327
328         Intent intent = new Intent("com.farmerbb.taskbar.HIDE_START_MENU");
329         LocalBroadcastManager.getInstance(TaskbarService.this).sendBroadcast(intent);
330
331         if(altButtonConfig) {
332             button = (Button) layout.findViewById(R.id.hide_taskbar_button_alt);
333             layout.findViewById(R.id.hide_taskbar_button).setVisibility(View.GONE);
334         } else {
335             button = (Button) layout.findViewById(R.id.hide_taskbar_button);
336             layout.findViewById(R.id.hide_taskbar_button_alt).setVisibility(View.GONE);
337         }
338
339         try {
340             button.setTypeface(Typeface.createFromFile("/system/fonts/Roboto-Regular.ttf"));
341         } catch (RuntimeException e) { /* Gracefully fail */ }
342
343         updateButton(false);
344         button.setOnClickListener(v -> toggleTaskbar());
345
346         LinearLayout buttonLayout = (LinearLayout) layout.findViewById(altButtonConfig
347                 ? R.id.hide_taskbar_button_layout_alt
348                 : R.id.hide_taskbar_button_layout);
349         if(buttonLayout != null) buttonLayout.setOnClickListener(v -> toggleTaskbar());
350
351         LinearLayout buttonLayoutToHide = (LinearLayout) layout.findViewById(altButtonConfig
352                 ? R.id.hide_taskbar_button_layout
353                 : R.id.hide_taskbar_button_layout_alt);
354         if(buttonLayoutToHide != null) buttonLayoutToHide.setVisibility(View.GONE);
355
356         int backgroundTint = U.getBackgroundTint(this);
357         int accentColor = U.getAccentColor(this);
358
359         dashboardButton = (FrameLayout) layout.findViewById(R.id.dashboard_button);
360         navbarButtons = (LinearLayout) layout.findViewById(R.id.navbar_buttons);
361
362         dashboardEnabled = pref.getBoolean("dashboard", false);
363         if(dashboardEnabled) {
364             layout.findViewById(R.id.square1).setBackgroundColor(accentColor);
365             layout.findViewById(R.id.square2).setBackgroundColor(accentColor);
366             layout.findViewById(R.id.square3).setBackgroundColor(accentColor);
367             layout.findViewById(R.id.square4).setBackgroundColor(accentColor);
368             layout.findViewById(R.id.square5).setBackgroundColor(accentColor);
369             layout.findViewById(R.id.square6).setBackgroundColor(accentColor);
370
371             dashboardButton.setOnClickListener(v -> LocalBroadcastManager.getInstance(TaskbarService.this).sendBroadcast(new Intent("com.farmerbb.taskbar.TOGGLE_DASHBOARD")));
372         } else
373             dashboardButton.setVisibility(View.GONE);
374
375         if(pref.getBoolean("button_back", false)) {
376             navbarButtonsEnabled = true;
377
378             ImageView backButton = (ImageView) layout.findViewById(R.id.button_back);
379             backButton.setVisibility(View.VISIBLE);
380             backButton.setOnClickListener(v -> {
381                 U.sendAccessibilityAction(this, AccessibilityService.GLOBAL_ACTION_BACK);
382                 if(pref.getBoolean("hide_taskbar", true) && !FreeformHackHelper.getInstance().isInFreeformWorkspace())
383                     hideTaskbar(true);
384             });
385         }
386
387         if(pref.getBoolean("button_home", false)) {
388             navbarButtonsEnabled = true;
389
390             ImageView homeButton = (ImageView) layout.findViewById(R.id.button_home);
391             homeButton.setVisibility(View.VISIBLE);
392             homeButton.setOnClickListener(v -> {
393                 U.sendAccessibilityAction(this, AccessibilityService.GLOBAL_ACTION_HOME);
394                 if(pref.getBoolean("hide_taskbar", true) && !FreeformHackHelper.getInstance().isInFreeformWorkspace())
395                     hideTaskbar(true);
396             });
397         }
398
399         if(pref.getBoolean("button_recents", false)) {
400             navbarButtonsEnabled = true;
401
402             ImageView recentsButton = (ImageView) layout.findViewById(R.id.button_recents);
403             recentsButton.setVisibility(View.VISIBLE);
404             recentsButton.setOnClickListener(v -> {
405                 U.sendAccessibilityAction(this, AccessibilityService.GLOBAL_ACTION_RECENTS);
406                 if(pref.getBoolean("hide_taskbar", true) && !FreeformHackHelper.getInstance().isInFreeformWorkspace())
407                     hideTaskbar(true);
408             });
409
410             if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
411                 recentsButton.setOnLongClickListener(v -> {
412                     U.sendAccessibilityAction(this, AccessibilityService.GLOBAL_ACTION_TOGGLE_SPLIT_SCREEN);
413                     if(pref.getBoolean("hide_taskbar", true) && !FreeformHackHelper.getInstance().isInFreeformWorkspace())
414                         hideTaskbar(true);
415
416                     return true;
417                 });
418
419                 recentsButton.setOnGenericMotionListener((view13, motionEvent) -> {
420                     if(motionEvent.getAction() == MotionEvent.ACTION_BUTTON_PRESS
421                             && motionEvent.getButtonState() == MotionEvent.BUTTON_SECONDARY) {
422                         U.sendAccessibilityAction(this, AccessibilityService.GLOBAL_ACTION_TOGGLE_SPLIT_SCREEN);
423                         if(pref.getBoolean("hide_taskbar", true) && !FreeformHackHelper.getInstance().isInFreeformWorkspace())
424                             hideTaskbar(true);
425                     }
426                     return true;
427                 });
428             }
429         }
430
431         if(!navbarButtonsEnabled)
432             navbarButtons.setVisibility(View.GONE);
433
434         layout.setBackgroundColor(backgroundTint);
435         layout.findViewById(R.id.divider).setBackgroundColor(accentColor);
436         button.setTextColor(accentColor);
437
438         if(isFirstStart && FreeformHackHelper.getInstance().isInFreeformWorkspace())
439             showTaskbar(false);
440         else if(!pref.getBoolean("collapsed", false) && pref.getBoolean("taskbar_active", false))
441             toggleTaskbar();
442
443         LocalBroadcastManager.getInstance(this).unregisterReceiver(showReceiver);
444         LocalBroadcastManager.getInstance(this).unregisterReceiver(hideReceiver);
445         LocalBroadcastManager.getInstance(this).unregisterReceiver(tempShowReceiver);
446         LocalBroadcastManager.getInstance(this).unregisterReceiver(tempHideReceiver);
447
448         LocalBroadcastManager.getInstance(this).registerReceiver(showReceiver, new IntentFilter("com.farmerbb.taskbar.SHOW_TASKBAR"));
449         LocalBroadcastManager.getInstance(this).registerReceiver(hideReceiver, new IntentFilter("com.farmerbb.taskbar.HIDE_TASKBAR"));
450         LocalBroadcastManager.getInstance(this).registerReceiver(tempShowReceiver, new IntentFilter("com.farmerbb.taskbar.TEMP_SHOW_TASKBAR"));
451         LocalBroadcastManager.getInstance(this).registerReceiver(tempHideReceiver, new IntentFilter("com.farmerbb.taskbar.TEMP_HIDE_TASKBAR"));
452
453         startRefreshingRecents();
454
455         windowManager.addView(layout, params);
456
457         isFirstStart = false;
458     }
459
460     private void startRefreshingRecents() {
461         if(thread != null) thread.interrupt();
462         stopThread2 = true;
463
464         SharedPreferences pref = U.getSharedPreferences(this);
465         showHideAutomagically = pref.getBoolean("hide_when_keyboard_shown", false);
466
467         currentTaskbarIds.clear();
468
469         handler = new Handler();
470         thread = new Thread() {
471             @Override
472             public void run() {
473                 updateRecentApps(true);
474
475                 if(!isRefreshingRecents) {
476                     isRefreshingRecents = true;
477
478                     while(shouldRefreshRecents) {
479                         SystemClock.sleep(refreshInterval);
480                         updateRecentApps(false);
481
482                         if(showHideAutomagically && !positionIsVertical && !StartMenuHelper.getInstance().isStartMenuOpen())
483                             handler.post(() -> {
484                                 if(layout != null) {
485                                     int[] location = new int[2];
486                                     layout.getLocationOnScreen(location);
487
488                                     if(location[1] != 0) {
489                                         if(location[1] > currentTaskbarPosition) {
490                                             currentTaskbarPosition = location[1];
491                                         } else if(location[1] < currentTaskbarPosition) {
492                                             if(currentTaskbarPosition - location[1] == getNavBarSize())
493                                                 currentTaskbarPosition = location[1];
494                                             else if(!startThread2) {
495                                                 startThread2 = true;
496                                                 tempHideTaskbar(true);
497                                             }
498                                         }
499                                     }
500                                 }
501                             });
502                         }
503
504                     isRefreshingRecents = false;
505                 }
506             }
507         };
508
509         thread.start();
510     }
511
512     @SuppressWarnings("Convert2streamapi")
513     @TargetApi(Build.VERSION_CODES.LOLLIPOP_MR1)
514     private void updateRecentApps(final boolean firstRefresh) {
515         SharedPreferences pref = U.getSharedPreferences(this);
516         final PackageManager pm = getPackageManager();
517         final List<AppEntry> entries = new ArrayList<>();
518         List<LauncherActivityInfo> launcherAppCache = new ArrayList<>();
519         int maxNumOfEntries = U.getMaxNumOfEntries(this);
520         int realNumOfPinnedApps = 0;
521         boolean fullLength = pref.getBoolean("full_length", false);
522
523         PinnedBlockedApps pba = PinnedBlockedApps.getInstance(this);
524         List<AppEntry> pinnedApps = pba.getPinnedApps();
525         List<AppEntry> blockedApps = pba.getBlockedApps();
526         List<String> applicationIdsToRemove = new ArrayList<>();
527
528         // Filter out anything on the pinned/blocked apps lists
529         if(pinnedApps.size() > 0) {
530             UserManager userManager = (UserManager) getSystemService(USER_SERVICE);
531             LauncherApps launcherApps = (LauncherApps) getSystemService(LAUNCHER_APPS_SERVICE);
532
533             for(AppEntry entry : pinnedApps) {
534                 boolean packageEnabled = launcherApps.isPackageEnabled(entry.getPackageName(),
535                         userManager.getUserForSerialNumber(entry.getUserId(this)));
536
537                 if(packageEnabled)
538                     entries.add(entry);
539                 else
540                     realNumOfPinnedApps--;
541
542                 applicationIdsToRemove.add(entry.getPackageName());
543             }
544             
545             realNumOfPinnedApps = realNumOfPinnedApps + pinnedApps.size();
546         }
547
548         if(blockedApps.size() > 0) {
549             for(AppEntry entry : blockedApps) {
550                 applicationIdsToRemove.add(entry.getPackageName());
551             }
552         }
553
554         // Get list of all recently used apps
555         List<AppEntry> usageStatsList = realNumOfPinnedApps < maxNumOfEntries ? getAppEntries() : new ArrayList<>();
556         if(usageStatsList.size() > 0 || realNumOfPinnedApps > 0 || fullLength) {
557             if(realNumOfPinnedApps < maxNumOfEntries) {
558                 List<AppEntry> usageStatsList2 = new ArrayList<>();
559                 List<AppEntry> usageStatsList3 = new ArrayList<>();
560                 List<AppEntry> usageStatsList4 = new ArrayList<>();
561                 List<AppEntry> usageStatsList5 = new ArrayList<>();
562                 List<AppEntry> usageStatsList6;
563
564                 Intent homeIntent = new Intent(Intent.ACTION_MAIN);
565                 homeIntent.addCategory(Intent.CATEGORY_HOME);
566                 ResolveInfo defaultLauncher = pm.resolveActivity(homeIntent, PackageManager.MATCH_DEFAULT_ONLY);
567
568                 // Filter out apps without a launcher intent
569                 // Also filter out the current launcher, and Taskbar itself
570                 for(AppEntry packageInfo : usageStatsList) {
571                     if(pm.getLaunchIntentForPackage(packageInfo.getPackageName()) != null
572                             && !packageInfo.getPackageName().contains(BuildConfig.BASE_APPLICATION_ID)
573                             && !packageInfo.getPackageName().equals(defaultLauncher.activityInfo.packageName))
574                         usageStatsList2.add(packageInfo);
575                 }
576
577                 // Filter out apps that don't fall within our current search interval
578                 for(AppEntry stats : usageStatsList2) {
579                     if(stats.getLastTimeUsed() > searchInterval || runningAppsOnly)
580                         usageStatsList3.add(stats);
581                 }
582
583                 // Sort apps by either most recently used, or most time used
584                 if(!runningAppsOnly) {
585                     if(sortOrder.contains("most_used")) {
586                         Collections.sort(usageStatsList3, (us1, us2) -> Long.compare(us2.getTotalTimeInForeground(), us1.getTotalTimeInForeground()));
587                     } else {
588                         Collections.sort(usageStatsList3, (us1, us2) -> Long.compare(us2.getLastTimeUsed(), us1.getLastTimeUsed()));
589                     }
590                 }
591
592                 // Filter out any duplicate entries
593                 List<String> applicationIds = new ArrayList<>();
594                 for(AppEntry stats : usageStatsList3) {
595                     if(!applicationIds.contains(stats.getPackageName())) {
596                         usageStatsList4.add(stats);
597                         applicationIds.add(stats.getPackageName());
598                     }
599                 }
600
601                 // Filter out the currently running foreground app, if requested by the user
602                 if(pref.getBoolean("hide_foreground", false)) {
603                     UsageStatsManager mUsageStatsManager = (UsageStatsManager) getSystemService(USAGE_STATS_SERVICE);
604                     UsageEvents events = mUsageStatsManager.queryEvents(searchInterval, System.currentTimeMillis());
605                     UsageEvents.Event eventCache = new UsageEvents.Event();
606                     String currentForegroundApp = null;
607
608                     while(events.hasNextEvent()) {
609                         events.getNextEvent(eventCache);
610
611                         if(eventCache.getEventType() == UsageEvents.Event.MOVE_TO_FOREGROUND) {
612                             if(!(eventCache.getPackageName().contains(BuildConfig.BASE_APPLICATION_ID)
613                                     && !eventCache.getClassName().equals(MainActivity.class.getCanonicalName())
614                                     && !eventCache.getClassName().equals(HomeActivity.class.getCanonicalName())
615                                     && !eventCache.getClassName().equals(InvisibleActivityFreeform.class.getCanonicalName())))
616                                 currentForegroundApp = eventCache.getPackageName();
617                         }
618                     }
619
620                     if(!applicationIdsToRemove.contains(currentForegroundApp))
621                         applicationIdsToRemove.add(currentForegroundApp);
622                 }
623
624                 for(AppEntry stats : usageStatsList4) {
625                     if(!applicationIdsToRemove.contains(stats.getPackageName())) {
626                         usageStatsList5.add(stats);
627                     }
628                 }
629
630                 // Truncate list to a maximum length
631                 if(usageStatsList5.size() > maxNumOfEntries)
632                     usageStatsList6 = usageStatsList5.subList(0, maxNumOfEntries);
633                 else
634                     usageStatsList6 = usageStatsList5;
635
636                 // Determine if we need to reverse the order
637                 boolean needToReverseOrder;
638                 switch(U.getTaskbarPosition(this)) {
639                     case "bottom_right":
640                     case "top_right":
641                         needToReverseOrder = sortOrder.contains("false");
642                         break;
643                     default:
644                         needToReverseOrder = sortOrder.contains("true");
645                         break;
646                 }
647
648                 if(needToReverseOrder) {
649                     Collections.reverse(usageStatsList6);
650                 }
651
652                 // Generate the AppEntries for TaskbarAdapter
653                 int number = usageStatsList6.size() == maxNumOfEntries
654                         ? usageStatsList6.size() - realNumOfPinnedApps
655                         : usageStatsList6.size();
656
657                 UserManager userManager = (UserManager) getSystemService(Context.USER_SERVICE);
658                 LauncherApps launcherApps = (LauncherApps) getSystemService(Context.LAUNCHER_APPS_SERVICE);
659
660                 final List<UserHandle> userHandles = userManager.getUserProfiles();
661
662                 for(int i = 0; i < number; i++) {
663                     for(UserHandle handle : userHandles) {
664                         String packageName = usageStatsList6.get(i).getPackageName();
665                         List<LauncherActivityInfo> list = launcherApps.getActivityList(packageName, handle);
666                         if(!list.isEmpty()) {
667                             // Google App workaround
668                             if(!packageName.equals("com.google.android.googlequicksearchbox"))
669                                 launcherAppCache.add(list.get(0));
670                             else {
671                                 boolean added = false;
672                                 for(LauncherActivityInfo info : list) {
673                                     if(info.getName().equals("com.google.android.googlequicksearchbox.SearchActivity")) {
674                                         launcherAppCache.add(info);
675                                         added = true;
676                                     }
677                                 }
678
679                                 if(!added) launcherAppCache.add(list.get(0));
680                             }
681
682                             AppEntry newEntry = new AppEntry(
683                                     packageName,
684                                     null,
685                                     null,
686                                     null,
687                                     false
688                             );
689
690                             newEntry.setUserId(userManager.getSerialNumberForUser(handle));
691                             entries.add(newEntry);
692
693                             break;
694                         }
695                     }
696                 }
697             }
698
699             while(entries.size() > maxNumOfEntries) {
700                 try {
701                     entries.remove(entries.size() - 1);
702                     launcherAppCache.remove(launcherAppCache.size() - 1);
703                 } catch (ArrayIndexOutOfBoundsException e) { /* Gracefully fail */ }
704             }
705
706             // Determine if we need to reverse the order again
707             if(U.getTaskbarPosition(this).contains("vertical")) {
708                 Collections.reverse(entries);
709                 Collections.reverse(launcherAppCache);
710             }
711
712             // Now that we've generated the list of apps,
713             // we need to determine if we need to redraw the Taskbar or not
714             boolean shouldRedrawTaskbar = firstRefresh;
715
716             List<String> finalApplicationIds = new ArrayList<>();
717             for(AppEntry entry : entries) {
718                 finalApplicationIds.add(entry.getPackageName());
719             }
720
721             if(finalApplicationIds.size() != currentTaskbarIds.size()
722                     || numOfPinnedApps != realNumOfPinnedApps)
723                 shouldRedrawTaskbar = true;
724             else {
725                 for(int i = 0; i < finalApplicationIds.size(); i++) {
726                     if(!finalApplicationIds.get(i).equals(currentTaskbarIds.get(i))) {
727                         shouldRedrawTaskbar = true;
728                         break;
729                     }
730                 }
731             }
732
733             if(shouldRedrawTaskbar) {
734                 currentTaskbarIds = finalApplicationIds;
735                 numOfPinnedApps = realNumOfPinnedApps;
736
737                 UserManager userManager = (UserManager) getSystemService(USER_SERVICE);
738
739                 int launcherAppCachePos = -1;
740                 for(int i = 0; i < entries.size(); i++) {
741                     if(entries.get(i).getComponentName() == null) {
742                         launcherAppCachePos++;
743                         LauncherActivityInfo appInfo = launcherAppCache.get(launcherAppCachePos);
744                         String packageName = entries.get(i).getPackageName();
745
746                         entries.remove(i);
747
748                         AppEntry newEntry = new AppEntry(
749                                 packageName,
750                                 appInfo.getComponentName().flattenToString(),
751                                 appInfo.getLabel().toString(),
752                                 IconCache.getInstance(TaskbarService.this).getIcon(TaskbarService.this, pm, appInfo),
753                                 false);
754
755                         newEntry.setUserId(userManager.getSerialNumberForUser(appInfo.getUser()));
756                         entries.add(i, newEntry);
757                     }
758                 }
759
760                 final int numOfEntries = Math.min(entries.size(), maxNumOfEntries);
761
762                 handler.post(() -> {
763                     if(numOfEntries > 0 || fullLength) {
764                         ViewGroup.LayoutParams params = scrollView.getLayoutParams();
765                         DisplayMetrics metrics = getResources().getDisplayMetrics();
766                         int recentsSize = getResources().getDimensionPixelSize(R.dimen.icon_size) * numOfEntries;
767                         float maxRecentsSize = fullLength ? Float.MAX_VALUE : recentsSize;
768
769                         if(U.getTaskbarPosition(TaskbarService.this).contains("vertical")) {
770                             int maxScreenSize = metrics.heightPixels
771                                     - U.getStatusBarHeight(TaskbarService.this)
772                                     - U.getBaseTaskbarSize(TaskbarService.this);
773
774                             params.height = (int) Math.min(maxRecentsSize, maxScreenSize)
775                                     + getResources().getDimensionPixelSize(R.dimen.divider_size);
776
777                             if(fullLength && U.getTaskbarPosition(this).contains("bottom")) {
778                                 Space whitespace = (Space) layout.findViewById(R.id.whitespace);
779                                 ViewGroup.LayoutParams params2 = whitespace.getLayoutParams();
780                                 if(params2 != null) {
781                                     params2.height = maxScreenSize - recentsSize;
782                                     whitespace.setLayoutParams(params2);
783                                 }
784                             }
785                         } else {
786                             int maxScreenSize = metrics.widthPixels
787                                     - U.getBaseTaskbarSize(TaskbarService.this);
788
789                             params.width = (int) Math.min(maxRecentsSize, maxScreenSize)
790                                     + getResources().getDimensionPixelSize(R.dimen.divider_size);
791
792                             if(fullLength && U.getTaskbarPosition(this).contains("right")) {
793                                 Space whitespace = (Space) layout.findViewById(R.id.whitespace);
794                                 ViewGroup.LayoutParams params2 = whitespace.getLayoutParams();
795                                 if(params2 != null) {
796                                     params2.width = maxScreenSize - recentsSize;
797                                     whitespace.setLayoutParams(params2);
798                                 }
799                             }
800                         }
801
802                         scrollView.setLayoutParams(params);
803
804                         taskbar.removeAllViews();
805                         for(int i = 0; i < entries.size(); i++) {
806                             taskbar.addView(getView(entries, i));
807                         }
808
809                         isShowingRecents = true;
810                         if(shouldRefreshRecents && scrollView.getVisibility() != View.VISIBLE) {
811                             if(firstRefresh)
812                                 scrollView.setVisibility(View.INVISIBLE);
813                             else
814                                 scrollView.setVisibility(View.VISIBLE);
815                         }
816
817                         if(firstRefresh && scrollView.getVisibility() != View.VISIBLE)
818                             new Handler().post(() -> {
819                                 switch(U.getTaskbarPosition(TaskbarService.this)) {
820                                     case "bottom_left":
821                                     case "bottom_right":
822                                     case "top_left":
823                                     case "top_right":
824                                         if(sortOrder.contains("false"))
825                                             scrollView.scrollTo(0, 0);
826                                         else if(sortOrder.contains("true"))
827                                             scrollView.scrollTo(taskbar.getWidth(), taskbar.getHeight());
828                                         break;
829                                     case "bottom_vertical_left":
830                                     case "bottom_vertical_right":
831                                     case "top_vertical_left":
832                                     case "top_vertical_right":
833                                         if(sortOrder.contains("false"))
834                                             scrollView.scrollTo(taskbar.getWidth(), taskbar.getHeight());
835                                         else if(sortOrder.contains("true"))
836                                             scrollView.scrollTo(0, 0);
837                                         break;
838                                 }
839
840                                 if(shouldRefreshRecents) {
841                                     scrollView.setVisibility(View.VISIBLE);
842                                 }
843                             });
844                     } else {
845                         isShowingRecents = false;
846                         scrollView.setVisibility(View.GONE);
847                     }
848                 });
849             }
850         } else if(firstRefresh || currentTaskbarIds.size() > 0) {
851             currentTaskbarIds.clear();
852             handler.post(() -> {
853                 isShowingRecents = false;
854                 scrollView.setVisibility(View.GONE);
855             });
856         }
857     }
858
859     private void toggleTaskbar() {
860         if(startButton.getVisibility() == View.GONE)
861             showTaskbar(true);
862         else
863             hideTaskbar(true);
864     }
865
866     private void showTaskbar(boolean clearVariables) {
867         if(clearVariables) {
868             taskbarShownTemporarily = false;
869             taskbarHiddenTemporarily = false;
870         }
871
872         if(startButton.getVisibility() == View.GONE) {
873             startButton.setVisibility(View.VISIBLE);
874             space.setVisibility(View.VISIBLE);
875
876             if(dashboardEnabled)
877                 dashboardButton.setVisibility(View.VISIBLE);
878
879             if(navbarButtonsEnabled)
880                 navbarButtons.setVisibility(View.VISIBLE);
881
882             if(isShowingRecents && scrollView.getVisibility() == View.GONE)
883                 scrollView.setVisibility(View.INVISIBLE);
884
885             shouldRefreshRecents = true;
886             startRefreshingRecents();
887
888             SharedPreferences pref = U.getSharedPreferences(this);
889             pref.edit().putBoolean("collapsed", true).apply();
890
891             updateButton(false);
892         }
893     }
894
895     private void hideTaskbar(boolean clearVariables) {
896         if(clearVariables) {
897             taskbarShownTemporarily = false;
898             taskbarHiddenTemporarily = false;
899         }
900
901         if(startButton.getVisibility() == View.VISIBLE) {
902             startButton.setVisibility(View.GONE);
903             space.setVisibility(View.GONE);
904
905             if(dashboardEnabled)
906                 dashboardButton.setVisibility(View.GONE);
907
908             if(navbarButtonsEnabled)
909                 navbarButtons.setVisibility(View.GONE);
910
911             if(isShowingRecents) {
912                 scrollView.setVisibility(View.GONE);
913             }
914
915             shouldRefreshRecents = false;
916             if(thread != null) thread.interrupt();
917
918             SharedPreferences pref = U.getSharedPreferences(this);
919             pref.edit().putBoolean("collapsed", false).apply();
920
921             updateButton(true);
922
923             LocalBroadcastManager.getInstance(TaskbarService.this).sendBroadcast(new Intent("com.farmerbb.taskbar.HIDE_START_MENU"));
924             LocalBroadcastManager.getInstance(TaskbarService.this).sendBroadcast(new Intent("com.farmerbb.taskbar.HIDE_DASHBOARD"));
925         }
926     }
927
928     private void tempShowTaskbar() {
929         if(!taskbarHiddenTemporarily) {
930             SharedPreferences pref = U.getSharedPreferences(TaskbarService.this);
931             if(!pref.getBoolean("collapsed", false)) taskbarShownTemporarily = true;
932         }
933
934         showTaskbar(false);
935
936         if(taskbarHiddenTemporarily)
937             taskbarHiddenTemporarily = false;
938     }
939
940     private void tempHideTaskbar(boolean monitorPositionChanges) {
941         if(!taskbarShownTemporarily) {
942             SharedPreferences pref = U.getSharedPreferences(TaskbarService.this);
943             if(pref.getBoolean("collapsed", false)) taskbarHiddenTemporarily = true;
944         }
945
946         hideTaskbar(false);
947
948         if(taskbarShownTemporarily)
949             taskbarShownTemporarily = false;
950
951         if(monitorPositionChanges && showHideAutomagically && !positionIsVertical) {
952             if(thread2 != null) thread2.interrupt();
953
954             handler2 = new Handler();
955             thread2 = new Thread() {
956                 @Override
957                 public void run() {
958                     stopThread2 = false;
959
960                     while(!stopThread2) {
961                         SystemClock.sleep(refreshInterval);
962
963                         handler2.post(() -> stopThread2 = checkPositionChange());
964                     }
965
966                     startThread2 = false;
967                 }
968             };
969
970             thread2.start();
971         }
972     }
973
974     private boolean checkPositionChange() {
975         if(layout != null) {
976             int[] location = new int[2];
977             layout.getLocationOnScreen(location);
978
979             if(location[1] == 0) {
980                 return true;
981             } else {
982                 if(location[1] > currentTaskbarPosition) {
983                     currentTaskbarPosition = location[1];
984                     if(taskbarHiddenTemporarily) {
985                         tempShowTaskbar();
986                         return true;
987                     }
988                 } else if(location[1] == currentTaskbarPosition && taskbarHiddenTemporarily) {
989                     tempShowTaskbar();
990                     return true;
991                 } else if(location[1] < currentTaskbarPosition
992                         && currentTaskbarPosition - location[1] == getNavBarSize()) {
993                     currentTaskbarPosition = location[1];
994                 }
995             }
996         }
997
998         return false;
999     }
1000
1001     private int getNavBarSize() {
1002         Point size = new Point();
1003         Point realSize = new Point();
1004
1005         WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
1006         Display display = wm.getDefaultDisplay();
1007         display.getSize(size);
1008         display.getRealSize(realSize);
1009
1010         return realSize.y - size.y;
1011     }
1012
1013     @Override
1014     public void onDestroy() {
1015         shouldRefreshRecents = false;
1016
1017         super.onDestroy();
1018         if(layout != null)
1019             try {
1020                 windowManager.removeView(layout);
1021             } catch (IllegalArgumentException e) { /* Gracefully fail */ }
1022
1023         LocalBroadcastManager.getInstance(this).unregisterReceiver(showReceiver);
1024         LocalBroadcastManager.getInstance(this).unregisterReceiver(hideReceiver);
1025         LocalBroadcastManager.getInstance(this).unregisterReceiver(tempShowReceiver);
1026         LocalBroadcastManager.getInstance(this).unregisterReceiver(tempHideReceiver);
1027
1028         isFirstStart = true;
1029     }
1030
1031     @SuppressWarnings("deprecation")
1032     private void openContextMenu() {
1033         SharedPreferences pref = U.getSharedPreferences(this);
1034         Intent intent = null;
1035
1036         switch(pref.getString("theme", "light")) {
1037             case "light":
1038                 intent = new Intent(this, ContextMenuActivity.class);
1039                 break;
1040             case "dark":
1041                 intent = new Intent(this, ContextMenuActivityDark.class);
1042                 break;
1043         }
1044
1045         if(intent != null) {
1046             intent.putExtra("dont_show_quit", LauncherHelper.getInstance().isOnHomeScreen() && !pref.getBoolean("taskbar_active", false));
1047             intent.putExtra("is_start_button", true);
1048             intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1049         }
1050
1051         if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && FreeformHackHelper.getInstance().isInFreeformWorkspace()) {
1052             DisplayManager dm = (DisplayManager) getSystemService(DISPLAY_SERVICE);
1053             Display display = dm.getDisplay(Display.DEFAULT_DISPLAY);
1054
1055             if(intent != null && U.isOPreview())
1056                 intent.putExtra("context_menu_fix", true);
1057
1058             startActivity(intent, U.getActivityOptions(ApplicationType.CONTEXT_MENU).setLaunchBounds(new Rect(0, 0, display.getWidth(), display.getHeight())).toBundle());
1059         } else
1060             startActivity(intent);
1061     }
1062
1063     private void updateButton(boolean isCollapsed) {
1064         SharedPreferences pref = U.getSharedPreferences(this);
1065         boolean hide = pref.getBoolean("invisible_button", false);
1066
1067         if(button != null) button.setText(getString(isCollapsed ? R.string.right_arrow : R.string.left_arrow));
1068         if(layout != null) layout.setAlpha(isCollapsed && hide ? 0 : 1);
1069     }
1070
1071     @TargetApi(Build.VERSION_CODES.M)
1072     @Override
1073     public void onConfigurationChanged(Configuration newConfig) {
1074         super.onConfigurationChanged(newConfig);
1075
1076         if(layout != null) {
1077             try {
1078                 windowManager.removeView(layout);
1079             } catch (IllegalArgumentException e) { /* Gracefully fail */ }
1080
1081             currentTaskbarPosition = 0;
1082
1083             if(Build.VERSION.SDK_INT < Build.VERSION_CODES.M || Settings.canDrawOverlays(this))
1084                 drawTaskbar();
1085             else {
1086                 SharedPreferences pref = U.getSharedPreferences(this);
1087                 pref.edit().putBoolean("taskbar_active", false).apply();
1088
1089                 stopSelf();
1090             }
1091         }
1092     }
1093
1094     private View getView(List<AppEntry> list, int position) {
1095         View convertView = View.inflate(this, R.layout.icon, null);
1096
1097         final AppEntry entry = list.get(position);
1098         final SharedPreferences pref = U.getSharedPreferences(this);
1099
1100         ImageView imageView = (ImageView) convertView.findViewById(R.id.icon);
1101         ImageView imageView2 = (ImageView) convertView.findViewById(R.id.shortcut_icon);
1102         imageView.setImageDrawable(entry.getIcon(this));
1103         imageView2.setBackgroundColor(pref.getInt("accent_color", getResources().getInteger(R.integer.translucent_white)));
1104
1105         String taskbarPosition = U.getTaskbarPosition(this);
1106         if(pref.getBoolean("shortcut_icon", true)) {
1107             boolean shouldShowShortcutIcon;
1108             if(taskbarPosition.contains("vertical"))
1109                 shouldShowShortcutIcon = position >= list.size() - numOfPinnedApps;
1110             else
1111                 shouldShowShortcutIcon = position < numOfPinnedApps;
1112
1113             if(shouldShowShortcutIcon) imageView2.setVisibility(View.VISIBLE);
1114         }
1115
1116         if(taskbarPosition.equals("bottom_right") || taskbarPosition.equals("top_right")) {
1117             imageView.setRotationY(180);
1118             imageView2.setRotationY(180);
1119         }
1120
1121         FrameLayout layout = (FrameLayout) convertView.findViewById(R.id.entry);
1122         layout.setOnClickListener(view -> U.launchApp(TaskbarService.this, entry.getPackageName(), entry.getComponentName(), entry.getUserId(TaskbarService.this), null, true, false));
1123
1124         layout.setOnLongClickListener(view -> {
1125             int[] location = new int[2];
1126             view.getLocationOnScreen(location);
1127             openContextMenu(entry, location);
1128             return true;
1129         });
1130
1131         layout.setOnGenericMotionListener((view, motionEvent) -> {
1132             int action = motionEvent.getAction();
1133
1134             if(action == MotionEvent.ACTION_BUTTON_PRESS
1135                     && motionEvent.getButtonState() == MotionEvent.BUTTON_SECONDARY) {
1136                 int[] location = new int[2];
1137                 view.getLocationOnScreen(location);
1138                 openContextMenu(entry, location);
1139             }
1140
1141             if(action == MotionEvent.ACTION_SCROLL && pref.getBoolean("visual_feedback", true))
1142                 view.setBackgroundColor(0);
1143
1144             return false;
1145         });
1146
1147         if(pref.getBoolean("visual_feedback", true)) {
1148             layout.setOnHoverListener((v, event) -> {
1149                 if(event.getAction() == MotionEvent.ACTION_HOVER_ENTER) {
1150                     int accentColor = U.getAccentColor(TaskbarService.this);
1151                     accentColor = ColorUtils.setAlphaComponent(accentColor, Color.alpha(accentColor) / 2);
1152                     v.setBackgroundColor(accentColor);
1153                 }
1154
1155                 if(event.getAction() == MotionEvent.ACTION_HOVER_EXIT)
1156                     v.setBackgroundColor(0);
1157
1158                 if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
1159                     v.setPointerIcon(PointerIcon.getSystemIcon(TaskbarService.this, PointerIcon.TYPE_DEFAULT));
1160
1161                 return false;
1162             });
1163
1164             layout.setOnTouchListener((v, event) -> {
1165                 v.setAlpha(event.getAction() == MotionEvent.ACTION_DOWN || event.getAction() == MotionEvent.ACTION_MOVE ? 0.5f : 1);
1166                 return false;
1167             });
1168         }
1169
1170         return convertView;
1171     }
1172
1173     @SuppressWarnings("deprecation")
1174     private void openContextMenu(AppEntry entry, int[] location) {
1175         SharedPreferences pref = U.getSharedPreferences(this);
1176         Intent intent = null;
1177
1178         switch(pref.getString("theme", "light")) {
1179             case "light":
1180                 intent = new Intent(this, ContextMenuActivity.class);
1181                 break;
1182             case "dark":
1183                 intent = new Intent(this, ContextMenuActivityDark.class);
1184                 break;
1185         }
1186
1187         if(intent != null) {
1188             intent.putExtra("package_name", entry.getPackageName());
1189             intent.putExtra("app_name", entry.getLabel());
1190             intent.putExtra("component_name", entry.getComponentName());
1191             intent.putExtra("user_id", entry.getUserId(this));
1192             intent.putExtra("x", location[0]);
1193             intent.putExtra("y", location[1]);
1194             intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1195         }
1196
1197         if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && FreeformHackHelper.getInstance().isInFreeformWorkspace()) {
1198             DisplayManager dm = (DisplayManager) getSystemService(DISPLAY_SERVICE);
1199             Display display = dm.getDisplay(Display.DEFAULT_DISPLAY);
1200
1201             if(intent != null && U.isOPreview())
1202                 intent.putExtra("context_menu_fix", true);
1203
1204             startActivity(intent, U.getActivityOptions(ApplicationType.CONTEXT_MENU).setLaunchBounds(new Rect(0, 0, display.getWidth(), display.getHeight())).toBundle());
1205         } else
1206             startActivity(intent);
1207     }
1208
1209     private List<AppEntry> getAppEntries() {
1210         SharedPreferences pref = U.getSharedPreferences(this);
1211         if(runningAppsOnly)
1212             return getAppEntriesUsingActivityManager(Integer.parseInt(pref.getString("max_num_of_recents", "10")));
1213         else
1214             return getAppEntriesUsingUsageStats();
1215     }
1216
1217     @SuppressWarnings("deprecation")
1218     private List<AppEntry> getAppEntriesUsingActivityManager(int maxNum) {
1219         ActivityManager mActivityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
1220         List<ActivityManager.RunningTaskInfo> usageStatsList = mActivityManager.getRunningTasks(maxNum);
1221         List<AppEntry> entries = new ArrayList<>();
1222
1223         for(ActivityManager.RunningTaskInfo usageStats : usageStatsList) {
1224             AppEntry newEntry = new AppEntry(
1225                     usageStats.baseActivity.getPackageName(),
1226                     null,
1227                     null,
1228                     null,
1229                     false
1230             );
1231
1232             entries.add(newEntry);
1233         }
1234
1235         return entries;
1236     }
1237
1238     @TargetApi(Build.VERSION_CODES.LOLLIPOP_MR1)
1239     private List<AppEntry> getAppEntriesUsingUsageStats() {
1240         UsageStatsManager mUsageStatsManager = (UsageStatsManager) getSystemService(USAGE_STATS_SERVICE);
1241         List<UsageStats> usageStatsList = mUsageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_YEARLY, searchInterval, System.currentTimeMillis());
1242         List<AppEntry> entries = new ArrayList<>();
1243
1244         for(UsageStats usageStats : usageStatsList) {
1245             AppEntry newEntry = new AppEntry(
1246                     usageStats.getPackageName(),
1247                     null,
1248                     null,
1249                     null,
1250                     false
1251             );
1252
1253             newEntry.setTotalTimeInForeground(usageStats.getTotalTimeInForeground());
1254             newEntry.setLastTimeUsed(usageStats.getLastTimeUsed());
1255             entries.add(newEntry);
1256         }
1257
1258         return entries;
1259     }
1260 }