…lines 1–4 unchanged (4 lines)
5
6import android.content.ClipData;
7import android.content.IOnPrimaryClipChangedListener;
8import android.os.Build;
9import android.os.IInterface;
10
11import java.lang.reflect.InvocationTargetException;
12import java.lang.reflect.Method;
13
14public final class ClipboardManager {
15 private final IInterface manager;
16 private Method getPrimaryClipMethod;
17 private Method setPrimaryClipMethod;
…lines 18–95 unchanged (78 lines)
96 }
97 }
98 return setPrimaryClipMethod;
99 }
100
101 private static ClipData getPrimaryClip(Method method, int methodVersion, IInterface manager)
102 throws InvocationTargetException, IllegalAccessException {
103 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
104 return (ClipData) method.invoke(manager, FakeContext.PACKAGE_NAME);
105 }
106
107 switch (methodVersion) {
108 case 0:
109 return (ClipData) method.invoke(manager, FakeContext.PACKAGE_NAME, FakeContext.ROOT_UID);
110 case 1:
111 return (ClipData) method.invoke(manager, FakeContext.PACKAGE_NAME, null, FakeContext.ROOT_UID);
112 case 2:
113 return (ClipData) method.invoke(manager, FakeContext.PACKAGE_NAME, null, FakeContext.ROOT_UID, 0);
114 case 3:
115 return (ClipData) method.invoke(manager, FakeContext.PACKAGE_NAME, FakeContext.ROOT_UID, null);
116 case 4:
117 // The last boolean parameter is "userOperate"
118 return (ClipData) method.invoke(manager, FakeContext.PACKAGE_NAME, null, FakeContext.ROOT_UID, 0, true);
119 default:
120 return (ClipData) method.invoke(manager, FakeContext.PACKAGE_NAME, null, null, null, FakeContext.ROOT_UID, 0, true);
121 }
122 }
123
124 private static void setPrimaryClip(Method method, int methodVersion, IInterface manager, ClipData clipData)
125 throws InvocationTargetException, IllegalAccessException {
126 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
127 method.invoke(manager, clipData, FakeContext.PACKAGE_NAME);
128 return;
129 }
130
131 switch (methodVersion) {
132 case 0:
133 method.invoke(manager, clipData, FakeContext.PACKAGE_NAME, FakeContext.ROOT_UID);
134 break;
135 case 1:
136 method.invoke(manager, clipData, FakeContext.PACKAGE_NAME, null, FakeContext.ROOT_UID);
137 break;
138 default:
139 method.invoke(manager, clipData, FakeContext.PACKAGE_NAME, null, FakeContext.ROOT_UID, 0);
140 break;
141 }
142 }
143
144 public CharSequence getText() {
145 try {
146 Method method = getGetPrimaryClipMethod();
147 ClipData clipData = getPrimaryClip(method, getMethodVersion, manager);
148 if (clipData == null || clipData.getItemCount() == 0) {
149 return null;
150 }
151 return clipData.getItemAt(0).getText();
152 } catch (InvocationTargetException | IllegalAccessException | NoSuchMethodException e) {
153 Ln.e("Could not invoke method", e);
154 return null;
155 }
156 }
157
158 public boolean setText(CharSequence text) {
159 try {
160 Method method = getSetPrimaryClipMethod();
161 ClipData clipData = ClipData.newPlainText(null, text);
162 setPrimaryClip(method, setMethodVersion, manager, clipData);
163 return true;
164 } catch (InvocationTargetException | IllegalAccessException | NoSuchMethodException e) {
165 Ln.e("Could not invoke method", e);
166 return false;
167 }
168 }
169
170 private static void addPrimaryClipChangedListener(Method method, int methodVersion, IInterface manager, IOnPrimaryClipChangedListener listener)
171 throws InvocationTargetException, IllegalAccessException {
172 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
173 method.invoke(manager, listener, FakeContext.PACKAGE_NAME);
174 return;
175 }
176
177 switch (methodVersion) {
178 case 0:
179 method.invoke(manager, listener, FakeContext.PACKAGE_NAME, FakeContext.ROOT_UID);
180 break;
181 case 1:
182 method.invoke(manager, listener, FakeContext.PACKAGE_NAME, null, FakeContext.ROOT_UID);
183 break;
184 default:
185 method.invoke(manager, listener, FakeContext.PACKAGE_NAME, null, FakeContext.ROOT_UID, 0);
186 break;
187 }
188 }
189
190 private Method getAddPrimaryClipChangedListener() throws NoSuchMethodException {
191 if (addPrimaryClipChangedListener == null) {
192 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
193 addPrimaryClipChangedListener = manager.getClass()
194 .getMethod("addPrimaryClipChangedListener", IOnPrimaryClipChangedListener.class, String.class);
…lines 195–216 unchanged (22 lines)
217
218 public boolean addPrimaryClipChangedListener(IOnPrimaryClipChangedListener listener) {
219 try {
220 Method method = getAddPrimaryClipChangedListener();
221 addPrimaryClipChangedListener(method, addListenerMethodVersion, manager, listener);
222 return true;
223 } catch (InvocationTargetException | IllegalAccessException | NoSuchMethodException e) {
224 Ln.e("Could not invoke method", e);
225 return false;
226 }
227 }
228}
229