version:
fix: update:更换为酷信
This commit is contained in:
23
tests/src/com/uiuipad/os/testcomponent/AppWidgetHidden.java
Normal file
23
tests/src/com/uiuipad/os/testcomponent/AppWidgetHidden.java
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.uiuipad.os.testcomponent;
|
||||
|
||||
import android.appwidget.AppWidgetProvider;
|
||||
|
||||
/**
|
||||
* A simple app widget without any configuration screen and is hidden in picker.
|
||||
*/
|
||||
public class AppWidgetHidden extends AppWidgetProvider { }
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.uiuipad.os.testcomponent;
|
||||
|
||||
import android.appwidget.AppWidgetProvider;
|
||||
|
||||
/**
|
||||
* A simple app widget without any configuration screen.
|
||||
*/
|
||||
public class AppWidgetNoConfig extends AppWidgetProvider {
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.uiuipad.os.testcomponent;
|
||||
|
||||
/**
|
||||
* A simple app widget with configuration sceen.
|
||||
*/
|
||||
public class AppWidgetWithConfig extends AppWidgetNoConfig {
|
||||
|
||||
}
|
||||
128
tests/src/com/uiuipad/os/testcomponent/BaseTestingActivity.java
Normal file
128
tests/src/com/uiuipad/os/testcomponent/BaseTestingActivity.java
Normal file
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.uiuipad.os.testcomponent;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.util.TypedValue;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.LinearLayout.LayoutParams;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
/**
|
||||
* Base activity with utility methods to help automate testing.
|
||||
*/
|
||||
public class BaseTestingActivity extends Activity implements View.OnClickListener {
|
||||
|
||||
public static final String SUFFIX_COMMAND = "-command";
|
||||
public static final String EXTRA_METHOD = "method";
|
||||
public static final String EXTRA_PARAM = "param_";
|
||||
|
||||
private static final int MARGIN_DP = 20;
|
||||
|
||||
private final String mAction = this.getClass().getName();
|
||||
|
||||
private LinearLayout mView;
|
||||
private int mMargin;
|
||||
|
||||
private final BroadcastReceiver mCommandReceiver = new BroadcastReceiver() {
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
handleCommand(intent);
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
mMargin = Math.round(TypedValue.applyDimension(
|
||||
TypedValue.COMPLEX_UNIT_DIP, MARGIN_DP, getResources().getDisplayMetrics()));
|
||||
mView = new LinearLayout(this);
|
||||
mView.setPadding(mMargin, mMargin, mMargin, mMargin);
|
||||
mView.setOrientation(LinearLayout.VERTICAL);
|
||||
mView.setBackgroundColor(Color.BLUE);
|
||||
setContentView(mView);
|
||||
|
||||
registerReceiver(mCommandReceiver, new IntentFilter(mAction + SUFFIX_COMMAND));
|
||||
}
|
||||
|
||||
protected void addButton(String title, String method) {
|
||||
Button button = new Button(this);
|
||||
button.setText(title);
|
||||
button.setTag(method);
|
||||
button.setOnClickListener(this);
|
||||
|
||||
LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
|
||||
lp.bottomMargin = mMargin;
|
||||
mView.addView(button, lp);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
sendBroadcast(new Intent(mAction).putExtra(Intent.EXTRA_INTENT, getIntent()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
unregisterReceiver(mCommandReceiver);
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
handleCommand(new Intent().putExtra(EXTRA_METHOD, (String) view.getTag()));
|
||||
}
|
||||
|
||||
private void handleCommand(Intent cmd) {
|
||||
String methodName = cmd.getStringExtra(EXTRA_METHOD);
|
||||
try {
|
||||
Method method = null;
|
||||
for (Method m : this.getClass().getDeclaredMethods()) {
|
||||
if (methodName.equals(m.getName()) &&
|
||||
!Modifier.isStatic(m.getModifiers()) &&
|
||||
Modifier.isPublic(m.getModifiers())) {
|
||||
method = m;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Object[] args = new Object[method.getParameterTypes().length];
|
||||
Bundle extras = cmd.getExtras();
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
args[i] = extras.get(EXTRA_PARAM + i);
|
||||
}
|
||||
method.invoke(this, args);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static Intent getCommandIntent(Class<?> clazz, String method) {
|
||||
return new Intent(clazz.getName() + SUFFIX_COMMAND)
|
||||
.putExtra(EXTRA_METHOD, method);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.uiuipad.os.testcomponent;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.PendingIntent;
|
||||
import android.appwidget.AppWidgetManager;
|
||||
import android.content.ComponentName;
|
||||
import android.content.IntentSender;
|
||||
import android.content.pm.ShortcutInfo;
|
||||
import android.content.pm.ShortcutManager;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.drawable.Icon;
|
||||
import android.os.Bundle;
|
||||
import android.widget.RemoteViews;
|
||||
|
||||
/**
|
||||
* Sample activity to request pinning an item.
|
||||
*/
|
||||
@TargetApi(26)
|
||||
public class RequestPinItemActivity extends BaseTestingActivity {
|
||||
|
||||
private PendingIntent mCallback = null;
|
||||
private String mShortcutId = "test-id";
|
||||
private int mRemoteViewColor = Color.TRANSPARENT;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
addButton("Pin Shortcut", "pinShortcut");
|
||||
addButton("Pin Widget without config ", "pinWidgetNoConfig");
|
||||
addButton("Pin Widget with config", "pinWidgetWithConfig");
|
||||
}
|
||||
|
||||
public void setCallback(PendingIntent callback) {
|
||||
mCallback = callback;
|
||||
}
|
||||
|
||||
public void setRemoteViewColor(int color) {
|
||||
mRemoteViewColor = color;
|
||||
}
|
||||
|
||||
public void setShortcutId(String id) {
|
||||
mShortcutId = id;
|
||||
}
|
||||
|
||||
public void pinShortcut() {
|
||||
ShortcutManager sm = getSystemService(ShortcutManager.class);
|
||||
|
||||
// Generate icon
|
||||
int r = sm.getIconMaxWidth() / 2;
|
||||
Bitmap icon = Bitmap.createBitmap(r * 2, r * 2, Bitmap.Config.ARGB_8888);
|
||||
Paint p = new Paint();
|
||||
p.setColor(Color.RED);
|
||||
new Canvas(icon).drawCircle(r, r, r, p);
|
||||
|
||||
ShortcutInfo info = new ShortcutInfo.Builder(this, mShortcutId)
|
||||
.setIntent(getPackageManager().getLaunchIntentForPackage(getPackageName()))
|
||||
.setIcon(Icon.createWithBitmap(icon))
|
||||
.setShortLabel("Test shortcut")
|
||||
.build();
|
||||
|
||||
IntentSender callback = mCallback == null ? null : mCallback.getIntentSender();
|
||||
sm.requestPinShortcut(info, callback);
|
||||
}
|
||||
|
||||
public void pinWidgetNoConfig() {
|
||||
requestWidget(new ComponentName(this, AppWidgetNoConfig.class));
|
||||
}
|
||||
|
||||
public void pinWidgetWithConfig() {
|
||||
requestWidget(new ComponentName(this, AppWidgetWithConfig.class));
|
||||
}
|
||||
|
||||
private void requestWidget(ComponentName cn) {
|
||||
Bundle extras = null;
|
||||
if (mRemoteViewColor != Color.TRANSPARENT) {
|
||||
int layoutId = getResources().getIdentifier(
|
||||
"test_layout_appwidget_view", "layout", getPackageName());
|
||||
RemoteViews views = new RemoteViews(getPackageName(), layoutId);
|
||||
views.setInt(android.R.id.icon, "setBackgroundColor", mRemoteViewColor);
|
||||
extras = new Bundle();
|
||||
extras.putParcelable(AppWidgetManager.EXTRA_APPWIDGET_PREVIEW, views);
|
||||
}
|
||||
|
||||
AppWidgetManager.getInstance(this).requestPinAppWidget(cn, extras, mCallback);
|
||||
}
|
||||
}
|
||||
129
tests/src/com/uiuipad/os/testcomponent/TestCommandReceiver.java
Normal file
129
tests/src/com/uiuipad/os/testcomponent/TestCommandReceiver.java
Normal file
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.uiuipad.os.testcomponent;
|
||||
|
||||
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
|
||||
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
|
||||
import static android.content.pm.PackageManager.DONT_KILL_APP;
|
||||
import static android.os.ParcelFileDescriptor.MODE_READ_WRITE;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.Instrumentation;
|
||||
import android.content.ComponentName;
|
||||
import android.content.ContentProvider;
|
||||
import android.content.ContentValues;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.util.Base64;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
|
||||
import androidx.test.InstrumentationRegistry;
|
||||
|
||||
/**
|
||||
* Content provider to receive commands from tests
|
||||
*/
|
||||
public class TestCommandReceiver extends ContentProvider {
|
||||
|
||||
public static final String ENABLE_TEST_LAUNCHER = "enable-test-launcher";
|
||||
public static final String DISABLE_TEST_LAUNCHER = "disable-test-launcher";
|
||||
public static final String KILL_PROCESS = "kill-process";
|
||||
|
||||
@Override
|
||||
public boolean onCreate() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int delete(Uri uri, String selection, String[] selectionArgs) {
|
||||
throw new UnsupportedOperationException("unimplemented mock method");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType(Uri uri) {
|
||||
throw new UnsupportedOperationException("unimplemented mock method");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Uri insert(Uri uri, ContentValues values) {
|
||||
throw new UnsupportedOperationException("unimplemented mock method");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
|
||||
String sortOrder) {
|
||||
throw new UnsupportedOperationException("unimplemented mock method");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
|
||||
throw new UnsupportedOperationException("unimplemented mock method");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bundle call(String method, String arg, Bundle extras) {
|
||||
switch (method) {
|
||||
case ENABLE_TEST_LAUNCHER: {
|
||||
getContext().getPackageManager().setComponentEnabledSetting(
|
||||
new ComponentName(getContext(), TestLauncherActivity.class),
|
||||
COMPONENT_ENABLED_STATE_ENABLED, DONT_KILL_APP);
|
||||
return null;
|
||||
}
|
||||
case DISABLE_TEST_LAUNCHER: {
|
||||
getContext().getPackageManager().setComponentEnabledSetting(
|
||||
new ComponentName(getContext(), TestLauncherActivity.class),
|
||||
COMPONENT_ENABLED_STATE_DISABLED, DONT_KILL_APP);
|
||||
return null;
|
||||
}
|
||||
case KILL_PROCESS: {
|
||||
((ActivityManager) getContext().getSystemService(Activity.ACTIVITY_SERVICE)).
|
||||
killBackgroundProcesses(arg);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return super.call(method, arg, extras);
|
||||
}
|
||||
|
||||
public static Bundle callCommand(String command) {
|
||||
return callCommand(command, null);
|
||||
}
|
||||
|
||||
public static Bundle callCommand(String command, String arg) {
|
||||
Instrumentation inst = InstrumentationRegistry.getInstrumentation();
|
||||
Uri uri = Uri.parse("content://" + inst.getContext().getPackageName() + ".commands");
|
||||
return inst.getTargetContext().getContentResolver().call(uri, command, arg, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
|
||||
String path = Base64.encodeToString(uri.getPath().getBytes(),
|
||||
Base64.NO_CLOSE | Base64.NO_PADDING | Base64.NO_WRAP);
|
||||
File file = new File(getContext().getCacheDir(), path);
|
||||
if (!file.exists()) {
|
||||
// Create an empty file so that we can pass its descriptor
|
||||
try {
|
||||
file.createNewFile();
|
||||
} catch (IOException e) { }
|
||||
}
|
||||
|
||||
return ParcelFileDescriptor.open(file, MODE_READ_WRITE);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.uiuipad.os.testcomponent;
|
||||
|
||||
import static android.content.Intent.ACTION_MAIN;
|
||||
import static android.content.Intent.CATEGORY_LAUNCHER;
|
||||
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
|
||||
import static android.content.Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED;
|
||||
|
||||
import android.app.LauncherActivity;
|
||||
import android.content.Intent;
|
||||
|
||||
public class TestLauncherActivity extends LauncherActivity {
|
||||
|
||||
@Override
|
||||
protected Intent getTargetIntent() {
|
||||
return new Intent(ACTION_MAIN, null)
|
||||
.addCategory(CATEGORY_LAUNCHER)
|
||||
.addFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
|
||||
}
|
||||
}
|
||||
275
tests/src/com/uiuipad/os/testcomponent/TouchEventGenerator.java
Normal file
275
tests/src/com/uiuipad/os/testcomponent/TouchEventGenerator.java
Normal file
@@ -0,0 +1,275 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.uiuipad.os.testcomponent;
|
||||
|
||||
import android.graphics.Point;
|
||||
import android.util.Pair;
|
||||
import android.view.InputDevice;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.MotionEvent.PointerCoords;
|
||||
import android.view.MotionEvent.PointerProperties;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Utility class to generate MotionEvent event sequences for testing touch gesture detectors.
|
||||
*/
|
||||
public class TouchEventGenerator {
|
||||
|
||||
/**
|
||||
* Amount of time between two generated events.
|
||||
*/
|
||||
private static final long TIME_INCREMENT_MS = 20L;
|
||||
|
||||
/**
|
||||
* Id of the fake device generating the events.
|
||||
*/
|
||||
private static final int DEVICE_ID = 2104;
|
||||
|
||||
/**
|
||||
* The fingers currently present on the emulated touch screen.
|
||||
*/
|
||||
private Map<Integer, Point> mFingers;
|
||||
|
||||
/**
|
||||
* Initial event time for the current sequence.
|
||||
*/
|
||||
private long mInitialTime;
|
||||
|
||||
/**
|
||||
* Time of the last generated event.
|
||||
*/
|
||||
private long mLastEventTime;
|
||||
|
||||
/**
|
||||
* Time of the next event.
|
||||
*/
|
||||
private long mTime;
|
||||
|
||||
/**
|
||||
* Receives the generated events.
|
||||
*/
|
||||
public interface Listener {
|
||||
|
||||
/**
|
||||
* Called when an event was generated.
|
||||
*/
|
||||
void onTouchEvent(MotionEvent event);
|
||||
}
|
||||
private final Listener mListener;
|
||||
|
||||
public TouchEventGenerator(Listener listener) {
|
||||
mListener = listener;
|
||||
mFingers = new HashMap<Integer, Point>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a finger on the touchscreen.
|
||||
*/
|
||||
public TouchEventGenerator put(int id, int x, int y, long ms) {
|
||||
checkFingerExistence(id, false);
|
||||
boolean isInitialDown = mFingers.isEmpty();
|
||||
mFingers.put(id, new Point(x, y));
|
||||
int action;
|
||||
if (isInitialDown) {
|
||||
action = MotionEvent.ACTION_DOWN;
|
||||
} else {
|
||||
action = MotionEvent.ACTION_POINTER_DOWN;
|
||||
// Set the id of the changed pointer.
|
||||
action |= id << MotionEvent.ACTION_POINTER_INDEX_SHIFT;
|
||||
}
|
||||
generateEvent(action, ms);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a finger on the touchscreen after advancing default time interval.
|
||||
*/
|
||||
public TouchEventGenerator put(int id, int x, int y) {
|
||||
return put(id, x, y, TIME_INCREMENT_MS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjusts the position of a finger for an upcoming move event.
|
||||
*
|
||||
* @see #move(long ms)
|
||||
*/
|
||||
public TouchEventGenerator position(int id, int x, int y) {
|
||||
checkFingerExistence(id, true);
|
||||
mFingers.get(id).set(x, y);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Commits the finger position changes of {@link #position(int, int, int)} by generating a move
|
||||
* event.
|
||||
*
|
||||
* @see #position(int, int, int)
|
||||
*/
|
||||
public TouchEventGenerator move(long ms) {
|
||||
generateEvent(MotionEvent.ACTION_MOVE, ms);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Commits the finger position changes of {@link #position(int, int, int)} by generating a move
|
||||
* event after advancing the default time interval.
|
||||
*
|
||||
* @see #position(int, int, int)
|
||||
*/
|
||||
public TouchEventGenerator move() {
|
||||
return move(TIME_INCREMENT_MS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves a single finger on the touchscreen.
|
||||
*/
|
||||
public TouchEventGenerator move(int id, int x, int y, long ms) {
|
||||
return position(id, x, y).move(ms);
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves a single finger on the touchscreen after advancing default time interval.
|
||||
*/
|
||||
public TouchEventGenerator move(int id, int x, int y) {
|
||||
return move(id, x, y, TIME_INCREMENT_MS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an existing finger from the touchscreen.
|
||||
*/
|
||||
public TouchEventGenerator lift(int id, long ms) {
|
||||
checkFingerExistence(id, true);
|
||||
boolean isFinalUp = mFingers.size() == 1;
|
||||
int action;
|
||||
if (isFinalUp) {
|
||||
action = MotionEvent.ACTION_UP;
|
||||
} else {
|
||||
action = MotionEvent.ACTION_POINTER_UP;
|
||||
// Set the id of the changed pointer.
|
||||
action |= id << MotionEvent.ACTION_POINTER_INDEX_SHIFT;
|
||||
}
|
||||
generateEvent(action, ms);
|
||||
mFingers.remove(id);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a finger from the touchscreen.
|
||||
*/
|
||||
public TouchEventGenerator lift(int id, int x, int y, long ms) {
|
||||
checkFingerExistence(id, true);
|
||||
mFingers.get(id).set(x, y);
|
||||
return lift(id, ms);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an existing finger from the touchscreen after advancing default time interval.
|
||||
*/
|
||||
public TouchEventGenerator lift(int id) {
|
||||
return lift(id, TIME_INCREMENT_MS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels an ongoing sequence.
|
||||
*/
|
||||
public TouchEventGenerator cancel(long ms) {
|
||||
generateEvent(MotionEvent.ACTION_CANCEL, ms);
|
||||
mFingers.clear();
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels an ongoing sequence.
|
||||
*/
|
||||
public TouchEventGenerator cancel() {
|
||||
return cancel(TIME_INCREMENT_MS);
|
||||
}
|
||||
|
||||
private void checkFingerExistence(int id, boolean shouldExist) {
|
||||
if (shouldExist != mFingers.containsKey(id)) {
|
||||
throw new IllegalArgumentException(
|
||||
shouldExist ? "Finger does not exist" : "Finger already exists");
|
||||
}
|
||||
}
|
||||
|
||||
private void generateEvent(int action, long ms) {
|
||||
mTime = mLastEventTime + ms;
|
||||
Pair<PointerProperties[], PointerCoords[]> state = getFingerState();
|
||||
MotionEvent event = MotionEvent.obtain(
|
||||
mInitialTime,
|
||||
mTime,
|
||||
action,
|
||||
state.first.length,
|
||||
state.first,
|
||||
state.second,
|
||||
0 /* metaState */,
|
||||
0 /* buttonState */,
|
||||
1.0f /* xPrecision */,
|
||||
1.0f /* yPrecision */,
|
||||
DEVICE_ID,
|
||||
0 /* edgeFlags */,
|
||||
InputDevice.SOURCE_TOUCHSCREEN,
|
||||
0 /* flags */);
|
||||
mListener.onTouchEvent(event);
|
||||
if (action == MotionEvent.ACTION_UP) {
|
||||
resetTime();
|
||||
}
|
||||
event.recycle();
|
||||
mLastEventTime = mTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the description of the fingers' state expected by MotionEvent.
|
||||
*/
|
||||
private Pair<PointerProperties[], PointerCoords[]> getFingerState() {
|
||||
int nFingers = mFingers.size();
|
||||
PointerProperties[] properties = new PointerProperties[nFingers];
|
||||
PointerCoords[] coordinates = new PointerCoords[nFingers];
|
||||
|
||||
int index = 0;
|
||||
for (Map.Entry<Integer, Point> entry : mFingers.entrySet()) {
|
||||
int id = entry.getKey();
|
||||
Point location = entry.getValue();
|
||||
|
||||
PointerProperties property = new PointerProperties();
|
||||
property.id = id;
|
||||
property.toolType = MotionEvent.TOOL_TYPE_FINGER;
|
||||
properties[index] = property;
|
||||
|
||||
PointerCoords coordinate = new PointerCoords();
|
||||
coordinate.x = location.x;
|
||||
coordinate.y = location.y;
|
||||
coordinate.pressure = 1.0f;
|
||||
coordinates[index] = coordinate;
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
return new Pair<MotionEvent.PointerProperties[], MotionEvent.PointerCoords[]>(
|
||||
properties, coordinates);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the time references for a new sequence.
|
||||
*/
|
||||
private void resetTime() {
|
||||
mInitialTime = 0L;
|
||||
mLastEventTime = -1L;
|
||||
mTime = 0L;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.uiuipad.os.testcomponent;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
/**
|
||||
* Simple activity for widget configuration
|
||||
*/
|
||||
public class WidgetConfigActivity extends BaseTestingActivity {
|
||||
|
||||
public static final String SUFFIX_FINISH = "-finish";
|
||||
public static final String EXTRA_CODE = "code";
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
addButton("Cancel", "clickCancel");
|
||||
addButton("OK", "clickOK");
|
||||
}
|
||||
|
||||
public void clickCancel() {
|
||||
setResult(RESULT_CANCELED);
|
||||
finish();
|
||||
}
|
||||
|
||||
public void clickOK() {
|
||||
setResult(RESULT_OK);
|
||||
finish();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user