1 /*
2  * Copyright (C) 2015 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.dialer.janktests;
18 
19 import android.content.ComponentName;
20 import android.content.ContentProviderOperation;
21 import android.content.ContentValues;
22 import android.content.Intent;
23 import android.content.OperationApplicationException;
24 import android.content.pm.PackageManager;
25 import android.database.Cursor;
26 import android.net.Uri;
27 import android.os.RemoteException;
28 import android.os.SystemClock;
29 import android.provider.BaseColumns;
30 import android.provider.CallLog;
31 import android.provider.ContactsContract;
32 import android.provider.ContactsContract.CommonDataKinds;
33 import android.provider.ContactsContract.CommonDataKinds.Phone;
34 import android.provider.ContactsContract.CommonDataKinds.StructuredName;
35 import android.provider.ContactsContract.RawContacts;
36 import android.support.test.jank.GfxMonitor;
37 import android.support.test.jank.JankTest;
38 import android.support.test.jank.JankTestBase;
39 import android.support.test.uiautomator.By;
40 import android.support.test.uiautomator.Direction;
41 import android.support.test.uiautomator.UiDevice;
42 import android.support.test.uiautomator.UiObject2;
43 import android.support.test.uiautomator.UiObjectNotFoundException;
44 import android.support.test.uiautomator.Until;
45 import android.view.View;
46 
47 import junit.framework.Assert;
48 
49 import java.util.ArrayList;
50 import java.util.Random;
51 
52 /**
53  * Jank test for Dialer app
54  * open a contact, initiate call to open the dialing screen
55  * fling call log
56  */
57 public class DialerJankTests extends JankTestBase {
58     private static final int TIMEOUT = 5000;
59     private static final int INNER_LOOP = 5;
60     private static final int EXPECTED_FRAMES = 100;
61     private static final String PACKAGE_NAME = "com.google.android.dialer";
62     private static final String RES_PACKAGE_NAME = "com.android.dialer";
63     private static final String RES_PACKAGE_NAME2 = "com.android.contacts";
64     private static final String RES_PACKAGE_NAME3 = "android";
65     private static final String APP_NAME = "Phone";
66     private static final String CONTACT_NAME = "A AAA Test Account";
67     private static final String CONTACT_NUMBER = "2468";
68     private UiDevice mDevice;
69     static final int PICK_CONTACT_REQUEST = 1;
70 
71     @Override
setUp()72     public void setUp() throws Exception {
73         super.setUp();
74         mDevice = UiDevice.getInstance(getInstrumentation());
75         mDevice.setOrientationNatural();
76     }
77 
78     @Override
tearDown()79     protected void tearDown() throws Exception {
80         mDevice.unfreezeRotation();
81         super.tearDown();
82     }
83 
launchApp(String packageName)84     public void launchApp(String packageName) {
85         PackageManager pm = getInstrumentation().getContext().getPackageManager();
86         Intent appIntent = pm.getLaunchIntentForPackage(packageName);
87         appIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
88         getInstrumentation().getContext().startActivity(appIntent);
89         mDevice.waitForIdle();
90     }
91 
launchDialer()92     public void launchDialer () throws OperationApplicationException, RemoteException {
93         if (!doesContactExist()) {
94             insertNewContacts();
95         }
96         launchApp(PACKAGE_NAME);
97         mDevice.waitForIdle();
98 
99         // Open contacts list
100         UiObject2 contacts = mDevice.wait(Until.findObject(By.desc("Contacts")), TIMEOUT);
101         assertNotNull("Contacts can't be found", contacts);
102         contacts.clickAndWait(Until.newWindow(), TIMEOUT);
103         // Find a contact by a given contact-name
104         UiObject2 contactName = mDevice.wait(Until.findObject(
105             By.res(RES_PACKAGE_NAME, "cliv_name_textview").text(CONTACT_NAME)), TIMEOUT);
106         assertNotNull("Contactname can't be found", contactName);
107         contactName.clickAndWait(Until.newWindow(), TIMEOUT);
108         // Click on dial-icon beside contact-number to ensure test is ready to be executed
109         UiObject2 contactNumber = mDevice.wait(Until.findObject(
110             By.res(RES_PACKAGE_NAME2,"header").text(CONTACT_NUMBER)), TIMEOUT);
111         assertNotNull("Contact number can't be found", contactNumber);
112         contactNumber.clickAndWait(Until.newWindow(), TIMEOUT);
113 
114         UiObject2 endCall = mDevice.wait(Until.findObject(By.res(RES_PACKAGE_NAME,
115               "floating_end_call_action_button")), 2 * TIMEOUT);
116         endCall.clickAndWait(Until.newWindow(), TIMEOUT);;
117         SystemClock.sleep(200);
118     }
119 
120     @JankTest(beforeTest="launchDialer", expectedFrames=EXPECTED_FRAMES)
121     @GfxMonitor(processName=PACKAGE_NAME)
testDialerCallInit()122     public void testDialerCallInit() {
123         for (int i = 0; i < INNER_LOOP; i++) {
124             UiObject2 contactNumber = mDevice.wait(Until.findObject(
125                     By.res(RES_PACKAGE_NAME2,"header").text(CONTACT_NUMBER)), TIMEOUT);
126             assertNotNull("Contact number can't be found", contactNumber);
127             contactNumber.clickAndWait(Until.newWindow(), TIMEOUT);
128             UiObject2 endCall = mDevice.wait(Until.findObject(By.res(RES_PACKAGE_NAME,
129                       "floating_end_call_action_button")), 2 * TIMEOUT);
130             endCall.clickAndWait(Until.newWindow(), TIMEOUT);
131             SystemClock.sleep(200);
132         }
133     }
134 
launchCallLog()135     public void launchCallLog() throws UiObjectNotFoundException {
136         if (getCallLogCount() < 100) {
137             for (int i = 0; i < 100; i++) {
138                 addNumToCalLog(getRandomPhoneNumber());
139             }
140         }
141         launchApp(PACKAGE_NAME);
142         mDevice.waitForIdle();
143         // Find 'Call History' and click
144         mDevice.wait(Until.findObject(By.desc("Call History")), TIMEOUT).click();
145         mDevice.wait(Until.findObject(By.res(RES_PACKAGE_NAME,"lists_pager")), TIMEOUT);
146     }
147 
148     @JankTest(beforeTest="launchCallLog", expectedFrames=EXPECTED_FRAMES)
149     @GfxMonitor(processName=PACKAGE_NAME)
testDialerCallLogFling()150     public void testDialerCallLogFling() {
151         UiObject2 callLog = mDevice.wait(Until.findObject(
152                 By.res(RES_PACKAGE_NAME,"lists_pager")), TIMEOUT);
153         assertNotNull("Call log can't be found", callLog);
154         for (int i = 0; i < INNER_LOOP; i++) {
155             callLog.fling(Direction.DOWN);
156             SystemClock.sleep(100);
157             callLog.fling(Direction.UP);
158             SystemClock.sleep(100);
159         }
160     }
161 
162     // Method to insert a new contact
insertNewContacts()163     public void insertNewContacts() throws OperationApplicationException, RemoteException {
164         ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
165         int rawContactID = ops.size();
166         // to insert a new raw contact in the table ContactsContract.RawContacts
167         ops.add(ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI)
168                 .withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, "Test")
169                 .withValue(RawContacts.ACCOUNT_NAME, CONTACT_NAME)
170                 .build());
171 
172         // to insert display name in the table ContactsContract.Data
173         ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
174                 .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, rawContactID)
175                 .withValue(ContactsContract.Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE)
176                 .withValue(StructuredName.DISPLAY_NAME, CONTACT_NAME)
177                 .build());
178 
179         // to insert Mobile Number in the table ContactsContract.Data
180         ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
181                 .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, rawContactID)
182                 .withValue(ContactsContract.Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE)
183                 .withValue(Phone.NUMBER, CONTACT_NUMBER)
184                 .withValue(Phone.TYPE, CommonDataKinds.Phone.TYPE_MOBILE)
185                 .build());
186 
187             // Executing all the insert operations as a single database transaction
188         getInstrumentation().getContext().getContentResolver()
189                 .applyBatch(ContactsContract.AUTHORITY, ops);
190     }
191 
192     // Checks whether certain contact exists or not
doesContactExist()193     public boolean doesContactExist() {
194         Uri uri = Uri.withAppendedPath(
195                 ContactsContract.PhoneLookup.CONTENT_FILTER_URI, Uri.encode(CONTACT_NUMBER));
196         Cursor contactLookup = getInstrumentation().getContext().getContentResolver().query(
197                 uri, new String[] {
198                         BaseColumns._ID,
199                         ContactsContract.PhoneLookup.DISPLAY_NAME },
200                         null,
201                         null,
202                         null);
203         boolean found = false;
204         try {
205             if (contactLookup != null && contactLookup.getCount() > 0) {
206                 contactLookup.moveToNext();
207                 if (contactLookup.getString(contactLookup.getColumnIndex(
208                             ContactsContract.Data.DISPLAY_NAME)).equals(CONTACT_NAME))
209                     found = true;
210             }
211         } finally {
212             if (contactLookup != null) {
213                 contactLookup.close();
214             }
215         }
216 
217         return found;
218     }
219 
220     // Inserts a new entry in the call log
addNumToCalLog(String number)221     public void addNumToCalLog(String number){
222         ContentValues values = new ContentValues();
223         values.put(CallLog.Calls.NUMBER, number);
224         values.put(CallLog.Calls.DATE, System.currentTimeMillis());
225         values.put(CallLog.Calls.DURATION, 0);
226         values.put(CallLog.Calls.TYPE, CallLog.Calls.OUTGOING_TYPE);
227         values.put(CallLog.Calls.NEW, 1);
228         values.put(CallLog.Calls.CACHED_NAME, "");
229         values.put(CallLog.Calls.CACHED_NUMBER_TYPE, 0);
230         values.put(CallLog.Calls.CACHED_NUMBER_LABEL, "");
231         getInstrumentation().getContext().getContentResolver()
232                 .insert(CallLog.Calls.CONTENT_URI, values);
233     }
234 
235     // Gets call log count
getCallLogCount()236     public int getCallLogCount() {
237        Cursor cursor = getInstrumentation().getContext().getContentResolver()
238                .query(CallLog.Calls.CONTENT_URI, null, null, null, null);
239        return cursor.getCount();
240     }
241 
242     // Generates a random phone number
getRandomPhoneNumber()243     public String getRandomPhoneNumber() {
244         Random rand = new Random();
245         int num1 = (rand.nextInt(7) + 1) * 100 + (rand.nextInt(8) * 10) + rand.nextInt(8);
246         int num2 = rand.nextInt(743);
247         int num3 = rand.nextInt(10000);
248 
249         return String.format("%03d-%03d-%04d", num1, num2, num3);
250     }
251 }
252