142.s1-看门狗实现程序锁密码

程序锁需要实时监听应用程序,利用看门狗服务实现。首先获取到所有的任务栈,任务栈最上面的就是刚刚点击的应用,然后便利程序锁数据库,看在不在程序锁数据库中,在程序锁数据库中,就直接跳转到输入密码的界面,由于EditText会获取到焦点,点击的时候会获取到系统的键盘,需要先隐藏系统的键盘et_pwd.setInputType(InputType.TYPE_NULL);

服务不能直接跳activity,需要设置标记

//服务网activity跳转需要设置flag
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

获取任务栈需要权限

<uses-permission android:name="android.permission.GET_TASKS"></uses-permission>

注册看门狗的服务

 

<service android:name="com.ldw.safe.service.WatchDogService"></service>

设置密码的界面activity_set_pwd.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    

    <TextView 
        style="@style/TitleStyle"
        android:text="请输入隐私密码"
        />
    <ImageView 
        android:layout_width="wrap_content"
    	android:layout_height="wrap_content"
    	android:src="@drawable/icon_lock_big"
    	android:layout_marginTop="20dp"
    	android:layout_gravity="center_horizontal"
        />
    <RelativeLayout 
        android:layout_width="match_parent"
    	android:layout_height="wrap_content"
        >
    <EditText 
        android:id="@+id/et_pwd"
        android:layout_width="match_parent"
    	android:layout_height="wrap_content"
    	android:layout_marginLeft="10dp"
    	android:layout_marginRight="10dp"
    	android:layout_marginTop="20dp"
        />
    <Button 
        android:id="@+id/bt_ok"
        android:layout_width="wrap_content"
    	android:layout_height="wrap_content"
    	android:text="确定"
    	android:layout_alignParentRight="true"
    	android:layout_marginRight="10dp"
    	android:background="@drawable/desktop_button_1"
        />
    </RelativeLayout>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="bottom"
        android:orientation="vertical" 
        android:background="#22000000">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal" >

            <Button
                android:id="@+id/bt_1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="1" />

            <Button
                android:id="@+id/bt_2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="2" />

            <Button
                android:id="@+id/bt_3"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="3" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal" >

            <Button
                android:id="@+id/bt_4"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="4" />

            <Button
                android:id="@+id/bt_5"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="5" />

            <Button
                android:id="@+id/bt_6"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="6" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal" >

            <Button
                android:id="@+id/bt_7"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="7" />

            <Button
                android:id="@+id/bt_8"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="8" />

            <Button
                android:id="@+id/bt_9"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="9" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal" >

            <Button
                android:id="@+id/bt_clean_all"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="清空" />

            <Button
                android:id="@+id/bt_0"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="0" />

            <Button
                android:id="@+id/bt_delete"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="删除" />
        </LinearLayout>
    </LinearLayout>
</LinearLayout>

看门狗服务开启的界面activity_setting.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:ldw="http://schemas.android.com/apk/res/com.ldw.safe"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    

    <TextView 
		style="@style/TitleStyle"
    	android:text="手机设置"
        />
    <com.ldw.safe.view.SettingItemView
        android:id="@+id/siv_update"
        android:layout_width="match_parent"
    	android:layout_height="wrap_content"
    	ldw:title="自动更新设置"
    	ldw:desc_on="自动更新已开启"
    	ldw:desc_off="自动更新已关闭"
        />
    <com.ldw.safe.view.SettingItemView
        android:id="@+id/siv_address"
        android:layout_width="match_parent"
    	android:layout_height="wrap_content"
    	ldw:title="电话归属地显示设置"
    	ldw:desc_on="电话归属地显示已开启"
    	ldw:desc_off="电话归属地显示已关闭"
        />
    <com.ldw.safe.view.SettingClickView
        android:id="@+id/scv_address_style"
        android:layout_width="match_parent"
    	android:layout_height="wrap_content"
        />
    <com.ldw.safe.view.SettingClickView
        android:id="@+id/scv_address_location"
        android:layout_width="match_parent"
    	android:layout_height="wrap_content"
        />
    <com.ldw.safe.view.SettingItemView
        android:id="@+id/siv_callsafe"
        android:layout_width="match_parent"
    	android:layout_height="wrap_content"
    	ldw:title="黑名单更新设置"
    	ldw:desc_on="黑名单更新已开启"
    	ldw:desc_off="黑名单更新已关闭"
        />
    <com.ldw.safe.view.SettingItemView
        android:id="@+id/siv_watch_dog"
        android:layout_width="match_parent"
    	android:layout_height="wrap_content"
    	ldw:title="看门狗设置"
    	ldw:desc_on="看门狗已经打开"
    	ldw:desc_off="看门狗已经关闭"
        />
