package autoinstall.com.tamic.autoinstall; import android.accessibilityservice.AccessibilityService; import android.content.Intent; import android.os.Build; import android.provider.Settings; import android.util.Log; import android.view.KeyEvent; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; import android.content.BroadcastReceiver; import android.content.Context; import android.content.IntentFilter; import android.text.TextUtils; import java.util.Iterator; import java.util.List; /** Created by liyongkui on 15/9/13. */ public class TamicInstallService extends AccessibilityService { /** INVOKE_TYPE */ private static int INVOKE_TYPE = 0; /** INSTALL */ public static final int TYPE_INSTALL_APP = 1; /** UNINSTALL */ public static final int TYPE_UNINSTALL_APP = 2; /** REASON_KEY */ private static final String SYSTEM_DIALOG_REASON_KEY = "reason"; /** RECENT_APPS */ private static final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps"; /** HOME_KEY */ private static final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey"; /** _LOCK */ private static final String SYSTEM_DIALOG_REASON_LOCK = "lock"; /** ASSIST */ private static final String SYSTEM_DIALOG_REASON_ASSIST = "assist"; /** isAoutOpenApp */ private boolean isAutoRunning = false; /** tag */ public static String LOG_TAG = "AccessibilityService"; @Override protected void onServiceConnected() { // TODO Auto-generated method stub super.onServiceConnected(); registerFilter(); } @Override public void onCreate() { super.onCreate(); } @Override public void onDestroy() { super.onDestroy(); if (homecastReceiver != null) { unregisterReceiver(homecastReceiver); } } @Override public void onAccessibilityEvent(AccessibilityEvent event) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { if (event.getSource() == null) { Log.d(LOG_TAG, "the source = null"); return; } switch (INVOKE_TYPE) { case TYPE_INSTALL_APP: try { processAccessibilityEvent(event); } catch (Exception e) { e.printStackTrace(); } break; case TYPE_UNINSTALL_APP: //processUninstallApplication(event); break; default: break; } } } @Override public void onInterrupt() { } @Override protected boolean onKeyEvent(KeyEvent aKeyEvent) { return true; } @Override public int onStartCommand(Intent intent, int flags, int startId) { return super.onStartCommand(intent, flags, startId); } /** * extractNode. * @param aAccessibilityEvent aAccessibilityEvent * @param aNodeClassName aNodeClassName * @param aNodeText aNodeText * @return AccessibilityNodeInfo */ private AccessibilityNodeInfo extractNode(AccessibilityEvent aAccessibilityEvent, String aNodeClassName, String aNodeText) { List<AccessibilityNodeInfo> extractList = null; AccessibilityNodeInfo targetNode = null; AccessibilityNodeInfo rootNode; if((aAccessibilityEvent == null) || (aAccessibilityEvent.getSource() == null)) { rootNode = this.getRootInActiveWindow(); if(rootNode != null) { extractList = rootNode.findAccessibilityNodeInfosByText(aNodeText); } } else { extractList = aAccessibilityEvent.getSource().findAccessibilityNodeInfosByText(aNodeText); } if ((extractList == null) || extractList.isEmpty()) { targetNode = null; } else { Iterator<AccessibilityNodeInfo> it = extractList.iterator(); AccessibilityNodeInfo tempNode = null; while (it.hasNext()) { tempNode = it.next(); if (!tempNode.getClassName().equals(aNodeClassName)) { continue; } String nodeName = (tempNode.getText() == null) ? "" : tempNode.getText().toString(); if (!nodeName.endsWith(aNodeText)) { continue; } targetNode = tempNode; break; } } return targetNode; } /** * performClickAction * @param aAccessibilityNodeInfo aAccessibilityNodeInfo * @return */ private boolean performClickAction(AccessibilityNodeInfo aAccessibilityNodeInfo) { int targetAction = AccessibilityNodeInfo.ACTION_CLICK; if ((aAccessibilityNodeInfo != null) && aAccessibilityNodeInfo.isEnabled() && aAccessibilityNodeInfo.isClickable() && aAccessibilityNodeInfo.performAction(targetAction)) { return true; } return false; } private void handleAlertDialog(AccessibilityEvent aAccessibilityEvent, String aClassName, String aNodeText) { if (!aAccessibilityEvent.getText().toString().contains(this.getString(R.string.str_accessibility_error))) { AccessibilityNodeInfo accessibilityNodeInfo = extractNode(aAccessibilityEvent, "android.widget.Button", this.getString(R.string.btn_accessibility_ok)); if (accessibilityNodeInfo != null) { performClickAction(accessibilityNodeInfo); } } } /** * containNodeWithText. * @param aAccessibilityEvent aAccessibilityEvent * @param aText aText * @return Text */ private boolean containNodeWithText(AccessibilityEvent aAccessibilityEvent, String aText) { List<AccessibilityNodeInfo> extractList = null; if ((aAccessibilityEvent != null) && (aAccessibilityEvent.getSource()) != null) { extractList = aAccessibilityEvent.getSource().findAccessibilityNodeInfosByText(aText); } else { AccessibilityNodeInfo rootNode = this.getRootInActiveWindow(); if (rootNode != null) { extractList = rootNode.findAccessibilityNodeInfosByText(aText); } } return !(extractList == null || extractList.isEmpty()); } /** * containUninstallInfo * @param aAccessibilityEvent aAccessibilityEvent * @param aNodeText aNodeText * @return installInfos */ private boolean containUninstallInfo(AccessibilityEvent aAccessibilityEvent, String aClassName, String aNodeText) { return containNodeWithText(null, this.getString(R.string.str_accessibility_uninstalled)) || containNodeWithText(null, this.getString(R.string.str_accessibility_uninstalled2)) || containNodeWithText(null, this.getString(R.string.str_accessibility_uninstalled3)); } /** * InstalledFinish * @param aAccessibilityEvent aAccessibilityEvent * @param aClassName aClassName * @param aNodeText aNodeText * @return isInstalledFinish */ private boolean isInstalledFinish(AccessibilityEvent aAccessibilityEvent, String aClassName, String aNodeText) { return aNodeText.equalsIgnoreCase(this.getString(R.string.str_accessibility_installed)) || aNodeText.equalsIgnoreCase(this.getString(R.string.str_accessibility_installed2)) || aNodeText.contains(this.getString(R.string.str_accessibility_installed3)) || aNodeText.contains(this.getString(R.string.btn_accessibility_open)) || aNodeText.contains(this.getString(R.string.btn_accessibility_run)) || containNodeWithText(null, this.getString(R.string.str_accessibility_installed)) || containNodeWithText(null, this.getString(R.string.str_accessibility_installed2)) || containNodeWithText(null, this.getString(R.string.str_accessibility_installed3)); } /** * performClickActionWithFindNode. * @param aAccessibilityNodeInfo aAccessibilityNodeInfo * @param aClassName aClassName * @param aNodeTxt aNodeTxt * @param isGlobal isGlobal * @return true */ private boolean performClickActionWithFindNode(AccessibilityNodeInfo aAccessibilityNodeInfo, String aClassName, String aNodeTxt, boolean isGlobal) { if(aAccessibilityNodeInfo == null) { return false; } else { List<AccessibilityNodeInfo> targetList = aAccessibilityNodeInfo.findAccessibilityNodeInfosByText(aNodeTxt); if (targetList != null) { for (AccessibilityNodeInfo targetNode : targetList) { if (aClassName != null) { String targetClassName = targetNode.getClassName() == null ? "" : targetNode.getClassName().toString(); if (!aClassName.equals(targetClassName)) { continue; } } String targetNodeText = targetNode.getText() == null ? "" : targetNode.getText().toString(); if (!aNodeTxt.equals(targetNodeText)) { continue; } if (isGlobal && !isAutoRunning) { performGlobalAction(AccessibilityNodeInfo.ACTION_FOCUS); } else { performClickAction(targetNode); } return true; } } } return false; } /** * performCloseInstalledUI. * @param aAccessibilityEvent aAccessibilityEvent * @return boolean */ private boolean performCloseInstalledUI(AccessibilityEvent aAccessibilityEvent) { AccessibilityNodeInfo targetNode = (aAccessibilityEvent != null) && (aAccessibilityEvent.getSource() != null) ? aAccessibilityEvent.getSource() : getRootInActiveWindow(); if (performClickActionWithFindNode(targetNode, null, this.getString(R.string.btn_accessibility_ok), false)) { return true; } if (performClickActionWithFindNode(targetNode, null, this.getString(R.string.btn_accessibility_done), false)) { reset(); return true; } if (performClickActionWithFindNode(targetNode, null, this.getString(R.string.btn_accessibility_complete), false)) { reset(); return true; } if (performClickActionWithFindNode(targetNode, null, this.getString(R.string.btn_accessibility_know), false)) { return true; } if (performClickActionWithFindNode(targetNode, null, this.getString(R.string.btn_accessibility_run), true)) { reset(); return true; } if (performClickActionWithFindNode(targetNode, null, this.getString(R.string.btn_accessibility_open), true)) { reset(); return true; } return false; } /** * closeInstalledUI. * @param aAccessibilityEvent aAccessibilityEvent */ private void closeInstalledUI(AccessibilityEvent aAccessibilityEvent) { performCloseInstalledUI(aAccessibilityEvent); } /** * isUninstallUI * @param aAccessibilityEvent aAccessibilityEvent * @param aClassName aClassName * @param aNodeText aNodeText * @return isUninstallUI */ private boolean isUninstallUI(AccessibilityEvent aAccessibilityEvent, String aClassName, String aNodeText) { return aClassName.equalsIgnoreCase("com.android.packageinstaller.UninstallerActivity") || aNodeText.contains(this.getString(R.string.str_accessibility_uninstall)); } /** * InstallUI. * @param aAccessibilityEvent aAccessibilityEvent * @param aClassName aClassName * @param aNodeText aNodeText * @return isInstallUI */ private boolean isInstallUI(AccessibilityEvent aAccessibilityEvent, String aClassName, String aNodeText) { return aClassName.equalsIgnoreCase("com.android.packageinstaller.PackageInstallerActivity") || aNodeText.contains(this.getString(R.string.btn_accessibility_install)); } /** * reset Type */ public static void reset(){ INVOKE_TYPE = 0; } /** * setInvokeType * @param aType type */ public static void setInvokeType(int aType){ INVOKE_TYPE = aType; } private int checkSmartBar = 0; //not yet private boolean hasSmartBar() { if (checkSmartBar == 0) { try { if (Build.class.getMethod("hasSmartBar") != null) { checkSmartBar = 1; } else { checkSmartBar = -1; } } catch(Exception e) { checkSmartBar = -1; } } return (checkSmartBar == 1); } /** * performAutoInstall * @param aAccessibilityEvent aAccessibilityEvent * @param aClassName aClassName */ private void performAutoInstall(AccessibilityEvent aAccessibilityEvent, String aClassName) { AccessibilityNodeInfo targetNode = extractNode(aAccessibilityEvent, aClassName, this.getString(R.string.btn_accessibility_install)); Log.e("test", "target node 1 " + targetNode); if (targetNode != null) { performClickAction(targetNode); return; } targetNode = extractNode(aAccessibilityEvent, aClassName, this.getString(R.string.btn_accessibility_allow_once)); Log.e("test", "target node 2 " + targetNode); if (targetNode != null) { performClickAction(targetNode); return; } targetNode = extractNode(aAccessibilityEvent, aClassName, this.getString(R.string.btn_accessibility_next)); Log.e("test", "target node 3 " + targetNode); if(targetNode != null) { performClickAction(targetNode); autoInstall(aAccessibilityEvent); } } /** * autoInstall * @param aAccessibilityEvent aAccessibilityEvent */ private void autoInstall(AccessibilityEvent aAccessibilityEvent) { String targetClassName = hasSmartBar() ? "android.widget.TextView" : "android.widget.Button"; performAutoInstall(aAccessibilityEvent, targetClassName); } /** * processAccessibilityEvent. * @param aAccessibilityEvent aAccessibilityEvent */ private void processAccessibilityEvent(AccessibilityEvent aAccessibilityEvent) { if(aAccessibilityEvent.getSource() != null) { String packageName = aAccessibilityEvent.getPackageName().toString(); String className = aAccessibilityEvent.getClassName().toString(); String nodeText = aAccessibilityEvent.getSource().getText() == null ? "" : aAccessibilityEvent.getSource().getText().toString().trim(); if(packageName.equals("com.android.packageinstaller")) { if(className.equalsIgnoreCase("android.app.AlertDialog")) { // handleAlertDialog(aAccessibilityEvent, className, nodeText); //should for uninstall Log.e("test", "onAccessibilityEvent alert dialog"); return; } if(containUninstallInfo(aAccessibilityEvent, className, nodeText)) { //skip Log.e("test", "onAccessibilityEvent uninstall 1"); return; } if(isInstalledFinish(aAccessibilityEvent, className, nodeText)) { closeInstalledUI(null); return; } if(isUninstallUI(aAccessibilityEvent, className, nodeText)) { //skip Log.e("test", "onAccessibilityEvent uninstall 2"); return; } if(isInstallUI(aAccessibilityEvent, className, nodeText)) { Log.e("test", "onAccessibilityEvent install"); autoInstall(null); return; } if (!containNodeWithText(null, this.getString(R.string.str_accessibility_install_blocked))) { Log.e("test", "onAccessibilityEvent not contain block"); return; } autoInstall(null); return; } if(packageName.equals("com.lenovo.safecenter")) { processAccessibilityEventForLenvo(aAccessibilityEvent, className, nodeText); } } } /** * registerReceiver. */ private void registerFilter() { IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_SCREEN_ON); filter.addAction(Intent.ACTION_SCREEN_OFF); filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS); //filter.addDataScheme("package"); //regist for broadcasts of interest registerReceiver(homecastReceiver, filter); } /** * EventForLenvo * @param aAccessibilityEvent aAccessibilityEvent * @param aClassName ClassName * @param aNodeText aNodeText */ private void processAccessibilityEventForLenvo(AccessibilityEvent aAccessibilityEvent, String aClassName, String aNodeText) { checkSmartBar = -1; if (aNodeText.contains(this.getString(R.string.str_accessibility_installed3))) { //auto close installed closeInstalledUI(null); } else if (aNodeText.contains(this.getString(R.string.str_accessibility_uninstalled3))) { return; //skip } else if (aClassName.equals("com.lenovo.safecenter.defense.fragment.install.UninstallerActivity")) { //skip } else {//auto install performAutoInstall(null, "android.widget.TextView"); } } /** * BroadcastReceiver */ private BroadcastReceiver homecastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (context == null || intent == null) { return; } String action = intent.getAction(); if (TextUtils.equals(action, Intent.ACTION_SCREEN_ON)) { Log.d(LOG_TAG, "ACTION_SCREEN_ON"); } if (TextUtils.equals(action, Intent.ACTION_SCREEN_OFF)) { Log.d(LOG_TAG, "ACTION_SCREEN_OFF)"); } if (TextUtils.equals(action, Intent.ACTION_PACKAGE_ADDED)) { Log.d(LOG_TAG, "PackAge install"); } if (TextUtils.equals(action, Intent.ACTION_INSTALL_PACKAGE)) { Log.d(LOG_TAG, "ACTION_INSTALL_PACKAGE"); } if (TextUtils.equals(action, Intent.ACTION_CLOSE_SYSTEM_DIALOGS)) { String reason = intent.getStringExtra(SYSTEM_DIALOG_REASON_KEY); if (SYSTEM_DIALOG_REASON_RECENT_APPS.equals(reason)) { // 长按Home键 或者 activity切换键 Log.d(LOG_TAG, "home long onclick"); TamicWindowManager.dismiss(); } else if (SYSTEM_DIALOG_REASON_HOME_KEY.equals(reason)) { // 短按Home键 Log.d(LOG_TAG, "home onclick"); TamicWindowManager.dismiss(); } else if (SYSTEM_DIALOG_REASON_LOCK.equals(reason)) { // 锁屏 TamicWindowManager.dismiss(); } else if (SYSTEM_DIALOG_REASON_ASSIST.equals(reason)) { // samsung 长按Home键 TamicWindowManager.dismiss(); } } } }; /** * isAccessibilitySettingsOn */ public static boolean isAccessibilitySettingsOn(Context mContext) { int accessibilityEnabled = 0; final String service = mContext.getPackageName() + "/" + TamicInstallService.class.getCanonicalName(); try { accessibilityEnabled = Settings.Secure.getInt( mContext.getApplicationContext().getContentResolver(), android.provider.Settings.Secure.ACCESSIBILITY_ENABLED); Log.v(LOG_TAG, "accessibilityEnabled = " + accessibilityEnabled); } catch (Settings.SettingNotFoundException e) { Log.e(LOG_TAG, "Error finding setting, default accessibility to not found: " + e.getMessage()); } TextUtils.SimpleStringSplitter mStringColonSplitter = new TextUtils.SimpleStringSplitter(':'); if (accessibilityEnabled == 1) { Log.v(LOG_TAG, "***ACCESSIBILITY IS ENABLED*** -"); String settingValue = Settings.Secure.getString( mContext.getApplicationContext().getContentResolver(), Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES); if (settingValue != null) { mStringColonSplitter.setString(settingValue); while (mStringColonSplitter.hasNext()) { String accessibilityService = mStringColonSplitter.next(); Log.v(LOG_TAG, " accessibilityService :: " + accessibilityService + " " + service); if (accessibilityService.equalsIgnoreCase(service)) { Log.v(LOG_TAG, "We've found the correct setting - accessibility is switched on!"); return true; } } } } else { Log.v(LOG_TAG, "---ACCESSIBILITY IS DISABLED--"); } return false; } }