Android Open Source - Cafe View Property Provider






From Project

Back to project page Cafe.

License

The source code is released under:

Apache License

If you think the Android project Cafe listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*
 * Copyright (C) 2011 Baidu.com Inc/*from   w w  w.j  a  va2s .  c om*/
 *
 * 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.remote;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.ArrayList;

/**
 * Dump view property from view server. It works when "adb shell getprop
 * ro.debuggable" returns 1.
 * 
 * @author luxiaoyu01@baidu.com
 * @date 2011-7-6
 * @version
 * @todo
 */
public class ViewPropertyProvider {
    public final static int           SEARCHMODE_COMPLETE_MATCHING = 1;
    public final static int           SEARCHMODE_DEFAULT           = 1;
    public final static int           SEARCHMODE_INCLUDE_MATCHING  = 2;

    private final static int          DUMP_TIMEOUT                 = 30000;
    private final static int          VIEWSERVER_PORT              = 4939;

    private int                       mHeight                      = 0;
    private int                       mHeightOfStatusBar           = 0;
    private BufferedReader            mIn                          = null;
    private ArrayList<BufferedReader> mIns                         = null;
    private ArrayList<String>         mDumpedLines                 = null;
    private BufferedWriter            mOut                         = null;
    private int                       mRootHeight                  = 0;
    private String                    mRootLayoutType              = null;
    private String                    mRootLayoutWidth             = null;
    private int                       mRootWidth                   = 0;
    private Socket                    mSocket                      = null;
    private SystemLib                 mSystemLib                   = null;
    private ArrayList<Integer>        mTargetIndexes               = null;
    private int                       mThreadNumber                = 0;
    private int                       mWidth                       = 0;

    public ViewPropertyProvider(SystemLib systemLib) {
        mSystemLib = systemLib;
        mIns = new ArrayList<BufferedReader>();
        init();
        // for test git
    }

    public void setStatusBarHeight(int height) {
        mHeightOfStatusBar = height;
        Log.print("mHeightOfStatusBar:" + mHeightOfStatusBar);
    }

    /**
     * check whether the given process alive or not
     * 
     * @param processName
     *            the name string of process e.g.
     *            "com.baidu.baiduclock/com.baidu.baiduclock.BaiduClock"
     * @return true:alive false:dead
     */
    public boolean checkProcessAlive(String processName) {
        String processNumber = getProcessNumber(processName);
        if (processNumber == null) {
            return false;
        }
        return true;
    }

    /**
     * get focused window name
     * 
     * @return the name string of focused window
     */
    public String getFocusedWindow() {
        dumpTargetViews("GET_FOCUS", "", "", SEARCHMODE_COMPLETE_MATCHING, 1, true, false);

        if (mDumpedLines.size() != 1) {
            return null;
        }

        Log.print("GET_FOCUS:" + mDumpedLines.get(0));
        /*
        String[] focusSplit = mKnownLines.get(0).split(" ");
        
        if (focusSplit.length < 2){
            print("focusSplit.length < 2");
            return null;
        }*/

        //return focusSplit[1];
        return mDumpedLines.get(0);
    }

    /**
     * get input method status
     * 
     * @return true means VISIBLE; false means GONE
     */
    public boolean getInputMethodStatus() {
        String processNumber = getProcessNumber("InputMethod");
        if (null == processNumber) {
            Log.print("Cannot found InputMethod!\nUse default status[false] of InputMethod!");
            return false;
        }

        ArrayList<String> targetLines = dumpTargetViews("DUMP " + processNumber, "layout_type",
                "TYPE_INPUT_METHOD", SEARCHMODE_INCLUDE_MATCHING, 1, true, false);
        if (null == targetLines || targetLines.size() == 0) {
            return false;
        }

        return isVisible(targetLines.get(0));
    }