</LinearLayout>


 

看门狗服务的初始化逻辑文件SettingActivity.java

package com.ldw.safe.Activity;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;

import com.ldw.safe.R;
import com.ldw.safe.service.AddressService;
import com.ldw.safe.service.CallSafeService;
import com.ldw.safe.service.WatchDogService;
import com.ldw.safe.utils.ServiceStatusUtils;
import com.ldw.safe.view.SettingClickView;
import com.ldw.safe.view.SettingItemView;

/**
 * 设置中心
 */
public class SettingActivity extends Activity {

	private SettingItemView siv_update;//设置自动更新
	private SettingItemView siv_address;//归属地
	private SettingClickView scv_address_style;//归属地显示的风格
	private SettingClickView scv_address_location;//初始化归属地的位置
	private SettingItemView siv_callsafe;//黑名单
	private SettingItemView siv_watch_dog;//看门狗
	
	private SharedPreferences mPref;//把设置的数据保存在mPref
	
	@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_setting);
        
        //把设置的数据保存在mPref
        mPref = getSharedPreferences("config", MODE_PRIVATE);
               
        initUpdateView();//初始化自动升级开关
        initAdressView();//初始化归属地开关
        initAddressStyle();//初始化归属地样式的选择
        initAddressLocation();//初始化归属地出现的位置
        initBlackView();//黑名单设置开关
        initWatchDog();
	}
	
	/*
	 * 看门狗设置初始化
	 */
	private void initWatchDog() {
		siv_watch_dog = (SettingItemView) findViewById(R.id.siv_watch_dog);

        // 根据归属地服务是否运行来更新checkbox
        boolean serviceRunning = ServiceStatusUtils.isServiceRunning(this,
                "com.ldw.safe.service.WatchDogService");

        if (serviceRunning) {
        	siv_watch_dog.setChecked(true);
        } else {
        	siv_watch_dog.setChecked(false);
        }

        siv_watch_dog.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                if (siv_watch_dog.isChecked()) {
                	siv_watch_dog.setChecked(false);
                    stopService(new Intent(SettingActivity.this,
                    		WatchDogService.class));// 停止归属地服务
                } else {
                	siv_watch_dog.setChecked(true);
                    startService(new Intent(SettingActivity.this,
                    		WatchDogService.class));// 开启归属地服务
                }
            }
        });
		
	}
	
	/*
	 * 黑名单设置初始化
	 */
	private void initBlackView() {
		siv_callsafe = (SettingItemView) findViewById(R.id.siv_callsafe);

        // 根据归属地服务是否运行来更新checkbox
        boolean serviceRunning = ServiceStatusUtils.isServiceRunning(this,
                "com.ldw.safe.service.CallSafeService");

        if (serviceRunning) {
            siv_callsafe.setChecked(true);
        } else {
            siv_callsafe.setChecked(false);
        }

        siv_callsafe.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                if (siv_callsafe.isChecked()) {
                    siv_callsafe.setChecked(false);
                    stopService(new Intent(SettingActivity.this,
                            CallSafeService.class));// 停止归属地服务
                } else {
                    siv_callsafe.setChecked(true);
                    startService(new Intent(SettingActivity.this,
                            CallSafeService.class));// 开启归属地服务
                }
            }
        });
		
	}

	/*
	 * 初始化自动升级开关
	 */
	private void initUpdateView(){
		siv_update = (SettingItemView)findViewById(R.id.siv_update);
        //siv_update.setTitle("自动更新设置");
        
        //获取保存的数据,判断之前选择的是开始还是关闭,初始化进入界面是否勾选
        boolean autoUpdate = mPref.getBoolean("auto_update", true);
        if(autoUpdate){
        	siv_update.setDesc("自动更新已经开启");
        	siv_update.setChecked(true);
        }else{
        	siv_update.setDesc("自动更新已经关闭");
        	siv_update.setChecked(false);
        }
        
        siv_update.setOnClickListener(new OnClickListener(){

			@Override
			public void onClick(View v) {
				//判断右边框的勾选状态
				if(siv_update.isChecked()){
					//设置不勾选
					siv_update.setChecked(false);
					//siv_update.setDesc("自动更新已经关闭");
					//编辑mPref的值
					mPref.edit().putBoolean("auto_update", false).commit();
				}else{
					//设置勾选
					siv_update.setChecked(true);
					//siv_update.setDesc("自动更新已经开启");
					//编辑mPref的值
					mPref.edit().putBoolean("auto_update", true).commit();
				}
			}
        	
        });
	}
	
	/*
	 * 初始化归属地开关
	 */
	private void initAdressView(){
		
		siv_address = (SettingItemView) findViewById(R.id.siv_address);
		//判断归属地的服务是否在运行
		boolean serviceRunning = ServiceStatusUtils.isServiceRunning(this, "com.ldw.safe.service.AddressService");
		//让服务的那个勾选框根据系统中是否有服务来判断是否去开启
		if(serviceRunning){
			siv_address.setChecked(true);
		}else{
			siv_address.setChecked(false);
		}
		
		siv_address.setOnClickListener(new OnClickListener(){

			@Override
			public void onClick(View v) {
				if(siv_address.isChecked()){
					siv_address.setChecked(false);
					stopService(new Intent(SettingActivity.this, AddressService.class));
				}else{
					siv_address.setChecked(true);
					//号码归属地显示开启的时候要开启服务
					startService(new Intent(SettingActivity.this, AddressService.class));
				}
				
			}
			
		});
	}
	
	/*
	 * 修改号码归属地提示框的风格
	 */
	private void initAddressStyle(){
		scv_address_style = (SettingClickView) findViewById(R.id.scv_address_style);
		
		scv_address_style.setTitle("归属地提示框风格");
		//获取保存的样式
		int style = mPref.getInt("address_Style", 0);
		//设置样式
		scv_address_style.setDesc(items[style]);
		
		scv_address_style.setOnClickListener(new OnClickListener(){

			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				showSingleChooseDialog();
			}
			
		});
	}
	
	final String[] items = new String[]{"半透明", "活力橙", "卫士蓝", "金属灰", "苹果绿"};
	
	/*
	 * 弹出归属地样式选择的单选框
	 */
	public void showSingleChooseDialog(){
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		//设置选择框额logo
		builder.setIcon(R.drawable.ic_launcher);
		builder.setTitle("归属地提示框风格");
		//获取保存的风格样式,默认为0
		int style = mPref.getInt("address_Style", 0);
		
		
		builder.setSingleChoiceItems(items, style, 
				new DialogInterface.OnClickListener(){

			@Override
			public void onClick(DialogInterface dialog, int which) {
				//保存选择的样式的序号
				mPref.edit().putInt("address_Style", which).commit();
				//点击以后对话框消失
				dialog.dismiss();
				//设置组合控件的文字描述
				scv_address_style.setDesc(items[which]);
				
			}
			
		});
		builder.setNegativeButton("取消", null);
		builder.show();
	}
	
	/*
	 * 初始化归属地出现的位置
	 */
	private void initAddressLocation(){
		scv_address_location = (SettingClickView) findViewById(R.id.scv_address_location);
		
		scv_address_location.setTitle("归属地提示框的显示位置");
		scv_address_location.setDesc("设置归属地提示框的显示位置");
		
		scv_address_location.setOnClickListener(new OnClickListener(){

			@Override
			public void onClick(View v) {
				//点击以后直接跳转页面
				startActivity(new Intent(SettingActivity.this, DragViewActivity.class));
			}
			
		});
	}

}

 

 

 

