swt_思维题 - CSDN
精华内容
参与话题
  • swt做JAVA界面

    千次阅读 2018-06-18 12:20:39
    SWT概述 SWT是IBM公司开发的UI开发组件,它与AWT/SWING组件类似,但是SWT克服了AWT/SWING中许多问题,所以用SWT编写UI程序无论在美观成都还是响应速
    原文地址为:用swt做JAVA界面

    SWT概述

    SWTIBM公司开发的UI开发组件,它与AWT/SWING组件类似,但是SWT克服了AWT/SWING中许多问题,所以用SWT编写UI程序无论在美观成都还是响应速度上都远远超越了AWTSWING.这主要是因为AWT只是单纯模拟本地操作系统窗口组件,SWT最大化了操作系统的图形构件API,也就是说只要操作系统提供了图形构件,SWT就可以利用JNI调用他们,只有操作系统中不提供的组件SWT才会去模拟实现由于使用了JNI,使得它和本地操作系统紧密连接在一起,因此编写的界面和本地系统窗口几乎没有区别.JFaceSWT的一个增强库,它以来SWT并将其扩展,功能强大目前企业级的Java开发应用都会用到这个。

    调用关系:

    JFaceàSWTàJNIà--à本地操作系统窗口组件

    安装

    下载SWT安装的Jar包(注意操作系统),也可以在eclipseplugin目录中找到(SWT.jar),然后用WinRAR解压缩得到org.eclipse.swt.win32.win32.x86_3.4.1.v3449c.jar以及5dll文件,如果已经配置好了JDK,那么将jar文件复制到JDK/jre/lib/ext/中,将dll文件复制到JDK/jre/bin/目录下,就完成了安装。

    http://zhidao.baidu.com/question/130025979.html?fr=ala0

    一、SWT程序起步

    第一个SWT程序:实现了一个记事本

    package swt;

    import org.eclipse.swt.widgets.*;

    import org.eclipse.swt.*;

    import org.eclipse.swt.events.*;

    import java.io.*;

    public class FirstSWT {

    private static String fn = "";

    private static Display display;

    private static Shell shell;

    private static Text text;

    private Button newButton;

    private Button openButton;

    private Button saveButton;

    private Button delButton;

    private Button quitButton;

    public FirstSWT(){

    display = new Display();

    //基本对话框

    shell = new Shell(display,SWT.DIALOG_TRIM);

    shell.setText("Note pad");

    shell.setSize(600,400);

    newButton = new Button(shell,SWT.PUSH);

    newButton.setLocation(2,5);

    newButton.setSize(50,20);

    newButton.setText("new");

    openButton = new Button(shell,SWT.PUSH);

    openButton.setLocation(60,5);

    openButton.setSize(50,20);

    openButton.setText("open");

    saveButton = new Button(shell,SWT.PUSH);

    saveButton.setLocation(118,5);

    saveButton.setSize(50,20);

    saveButton.setText("save");

    delButton = new Button(shell,SWT.PUSH);

    delButton.setLocation(180,5);

    delButton.setSize(50,20);

    delButton.setText("delete");

    quitButton = new Button(shell,SWT.PUSH);

    quitButton.setLocation(540,5);

    quitButton.setSize(50,20);

    quitButton.setText("quit");

    text = new Text(shell,SWT.MULTI|SWT.BORDER|SWT.V_SCROLL|SWT.WRAP);

    text.setLocation(2,30);

    text.setSize(shell.getClientArea().width-4,shell.getClientArea().height-35);

    newButton.addSelectionListener(new SelectionAdapter(){

    public void widgetSelected(SelectionEvent event)

    {

    fn = "";

    shell.setText("第一个SWT程序");

    text.setText("");

    }

    });

    openButton.addSelectionListener(new SelectionAdapter()

    {

    public void widgetSelected(SelectionEvent event)

    {

    FileDialog dlg = new FileDialog(shell,SWT.OPEN);

    String fileName = dlg.open();

    try{

    if(fileName != null)

    {

    //打开指定文件

    FileInputStream fis = new FileInputStream(fileName);

    text.setText("");

    BufferedReader in = new BufferedReader(new InputStreamReader(fis));

    String s = null;

    //将指定文件一行一行的加入记事本

    while((s=in.readLine())!=null)

    text.append(s+"/r/n");

    fn = fileName;

    shell.setText(fn);

    MessageBox successBox = new MessageBox(shell);

    successBox.setMessage("打开文件成功");

    successBox.setText("信息");

    successBox.open();

    in.close();

    }

    }catch(NullPointerException en)

    {

    System.out.println("warning No file selected!");

    }catch(Exception e)

    {

    MessageBox errorBox = new MessageBox(shell,SWT.ICON_ERROR);

    errorBox.setText("错误");

    errorBox.setMessage("打开文件失败!");

    errorBox.open();

    }

    }

    }

    );

    saveButton.addSelectionListener(new SelectionAdapter()

    {

    public void widgetSelected(SelectionEvent event)

    {

    try{

    String fileName = null;

    if(fn.equals(""))

    {

    FileDialog dlg = new FileDialog(shell,SWT.SAVE);

    fileName = dlg.open();

    FileOutputStream fos = new FileOutputStream(fileName);

    OutputStreamWriter out = new OutputStreamWriter(fos);

    out.write(text.getText());

    out.close();

    alertMsg(shell,"创建文件成功");

    if(fileName != null)

    {

    fn = fileName;

    shell.setText(fn);

    }

    }else

    {

    FileOutputStream fos = new FileOutputStream(fn);

    OutputStreamWriter out = new OutputStreamWriter(fos);

    out.write(text.getText());

    out.close();

    }

    }catch(NullPointerException en)

    {

    System.out.println("warning No file selected!");

    }

    catch(Exception e)

    {

    e.printStackTrace();

    MessageBox errorBox = new MessageBox(shell,SWT.ICON_ERROR);

    errorBox.setText("错误");

    errorBox.setMessage("保存文件失败!");

    errorBox.open();

    }

    }

    });

    quitButton.addSelectionListener(new SelectionAdapter()

    {

    public void widgetSelected(SelectionEvent e)

    {

    System.out.println(e.toString());

    display.dispose();

    }

    });

    shell.open();

    while(!shell.isDisposed())

    {

    if(!display.readAndDispatch())

    {

    // System.out.println(display.msg.toString());

    display.sleep();

    }

    }

    System.out.println("closed");

    display.dispose();

    }

    public static void main(String[] args) {

    // TODO Auto-generated method stub

    new FirstSWT();

    }

    public static void alertMsg(Shell shell,String msg)

    {

    MessageBox alertBox = new MessageBox(shell);

    alertBox.setMessage(msg);

    alertBox.setText("信息");

    alertBox.open();

    }

    }

    SWT程序流程

    1. 创建一个Display对象

    2. 创建一个或者多个Shell对象,你可以认为Shell代表了程序的窗口。

    3. Shell内创建各种部件(widget

    4. 对各个部件进行初始化(外观,状态等),同时为各种部件的事件创建监听器(listener

    5. 调用Shell对象的open()方法以显示窗体

    6. 各种事件进行监听并处理,直到程序发出退出消息

    7. 调用Display对象的dispose()方法以结束程序。

    可见和Swing&AWT差不多,都是一个主容器以及一系列内部容器嵌套而成。只是这里我们在组建或是容器的构造函数中就指定了其所述的父组件,不用再add了。在一个就是SWT的布局管理和Swing有所不同。

    二、SWT的布局管理

    主要分为:FillLayoutGridLayoutRowLayoutFormLayoutStackLayout,顾名思义吧。目前绝大多数(90%)都是GridLayout,资料甚多,不介绍了,介绍下自己感觉比较灵活的另一种FormLayout

    FormLayout formLayout = new FormLayout();

    formLayout.marginHeight = 5; 

    formLayout.marginWidth = 5;

    formLayout.spacing = 5;

    //设置了边界高度和宽度以及组件间距的FormLayout

    这个在原有UI组件中没有,它是一个非常灵活可控的布局方式,每一个组件在添加时候,需要设置一个构造并设置一个FormData对象,布局管理器通过对它的设置来完成布局。FromData拥有四个域topbottomleftright分别对应此组件的上下左右。每一个域都要构造一个FormAttachment对象来进行设置,FormAttachment构造器如下:

    来看如下代码:

    formData = new FormData();

    formData.top = new FormAttachment(0,0);

    formData.left = new FormAttachment(tabFolder,0,SWT.RIGHT);

    formData.right = new FormAttachment(100,0);

    formData.bottom = new FormAttachment(97,0);

    channelTree.setLayoutData(formData);

    这里这个Tree组件的top被设置在距离顶端0%,偏移为0个像素点的位置,当然,因为前面我们设置了组件的边界高度、宽度以及间距,所以它并不会顶格;组件的left被设置在距离tabFolder组件右边0个像素点的位置,同理因为有marginspace,两组件有至少10的距离;后面两个比较好理解,即右边界设置为整个父组件的最右边(从左往右100%)的位置,偏移为0,下边界为97%的位置。

    三、SWT中的ActiveX/Com接口

    SWT中,我们可以通过java代码(OLE操作)调用ActiveX组件,例如WordExcelWMP等,而且它们都是可控的。下面介绍下具体的引用和控制方法。

    基本方法:

    1. 使用SWT进行OLE操作时,所有的对OLE对象的引用都是通过OlE定义的Id获得,获得各个对象的Id方法稍后会进行说明。

    2. 所有的动作都通过OleAutomation对象进行,OleAutomation可以代表任一OLE对象,如WorkbookWorksheetRange。可以通过getProperty()方法获得它的属性,也可以用setProperty()方法为它的属性赋值

    3. Variant对象一般是封装了OLE对象的值,可以通过它进行值传入及获得相应的值,也可以通过它获得OleAutomation对象。

    以控制Excel表格为例介绍SWTOLE操作:

    1. 打开OLE/COM Object Viewer(VS2008自带),找到DocumentObjects,找到Microsoft Excel工作表。找到VersionIndependentProgID,也就是对应的程序中需要调用的ID值。这里是Excel.Sheet,然后写下如下代码,创建workbook

    OleClientSite clientSite = new OleClientSite(oleFrame,SWT.NONE,"Excel.Sheet");

            //获得Excelworkbook对象

    OleAutomation workbook = new OleAutomation(clientSite);  

    2. 点击右键选择view type informat,找到dispinterface _Workbooks (注意:有下划线。如果使用了分类功能,在Dispinterfaces节点下),然后点击method,即查找它所包含的方法,选择sheet,找到对应方法的ID 0x000001e5

    3. OleAutomation sheet = workbook.getProperty(SHEET_ID,new Variant[]{new Variant(1)}).getAutomation();获得sheet对象。这里SHEET_ID就是0x000001e5

    4. 获得worksheet对象之后,再查找worksheet的方法(dispinterface _Worksheet),找到Range,得知:这个方法是获得一组Range对象,是一个是一个proget类型的方法(get类型),方法描述是Range* Range([in] VARIANT Cell1, [in, optional] VARIANT Cell2),这里的“in”表示传入的参数,“optional”表示这个参数是可选的,即可要可不要。传入的参数以单元格的location表示(如:A1D2E5),一个参数表示一个单元格,两个参数表示两个参数代表的单元格区域(如:A1 * D5),那么我们可以根据这个方法写如下代码:        

    5. Variant cellA1Variant = sheet.getProperty(CELL_IDnew Variant[]{new Variant("A1")});

    OleAutomation cellA1 = cellA1Variant.getAutomation();

    获得A1单元格,CELL_ID即刚才Range方法的ID 0x000000c5

    6. 获得cellA1这个Range对象之后,查找其中的Value方法,可以对其赋值:

    //A1单元格赋值

    cellA1.setProperty(CELL_VALUE_IDnew Variant("Hello OLE!"));

    其中CELL_VALUE_IDValue方法的ID,这样就Hello OLE写到了A1单元格中了。

    7. 在组件中不仅有propset类型的方法,也会有对应的propget的方法,用于获得相应的值,返回值仍然用Variant带回。

    Variant getValue = cellA1.getProperty(CELL_VALUE_ID);

    System.out.println(getValue.toString());

    四、结束

    由于时间关系只能讲一些SWT的基本应用,更加全面的学习的话大家可以去参阅《Eclipse从入门到精通》,里面不仅介绍了SWT,对JFace也有一定的讲解,内容涵盖较广。

     

     

     

    以上是俱乐部一位前辈所写,本人只是把这贴出来而已


    转载请注明本文地址:用swt做JAVA界面
    展开全文
  • SWT基础学习

    千次阅读 2012-07-13 09:38:03
    开发步骤: 1.创建新工程,在src下新建lib文件夹,然后导入需要的jar包,配置 Java Build Path 将刚刚复制过来的jar包导入到工程, ...import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Color; i

    开发步骤:

    1.创建新工程,在src下新建lib文件夹,然后导入需要的jar包,配置 Java Build Path 将刚刚复制过来的jar包导入到工程,

                      

    2.新建一个java类,并创建main方法,方法内写入:

    import org.eclipse.swt.SWT;
    import org.eclipse.swt.graphics.Color;
    import org.eclipse.swt.graphics.Font;
    import org.eclipse.swt.graphics.Image;
    import org.eclipse.swt.layout.GridData;
    import org.eclipse.swt.layout.GridLayout;
    import org.eclipse.swt.widgets.Button;
    import org.eclipse.swt.widgets.Combo;
    import org.eclipse.swt.widgets.Display;
    import org.eclipse.swt.widgets.Label;
    import org.eclipse.swt.widgets.Shell;
    import org.eclipse.swt.widgets.Table;
    import org.eclipse.swt.widgets.TableColumn;
    import org.eclipse.swt.widgets.TableItem;
    import org.eclipse.swt.widgets.Text;
    
    
    public class TestShell {
    	public static void main(String[] args) {
    		/**
    		 * 第一步创建Display,对应操作系统的控件,使用完必须释放
    		 */
    		Display display = new Display();
    		/**
    		 * 第二部创建shell
    		 * @style 
    		 */
    		Shell shell = new Shell(display);
    		shell.setText("第一个shell窗口");
    		/**
    		 * 第三部指定容器的布局类型
    		 */
    		GridLayout gl = new GridLayout(2,false);
    		gl.marginBottom = 20;
    		gl.marginTop = 10;
    		gl.marginLeft=30;
    		gl.marginRight = 30;
    		gl.verticalSpacing = 20;
    		gl.horizontalSpacing = 20;
    		shell.setLayout(gl);
    		/****
    		 * 第四步创建容器里的控件,并指定摆放位置
    		 */
    		Label label1 = new Label(shell,SWT.NONE);
    		label1.setText("姓名");
    		/**
    		 * 第一个参数是操作系统资源
    		 * 第二参数是字体样式
    		 * 第三参数是字的高度(字号大小)
    		 * 第4个参数是字显示样式
    		 */
    		Font labelFont = new Font(display,"微软雅黑",20,SWT.NONE);
    		
    		Text text1 = new Text(shell,SWT.BORDER);
    		text1.setFont(labelFont);
    		text1.setLayoutData(new GridData(SWT.FILL,SWT.TOP,true,false));
    		
    		Label label2 = new Label(shell,SWT.NONE);
    		label2.setText("密码");
    		
    		Color foreColor = new Color(display,255,0,0);
    		label2.setForeground(foreColor);
    		
    		Text text2 = new Text(shell,SWT.BORDER|SWT.PASSWORD);
    		text2.setLayoutData(new GridData(SWT.FILL,SWT.TOP,true,false));
    		Label label3 = new Label(shell,SWT.NONE);
    		label3.setText("下拉:");
    		Combo combo = new Combo(shell,SWT.NONE);
    		for(int i=1; i<=9; i++){
    			combo.add("下拉选项"+i);
    		}
    		combo.setLayoutData(new GridData(SWT.FILL,SWT.CENTER,true,false));
    		
    		/**
    		 * 创建表格4列的表格
    		 * 
    		 * 1.创建表头
    		 * 2.创建内容数据
    		 */
    		//表格样式是多选 垂直 水平滚动条,显示边缘
    		Table table = new Table(shell,SWT.MULTI|SWT.V_SCROLL|SWT.H_SCROLL|SWT.BORDER);
    		table.setLayoutData(new GridData(SWT.FILL,SWT.FILL,true,true,2,1));
    		table.setHeaderVisible(true);//设置表格头可见
    		table.setLinesVisible(true);//设置表格线可见
    		//创建表格头
    		for(int i=1; i<=4; i++){
    			TableColumn tableColumn = new TableColumn(table,SWT.NONE);
    			tableColumn.setText("第"+i+"列");
    			tableColumn.setWidth(200);
    		}
    		
    		//创建几个数据
    		TableItem item1 = new TableItem(table,SWT.NONE);
    		item1.setText(new String[]{"111","222","3333","444"});
    		
    		Button btn = new Button(shell,SWT.NONE);
    		btn.setText("提交");
    		btn.setLayoutData(new GridData(SWT.CENTER,SWT.CENTER,false,false,2,1));
    		
    		shell.open();
    		while (!shell.isDisposed()) {
    			if (!display.readAndDispatch())
    				display.sleep();
    		}
    		
    		
    		display.dispose();
    	
    	}
    }
    


    至此,一个简单的shell就创建成功了.运行结果如下:


    展开全文
  • java SWT官网例子

    热门讨论 2020-07-29 14:21:05
    java的一套GUI库,eclipse就是用...这套例子是swt官网上的小型例子,每个文件介绍一个简单的功能。 官方网址 http://www.eclipse.org/swt/snippets/ 需要的界面效果可以再官方网址上找到说明,再查看对应的java文件即可
  • SWT examples,SWT官方例子:http://www.eclipse.org/swt/examples.php 该页面所要下载的例子 其中,swt的例子在\plugins\org.eclipse.swt.examples.source_3.7.0.v3740f.jar中
  • SWT问题分析总结

    千次阅读 2019-03-06 17:33:46
    文章目录1 概述2 SWT机制2.1 原理设计框图2.2 Watchdog的初始化2.3 Watchdog的运作3 导致 SWT 重启原因4 log分析4.1 搜索关键 watchdog4.2 搜索关键字 held by4.3 检查Binder的Server 端4.3.1 重要信息4.3.2 如何...

    1 概述

    一般手机异常reboot的原因:
    Reboot rootcause

    1.JE on the system process
       search keywords “FATAL EXCEPTION IN SYSTEM PROCESS:”in main_log
    
    2.NE on the system process
       search keywords “Fatal signal”in main_log
    
    3.SWT on the system process
       Search keywords “WATCHDOG KILLING SYSTEM PROCESS”in main_log
    
    4.KE occurs
       Search keywords “Kernel panic”in kernel_log
    

    Android SWT 即 Android Software Watchdog Timeout。

    System Server进程是Android的一个核心进程,里面为APP运行提供了核心的服务。如果System Server的一些核心服务和重要线程卡住,就会导致相应的功能异常。

    如手机发生hang机,输入无响应,无法启动APP等一些不正常的情况。而且,如果没有一种机制,让这些服务复位的话,那么将严重影响客户体验。尤其是当前大多数手机把电池封装在手机里面的这种,想拨电池重启都很难。

    所以有必要在核心服务和核心线程卡住的时候,让系统有自动复位的机会。于是,google引入了Sytem Server watchdog机制。这个机制来监控核心服务和核心线程是否卡住。

    Framework层的Watchdog监控系统的重要服务和进程是否死锁,例如AMS、WMS、PMS、MS、IMS等。在解析init.rc时初始化和启动,通过addMonitor添加需要监控对象,然后开启30s循环,如果检测到死锁,则dumpTrace并再检测一轮,如果还是死锁,则dumpTrace并杀掉systemServer让zygote重启。

    watchdog is a thread of system_server, it will mornitor some core service of system_server, such as:
    AcitivityManagerService,WindowManagerService,PowerManagerService

    SWT主要用来监控SystemServer 重要线程/Service 的运行情况。如果判断阻塞 60s ,就会把系统重启,来保证系统恢复正常状态.

    2 SWT机制

    2.1 原理设计框图

    在这里插入图片描述
    最开始设计只是在main looper 里面执行register 的monitor 对象 的monitor 方法. 后续Google 改进,通过HandlerChecker 来达成,在HandlerChecker 中审查注入的montior 对象是否能快速执行。即在foreground thread 来执行register 的monitor 对象,而对于其他的线程,则是审查规定时间内是否可以达到idle,不是一直卡死在某个message执行上。
    需要注意的是, SystemServer Watchdog启动是在SystemServer init 的后期, 如果SystemServer 在init 的过程中卡死了,那么就意味着watchdog 不会有任何的作用.

    2.2 Watchdog的初始化

    Android的Watchdog是一个单例线程,在System Server启动时就会init &start Watchdog:

     private void startOtherServices() {
                ...
                traceBeginAndSlog("InitWatchdog");
                final Watchdog watchdog = Watchdog.getInstance();
                watchdog.init(context, mActivityManagerService);
                traceEnd();
                ...
                traceBeginAndSlog("StartWatchdog");
                Watchdog.getInstance().start();
                traceEnd();
                ...
        }
    

    Watchdog在初始化时,会构建很多HandlerChecker,大致可以分为两类:

    Monitor Checker,用于检查是Monitor对象可能发生的死锁, AMS, PKMS, WMS等核心的系统服务都是Monitor对象。

    在代码里搜索关键字addMonitor,会检测如下信息:

    LINUX/android/frameworks/base/services/core/java/com/android/server/input/
    InputManagerService.java	349 Watchdog.getInstance().addMonitor(this); in start()
    LINUX/android/frameworks/base/services/core/java/com/android/server/wm/
    WindowManagerService.java	1161 Watchdog.getInstance().addMonitor(this); in WindowManagerService()
    LINUX/android/frameworks/base/services/core/java/com/android/server/am/
    ActivityManagerService.java	2988 Watchdog.getInstance().addMonitor(this); in ActivityManagerService()
    LINUX/android/frameworks/base/services/core/java/com/android/server/media/
    MediaRouterService.java	95 Watchdog.getInstance().addMonitor(this); in MediaRouterService()
    ......
    

    各个server的monitor函数也只是检测是否可以获得要检测的锁对象,这些service通过
    Watchdog.getInstance().addMonitor(this)将自己(实现了Watchdog.Monitor)添加到
    Watchdog.mMonitorChecker.mMonitors列表中,该列表会不断调用Monitor.Monitor()函数。

     WindowManagerService.java  
        // Called by the heartbeat to ensure locks are not held indefnitely (for deadlock detection).
        @Override
        public void monitor() {
            synchronized (mWindowMap) { }
        }
    

    具体看各个service中实现的monitor函数,发现这个函数很简单,就是去获取对应锁,如果线程死锁或其他原因阻塞,那么必然无法获取锁,monitor()函数执行必然会阻塞。Watchdog就是利用这个原理来判断是否死锁。

    Looper Checker,用于检查线程的消息队列是否长时间处于工作状态。Watchdog自身的消息队列,Ui, Io, Display这些全局的消息队列都是被检查的对象。此外,一些重要的线程的消息队列,也会加入到Looper Checker中,譬如AMS, PKMS,这些是在对应的对象初始化时加入的。
    代码里搜索关键字addThread,会检测如下信息:

    LINUX/android/frameworks/base/services/core/java/com/android/server/power/
    PowerManagerService.java	775 Watchdog.getInstance().addThread(mHandler); in onStart()
    LINUX/android/frameworks/base/services/core/java/com/android/server/am/
    ActivityManagerService.java	2989 Watchdog.getInstance().addThread(mHandler); in ActivityManagerService()
    LINUX/android/frameworks/base/services/core/java/com/android/server/pm/
    PackageManagerService.java	2512 Watchdog.getInstance().addThread(mHandler, WATCHDOG_TIMEOUT); in PackageManagerService()
    

    addThread()将PowerManagerService、PackageManagerService、ActivityManagerService
    等几个主线程Handler保存到Watchdog.mHandlerCheckers列表中;同时还会把上面提到的mMonitorChecker也保存到Watchdog.mHandlerCheckers中;另外还会将foreground thread、ui thread、i/o thread 、display thread 、main thread的Handler也保存到Watchdog.mHandlerCheckers中来;

      /frameworks/base/services/core/java/com/android/server/Watchdog.java        
            // The shared foreground thread is the main checker.  It is where we
            // will also dispatch monitor checks and do other work.
            mMonitorChecker = new HandlerChecker(FgThread.getHandler(),
                    "foreground thread", DEFAULT_TIMEOUT);
            mHandlerCheckers.add(mMonitorChecker);
            // Add checker for main thread.  We only do a quick check since there
            // can be UI running on the thread.
            mHandlerCheckers.add(new HandlerChecker(new Handler(Looper.getMainLooper()),
                    "main thread", DEFAULT_TIMEOUT));
            // Add checker for shared UI thread.
            mHandlerCheckers.add(new HandlerChecker(UiThread.getHandler(),
                    "ui thread", DEFAULT_TIMEOUT));
            // And also check IO thread.
            mHandlerCheckers.add(new HandlerChecker(IoThread.getHandler(),
                    "i/o thread", DEFAULT_TIMEOUT));
            // And the display thread.
            mHandlerCheckers.add(new HandlerChecker(DisplayThread.getHandler(),
                    "display thread", DEFAULT_TIMEOUT));
    

    Watchdog会不断判断这些线程的Looper是否空闲,如果一直非空闲,那么必然被blocked住了。

    2.3 Watchdog的运作

    通过前面的初始化,已经将watchdog需要监测的对象全部准备就绪。接下来就要看它具体是如何去监测的了。

    watchdog本身就是一个线程,我们想知道它是如何去监测各个对象的?那就直接从它的run方法来看就好:

     @Override
        public void run() {
            boolean waitedHalf = false;//标识第一个30s超时
            boolean mSFHang = false;//标识surfaceflinger是否hang?
            mProcessStats.init(); // mtk: get cpu info when SWT occur.
            while (true) {
                final List<HandlerChecker> blockedCheckers;
                final String subject;
                final String name;
                mSFHang = false;
                if (exceptionHWT != null && waitedHalf == false ) {
                    exceptionHWT.WDTMatterJava(300);//hang_detect机制相关,用来重置hang_detect的计数,这里表示正常阶段
    具体可以查看MOL > Quick Start > Hang Detect 问题快速分析 专题!
                }
                final boolean allowRestart;//发生SWT要不要重启
                int debuggerWasConnected = 0;
    
                if (DEBUG)
                    Slog.w(TAG, "SWT Watchdog before synchronized:" + SystemClock.uptimeMillis());
    
                synchronized (this) {
    
                    if (DEBUG)
                        Slog.w(TAG, "SWT Watchdog after synchronized:" + SystemClock.uptimeMillis());
    
                    long timeout = CHECK_INTERVAL;
                    long SFHangTime;
                    // Make sure we (re)spin the checkers that have become idle within
                    // this wait-and-check interval
                 //1、调度所有的HandlerChecker
                    for (int i=0; i<mHandlerCheckers.size(); i++) {
                        //mHandlerCheckers中包含一个mMonitorChecker和几个重要线程的HandlerChecker
    (System_Server进程是最重要的线程):该for循环主要检测mMonitorChecker中重要的
     几把锁(检测死锁)、几个重要线程的消息队列是否空闲(检测是否blocked),当然判断是
     否死锁和被blocked的依据便是是否超时。
                        HandlerChecker hc = mHandlerCheckers.get(i);
                        hc.scheduleCheckLocked();//
    shceduleCheckLocked()所做的事情可以想象成给所有的目标thread发放任务。
                        //如果一个线程死锁或被blocked,那么该HandlerChecker的mCompleted = false、
     mStartTime=阻塞的初始时间点,是判断的基础
                    }
    
                    if (debuggerWasConnected > 0) {
                        debuggerWasConnected--;
                    }
    
                    // NOTE: We use uptimeMillis() here because we do not want to increment the time we
                    // wait while asleep. If the device is asleep then the thing that we are waiting
                    // to timeout on is asleep as well and won't have a chance to run, causing a false
                    // positive on when to kill things.
                    //2、开始定期检查
                    long start = SystemClock.uptimeMillis();
                    while (timeout > 0) {
                        if (Debug.isDebuggerConnected()) {
                            debuggerWasConnected = 2;
                        }
                        try {
                            wait(timeout);
                        } catch (InterruptedException e) {
                            Log.wtf(TAG, e);
                        }
                        if (Debug.isDebuggerConnected()) {
                            debuggerWasConnected = 2;
                        }
                        timeout = CHECK_INTERVAL - (SystemClock.uptimeMillis() - start);
                    }
    
                    //3、检查HandlerChecker的完成状态
                    //MTK enhance
                    SFHangTime = GetSFStatus();
                    if (DEBUG) Slog.w(TAG, "**Get SF Time **" + SFHangTime);
                    if (SFHangTime > TIME_SF_WAIT * 2) {
                        Slog.v(TAG, "**SF hang Time **" + SFHangTime);
                        mSFHang = true;
                        blockedCheckers = getBlockedCheckersLocked();
                        subject = "";
    
                    } //@@
                    else {
                        boolean fdLimitTriggered = false;
                        if (mOpenFdMonitor != null) {
                            fdLimitTriggered = mOpenFdMonitor.monitor();
                        }
    
                        if (!fdLimitTriggered) {
                            final int waitState = evaluateCheckerCompletionLocked();
    //根据mCompleted 、mStartTime值评估等待状态
                            if (waitState == COMPLETED) {//检测完成并正常,继续检查
                                // The monitors have returned; reset
                                waitedHalf = false;
                                continue;
                            } else if (waitState == WAITING) {//30秒之内,继续检查
                                // still waiting but within their configured intervals;
                                // back off and recheck
                                continue;
                            } else if (waitState == WAITED_HALF) {//30~60秒之内,dump一些信息并继续检查
                                if (!waitedHalf) {
                                    // We've waited half the deadlock-detection interval.  Pull a stack
                                    // trace and wait another half.
                                    if (exceptionHWT != null) {
                                        exceptionHWT.WDTMatterJava(360);//hang_detect机制相关,表示进入dump阶段
                                    }
                                    ArrayList<Integer> pids = new ArrayList<Integer>();
                                    pids.add(Process.myPid());
                                    ActivityManagerService.dumpStackTraces(true, pids, null, null,
                                        getInterestingNativePids());
                                    mProcessStats.update();
                                    waitedHalf = true;
                                }
                                continue;
                            }
                            //4、收集超时的HandlerChecker
                            // something is overdue!
                            blockedCheckers = getBlockedCheckersLocked();
    //超了60秒,此时便出问题了,收集超时的HandlerChecker
                            subject = describeCheckersLocked(blockedCheckers);
                        } else {
                            blockedCheckers = Collections.emptyList();
                            subject = "Open FD high water mark reached";
                        }
                    }
                    allowRestart = mAllowRestart;
                }
    
                // If we got here, that means that the system is most likely hung.
                // First collect stack traces from all threads of the system process.
                // Then kill this process so that the system will restart.
                //5、保存一些重要日志,并根据设定,来判断是否需要重启系统
                Slog.e(TAG, "**SWT happen **" + subject);
                if (exceptionHWT != null) {
                    exceptionHWT.switchFtrace(2);
                }
                name = (mSFHang && subject.isEmpty()) ? "surfaceflinger  hang." : "";
                EventLog.writeEvent(EventLogTags.WATCHDOG, name.isEmpty() ? subject : name);
    //将阻塞线程信息打印到Event日志中
    
                if (exceptionHWT != null) {
                    exceptionHWT.WDTMatterJava(420);//hang_detect机制相关,表示发生了SWT
                }
                mProcessStats.update();
                final String cpuInfo = mProcessStats.printCurrentState(SystemClock.uptimeMillis());
                Slog.d(TAG, mProcessStats.printCurrentLoad());
    
                ArrayList<Integer> pids = new ArrayList<>();
                pids.add(Process.myPid());
                if (mPhonePid > 0) pids.add(mPhonePid);
                // Pass !waitedHalf so that just in case we somehow wind up here without having
                // dumped the halfway stacks, we properly re-initialize the trace file.
                final File stack = ActivityManagerService.dumpStackTraces(
                        !waitedHalf, pids, null, null, getInterestingNativePids());
    
                // Give some extra time to make sure the stack traces get written.
                // The system's been hanging for a minute, another second or two won't hurt much.
                SystemClock.sleep(2000);
    
                // Trigger the kernel to dump all blocked threads, and backtraces on all CPUs to the kernel log
                doSysRq('w');
                doSysRq('l');
    
                /// M: WDT debug enhancement
                /// need to wait the AEE dumps all info, then kill system server @{
                // Try to add the error to the dropbox, but assuming that the ActivityManager
                // itself may be deadlocked.  (which has happened, causing this statement to
                // deadlock and the watchdog as a whole to be ineffective)
                Slog.v(TAG, "** save all info before killnig system server **");
                Thread dropboxThread = new Thread("watchdogWriteToDropbox") {
                        public void run() {
                            Slog.v(TAG, "** start addErrorToDropBox **");
                            mActivity.addErrorToDropBox(
                                    "watchdog", null, "system_server", null, null,
                                    name.isEmpty() ? subject : name, cpuInfo, stack, null);
                        }
                    };
                dropboxThread.start();
                try {
                    dropboxThread.join(2000);  // wait up to 2 seconds for it to return.
                } catch (InterruptedException ignored) {}
    
                IActivityController controller;
                synchronized (this) {
                    controller = mController;
                }
                if ((mSFHang == false) && (controller != null)) {
                    Slog.i(TAG, "Reporting stuck state to activity controller");
                    try {
                        Binder.setDumpDisabled("Service dumps disabled due to hung system process.");
                        Slog.i(TAG, "Binder.setDumpDisabled");
                        // 1 = keep waiting, -1 = kill system
                        int res = controller.systemNotResponding(subject);
                        if (res >= 0) {
                            Slog.i(TAG, "Activity controller requested to coninue to wait");
                            waitedHalf = false;
                            continue;
                        }
                        Slog.i(TAG, "Activity controller requested to reboot");
                    } catch (RemoteException e) {
                    }
                }
    
                // Only kill the process if the debugger is not attached.
                if (Debug.isDebuggerConnected()) {
                    debuggerWasConnected = 2;
                }
                if (debuggerWasConnected >= 2) {
                    Slog.w(TAG, "Debugger connected: Watchdog is *not* killing the system process");
                } else if (debuggerWasConnected > 0) {
                    Slog.w(TAG, "Debugger was connected: Watchdog is *not* killing the system process");
                } else if (!allowRestart) {
                    Slog.w(TAG, "Restart not allowed: Watchdog is *not* killing the system process");
                } else {
                    Slog.w(TAG, "*** WATCHDOG KILLING SYSTEM PROCESS: " + subject);
                    WatchdogDiagnostics.diagnoseCheckers(blockedCheckers);
                    /// @}
    
                    Slog.w(TAG, "*** GOODBYE!");
                    exceptionHWT.WDTMatterJava(330); // 330 means watchdog exit successfully.
                    // MTK enhance
                    if (mSFHang)
                    {
                        Slog.w(TAG, "SF hang!");
                        if (GetSFReboot() > 3)
                        {
                            Slog.w(TAG, "SF hang reboot time larger than 3 time, reboot device!");
                            rebootSystem("Maybe SF driver hang,reboot device.");
                        }
                        else
                        {
                            SetSFReboot();
                        }
                    }
                    //@
                    if (mSFHang) {
                        Slog.v(TAG, "killing surfaceflinger for surfaceflinger hang");
                        String[] sf = new String[] {"/system/bin/surfaceflinger"};
                        int[] pid_sf =  Process.getPidsForCommands(sf);
                        if (pid_sf[0] > 0) {
                            Process.killProcess(pid_sf[0]);
                        }
                        Slog.v(TAG, "killing surfaceflinger end");
                    } else {
                        Process.killProcess(Process.myPid());
                    }
    
                    System.exit(10);
                }
    
                waitedHalf = false;
            }
        }
    

    以上代码片段主要的运行逻辑如下:

    1、Watchdog运行后,便开始无限循环,依次调用每一个HandlerChecker的scheduleCheckLocked()方法

    2、调度完HandlerChecker之后,便开始定期检查是否超时,每一次检查的间隔时间由CHECK_INTERVAL常量设定,为30秒

    3、每一次检查都会调用evaluateCheckerCompletionLocked()方法来评估一下HandlerChecker的完成状态:
    a、COMPLETED表示已经完成
    b、WAITING和WAITED_HALF表示还在等待,但未超时
    c、OVERDUE表示已经超时。默认情况下,timeout是1分钟,但监测对象可以通过传参自行设定,譬如PKMS的Handler Checker的超时是10分钟

    4、如果超时时间到了,还有HandlerChecker处于未完成的状态(OVERDUE),则通过getBlockedCheckersLocked()方法,获取阻塞的HandlerChecker,生成一些描述信息

    5、保存日志,包括一些运行时的堆栈信息,这些日志是我们解决Watchdog问题的重要依据。如果判断需要杀掉system_server进程,则给当前进程(system_server)发送signal 9

    3 导致 SWT 重启原因

    线程死锁
    Binder的server端卡住
    Native方法执行时间过长
    SurfaceFlinger卡住
    Dump时间过长
    Zygote fork进程时卡住
    Binder used up

    4 log分析

    4.1 搜索关键 watchdog

    搜索关键 watchdog初步分析rootcause

    03-29 16:59:14.818   748  4784 W Watchdog: *** WATCHDOG KILLING SYSTEM PROCESS: Blocked in monitor com.android.server.input.InputManagerService on foreground thread (android.fg) 
    03-29 16:59:14.818   748  4784 W Watchdog: foreground thread stack trace: 
    03-29 16:59:14.819   748  4784 W Watchdog:     at com.android.server.input.InputManagerService.nativeMonitor(Native Method) 
    03-29 16:59:14.819   748  4784 W Watchdog:     at com.android.server.input.InputManagerService.monitor(InputManagerService.java:1404) 03-29 16:59:14.819   748  4784 W Watchdog:     at com.android.server.Watchdog$HandlerChecker.run(Watchdog.java:179) 
    03-29 16:59:14.819   748  4784 W Watchdog:     at android.os.Handler.handleCallback(Handler.java:739) 03-29 16:59:14.819   748  4784 W Watchdog:     at android.os.Handler.dispatchMessage(Handler.java:95) 
    03-29 16:59:14.819   748  4784 W Watchdog:     at android.os.Looper.loop(Looper.java:135) 
    03-29 16:59:14.819   748  4784 W Watchdog:     at android.os.HandlerThread.run(HandlerThread.java:61) 
    03-29 16:59:14.819   748  4784 W Watchdog:     at com.android.server.ServiceThread.run(ServiceThread.java:46) 
    03-29 16:59:14.819   748  4784 W Watchdog: *** GOODBYE!
    

    可见WD检测到InputManagerService发生Block:

    03-29 16:59:14.818 748 4784 W Watchdog: *** WATCHDOG KILLING SYSTEM PROCESS: Blocked in monitor com.android.server.input.InputManagerService on foreground thread (android.fg)

    在 android.fg线程发生block,查看对应trace:

    "android.fg" prio=5 tid=17 Native 
      | group="main" sCount=1 dsCount=0 obj=0x12e7a120 self=0xb7b20160
      | sysTid=771 nice=0 cgrp=default sched=0/0 handle=0xb7b20538
      | state=S schedstat=( 1927397505 30260078920 12131 ) utm=138 stm=54 core=0 HZ=100 
      | stack=0xa51df000-0xa51e1000 stackSize=1036KB
      | held mutexes=
      kernel: (couldn't read /proc/self/task/771/stack)
      native: #00 pc 0000f9b0  /system/lib/libc.so (syscall+28)
      native: #01 pc 0001318d  
    /system/lib/libc.so (__pthread_cond_timedwait_relative(pthread_cond_t*, pthread_mutex_t*, timespec const*)+56) 
    native: #02 pc 00025315  /system/lib/libinputflinger.so (android::InputReader::monitor()+28) 
    native: #03 pc 0000f56d  /system/lib/libandroid_servers.so (???)
    native: #04 pc 0011441d  
    /system/framework/arm/services.odex (Java_com_android_server_input_InputManagerService_nativeMonitor__J+88) 
      at com.android.server.input.InputManagerService.nativeMonitor(Native method) 
      at com.android.server.input.InputManagerService.monitor(InputManagerService.java:1404) 
      at com.android.server.Watchdog$HandlerChecker.run(Watchdog.java:179)
      at android.os.Handler.handleCallback(Handler.java:739)
      at android.os.Handler.dispatchMessage(Handler.java:95)
      at android.os.Looper.loop(Looper.java:135)
      at android.os.HandlerThread.run(HandlerThread.java:61)
      at com.android.server.ServiceThread.run(ServiceThread.java:46)
    

    Wd监控IMS的InputReader及InputDispatcher线程,从以上trace可知InputReader可能发生死锁,所以继续查看InputReader线程:

    "InputReader" prio=10 tid=34 Native 
      | group="main" sCount=1 dsCount=0 obj=0x13100220 self=0xb7c0dc80
      | sysTid=4310 nice=-8 cgrp=default sched=0/0 handle=0xb7b098a0
      | state=S schedstat=( 62300529241 31784888301 33265 ) utm=5130 stm=1100 core=3 HZ=100 
      | stack=0xa3b7b000-0xa3b7d000 stackSize=1012KB
      | held mutexes=
       kernel: (couldn't read /proc/self/task/4310/stack)
    native: #00 pc 0000f9b0  /system/lib/libc.so (syscall+28)
    native: #01 pc 000a8c4b  /system/lib/libart.so (art::ConditionVariable::Wait(art::Thread*)+82) 
    native: #02 pc 001abc1b  /system/lib/libart.so (art::JNI::IsInstanceOf(_JNIEnv*, _jobject*, _jclass*)+1022) 
    native: #03 pc 0001fe2f  /system/lib/libjavacore.so (???)
    native: #04 pc 0001fe71  /system/lib/libjavacore.so (???)
    native: #05 pc 00283a93  /system/framework/arm/boot.oat (Java_libcore_io_Posix_writeBytes__Ljava_io_FileDescriptor_2Ljava_lang_Object_2II+142) 
      at libcore.io.Posix.writeBytes(Native method)
      at libcore.io.Posix.write(Posix.java:258)
      at libcore.io.BlockGuardOs.write(BlockGuardOs.java:313)
      at libcore.io.IoBridge.write(IoBridge.java:497)
      at java.io.FileOutputStream.write(FileOutputStream.java:186)
      at java.io.OutputStreamWriter.flushBytes(OutputStreamWriter.java:167)
      - locked <@addr=0x14079080> (a java.io.FileOutputStream)
      at java.io.OutputStreamWriter.close(OutputStreamWriter.java:140)
      - locked <@addr=0x14079080> (a java.io.FileOutputStream)
      at com.android.internal.policy.impl.PhoneWindowManager.saveCoverStatus(PhoneWindowManager.java:6266) 
      at com.android.internal.policy.impl.PhoneWindowManager.interceptKeyBeforeQueueing(PhoneWindowManager.java:5823)
      at com.android.server.wm.InputMonitor.interceptKeyBeforeQueueing(InputMonitor.java:370)
      at com.android.server.input.InputManagerService.interceptKeyBeforeQueueing(InputManagerService.java:1491)
    

    可知在 saveCoverStatus时write发生等待,所以一方面检测函数调用。

    另外从全局来查看下InputReader是否正常:
    按power键点亮屏幕:

    03-29 16:53:36.248   748  4310 D InputReader: Perf-Track KeyboardInputMapper Up keyCode=26
    

    进行触屏操作:

    03-29 16:53:52.894   748  4310 D InputReader: Perf-Track AppLaunch_dispatchPtr:Down:x=396.44937, y=1192.06873
    03-29 16:53:53.007   748  4310 D InputReader: Perf-Track AppLaunch_dispatchPtr:Up:x=396.44937, y=1192.06873
    03-29 16:53:53.954   748  4310 D InputReader: Perf-Track AppLaunch_dispatchPtr:Down:x=646.10266, y=853.33331
    03-29 16:53:54.112   748  4310 D InputReader: Perf-Track AppLaunch_dispatchPtr:Up:x=532.26074, y=902.29510
    03-29 16:53:54.457   748  4310 D InputReader: Perf-Track AppLaunch_dispatchPtr:Down:x=370.48544, y=1029.19592
    03-29 16:53:54.595   748  4310 D InputReader: Perf-Track AppLaunch_dispatchPtr:Up:x=518.28015, y=920.28101
    

    传入了键值keyCode=0 (KEYCODE_UNKNOWN = 0):

    03-29 16:57:35.743   748  4310 D InputReader: Perf-Track KeyboardInputMapper Down keyCode=0, scanCode=251, DownTime=0
    03-29 16:57:35.743   748  4310 D InputReader: Perf-Track KeyboardInputMapper Up keyCode=0
    

    所以另一方面检查keyCode=0 (KEYCODE_UNKNOWN = 0)产生的原因。一方面检查函数调用是否有异常,另一方面从键值映射方面来检查。
    此外 ,我们可以从中吸取一些经验就是尽量避免在重要服务进行大量耗时操作。

    4.2 搜索关键字 held by

    搜索关键字held by判断线程是否被 Block,是否有死锁问题
    例如:

    Cmd line: system_server
    "ActivityManager" prio=5 tid=14 Blocked
    | group="main" sCount=1 dsCount=0 obj=0x12d46f90 self=0xb732ba18
    | sysTid=840 nice=-2 cgrp=apps sched=0/0 handle=0xb732c040
    | state=S schedstat=( 3934680041 3104214846 9460 ) utm=166 stm=227 core=2 HZ=100
    | stack=0xa6106000-0xa6108000 stackSize=1036KB
    | held mutexes=
    at com.android.server.net.NetworkStatsService.setUidForeground(NetworkStatsService.java:641)
    - waiting to lock <0x2e5f7eff> (a java.lang.Object) held by thread 35
    at com.android.server.net.NetworkPolicyManagerService.updateRulesForUidLocked(NetworkPolicyMana
    gerService.java:2081)
    

    waiting to lock <0x2e5f7eff> (a java.lang.Object) held by thread 35, 查看thread 35

    "NetworkStats" prio=5 tid=35 TimedWaiting
    | group="main" sCount=1 dsCount=0 obj=0x1393f9e0 self=0xb758ce48
    | sysTid=2021 nice=0 cgrp=apps sched=0/0 handle=0xb76fab58
    | state=S schedstat=( 402053186 255954674 601 ) utm=27 stm=13 core=0 HZ=100
    | stack=0xa32db000-0xa32dd000 stackSize=1036KB
    | held mutexes=
    at java.lang.Object.wait!(Native method)
    - waiting on <0x16b70c1b> (a java.lang.Object)
    at java.lang.Thread.parkFor(Thread.java:1220)
    - locked <0x16b70c1b> (a java.lang.Object)
    at sun.misc.Unsafe.park(Unsafe.java:299)
    at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:197)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueue
    dSynchronizer.java:2055)
    at java.util.concurrent.ArrayBlockingQueue.poll(ArrayBlockingQueue.java:388)
    at com.android.server.NativeDaemonConnector$ResponseQueue.remove(NativeDaemonConnector.jav
    a:614)
    at com.android.server.NativeDaemonConnector.execute(NativeDaemonConnector.java:406)
    at com.android.server.NativeDaemonConnector.executeForList(NativeDaemonConnector.java:360)
    at com.android.server.NetworkManagementService.getNetworkStatsTethering(NetworkManagementSer
    vice.java:1731)
    

    4.3 检查Binder的Server 端

    检查Binder的Server 端是否卡住

    4.3.1 重要信息

    如果线程的状态是Native,并且callstack中含有IPCThreadState::waitForResponse–>IPCThreadState::talkWithDriver的信息就可以初步说明是卡在对端,下一步就是要找到对端

    找到事件以及发生的时间点

    01-01 03:05:34.411 639 1064 I watchdog: Blocked in handler on main thread (main)
    block module: main timeout: 60s
    

    查看时间段内对应线程的 call stack,初步说明是卡在对端

    "main" prio=5 tid=1 Native
      | group="main" sCount=1 dsCount=0 flags=1 obj=0x721e0870 self=0xa805d000
      | sysTid=941 nice=0 cgrp=default sched=0/0 handle=0xabfe74a4
      | state=S schedstat=( 6662448086 9845197785 9495 ) utm=548 stm=118 core=1 HZ=100
      | stack=0xbe090000-0xbe092000 stackSize=8MB
      | held mutexes=
      kernel: (couldn't read /proc/self/task/941/stack)
      native: #00 pc 00049304  /system/lib/libc.so (__ioctl+8)
      native: #01 pc 0001deef  /system/lib/libc.so (ioctl+38)
      native: #02 pc 0004242f  /system/lib/libbinder.so (android::IPCThreadState::talkWithDriver(bool)+170)
      native: #03 pc 00042de9  /system/lib/libbinder.so (android::IPCThreadState::waitForResponse(android::Parcel*, int*)+236)
      native: #04 pc 0003d2e5  /system/lib/libbinder.so (android::BpBinder::transact(unsigned int, android::Parcel const&, android::Parcel*, unsigned int)+36)
      native: #05 pc 000bcdad  /system/lib/libandroid_runtime.so (???)
      native: #06 pc 0074ec65  /system/framework/arm/boot-framework.oat (Java_android_os_BinderProxy_transactNative__ILandroid_os_Parcel_2Landroid_os_Parcel_2I+132)
      at android.os.BinderProxy.transactNative(Native method)
      at android.os.BinderProxy.transact(Binder.java:764)
      at android.content.om.IOverlayManager$Stub$Proxy.getOverlayInfo(IOverlayManager.java:254)
      at com.android.systemui.statusbar.phone.StatusBar.isUsingDarkTheme(unavailable:-1)
      at com.android.systemui.statusbar.phone.StatusBar.updateTheme(unavailable:-1)
      at com.android.systemui.statusbar.phone.StatusBar.onColorsChanged(unavailable:-1)
      at com.android.internal.colorextraction.ColorExtractor.triggerColorsChanged(ColorExtractor.java:186)
      at com.android.systemui.colorextraction.SysuiColorExtractor.setWallpaperVisible(unavailable:-1)
      at com.android.systemui.colorextraction.SysuiColorExtractor$1.lambda$-com_android_systemui_colorextraction_SysuiColorExtractor$1_3105(unavailable:-1)
      at com.android.systemui.colorextraction.-$Lambda$j2m7lOWVNe22BvvVwNuW1ftTq4c.$m$0(unavailable:-1)
      at com.android.systemui.colorextraction.-$Lambda$j2m7lOWVNe22BvvVwNuW1ftTq4c.run(unavailable:-1)
      at android.os.Handler.handleCallback(Handler.java:790)
      at android.os.Handler.dispatchMessage(Handler.java:99)
      at android.os.Looper.loop(Looper.java:164)
      at android.app.ActivityThread.main(ActivityThread.java:6523)
      at java.lang.reflect.Method.invoke(Native method)
      at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:857)
    

    systemui调用getOverlayInfo 出问题是因为Binder对端
    查看SYS_BINDER_INFO,确定Binder对端tid以及sysTid,这里无法确认,但是从getOverlayInfo 来看可能是sysTid=4447

    "Binder:639_17" prio=5 tid=115 Blocked
      | group="main" sCount=1 dsCount=0 flags=1 obj=0x13e4a4a0 self=0xa0310e00
      | sysTid=4447 nice=0 cgrp=default sched=0/0 handle=0x85a75970
      | state=S schedstat=( 1407904321 1543930926 3137 ) utm=101 stm=39 core=2 HZ=100
      | stack=0x8597b000-0x8597d000 stackSize=1006KB
      | held mutexes=
      at com.android.server.om.OverlayManagerService$1.getOverlayInfo(OverlayManagerService.java:511)
      - waiting to lock <0x0d53be75> (a java.lang.Object) held by thread 1
      at android.content.om.IOverlayManager$Stub.onTransact(IOverlayManager.java:79)
      at android.os.Binder.execTransact(Binder.java:697)
    

    而0x0d53be75锁被sysTid=639 持有,持有不释放是639的Binder调用出了问题

    "main" prio=5 tid=1 Native
      | group="main" sCount=1 dsCount=0 flags=1 obj=0x721e0870 self=0xa805d000
      | sysTid=639 nice=-2 cgrp=default sched=0/0 handle=0xabfe74a4
      | state=S schedstat=( 38966905233 5299817531 20464 ) utm=3323 stm=573 core=0 HZ=100
      | stack=0xbe090000-0xbe092000 stackSize=8MB
      | held mutexes=
      kernel: (couldn't read /proc/self/task/639/stack)
      native: #00 pc 00049304  /system/lib/libc.so (__ioctl+8)
      native: #01 pc 0001deef  /system/lib/libc.so (ioctl+38)
      native: #02 pc 0004242f  /system/lib/libbinder.so (android::IPCThreadState::talkWithDriver(bool)+170)
      native: #03 pc 00042de9  /system/lib/libbinder.so (android::IPCThreadState::waitForResponse(android::Parcel*, int*)+236)
      native: #04 pc 0003d2e5  /system/lib/libbinder.so (android::BpBinder::transact(unsigned int, android::Parcel const&, android::Parcel*, unsigned int)+36)
      native: #05 pc 000bcdad  /system/lib/libandroid_runtime.so (???)
      native: #06 pc 0074ec65  /system/framework/arm/boot-framework.oat (Java_android_os_BinderProxy_transactNative__ILandroid_os_Parcel_2Landroid_os_Parcel_2I+132)
      at android.os.BinderProxy.transactNative(Native method)
      at android.os.BinderProxy.transact(Binder.java:764)
      at android.os.IInstalld$Stub$Proxy.idmap(IInstalld.java:936)
      at com.android.server.pm.Installer.idmap(Installer.java:327)
      at com.android.server.om.IdmapManager.createIdmap(IdmapManager.java:62)
      at com.android.server.om.OverlayManagerServiceImpl.updateState(OverlayManagerServiceImpl.java:493)
      at com.android.server.om.OverlayManagerServiceImpl.updateAllOverlaysForTarget(OverlayManagerServiceImpl.java:237)
      at com.android.server.om.OverlayManagerServiceImpl.onTargetPackageChanged(OverlayManagerServiceImpl.java:187)
      at com.android.server.om.OverlayManagerService$PackageReceiver.onPackageChanged(OverlayManagerService.java:392)
      - locked <0x0d53be75> (a java.lang.Object)
      at com.android.server.om.OverlayManagerService$PackageReceiver.onReceive(OverlayManagerService.java:350)
      at android.app.LoadedApk$ReceiverDispatcher$Args.lambda$-android_app_LoadedApk$ReceiverDispatcher$Args_53034(LoadedApk.java:1323)
    

    binder调用卡住导致问题发生,这种情况需要检查binder对端的行为
    若binder对端已无空闲binder线程,则需要从以下两个方面做进一步分析和解决:
    1) 为何binder线程执行如此长时间?
    2) 是否有太多重复binder请求导致binder线程资源被占用,这种请求是否合理?

    4.3.2 如何确定binder的对端

    前提:有binder block的callstack的特征,线程状态为Native

    IPCThreadState::waitForResponse-->IPCThreadState::talkWithDriver
    
    Cmd line: system_server
    "main" prio=5 tid=1 Native
      | group="main" sCount=1 dsCount=0 flags=1 obj=0x721b49b0 self=0xa97b2000
      | sysTid=815 nice=-2 cgrp=default sched=0/0 handle=0xae13a4a4
    

    确定方法:
    第一步:获取时间点 17:54:29.433

    06-22 17:54:29.433   815  1035 I watchdog: Blocked in handler on main thread (main)
    block module: main                 timeout: 60s
    

    第二步:查看时间段内对应线程的 call stack , 获取 sysTid 以及卡住的具体接口

    ----- pid 815 at 2018-06-22 17:53:54 -----
    Cmd line: system_server
    "main" prio=5 tid=1 Native
      | group="main" sCount=1 dsCount=0 flags=1 obj=0x721b49b0 self=0xa97b2000
      | sysTid=815 nice=-2 cgrp=default sched=0/0 handle=0xae13a4a4
      | state=S schedstat=( 18775190570 13246793364 27928 ) utm=1310 stm=566 core=0 HZ=100
      | stack=0xbe1be000-0xbe1c0000 stackSize=8MB
      | held mutexes=
      kernel: (couldn't read /proc/self/task/815/stack)
      native: #00 pc 00048c8c  /system/lib/libc.so (__ioctl+8)
      native: #01 pc 0001dd65  /system/lib/libc.so (ioctl+32)
      native: #02 pc 00042535  /system/lib/libbinder.so (android::IPCThreadState::talkWithDriver(bool)+168)
      native: #03 pc 00042ee9  /system/lib/libbinder.so (android::IPCThreadState::waitForResponse(android::Parcel*, int*)+236)
      native: #04 pc 0003d309  /system/lib/libbinder.so (android::BpBinder::transact(unsigned int, android::Parcel const&, android::Parcel*, unsigned int)+36)
      native: #05 pc 000bcf89  /system/lib/libandroid_runtime.so (???)
      native: #06 pc 002a90a5  /system/framework/arm/boot-framework.oat (Java_android_os_BinderProxy_transactNative__ILandroid_os_Parcel_2Landroid_os_Parcel_2I+132)
      at android.os.BinderProxy.transactNative(Native method)
      at android.os.BinderProxy.transact(Binder.java:764)
      at com.android.internal.telephony.ITelephony$Stub$Proxy.invokeOemRilRequestRaw(ITelephony.java:4634)
      at android.telephony.TelephonyManager.invokeOemRilRequestRaw(TelephonyManager.java:5716)
      at com.android.server.audio.AudioService.sendATCommand(AudioService.java:1068)
      at com.android.server.audio.AudioService.setModemAllPowerdown(AudioService.java:1083)
      at com.android.server.audio.AudioService$AsOnAudioPortUpdateListener.onAudioPatchListUpdate(AudioService.java:1045)
      at android.media.AudioPortEventHandler$1.handleMessage(AudioPortEventHandler.java:108)
      at android.os.Handler.dispatchMessage(Handler.java:106)
      at android.os.Looper.loop(Looper.java:164)
      at com.android.server.SystemServer.run(SystemServer.java:442)
      at com.android.server.SystemServer.main(SystemServer.java:283)
      at java.lang.reflect.Method.invoke(Native method)
      at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:837)
    
    ----- pid 815 at 2018-06-22 17:54:29 -----
    Cmd line: system_server
    "main" prio=5 tid=1 Native
      | group="main" sCount=1 dsCount=0 flags=1 obj=0x721b49b0 self=0xa97b2000
      | sysTid=815 nice=-2 cgrp=default sched=0/0 handle=0xae13a4a4
      | state=S schedstat=( 18775421647 13246793364 27930 ) utm=1310 stm=566 core=0 HZ=100
      | stack=0xbe1be000-0xbe1c0000 stackSize=8MB
      | held mutexes=
      kernel: (couldn't read /proc/self/task/815/stack)
      native: #00 pc 00048c8c  /system/lib/libc.so (__ioctl+8)
      native: #01 pc 0001dd65  /system/lib/libc.so (ioctl+32)
      native: #02 pc 00042535  /system/lib/libbinder.so (android::IPCThreadState::talkWithDriver(bool)+168)
      native: #03 pc 00042ee9  /system/lib/libbinder.so (android::IPCThreadState::waitForResponse(android::Parcel*, int*)+236)
      native: #04 pc 0003d309  /system/lib/libbinder.so (android::BpBinder::transact(unsigned int, android::Parcel const&, android::Parcel*, unsigned int)+36)
      native: #05 pc 000bcf89  /system/lib/libandroid_runtime.so (???)
      native: #06 pc 002a90a5  /system/framework/arm/boot-framework.oat (Java_android_os_BinderProxy_transactNative__ILandroid_os_Parcel_2Landroid_os_Parcel_2I+132)
      at android.os.BinderProxy.transactNative(Native method)
      at android.os.BinderProxy.transact(Binder.java:764)
      at com.android.internal.telephony.ITelephony$Stub$Proxy.invokeOemRilRequestRaw(ITelephony.java:4634)
      at android.telephony.TelephonyManager.invokeOemRilRequestRaw(TelephonyManager.java:5716)
      at com.android.server.audio.AudioService.sendATCommand(AudioService.java:1068)
      at com.android.server.audio.AudioService.setModemAllPowerdown(AudioService.java:1083)
      at com.android.server.audio.AudioService$AsOnAudioPortUpdateListener.onAudioPatchListUpdate(AudioService.java:1045)
      at android.media.AudioPortEventHandler$1.handleMessage(AudioPortEventHandler.java:108)
      at android.os.Handler.dispatchMessage(Handler.java:106)
      at android.os.Looper.loop(Looper.java:164)
      at com.android.server.SystemServer.run(SystemServer.java:442)
      at com.android.server.SystemServer.main(SystemServer.java:283)
      at java.lang.reflect.Method.invoke(Native method)
      at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:837)
    
    

    可见是卡在com.android.internal.telephony.ITelephonyStubStubProxy.invokeOemRilRequestRaw(ITelephony.java:4634),卡住的接口是invokeOemRilRequestRaw, sysTid = 815

    第三步:Check "SYS_BINDER_INFO"找到815的通信对端
    比如
    如果 sysTid = 2938,在Check "SYS_BINDER_INFO"找到如下信息:

    proc 838
    thread 2938:
        outgoing transaction 139654941: ffffffc0877d87ab from 838:2938 to 9111:9123 code 1 flags 10 priv -6...
    

    然后从"SYS_PROCESSES_AND_THREADE" 找到9111是进程monkey

    root 9111  9100  1150100  21780  0  20  0  0  0  fg  fffff  2487234d  S  64  com.android.monkey
    root 9123  9111  1150100  21780  2  14 -6  0  0  fg  00000  5456456c  R  64  bonder_1
    

    如果不能从SYS_BINDER_INFO找到信息,也可以从kernel log去找,或者在当前卡住的callstack中,仅从名字上结合code,确认卡住的对端和具体的接口

    如上例在binder info中找不到815的通信对端,在kernel log中发现binder release的信息:

    [11645.672135] (3)[23724:kworker/u8:6]binder: release 815:815 transaction 3729140 out, still active
    <6>[11647.223911]  (1)[23672:kworker/u8:1]binder: release 1207:1229 transaction 3729140 in, still active
    <6>[11647.223954]  (1)[23672:kworker/u8:1]binder: send failed reply for transaction 3729140, target dead
    

    在binder_info中查找对端,确认对端是1207:1229

    incoming transaction 3729140: cc857480 from 0:0 to 1207:1229 code 79 flags 10 pri 0:118 r1 node 23923 size 120:0 data e6280068
    

    查看1207:1229的backtrace:

    ----- pid 1207 at 2018-06-22 17:54:30 -----
    Cmd line: com.android.phone
    "Binder:1207_2" prio=5 tid=9 Waiting
      | group="main" sCount=1 dsCount=0 flags=1 obj=0x13c01a90 self=0x9fc53c00
      | sysTid=1229 nice=-2 cgrp=default sched=0/0 handle=0x91ca7970
      | state=S schedstat=( 10524016079 5984437221 36564 ) utm=647 stm=404 core=0 HZ=100
      | stack=0x91bad000-0x91baf000 stackSize=1006KB
      | held mutexes=
      at java.lang.Object.wait(Native method)
      - waiting on <0x0bbbfc71> (a com.android.phone.PhoneInterfaceManager$MainThreadRequest)
      at com.android.phone.PhoneInterfaceManager.PhoneInterfaceManager.java(PhoneInterfaceManager.java:1031)
      - locked <0x0bbbfc71> (a com.android.phone.PhoneInterfaceManager$MainThreadRequest)
      at com.android.phone.PhoneInterfaceManager.sendRequest(PhoneInterfaceManager.java:1010)
      at com.android.phone.PhoneInterfaceManager.invokeOemRilRequestRaw(PhoneInterfaceManager.java:3114)
      at com.android.internal.telephony.ITelephony$Stub.onTransact(ITelephony.java:1448)
      at android.os.Binder.execTransact(Binder.java:697)
    

    看起来应该是卡在phone这边的invokeOemRilRequestRaw操作

    4.4 Native 方法执行时间过长导致重启

    线程状态Native,查看是否有PowerManagerService.nativeSetAutoSuspend
    根据callstack找到是何Native方法时间太久,是否等待硬件返回信息,或者硬件本身有问题

    4.5 SurfaceFlinger 卡住导致重启

    搜索关键字 I watchdog ,查看是否有 surfaceflinger hang,默认卡住40s,就会重启。

    4.6 Zygote Fork 进程时卡住

    线程状态Native,查看是否有 Process.zygoteSendArgsAndGetResult

    4.7 Dump 时间过长

    Dump 超过60s 可能会引起手机重启。
    搜索关键字dumpStackTraces 或 dumpStackTraces process

    一般前面会有ANR发生
    前面有fatal JE NE K等Exception
    自动化脚本有call “dumpsys” 去dump 系统信息

    一般来说上面的情况enduser不会遇到,上面原因一般是系统loading过重或者dump的信息过多

    5 案例

    现象:
    安装应用时swt,系统重启
    1.小概率登录账户后台在更新google应用,
    2.连接电脑用豌豆荚安装应用时,
    点击屏幕解锁然后就重启卡死了
    搜索"watchdog":

    07-15 15:13:52.132 984 1174 I watchdog: Blocked in monitor com.android.server.am.ActivityManagerService on foreground thread (android.fg), 
     Blocked in handler on main thread (main), 
     Blocked in handler on i/o thread (android.io),
     Blocked in handler on display thread (android.display), 
     Blocked in handler on ActivityManager (ActivityManager), 
     Blocked in handler on PowerManagerService (PowerManagerService)
    block module: android.fg timeout: 60s
    

    查看对应时间线程的call stack

    1、----- pid 984 at 2017-07-15 15:13:17 -----
    Cmd line: system_server
    "android.fg" prio=5 tid=16 Blocked
    | group="main" sCount=1 dsCount=0 obj=0x12ca59c0 self=0x9de63800
    | sysTid=1004 nice=0 cgrp=default sched=0/0 handle=0x92238920
    | state=S schedstat=( 817332233 838592314 1765 ) utm=68 stm=13 core=2 HZ=100
    | stack=0x92136000-0x92138000 stackSize=1038KB
    | held mutexes=
    at com.android.server.am.ActivityManagerService.monitor(ActivityManagerService.java:22667)
    - waiting to lock <0x04cc3347> (a com.android.server.am.ActivityManagerService) held by thread 11
    at com.android.server.Watchdog$HandlerChecker.run(Watchdog.java:207)
    at android.os.Handler.handleCallback(Handler.java:836)
    at android.os.Handler.dispatchMessage(Handler.java:103)
    at android.os.Looper.loop(Looper.java:203)
    at android.os.HandlerThread.run(HandlerThread.java:61)
    at com.android.server.ServiceThread.run(ServiceThread.java:46)
    
    //android.fg等待的锁,被thread 11拿着;
    
    ----- pid 984 at 2017-07-15 15:13:17 -----
    Cmd line: system_server
    "ActivityManager" prio=5 tid=11 Blocked
    | group="main" sCount=1 dsCount=0 obj=0x12c532e0 self=0x9de61f00
    | sysTid=999 nice=-2 cgrp=default sched=0/0 handle=0x92751920
    | state=S schedstat=( 12393939024 9340072944 12993 ) utm=679 stm=560 core=2 HZ=100
    | stack=0x9264f000-0x92651000 stackSize=1038KB
    | held mutexes=
    at com.android.server.pm.PackageManagerService.prepareUserData(PackageManagerService.java:20141)
    - waiting to lock <0x0d65c6e0> (a java.lang.Object) held by thread 23
    at com.android.server.pm.UserManagerService.onBeforeUnlockUser(UserManagerService.java:2883)
    at com.android.server.am.UserController.finishUserUnlocking(UserController.java:292)
    - locked <0x04cc3347> (a com.android.server.am.ActivityManagerService)
    at com.android.server.am.UserController.unlockUserCleared(UserController.java:973)
    - locked <0x04cc3347> (a com.android.server.am.ActivityManagerService)
    at com.android.server.am.UserController.maybeUnlockUser(UserController.java:938)
    at com.android.server.am.UserController.finishUserBoot(UserController.java:267)
    - locked <0x04cc3347> (a com.android.server.am.ActivityManagerService)
    at com.android.server.am.UserController.finishUserBoot(UserController.java:222)
    at com.android.server.am.UserController.finishUserSwitch(UserController.java:177)
    - locked <0x04cc3347> (a com.android.server.am.ActivityManagerService)
    at com.android.server.am.ActivityStackSupervisor.activityIdleInternalLocked(ActivityStackSupervisor.java:1739)
    at com.android.server.am.ActivityStackSupervisor$ActivityStackSupervisorHandler.activityIdleInternal(ActivityStackSupervisor.java:3902)
    - locked <0x04cc3347> (a com.android.server.am.ActivityManagerService)
    at com.android.server.am.ActivityStackSupervisor$ActivityStackSupervisorHandler.handleMessage(ActivityStackSupervisor.java:3941)
    at android.os.Handler.dispatchMessage(Handler.java:110)
    at android.os.Looper.loop(Looper.java:203)
    at android.os.HandlerThread.run(HandlerThread.java:61)
    at com.android.server.ServiceThread.run(ServiceThread.java:46)
    
    //此处为thread 11 的call stack ,看此部分也在等待锁,此锁被thread 23 拉着,
    
    查看thread 23 的状态:
    
    ---- pid 984 at 2017-07-15 15:13:17 -----
    Cmd line: system_server
    "PackageManager" prio=5 tid=23 Native
    | group="main" sCount=1 dsCount=0 obj=0x12e4b380 self=0x9de65b00
    | sysTid=1015 nice=10 cgrp=bg_non_interactive sched=0/0 handle=0x9183b920
    | state=S schedstat=( 3538952919 2746466081 4616 ) utm=294 stm=59 core=1 HZ=100
    | stack=0x91739000-0x9173b000 stackSize=1038KB
    | held mutexes=
    at android.net.LocalSocketImpl.readba_native(Native method)
    at android.net.LocalSocketImpl.-wrap1(LocalSocketImpl.java:-1)
    at android.net.LocalSocketImpl$SocketInputStream.read(LocalSocketImpl.java:110)
    - locked <0x05fd685e> (a java.lang.Object)
    at libcore.io.Streams.readFully(Streams.java:81)
    at com.android.internal.os.InstallerConnection.readFully(InstallerConnection.java:222)
    at com.android.internal.os.InstallerConnection.readReply(InstallerConnection.java:237)
    at com.android.internal.os.InstallerConnection.transact(InstallerConnection.java:91)
    - locked <0x0966443f> (a com.android.internal.os.InstallerConnection)
    at com.android.internal.os.InstallerConnection.execute(InstallerConnection.java:124)
    at com.android.internal.os.InstallerConnection.dexopt(InstallerConnection.java:147)
    at com.android.server.pm.Installer.dexopt(Installer.java:153)
    at com.android.server.pm.PackageDexOptimizer.performDexOptLI(PackageDexOptimizer.java:257)
    at com.android.server.pm.PackageDexOptimizer.performDexOpt(PackageDexOptimizer.java:101)
    - locked <0x0d65c6e0> (a java.lang.Object)
    at com.android.server.pm.PackageManagerService.installPackageLI(PackageManagerService.java:15729)
    at com.android.server.pm.PackageManagerService.installPackageTracedLI(PackageManagerService.java:15394)
    at com.android.server.pm.PackageManagerService.-wrap25(PackageManagerService.java:-1)
    at com.android.server.pm.PackageManagerService$9.run(PackageManagerService.java:12798)
    - locked <0x0d65c6e0> (a java.lang.Object)
    at android.os.Handler.handleCallback(Handler.java:836)
    at android.os.Handler.dispatchMessage(Handler.java:103)
    at android.os.Looper.loop(Looper.java:203)
    at android.os.HandlerThread.run(HandlerThread.java:61)
    at com.android.server.ServiceThread.run(ServiceThread.java:46)
    

    从以上的依赖可以看出:

    984(system_server):1004(android.fg)—>984(system_server):999(ActivityManager)—>984(system_server):1015(PackageManager)

    所以需要查看上面PackageManager 的行为:看起来在read 信息,如下backtrace ,read 为何这部分read 操作那么久??如下,在read 前还有dexoat 优化,安装,执行的操作,

    所以应该是这部分的操作影响到如下这个call stack 执行力较长时间导致SWT

    at android.net.LocalSocketImpl.readba_native(Native method)
    at android.net.LocalSocketImpl.-wrap1(LocalSocketImpl.java:-1)
    at android.net.LocalSocketImpl$SocketInputStream.read(LocalSocketImpl.java:110)
    - locked <0x05fd685e> (a java.lang.Object)
    at libcore.io.Streams.readFully(Streams.java:81)
    at com.android.internal.os.InstallerConnection.readFully(InstallerConnection.java:222)
    at com.android.internal.os.InstallerConnection.readReply(InstallerConnection.java:237)
    at com.android.internal.os.InstallerConnection.transact(InstallerConnection.java:91)
    - locked <0x0966443f> (a com.android.internal.os.InstallerConnection)
    at com.android.internal.os.InstallerConnection.execute(InstallerConnection.java:124)
    at com.android.internal.os.InstallerConnection.dexopt(InstallerConnection.java:147)
    at com.android.server.pm.Installer.dexopt(Installer.java:153)
    at com.android.server.pm.PackageDexOptimizer.performDexOptLI(Packag
    

    如以上分析,是在等锁超时,SWT,导致超时的原因应该是安装一些应用时,dex2oat 操作等时间较长:如下为SWT时间时,dex2oat 的时间

    07-15 15:12:36.600 12505 12505 I dex2oat : /system/bin/dex2oat --compiler-filter=interpret-only -j1
    07-15 15:12:36.600 12505 12505 I dex2oat : /system/bin/dex2oat --compiler-filter=interpret-only -j1
    07-15 15:12:46.360 12505 12505 I dex2oat : Large app, accepted running with swap.
    07-15 15:12:50.775 12505 12505 W dex2oat : Before Android 4.1, method void com.tencent.biz.pubaccount.AccountDetail.activity.EqqAccountDetailActivity.l() would have incorrectly overridden the package-private method in com.tencent.biz.pubaccount.AccountDetailActivity
    07-15 15:12:51.150 12505 12505 W dex2oat : Before Android 4.1, method void com.tencent.mobileqq.activity.fling.ContentWrapView.ensureTransformationInfo() would have incorrectly overridden the package-private method in android.view.View
    07-15 15:13:19.736 12505 12505 W dex2oat : Verification of java.util.List com.tencent.mobileqq.activity.contact.addcontact.AddContactsView.b() took 151.200ms
    07-15 15:13:54.697 12505 12505 I dex2oat : dex2oat took 78.103s (threads: 1) arena alloc=2MB (2243640B) java alloc=50MB (53066064B) native alloc=45MB (47911536B) free=4MB (4910480B) swap=32MB (33554432B)
    07-15 15:13:54.697 12505 12505 I dex2oat : dex2oat took 78.103s (threads: 1) arena alloc=2MB (2243640B) java alloc=50MB (53066064B) native alloc=45MB (47911536B) free=4MB (4910480B) swap=32MB (33554432B)
    

    可以 针对个别apk由于的dex2oat原因安装失败/ 安装慢 / lunch慢进行处理
    关于个别apk由于的dex2oat原因安装失败/ 安装慢 / lunch慢进行处理可参考

    看上面的应用:是微信,qq,之前我们还有处理过可能会导致这样的问题的apk:包括qq、微信、GMS

    展开全文
  • swt中各种参数大全

    2019-07-05 15:15:20
    1按钮组件(Button) (1)Button组件常用样式 SWT.PUSH按钮 ...SWT.CENTER文字居中与SWT.NONE SWT.LEFT左对齐 SWT.RIGHT右对齐 SWT.BORDER深陷型按钮 SWT.FLAT平面型按钮 一个Button可以指定多...

    1按钮组件(Button)

    (1)Button组件常用样式

    SWT.PUSH按钮

    SWT.CHECK多选按钮

    SWT.RADIO单选按钮

    SWT.ARROW箭头按钮

    SWT.NONE默认按钮

    SWT.CENTER文字居中与SWT.NONE

    SWT.LEFT左对齐

    SWT.RIGHT右对齐

    SWT.BORDER深陷型按钮

    SWT.FLAT平面型按钮

    一个Button可以指定多个样式,只要将指定的各个样式用符号“|”连接起来即可

    Buttonbt=newButton(shell,SWT.CHECK|SWT.BORDER|SWT.LEFT);

    多选、深陷、左对齐

    (2)Button组件的常用方法

    setText(Stringstring),设置组件的标签文字

    setBounds(intx,inty,intwidth,intheight);//设置组件的坐标位置和大小

    setEnabled(Booleanenabled);设置组件是否可用,默认为true

    setFont(Fontfont);设置文字的字体

    setForeground(Colorcolor);设置前景色

    setBackground(Colorcolor);设置背景色

    setImage(Imageimage);设置显示用的图片

    setSelection(Booleanselected);设置是否选中,默认为false

    setToolTipText(Stringstring);设置鼠标停留在组件上是显示的提示信息

     

    2标签组件(Label)

    (1)Label常见式样

    SWT.CENTER居中

    SWT.RIGHT右对齐

    SWT.LEFT左对齐

    SWT.NONE默认样式

    SWT.WRAP自动换行

    SWT.BORDER深陷型

    SWT.SEPARATOR分栏符,默认为竖线分栏符

    HORIZONTAL横线分栏符

     

    3文本框组件(Text)

    (1)Text常见式样

    SWT.NONE默认式样

    SWT.CENTER

    SWT.RIGHT

    SWT.LEFT

    SWT.MULTI可以输入多行,需回车换行

    SWT.WRAP可以输入多行,自动换行

    SWT.PASSWORD密码型,输入字符显示成“*”

    SWT.BORDER深陷型

    SWT.V_SCROLL垂直滚动条

    SWT.H_SCROLL水平滚动条

     

    4下拉框组件(Combo)

    (1)Combo常见样式

    SWT.NONE默认

    SWT.READ_ONLY只读

    SWT.SIMPLE无需单击下拉框,列表会一直显示

     

    (2)Combo下拉框常用方法

    add(Stringstring)在Combo上添加一项

    add(Stringstring,intindex)在Combo的第index(从0开始)项后插入一项

    deselectAll()使Combo组件中的当前选项为空

    removeAll()将Combo中的所有选项清空

    setItems(String[]items)将数组中的各项依次加入到Combo中

    select(intindex)将Combo的第index+1项设置为当前选择项

     

    5列表框组件(List)

    (1)List常见样式

    SWT.NONE默认样式

    SWT.V_SCROLL带垂直滚动条

    SWT.MULTI允许复选

    SWT.SINGLE允许单选

     

    (2)常用方法

    List和Combo组件的方法是一样的,但由于List可选择多项,而Combo只能选择一项

    ,所以List没有getText()方法,List的取值使用getSelection(),返回一个String

    数组。

     

    6菜单(Menu,MenuItem)

    菜单(Menu、MenuItem)是常用的SWT组件,Menu是一个菜单栏,同时也是一个容器

    ,可以容纳菜单项(MenuItem)

    (1)Menu样式

    SWT.BAR菜单栏,用于主菜单

    SWT.DROP_DOWN下拉菜单,用于子菜单

    SWT.POP_UP鼠标右键弹出菜单

    (2)MenuItem式样

    SWT.CASCADE有子菜单的菜单项

    SWT.CHECK选中后前面显示一个小勾

    SWT.PUSH普通型菜单

    SWT.RADIO选中后前面显示一个圆点

    SWT.SEPARATOR分隔符

    (3)建立菜单一般步骤

    ①首先建立一个菜单栏,需要用到SWT.BAR属性

    MenumainMunu=newMenu(shell,SWT.BAR);

    ②在窗体中指定需要显示的菜单栏

    shell.setMenuBar(mainMenu);

    ③创建顶级菜单项,需要使用SWT.CASCADE属性

    MenuItemfileItem=newMenuItem(mainMenu,SWT.CASCADE);

    fileItem.setText("file&F");

    ④创建与顶级菜单项相关的下拉式菜单

    MenufileMenu=newMenu(shell,SWT.DROP_DOWN);

    ⑤将顶级菜单项与下拉菜单关联

    fileItem.setMenu(fileMenu);

    二级菜单的建立只需要重复③~⑤即可

     

    容器类

    1面板(Composite)

    (1)Composite常用方法

    getLayout()获得布局管理器

    getLayoutData()得到布局数据

    getParent()得到容纳该容器的父容器

    getShell()得到容纳该容器的Shell

    layout()将容器上的组件重新布局,相当于刷新

     

     

    2分组框(Group)

    Group是Composite的子类,所以两者用法基本相同。主要区别是Group显示有一个方框,且方

    框线上还可以显示说明文字

     

    3选项卡(TabFolder、TabItem)

    选项卡包括一个选项卡(TabFolder类)和一个选项页(TabItem类),TabFolder是容器,可

    以容纳其它容器和组件,但TabItem不是容器,可以把它看成是一个选项标签,TabFolder通过

    TabItem来对其中的组件进行控制。每一个TabItem用setControl()来控制一个界面组件。

     

    布局管理器

    1充满式布局(FillLayout)

    FillLayout是最简单的布局管理器,它把组件按一行或一列充满整个容器,并强制组件的大小一致。

    一般组件高度和最高组件相同,宽度与最宽组件相同。FillLayout不能折行,不能设置边界距离和间距。

    如果容器中只有一个组件,则该组件会充满整个容器。

    (1)构造方法

    FillLayout()创建按一行充满容器的对象。

    FillLayout(inttype)创建按指定类型充满容器的对象,type有:SWT.HORIZONTAL(行)

    SWT.VERTICAL(列)

    (2)常用属性

    inttype指定组件充满容器的类型

    FillLayout.type=SWT.VERTICAL或SWT.HORIZONTAL;

     

    2行式布局(RowLayout)

    RowLayout可以是组件折行显示,可以设置边界距离和间距。另外,还可以对每个组件通过setLayoutData()

    方法设置RowData对象。RowData用来设置组件大小。

    (1)构造方法

    RowLayout()创建按行放置组件的对象

    RowLayout(inttype)创建按指定类型放置组件的对象。type:SWT.HORIZONTALSWT.VERTICAL

    (2)常用属性

    intmarginWidth组件距容器边缘的宽度(像素),默认为0

    intmarginHeight组件距容器边缘的高度(像素),默认为0

    intmarginTop组件距容器上边缘的距离(像素),默认为3

    intmarginBottom组件距容器下边缘的距离(像素),默认为3

    intspacing组件之间的距离,默认值为3

    booleanjustify如果该属性为true,则组件间的距离随容器的拉伸而变大,默认值为false

    booleanwrap如果该属性为true,当空间不足时会自动折行,默认为true

    booleanpack如果该属性为true,组件大小为设定值;如果为false,则强制组件大小相同

    默认为true

    inttyepSWT.HORIZONTAL(行)SWT.VERTICAL(列)

    (2)RowData类

    RowData称为RowLayout的布局数据类,可用于改变容器中组件外观形状,其构造方法为

    RowData(intwidth,intheight)

     

    3网格式布局(GridLayout)

    GridLayout是实用而且功能强大的标准布局,也是较为复杂的一种布局。这种布局把容器分成网格

    ,把组件放置在网格中。GridLayout有很多可配置属性,和RowLayout一样,也有专用的布局数据类

    GridData.GridLayout的构造方法无参数,但可以通过GridData和设置GridLayout属性来设置组建的排列、

    形状、和位置。

    (1)GridLayout属性

    intnumColumn设置容器的列数,组件从左到右按列放置,当组件数大于列数时,下一个组件

    将自动添加到新的一行

    booleanmakeColumnsEqualWidth强制使列都具有相同的宽度,默认为false

    intmarginWidth设置组件与容器边缘的水平距离,默认值为5

    intmarginHeight设置组件与容器边缘的垂直高度,默认值为5

    inthorizontalSpacing设置列与列之间的间距,默认为5

    intverticalSpacing设置行与行之间的间隔,默认为5

     

    (2)布局数据类(GridData类)

    GridData是GridLayout专用的布局数据类,用GridData可以构建很多复杂的布局方式。

    ①构造方法

    GridData()创建一个属性值为默认值的对象

    GridData(inttype)

    ②GridData常用类型

    GridData.FILL通常与对象属性horizontalAlignment和verticalAlignment配合使用,充满对象

    属性指定空间。

    GridData.FILL_HORIZONTAL水平充满,

    GridData.FILL_VERTICAL垂直充满

    GridData.FILL_BOTH双向充满

    GridData.HORIZONTAL_ALIGN_BEGINNING水平靠在对齐

    GridData.HORIZONTAL_ALIGN_END水平靠右对齐

    GridData.HORIZONTAL_ALIGN_CENTER水平居中对齐

    ③GridData常有对象属性如下:

    inthorizontalSpan设置组件占用的列数,默认为1

    intverticalSpan设置组件占用的行数,默认为1

    horizontalAlignment设置组件对齐方式为水平方向

    verticalAlignment设置组件对齐方式为垂直方向

    grabExcessHorizontalSpace抢占额外水平空间

    grabExcessVerticalSpace抢占额外垂直空间

    horizontalAlignment和verticalAlignment可以取以下值:

    GEGINNING开始(水平对齐时居左,垂直对齐时居上)

    CENTER居中,默认

    END结束(水平对齐时居右,垂直对齐时居下)

    FILL充满

     

    4表格式布局(FormLayout)

    FormLayout是一种非常灵活、精确的布局方式,FormData使其专用的布局数据类。

    此外,还增加了一个FormAttachment类。FormAttachment定义了组件的四边与父容器

    (Shell、Composite)的边距,为保证组件在父容器中的相对位置不变,FormAttachment

    类用不同的构造方法来实现组件的定位,用FormData和FormAttachment配合,可以创建复杂

    的界面,而且当主窗体大小改变时,组件的相对位置能保持相对不变。

    (1)FormLayout构造函数

    FormLayout();

    (2)FormLayout的属性

    intmarginWidth//设置组件与容器边缘的水平距离,默认值为0

    intmarginHeihgt//设置组件与容器边缘的垂直距离,默认为0

    (3)FormData类

    ①FormData的构造方法

    FormData()

    FormData(intwidth,intheight)设置组件的宽度和高度

    ②FormData的属性

    width设置组件的宽度

    height设置组件的高度

    top和FormAttachment配合设置组件底部和父容器底部的边距

    left和FormAttachment配合设置组件右边和父容器右边的边框

    如果FormData中的width和height设置的宽度和高度与FormAttachment设置的约束

    发生冲突,则按照FormAttachment设置,width和height的设定值就不起作用了。

    (3)FormAttachment类

    Attachment的含义是附着、粘贴。FormAttachment类就是用来指定组件在父容器中粘贴的

    位置。FormAttachment计算组件粘贴位置和组件大小的方法是依据下面的表达式:

    y=ax+b

    ①FormatAttachment构造方法

    FormatAttachment()组件紧贴父容器的左边缘和上边缘,如果父容器设置了FormLayout属

    性marginWidth、marginHeight,则距父容器的上边缘和左边缘为其值。

    FormatAttachment(Controlcontrol)以指定组件control为参照物

    FormatAttachment(Controlcontrol,intoffset)以指定组件control为参照物,相对指定

    组件偏移量为offset

    FormatAttachment(Controlcontrol,intoffset,intalignment)对齐方式为alignment

    SWT.TOPSWT.BOTTOMSWT.LEFTSWT.RIGHTSWT.CENTER

    FormAttachment(intm,intn,intoffset)以组件相对与父容器宽度或高度的百分比(即斜率a)来给

    组件定位,m为a的分子,n为分母,offset为偏移量

    FormAttachment(intm,intoffer)n默认为100

    FormAttachment(intm)n默认为100,offset默认为0

     

     

    SWT的常用事件

    所有事件、监听器和适配器都放在包org.eclipse.swt.events中。

    (1)SWT中常用事件如下:

    ①addMouseListener鼠标监听器

    mouseDown()

    mouseUP()

    mouseDoubleClick()

    ②addKeyListener按键监听器

    keyPressed()

    keyReleased()

    ③addSelectionListener组件选择监听器

    widgetSelected()

    ④addFocusListener焦点监听器

    focusGained()得到焦点

    focusLost()失去焦点

     

    原文链接:https://wjy320.iteye.com/blog/1999906

    展开全文
  • 什么是SWT

    千次阅读 2016-01-07 14:18:17
    什么是SWT 参考:http://www.cppblog.com/baby-fly/archive/2009/10/20/99008.html  用java的人一定都知道AWT和Swing,而SWT(Standard Widget Toolkit)则是由Eclipse项目组织开发的一套完整的图形界面开发包...
  • SWT

    2018-07-26 13:55:12
    SWT是一个GUI的开发工具包,SWT将GUI的基本组成成分分为了显示界面(Display)命令界面(Shell)和窗口部件(widgets). swt.widgets包下面有Button,Text,Label等最常用的组件。其中自重要的组件是shell和Composite....
  • 从Java诞生至今,已经在太多的领域取得成功,然而它却很少在图形界面程序上崭露头角。究其原因,Java语言缺省的...如今,Eclipse组织编写的SWT开发包,为Java程序员提供了AWT和SWING之外的一个更佳的选择。在本文中...
  • SWT概述

    千次阅读 2016-04-29 22:10:12
    SWT技术是一套基于Java的第三方图形工具库。它的设计思想是提供一套通用的API,使得开发出的图形程序不仅可以不加修改地在平台间移植,而且外观上和速度上与使用C/C++等语言在操作系统平台上开发出来的本地图形程序...
  • 看了一下对Java GUI讨论的帖子,所以写了一篇文章来阐述一下各种GUI技术的优劣。 Java世界中,目前最知名的三大GUI库分别是: ...3、来自IBM Eclipse开源项目的SWT(Standard Widget Toolkit)标...
  • SWT简介

    千次阅读 2007-10-24 17:57:00
    SWT简介 1. 为什么要使用SWT? SWT是一个IBM开发的跨平台GUI开发工具包。在SWT之前,Sun已经提供了一个跨平台GUI开发工具包AWT (Abstract Windowing Toolkit)。虽然AWT框架也使用的是原生窗口部件(native widgets),...
  • 错误:  org.eclipse.swt.SWTError: No more ... at org.eclipse.swt.SWT.error(SWT.java:4387)  at org.eclipse.swt.SWT.error(SWT.java:4276)  at org.eclipse.swt.SWT.error(SWT.java:4247)  
  • 最近两天eclipse莫名其妙出现如题所示问题 ,以下是详细的错误日志:org.eclipse.swt.SWTError: No more handles at org.eclipse.swt.SWT.error(SWT.java:4517) at org.eclipse.swt.SWT.error(SWT.java:4406) at ...
  • 初次接触SWT工程,打算用这个编写一个记事本。跟着我一步步从无到有建立SWT工程吧!
  • 运行SWT程序时,出现上java.lang.UnsatisfiedLinkError: no swt-win32-3236 in java.library.path异常,主要原因于在于,Windows平台中SWT应用程序需要本地化的DLL库的支持才能运行,它们分别是swt-awt-win32-3236.dll和...
  • SWT开发Java应用程序GUI入门

    万次阅读 2016-07-10 11:29:46
    第一次做了Java GUI,我选择用elipse自己的前段开发工具 SWT/JFace。这篇文章是基于eclipse MARS.2. 用SWT编写的GUI的风格如下: 1、 SWT中的一些概念1.1 Display & Shell Display 和 She
  • org.eclipse.swt包的引入

    万次阅读 2018-01-02 09:42:49
    我在做Java可视化程序时,用到下面这几个包,应该怎么处理呢?:(Eclipse环境) import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widg
  • SWT的MessageBox对话框

    千次阅读 2013-05-13 16:37:40
    SWT有不同类型的对话框。有些对话框具有特殊的属性。 MessageBox messageBox = new MessageBox(shell, SWT.OK|SWT.CANCEL); if (messageBox.open() == SWT.OK) { System.out.println("Ok is pressed."); } ...
  • Java界面SWT基本组件——Button

    千次阅读 2014-03-10 10:17:32
    按钮包含普通按钮(SWT.PUSH)、单选按钮(SWT.RADIO)、多选按钮(SWT.CHECK)、箭头按钮(SWT.ARROW)、切换按钮(SWT.TOGGLE)五种类型;按钮可设置按钮的样式,文字对齐方式的样式有 SWT.LEFT、SWT.RIGHT 和 SWT...
1 2 3 4 5 ... 20
收藏数 26,716
精华内容 10,686
关键字:

swt