    /**
     * get icon state on statusbar
     * 
     * @param slotName
     *            mSlot of StatusBarIconView e.g. 3G icon's name is
     *            data_connection
     * @return state of icon; true means VISIBLE, false means GONE
     */
    public boolean getStatusBarIconState(String slotName) {
        String processNumber = getProcessNumber("StatusBar");
        ArrayList<String> targetLines = dumpTargetViews("DUMP " + processNumber, "name",
                "StatusBarIconView", SEARCHMODE_COMPLETE_MATCHING, 20, true, false);

        for (String targetLine : targetLines) {
            String sName = getPropertyValue(targetLine, "mSlot");
            // Log.print("sName:" + sName);
            if (null == sName) {
                continue;
            }

            if (sName.contains(slotName)) {
                return isVisible(targetLine);
            }
        }
        Log.print("iconName[" + slotName + "] has not found!");

        return false;
    }

    /**
     * get view's properties from focused window
     * 
     * @param searchKey
     *            property's name use to search
     * @param searchValue
     *            property's value use to search
     * @param targetNumber
     *            target index in search result. Beacuse a pair of searchKey and
     *            searchValue can return not only one search result.
     * @param getKeys
     *            property's name use to get
     * @param getNew
     *            True means start a new dump. If UI has changed, use true.
     *            False means get propery from last dump. If UI has not changed,
     *            use false.
     * 
     * @return String[] getValues
     */
    public String[] getViewProperties(String searchKey, String searchValue, int searchMode,
            int targetNumber, String[] getKeys, boolean getNew) {
        ArrayList<String[]> viewsProperties = getViewsProperties(searchKey, searchValue,
                searchMode, targetNumber, getKeys, getNew, false);
        return viewsProperties.size() < targetNumber ? null : viewsProperties.get(targetNumber - 1);
    }

    /**
     * get views' properties according to key, value and mode
     * 
     * @param searchKey
     *            key property to be dumped
     * @param searchValue
     *            key value to be dumped
     * @param searchMode
     *            dumping mode including SEARCHMODE_INCLUDE_MATCHING,
     *            SEARCHMODE_COMPLETE_MATCHING
     * @param targetNumber
     *            the amount of views you wanna to dump
     * @param getKeys
     *            what the keys u wanna to get its properties
     * @param getNew
     *            true if the view is already dumped, else false
     * @param onlyVisible
     *            true if u just wanna dump visible views
     * @return all of view properties dumped
     */
    public ArrayList<String[]> getViewsProperties(String searchKey, String searchValue,
            int searchMode, int targetNumber, String[] getKeys, boolean getNew, boolean onlyVisible) {
        if (null == searchKey || searchKey.equals("") || null == searchValue || null == getKeys
                || targetNumber < 1) {
            Log.print("getViewProperties()'s arguments is not correct!");
            return null;
        }

        setCurrentXY();

        // get target lines
        // Log.print("searchKey:" + searchKey + "\nsearchValue:" + searchValue + "\ntargetNumber:" + targetNumber);
        ArrayList<String> targetLines = dumpTargetViews("DUMP -1", searchKey, searchValue,
                searchMode, targetNumber, getNew, onlyVisible);
        for (String line : targetLines) {
            Log.print("target line:" + line);
        }

        // get properties
        ArrayList<String[]> targets = new ArrayList<String[]>();

        for (int i = 0; i < targetLines.size(); i++) {
            String[] properties = new String[getKeys.length];
            for (int j = 0; j < getKeys.length; j++) {
                if (getKeys[j].equals("coordinate")) {
                    properties[j] = getAbsoluteCoordinates(mTargetIndexes.get(i));
                    // Log.print(properties[j]);
                    continue;
                }
                properties[j] = getPropertyValue(targetLines.get(i), getKeys[j]);
            }

            targets.add(properties);

            //            for (String property : properties) {
            //                Log.print(property);
            //            }
        }

        return targets;
    }

    /**
     * get the current window list
     * 
     * @return the current window list
     */
    public String[] getWindowList() {
        dumpTargetViews("LIST", "", "", SEARCHMODE_COMPLETE_MATCHING, 1, true, false);
        return mDumpedLines.toArray(new String[mDumpedLines.size()]);
    }

