• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.quickstep;
18 
19 import static com.android.launcher3.ResourceUtils.INVALID_RESOURCE_HANDLE;
20 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_NAVIGATION_MODE_2_BUTTON;
21 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_NAVIGATION_MODE_3_BUTTON;
22 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_NAVIGATION_MODE_GESTURE_BUTTON;
23 import static com.android.launcher3.util.PackageManagerHelper.getPackageFilter;
24 
25 import android.content.BroadcastReceiver;
26 import android.content.Context;
27 import android.content.Intent;
28 import android.util.Log;
29 
30 import com.android.launcher3.ResourceUtils;
31 import com.android.launcher3.logging.StatsLogManager.LauncherEvent;
32 import com.android.launcher3.util.MainThreadInitializedObject;
33 
34 import java.io.PrintWriter;
35 import java.util.ArrayList;
36 import java.util.List;
37 import java.util.concurrent.CopyOnWriteArrayList;
38 
39 /**
40  * Observer for the resource config that specifies the navigation bar mode.
41  */
42 public class SysUINavigationMode {
43 
44     public enum Mode {
45         THREE_BUTTONS(false, 0, LAUNCHER_NAVIGATION_MODE_3_BUTTON),
46         TWO_BUTTONS(true, 1, LAUNCHER_NAVIGATION_MODE_2_BUTTON),
47         NO_BUTTON(true, 2, LAUNCHER_NAVIGATION_MODE_GESTURE_BUTTON);
48 
49         public final boolean hasGestures;
50         public final int resValue;
51         public final LauncherEvent launcherEvent;
52 
Mode(boolean hasGestures, int resValue, LauncherEvent launcherEvent)53         Mode(boolean hasGestures, int resValue, LauncherEvent launcherEvent) {
54             this.hasGestures = hasGestures;
55             this.resValue = resValue;
56             this.launcherEvent = launcherEvent;
57         }
58     }
59 
getMode(Context context)60     public static Mode getMode(Context context) {
61         return INSTANCE.get(context).getMode();
62     }
63 
64     public static final MainThreadInitializedObject<SysUINavigationMode> INSTANCE =
65             new MainThreadInitializedObject<>(SysUINavigationMode::new);
66 
67     private static final String TAG = "SysUINavigationMode";
68     private static final String ACTION_OVERLAY_CHANGED = "android.intent.action.OVERLAY_CHANGED";
69     private static final String NAV_BAR_INTERACTION_MODE_RES_NAME =
70             "config_navBarInteractionMode";
71     private static final String TARGET_OVERLAY_PACKAGE = "android";
72 
73     private final Context mContext;
74     private Mode mMode;
75 
76     private int mNavBarGesturalHeight;
77     private int mNavBarLargerGesturalHeight;
78 
79     private final List<NavigationModeChangeListener> mChangeListeners =
80             new CopyOnWriteArrayList<>();
81     private final List<OneHandedModeChangeListener> mOneHandedOverlayChangeListeners =
82             new ArrayList<>();
83 
SysUINavigationMode(Context context)84     public SysUINavigationMode(Context context) {
85         mContext = context;
86         initializeMode();
87 
88         mContext.registerReceiver(new BroadcastReceiver() {
89             @Override
90             public void onReceive(Context context, Intent intent) {
91                 updateMode();
92                 updateGesturalHeight();
93             }
94         }, getPackageFilter(TARGET_OVERLAY_PACKAGE, ACTION_OVERLAY_CHANGED));
95     }
96 
97     /** Updates navigation mode when needed. */
updateMode()98     public void updateMode() {
99         Mode oldMode = mMode;
100         initializeMode();
101         if (mMode != oldMode) {
102             dispatchModeChange();
103         }
104     }
105 
updateGesturalHeight()106     private void updateGesturalHeight() {
107         int newGesturalHeight = ResourceUtils.getDimenByName(
108                 ResourceUtils.NAVBAR_BOTTOM_GESTURE_SIZE, mContext.getResources(),
109                 INVALID_RESOURCE_HANDLE);
110 
111         if (newGesturalHeight == INVALID_RESOURCE_HANDLE) {
112             Log.e(TAG, "Failed to get system resource ID. Incompatible framework version?");
113             return;
114         }
115 
116         if (mNavBarGesturalHeight != newGesturalHeight) {
117             mNavBarGesturalHeight = newGesturalHeight;
118         }
119 
120         int newLargerGesturalHeight = ResourceUtils.getDimenByName(
121                 ResourceUtils.NAVBAR_BOTTOM_GESTURE_LARGER_SIZE, mContext.getResources(),
122                 INVALID_RESOURCE_HANDLE);
123         if (newLargerGesturalHeight == INVALID_RESOURCE_HANDLE) {
124             Log.e(TAG, "Failed to get system resource ID. Incompatible framework version?");
125             return;
126         }
127         if (mNavBarLargerGesturalHeight != newLargerGesturalHeight) {
128             mNavBarLargerGesturalHeight = newLargerGesturalHeight;
129             dispatchOneHandedOverlayChange();
130         }
131     }
132 
initializeMode()133     private void initializeMode() {
134         int modeInt = ResourceUtils.getIntegerByName(NAV_BAR_INTERACTION_MODE_RES_NAME,
135                 mContext.getResources(), INVALID_RESOURCE_HANDLE);
136         mNavBarGesturalHeight = ResourceUtils.getDimenByName(
137                 ResourceUtils.NAVBAR_BOTTOM_GESTURE_SIZE, mContext.getResources(),
138                 INVALID_RESOURCE_HANDLE);
139         mNavBarLargerGesturalHeight = ResourceUtils.getDimenByName(
140                 ResourceUtils.NAVBAR_BOTTOM_GESTURE_LARGER_SIZE, mContext.getResources(),
141                 mNavBarGesturalHeight);
142 
143         if (modeInt == INVALID_RESOURCE_HANDLE) {
144             Log.e(TAG, "Failed to get system resource ID. Incompatible framework version?");
145             return;
146         }
147 
148         for (Mode m : Mode.values()) {
149             if (m.resValue == modeInt) {
150                 mMode = m;
151             }
152         }
153     }
154 
dispatchModeChange()155     private void dispatchModeChange() {
156         for (NavigationModeChangeListener listener : mChangeListeners) {
157             listener.onNavigationModeChanged(mMode);
158         }
159     }
160 
dispatchOneHandedOverlayChange()161     private void dispatchOneHandedOverlayChange() {
162         for (OneHandedModeChangeListener listener : mOneHandedOverlayChangeListeners) {
163             listener.onOneHandedModeChanged(mNavBarLargerGesturalHeight);
164         }
165     }
166 
addModeChangeListener(NavigationModeChangeListener listener)167     public Mode addModeChangeListener(NavigationModeChangeListener listener) {
168         mChangeListeners.add(listener);
169         return mMode;
170     }
171 
removeModeChangeListener(NavigationModeChangeListener listener)172     public void removeModeChangeListener(NavigationModeChangeListener listener) {
173         mChangeListeners.remove(listener);
174     }
175 
addOneHandedOverlayChangeListener(OneHandedModeChangeListener listener)176     public int addOneHandedOverlayChangeListener(OneHandedModeChangeListener listener) {
177         mOneHandedOverlayChangeListeners.add(listener);
178         return mNavBarLargerGesturalHeight;
179     }
180 
removeOneHandedOverlayChangeListener(OneHandedModeChangeListener listener)181     public void removeOneHandedOverlayChangeListener(OneHandedModeChangeListener listener) {
182         mOneHandedOverlayChangeListeners.remove(listener);
183     }
184 
getMode()185     public Mode getMode() {
186         return mMode;
187     }
188 
dump(PrintWriter pw)189     public void dump(PrintWriter pw) {
190         pw.println("SysUINavigationMode:");
191         pw.println("  mode=" + mMode.name());
192         pw.println("  mNavBarGesturalHeight=:" + mNavBarGesturalHeight);
193     }
194 
195     public interface NavigationModeChangeListener {
onNavigationModeChanged(Mode newMode)196         void onNavigationModeChanged(Mode newMode);
197     }
198 
199     public interface OneHandedModeChangeListener {
onOneHandedModeChanged(int newGesturalHeight)200         void onOneHandedModeChanged(int newGesturalHeight);
201     }
202 }
203