blob: 3db1e310533056ca999aff612c9db3060d90e121 [file] [log] [blame]
// Copyright 2019 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package arc
import (
"context"
"time"
"chromiumos/tast/errors"
"chromiumos/tast/local/android/ui"
"chromiumos/tast/local/arc"
"chromiumos/tast/local/chrome/ash"
"chromiumos/tast/local/chrome/display"
"chromiumos/tast/local/chrome/uiauto/vkb"
"chromiumos/tast/testing"
)
func init() {
testing.AddTest(&testing.Test{
Func: SoftInputMode,
Desc: "Verifies that Ash split view works properly with softInputMode=adjustPan|adjustResize activity flags",
Contacts: []string{"tetsui@chromium.org", "arc-framework+tast@google.com"},
SoftwareDeps: []string{"chrome"},
Fixture: "arcBootedInTabletMode",
Params: []testing.Param{{
ExtraAttr: []string{"informational", "group:mainline"},
ExtraSoftwareDeps: []string{"android_p"},
}, {
Name: "vm",
ExtraAttr: []string{"informational", "group:mainline"},
ExtraSoftwareDeps: []string{"android_vm"},
}},
})
}
func SoftInputMode(ctx context.Context, s *testing.State) {
p := s.FixtValue().(*arc.PreData)
cr := p.Chrome
a := p.ARC
isVMEnabled, err := arc.VMEnabled()
if err != nil {
s.Fatal("Failed to get whether ARCVM is enabled: ", err)
}
tconn, err := cr.TestAPIConn(ctx)
if err != nil {
s.Fatal("Creating test API connection failed: ", err)
}
d, err := a.NewUIDevice(ctx)
if err != nil {
s.Fatal("Failed initializing UI Automator: ", err)
}
defer d.Close(ctx)
s.Log("Installing app")
const apk = "ArcSoftInputModeTest.apk"
if err := a.Install(ctx, arc.APKPath(apk)); err != nil {
s.Fatal("Failed installing app: ", err)
}
infos, err := display.GetInfo(ctx, tconn)
if err != nil {
s.Fatal("Failed to get display info: ", err)
}
if len(infos) == 0 {
s.Fatal("No display found")
}
var info *display.Info
for i := range infos {
if infos[i].IsInternal {
info = &infos[i]
}
}
if info == nil {
s.Log("No internal display found. Default to the first display")
info = &infos[0]
}
waitForRotation := func(expectLandscape bool) error {
return testing.Poll(ctx, func(ctx context.Context) error {
disp, err := arc.NewDisplay(a, arc.DefaultDisplayID)
if err != nil {
return testing.PollBreak(err)
}
defer disp.Close()
s, err := disp.Size(ctx)
if err != nil {
// It may return error while transition, keep retrying.
return err
}
if s.Width > s.Height == expectLandscape {
return nil
}
return errors.New("display not rotated in ARC")
}, nil)
}
// TODO(tetsui): Use camera position for getting the default orientation.
portraitByDefault := info.Bounds.Height > info.Bounds.Width
runTest := func(ctx context.Context, s *testing.State, activityName string, rotation int) {
// When the device is portrait by default, rotate for additional 90 degrees.
actualRotation := rotation
if portraitByDefault {
actualRotation = (rotation + 90) % 360
}
if err := display.SetDisplayProperties(ctx, tconn, info.ID,
display.DisplayProperties{Rotation: &actualRotation}); err != nil {
s.Fatalf("Failed to rotate display to %d: %q", actualRotation, err)
}
if err := waitForRotation(rotation%180 == 0); err != nil {
s.Fatal("Failed to wait for rotation: ", err)
}
firstAct, err := arc.NewActivity(a, "com.android.settings", ".Settings")
if err != nil {
s.Fatal("Failed to create a new activity: ", err)
}
defer firstAct.Close()
if err := firstAct.Start(ctx, tconn); err != nil {
s.Fatal("Failed to start the activity: ", err)
}
defer firstAct.Stop(ctx, tconn)
const pkg = "org.chromium.arc.testapp.softinputmode"
secondAct, err := arc.NewActivity(a, pkg, activityName)
if err != nil {
s.Fatal("Failed to create a new activity: ", err)
}
defer secondAct.Close()
if err := secondAct.Start(ctx, tconn); err != nil {
s.Fatal("Failed to start the activity: ", err)
}
defer secondAct.Stop(ctx, tconn)
if _, err := ash.SetARCAppWindowState(ctx, tconn, secondAct.PackageName(), ash.WMEventSnapRight); err != nil {
s.Fatal("Failed to snap app in split view: ", err)
}
if _, err := ash.SetARCAppWindowState(ctx, tconn, firstAct.PackageName(), ash.WMEventSnapLeft); err != nil {
s.Fatal("Failed to snap app in split view: ", err)
}
const fieldID = "org.chromium.arc.testapp.softinputmode:id/text"
field := d.Object(ui.ID(fieldID))
if err := field.WaitForExists(ctx, 30*time.Second); err != nil {
s.Fatal("Failed to find the field: ", err)
}
if err := field.Click(ctx); err != nil {
s.Fatal("Failed to click the field: ", err)
}
field = d.Object(ui.ID(fieldID), ui.Focused(true))
if err := field.WaitForExists(ctx, 30*time.Second); err != nil {
s.Fatal("Failed to focus the field: ", err)
}
if isVMEnabled {
// On ARC R, another click is necessary to open the virtual keyboard i.e. the first click only
// focuses on the input field, which is different from ARC P.
if err := field.Click(ctx); err != nil {
s.Fatal("Failed to click the field: ", err)
}
}
if err := vkb.NewContext(nil, tconn).WaitLocationStable()(ctx); err != nil {
s.Fatal("Failed to wait for the virtual keyboard to show: ", err)
}
if err := field.Exists(ctx); err != nil {
s.Fatal("Could not find the field; probably hidden by the virtual keyboard?")
}
}
// Restore the initial rotation.
defer func() {
if err := display.SetDisplayProperties(ctx, tconn, info.ID,
display.DisplayProperties{Rotation: &info.Rotation}); err != nil {
s.Fatal("Failed to restore the initial display rotation: ", err)
}
}()
for _, data := range []struct {
activityName string
rotation int
}{
{".AdjustPanActivity", 0},
{".AdjustResizeActivity", 270},
} {
s.Run(ctx, data.activityName, func(ctx context.Context, s *testing.State) {
runTest(ctx, s, data.activityName, data.rotation)
})
}
}