| /* |
| * Copyright (C) 2021 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 android.security.cts.CVE_2021_0481; |
| |
| import org.junit.Before; |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| |
| import android.content.Context; |
| import android.content.Intent; |
| import android.content.pm.PackageManager; |
| import android.content.pm.ResolveInfo; |
| import android.os.SystemClock; |
| import android.util.Log; |
| |
| import static androidx.test.core.app.ApplicationProvider.getApplicationContext; |
| import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; |
| import androidx.test.filters.SdkSuppress; |
| import androidx.test.runner.AndroidJUnit4; |
| import androidx.test.uiautomator.By; |
| import androidx.test.uiautomator.UiDevice; |
| import androidx.test.uiautomator.UiObject2; |
| import androidx.test.uiautomator.Until; |
| import androidx.test.uiautomator.BySelector; |
| |
| import java.util.List; |
| |
| import static org.hamcrest.CoreMatchers.equalTo; |
| import static org.hamcrest.CoreMatchers.is; |
| import static org.hamcrest.CoreMatchers.notNullValue; |
| import static org.junit.Assert.assertThat; |
| import static org.junit.Assert.assertFalse; |
| import static org.junit.Assume.assumeNoException; |
| |
| /** |
| * launch "Settings" app |
| * set up user photo |
| */ |
| @RunWith(AndroidJUnit4.class) |
| public class DeviceTest { |
| |
| class ClickableNotFound extends Exception{ |
| public ClickableNotFound(String s){ |
| super(s); |
| } |
| } |
| |
| private static final String BASIC_SAMPLE_PACKAGE |
| = "android.security.cts.CVE_2021_0481"; |
| private static final int LAUNCH_TIMEOUT_MS = 20000; |
| private static final String TAG = "TAG_2021_0481"; |
| private static final int IS_FOUND_FLAG = 1; // 0001 |
| private static final int IS_CHECKED_FLAG = 2; // 0010 |
| private UiDevice mDevice; |
| |
| @Test |
| public void testUserPhotoSetUp() { |
| |
| //set mDevice and go to homescreen |
| mDevice = UiDevice.getInstance(getInstrumentation()); |
| mDevice.pressHome(); |
| |
| //start "Settings" app |
| Intent myIntent = new Intent("android.settings.USER_SETTINGS"); |
| //android.provider.Settings.ACTION_USER_SETTINGS |
| myIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); |
| try{ |
| getApplicationContext().startActivity(myIntent); |
| } catch(android.content.ActivityNotFoundException e){ |
| Log.d(TAG, "Activity to be tested doesn't exist. Test will pass."); |
| return; |
| } |
| |
| //wait for "User Settings" activity to appear. |
| SystemClock.sleep(6000); |
| |
| //perform UI test steps |
| try { |
| |
| //in "Multiple users" activity showing "Use multiple users" switch |
| searchAndClick(mDevice, "android:id/switch_widget", 2000); |
| |
| //in "Multiple users" activity showing a list of current users, |
| //look for the first item "android:id/title" on the list showing "You(Owner)" |
| searchAndClick(mDevice, "android:id/title", 2000); |
| |
| //in "Profile Info" dialog window showing clickable user silhouette |
| //look for clickable android.widget.ImageView object with attributes: |
| // getContentDescription()=Select photo |
| // getResourceName()=com.android.settings:id/user_photo |
| searchAndClick(mDevice, "com.android.settings:id/user_photo", 2000); |
| |
| //in unnamed subdialog showing two options: "Take a photo" "Choose an image" |
| searchAndClick(mDevice, "Choose an image", 6000); |
| |
| //in "Browse Files in Other Apps" activity |
| searchAndClick(mDevice, "android.security.cts.CVE_2021_0481.EvilActivity", 5000); |
| |
| //Image is chosen as (evilActivity) so we are getting back to |
| //"Profile Info" dialog window showing clickable user silhouette |
| //end "Cancel" and "OK" buttons. |
| //look for "Cancel button and click it" |
| searchAndClick(mDevice, "Cancel", 2000); |
| |
| } catch (ClickableNotFound e){ |
| Log.d(TAG, e.toString()); |
| assumeNoException(e); |
| } |
| Log.d(TAG, "end of testUserPhotoSetUp()"); |
| } |
| |
| //see what is on screen and click on object containing name |
| //throw exception if object not found |
| private void searchAndClick(UiDevice mDevice, String name, int timeOut) throws ClickableNotFound { |
| |
| int ret; |
| List<UiObject2> objects = mDevice.findObjects(By.clickable(true)); |
| boolean found = false; |
| Log.d(TAG, "looking for " + name); |
| Log.d(TAG, "found " + String.valueOf(objects!=null ? objects.size() : 0) + " clickables"); |
| |
| if(objects != null){ |
| for (UiObject2 o : objects) { |
| if((ret=searchAndLog(o, name, "")) !=0 ) |
| { |
| found=true; |
| Log.d(TAG, name + " found"); |
| if((ret & IS_CHECKED_FLAG) == 0) { |
| o.click(); |
| Log.d(TAG, name + " clicked"); |
| SystemClock.sleep(timeOut); //wait for click result to appear onscreen |
| } |
| break; //to avoid androidx.test.uiautomator.StaleObjectException |
| } |
| } |
| } |
| if(!found) { |
| throw new ClickableNotFound("\"" + name + "\" not found to click on"); |
| } |
| } |
| |
| //Search for 'name' in UiObject2 |
| //returns int flags showing search result: |
| // IS_CHECKED_FLAG - 'name' matches o.getResourceName() and o.isSelected()==true |
| // IS_FOUND_FLAG - 'name' matches anything else |
| private int searchAndLog(UiObject2 o, String name, String prefix){ |
| |
| int ret = 0; |
| String lname = o.getText(); |
| String cname = o.getClassName(); |
| String cdesc = o.getContentDescription(); |
| String rname = o.getResourceName(); |
| boolean checked = o.isChecked(); |
| |
| Log.d(TAG, prefix + "class=" + cname); |
| Log.d(TAG, prefix + "o.getText()=" + lname); |
| Log.d(TAG, prefix + "o.getContentDescription()=" + cdesc); |
| Log.d(TAG, prefix + "o.getResourceName()=" + rname); |
| Log.d(TAG, prefix + "o.getChildCount()=" + o.getChildCount()); |
| |
| if( rname != null && rname.equals(name) && checked) { |
| ret |= IS_CHECKED_FLAG; |
| } |
| else if(lname != null && lname.equals(name) || cdesc != null && cdesc.equals(name) || rname != null && rname.equals(name) ) { |
| ret |= IS_FOUND_FLAG; |
| } |
| |
| if(ret != 0) { |
| Log.d(TAG, prefix + "found-->" + name); |
| return ret; |
| } else { |
| java.util.List<UiObject2> objects2 = o.getChildren(); |
| if(objects2 != null && objects2.size() > 0 && prefix.length() < 50) { |
| for (UiObject2 o2 : objects2) { |
| if((ret=searchAndLog(o2, name, prefix + "__")) != 0){ |
| return ret; |
| } |
| } |
| } |
| } |
| return ret; |
| } |
| |
| } |
| |