Skip to content

Commit 2c56b25

Browse files
author
ifeegoo
committed
android-sdk-sources-for-api-level-31 [Android 12]
0 parents  commit 2c56b25

13,522 files changed

Lines changed: 4865978 additions & 0 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
/*
2+
* Copyright (C) 2017 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 android.accessibilityservice;
18+
19+
import android.annotation.NonNull;
20+
import android.os.Handler;
21+
import android.os.Looper;
22+
import android.os.RemoteException;
23+
import android.util.ArrayMap;
24+
import android.util.Slog;
25+
26+
import java.util.Objects;
27+
28+
/**
29+
* Controller for the accessibility button within the system's navigation area
30+
* <p>
31+
* This class may be used to query the accessibility button's state and register
32+
* callbacks for interactions with and state changes to the accessibility button when
33+
* {@link AccessibilityServiceInfo#FLAG_REQUEST_ACCESSIBILITY_BUTTON} is set.
34+
* </p>
35+
* <p>
36+
* <strong>Note:</strong> This class and
37+
* {@link AccessibilityServiceInfo#FLAG_REQUEST_ACCESSIBILITY_BUTTON} should not be used as
38+
* the sole means for offering functionality to users via an {@link AccessibilityService}.
39+
* Some device implementations may choose not to provide a software-rendered system
40+
* navigation area, making this affordance permanently unavailable.
41+
* </p>
42+
* <p>
43+
* <strong>Note:</strong> On device implementations where the accessibility button is
44+
* supported, it may not be available at all times, such as when a foreground application uses
45+
* {@link android.view.View#SYSTEM_UI_FLAG_HIDE_NAVIGATION}. A user may also choose to assign
46+
* this button to another accessibility service or feature. In each of these cases, a
47+
* registered {@link AccessibilityButtonCallback}'s
48+
* {@link AccessibilityButtonCallback#onAvailabilityChanged(AccessibilityButtonController, boolean)}
49+
* method will be invoked to provide notifications of changes in the accessibility button's
50+
* availability to the registering service.
51+
* </p>
52+
*/
53+
public final class AccessibilityButtonController {
54+
private static final String LOG_TAG = "A11yButtonController";
55+
56+
private final IAccessibilityServiceConnection mServiceConnection;
57+
private final Object mLock;
58+
private ArrayMap<AccessibilityButtonCallback, Handler> mCallbacks;
59+
60+
AccessibilityButtonController(@NonNull IAccessibilityServiceConnection serviceConnection) {
61+
mServiceConnection = serviceConnection;
62+
mLock = new Object();
63+
}
64+
65+
/**
66+
* Retrieves whether the accessibility button in the system's navigation area is
67+
* available to the calling service.
68+
* <p>
69+
* <strong>Note:</strong> If the service is not yet connected (e.g.
70+
* {@link AccessibilityService#onServiceConnected()} has not yet been called) or the
71+
* service has been disconnected, this method will have no effect and return {@code false}.
72+
* </p>
73+
*
74+
* @return {@code true} if the accessibility button in the system's navigation area is
75+
* available to the calling service, {@code false} otherwise
76+
*/
77+
public boolean isAccessibilityButtonAvailable() {
78+
if (mServiceConnection != null) {
79+
try {
80+
return mServiceConnection.isAccessibilityButtonAvailable();
81+
} catch (RemoteException re) {
82+
Slog.w(LOG_TAG, "Failed to get accessibility button availability.", re);
83+
re.rethrowFromSystemServer();
84+
return false;
85+
}
86+
}
87+
return false;
88+
}
89+
90+
/**
91+
* Registers the provided {@link AccessibilityButtonCallback} for interaction and state
92+
* changes callbacks related to the accessibility button.
93+
*
94+
* @param callback the callback to add, must be non-null
95+
*/
96+
public void registerAccessibilityButtonCallback(@NonNull AccessibilityButtonCallback callback) {
97+
registerAccessibilityButtonCallback(callback, new Handler(Looper.getMainLooper()));
98+
}
99+
100+
/**
101+
* Registers the provided {@link AccessibilityButtonCallback} for interaction and state
102+
* change callbacks related to the accessibility button. The callback will occur on the
103+
* specified {@link Handler}'s thread, or on the services's main thread if the handler is
104+
* {@code null}.
105+
*
106+
* @param callback the callback to add, must be non-null
107+
* @param handler the handler on which the callback should execute, must be non-null
108+
*/
109+
public void registerAccessibilityButtonCallback(@NonNull AccessibilityButtonCallback callback,
110+
@NonNull Handler handler) {
111+
Objects.requireNonNull(callback);
112+
Objects.requireNonNull(handler);
113+
synchronized (mLock) {
114+
if (mCallbacks == null) {
115+
mCallbacks = new ArrayMap<>();
116+
}
117+
118+
mCallbacks.put(callback, handler);
119+
}
120+
}
121+
122+
/**
123+
* Unregisters the provided {@link AccessibilityButtonCallback} for interaction and state
124+
* change callbacks related to the accessibility button.
125+
*
126+
* @param callback the callback to remove, must be non-null
127+
*/
128+
public void unregisterAccessibilityButtonCallback(
129+
@NonNull AccessibilityButtonCallback callback) {
130+
Objects.requireNonNull(callback);
131+
synchronized (mLock) {
132+
if (mCallbacks == null) {
133+
return;
134+
}
135+
136+
final int keyIndex = mCallbacks.indexOfKey(callback);
137+
final boolean hasKey = keyIndex >= 0;
138+
if (hasKey) {
139+
mCallbacks.removeAt(keyIndex);
140+
}
141+
}
142+
}
143+
144+
/**
145+
* Dispatches the accessibility button click to any registered callbacks. This should
146+
* be called on the service's main thread.
147+
*/
148+
void dispatchAccessibilityButtonClicked() {
149+
final ArrayMap<AccessibilityButtonCallback, Handler> entries;
150+
synchronized (mLock) {
151+
if (mCallbacks == null || mCallbacks.isEmpty()) {
152+
Slog.w(LOG_TAG, "Received accessibility button click with no callbacks!");
153+
return;
154+
}
155+
156+
// Callbacks may remove themselves. Perform a shallow copy to avoid concurrent
157+
// modification.
158+
entries = new ArrayMap<>(mCallbacks);
159+
}
160+
161+
for (int i = 0, count = entries.size(); i < count; i++) {
162+
final AccessibilityButtonCallback callback = entries.keyAt(i);
163+
final Handler handler = entries.valueAt(i);
164+
handler.post(() -> callback.onClicked(this));
165+
}
166+
}
167+
168+
/**
169+
* Dispatches the accessibility button availability changes to any registered callbacks.
170+
* This should be called on the service's main thread.
171+
*/
172+
void dispatchAccessibilityButtonAvailabilityChanged(boolean available) {
173+
final ArrayMap<AccessibilityButtonCallback, Handler> entries;
174+
synchronized (mLock) {
175+
if (mCallbacks == null || mCallbacks.isEmpty()) {
176+
Slog.w(LOG_TAG,
177+
"Received accessibility button availability change with no callbacks!");
178+
return;
179+
}
180+
181+
// Callbacks may remove themselves. Perform a shallow copy to avoid concurrent
182+
// modification.
183+
entries = new ArrayMap<>(mCallbacks);
184+
}
185+
186+
for (int i = 0, count = entries.size(); i < count; i++) {
187+
final AccessibilityButtonCallback callback = entries.keyAt(i);
188+
final Handler handler = entries.valueAt(i);
189+
handler.post(() -> callback.onAvailabilityChanged(this, available));
190+
}
191+
}
192+
193+
/**
194+
* Callback for interaction with and changes to state of the accessibility button
195+
* within the system's navigation area.
196+
*/
197+
public static abstract class AccessibilityButtonCallback {
198+
199+
/**
200+
* Called when the accessibility button in the system's navigation area is clicked.
201+
*
202+
* @param controller the controller used to register for this callback
203+
*/
204+
public void onClicked(AccessibilityButtonController controller) {}
205+
206+
/**
207+
* Called when the availability of the accessibility button in the system's
208+
* navigation area has changed. The accessibility button may become unavailable
209+
* because the device shopped showing the button, the button was assigned to another
210+
* service, or for other reasons.
211+
*
212+
* @param controller the controller used to register for this callback
213+
* @param available {@code true} if the accessibility button is available to this
214+
* service, {@code false} otherwise
215+
*/
216+
public void onAvailabilityChanged(AccessibilityButtonController controller,
217+
boolean available) {
218+
}
219+
}
220+
}

0 commit comments

Comments
 (0)