1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 5 * except in compliance with the License. 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 distributed under the 10 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 11 * KIND, either express or implied. See the License for the specific language governing 12 * permissions and limitations under the License. 13 */ 14 15 package com.android.systemui.util; 16 17 import static android.view.Display.DEFAULT_DISPLAY; 18 19 import android.Manifest; 20 import android.content.Context; 21 import android.content.Intent; 22 import android.content.pm.PackageManager; 23 import android.provider.Settings; 24 import android.view.View; 25 26 import com.android.systemui.shared.system.QuickStepContract; 27 import com.android.systemui.statusbar.CommandQueue; 28 29 import java.util.List; 30 import java.util.function.Consumer; 31 32 public class Utils { 33 34 /** 35 * Allows lambda iteration over a list. It is done in reverse order so it is safe 36 * to add or remove items during the iteration. Skips over null items. 37 */ safeForeach(List<T> list, Consumer<T> c)38 public static <T> void safeForeach(List<T> list, Consumer<T> c) { 39 for (int i = list.size() - 1; i >= 0; i--) { 40 T item = list.get(i); 41 if (item != null) { 42 c.accept(item); 43 } 44 } 45 } 46 47 /** 48 * Sets the visibility of an UI element according to the DISABLE_* flags in 49 * {@link android.app.StatusBarManager}. 50 */ 51 public static class DisableStateTracker implements CommandQueue.Callbacks, 52 View.OnAttachStateChangeListener { 53 private final int mMask1; 54 private final int mMask2; 55 private final CommandQueue mCommandQueue; 56 private View mView; 57 private boolean mDisabled; 58 DisableStateTracker(int disableMask, int disable2Mask, CommandQueue commandQueue)59 public DisableStateTracker(int disableMask, int disable2Mask, CommandQueue commandQueue) { 60 mMask1 = disableMask; 61 mMask2 = disable2Mask; 62 mCommandQueue = commandQueue; 63 } 64 65 @Override onViewAttachedToWindow(View v)66 public void onViewAttachedToWindow(View v) { 67 mView = v; 68 mCommandQueue.addCallback(this); 69 } 70 71 @Override onViewDetachedFromWindow(View v)72 public void onViewDetachedFromWindow(View v) { 73 mCommandQueue.removeCallback(this); 74 mView = null; 75 } 76 77 /** 78 * Sets visibility of this {@link View} given the states passed from 79 * {@link com.android.systemui.statusbar.CommandQueue.Callbacks#disable(int, int, int)}. 80 */ 81 @Override disable(int displayId, int state1, int state2, boolean animate)82 public void disable(int displayId, int state1, int state2, boolean animate) { 83 if (displayId != mView.getDisplay().getDisplayId()) { 84 return; 85 } 86 final boolean disabled = ((state1 & mMask1) != 0) || ((state2 & mMask2) != 0); 87 if (disabled == mDisabled) return; 88 mDisabled = disabled; 89 mView.setVisibility(disabled ? View.GONE : View.VISIBLE); 90 } 91 92 /** @return {@code true} if and only if this {@link View} is currently disabled */ isDisabled()93 public boolean isDisabled() { 94 return mDisabled; 95 } 96 } 97 98 99 /** 100 * Returns {@code true} iff the package {@code packageName} is a headless remote display 101 * provider, i.e, that the package holds the privileged {@code REMOTE_DISPLAY_PROVIDER} 102 * permission and that it doesn't host a launcher icon. 103 */ isHeadlessRemoteDisplayProvider(PackageManager pm, String packageName)104 public static boolean isHeadlessRemoteDisplayProvider(PackageManager pm, String packageName) { 105 if (pm.checkPermission(Manifest.permission.REMOTE_DISPLAY_PROVIDER, packageName) 106 != PackageManager.PERMISSION_GRANTED) { 107 return false; 108 } 109 110 Intent homeIntent = new Intent(Intent.ACTION_MAIN); 111 homeIntent.addCategory(Intent.CATEGORY_LAUNCHER); 112 homeIntent.setPackage(packageName); 113 114 return pm.queryIntentActivities(homeIntent, 0).isEmpty(); 115 } 116 117 /** 118 * Returns {@code true} if the navMode is that of 119 * {@link android.view.WindowManagerPolicyConstants#NAV_BAR_MODE_GESTURAL} AND 120 * the context is that of the default display 121 */ isGesturalModeOnDefaultDisplay(Context context, int navMode)122 public static boolean isGesturalModeOnDefaultDisplay(Context context, int navMode) { 123 return context.getDisplayId() == DEFAULT_DISPLAY 124 && QuickStepContract.isGesturalMode(navMode); 125 } 126 127 /** 128 * Allow the media player to be shown in the QS area, controlled by 2 flags. 129 * Off by default, but can be disabled by setting to 0 130 */ useQsMediaPlayer(Context context)131 public static boolean useQsMediaPlayer(Context context) { 132 return true; 133 } 134 135 /** 136 * Allow media resumption controls. Requires {@link #useQsMediaPlayer(Context)} to be enabled. 137 * Off by default, but can be enabled by setting to 1 138 */ useMediaResumption(Context context)139 public static boolean useMediaResumption(Context context) { 140 int flag = Settings.Secure.getInt(context.getContentResolver(), 141 Settings.Secure.MEDIA_CONTROLS_RESUME, 1); 142 return useQsMediaPlayer(context) && flag > 0; 143 } 144 } 145