看门狗的服务,同时注册广播,根据屏幕的开启和关闭来启动和关闭看门狗WatchDogReceiver.java

 

package com.ldw.safe.service;

import java.util.List;

import android.app.ActivityManager;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;
import android.os.SystemClock;

import com.ldw.safe.Activity.EnterPwdActivity;
import com.ldw.safe.db.dao.AppLockDao;

public class WatchDogService extends Service {

	private ActivityManager activityManager;
	private AppLockDao dao;
	private List<String> appLockInfos;
	//临时停止保护的包名
	private String tempStopProtectPackageName;

	@Override
	public IBinder onBind(Intent intent) {
		// TODO Auto-generated method stub
		return null;
	}
	
private class WatchDogReceiver extends BroadcastReceiver{

		@Override
		public void onReceive(Context context, Intent intent) {
			
			if(intent.getAction().equals("com.ldw.safe.stopprotect")){
				//获取到停止保护的对象
				
				tempStopProtectPackageName = intent.getStringExtra("packageName");
			}else if(intent.getAction().equals(Intent.ACTION_SCREEN_OFF)){
				tempStopProtectPackageName = null;
				// 让看门狗休息
				flag = false;
			}else if(intent.getAction().equals(Intent.ACTION_SCREEN_ON)){
				//让看门狗继续干活
				if(flag == false){
					startWatchDog();
				}
			}
			
			
		}
		
	}
	