    /**
     * wait for all dumping in threads completing It only can be invoked once in
     * a process!
     */
    public void waitForAllDumpCompleted() {
        Log.print("Wait for all dumping...");
        String line;
        Long begin = System.currentTimeMillis();
        Boolean isTimeout = false;

        for (BufferedReader in : mIns) {
            if (isTimeout) {
                // tolerate 30s dump, and then it will exit that will cause socket exception in logcat at w level
                break;
            }

            if (null == in) {
                continue;
            }

            try {
                while (true) {
                    if (System.currentTimeMillis() - begin > DUMP_TIMEOUT) {
                        isTimeout = true;
                        Log.print("Dump time is over than DUMP_TIMEOUT!\nSocket to ViewServer will be closed And it will throw [java.net.SocketException: Broken pipe].");
                        break;
                    }

                    if ((line = in.readLine()) == null || "DONE.".equalsIgnoreCase(line)
                            || "DONE".equalsIgnoreCase(line)) {
                        //Log.print("break@wait:" + line);
                        break;
                    }
                    //Log.print("wait:" + line);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            /*
               try {
               in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            */
        }

        try {
            /*
            if (mOut != null) {
                mOut.close();
            }
            
            if (mIn != null) {
                mIn.close();
            }
            */
            if (mSocket != null) {
                mSocket.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        Log.print("All dump has completed. It cost " + (System.currentTimeMillis() - begin) + "ms");
    }

    /**
     * format the dumped tree lines to its level
     * 
     * @param lines
     *            the dumped tree lines
     * @return the dumped tree level such as 0.1.3.4
     */
    private String[] formatDumpedLevels(ArrayList<String> lines) {
        String[] newLines = new String[lines.size()];

        // change the first line
        String levelString = "0";
        newLines[0] = levelString;

        // change other lines
        for (int i = 1; i < lines.size(); i++) {
            // select current head from head
            StringBuffer levelBuf = new StringBuffer();
            String[] levelSplit = levelString.split("\\.");
            int level = countFrontWhitespace(lines.get(i));
            for (int j = 0; j < level; j++) {
                levelBuf.append(levelSplit[j]).append('.');
            }
            String currentLevel = levelBuf.toString();
            levelString = currentLevel + i;
            newLines[i] = levelString;
            // Log.print(newLines[i]);
        }

        return newLines;
    }

    /**
     * open a new thread to complete remaining dumping job.
     */
    private void completeRemainingDump() {
        final int index = mThreadNumber;
        new Thread(new Runnable() {
            public void run() {
                BufferedReader in = mIns.get(index);
                String line;
                try {
                    while (true) {
                        if ((line = in.readLine()) == null || "DONE.".equalsIgnoreCase(line)
                                || "DONE".equalsIgnoreCase(line)) {
                            // Log.print("break:" + line);
                            break;
                        }
                        // Log.print(line);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }, "completeRemainingDump").start();
        mThreadNumber++;
    }

    /**
     * count the number of the white space of the given line
     * 
     * @param line
     *            the dumped line to be searched
     * @return the number of the white space
     */
    private int countFrontWhitespace(String line) {
        int count = 0;
        while (line.charAt(count) == ' ') {
            count++;
        }
        return count;
    }

    /**
     * search the given line according to given key, value and mode.
     * 
     * @param searchKey
     *            key property to be dumped
     * @param searchValue
     *            key value to be dumped
     * @param searchMode
     *            dumping mode including SEARCHMODE_PARTIAL_MATCHING,
     *            SEARCHMODE_COMPLETE_MATCHING
     * @param line
     *            the dumped line to be searched
     * @return if found, return true; else false
     */
    private boolean findTarget(String searchKey, String searchValue, int searchMode, String line) {
        if ("name".equals(searchKey)) {
            if (searchValue.equals(getName(line))) {
                return true;
            }
        } else {
            String getValue = getPropertyValue(line, searchKey);
            if (null == getValue) {
                return false;
            }
            return isMatch(searchValue, getValue, searchMode);
        }

        return false;
    }

    private String getAbsoluteCoordinates(int viewIndex) {
        String[] newLines = formatDumpedLevels(mDumpedLines);
        int[] relativeCoordinates = new int[4];
        int x = 0;
        int y = 0;

        String[] fathersLevel = newLines[viewIndex].split("\\.");
        for (int j = 0; j < fathersLevel.length; j++) {
            // Log.print("at level " + new Integer(fathersLevel[j]));
            relativeCoordinates = getRelativeCoordinates(mDumpedLines.get(
                    new Integer(fathersLevel[j])).trim());

            // accumulate relative coordinates
            if (relativeCoordinates != null) {
                // x += left - mScrollX
                x += relativeCoordinates[0] - relativeCoordinates[2];
                // y += top - mScrollY
                y += relativeCoordinates[1] - relativeCoordinates[3];
            }
        }
        x += relativeCoordinates[2];
        y += relativeCoordinates[3];

        String widthString = getPropertyValue(
                mDumpedLines.get(new Integer(fathersLevel[fathersLevel.length - 1])).trim(),
                "getWidth()");
        String heightString = getPropertyValue(
                mDumpedLines.get(new Integer(fathersLevel[fathersLevel.length - 1])).trim(),
                "getHeight()");
        if (heightString == null || widthString == null) {
            return null;
        }
        int width = new Integer(widthString);
        int height = new Integer(heightString);

        parseRoot();

        Log.print("[mRootHeight,mRootWidth]:[" + mRootHeight + "," + mRootWidth + "]");
        /*
        if (isFullScreen(mKnownLines.get(0))) {
            if (isExpandFullScreen(mKnownLines.get(0))) {
                // expand absoluteCoordinates to full screen
                Log.print("expand to full screen");
                float scale = (float) mHeight / (float) mRootHeight;
                Log.print("scale:" + scale);
                x *= scale;
                y *= scale;
                width *= scale;
                height *= scale;
            }
        } else {
            // add non full screen window height offset
            y += getNonFullScreenWindowHeightOffset();
        }
        */

        if (!isFullScreen()) {
            // add non full screen window height offset
            y += getNonFullScreenWindowHeightOffset();
        }
        Log.print("x = " + x);
        Log.print("y = " + y);
        Log.print("width = " + width);
        Log.print("height = " + height);

        return "" + x + "," + y + "," + width + "," + height;
    }

    /**
     * set X value and Y value of the current coordinates,
     */
    private void setCurrentXY() {
        mHeight = mSystemLib.getDisplayY();
        mWidth = mSystemLib.getDisplayX();
        Log.print("mHeight:" + mHeight);
        Log.print("mWidth:" + mWidth);
    }

    /**
     * get the height of the input method.
     * 
     * @return the height of the input method
     */
    private int dumpInputMethodHeight() {
        String processNumber = getProcessNumber("InputMethod");

        if (processNumber != null) {
            ArrayList<String> targetLines = dumpTargetViews("DUMP " + processNumber, "layout_type",
                    "TYPE_INPUT_METHOD", SEARCHMODE_INCLUDE_MATCHING, 1, true, false);
            int heightOfInputMethod = Integer.valueOf(getPropertyValue(targetLines.get(0),
                    "getHeight()"));
            if (heightOfInputMethod > 0) {
                mSystemLib.setSystemProperties("persist.sys.inputmethod.h", ""
                        + heightOfInputMethod);
                return heightOfInputMethod;
            }
        }

        return 0;
    }

    private int getLengthNumberWidth(String line, int beginIndex) {
        int length = 0;
        for (int i = 0; i < line.length(); i++) {
            if (line.substring(beginIndex + i, beginIndex + i + 1).equals(",")) {
                length = i;
                break;
            }
        }
        return length;
    }

    /**
     * search views from dumped lines according to key, value and search mode.
     * 
     * @param searchKey
     *            key property to be dumped
     * @param searchValue
     *            key value to be dumped
     * @param searchMode
     *            dumping mode including SEARCHMODE_INCLUDE_MATCHING,
     *            SEARCHMODE_COMPLETE_MATCHING
     * @param targetNumber
     * @param onlyVisible
     * @return lines which are selected
     */
    private ArrayList<String> searchDumpedLines(String searchKey, String searchValue,
            int searchMode, int targetNumber, boolean onlyVisible) {
        ArrayList<String> targetLines = new ArrayList<String>();
        if (null == mDumpedLines || mDumpedLines.size() == 0) {
            Log.print("mDupmedLines is empty!\nThere is no dump to find.");
            return null;
        }

        for (int i = 0; i < mDumpedLines.size(); i++) {
            String line = mDumpedLines.get(i);
            if (findTarget(searchKey, searchValue, searchMode, line)) {
                if (onlyVisible && !isFamilyVisible(i)) {
                    Log.print("invisible line: " + line);
                    continue;
                }

                Log.print("old: " + searchKey + " == " + searchValue + " at [" + line + "]");
                targetLines.add(line);
                mTargetIndexes.add(i);

                if (targetLines.size() == targetNumber) {
                    break;
                }
            }
        }

        return targetLines;
    }

    public static boolean isViewServerOpen() {
        boolean open = true;
        Socket socket = new Socket();
        try {
            socket.connect(new InetSocketAddress("127.0.0.1", VIEWSERVER_PORT));
        } catch (IOException e) {
            //            e.printStackTrace();
            open = false;
        } finally {
            try {
                socket.close();
                socket = null;
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return open;
    }

    /**
     * @return
     */
    public ArrayList<String> dumpAllLines() {
        ArrayList<String> lines = new ArrayList<String>();
        Long begin = System.currentTimeMillis();
        try {
            mSocket = new Socket();
            mSocket.connect(new InetSocketAddress("127.0.0.1", VIEWSERVER_PORT));
            mOut = new BufferedWriter(new OutputStreamWriter(mSocket.getOutputStream()));
            mIn = new BufferedReader(new InputStreamReader(mSocket.getInputStream(), "utf-8"));

            // send command
            mOut.write("DUMP -1");
            mOut.newLine();
            mOut.flush();

            while (true) {
                String line = null;
                if ((line = mIn.readLine()) == null || "DONE.".equalsIgnoreCase(line)) {
                    break;
                }
                lines.add(line);
                //                Log.print(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        Log.print("Dump time cost: " + (System.currentTimeMillis() - begin) + "ms");
        return lines;
    }

    /**
     * dump lines from view server by the given dumping command
     * 
     * @param command
     *            the dumping command
     * @param searchKey
     *            key property to be dumped
     * @param searchValue
     *            key value to be dumped
     * @param searchMode
     *            the dumping mode including SEARCHMODE_INCLUDE_MATCHING,
     *            SEARCHMODE_COMPLETE_MATCHING
     * @param targetNumber
     * @param onlyVisible
     * @return the lines dumped
     */
    private ArrayList<String> dumpLinesFromViewServer(String command, String searchKey,
            String searchValue, int searchMode, int targetNumber, boolean onlyVisible) {
        // init
        mDumpedLines = new ArrayList<String>();
        ArrayList<String> targetLines = new ArrayList<String>();
        boolean isCompleted = false;

        try {
            mSocket = new Socket();
            mSocket.connect(new InetSocketAddress("127.0.0.1", VIEWSERVER_PORT));
            mOut = new BufferedWriter(new OutputStreamWriter(mSocket.getOutputStream()));
            mIn = new BufferedReader(new InputStreamReader(mSocket.getInputStream(), "utf-8"));

            // send command
            mOut.write(command);
            mOut.newLine();
            mOut.flush();

            Long begin = System.currentTimeMillis();
            while (true) {
                String line;

                if ((line = mIn.readLine()) == null || "DONE.".equalsIgnoreCase(line)) {
                    isCompleted = true;
                    break;
                }

                //Log.print(line);
                mDumpedLines.add(line);
                int viewIndex = Integer.valueOf(mDumpedLines.size() - 1);
                // got targets already
                if (findTarget(searchKey, searchValue, searchMode, line)) {
                    if (onlyVisible && !isFamilyVisible(viewIndex)) {
                        Log.print("invisible line: " + line);
                        continue;
                    }

                    Log.print("new: " + searchKey + " == " + searchValue + " at [" + line + "]");
                    targetLines.add(line);
                    mTargetIndexes.add(viewIndex);

                    if (targetLines.size() == targetNumber) {
                        break;
                    }
                }
            }

            if (!isCompleted) {
                // save socket
                mIns.add(mIn);
                completeRemainingDump();
            }

            Log.print("Dump time cost: " + (System.currentTimeMillis() - begin) + "ms");
        } catch (IOException e) {
            e.printStackTrace();
        }
        return targetLines;
    }

    /**
     * get last property from dumped line e.g.
     * com.android.calculator2.ColorButton@43e49bf8, then ColorButtor will be
     * returned
     * 
     * @param line
     *            the dumped line to be searched
     * @return the last property
     */
    private String getName(String line) {
        String fullName = line.substring(0, line.indexOf("@"));
        String[] names = fullName.split("\\.");
        return names[names.length - 1];
    }

    private int getNonFullScreenWindowHeightOffset() {
        int heightOffset = 0;

        if (mRootHeight < mHeight || mRootWidth < mWidth) {
            if (("TYPE_BASE_APPLICATION".equals(mRootLayoutType) && "WRAP_CONTENT"
                    .equals(mRootLayoutWidth))
                    || "TYPE_SYSTEM_ALERT".equals(mRootLayoutType)
                    || ("TYPE_APPLICATION".equals(mRootLayoutType) && !"MATCH_PARENT"
                            .equals(mRootLayoutWidth))) {
                // middle of screen
                // some dialogs are TYPE_APPLICATION, some are TYPE_BASE_APPLICATION(such as dialog of launcher)
                // and all of full screen activity is TYPE_BASE_APPLICATION
                heightOffset = (mHeight - mHeightOfStatusBar - mRootHeight) / 2
                        + mHeightOfStatusBar;

                // get input method state
                if (getInputMethodStatus()) {
                    heightOffset = (mHeight - mHeightOfStatusBar - getInputMethodHeight() - mRootHeight)
                            / 2 + mHeightOfStatusBar;
                }
                Log.print("middle of screen");
            } else if ("TYPE_APPLICATION_PANEL".equals(mRootLayoutType)
                    || "TYPE_APPLICATION_ATTACHED_DIALOG".equals(mRootLayoutType)
                    || ("TYPE_APPLICATION".equals(mRootLayoutType) && "MATCH_PARENT"
                            .equals(mRootLayoutWidth))) {
                // bottom of screen
                // heightOffset = mHeight - mHeightOfStatusBar - height;
                heightOffset = mHeight - mRootHeight;
                Log.print("bottom of screen");
            } else if ("TYPE_APPLICATION_SUB_PANEL".equals(mRootLayoutType)
                    || ("TYPE_BASE_APPLICATION".equals(mRootLayoutType) && "MATCH_PARENT"
                            .equals(mRootLayoutWidth))) {
                // top of screen
                heightOffset = 0;
                Log.print("top of screen");
            } else if ("TYPE_STATUS_BAR_PANEL".equals(mRootLayoutType)
                    || "TYPE_KEYGUARD".equals(mRootLayoutType)) {
                // at status bar expanded or keyguard
                heightOffset = mHeightOfStatusBar;
                Log.print("at status bar expanded or keyguard");
            } else {
                Log.print("Unknown type appeared!");
            }
            Log.print("heightOffset:" + heightOffset);
        }

        return heightOffset;
    }

    /**
     * get the process number by the given process name
     * 
     * @param processName
     *            which process number to be queried
     * @return the process number
     */
    private String getProcessNumber(String processName) {
        dumpTargetViews("LIST", "", "", SEARCHMODE_COMPLETE_MATCHING, 1, true, false);
        for (String line : mDumpedLines) {
            String[] lineSplit = line.split(" ");
            if (null == lineSplit || lineSplit.length < 2) {
                Log.print("null == lineSplit || lineSplit.length < 2");
                return null;
            }
            if (processName.equals(lineSplit[1])) {
                return lineSplit[0];
            }
        }
        return null;
    }

    /**
     * get the value from the given line according to the given key
     * 
     * @param searchKey
     *            key property to be dumped
     * @param line
     *            the dumped line to be searched
     * @return the matched value
     */
    private String getPropertyValue(String line, String searchKey) {
        try {
            if (searchKey.length() != 0 && line.indexOf(searchKey + "=") != -1) {
                int beginIndex = line.indexOf(searchKey) + searchKey.length() + 1;
                int endIndex = beginIndex + getLengthNumberWidth(line, beginIndex);
                int length = new Integer(line.substring(beginIndex, endIndex));
                beginIndex = endIndex + 1;
                endIndex = beginIndex + length;
                return line.substring(beginIndex, endIndex);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        // Log.print(property + " has not be found at " + line);
        return null;
    }

    /**
     * get the relative coordinates of the given line
     * 
     * @param line
     *            the line to be calculated
     * @return the relative coordinates
     */
    private int[] getRelativeCoordinates(String line) {
        String property = null;
        int[] relativeCoordinates = new int[4];

        property = getPropertyValue(line, "mLeft");
        if (property == null) {
            return null;
        }
        relativeCoordinates[0] = new Integer(property);

        property = getPropertyValue(line, "mTop");
        if (property == null) {
            return null;
        }
        relativeCoordinates[1] = new Integer(property);

        property = getPropertyValue(line, "mScrollX");
        if (property == null) {
            return null;
        }
        relativeCoordinates[2] = new Integer(property);

        property = getPropertyValue(line, "mScrollY");
        if (property == null) {
            return null;
        }
        relativeCoordinates[3] = new Integer(property);

        return relativeCoordinates;
    }

    /**
     * dump target views, if already dumped, just return; else dump it from view
     * server
     * 
     * @param command
     *            dumping command
     * @param searchKey
     *            key property to be dumped
     * @param searchValue
     *            key value to be dumped
     * @param searchMode
     *            dumping mode including SEARCHMODE_INCLUDE_MATCHING,
     *            SEARCHMODE_COMPLETE_MATCHING
     * @param targetNumber
     *            the amount of views you wanna to dump
     * @param getNew
     *            true if the view is already dumped, else false
     * @param onlyVisible
     *            true if u just wanna dump visible views
     * @return all of dumped views
     */
    private ArrayList<String> dumpTargetViews(final String command, final String searchKey,
            final String searchValue, final int searchMode, final int targetNumber,
            final boolean getNew, final boolean onlyVisible) {
        mTargetIndexes = new ArrayList<Integer>();

        // getViewLines from dumped lines
        if (!getNew) {
            return searchDumpedLines(searchKey, searchValue, searchMode, targetNumber, onlyVisible);
        }

        return dumpLinesFromViewServer(command, searchKey, searchValue, searchMode, targetNumber,
                onlyVisible);
    }

    /**
     * adjust whether the searched key has its value
     * 
     * @param key
     *            the key to be searched
     * @return true if the key has its value
     */
    private boolean hasValue(String key) {
        String value = mSystemLib.getSystemProperties(key);
        return (null == value || value.equals("") || Integer.valueOf(value) == 0) ? false : true;
    }

    /**
     * init process include: 1. set the height of the status bar
     */
    private void init() {
        // set by setStatusBarHeight()
        //        mHeightOfStatusBar = mSystemLib.getStatusBarHeight();
        Log.print("mHeightOfStatusBar:" + mHeightOfStatusBar);
    }

    private int getInputMethodHeight() {
        int heightOfInputMethod;
        if (hasValue("persist.sys.inputmethod.h")) {
            heightOfInputMethod = Integer.valueOf(mSystemLib
                    .getSystemProperties("persist.sys.inputmethod.h"));
        } else {
            heightOfInputMethod = dumpInputMethodHeight();
            mSystemLib.setSystemProperties("persist.sys.inputmethod.h", "" + heightOfInputMethod);
        }
        Log.print("heightOfInputMethod:" + heightOfInputMethod);

        return heightOfInputMethod;
    }

    /**
     * adjust whether the family is visible of the dumped tree lines
     * 
     * @param viewIndex
     *            the index to get father level
     * @return true if family is visible, else false
     */
    private boolean isFamilyVisible(int viewIndex) {
        String[] dumpedLevels = formatDumpedLevels(mDumpedLines);
        String[] fathersLevel = dumpedLevels[viewIndex].split("\\.");

        for (int j = 0; j < fathersLevel.length; j++) {
            String fatherLine = mDumpedLines.get(new Integer(fathersLevel[j])).trim();
            if (!isVisible(fatherLine)) {
                return false;
            }
        }

        return true;
    }

    /**
     * adjust if the screen is full
     * 
     * @return true if full screen, else false
     */
    private boolean isFullScreen() {
        return (mRootHeight < mHeight || mRootWidth < mWidth) ? false : true;
    }

    /**
     * adjust whether the got value and to be searched value are matched
     * 
     * @param searchValue
     *            key value to be dumped
     * @param getValue
     *            the already got value
     * @param searchMode
     *            dumping mode including SEARCHMODE_INCLUDE_MATCHING,
     *            SEARCHMODE_COMPLETE_MATCHING
     * @return true if matched, else false
     */
    private boolean isMatch(String searchValue, String getValue, int searchMode) {
        switch (searchMode) {
        case SEARCHMODE_COMPLETE_MATCHING:
            return searchValue.equals(getValue) ? true : false;
        case SEARCHMODE_INCLUDE_MATCHING:
            return getValue.indexOf(searchValue) != -1 ? true : false;
        default:
            Log.print("Unknown type of SEARCHMODE");
            return false;
        }
    }

    // landscape
    private boolean isPortrait() {
        setCurrentXY();
        return mHeight > mWidth;
    }

    /**
     * adjust whether the given line is visible
     * 
     * @param line
     *            the dumped line to be searched
     * @return true if visible, else false
     */
    private boolean isVisible(String line) {
        return "VISIBLE".equals(getPropertyValue(line, "getVisibility()")) ? true : false;
    }

    /**
     * parse root dumped line including its height, width, layout type and
     * layout width.
     */
    private void parseRoot() {
        String rootView = mDumpedLines.get(0);
        mRootHeight = Integer.valueOf(getPropertyValue(rootView, "getHeight()"));
        mRootWidth = Integer.valueOf(getPropertyValue(rootView, "getWidth()"));
        mRootLayoutType = getPropertyValue(rootView, "layout_type");
        mRootLayoutWidth = getPropertyValue(rootView, "layout_width");
        Log.print("layoutType:" + mRootLayoutType);
        Log.print("mRootLayoutWidth:" + mRootLayoutWidth);
    }

}




Java Source Code List

com.baidu.cafe.CafeExceptionHandler.java
com.baidu.cafe.CafeListener.java
com.baidu.cafe.CafeServiceTestCase.java
com.baidu.cafe.CafeTestCase.java
com.baidu.cafe.CafeTestRunner.java
com.baidu.cafe.TearDownHelper.java
com.baidu.cafe.local.DESEncryption.java
com.baidu.cafe.local.FPSTracer.java
com.baidu.cafe.local.FileUtils.java
com.baidu.cafe.local.LocalLib.java
com.baidu.cafe.local.Log.java
com.baidu.cafe.local.NetworkUtils.java
com.baidu.cafe.local.SnapshotHelper.java
com.baidu.cafe.local.record.CafeWebViewClient.java
com.baidu.cafe.local.record.OutputEvent.java
com.baidu.cafe.local.record.ViewRecorderSDK.java
com.baidu.cafe.local.record.ViewRecorder.java
com.baidu.cafe.local.record.WebElementRecorder.java
com.baidu.cafe.local.traveler.APPTraveler.java
com.baidu.cafe.local.traveler.Logger.java
com.baidu.cafe.local.traveler.Operation.java
com.baidu.cafe.local.traveler.Util.java
com.baidu.cafe.local.traveler.ViewHelper.java
com.baidu.cafe.remote.ArmsBinder.java
com.baidu.cafe.remote.ArmsBootupReceiver.java
com.baidu.cafe.remote.Arms.java
com.baidu.cafe.remote.Armser.java
com.baidu.cafe.remote.BatteryState.java
com.baidu.cafe.remote.LockActivity.java
com.baidu.cafe.remote.Log.java
com.baidu.cafe.remote.MonkeyNetwork.java
com.baidu.cafe.remote.MyIntent.java
com.baidu.cafe.remote.SystemLib.java
com.baidu.cafe.remote.UILib.java
com.baidu.cafe.remote.ViewPropertyProvider.java
com.baidu.cafe.utils.CommandResult.java
com.baidu.cafe.utils.ReflectHelper.java
com.baidu.cafe.utils.ShellExecute.java
com.baidu.cafe.utils.Strings.java
com.baidu.cafe.utils.TreeNode.java