Merge "Add new config and API for QuickAccessWallet features."

This commit is contained in:
TreeHugger Robot
2022-02-08 05:56:08 +00:00
committed by Android (Google) Code Review
12 changed files with 270 additions and 13 deletions

View File

@@ -1642,6 +1642,7 @@ package android {
field public static final int useEmbeddedDex = 16844190; // 0x101059e
field public static final int useIntrinsicSizeAsMinimum = 16843536; // 0x1010310
field public static final int useLevel = 16843167; // 0x101019f
field public static final int useTargetActivityForQuickAccess;
field public static final int userVisible = 16843409; // 0x1010291
field public static final int usesCleartextTraffic = 16844012; // 0x10104ec
field public static final int usesPermissionFlags = 16844356; // 0x1010644
@@ -38995,6 +38996,7 @@ package android.service.quickaccesswallet {
public abstract class QuickAccessWalletService extends android.app.Service {
ctor public QuickAccessWalletService();
method @Nullable public android.app.PendingIntent getTargetActivityPendingIntent();
method @Nullable public android.os.IBinder onBind(@NonNull android.content.Intent);
method public abstract void onWalletCardSelected(@NonNull android.service.quickaccesswallet.SelectWalletCardRequest);
method public abstract void onWalletCardsRequested(@NonNull android.service.quickaccesswallet.GetWalletCardsRequest, @NonNull android.service.quickaccesswallet.GetWalletCardsCallback);

View File

@@ -2357,12 +2357,14 @@ package android.service.quickaccesswallet {
method public void disconnect();
method public void getWalletCards(@NonNull android.service.quickaccesswallet.GetWalletCardsRequest, @NonNull android.service.quickaccesswallet.QuickAccessWalletClient.OnWalletCardsRetrievedCallback);
method public void getWalletCards(@NonNull java.util.concurrent.Executor, @NonNull android.service.quickaccesswallet.GetWalletCardsRequest, @NonNull android.service.quickaccesswallet.QuickAccessWalletClient.OnWalletCardsRetrievedCallback);
method public void getWalletPendingIntent(@NonNull java.util.concurrent.Executor, @NonNull android.service.quickaccesswallet.QuickAccessWalletClient.WalletPendingIntentCallback);
method public boolean isWalletFeatureAvailable();
method public boolean isWalletFeatureAvailableWhenDeviceLocked();
method public boolean isWalletServiceAvailable();
method public void notifyWalletDismissed();
method public void removeWalletServiceEventListener(@NonNull android.service.quickaccesswallet.QuickAccessWalletClient.WalletServiceEventListener);
method public void selectWalletCard(@NonNull android.service.quickaccesswallet.SelectWalletCardRequest);
method public boolean useTargetActivityForQuickAccess();
}
public static interface QuickAccessWalletClient.OnWalletCardsRetrievedCallback {
@@ -2370,6 +2372,10 @@ package android.service.quickaccesswallet {
method public void onWalletCardsRetrieved(@NonNull android.service.quickaccesswallet.GetWalletCardsResponse);
}
public static interface QuickAccessWalletClient.WalletPendingIntentCallback {
method public void onWalletPendingIntentRetrieved(@Nullable android.app.PendingIntent);
}
public static interface QuickAccessWalletClient.WalletServiceEventListener {
method public void onWalletServiceEvent(@NonNull android.service.quickaccesswallet.WalletServiceEvent);
}

View File

@@ -41,4 +41,6 @@ interface IQuickAccessWalletService {
in IQuickAccessWalletServiceCallbacks callback);
// Unregister an event listener
oneway void unregisterWalletServiceEventListener(in WalletServiceEventListenerRequest request);
}
// Request to get a PendingIntent to launch an activity from which the user can manage their cards.
oneway void onTargetActivityIntentRequested(in IQuickAccessWalletServiceCallbacks callbacks);
}

View File

@@ -16,6 +16,7 @@
package android.service.quickaccesswallet;
import android.app.PendingIntent;
import android.service.quickaccesswallet.GetWalletCardsError;
import android.service.quickaccesswallet.GetWalletCardsResponse;
import android.service.quickaccesswallet.WalletServiceEvent;
@@ -34,4 +35,6 @@ interface IQuickAccessWalletServiceCallbacks {
// Called in response to registerWalletServiceEventListener. May be called multiple times as
// long as the event listener is registered.
oneway void onWalletServiceEvent(in WalletServiceEvent event);
// Called in response to onTargetActivityIntentRequested. May only be called once per request.
oneway void onTargetActivityPendingIntentReceived(in PendingIntent pendingIntent);
}

View File

@@ -20,6 +20,7 @@ import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Drawable;
@@ -152,6 +153,21 @@ public interface QuickAccessWalletClient extends Closeable {
*/
void disconnect();
/**
* The QuickAccessWalletService may provide a {@link PendingIntent} to start the activity that
* hosts the Wallet view. This is typically the home screen of the Wallet application. If this
* method returns null, the value returned by getWalletIntent() will be used instead.
*/
void getWalletPendingIntent(@NonNull @CallbackExecutor Executor executor,
@NonNull WalletPendingIntentCallback walletPendingIntentCallback);
/**
* Callback for getWalletPendingIntent.
*/
interface WalletPendingIntentCallback {
void onWalletPendingIntentRetrieved(@Nullable PendingIntent walletPendingIntent);
}
/**
* The manifest entry for the QuickAccessWalletService may also publish information about the
* activity that hosts the Wallet view. This is typically the home screen of the Wallet
@@ -212,4 +228,15 @@ public interface QuickAccessWalletClient extends Closeable {
*/
@Nullable
CharSequence getShortcutLongLabel();
/**
* Return whether the system should use the component specified by the
* {@link android:targetActivity} or
* {@link QuickAccessWalletService#getTargetActivityPendingIntent()}
* as the "quick access" , invoked directly by the system.
* If false, the system will use the built-in UI instead of the component specified
* in {@link android:targetActivity} or
* {@link QuickAccessWalletService#getTargetActivityPendingIntent()}.
*/
boolean useTargetActivityForQuickAccess();
}

View File

@@ -24,6 +24,7 @@ import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -67,10 +68,9 @@ public class QuickAccessWalletClientImpl implements QuickAccessWalletClient, Ser
private final Queue<ApiCaller> mRequestQueue;
private final Map<WalletServiceEventListener, String> mEventListeners;
private boolean mIsConnected;
/**
* Timeout for active service connections (1 minute)
*/
/** Timeout for active service connections (1 minute) */
private static final long SERVICE_CONNECTION_TIMEOUT_MS = 60 * 1000;
@Nullable
private IQuickAccessWalletService mService;
@@ -146,7 +146,6 @@ public class QuickAccessWalletClientImpl implements QuickAccessWalletClient, Ser
serviceCallback.onGetWalletCardsFailure(new GetWalletCardsError(null, null));
}
});
}
@Override
@@ -246,6 +245,25 @@ public class QuickAccessWalletClientImpl implements QuickAccessWalletClient, Ser
return createIntent(walletActivity, packageName, ACTION_VIEW_WALLET);
}
@Override
public void getWalletPendingIntent(
@NonNull @CallbackExecutor Executor executor,
@NonNull WalletPendingIntentCallback pendingIntentCallback) {
BaseCallbacks callbacks = new BaseCallbacks() {
@Override
public void onTargetActivityPendingIntentReceived(PendingIntent pendingIntent) {
executor.execute(
() -> pendingIntentCallback.onWalletPendingIntentRetrieved(pendingIntent));
}
};
executeApiCall(new ApiCaller("getTargetActivityPendingIntent") {
@Override
void performApiCall(IQuickAccessWalletService service) throws RemoteException {
service.onTargetActivityIntentRequested(callbacks);
}
});
}
@Override
@Nullable
public Intent createWalletSettingsIntent() {
@@ -330,6 +348,11 @@ public class QuickAccessWalletClientImpl implements QuickAccessWalletClient, Ser
return mServiceInfo == null ? null : mServiceInfo.getShortcutLongLabel(mContext);
}
@Override
public boolean useTargetActivityForQuickAccess() {
return mServiceInfo.getUseTargetActivityForQuickAccess();
}
private void connect() {
mHandler.post(this::connectInternal);
}
@@ -388,7 +411,7 @@ public class QuickAccessWalletClientImpl implements QuickAccessWalletClient, Ser
return;
}
mIsConnected = false;
mContext.unbindService(/*conn=*/this);
mContext.unbindService(/*conn=*/ this);
mService = null;
mEventListeners.clear();
mRequestQueue.clear();
@@ -482,5 +505,9 @@ public class QuickAccessWalletClientImpl implements QuickAccessWalletClient, Ser
public void onWalletServiceEvent(WalletServiceEvent event) {
throw new IllegalStateException();
}
public void onTargetActivityPendingIntentReceived(PendingIntent pendingIntent) {
throw new IllegalStateException();
}
}
}

