170e34108e0fc19277e642aef3b36b65b8e254899Kevin Jin/*
270e34108e0fc19277e642aef3b36b65b8e254899Kevin Jin * Copyright (C) 2013 DroidDriver committers
370e34108e0fc19277e642aef3b36b65b8e254899Kevin Jin *
470e34108e0fc19277e642aef3b36b65b8e254899Kevin Jin * Licensed under the Apache License, Version 2.0 (the "License");
570e34108e0fc19277e642aef3b36b65b8e254899Kevin Jin * you may not use this file except in compliance with the License.
670e34108e0fc19277e642aef3b36b65b8e254899Kevin Jin * You may obtain a copy of the License at
770e34108e0fc19277e642aef3b36b65b8e254899Kevin Jin *
870e34108e0fc19277e642aef3b36b65b8e254899Kevin Jin *      http://www.apache.org/licenses/LICENSE-2.0
970e34108e0fc19277e642aef3b36b65b8e254899Kevin Jin *
1070e34108e0fc19277e642aef3b36b65b8e254899Kevin Jin * Unless required by applicable law or agreed to in writing, software
1170e34108e0fc19277e642aef3b36b65b8e254899Kevin Jin * distributed under the License is distributed on an "AS IS" BASIS,
1270e34108e0fc19277e642aef3b36b65b8e254899Kevin Jin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1370e34108e0fc19277e642aef3b36b65b8e254899Kevin Jin * See the License for the specific language governing permissions and
1470e34108e0fc19277e642aef3b36b65b8e254899Kevin Jin * limitations under the License.
1570e34108e0fc19277e642aef3b36b65b8e254899Kevin Jin */
1670e34108e0fc19277e642aef3b36b65b8e254899Kevin Jin
1770e34108e0fc19277e642aef3b36b65b8e254899Kevin Jinpackage com.google.android.droiddriver.base;
1870e34108e0fc19277e642aef3b36b65b8e254899Kevin Jin
1970e34108e0fc19277e642aef3b36b65b8e254899Kevin Jinimport android.app.Service;
20f50519233078e65a056cff49d7b4989d57c3e750Kevin Jinimport android.graphics.Bitmap;
21f50519233078e65a056cff49d7b4989d57c3e750Kevin Jinimport android.graphics.Bitmap.CompressFormat;
2270e34108e0fc19277e642aef3b36b65b8e254899Kevin Jinimport android.os.PowerManager;
23f50519233078e65a056cff49d7b4989d57c3e750Kevin Jinimport android.util.Log;
2470e34108e0fc19277e642aef3b36b65b8e254899Kevin Jinimport android.view.KeyEvent;
2570e34108e0fc19277e642aef3b36b65b8e254899Kevin Jin
2670e34108e0fc19277e642aef3b36b65b8e254899Kevin Jinimport com.google.android.droiddriver.UiDevice;
2770e34108e0fc19277e642aef3b36b65b8e254899Kevin Jinimport com.google.android.droiddriver.actions.Action;
2829d66eeee5d30f7db747cceeb84defec961b4125Kevin Jinimport com.google.android.droiddriver.actions.SingleKeyAction;
29f50519233078e65a056cff49d7b4989d57c3e750Kevin Jinimport com.google.android.droiddriver.util.FileUtils;
30f50519233078e65a056cff49d7b4989d57c3e750Kevin Jinimport com.google.android.droiddriver.util.Logs;
31f50519233078e65a056cff49d7b4989d57c3e750Kevin Jin
32f50519233078e65a056cff49d7b4989d57c3e750Kevin Jinimport java.io.BufferedOutputStream;
3370e34108e0fc19277e642aef3b36b65b8e254899Kevin Jin
3470e34108e0fc19277e642aef3b36b65b8e254899Kevin Jin/**
3570e34108e0fc19277e642aef3b36b65b8e254899Kevin Jin * Base implementation of {@link UiDevice}.
3670e34108e0fc19277e642aef3b36b65b8e254899Kevin Jin */
37f50519233078e65a056cff49d7b4989d57c3e750Kevin Jinpublic abstract class BaseUiDevice implements UiDevice {
3870e34108e0fc19277e642aef3b36b65b8e254899Kevin Jin  // power off may not trigger new events
3929d66eeee5d30f7db747cceeb84defec961b4125Kevin Jin  private static final SingleKeyAction POWER_OFF = new SingleKeyAction(KeyEvent.KEYCODE_POWER, 0,
4070e34108e0fc19277e642aef3b36b65b8e254899Kevin Jin      false);
4170e34108e0fc19277e642aef3b36b65b8e254899Kevin Jin  // power on should always trigger new events
42d414dc59622a9a8a0a2e3af94387d2ecd148ca55Kevin Jin  private static final SingleKeyAction POWER_ON = new SingleKeyAction(KeyEvent.KEYCODE_POWER,
43d414dc59622a9a8a0a2e3af94387d2ecd148ca55Kevin Jin      1000L, false);
4470e34108e0fc19277e642aef3b36b65b8e254899Kevin Jin
45d414dc59622a9a8a0a2e3af94387d2ecd148ca55Kevin Jin  @SuppressWarnings("deprecation")
4670e34108e0fc19277e642aef3b36b65b8e254899Kevin Jin  @Override
4770e34108e0fc19277e642aef3b36b65b8e254899Kevin Jin  public boolean isScreenOn() {
4870e34108e0fc19277e642aef3b36b65b8e254899Kevin Jin    PowerManager pm =
49f50519233078e65a056cff49d7b4989d57c3e750Kevin Jin        (PowerManager) getContext().getInstrumentation().getTargetContext()
50f50519233078e65a056cff49d7b4989d57c3e750Kevin Jin            .getSystemService(Service.POWER_SERVICE);
5170e34108e0fc19277e642aef3b36b65b8e254899Kevin Jin    return pm.isScreenOn();
5270e34108e0fc19277e642aef3b36b65b8e254899Kevin Jin  }
5370e34108e0fc19277e642aef3b36b65b8e254899Kevin Jin
5470e34108e0fc19277e642aef3b36b65b8e254899Kevin Jin  @Override
5570e34108e0fc19277e642aef3b36b65b8e254899Kevin Jin  public void wakeUp() {
5670e34108e0fc19277e642aef3b36b65b8e254899Kevin Jin    if (!isScreenOn()) {
5727b635e33f18c439d6e511d71c762ae1352b1bc8Kevin Jin      perform(POWER_ON);
5870e34108e0fc19277e642aef3b36b65b8e254899Kevin Jin    }
5970e34108e0fc19277e642aef3b36b65b8e254899Kevin Jin  }
6070e34108e0fc19277e642aef3b36b65b8e254899Kevin Jin
6170e34108e0fc19277e642aef3b36b65b8e254899Kevin Jin  @Override
6270e34108e0fc19277e642aef3b36b65b8e254899Kevin Jin  public void sleep() {
6370e34108e0fc19277e642aef3b36b65b8e254899Kevin Jin    if (isScreenOn()) {
6470e34108e0fc19277e642aef3b36b65b8e254899Kevin Jin      perform(POWER_OFF);
6570e34108e0fc19277e642aef3b36b65b8e254899Kevin Jin    }
6670e34108e0fc19277e642aef3b36b65b8e254899Kevin Jin  }
6746cbd1ba6301e660d32bed661bd65994d4911c4eKevin Jin
6846cbd1ba6301e660d32bed661bd65994d4911c4eKevin Jin  @Override
6946cbd1ba6301e660d32bed661bd65994d4911c4eKevin Jin  public void pressBack() {
7046cbd1ba6301e660d32bed661bd65994d4911c4eKevin Jin    perform(SingleKeyAction.BACK);
7146cbd1ba6301e660d32bed661bd65994d4911c4eKevin Jin  }
7270e34108e0fc19277e642aef3b36b65b8e254899Kevin Jin
7370e34108e0fc19277e642aef3b36b65b8e254899Kevin Jin  @Override
7470e34108e0fc19277e642aef3b36b65b8e254899Kevin Jin  public boolean perform(Action action) {
75f50519233078e65a056cff49d7b4989d57c3e750Kevin Jin    return getContext().getDriver().getRootElement().perform(action);
76f50519233078e65a056cff49d7b4989d57c3e750Kevin Jin  }
77f50519233078e65a056cff49d7b4989d57c3e750Kevin Jin
78f50519233078e65a056cff49d7b4989d57c3e750Kevin Jin  @Override
79f50519233078e65a056cff49d7b4989d57c3e750Kevin Jin  public boolean takeScreenshot(String path) {
80f50519233078e65a056cff49d7b4989d57c3e750Kevin Jin    return takeScreenshot(path, Bitmap.CompressFormat.PNG, 0);
8170e34108e0fc19277e642aef3b36b65b8e254899Kevin Jin  }
82f50519233078e65a056cff49d7b4989d57c3e750Kevin Jin
83f50519233078e65a056cff49d7b4989d57c3e750Kevin Jin  @Override
84f50519233078e65a056cff49d7b4989d57c3e750Kevin Jin  public boolean takeScreenshot(String path, CompressFormat format, int quality) {
85f50519233078e65a056cff49d7b4989d57c3e750Kevin Jin    Logs.call(this, "takeScreenshot", path, quality);
86f50519233078e65a056cff49d7b4989d57c3e750Kevin Jin    Bitmap screenshot = takeScreenshot();
87f50519233078e65a056cff49d7b4989d57c3e750Kevin Jin    if (screenshot == null) {
88f50519233078e65a056cff49d7b4989d57c3e750Kevin Jin      return false;
89f50519233078e65a056cff49d7b4989d57c3e750Kevin Jin    }
90f50519233078e65a056cff49d7b4989d57c3e750Kevin Jin    BufferedOutputStream bos = null;
91f50519233078e65a056cff49d7b4989d57c3e750Kevin Jin    try {
92f50519233078e65a056cff49d7b4989d57c3e750Kevin Jin      bos = FileUtils.open(path);
93f50519233078e65a056cff49d7b4989d57c3e750Kevin Jin      screenshot.compress(format, quality, bos);
94f50519233078e65a056cff49d7b4989d57c3e750Kevin Jin      return true;
95f50519233078e65a056cff49d7b4989d57c3e750Kevin Jin    } catch (Exception e) {
96f50519233078e65a056cff49d7b4989d57c3e750Kevin Jin      Logs.log(Log.WARN, e);
97f50519233078e65a056cff49d7b4989d57c3e750Kevin Jin      return false;
98f50519233078e65a056cff49d7b4989d57c3e750Kevin Jin    } finally {
99f50519233078e65a056cff49d7b4989d57c3e750Kevin Jin      if (bos != null) {
100f50519233078e65a056cff49d7b4989d57c3e750Kevin Jin        try {
101f50519233078e65a056cff49d7b4989d57c3e750Kevin Jin          bos.close();
102f50519233078e65a056cff49d7b4989d57c3e750Kevin Jin        } catch (Exception e) {
103f50519233078e65a056cff49d7b4989d57c3e750Kevin Jin          // ignore
104f50519233078e65a056cff49d7b4989d57c3e750Kevin Jin        }
105f50519233078e65a056cff49d7b4989d57c3e750Kevin Jin      }
106f50519233078e65a056cff49d7b4989d57c3e750Kevin Jin      screenshot.recycle();
107f50519233078e65a056cff49d7b4989d57c3e750Kevin Jin    }
108f50519233078e65a056cff49d7b4989d57c3e750Kevin Jin  }
109f50519233078e65a056cff49d7b4989d57c3e750Kevin Jin
110f50519233078e65a056cff49d7b4989d57c3e750Kevin Jin  protected abstract Bitmap takeScreenshot();
111f50519233078e65a056cff49d7b4989d57c3e750Kevin Jin
11274676fdd3c8a9e599eddd13bea56898674d9916aKevin Jin  protected abstract DroidDriverContext<?, ?> getContext();
11370e34108e0fc19277e642aef3b36b65b8e254899Kevin Jin}
114