1 /*
2  * Copyright (C) 2022 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 com.android.carrierdefaultapp;
18 
19 import static org.mockito.ArgumentMatchers.anyInt;
20 import static org.mockito.ArgumentMatchers.anyString;
21 import static org.mockito.ArgumentMatchers.eq;
22 import static org.mockito.Mockito.doReturn;
23 import static org.mockito.Mockito.spy;
24 import static org.mockito.Mockito.times;
25 import static org.mockito.Mockito.verify;
26 
27 import android.app.NotificationManager;
28 import android.app.PendingIntent;
29 import android.content.Context;
30 import android.content.Intent;
31 import android.os.Looper;
32 import android.os.PersistableBundle;
33 import android.telephony.CarrierConfigManager;
34 import android.telephony.SubscriptionManager;
35 import android.telephony.TelephonyManager;
36 import android.test.ActivityUnitTestCase;
37 import android.webkit.WebView;
38 
39 import androidx.test.platform.app.InstrumentationRegistry;
40 import androidx.test.runner.AndroidJUnit4;
41 
42 import com.android.phone.slice.SlicePurchaseController;
43 
44 import org.junit.Before;
45 import org.junit.Test;
46 import org.junit.runner.RunWith;
47 import org.mockito.ArgumentCaptor;
48 import org.mockito.Mock;
49 import org.mockito.MockitoAnnotations;
50 
51 import java.util.Base64;
52 
53 @RunWith(AndroidJUnit4.class)
54 public class SlicePurchaseActivityTest extends ActivityUnitTestCase<SlicePurchaseActivity> {
55     private static final String CARRIER = "Some Carrier";
56     private static final String URL = "file:///android_asset/slice_purchase_test.html";
57     private static final int PHONE_ID = 0;
58 
59     @Mock PendingIntent mPendingIntent;
60     @Mock PendingIntent mSuccessfulIntent;
61     @Mock PendingIntent mCanceledIntent;
62     @Mock PendingIntent mRequestFailedIntent;
63     @Mock CarrierConfigManager mCarrierConfigManager;
64     @Mock NotificationManager mNotificationManager;
65     @Mock PersistableBundle mPersistableBundle;
66     @Mock WebView mWebView;
67 
68     private SlicePurchaseActivity mSlicePurchaseActivity;
69     private Context mContext;
70 
SlicePurchaseActivityTest()71     public SlicePurchaseActivityTest() {
72         super(SlicePurchaseActivity.class);
73     }
74 
75     @Before
setUp()76     public void setUp() throws Exception {
77         injectInstrumentation(InstrumentationRegistry.getInstrumentation());
78         if (Looper.myLooper() == null) {
79             Looper.prepare();
80         }
81         super.setUp();
82         MockitoAnnotations.initMocks(this);
83 
84         // setup context
85         mContext = spy(getInstrumentation().getTargetContext());
86         doReturn(mCarrierConfigManager).when(mContext)
87                 .getSystemService(eq(CarrierConfigManager.class));
88         doReturn(URL).when(mPersistableBundle).getString(
89                 CarrierConfigManager.KEY_PREMIUM_CAPABILITY_PURCHASE_URL_STRING);
90         doReturn(mPersistableBundle).when(mCarrierConfigManager).getConfigForSubId(anyInt());
91         doReturn(mNotificationManager).when(mContext)
92                 .getSystemService(eq(NotificationManager.class));
93         doReturn(mContext).when(mContext).getApplicationContext();
94         setActivityContext(mContext);
95 
96         // set up intent
97         Intent intent = new Intent();
98         intent.putExtra(SlicePurchaseController.EXTRA_PHONE_ID, PHONE_ID);
99         intent.putExtra(SlicePurchaseController.EXTRA_SUB_ID,
100                 SubscriptionManager.getDefaultDataSubscriptionId());
101         intent.putExtra(SlicePurchaseController.EXTRA_PREMIUM_CAPABILITY,
102                 TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY);
103         intent.putExtra(SlicePurchaseController.EXTRA_PURCHASE_URL,
104                 SlicePurchaseController.SLICE_PURCHASE_TEST_FILE);
105         intent.putExtra(SlicePurchaseController.EXTRA_CARRIER, CARRIER);
106         Intent spiedIntent = spy(intent);
107 
108         // set up pending intents
109         doReturn(TelephonyManager.PHONE_PROCESS_NAME).when(mPendingIntent).getCreatorPackage();
110         doReturn(true).when(mPendingIntent).isBroadcast();
111         doReturn(mPendingIntent).when(spiedIntent).getParcelableExtra(
112                 anyString(), eq(PendingIntent.class));
113         doReturn(TelephonyManager.PHONE_PROCESS_NAME).when(mCanceledIntent).getCreatorPackage();
114         doReturn(true).when(mCanceledIntent).isBroadcast();
115         doReturn(mCanceledIntent).when(spiedIntent).getParcelableExtra(
116                 eq(SlicePurchaseController.EXTRA_INTENT_CANCELED), eq(PendingIntent.class));
117         doReturn(TelephonyManager.PHONE_PROCESS_NAME).when(mSuccessfulIntent).getCreatorPackage();
118         doReturn(true).when(mSuccessfulIntent).isBroadcast();
119         doReturn(mSuccessfulIntent).when(spiedIntent).getParcelableExtra(
120                 eq(SlicePurchaseController.EXTRA_INTENT_SUCCESS), eq(PendingIntent.class));
121         doReturn(TelephonyManager.PHONE_PROCESS_NAME).when(mRequestFailedIntent)
122                 .getCreatorPackage();
123         doReturn(true).when(mRequestFailedIntent).isBroadcast();
124         doReturn(mRequestFailedIntent).when(spiedIntent).getParcelableExtra(
125                 eq(SlicePurchaseController.EXTRA_INTENT_REQUEST_FAILED), eq(PendingIntent.class));
126 
127         mSlicePurchaseActivity = startActivity(spiedIntent, null, null);
128     }
129 
130     @Test
testOnPurchaseSuccessful()131     public void testOnPurchaseSuccessful() throws Exception {
132         mSlicePurchaseActivity.onPurchaseSuccessful();
133         verify(mSuccessfulIntent).send();
134     }
135 
136     @Test
testOnPurchaseFailed()137     public void testOnPurchaseFailed() throws Exception {
138         int failureCode = SlicePurchaseController.FAILURE_CODE_CARRIER_URL_UNAVAILABLE;
139         String failureReason = "Server unreachable";
140         mSlicePurchaseActivity.onPurchaseFailed(failureCode, failureReason);
141         ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
142         verify(mPendingIntent).send(eq(mContext), eq(0), intentCaptor.capture());
143         Intent intent = intentCaptor.getValue();
144         assertEquals(failureCode, intent.getIntExtra(
145                 SlicePurchaseController.EXTRA_FAILURE_CODE, failureCode));
146         assertEquals(failureReason, intent.getStringExtra(
147                 SlicePurchaseController.EXTRA_FAILURE_REASON));
148     }
149 
150     @Test
testOnUserCanceled()151     public void testOnUserCanceled() throws Exception {
152         mSlicePurchaseActivity.onDestroy();
153         verify(mCanceledIntent).send();
154     }
155 
156     @Test
testOnDismissFlow()157     public void testOnDismissFlow() throws Exception {
158         mSlicePurchaseActivity.onDismissFlow();
159         verify(mRequestFailedIntent).send();
160     }
161 
162     @Test
testStartWebView()163     public void testStartWebView() {
164         // unspecified contents type
165         SlicePurchaseActivity.startWebView(mWebView, URL, 0 /* CONTENTS_TYPE_UNSPECIFIED */, null);
166         verify(mWebView).loadUrl(eq(URL));
167 
168         // specified contents type with user data
169         String userData = "userData";
170         byte[] userDataBytes = userData.getBytes();
171         SlicePurchaseActivity.startWebView(mWebView, URL, 1 /* CONTENTS_TYPE_JSON */, userData);
172         verify(mWebView).postUrl(eq(URL), eq(userDataBytes));
173 
174         // specified contents type with encoded user data
175         byte[] encodedUserData = Base64.getEncoder().encode(userDataBytes);
176         userData = "encodedValue=" + new String(encodedUserData);
177         SlicePurchaseActivity.startWebView(mWebView, URL, 1 /* CONTENTS_TYPE_JSON */, userData);
178         verify(mWebView, times(2)).postUrl(eq(URL), eq(userDataBytes));
179     }
180 }
181