	@Override
	public void onCreate(){
		super.onCreate();
		
		dao = new AppLockDao(this);
		
		appLockInfos = dao.findAll();
		
		receiver = new WatchDogReceiver();
		IntentFilter filter = new IntentFilter();
		//停止保护
		filter.addAction("com.ldw.safe.stopprotect");
		//注册一个锁屏的广播,当锁屏的时候看门狗关闭
		//屏幕解锁的时候看门狗打开
		filter.addAction(Intent.ACTION_SCREEN_OFF);
		filter.addAction(Intent.ACTION_SCREEN_ON);
		//注册广播
		registerReceiver(receiver, filter);
		
				
		//获取到进程管理器
		activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
		//首先获取到当前的任务栈
		//知道任务栈最上面的任务(刚刚点击操作的任务栈)
		startWatchDog();
	}
	
	//标记当前看门狗的状态,默认false
	private boolean flag = false;
	private WatchDogReceiver receiver;
	
	private void startWatchDog() {
		//由于看门狗一直在后台运行,子线程中操作,防止阻塞主线程
		new Thread(){
			public void run(){
				flag = true;
				//一直在后台运行
				while (flag) {
					//由于这个狗一直在后台运行。为了避免程序阻塞。
					//获取到当前正在运行的任务栈
					List<RunningTaskInfo> tasks = activityManager.getRunningTasks(1);
					//获取到最上面的进程
					RunningTaskInfo taskInfo = tasks.get(0);
					//获取到最顶端应用程序的包名
					String packageName = taskInfo.topActivity.getPackageName();
					
					System.out.println(packageName);
					//让狗休息一会
					SystemClock.sleep(30);
					//直接从数据库里面查找当前的数据
					//这个可以优化。改成从内存当中寻找
					if(appLockInfos.contains(packageName)){
//					if(dao.find(packageName)){
//						System.out.println("在程序锁数据库里面");
						
						//说明需要临时取消保护
						//是因为用户输入了正确的密码
						if(packageName.equals(tempStopProtectPackageName)){
							
						}else{
							Intent intent = new Intent(WatchDogService.this,EnterPwdActivity.class);
							/**
							 * 需要注意:如果是在服务里面往activity界面跳的话。需要设置flag
							 */
							intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
							//停止保护的对象
							intent.putExtra("packageName", packageName);
							
							startActivity(intent);
						}
					}
				}

			};
		}.start();
		
	}

	@Override
	public void onDestroy(){
		super.onDestroy();
		flag = false;
		unregisterReceiver(receiver);
		receiver = null;
	}

}

密码输入的逻辑文件EnterPwdActivity.java

 

 

package com.ldw.safe.Activity;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.text.InputType;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;

import com.ldw.safe.R;
import com.ldw.safe.utils.UIUtils;

public class EnterPwdActivity extends Activity implements OnClickListener {
	
	private EditText et_pwd;
	private Button bt_0;
	private Button bt_1;
	private Button bt_2;
	private Button bt_3;
	private Button bt_4;
	private Button bt_5;
	private Button bt_6;
	private Button bt_7;
	private Button bt_8;
	private Button bt_9;
	private Button bt_clean_all;
	private Button bt_delete;
	private Button bt_ok;
	private String packageName;

