Adding some tests for request pin shortcut/widget flow

Bug: 33584624
Change-Id: I49df36f60d2ae071b9d2c77c9c3300e010cd3bb9
This commit is contained in:
Sunny Goyal
2017-01-25 11:19:59 -08:00
parent 9f0fa84439
commit d9843357d0
12 changed files with 575 additions and 70 deletions
@@ -0,0 +1,126 @@
/*
* 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.android.launcher3.testcomponent;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
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);
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,89 @@
/*
* 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.android.launcher3.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;
/**
* Sample activity to request pinning an item.
*/
@TargetApi(26)
public class RequestPinItemActivity extends BaseTestingActivity {
private PendingIntent mCallback = null;
private String mShortcutId;
@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 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) {
AppWidgetManager.getInstance(this).requestPinAppWidget(cn, mCallback);
}
}
@@ -15,50 +15,30 @@
*/
package com.android.launcher3.testcomponent;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
/**
* Simple activity for widget configuration
*/
public class WidgetConfigActivity extends Activity {
public class WidgetConfigActivity extends BaseTestingActivity {
public static final String SUFFIX_FINISH = "-finish";
public static final String EXTRA_CODE = "code";
public static final String EXTRA_INTENT = "intent";
private final BroadcastReceiver mFinishReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
WidgetConfigActivity.this.setResult(
intent.getIntExtra(EXTRA_CODE, RESULT_CANCELED),
(Intent) intent.getParcelableExtra(EXTRA_INTENT));
WidgetConfigActivity.this.finish();
}
};
private final String mAction = this.getClass().getName();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
registerReceiver(mFinishReceiver, new IntentFilter(mAction + SUFFIX_FINISH));
addButton("Cancel", "clickCancel");
addButton("OK", "clickOK");
}
@Override
protected void onResume() {
super.onResume();
sendBroadcast(new Intent(mAction).putExtra(Intent.EXTRA_INTENT, getIntent()));
public void clickCancel() {
setResult(RESULT_CANCELED);
finish();
}
@Override
protected void onDestroy() {
unregisterReceiver(mFinishReceiver);
super.onDestroy();
public void clickOK() {
setResult(RESULT_OK);
finish();
}
}
@@ -22,6 +22,7 @@ public class AllAppsIconToHomeTest extends LauncherInstrumentationTestCase {
@Override
protected void setUp() throws Exception {
super.setUp();
setDefaultLauncher();
mSettingsApp = LauncherAppsCompat.getInstance(mTargetContext)
.getActivityList("com.android.settings", Process.myUserHandle()).get(0);
@@ -15,10 +15,14 @@
*/
package com.android.launcher3.ui;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.graphics.Point;
import android.os.ParcelFileDescriptor;
import android.os.Process;
@@ -46,16 +50,24 @@ import com.android.launcher3.testcomponent.AppWidgetNoConfig;
import com.android.launcher3.testcomponent.AppWidgetWithConfig;
import com.android.launcher3.util.ManagedProfileHeuristic;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Locale;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
/**
* Base class for all instrumentation tests providing various utility methods.
*/
public class LauncherInstrumentationTestCase extends InstrumentationTestCase {
public static final long DEFAULT_ACTIVITY_TIMEOUT = TimeUnit.SECONDS.toMillis(10);
public static final long DEFAULT_BROADCAST_TIMEOUT_SECS = 5;
public static final long DEFAULT_UI_TIMEOUT = 3000;
public static final long DEFAULT_WORKER_TIMEOUT_SECS = 5;
@@ -89,11 +101,14 @@ public class LauncherInstrumentationTestCase extends InstrumentationTestCase {
* Starts the launcher activity in the target package and returns the Launcher instance.
*/
protected Launcher startLauncher() {
Intent homeIntent = new Intent(Intent.ACTION_MAIN)
return (Launcher) getInstrumentation().startActivitySync(getHomeIntent());
}
protected Intent getHomeIntent() {
return new Intent(Intent.ACTION_MAIN)
.addCategory(Intent.CATEGORY_HOME)
.setPackage(mTargetPackage)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
return (Launcher) getInstrumentation().startActivitySync(homeIntent);
}
/**
@@ -104,15 +119,30 @@ public class LauncherInstrumentationTestCase extends InstrumentationTestCase {
if (mTargetContext.getPackageManager().checkPermission(
mTargetPackage, android.Manifest.permission.BIND_APPWIDGET)
!= PackageManager.PERMISSION_GRANTED) {
ParcelFileDescriptor pfd = getInstrumentation().getUiAutomation().executeShellCommand(
"appwidget grantbind --package " + mTargetPackage);
// Read the input stream fully.
FileInputStream fis = new ParcelFileDescriptor.AutoCloseInputStream(pfd);
while (fis.read() != -1);
fis.close();
runShellCommand("appwidget grantbind --package " + mTargetPackage);
}
}
/**
* Sets the target launcher as default launcher.
*/
protected void setDefaultLauncher() throws IOException {
ActivityInfo launcher = mTargetContext.getPackageManager()
.queryIntentActivities(getHomeIntent(), 0).get(0).activityInfo;
runShellCommand("cmd package set-home-activity " +
new ComponentName(launcher.packageName, launcher.name).flattenToString());
}
protected void runShellCommand(String command) throws IOException {
ParcelFileDescriptor pfd = getInstrumentation().getUiAutomation()
.executeShellCommand(command);
// Read the input stream fully.
FileInputStream fis = new ParcelFileDescriptor.AutoCloseInputStream(pfd);
while (fis.read() != -1);
fis.close();
}
/**
* Opens all apps and returns the recycler view
*/
@@ -285,4 +315,35 @@ public class LauncherInstrumentationTestCase extends InstrumentationTestCase {
String name = mTargetContext.getResources().getResourceEntryName(id);
return By.res(mTargetPackage, name);
}
/**
* Broadcast receiver which blocks until the result is received.
*/
public class BlockingBroadcastReceiver extends BroadcastReceiver {
private final CountDownLatch latch = new CountDownLatch(1);
private Intent mIntent;
public BlockingBroadcastReceiver(String action) {
mTargetContext.registerReceiver(this, new IntentFilter(action));
}
@Override
public void onReceive(Context context, Intent intent) {
mIntent = intent;
latch.countDown();
}
public Intent blockingGetIntent() throws InterruptedException {
latch.await(DEFAULT_BROADCAST_TIMEOUT_SECS, TimeUnit.SECONDS);
mTargetContext.unregisterReceiver(this);
return mIntent;
}
public Intent blockingGetExtraIntent() throws InterruptedException {
Intent intent = blockingGetIntent();
return intent == null ? null : (Intent) intent.getParcelableExtra(Intent.EXTRA_INTENT);
}
}
}
@@ -25,6 +25,7 @@ public class ShortcutsLaunchTest extends LauncherInstrumentationTestCase {
@Override
protected void setUp() throws Exception {
super.setUp();
setDefaultLauncher();
mSettingsApp = LauncherAppsCompat.getInstance(mTargetContext)
.getActivityList("com.android.settings", Process.myUserHandle()).get(0);
@@ -25,6 +25,7 @@ public class ShortcutsToHomeTest extends LauncherInstrumentationTestCase {
@Override
protected void setUp() throws Exception {
super.setUp();
setDefaultLauncher();
mSettingsApp = LauncherAppsCompat.getInstance(mTargetContext)
.getActivityList("com.android.settings", Process.myUserHandle()).get(0);
@@ -18,10 +18,7 @@ package com.android.launcher3.ui.widget;
import android.app.Activity;
import android.app.Application;
import android.appwidget.AppWidgetManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.support.test.uiautomator.By;
import android.support.test.uiautomator.UiObject2;
import android.test.suitebuilder.annotation.LargeTest;
@@ -41,8 +38,6 @@ import com.android.launcher3.util.Wait;
import com.android.launcher3.widget.WidgetCell;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
/**
* Test to verify widget configuration is properly shown.
@@ -50,9 +45,6 @@ import java.util.concurrent.TimeUnit;
@LargeTest
public class AddConfigWidgetTest extends LauncherInstrumentationTestCase {
public static final long DEFAULT_ACTIVITY_TIMEOUT = TimeUnit.SECONDS.toMillis(10);
public static final long DEFAULT_BROADCAST_TIMEOUT_SECS = 5;
private LauncherAppWidgetProviderInfo mWidgetInfo;
private SimpleActivityMonitor mActivityMonitor;
private MainThreadExecutor mMainThreadExecutor;
@@ -69,6 +61,8 @@ public class AddConfigWidgetTest extends LauncherInstrumentationTestCase {
.registerActivityLifecycleCallbacks(mActivityMonitor);
mMainThreadExecutor = new MainThreadExecutor();
mAppWidgetManager = AppWidgetManager.getInstance(mTargetContext);
grantWidgetPermission();
}
@Override
@@ -126,12 +120,11 @@ public class AddConfigWidgetTest extends LauncherInstrumentationTestCase {
// Verify that the widget id is valid and bound
assertNotNull(mAppWidgetManager.getAppWidgetInfo(mWidgetId));
setResult(acceptConfig);
if (acceptConfig) {
setResult(Activity.RESULT_OK);
assertTrue(Wait.atMost(new WidgetSearchCondition(), DEFAULT_ACTIVITY_TIMEOUT));
assertNotNull(mAppWidgetManager.getAppWidgetInfo(mWidgetId));
} else {
setResult(Activity.RESULT_CANCELED);
// Verify that the widget id is deleted.
assertTrue(Wait.atMost(new Condition() {
@Override
@@ -142,10 +135,11 @@ public class AddConfigWidgetTest extends LauncherInstrumentationTestCase {
}
}
private void setResult(int resultCode) {
String action = WidgetConfigActivity.class.getName() + WidgetConfigActivity.SUFFIX_FINISH;
private void setResult(boolean success) {
getInstrumentation().getTargetContext().sendBroadcast(
new Intent(action).putExtra(WidgetConfigActivity.EXTRA_CODE, resultCode));
WidgetConfigActivity.getCommandIntent(WidgetConfigActivity.class,
success ? "clickOK" : "clickCancel"));
}
/**
@@ -185,28 +179,17 @@ public class AddConfigWidgetTest extends LauncherInstrumentationTestCase {
/**
* Broadcast receiver for receiving widget config activity status.
*/
private class WidgetConfigStartupMonitor extends BroadcastReceiver {
private class WidgetConfigStartupMonitor extends BlockingBroadcastReceiver {
private final CountDownLatch latch = new CountDownLatch(1);
private Intent mIntent;
WidgetConfigStartupMonitor() {
getInstrumentation().getTargetContext().registerReceiver(this,
new IntentFilter(WidgetConfigActivity.class.getName()));
}
@Override
public void onReceive(Context context, Intent intent) {
mIntent = intent.getParcelableExtra(Intent.EXTRA_INTENT);
latch.countDown();
public WidgetConfigStartupMonitor() {
super(WidgetConfigActivity.class.getName());
}
public int getWidgetId() throws InterruptedException {
latch.await(DEFAULT_BROADCAST_TIMEOUT_SECS, TimeUnit.SECONDS);
getInstrumentation().getTargetContext().unregisterReceiver(this);
assertNotNull(mIntent);
assertEquals(AppWidgetManager.ACTION_APPWIDGET_CONFIGURE, mIntent.getAction());
int widgetId = mIntent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
Intent intent = blockingGetExtraIntent();
assertNotNull(intent);
assertEquals(AppWidgetManager.ACTION_APPWIDGET_CONFIGURE, intent.getAction());
int widgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
LauncherAppWidgetInfo.NO_ID);
assertNotSame(widgetId, LauncherAppWidgetInfo.NO_ID);
return widgetId;
@@ -41,6 +41,7 @@ public class AddWidgetTest extends LauncherInstrumentationTestCase {
@Override
protected void setUp() throws Exception {
super.setUp();
grantWidgetPermission();
widgetInfo = findWidgetProvider(false /* hasConfigureScreen */);
}
@@ -0,0 +1,210 @@
/*
* 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.android.launcher3.ui.widget;
import android.app.Activity;
import android.app.Application;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.content.Intent;
import android.support.test.uiautomator.By;
import android.support.test.uiautomator.UiObject2;
import android.support.test.uiautomator.Until;
import android.test.suitebuilder.annotation.LargeTest;
import android.view.View;
import com.android.launcher3.ItemInfo;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAppWidgetInfo;
import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.MainThreadExecutor;
import com.android.launcher3.R;
import com.android.launcher3.ShortcutInfo;
import com.android.launcher3.Utilities;
import com.android.launcher3.Workspace.ItemOperator;
import com.android.launcher3.shortcuts.ShortcutKey;
import com.android.launcher3.testcomponent.AppWidgetNoConfig;
import com.android.launcher3.testcomponent.AppWidgetWithConfig;
import com.android.launcher3.testcomponent.RequestPinItemActivity;
import com.android.launcher3.ui.LauncherInstrumentationTestCase;
import com.android.launcher3.util.Condition;
import com.android.launcher3.util.SimpleActivityMonitor;
import com.android.launcher3.util.Wait;
import com.android.launcher3.widget.WidgetCell;
import java.util.UUID;
import java.util.concurrent.Callable;
/**
* Test to verify pin item request flow.
*/
@LargeTest
public class RequestPinItemTest extends LauncherInstrumentationTestCase {
private SimpleActivityMonitor mActivityMonitor;
private MainThreadExecutor mMainThreadExecutor;
private String mCallbackAction;
private String mShortcutId;
private int mAppWidgetId;
@Override
protected void setUp() throws Exception {
super.setUp();
grantWidgetPermission();
setDefaultLauncher();
mActivityMonitor = new SimpleActivityMonitor();
((Application) getInstrumentation().getTargetContext().getApplicationContext())
.registerActivityLifecycleCallbacks(mActivityMonitor);
mMainThreadExecutor = new MainThreadExecutor();
mCallbackAction = UUID.randomUUID().toString();
mShortcutId = UUID.randomUUID().toString();
}
@Override
protected void tearDown() throws Exception {
((Application) getInstrumentation().getTargetContext().getApplicationContext())
.unregisterActivityLifecycleCallbacks(mActivityMonitor);
super.tearDown();
}
public void testPinWidgetNoConfig() throws Throwable {
runTest("pinWidgetNoConfig", true, new ItemOperator() {
@Override
public boolean evaluate(ItemInfo info, View view) {
return info instanceof LauncherAppWidgetInfo &&
((LauncherAppWidgetInfo) info).appWidgetId == mAppWidgetId &&
((LauncherAppWidgetInfo) info).providerName.getClassName()
.equals(AppWidgetNoConfig.class.getName());
}
});
}
public void testPinWidgetWithConfig() throws Throwable {
runTest("pinWidgetWithConfig", true, new ItemOperator() {
@Override
public boolean evaluate(ItemInfo info, View view) {
return info instanceof LauncherAppWidgetInfo &&
((LauncherAppWidgetInfo) info).appWidgetId == mAppWidgetId &&
((LauncherAppWidgetInfo) info).providerName.getClassName()
.equals(AppWidgetWithConfig.class.getName());
}
});
}
public void testPinWidgetShortcut() throws Throwable {
runTest("pinShortcut", false, new ItemOperator() {
@Override
public boolean evaluate(ItemInfo info, View view) {
return info instanceof ShortcutInfo &&
info.itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT &&
ShortcutKey.fromItemInfo(info).getId().equals(mShortcutId);
}
});
}
private void runTest(String activityMethod, boolean isWidget, ItemOperator itemMatcher)
throws Throwable {
if (!Utilities.isAtLeastO()) {
return;
}
lockRotation(true);
clearHomescreen();
startLauncher();
// Open all apps and wait for load complete
final UiObject2 appsContainer = openAllApps();
assertTrue(Wait.atMost(Condition.minChildCount(appsContainer, 2), DEFAULT_UI_TIMEOUT));
// Open Pin item activity
BlockingBroadcastReceiver openMonitor = new BlockingBroadcastReceiver(
RequestPinItemActivity.class.getName());
scrollAndFind(appsContainer, By.text("Test Pin Item")).click();
assertNotNull(openMonitor.blockingGetExtraIntent());
// Set callback
PendingIntent callback = PendingIntent.getBroadcast(mTargetContext, 0,
new Intent(mCallbackAction), PendingIntent.FLAG_ONE_SHOT);
mTargetContext.sendBroadcast(RequestPinItemActivity.getCommandIntent(
RequestPinItemActivity.class, "setCallback").putExtra(
RequestPinItemActivity.EXTRA_PARAM + "0", callback));
if (!isWidget) {
// Set shortcut id
mTargetContext.sendBroadcast(RequestPinItemActivity.getCommandIntent(
RequestPinItemActivity.class, "setShortcutId").putExtra(
RequestPinItemActivity.EXTRA_PARAM + "0", mShortcutId));
}
// call the requested method to start the flow
mTargetContext.sendBroadcast(RequestPinItemActivity.getCommandIntent(
RequestPinItemActivity.class, activityMethod));
UiObject2 widgetCell = mDevice.wait(
Until.findObject(By.clazz(WidgetCell.class)), DEFAULT_ACTIVITY_TIMEOUT);
assertNotNull(widgetCell);
// Accept confirmation:
BlockingBroadcastReceiver resultReceiver = new BlockingBroadcastReceiver(mCallbackAction);
mDevice.wait(Until.findObject(By.text(mTargetContext.getString(
R.string.place_automatically).toUpperCase())), DEFAULT_UI_TIMEOUT).click();
Intent result = resultReceiver.blockingGetIntent();
assertNotNull(result);
mAppWidgetId = result.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);
if (isWidget) {
assertNotSame(-1, mAppWidgetId);
}
// Go back to home
mTargetContext.startActivity(getHomeIntent());
assertTrue(Wait.atMost(new ItemSearchCondition(itemMatcher), DEFAULT_ACTIVITY_TIMEOUT));
}
/**
* Condition for for an item
*/
private class ItemSearchCondition extends Condition implements Callable<Boolean> {
private final ItemOperator mOp;
ItemSearchCondition(ItemOperator op) {
mOp = op;
}
@Override
public boolean isTrue() throws Throwable {
return mMainThreadExecutor.submit(this).get();
}
@Override
public Boolean call() throws Exception {
// Find the resumed launcher
Launcher launcher = null;
for (Activity a : mActivityMonitor.resumed) {
if (a instanceof Launcher) {
launcher = (Launcher) a;
}
}
if (launcher == null) {
return false;
}
return launcher.getWorkspace().getFirstMatch(mOp) != null;
}
}
}