View File

@@ -19,6 +19,7 @@ package android.service.quickaccesswallet;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SdkConstant;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.os.Build;
@@ -238,6 +239,14 @@ public abstract class QuickAccessWalletService extends Service {
mHandler.post(QuickAccessWalletService.this::onWalletDismissed);
}
@Override
public void onTargetActivityIntentRequested(
@NonNull IQuickAccessWalletServiceCallbacks callbacks) {
mHandler.post(
() -> QuickAccessWalletService.this.onTargetActivityIntentRequestedInternal(
callbacks));
}
public void registerWalletServiceEventListener(
@NonNull WalletServiceEventListenerRequest request,
@NonNull IQuickAccessWalletServiceCallbacks callback) {
@@ -257,6 +266,15 @@ public abstract class QuickAccessWalletService extends Service {
new GetWalletCardsCallbackImpl(request, callback, mHandler));
}
private void onTargetActivityIntentRequestedInternal(
IQuickAccessWalletServiceCallbacks callbacks) {
try {
callbacks.onTargetActivityPendingIntentReceived(getTargetActivityPendingIntent());
} catch (RemoteException e) {
Log.w(TAG, "Error returning wallet cards", e);
}
}
@Override
@Nullable
public IBinder onBind(@NonNull Intent intent) {
@@ -318,6 +336,11 @@ public abstract class QuickAccessWalletService extends Service {
mHandler.post(() -> sendWalletServiceEventInternal(serviceEvent));
}
@Nullable
public PendingIntent getTargetActivityPendingIntent() {
return null;
}
private void sendWalletServiceEventInternal(WalletServiceEvent serviceEvent) {
if (mEventListener == null) {
Log.i(TAG, "No dismiss listener registered");

View File

@@ -144,20 +144,23 @@ class QuickAccessWalletServiceInfo {
private final CharSequence mShortcutShortLabel;
@Nullable
private final CharSequence mShortcutLongLabel;
private final boolean mUseTargetActivityForQuickAccess;
private static ServiceMetadata empty() {
return new ServiceMetadata(null, null, null, null);
return new ServiceMetadata(null, null, null, null, false);
}
private ServiceMetadata(
String targetActivity,
String settingsActivity,
CharSequence shortcutShortLabel,
CharSequence shortcutLongLabel) {
CharSequence shortcutLongLabel,
boolean useTargetActivityForQuickAccess) {
mTargetActivity = targetActivity;
mSettingsActivity = settingsActivity;
mShortcutShortLabel = shortcutShortLabel;
mShortcutLongLabel = shortcutLongLabel;
mUseTargetActivityForQuickAccess = useTargetActivityForQuickAccess;
}
}
@@ -191,8 +194,11 @@ class QuickAccessWalletServiceInfo {
R.styleable.QuickAccessWalletService_shortcutShortLabel);
CharSequence shortcutLongLabel = afsAttributes.getText(
R.styleable.QuickAccessWalletService_shortcutLongLabel);
boolean useTargetActivityForQuickAccess = afsAttributes.getBoolean(
R.styleable.QuickAccessWalletService_useTargetActivityForQuickAccess,
false);
return new ServiceMetadata(targetActivity, settingsActivity, shortcutShortLabel,
shortcutLongLabel);
shortcutLongLabel, useTargetActivityForQuickAccess);
} finally {
if (afsAttributes != null) {
afsAttributes.recycle();
@@ -271,4 +277,8 @@ class QuickAccessWalletServiceInfo {
CharSequence getServiceLabel(Context context) {
return mServiceInfo.loadLabel(context.getPackageManager());
}
boolean getUseTargetActivityForQuickAccess() {
return mServiceMetadata.mUseTargetActivityForQuickAccess;
}
}

View File

@@ -8821,7 +8821,8 @@
<attr name="shortcutLongLabel"/>
<!-- Text shown on the button that takes users to the wallet application -->
<attr name="shortcutShortLabel"/>
<!-- When true, launch the component specified in targetActivity for quick access -->
<attr name="useTargetActivityForQuickAccess" format="boolean"/>
</declare-styleable>
<!-- Use <code>recognition-service</code> as the root tag of the XML resource that

View File

@@ -3262,6 +3262,7 @@
<public name="allowGameFpsOverride" />
<public name="localeConfig" />
<public name="showBackground" />
<public name="useTargetActivityForQuickAccess"/>
<public name="inheritKeyStoreKeys" />
<public name="preferKeepClear" />
<public name="autoHandwritingEnabled" />

View File

@@ -19,7 +19,10 @@ package com.android.systemui.wallet.controller;
import static com.android.systemui.wallet.controller.QuickAccessWalletController.WalletChangeEvent.DEFAULT_PAYMENT_APP_CHANGE;
import static com.android.systemui.wallet.controller.QuickAccessWalletController.WalletChangeEvent.WALLET_PREFERENCE_CHANGE;
import android.annotation.CallbackExecutor;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.database.ContentObserver;
import android.provider.Settings;
import android.service.quickaccesswallet.GetWalletCardsRequest;
@@ -28,10 +31,13 @@ import android.service.quickaccesswallet.QuickAccessWalletClientImpl;
import android.util.Log;
import com.android.systemui.R;
import com.android.systemui.animation.ActivityLaunchAnimator;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.util.settings.SecureSettings;
import com.android.systemui.util.time.SystemClock;
import com.android.systemui.wallet.ui.WalletActivity;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
@@ -57,6 +63,7 @@ public class QuickAccessWalletController {
private static final long RECREATION_TIME_WINDOW = TimeUnit.MINUTES.toMillis(10L);
private final Context mContext;
private final Executor mExecutor;
private final Executor mCallbackExecutor;
private final SecureSettings mSecureSettings;
private final SystemClock mClock;
@@ -72,11 +79,13 @@ public class QuickAccessWalletController {
public QuickAccessWalletController(
Context context,
@Main Executor executor,
@CallbackExecutor Executor callbackExecutor,
SecureSettings secureSettings,
QuickAccessWalletClient quickAccessWalletClient,
SystemClock clock) {
mContext = context;
mExecutor = executor;
mCallbackExecutor = callbackExecutor;
mSecureSettings = secureSettings;
mQuickAccessWalletClient = quickAccessWalletClient;
mClock = clock;
@@ -117,7 +126,6 @@ public class QuickAccessWalletController {
/**
* Unregister wallet change observers per {@link WalletChangeEvent} if needed.
*
*/
public void unregisterWalletChangeObservers(WalletChangeEvent... events) {
for (WalletChangeEvent event : events) {
@@ -178,6 +186,80 @@ public class QuickAccessWalletController {
mQawClientCreatedTimeMillis = mClock.elapsedRealtime();
}
/**
* Starts the QuickAccessWallet UI: either the app's designated UI, or the built-in Wallet UI.
*
* If the service has configured itself so that
* {@link QuickAccessWalletClient#useTargetActivityForQuickAccess()}
* is true, or the service isn't providing any cards, use the target activity. Otherwise, use
* the SysUi {@link WalletActivity}
*
* The Wallet target activity is defined as the {@link android.app.PendingIntent} returned by
* {@link QuickAccessWalletClient#getWalletPendingIntent} if that is not null. If that is null,
* then the {@link Intent} returned by {@link QuickAccessWalletClient#createWalletIntent()}. If
* that too is null, then fall back to {@link WalletActivity}.
*
* @param activityStarter an {@link ActivityStarter} to launch the Intent or PendingIntent.
* @param animationController an {@link ActivityLaunchAnimator.Controller} to provide a
* smooth animation for the activity launch.
* @param hasCard whether the service returns any cards.
*/
public void startQuickAccessUiIntent(ActivityStarter activityStarter,
ActivityLaunchAnimator.Controller animationController,
boolean hasCard) {
if (mQuickAccessWalletClient.useTargetActivityForQuickAccess() || !hasCard) {
mQuickAccessWalletClient.getWalletPendingIntent(mCallbackExecutor,
walletPendingIntent -> {
if (walletPendingIntent == null) {
Intent intent = mQuickAccessWalletClient.createWalletIntent();
if (intent == null) {
intent = getSysUiWalletIntent();
}
startQuickAccessViaIntent(intent, hasCard, activityStarter,
animationController);
return;
}
startQuickAccessViaPendingIntent(walletPendingIntent,
activityStarter, animationController);
});
} else {
startQuickAccessViaIntent(getSysUiWalletIntent(),
hasCard,
activityStarter,
animationController);
}
}
private Intent getSysUiWalletIntent() {
return new Intent(mContext, WalletActivity.class)
.setAction(Intent.ACTION_VIEW);
}
private void startQuickAccessViaIntent(Intent intent,
boolean hasCard,
ActivityStarter activityStarter,
ActivityLaunchAnimator.Controller animationController) {
if (hasCard) {
activityStarter.startActivity(intent, true /* dismissShade */,
animationController, true /* showOverLockscreenWhenLocked */);
} else {
activityStarter.postStartActivityDismissingKeyguard(
intent,
/* delay= */ 0,
animationController);
}
}
private void startQuickAccessViaPendingIntent(PendingIntent pendingIntent,
ActivityStarter activityStarter,
ActivityLaunchAnimator.Controller animationController) {
activityStarter.postStartActivityDismissingKeyguard(
pendingIntent,
animationController);
}
private void setupDefaultPaymentAppObserver(
QuickAccessWalletClient.OnWalletCardsRetrievedCallback cardsRetriever) {
if (mDefaultPaymentAppObserver == null) {

View File

@@ -23,10 +23,13 @@ import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.PendingIntent;
import android.content.Intent;
import android.service.quickaccesswallet.GetWalletCardsRequest;
import android.service.quickaccesswallet.QuickAccessWalletClient;
import android.testing.AndroidTestingRunner;
@@ -36,6 +39,8 @@ import androidx.test.filters.SmallTest;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.animation.ActivityLaunchAnimator;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.util.settings.SecureSettings;
import com.android.systemui.util.time.FakeSystemClock;
@@ -60,8 +65,16 @@ public class QuickAccessWalletControllerTest extends SysuiTestCase {
private SecureSettings mSecureSettings;
@Mock
private QuickAccessWalletClient.OnWalletCardsRetrievedCallback mCardsRetriever;
@Mock
private ActivityStarter mActivityStarter;
@Mock
private ActivityLaunchAnimator.Controller mAnimationController;
@Captor
private ArgumentCaptor<GetWalletCardsRequest> mRequestCaptor;
@Captor
private ArgumentCaptor<Intent> mIntentCaptor;
@Captor
private ArgumentCaptor<PendingIntent> mPendingIntentCaptor;
private FakeSystemClock mClock = new FakeSystemClock();
private QuickAccessWalletController mController;
@@ -69,14 +82,24 @@ public class QuickAccessWalletControllerTest extends SysuiTestCase {
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
when(mQuickAccessWalletClient.isWalletServiceAvailable()).thenReturn(true);
when(mQuickAccessWalletClient.isWalletFeatureAvailable()).thenReturn(true);
when(mQuickAccessWalletClient.isWalletFeatureAvailableWhenDeviceLocked()).thenReturn(true);
mClock.setElapsedRealtime(100L);
doAnswer(invocation -> {
QuickAccessWalletClient.WalletPendingIntentCallback callback =
(QuickAccessWalletClient.WalletPendingIntentCallback) invocation
.getArguments()[1];
callback.onWalletPendingIntentRetrieved(null);
return null;
}).when(mQuickAccessWalletClient).getWalletPendingIntent(any(), any());
mController = new QuickAccessWalletController(
mContext,
MoreExecutors.directExecutor(),
MoreExecutors.directExecutor(),
mSecureSettings,
mQuickAccessWalletClient,
mClock);
@@ -151,8 +174,7 @@ public class QuickAccessWalletControllerTest extends SysuiTestCase {
verify(mQuickAccessWalletClient)
.getWalletCards(
eq(MoreExecutors.directExecutor()),
mRequestCaptor.capture(),
eq(MoreExecutors.directExecutor()), mRequestCaptor.capture(),
eq(mCardsRetriever));
GetWalletCardsRequest request = mRequestCaptor.getValue();
@@ -173,4 +195,55 @@ public class QuickAccessWalletControllerTest extends SysuiTestCase {
verify(mQuickAccessWalletClient, never()).getWalletCards(any(), any(), any());
}
@Test
public void getQuickAccessUiIntent_hasCards_useTargetActivityFalse_startsWalletActivity() {
when(mQuickAccessWalletClient.useTargetActivityForQuickAccess()).thenReturn(false);
mController.startQuickAccessUiIntent(mActivityStarter, mAnimationController, true);
verify(mActivityStarter).startActivity(mIntentCaptor.capture(), eq(true),
any(ActivityLaunchAnimator.Controller.class), eq(true));
Intent intent = mIntentCaptor.getValue();
assertEquals(intent.getAction(), Intent.ACTION_VIEW);
assertEquals(
intent.getComponent().getClassName(),
"com.android.systemui.wallet.ui.WalletActivity");
}
@Test
public void getQuickAccessUiIntent_noCards_useTargetActivityFalse_isWalletActivity() {
when(mQuickAccessWalletClient.useTargetActivityForQuickAccess()).thenReturn(false);
mController.startQuickAccessUiIntent(mActivityStarter, mAnimationController, false);
verify(mActivityStarter).postStartActivityDismissingKeyguard(mIntentCaptor.capture(), eq(0),
any(ActivityLaunchAnimator.Controller.class));
Intent intent = mIntentCaptor.getValue();
assertEquals(intent.getAction(), Intent.ACTION_VIEW);
assertEquals(
intent.getComponent().getClassName(),
"com.android.systemui.wallet.ui.WalletActivity");
}
@Test
public void getQuickAccessUiIntent_targetActivityViaPendingIntent_intentComponentIsCorrect() {
doAnswer(invocation -> {
QuickAccessWalletClient.WalletPendingIntentCallback callback =
(QuickAccessWalletClient.WalletPendingIntentCallback) invocation
.getArguments()[1];
Intent intent = new Intent(Intent.ACTION_VIEW).setClassName(
"com.google.android.apps.testapp",
"com.google.android.apps.testapp.TestActivity");
callback.onWalletPendingIntentRetrieved(
PendingIntent.getActivity(mContext, 0, intent, PendingIntent.FLAG_IMMUTABLE));
return null;
}).when(mQuickAccessWalletClient).getWalletPendingIntent(any(), any());
when(mQuickAccessWalletClient.useTargetActivityForQuickAccess()).thenReturn(true);
mController.startQuickAccessUiIntent(mActivityStarter, mAnimationController, true);
verify(mActivityStarter).postStartActivityDismissingKeyguard(mPendingIntentCaptor.capture(),
any(ActivityLaunchAnimator.Controller.class));
PendingIntent pendingIntent = mPendingIntentCaptor.getValue();
Intent intent = pendingIntent.getIntent();
assertEquals(intent.getAction(), Intent.ACTION_VIEW);
assertEquals(
intent.getComponent().getClassName(),
"com.google.android.apps.testapp.TestActivity");
}
}