Keyguard模块CTS问题解决方案总结

cts测试源码中会发现都是如下格式的命令行:

//灭屏 然后 亮屏
protected void gotoKeyguard() throws DeviceNotAvailableException {
        sleepDevice();//灭屏
        wakeUpDevice();//亮屏
}

protected void sleepDevice() throws DeviceNotAvailableException {
        int retriesLeft = 5;
        runCommandAndPrintOutput("input keyevent 26");
        do {
            if (isDisplayOn()) {
                log("***Waiting for display to turn off...");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    log(e.toString());
                    // Well I guess we are not waiting...
                }
            } else {
                break;
            }
        } while (retriesLeft-- > 0);
}

protected void wakeUpDevice() throws DeviceNotAvailableException {
        runCommandAndPrintOutput("input keyevent 224");
}

protected String runCommandAndPrintOutput(String command) throws DeviceNotAvailableException {
        final String output = executeShellCommand(command);
        log(output);
        return output;
}

protected String executeShellCommand(String command) throws DeviceNotAvailableException {
        return executeShellCommand(mDevice, command);
}

protected static String executeShellCommand(ITestDevice device, String command)
            throws DeviceNotAvailableException {
        log("adb shell " + command);
        return device.executeShellCommand(command);
}

以上命令行相当于shell命令:
adb shell command
即:
   adb shell input keyevent 26   //灭屏
   adb shell input keyevent 224  //亮屏

类似的还有如下命令行:
   adb shell input keyevent 3    //HOME
   adb shell input keyevent 4    //BACK
   adb shell input keyevent 82   //MENU
   adb shell am stack list       //列出stack中的activity,显示的activity在最上面
   am start -a android.intent.action.MAIN -c android.intent.category.HOME //回到桌面

输入密码解锁屏:
private static final String LOCK_CREDENTIAL = "1234";
protected void enterAndConfirmLockCredential() throws Exception {
        // TODO: This should use waitForIdle..but there ain't such a thing on hostside tests, boo :(
        Thread.sleep(500);

        runCommandAndPrintOutput("input text " + LOCK_CREDENTIAL);
        runCommandAndPrintOutput("input keyevent KEYCODE_ENTER");
}

该命令输入密码不成功的原因是,锁屏界面输入框必须是文本框且要能够或得到焦点,我遇到的坑就是,我们的需求定制了解锁屏界面,
去掉了原生的文本输入框,修改方式就是:将原生的文本输入框恢复,字体改为0:

/packages/apps/KeyguardSmartisan/res/layout-xxhdpi/keyguard_pin_view.xml
<com.smartisanos.keyguard.KeyguardPINView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:androidprv="http://schemas.android.com/apk/res/android"
    android:id="@+id/keyguard_pin_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/lock_pattern_background_repeat"
    android:orientation="vertical" >

... ...
    <TextView
        android:id="@+id/passwordEntry"
        android:layout_width="@dimen/keyguard_pin_view_entry_w"
        android:layout_height="wrap_content"
        android:layout_marginLeft="@dimen/keyguard_pin_view_entry_left"
        android:layout_marginTop="@dimen/keyguard_password_view_padding_top"
        android:layout_below="@id/easy_password_tip"
        android:gravity="center"
        android:password="true"
        android:singleLine="true"
        android:visibility="invisible"
        android:textSize="28sp" />
... ...
/>

改为:

<com.smartisanos.keyguard.KeyguardPINView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:androidprv="http://schemas.android.com/apk/res/android"
    android:id="@+id/keyguard_pin_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/lock_pattern_background_repeat"
    android:orientation="vertical" >

... ...
    <TextView
        android:id="@+id/passwordEntry"
        android:layout_width="@dimen/keyguard_pin_view_entry_w"
        android:layout_height="wrap_content"
        android:layout_marginLeft="@dimen/keyguard_pin_view_entry_left"
        android:layout_marginTop="@dimen/keyguard_password_view_padding_top"
        android:layout_below="@id/easy_password_tip"
        android:gravity="center"
        android:password="true"
        android:singleLine="true"
        android:visibility="visible"
        android:textSize="0sp" />
... ...
/>

再一种测试就是通过回调方式来确认:

