/* * Copyright (C) 2012 Baidu.com Inc * * 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 com.baidu.cafe.local.traveler; import java.util.ArrayList; import android.view.View; import android.widget.EditText; import android.widget.ListView; import com.baidu.cafe.local.traveler.Util.Equal; import com.baidu.cafe.local.traveler.ViewHelper.AbstractList; /** * @author luxiaoyu01@baidu.com * @date 2012-1-2 * @version * @todo */ public class Operation { public final static int STATE_UNDONE = 0; public final static int STATE_DOING = 1; public final static int STATE_DONE = 2; private final static int RANDOM_STRING_LENGTH = 10; // activity index isDone private View mView = null; private String mViewString = null; private int[] mViewLocation = new int[2]; private int mState = STATE_UNDONE; private int mLevel = 0; private String mAction = null; private boolean mEnable = true; private String mActivity = null; private boolean mShouldRepeat = false; /** * index on activity */ private int mViewIndex = -1; public Operation(View view, int viewIndex, String action, String activity) { mView = view; mViewString = view.toString(); mView.getLocationOnScreen(mViewLocation); mViewIndex = viewIndex; mAction = action; mActivity = activity; } /** * @return click point (x, y) */ public int[] doOperation() { mState = STATE_DOING; int[] xy = APPTraveler.local.getViewCenter(mView); View targetView = mView; if (ViewHelper.ACTION_CLICK.equals(mAction)) { APPTraveler.local.clickViewWithoutAssert(mView); } else if (ViewHelper.ACTION_TEXT.equals(mAction)) { ViewHelper.enterText((EditText) mView, Util.getRandomString(RANDOM_STRING_LENGTH)); } else if (ViewHelper.ACTION_LONG_CLICK.equals(mAction)) { APPTraveler.local.clickLongOnView(mView); } else if (ViewHelper.ACTION_SLIDE.equals(mAction)) { APPTraveler.local.dragScreenToRight(10); } else if (mAction.indexOf(ViewHelper.ACTION_LISTVIEW) != -1) { AbstractList abstractListView = ViewHelper.getAbstractList(mView); targetView = ((ListView) abstractListView.list) .getChildAt(abstractListView.cursor++ - 1); xy = APPTraveler.local.getViewCenter(targetView); APPTraveler.local.clickViewWithoutAssert(targetView); } // else if (mAction.indexOf(ViewOperator.ACTION_SCROLLVIEW) != -1) { // AbstractList abstractScrollView = ViewOperator.getAbstractList(mView); // Logger.println("get scrollview: " + abstractScrollView.cursor); // targetView = ((ScrollView) abstractScrollView.list).getChildAt(abstractScrollView.cursor++ - 1); // ViewOperator.clickViewWithoutAssert(targetView); // } mState = STATE_DONE; if (isInScreen(xy)) { Logger.println(mAction + " on [" + getText() + "] " + mView.toString()); APPTraveler.local.hideInputMethod(); ViewHelper.sleep(); } else { Logger.println("click can not be performed because " + targetView + " is out of screen"); return null; } return xy; } public boolean isInScreen(int[] xy) { return xy[0] < 0 || xy[0] > APPTraveler.mDisplayX || xy[1] < 0 || xy[1] > APPTraveler.mDisplayY ? false : true; } public int[] getViewLocation() { return mViewLocation; } public void setViewLocation(int[] mViewLocation) { this.mViewLocation = mViewLocation; } public String getViewString() { return mViewString; } public void setViewString(String mViewString) { this.mViewString = mViewString; } public String getActivity() { return mActivity; } public void setActivity(String mActivity) { this.mActivity = mActivity; } public int getLevel() { return mLevel; } public void setLevel(int mLevel) { this.mLevel = mLevel; } public boolean isShouldRepeat() { return mShouldRepeat; } public void setShouldRepeat(boolean shouldRepeat) { this.mShouldRepeat = shouldRepeat; } public int getState() { return mState; } public void setState(int state) { this.mState = state; } public View getView() { return mView; } public void setView(View view) { this.mView = view; } public String getAction() { return mAction; } public void setAction(String action) { this.mAction = action; } public boolean isEnable() { return mEnable; } public void setEnable(boolean enable) { this.mEnable = enable; } private String getText() { return ViewHelper.getViewText(mView); } public int getViewIndex() { return mViewIndex; } public void setViewIndex(int viewIndex) { this.mViewIndex = viewIndex; } @Override public String toString() { String state = mEnable ? String.valueOf(mState) : "F"; return mViewString.substring(mViewString.indexOf('@') + 1) + "(" + getText() + ")" + "." + mAction + "(" + state + ")" + mLevel; } @Override public boolean equals(Object o) { if (!(o instanceof Operation)) { return false; } Operation operation = (Operation) o; if (!isTheSameView(operation)) { return false; } // if (!mActivity.equals(operation.mActivity)) { // return false; // } if (!operation.mAction.equals(this.mAction)) { return false; } return true; } // public boolean equals(Object o) { // if (!(o instanceof Operation)) { // return false; // } // // Operation operation = (Operation) o; // // view.toString() is like that "android.widget.ImageButton@402f8d80" // // so there is no need to compare this.index // if (!operation.mViewString.equals(this.mViewString)) { // return false; // } // // if (!operation.mAction.equals(this.mAction)) { // return false; // } // // return true; // } /** * stricter than equals() * * @param operation * @return */ public boolean isTheSameOperation(Operation operation) { if (!mViewString.equals(operation.mViewString)) { return false; } if (!this.equals(operation)) { return false; } return true; } private boolean isTheSameView(Operation operation) { if (!isTheSameLocation(operation)) { return false; } // view.toString() is like that "android.widget.ImageButton@402f8d80" // so there is no need to compare this.index if (!getTypeString(mView).equals(getTypeString(operation.mView))) { return false; } // if (Util.getViewSnapshot(view1).equals(Util.getViewSnapshot(view2))) { // return true; // } return true; } private boolean isTheSameLocation(Operation operation) { int[] location = operation.mViewLocation; return mViewLocation[0] == location[0] && mViewLocation[1] == location[1] ? true : false; } private String getTypeString(View view) { return view.getClass().toString().split(" ")[1]; } /** * @param level * means count of recursion * @return operations changed including added and removed */ public static ArrayList<Operation> updateOperations(int level) { ArrayList<Operation> newOperations = new ArrayList<Operation>(); ArrayList<Operation> operations = getCurrentOperations(); String topActivity = APPTraveler.remote.getTopActivity(); String topPackage = APPTraveler.remote.getTopPackage(); Logger.println("topActivity: " + topActivity); if (operations.size() == 0) { if (!APPTraveler.local.mPackageName.equals(topPackage)) { Logger.println("topPackage: " + topPackage); Logger.println(topActivity + " is out of package!"); if (APPTraveler.remote.isHome()) { Logger.println("Top activity is home!"); Logger.println("Travel end!"); APPTraveler.mIsEnd = true; return null; } } if (level > 5) { Logger.println("updateOperations is over 5 times!"); return newOperations; } ViewHelper.goBack("operations.size() == 0"); return updateOperations(level + 1); } // add operations. It's dup!!!! for (Operation operation : operations) { // TODO use getValidViews() to avoid to add dup views' operation newOperations.add(operation); } return newOperations; } public static ArrayList<Operation> getCurrentOperations() { ArrayList<View> views = ViewHelper.getAllOperatableViews(); ArrayList<Operation> operations = new ArrayList<Operation>(); for (int i = 0; i < views.size(); i++) { operations.addAll(ViewHelper.getViewOperations(views.get(i), i)); } return operations; } private boolean isSameDiff(ArrayList<View> diff, ArrayList<View> lastDiff) { return Util.isArraySame(diff, lastDiff, new Equal<View>() { @Override public boolean isEqual(View v1, View v2) { if (v1.getWidth() != v2.getWidth() || v1.getHeight() != v2.getHeight()) { return false; } if (Util.getViewSnapshot(v1).equals(Util.getViewSnapshot(v2))) { return true; } return false; } }); } /** * TODO unfinished!!! * * @param newViews * @return */ // private ArrayList<View> getValidViews(ArrayList<View> newViews) { // ArrayList<View> diff = Util.subArray(newViews, mOldViews); // ArrayList<View> validViews = new ArrayList<View>(); // // if (!isSameDiff(diff, mLastDiff)) { // validViews = diff; // } // // mOldViews = newViews; // mLastDiff = diff; // // return validViews; // } }