1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.systemui.model; 18 19 import android.annotation.NonNull; 20 import android.util.Log; 21 22 import com.android.systemui.Dumpable; 23 import com.android.systemui.dagger.SysUISingleton; 24 import com.android.systemui.settings.DisplayTracker; 25 import com.android.systemui.shared.system.QuickStepContract; 26 import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags; 27 28 import dalvik.annotation.optimization.NeverCompile; 29 30 import java.io.PrintWriter; 31 import java.util.ArrayList; 32 import java.util.List; 33 34 /** 35 * Contains sysUi state flags and notifies registered 36 * listeners whenever changes happen. 37 */ 38 @SysUISingleton 39 public class SysUiState implements Dumpable { 40 41 private static final String TAG = SysUiState.class.getSimpleName(); 42 public static final boolean DEBUG = false; 43 44 private final DisplayTracker mDisplayTracker; 45 private final SceneContainerPlugin mSceneContainerPlugin; 46 private @SystemUiStateFlags long mFlags; 47 private final List<SysUiStateCallback> mCallbacks = new ArrayList<>(); 48 private long mFlagsToSet = 0; 49 private long mFlagsToClear = 0; 50 SysUiState(DisplayTracker displayTracker, SceneContainerPlugin sceneContainerPlugin)51 public SysUiState(DisplayTracker displayTracker, SceneContainerPlugin sceneContainerPlugin) { 52 mDisplayTracker = displayTracker; 53 mSceneContainerPlugin = sceneContainerPlugin; 54 } 55 56 /** 57 * Add listener to be notified of changes made to SysUI state. 58 * The callback will also be called as part of this function. 59 */ addCallback(@onNull SysUiStateCallback callback)60 public void addCallback(@NonNull SysUiStateCallback callback) { 61 mCallbacks.add(callback); 62 callback.onSystemUiStateChanged(mFlags); 63 } 64 65 /** Callback will no longer receive events on state change */ removeCallback(@onNull SysUiStateCallback callback)66 public void removeCallback(@NonNull SysUiStateCallback callback) { 67 mCallbacks.remove(callback); 68 } 69 70 /** Returns the current sysui state flags. */ 71 @SystemUiStateFlags getFlags()72 public long getFlags() { 73 return mFlags; 74 } 75 isFlagEnabled(@ystemUiStateFlags long flag)76 public boolean isFlagEnabled(@SystemUiStateFlags long flag) { 77 return (mFlags & flag) != 0; 78 } 79 80 /** Methods to this call can be chained together before calling {@link #commitUpdate(int)}. */ setFlag(@ystemUiStateFlags long flag, boolean enabled)81 public SysUiState setFlag(@SystemUiStateFlags long flag, boolean enabled) { 82 final Boolean overrideOrNull = mSceneContainerPlugin.flagValueOverride(flag); 83 if (overrideOrNull != null && enabled != overrideOrNull) { 84 if (DEBUG) { 85 Log.d(TAG, "setFlag for flag " + flag + " and value " + enabled + " overridden to " 86 + overrideOrNull + " by scene container plugin"); 87 } 88 89 enabled = overrideOrNull; 90 } 91 92 if (enabled) { 93 mFlagsToSet |= flag; 94 } else { 95 mFlagsToClear |= flag; 96 } 97 return this; 98 } 99 100 /** Call to save all the flags updated from {@link #setFlag(long, boolean)}. */ commitUpdate(int displayId)101 public void commitUpdate(int displayId) { 102 updateFlags(displayId); 103 mFlagsToSet = 0; 104 mFlagsToClear = 0; 105 } 106 updateFlags(int displayId)107 private void updateFlags(int displayId) { 108 if (displayId != mDisplayTracker.getDefaultDisplayId()) { 109 // Ignore non-default displays for now 110 Log.w(TAG, "Ignoring flag update for display: " + displayId, new Throwable()); 111 return; 112 } 113 114 long newState = mFlags; 115 newState |= mFlagsToSet; 116 newState &= ~mFlagsToClear; 117 notifyAndSetSystemUiStateChanged(newState, mFlags); 118 } 119 120 /** Notify all those who are registered that the state has changed. */ notifyAndSetSystemUiStateChanged(long newFlags, long oldFlags)121 private void notifyAndSetSystemUiStateChanged(long newFlags, long oldFlags) { 122 if (DEBUG) { 123 Log.d(TAG, "SysUiState changed: old=" + oldFlags + " new=" + newFlags); 124 } 125 if (newFlags != oldFlags) { 126 mCallbacks.forEach(callback -> callback.onSystemUiStateChanged(newFlags)); 127 mFlags = newFlags; 128 } 129 } 130 131 @NeverCompile 132 @Override dump(PrintWriter pw, String[] args)133 public void dump(PrintWriter pw, String[] args) { 134 pw.println("SysUiState state:"); 135 pw.print(" mSysUiStateFlags="); pw.println(mFlags); 136 pw.println(" " + QuickStepContract.getSystemUiStateString(mFlags)); 137 pw.print(" backGestureDisabled="); 138 pw.println(QuickStepContract.isBackGestureDisabled(mFlags, false /* forTrackpad */)); 139 pw.print(" assistantGestureDisabled="); 140 pw.println(QuickStepContract.isAssistantGestureDisabled(mFlags)); 141 } 142 143 /** Callback to be notified whenever system UI state flags are changed. */ 144 public interface SysUiStateCallback{ 145 /** To be called when any SysUiStateFlag gets updated */ onSystemUiStateChanged(@ystemUiStateFlags long sysUiFlags)146 void onSystemUiStateChanged(@SystemUiStateFlags long sysUiFlags); 147 } 148 } 149 150 151