public void testDismissKeyguardActivity_method() throws Exception {
        if (!isHandheld()) {
            return;
        }
        final String logSeparator = clearLogcat();
        gotoKeyguard();//灭屏然后亮屏
        mAmWmState.computeState(mDevice, null);
        assertTrue(mAmWmState.getAmState().getKeyguardControllerState().keyguardShowing);
        launchActivity("DismissKeyguardMethodActivity");//其中注册有keyguard回调
        mAmWmState.waitForKeyguardGone(mDevice);
        mAmWmState.computeState(mDevice, new String[] { "DismissKeyguardMethodActivity"});
        mAmWmState.assertVisibility("DismissKeyguardMethodActivity", true);
        assertFalse(mAmWmState.getAmState().getKeyguardControllerState().keyguardShowing);
        assertOnDismissSucceededInLogcat(logSeparator);
    }

keyguard回调代码逻辑:
public class DismissKeyguardMethodActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getSystemService(KeyguardManager.class).requestDismissKeyguard(this,
                new KeyguardDismissLoggerCallback(this));
    }
}

KeyguardDismissLoggerCallback.java实现了系统公共接口:KeyguardDismissCallback
public class KeyguardDismissLoggerCallback extends KeyguardDismissCallback {

    private final String TAG = "KeyguardDismissLoggerCallback";

    private final Context mContext;

    public KeyguardDismissLoggerCallback(Context context) {
        mContext = context;
    }

    @Override
    public void onDismissError() {
        Log.i(TAG, "onDismissError");
    }

    @Override
    public void onDismissSucceeded() {
        if (mContext.getSystemService(KeyguardManager.class).isDeviceLocked()) {
            // Device is still locked? What a fail. Don't print "onDismissSucceded" such that the
            // log fails.
            Log.i(TAG, "dismiss succedded was called but device is still locked.");
        } else {
            Log.i(TAG, "onDismissSucceeded");
        }
    }

    @Override
    public void onDismissCancelled() {
        Log.i(TAG, "onDismissCancelled");
    }
}

根绝以上逻辑,可知在测试用例中,需要在某种场景下,回调以上三个keyguard状态方法

最后举例说明:

CtsServicesHostTestCases 中的如下一条测试失败:

android.server.cts.KeyguardLockedTests#testEnterPipOverKeyguard

本地单项case测试shell脚本:

run cts -m CtsServicesHostTestCases -t android.server.cts.KeyguardLockedTests#testEnterPipOverKeyguard

然后为了本地命令行分步模拟该case 测试单项的执行过程,则需要将当前case的log打开或者添加自己的log,然后编译当前case

的jar包,替换电脑端cts测试软件目录下testcases中CtsServicesHostTestCases.jar;

编译命令,系统源代码根目录下:

make CtsServicesHostTestCases 这样就会生成以上需要替换的那个jar包;

然后进一步,测试过程中需要启动摸个activity,如本case中需要启动:android-ocean-cts/cts/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/PipActivity.java

查看该activity所在目录的Android.mk文件:

LOCAL_PACKAGE_NAME := CtsDeviceServicesTestApp

则在源代码根目录android-ocean-cts下:make CtsDeviceServicesTestApp

好了经过以上两步编译:

然后手机本地安装以上生成的CtsDeviceServicesTestApp.apk,

然后就可以本地使用命令行的方式分步骤来模拟完成每一个测试项的过程测试了:

在锁屏界面使用shell 命令启动activity:

adb shell am start -n android.server.cts/.PipActivity  --es show_over_keyguard true

此时,以上activity悬浮在keyguard之上,然后设置锁屏密码:

adb shell locksettings set-pin 1234

然后向以上activity发送进入画中画广播:

adb shell am broadcast -a android.server.cts.PipActivity.enter_pip

google原生机器会进入解pin码界面,输入密码1234后,看到以上activity进入到画中画悬浮窗界面

我们的定制机器直接进入到了画中画界面,没有检查中途设置锁屏密码,所以fail;

有关画中画请参照:https://blog.csdn.net/ckwccc/article/details/79098602

猜你喜欢

转载自blog.csdn.net/tj_shenzhendaxue/article/details/81503946