	@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_set_pwd);
        
        initUi();
	}

	private void initUi() {
		et_pwd = (EditText) findViewById(R.id.et_pwd);
		// 隐藏当前的键盘
		et_pwd.setInputType(InputType.TYPE_NULL);
		
		bt_0 = (Button) findViewById(R.id.bt_0);
		bt_1 = (Button) findViewById(R.id.bt_1);
		bt_2 = (Button) findViewById(R.id.bt_2);
		bt_3 = (Button) findViewById(R.id.bt_3);
		bt_4 = (Button) findViewById(R.id.bt_4);
		bt_5 = (Button) findViewById(R.id.bt_5);
		bt_6 = (Button) findViewById(R.id.bt_6);
		bt_7 = (Button) findViewById(R.id.bt_7);
		bt_8 = (Button) findViewById(R.id.bt_8);
		bt_9 = (Button) findViewById(R.id.bt_9);
		
		bt_ok = (Button) findViewById(R.id.bt_ok);

		bt_ok.setOnClickListener(this);
		
		bt_clean_all = (Button) findViewById(R.id.bt_clean_all);

		bt_delete = (Button) findViewById(R.id.bt_delete);
		// 清空
		bt_clean_all.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				et_pwd.setText("");
			}
		});
		// 删除
		bt_delete.setOnClickListener(new OnClickListener() {

			private String str;

			@Override
			public void onClick(View v) {

				str = et_pwd.getText().toString();

				if (str.length() == 0) {
					return;
				}

				et_pwd.setText(str.substring(0, str.length() - 1));

			}
		});
		
		bt_0.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				String str = et_pwd.getText().toString();
				et_pwd.setText(str + bt_0.getText().toString());
			}
		});
		bt_1.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				String str = et_pwd.getText().toString();
				et_pwd.setText(str + bt_1.getText().toString());
			}
		});
		bt_2.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				String str = et_pwd.getText().toString();
				et_pwd.setText(str + bt_2.getText().toString());
			}
		});
		bt_3.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				String str = et_pwd.getText().toString();
				et_pwd.setText(str + bt_3.getText().toString());
			}
		});
		bt_4.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				String str = et_pwd.getText().toString();
				et_pwd.setText(str + bt_4.getText().toString());
			}
		});
		bt_5.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				String str = et_pwd.getText().toString();
				et_pwd.setText(str + bt_5.getText().toString());
			}
		});
		bt_6.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				String str = et_pwd.getText().toString();
				et_pwd.setText(str + bt_6.getText().toString());
			}
		});
		bt_7.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				String str = et_pwd.getText().toString();
				et_pwd.setText(str + bt_7.getText().toString());
			}
		});
		bt_8.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				String str = et_pwd.getText().toString();
				et_pwd.setText(str + bt_8.getText().toString());
			}
		});
		bt_9.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				String str = et_pwd.getText().toString();
				et_pwd.setText(str + bt_9.getText().toString());
			}
		});
		
	}

	@Override
	public void onClick(View v) {
		switch (v.getId()) {
		case R.id.bt_ok:
			String result = et_pwd.getText().toString();
			if ("123".equals(result)) {
				// 如果密码正确。说明是自己人
				/**
				 * 是自己家人。不要拦截他
				 */
				System.out.println("密码输入正确");

				Intent intent = new Intent();
				// 发送广播。停止保护
				intent.setAction("com.ldw.safe.stopprotect");
				// 跟狗说。现在停止保护短信
				intent.putExtra("packageName", packageName);

				sendBroadcast(intent);

				finish();

			} else {
				UIUtils.showToast(EnterPwdActivity.this, "密码错误");
			}

			break;

		}
		
	}
	
	@Override
	public void onBackPressed() {
		// 当用户输入后退健 的时候。我们进入到桌面
		Intent intent = new Intent();
		intent.setAction("android.intent.action.MAIN");
		intent.addCategory("android.intent.category.HOME");
		intent.addCategory("android.intent.category.DEFAULT");
		intent.addCategory("android.intent.category.MONKEY");
		startActivity(intent);
	}

}

 

 

 

这是我第二次的测试log "[ 5] local 192.85.10.15 port 2000 connected to 192.85.10.25 port 32930 Accepted connection from 192.85.10.25, port 55622 [ 5] local 192.85.10.15 port 2001 connected to 192.85.10.25 port 55638 [ 390.057897] watchdog 3622 [ 390.161970] watchdog 3623 [ 390.265906] watchdog 3624 [ 390.369908] watchdog 3625 [ 390.375713] Unable to handle kernel paging request at virtual address 0002001400000000 [ 390.386302] Mem abort info: [ 390.389109] ESR = 0x86000004 [ 390.392176] EC = 0x21: IABT (current EL), IL = 32 bits [ 390.397508] SET = 0, FnV = 0 [ 390.400573] EA = 0, S1PTW = 0 [ 390.403727] [0002001400000000] address between user and kernel address ranges [ 390.410893] Internal error: Oops: 0000000086000004 [#1] SMP [ 390.416489] Modules linked in: hi309a_eth_drv(O) hi309a_mag(O) hi309a_ppe(O) hi309a_poe(O) hi309a_urm(O) hns_mdio hi309a_watchdog(O) hi309a_djtag(O) ahci_platform libahci_platform libahci libata usb_storage sd_mod scsi_mod xhci_plat_hcd hi309a_usb_hisi(O) xhci_hcd usbcore hi309a_lbc(O) hi309a_tsensor(O) hi309a_log(O) hi309a_sata(O) hi309a_pcie(O) hi309a_serdes(O) hi309a_sfc(O) hi309a_pmbus(O) hi309a_i2c(O) hi309a_spi(O) hi309a_gpio(O) hi309a_pinctrl(O) hi309a_subctrl(O) ksecurec(O) [ 390.459397] CPU: 5 PID: 0 Comm: swapper/5 Tainted: G O 5.10.0 #1 [ 390.466739] Hardware name: Hisilicon PhosphorHi1230 EMU (DT) [ 390.472424] pstate: 60400089 (nZCv daIf +PAN -UAO -TCO BTYPE=--) [ 390.473935] watchdog 3626 [ 390.478458] pc : 0x2001400000000 [ 390.478465] lr : 0x1400000000 [ 390.481521] Insufficient stack space to handle exception! [ 390.481523] ESR: 0x96000047 -- DABT (current EL) [ 390.481524] FAR: 0xffff800012090120 [ 390.481527] Task stack: [0xffff800012090000..0xffff800012094000] [ 390.481529] IRQ stack: [0xffff800011d50000..0xffff800011d54000] [ 390.481531] Overflow stack: [0xffff0005fef5d310..0xffff0005fef5e310] [ 390.481533] CPU: 3 PID: 25 Comm: ksoftirqd/3 Tainted: G O 5.10.0 #1 [ 390.481535] Hardware name: Hisilicon PhosphorHi1230 EMU (DT) [ 390.481537] pstate: 004003c9 (nzcv DAIF +PAN -UAO -TCO BTYPE=--) [ 390.481538] pc : el1_sync+0x0/0x100 [ 390.481540] lr : __switch_to+0x80/0xe0 [ 390.481541] sp : ffff800012090120 [ 390.481543] x29: ffff800012093d80 x28: 0000000000000000 [ 390.481547] x27: ffff800011d7bb88 x26: ffff0004c01681c0 [ 390.481550] x25: ffff8000111ae058 x24: ffff0004c01569c8 [ 390.481552] x23: ffff800011553008 x22: ffff0004c01563c0 [ 390.481555] x21: ffff0004c01563c0 x20: ffff0004c01563c0 [ 390.481558] x19: ffff0004c00fc740 x18: 0000000000000000 [ 390.481561] x17: ffff80001155d438 x16: ffff0005fefde4c0 [ 390.481564] x15: 0000000000000000 x14: 00000000000003b2 [ 390.481566] x13: 00000000000003b2 x12: 0000000000000001 [ 390.481569] x11: 0000000000000001 x10: 0000000000000aa0 [ 390.481572] x9 : ffff800012093d80 x8 : ffff0004c0156ec0 [ 390.481575] x7 : ffff0005fef69e80 x6 : 0000000000736720 [ 390.481577] x5 : 0000000000000000 x4 : 0000000000000100 [ 390.481580] x3 : 0000000000000000 x2 : 0000000000000001 [ 390.481583] x1 : ffff0004c01563c0 x0 : ffff0004c00fc740 [ 390.481586] Kernel panic - not syncing: kernel stack overflow [ 390.484330] sp : ffff800012013f40 [ 390.484334] x29: 0000000000000000 x28: 0000000000000000 [ 390.484338] x27: 0000000000000000 x26: ffff0004c00fe3c0 [ 390.484341] x25: 0000000000000000 x24: 0000000000000000 [ 390.484343] x23: ffff8000119b9344 x22: ffff80001155e8f8 [ 390.484347] x21: ffff8000119b9320 x20: 0000000000000005 [ 390.484349] x19: ffff8000119b9248 x18: 0000000000000000 [ 390.484352] x17: 0000000000000000 x16: 0000000000000000 [ 390.484355] x15: 0000000000000000 x14: 00000000000001f3 [ 390.484358] x13: 00000000000001f3 x12: 0000000000000001 [ 390.484361] x11: 0000000000000000 x10: 0000000000000aa0 [ 390.484364] x9 : 0000000000000000 x8 : ffff8000119b8358 [ 390.484367] x7 : ffff800012013e38 x6 : 000000030f461e4b [ 390.484370] x5 : 00ffffffffffffff x4 : 0000000000cccccd [ 390.484373] x3 : 4000000000000000 x2 : 0000000000003baa [ 390.484376] x1 : ffff0005fef9ac20 x0 : 00000000000000e0 [ 390.484379] Call trace: [ 390.484383] 0x2001400000000 [ 390.484392] Code: bad PC value [ 390.487373] ---[ end trace 3a9fa070f655ea5c ]--- [ 390.487386] SMP: stopping secondary CPUs [ 390.487387] Kernel Offset: disabled [ 390.487389] CPU features: 0x00c0,00240026,2a00a838 [ 390.487391] Memory Limit: none BoardType = 0x0 Welcome to BIOS Hboot1....EMU OR formal version 1.0 Boot from main area Copy Hiboot2_A from FLASH to LLC! Copy Hiboot2_A Ok Hboot1 startup log is not initialized Get Cpu freq failed. Boot from main area Welcome to BIOS SEC, 2025-02-17 14:28:00 Reset Cause: External Watchdog Reset | Power On Soft reset count is 1 init by whitelist enter 4-Byte by 4-Byte Address Instruction Table IdxCtrl 0x0, IdxChip 0x0,0xC8 0x67 0x1A 0xFF 0xC8 0x67 PageSize 0x100, SectorSize 0x10000, Size 0x4000000, ReadOpcode 0x13, ReadDummy 0x0,WriteOpcode 0x12, EraseOpcode 0xDC, Protocol 0x0, 0x0, 0x0, Timeout 0x1312D00, 0xF4240!! sfc init, controller 0x0, cs 0x0 init success. ScTsensorCtrl.Val=0x0 ScTsensorCtrl.Val=0x1 ScTsensor1Ctrl.Val=0x0 ScTsensor1Ctrl.Val=0x1 Clear SRAM.RINT = 0x8, ecc, cleared intStatus:0x0 MN Init HHA Init. BIOS boot from area 0 CPU_Cluster0 Temperature: 52 degree CPU_Cluster1 Temperature: 53 degree AVS init start No pmu detected VDDAVS pmu not init, set voltage skipped! AVS init end Press 'Ctrl+D' to rom shell in 2 seconds.. Ddr self refresh check pass UefiId=0x0, BoardId=0xFFFD, DdrType=0x4 Get channel bit map: 0x1 IsSolderDown = 0x1, ChBitMap = 0x1 InRankMirrorEn = 0x1 "请帮我继续分析
最新发布
09-04
<think> 我们面对的是一个包含内核错误、硬件信息和网络连接信息的复杂日志分析任务。日志显示在运行iperf进行10GbE光口打流测试时出现了严重的系统崩溃(Kernel panic),涉及以下关键点: 1. **致命内核错误**: - `Unable to handle kernel paging request at virtual address 0001c01400000000`:这是关键错误,说明CPU试图访问一个无效的虚拟内存地址,通常由以下原因引起: - 内核驱动程序存在内存访问越界(如DMA操作错误) - 内存页表损坏(硬件故障或内核bug) - 堆栈溢出导致内存覆盖 - 错误发生在`swapper/7`进程(CPU空闲线程),表明问题可能发生在中断处理或后台任务中。 2. **硬件环境线索**: - 硬件平台:`Hisilicon PhosphorHi1230 EMU (DT)`(华为海思平台) - 加载的驱动模块:`hi309a_eth_drv`(网络驱动)、`hi309a_ppe`(包处理引擎)、`hns_mdio`(MDIO总线驱动)等 - 复位后BIOS日志显示`External Watchdog Reset | Power On`,暗示硬件看门狗触发复位 3. **网络操作关联**: - 错误触发于执行`iperf3`命令建立连接后(`connected to 192.85.10.15 port 2001`) - 涉及双流测试(同时启动两个iperf客户端进程) --- ### 根本原因分析 根据日志中的技术细节,我们推断根本原因如下: #### 1. **网络驱动的DMA内存管理缺陷** - **证据链**: - 错误地址`0001c01400000000`的数值异常(高位比特被置位),符合DMA缓冲地址特征 - 调用栈中虽无直接符号,但崩溃点邻近网络驱动操作(`kdrv_eth_dev_open`成功日志在前) - 海思平台历史问题:类似DMA地址映射错误在早期版本驱动中出现过(特别是多队列场景) - **机制**: 当两个iperf进程并发启动时(`-A 4`和`-A 5`指定了不同CPU亲和性),驱动可能错误处理了多核并发下的DMA缓冲分配: ```c // 疑似问题代码模式(简化) void* dma_buf = dma_alloc_coherent(dev, size, &dma_handle, GFP_KERNEL); if (!dma_buf) return -ENOMEM; // 多核竞争条件下,此处可能发生dma_handle被覆盖 priv->rx_ring[dma_handle] = dma_buf; // 竞争写入导致地址错乱 ``` 错误的DMA地址被写入硬件寄存器后,后续数据包触发总线错误。 #### 2. **硬件看门狗复位** - 内核崩溃后未能及时喂狗,导致硬件强制复位(`Reset Cause: External Watchdog Reset`) --- ### 解决方案 #### 紧急规避措施 1. **降级测试并发度**: - 避免多流并发测试:移除`-A`和`-Z`(零拷贝)参数 - 单流测试命令: ```bash iperf3 -c 192.85.10.15 -p 2000 -t 100 -i 10 ``` 2. **调整内核参数**: ```bash # 临时增加DMA映射区域(需重启驱动) echo 2048 > /sys/module/hi309a_eth_drv/parameters/dma_pool_size ``` #### 长期修复方案 1. **驱动更新**: - 联系海思获取最新版`hi309a_eth_drv`驱动(需确认修复类似bug的版本) - 若开源,检查驱动源码中DMA资源锁机制: ```c // 修复建议:添加自旋锁保护DMA缓冲区分配 spin_lock(&priv->dma_lock); dma_buf = dma_alloc_coherent(...); priv->rx_ring[index] = dma_buf; spin_unlock(&priv->dma_lock); ``` 2. **内核补丁验证**: - 测试主线内核是否修复:尝试5.15+内核(海思平台支持状态需确认) 3. **硬件诊断**: - 使用`memtester`工具检测内存稳定性 - 检查SFP+光模块兼容性(替换验证) --- ### 日志分析技术总结 | 日志段 | 关键信息 | 诊断结论 | |--------|----------|----------| | `[249.851696] kdrv_eth_dev_open success` | 网络驱动加载成功 | 基本功能正常 | | `[250.241931] Unable to handle kernel paging request` | 虚拟地址访问错误 | DMA/内存损坏 | | `Internal error: Oops: 0000000086000004 [#1] SMP` | CPU 7触发内存异常 | 多核并发问题 | | `Kernel panic - not syncing` | 系统崩溃 | 需立即修复 | | `Reset Cause: External Watchdog Reset` | 硬件看门狗复位 | 内核无响应超过阈值 | §§相关问题§§ 1. 如何诊断Linux内核的内存访问错误? 2. 海思平台网络驱动的常见问题有哪些? 3. 在服务器压力测试中如何避免硬件看门狗复位? </think> ### 日志分析及解决方案 根据提供的测试日志,系统在运行iperf打流测试时发生了严重的**内核级错误**,最终导致硬件复位。以下是关键问题的定位与解决方案: --- ### 核心问题分析 #### 1. **致命内存访问错误** - **日志关键点**: ```log [ 250.241931] Unable to handle kernel paging request at virtual address 0001c01400000000 [ 250.267306] [0001c01400000000] address between user and kernel address ranges [ 250.274471] Internal error: Oops: 0000000086000004 [#1] SMP ``` - **原因**: - CPU尝试访问无效的虚拟内存地址`0x0001c01400000000`,该地址位于用户空间与内核空间交界处(非法区域)。 - 触发场景:iperf测试启动时尝试通过驱动`hi309a_eth_drv`操作XGE光口,但驱动内部的内存管理逻辑错误(如DMA缓冲区映射失败或地址越界)。 - `ESR = 0x86000004`表明错误类型为**指令异常**(IABT),可能是内核代码或驱动访问了未映射的内存[^1]。 #### 2. **驱动兼容性问题** - **日志线索**: ```log Modules linked in: hi309a_eth_drv(O) hi309a_mag(O) hi309a_ppe(O) ... CPU: 7 PID: 0 Comm: swapper/7 Tainted: G O 5.10.0 #1 Hardware name: Hisilicon PhosphorHi1230 EMU (DT) ``` - **原因**: - 加载的驱动模块(如`hi309a_eth_drv`)与当前内核版本(`5.10.0`)存在兼容性问题,尤其在**并发处理**(iperf启动多线程打流)时暴露缺陷。 - `Tainted: G O`标记表明系统使用了第三方闭源驱动(`O`),这类驱动容易因未适配内核更新导致内存错误[^1]。 #### 3. **硬件复位根源** - **日志终点**: ```log Kernel panic - not syncing: Oops: Fatal exception Reset Cause: External Watchdog Reset | Power On ``` - **原因**: - 内核崩溃后触发硬件看门狗(Watchdog)超时,强制复位。 - 复位前日志显示`DDR Init...Warmboot`,表明内存子系统在错误后尝试重新初始化失败。 --- ### 解决方案 #### 1. **修复驱动内存错误** - **检查驱动内存分配逻辑**: - 联系驱动提供商(Hisilicon)获取更新版`hi309a_eth_drv`,重点修复DMA缓冲区映射问题。 - 临时规避:在驱动加载时限制并发线程数,例如修改`/etc/modprobe.d/hi309a.conf`: ```bash options hi309a_eth_drv max_queue=4 # 减少并发队列数 ``` #### 2. **内核参数调优** - **加固内存保护**: ```bash # 防止用户空间访问内核内存 echo 1 > /proc/sys/kernel/kptr_restrict # 增加PTY设备上限(避免资源竞争) echo 1024 > /proc/sys/kernel/pty/max ``` #### 3. **iperf测试参数优化** - **避免触发驱动缺陷**: - 限制测试线程数(减少并发压力): ```bash iperf3 -c 192.85.10.15 -p 2000 -t 100 -P 2 # -P 2 限制为2线程 ``` - 关闭零拷贝模式(`-Z`可能绕过内核缓冲,直接操作硬件引发错误): ```bash iperf3 -c 192.85.10.15 -p 2000 -t 100 # 移除 -Z ``` #### 4. **硬件诊断** - **排查内存与光模块**: - 使用`memtester`工具测试内存稳定性: ```bash memtester 2G 3 # 测试2GB内存,循环3次 ``` - 检查光模块兼容性:更换为厂商认证的SFP+模块。 --- ### 总结 问题根源是**第三方网络驱动**(`hi309a_eth_drv`)在并发高压场景下出现**内存访问越界**,引发内核崩溃。需优先更新驱动并限制并发,同时调整内核参数加固保护[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值