/* * * Apache License * Version 2.0, January 2004 * http://www.apache.org/licenses/ * * TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION * * 1. Definitions. * * "License" shall mean the terms and conditions for use, reproduction, * and distribution as defined by Sections 1 through 9 of this document. * * "Licensor" shall mean the copyright owner or entity authorized by * the copyright owner that is granting the License. * * "Legal Entity" shall mean the union of the acting entity and all * other entities that control, are controlled by, or are under common * control with that entity. For the purposes of this definition, * "control" means (i) the power, direct or indirect, to cause the * direction or management of such entity, whether by contract or * otherwise, or (ii) ownership of fifty percent (50%) or more of the * outstanding shares, or (iii) beneficial ownership of such entity. * * "You" (or "Your") shall mean an individual or Legal Entity * exercising permissions granted by this License. * * "Source" form shall mean the preferred form for making modifications, * including but not limited to software source code, documentation * source, and configuration files. * * "Object" form shall mean any form resulting from mechanical * transformation or translation of a Source form, including but * not limited to compiled object code, generated documentation, * and conversions to other media types. * * "Work" shall mean the work of authorship, whether in Source or * Object form, made available under the License, as indicated by a * copyright notice that is included in or attached to the work * (an example is provided in the Appendix below). * * "Derivative Works" shall mean any work, whether in Source or Object * form, that is based on (or derived from) the Work and for which the * editorial revisions, annotations, elaborations, or other modifications * represent, as a whole, an original work of authorship. For the purposes * of this License, Derivative Works shall not include works that remain * separable from, or merely link (or bind by name) to the interfaces of, * the Work and Derivative Works thereof. * * "Contribution" shall mean any work of authorship, including * the original version of the Work and any modifications or additions * to that Work or Derivative Works thereof, that is intentionally * submitted to Licensor for inclusion in the Work by the copyright owner * or by an individual or Legal Entity authorized to submit on behalf of * the copyright owner. For the purposes of this definition, "submitted" * means any form of electronic, verbal, or written communication sent * to the Licensor or its representatives, including but not limited to * communication on electronic mailing lists, source code control systems, * and issue tracking systems that are managed by, or on behalf of, the * Licensor for the purpose of discussing and improving the Work, but * excluding communication that is conspicuously marked or otherwise * designated in writing by the copyright owner as "Not a Contribution." * * "Contributor" shall mean Licensor and any individual or Legal Entity * on behalf of whom a Contribution has been received by Licensor and * subsequently incorporated within the Work. * * 2. Grant of Copyright License. Subject to the terms and conditions of * this License, each Contributor hereby grants to You a perpetual, * worldwide, non-exclusive, no-charge, royalty-free, irrevocable * copyright license to reproduce, prepare Derivative Works of, * publicly display, publicly perform, sublicense, and distribute the * Work and such Derivative Works in Source or Object form. * * 3. Grant of Patent License. Subject to the terms and conditions of * this License, each Contributor hereby grants to You a perpetual, * worldwide, non-exclusive, no-charge, royalty-free, irrevocable * (except as stated in this section) patent license to make, have made, * use, offer to sell, sell, import, and otherwise transfer the Work, * where such license applies only to those patent claims licensable * by such Contributor that are necessarily infringed by their * Contribution(s) alone or by combination of their Contribution(s) * with the Work to which such Contribution(s) was submitted. If You * institute patent litigation against any entity (including a * cross-claim or counterclaim in a lawsuit) alleging that the Work * or a Contribution incorporated within the Work constitutes direct * or contributory patent infringement, then any patent licenses * granted to You under this License for that Work shall terminate * as of the date such litigation is filed. * * 4. Redistribution. You may reproduce and distribute copies of the * Work or Derivative Works thereof in any medium, with or without * modifications, and in Source or Object form, provided that You * meet the following conditions: * * (a) You must give any other recipients of the Work or * Derivative Works a copy of this License; and * * (b) You must cause any modified files to carry prominent notices * stating that You changed the files; and * * (c) You must retain, in the Source form of any Derivative Works * that You distribute, all copyright, patent, trademark, and * attribution notices from the Source form of the Work, * excluding those notices that do not pertain to any part of * the Derivative Works; and * * (d) If the Work includes a "NOTICE" text file as part of its * distribution, then any Derivative Works that You distribute must * include a readable copy of the attribution notices contained * within such NOTICE file, excluding those notices that do not * pertain to any part of the Derivative Works, in at least one * of the following places: within a NOTICE text file distributed * as part of the Derivative Works; within the Source form or * documentation, if provided along with the Derivative Works; or, * within a display generated by the Derivative Works, if and * wherever such third-party notices normally appear. The contents * of the NOTICE file are for informational purposes only and * do not modify the License. You may add Your own attribution * notices within Derivative Works that You distribute, alongside * or as an addendum to the NOTICE text from the Work, provided * that such additional attribution notices cannot be construed * as modifying the License. * * You may add Your own copyright statement to Your modifications and * may provide additional or different license terms and conditions * for use, reproduction, or distribution of Your modifications, or * for any such Derivative Works as a whole, provided Your use, * reproduction, and distribution of the Work otherwise complies with * the conditions stated in this License. * * 5. Submission of Contributions. Unless You explicitly state otherwise, * any Contribution intentionally submitted for inclusion in the Work * by You to the Licensor shall be under the terms and conditions of * this License, without any additional terms or conditions. * Notwithstanding the above, nothing herein shall supersede or modify * the terms of any separate license agreement you may have executed * with Licensor regarding such Contributions. * * 6. Trademarks. This License does not grant permission to use the trade * names, trademarks, service marks, or product names of the Licensor, * except as required for reasonable and customary use in describing the * origin of the Work and reproducing the content of the NOTICE file. * * 7. Disclaimer of Warranty. Unless required by applicable law or * agreed to in writing, Licensor provides the Work (and each * Contributor provides its Contributions) on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * implied, including, without limitation, any warranties or conditions * of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A * PARTICULAR PURPOSE. You are solely responsible for determining the * appropriateness of using or redistributing the Work and assume any * risks associated with Your exercise of permissions under this License. * * 8. Limitation of Liability. In no event and under no legal theory, * whether in tort (including negligence), contract, or otherwise, * unless required by applicable law (such as deliberate and grossly * negligent acts) or agreed to in writing, shall any Contributor be * liable to You for damages, including any direct, indirect, special, * incidental, or consequential damages of any character arising as a * result of this License or out of the use or inability to use the * Work (including but not limited to damages for loss of goodwill, * work stoppage, computer failure or malfunction, or any and all * other commercial damages or losses), even if such Contributor * has been advised of the possibility of such damages. * * 9. Accepting Warranty or Additional Liability. While redistributing * the Work or Derivative Works thereof, You may choose to offer, * and charge a fee for, acceptance of support, warranty, indemnity, * or other liability obligations and/or rights consistent with this * License. However, in accepting such obligations, You may act only * on Your own behalf and on Your sole responsibility, not on behalf * of any other Contributor, and only if You agree to indemnify, * defend, and hold each Contributor harmless for any liability * incurred by, or claims asserted against, such Contributor by reason * of your accepting any such warranty or additional liability. * * END OF TERMS AND CONDITIONS * * APPENDIX: How to apply the Apache License to your work. * * To apply the Apache License to your work, attach the following * boilerplate notice, with the fields enclosed by brackets "[]" * replaced with your own identifying information. (Don't include * the brackets!) The text should be enclosed in the appropriate * comment syntax for the file format. We also recommend that a * file or class name and description of purpose be included on the * same "printed page" as the copyright notice for easier * identification within third-party archives. * * Copyright 2016 Alibaba Group * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * * */ package android.taobao.atlas.runtime; import android.annotation.TargetApi; import android.app.Activity; import android.app.ActivityManager; import android.app.ActivityManager.RunningTaskInfo; import android.app.Application; import android.app.Dialog; import android.app.Fragment; import android.app.Instrumentation; import android.app.UiAutomation; import android.content.ComponentName; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; import android.content.pm.ActivityInfo; import android.content.pm.ResolveInfo; import android.content.res.AssetManager; import android.content.res.Resources; import android.os.Build; import android.os.Bundle; import android.os.IBinder; import android.os.Looper; import android.preference.PreferenceManager; import android.taobao.atlas.bundleInfo.AtlasBundleInfoManager; import android.taobao.atlas.framework.Atlas; import android.taobao.atlas.framework.BundleClassLoader; import android.taobao.atlas.framework.BundleImpl; import android.taobao.atlas.framework.Framework; import android.taobao.atlas.hack.AtlasHacks; import android.taobao.atlas.runtime.newcomponent.activity.ActivityBridge; import android.taobao.atlas.util.log.impl.AtlasMonitor; import android.taobao.atlas.util.FileUtils; import android.taobao.atlas.util.StringUtils; import android.text.TextUtils; import android.util.Log; import android.view.KeyEvent; import android.view.MotionEvent; import android.content.BroadcastReceiver; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; import java.util.Set; public class InstrumentationHook extends Instrumentation { private Context context; private Instrumentation mBase; public static OnIntentRedirectListener sOnIntentRedirectListener; public static interface OnIntentRedirectListener{ public boolean onExternalRedirect(Intent intent,String targetPackageName,String targetActivityName,Activity sourceActivity); } public InstrumentationHook(Instrumentation mBase, Context context){ this.context = context; this.mBase = mBase; } public ActivityResult execStartActivity(final Context who, final IBinder contextThread, final IBinder token, final Activity target, final Intent intent, final int requestCode) { return execStartActivityInternal(who, intent, requestCode,new ExecStartActivityCallback() { @Override public ActivityResult execStartActivity() { return ActivityBridge.execStartActivity(intent,new ExecStartActivityCallback(){ @Override public ActivityResult execStartActivity(Intent wrapperIntent) { return mBase.execStartActivity(who, contextThread, token, target, wrapperIntent, requestCode); } }); } }); } @TargetApi(Build.VERSION_CODES.JELLY_BEAN) public ActivityResult execStartActivity(final Context who, final IBinder contextThread, final IBinder token, final Activity target, final Intent intent, final int requestCode, final Bundle options) { return execStartActivityInternal(who, intent,requestCode, new ExecStartActivityCallback() { @Override public ActivityResult execStartActivity() { return ActivityBridge.execStartActivity(intent,new ExecStartActivityCallback(){ @Override public ActivityResult execStartActivity(Intent wrapperIntent) { return mBase.execStartActivity(who, contextThread, token, target, wrapperIntent, requestCode, options); } }); } }); } @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) public ActivityResult execStartActivity(final Context who, final IBinder contextThread, final IBinder token, final Fragment target, final Intent intent, final int requestCode) { return execStartActivityInternal(who, intent,requestCode, new ExecStartActivityCallback() { @Override public ActivityResult execStartActivity() { return ActivityBridge.execStartActivity(intent,new ExecStartActivityCallback(){ @Override public ActivityResult execStartActivity(Intent wrapperIntent) { return mBase.execStartActivity(who, contextThread, token, target, intent, requestCode); } }); // return mBase.execStartActivity(who, contextThread, token, target, intent, requestCode); } }); } @TargetApi(Build.VERSION_CODES.JELLY_BEAN) public ActivityResult execStartActivity(final Context who, final IBinder contextThread, final IBinder token, final Fragment target, final Intent intent, final int requestCode, final Bundle options) { return execStartActivityInternal(who, intent,requestCode, new ExecStartActivityCallback() { @Override public ActivityResult execStartActivity() { return ActivityBridge.execStartActivity(intent,new ExecStartActivityCallback(){ @Override public ActivityResult execStartActivity(Intent wrapperIntent) { return mBase.execStartActivity(who, contextThread, token, target, intent, requestCode, options); } }); //return mBase.execStartActivity(who, contextThread, token, target, intent, requestCode, options); } }); } public static class ExecStartActivityCallback { ActivityResult execStartActivity(){ return null; } public ActivityResult execStartActivity(Intent wrapperIntent){ return null; } } private ActivityResult execStartActivityInternal(final Context context, Intent intent, final int requestCode, ExecStartActivityCallback callback) { if(intent!=null){ Atlas.getInstance().checkDownGradeToH5(intent); } // Get package name and component name String packageName = null; String componentName = null; if (intent.getComponent() != null) { packageName = intent.getComponent().getPackageName(); componentName = intent.getComponent().getClassName(); } else { ResolveInfo resolveInfo = context.getPackageManager().resolveActivity(intent, 0); if (resolveInfo != null && resolveInfo.activityInfo != null) { packageName = resolveInfo.activityInfo.packageName; componentName = resolveInfo.activityInfo.name; } } if (componentName == null){ ActivityResult result = null; try{ // Just invoke callback since component is null result = callback.execStartActivity(); } catch (Exception e){ e.printStackTrace(); } return result; } // Taobao may start a component not exist in com.taobao.taobao package. if (!StringUtils.equals(context.getPackageName(), packageName)) { if(sOnIntentRedirectListener!=null){ Activity sourceActivity = ActivityTaskMgr.getInstance().peekTopActivity(); if(!sOnIntentRedirectListener.onExternalRedirect(intent,packageName,componentName,sourceActivity)){ Log.e("InstrumentationHook","fiter app"+packageName); return null; } } return callback.execStartActivity(); } String bundleName = AtlasBundleInfoManager.instance().getBundleForComponet(componentName); if(!TextUtils.isEmpty(bundleName)){ BundleImpl impl = (BundleImpl)Atlas.getInstance().getBundle(bundleName); if(impl!=null&&impl.checkValidate()) { return callback.execStartActivity(); }else { if(ActivityTaskMgr.getInstance().peekTopActivity()!=null && Looper.getMainLooper().getThread().getId()==Thread.currentThread().getId()) { final String component = componentName; asyncStartActivity(context, bundleName, intent, requestCode, component,callback); }else{ callback.execStartActivity(); Log.e("InsturmentationHook","patch execStartActivity finish"); } } return null; } // Try to get class from system Classloader try { Class<?> clazz = null; clazz = Framework.getSystemClassLoader().loadClass(componentName); if (clazz != null) { return callback.execStartActivity(); } } catch (ClassNotFoundException e) { fallBackToClassNotFoundCallback(context, intent, componentName); } return null; } public static void fallBackToClassNotFoundCallback(Context context, Intent intent, String componentName) { if(Framework.getClassNotFoundCallback() !=null){ TrackH5FallBack(componentName); if(intent.getComponent() == null && !TextUtils.isEmpty(componentName)){ intent.setClassName(context,componentName); } if(intent.getComponent()!=null) { Framework.getClassNotFoundCallback().returnIntent(intent); } } } private void asyncStartActivity(final Context context,final String bundleName,final Intent intent, final int requestCode,final String component,final ExecStartActivityCallback callback){ final Activity current = ActivityTaskMgr.getInstance().peekTopActivity(); final Dialog dialog = current!=null ? RuntimeVariables.alertDialogUntilBundleProcessed(current,bundleName) : null; if(current!=null && dialog==null){ throw new RuntimeException("alertDialogUntilBundleProcessed can not return null"); } final int activitySize = ActivityTaskMgr.getInstance().sizeOfActivityStack(); final BundleUtil.CancelableTask successTask = new BundleUtil.CancelableTask(new Runnable() { @Override public void run() { Log.e("InstrumentationHook","async startActivity"); // if (current == ActivityTaskMgr.getInstance().peekTopActivity() || activitySize == ActivityTaskMgr.getInstance().sizeOfActivityStack()+1) { if (context instanceof Activity) { callback.execStartActivity(); ((Activity)context).overridePendingTransition(0,0); } else { context.startActivity(intent); } // } if (dialog != null && current != null && !current.isFinishing()) { try { if(dialog.isShowing()) dialog.dismiss(); }catch (Throwable e){} } } }); final BundleUtil.CancelableTask failedTask = new BundleUtil.CancelableTask(new Runnable() { @Override public void run() { if (current == ActivityTaskMgr.getInstance().peekTopActivity()) { fallBackToClassNotFoundCallback(context, intent, component); // Toast.makeText(RuntimeVariables.androidApplication, "install error", Toast.LENGTH_SHORT).show(); } if (dialog != null && current != null && !current.isFinishing()) { try { if(dialog.isShowing()) dialog.dismiss(); }catch(Throwable e){} } } }); if(dialog!=null) { dialog.setOnDismissListener(new DialogInterface.OnDismissListener() { @Override public void onDismiss(DialogInterface dialog) { successTask.cancel(); failedTask.cancel(); } }); BundleUtil.checkBundleStateAsync(bundleName, successTask, failedTask); if(Atlas.getInstance().getBundle(bundleName)==null || Build.VERSION.SDK_INT<22) { if (dialog != null && current != null && !current.isFinishing() && !dialog.isShowing()) { try { dialog.show(); } catch (Throwable e) { } } } } } private static void TrackH5FallBack(String componentName) { String bundleName; if (TextUtils.isEmpty(bundleName = AtlasBundleInfoManager.instance().getBundleForComponet(componentName))) { return; } if (!AtlasBundleInfoManager.instance().isInternalBundle(bundleName)){ return; } String pkg = AtlasBundleInfoManager.instance().getBundleForComponet(componentName); if (pkg != null && Atlas.getInstance().getBundle(pkg)==null){ } } @Override public Activity newActivity(Class<?> clazz, Context context, IBinder token, Application application, Intent intent, ActivityInfo info, CharSequence title, Activity parent, String id, Object lastNonConfigurationInstance) throws InstantiationException, IllegalAccessException { Activity activity = mBase.newActivity(clazz, context, token, application, intent, info, title, parent, id, lastNonConfigurationInstance); if(RuntimeVariables.androidApplication.getPackageName().equals(info.packageName)){ if (AtlasHacks.ContextThemeWrapper_mResources != null) { //AtlasHacks.ContextThemeWrapper_mResources.on(activity).set(RuntimeVariables.delegateResources); AtlasHacks.ContextThemeWrapper_mResources.set(activity,RuntimeVariables.delegateResources); } } return activity; } @Override public Activity newActivity(ClassLoader cl, String className, Intent intent) throws InstantiationException, IllegalAccessException, ClassNotFoundException { Activity activity = null; try{ if (intent!=null && intent.getAction()!=null&& intent.getAction().equals("android.intent.action.MAIN")){ boolean needWait = Framework.getProperty("android.taobao.atlas.mainAct.wait", false); intent.putExtra("android.taobao.atlas.mainAct.wait", needWait); } }catch (Exception e){ } try { activity = mBase.newActivity(cl, className, intent); } catch (ClassNotFoundException e) { String launchActivityName = Framework.getProperty("android.taobao.atlas.welcome",""); if(TextUtils.isEmpty(launchActivityName)) { Intent launchIntentForPackage = RuntimeVariables.androidApplication.getPackageManager().getLaunchIntentForPackage(RuntimeVariables.androidApplication.getPackageName()); if (launchIntentForPackage != null) { ComponentName componentName = launchIntentForPackage.resolveActivity(RuntimeVariables.androidApplication.getPackageManager()); launchActivityName = componentName.getClassName(); } } if (TextUtils.isEmpty(launchActivityName)) { throw e; } ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); List<RunningTaskInfo> runningTaskInfos = manager.getRunningTasks(1); if (runningTaskInfos != null && runningTaskInfos.size() > 0) { if (runningTaskInfos.get(0).numActivities > 1) { if(Framework.getClassNotFoundCallback()!=null){ if(intent.getComponent() ==null){ intent.setClassName(context,className); } Framework.getClassNotFoundCallback().returnIntent(intent); } } } activity = mBase.newActivity(cl, launchActivityName, intent); } if( cl instanceof DelegateClassLoader ){ if (AtlasHacks.ContextThemeWrapper_mResources != null) { //AtlasHacks.ContextThemeWrapper_mResources.on(activity).set(RuntimeVariables.delegateResources); AtlasHacks.ContextThemeWrapper_mResources.set(activity,RuntimeVariables.delegateResources); } } return activity; } @Override public void callActivityOnCreate(Activity activity, Bundle icicle) { if(!RuntimeVariables.androidApplication.getPackageName().equals(activity.getPackageName())){ mBase.callActivityOnCreate(activity, icicle); return; } ContextImplHook hook = new ContextImplHook(activity.getBaseContext(), activity.getClass().getClassLoader()); if(activity.getBaseContext().getResources()!=RuntimeVariables.delegateResources){ try{ AtlasHacks.ContextImpl_mResources.set(activity.getBaseContext(),RuntimeVariables.delegateResources); }catch(Throwable e){} } if(AtlasHacks.ContextThemeWrapper_mBase!=null && AtlasHacks.ContextThemeWrapper_mBase.getField()!=null){ AtlasHacks.ContextThemeWrapper_mBase.set(activity,hook); } AtlasHacks.ContextWrapper_mBase.set(activity,hook); String Location = null; if (activity.getClass().getClassLoader() instanceof BundleClassLoader) { BundleClassLoader bundleClassLoader = (BundleClassLoader) activity.getClass().getClassLoader(); BundleImpl bundle = bundleClassLoader.getBundle(); bundle.startBundle(); } else if ((Location = AtlasBundleInfoManager.instance().getBundleForComponet(activity.getClass().getName())) != null) { //yunos, get the bundle from bundleInfoList and Frameworks BundleImpl bundle = (BundleImpl)Framework.getBundle(Location); if (bundle != null) bundle.startBundle(); } String welcomeClassName = Framework.getProperty("android.taobao.atlas.welcome","com.taobao.tao.welcome.Welcome"); if(TextUtils.isEmpty(welcomeClassName)){ welcomeClassName = "com.taobao.tao.welcome.Welcome"; } if(activity.getIntent()!=null){ activity.getIntent().setExtrasClassLoader(RuntimeVariables.delegateClassLoader); } // ensureResourcesInjected(activity); if(activity.getClass().getName().equals(welcomeClassName)){ mBase.callActivityOnCreate(activity, null); }else{ try{ if(isAppFirstStartAfterUpdated()){ mBase.callActivityOnCreate(activity, null); }else { mBase.callActivityOnCreate(activity, icicle); } }catch(RuntimeException e){ if((e.toString().contains("android.content.res.Resources") || e.toString().contains("Error inflating class") || e.toString().contains("java.lang.ArrayIndexOutOfBoundsException")) && !e.toString().contains("OutOfMemoryError")){ HandleResourceNotFound(activity, icicle, e); } else { throw e; } } } } private void checkIntent(String bundleName,Intent intent){ try { String url = intent.getDataString(); String urlInfo = ""; String argInfo = ""; if (url != null && (url).getBytes().length > 1024 * 150) { urlInfo = String.format("url size:%s", url.getBytes().length); Log.e("too long url", url); } Bundle bundle = intent.getExtras(); if(bundle!=null) { Set<String> keySet = bundle.keySet(); if(keySet!=null) { for (String key : keySet) { Object value = bundle.get(key); if (value != null && value instanceof String) { int size = ((String) value).getBytes().length; if (size > 1024 * 150) { argInfo = String.format("arg size:%s", size); Log.e("too long arg",(String) value); break; } } } } } }catch(Throwable e){} } private boolean ValidateActivityResource(Activity activity){ String exceptionString = null; String bundleName = AtlasBundleInfoManager.instance().getBundleForComponet(activity.getLocalClassName()); BundleImpl b = (BundleImpl)Framework.getBundle(bundleName); String bundlePath = null; if (b != null){ bundlePath = b.getArchive().getArchiveFile().getAbsolutePath(); } Resources resource = null; if (AtlasHacks.ContextThemeWrapper_mResources != null){ resource = AtlasHacks.ContextThemeWrapper_mResources.get(activity); } else { resource = activity.getResources(); } Resources resource_runtime = RuntimeVariables.delegateResources; if (resource == resource_runtime){ return true; } List<String> paths = getAssetPathFromResources(resource); String pathsOfHis = DelegateResources.getCurrentAssetpathStr(RuntimeVariables.androidApplication.getAssets()); List<String> pathsRuntime = getAssetPathFromResources(resource_runtime); if ((bundlePath != null) && (paths != null) && !paths.contains(bundlePath)){ exceptionString += "(1.1) Activity Resources path not contains:" + b.getArchive().getArchiveFile().getAbsolutePath(); if (!pathsOfHis.contains(bundlePath)){ exceptionString += "(1.2) paths in history not contains:" + b.getArchive().getArchiveFile().getAbsolutePath(); } if (!pathsRuntime.contains(bundlePath)){ exceptionString += "(1.3) paths in runtime not contains:" + b.getArchive().getArchiveFile().getAbsolutePath(); } if (b.getArchive().getArchiveFile().exists() == false){ exceptionString += "(1.4) Bundle archive file not exist:" + b.getArchive().getArchiveFile().getAbsolutePath(); } exceptionString += "(1.5) Activity Resources paths length:" + paths.size(); } if (exceptionString != null){ return false; } return true; } private static List<String> ErrorActivityRecords = new ArrayList<String>(); private void HandleResourceNotFound(Activity activity, Bundle icicle, Exception e) { if(activity!=null && !ErrorActivityRecords.contains(activity.getClass().getName())){ //fix #8224429 ErrorActivityRecords.add(activity.getClass().getName()); try { activity.finish(); }catch(Throwable e2){} return; } String exceptionString = null; try{ Resources resource = null; if (AtlasHacks.ContextThemeWrapper_mResources != null){ resource = AtlasHacks.ContextThemeWrapper_mResources.get(activity); } else { resource = activity.getResources(); } List<String> paths = getAssetPathFromResources(resource); List<String> pathsRuntime = getAssetPathFromResources(RuntimeVariables.delegateResources); String pathsOfHis = DelegateResources.getCurrentAssetpathStr(resource.getAssets()); String bundleName = AtlasBundleInfoManager.instance().getBundleForComponet(activity.getLocalClassName()); BundleImpl b = (BundleImpl)Framework.getBundle(bundleName); exceptionString += "Paths: " + paths; if (b != null){ String bundlePath = b.getArchive().getArchiveFile().getAbsolutePath(); if (!paths.contains(bundlePath)){ exceptionString += "(2.1) Activity Resources path not contains:" + b.getArchive().getArchiveFile().getAbsolutePath(); } if (!pathsRuntime.contains(bundlePath)){ exceptionString += "(2.2) Activity Resources path not contains:" + b.getArchive().getArchiveFile().getAbsolutePath(); } if (!pathsOfHis.contains(bundlePath)){ exceptionString += "(2.3) paths in history not contains:" + b.getArchive().getArchiveFile().getAbsolutePath(); } if (b.getArchive().getArchiveFile().exists() == false){ exceptionString += "(2.4) Bundle archive file not exist:" + b.getArchive().getArchiveFile().getAbsolutePath(); } if (FileUtils.CheckFileValidation(b.getArchive().getArchiveFile().getAbsolutePath())){ exceptionString += "(2.5) Bundle archive file can not opened with stream:" + b.getArchive().getArchiveFile().getAbsolutePath(); } } if (resource == RuntimeVariables.delegateResources){ exceptionString += "(2.6) DelegateResources equals Activity Resources"; } exceptionString += "(2.7) Activity Resources paths length:" + paths.size(); } catch (Exception e1){ String pathsInRunTime = " " + DelegateResources.getCurrentAssetpathStr(RuntimeVariables.androidApplication.getAssets()); exceptionString = "(2.8) paths in history:" + pathsInRunTime + " getAssetPath fail: " + e1; } throw new RuntimeException( exceptionString, e); } private List<String> getAssetPathFromResources(Resources resource){ List<String> paths = null; try{ AssetManager asset = resource.getAssets(); paths = DelegateResources.getCurrentAssetPath(asset); } catch(Exception e){ e.printStackTrace(); } return paths; } private static String assetPathsToString(Set<String> paths){ StringBuffer sb = new StringBuffer(); sb.append("newDelegateResources ["); for (String path:paths) { sb.append(path).append(","); } sb.append("]"); return sb.toString(); } public static void notifyAppUpdated(){ if(RuntimeVariables.androidApplication!=null){ SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(RuntimeVariables.androidApplication); SharedPreferences.Editor editor = preferences.edit(); editor.putBoolean("atlas_appIsUpdated",true); editor.commit(); } } static Boolean sFirstartAfterUpdate = null; public static boolean isAppFirstStartAfterUpdated(){ if(RuntimeVariables.androidApplication!=null){ if(sFirstartAfterUpdate == null) { SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(RuntimeVariables.androidApplication); sFirstartAfterUpdate = preferences.getBoolean("atlas_appIsUpdated", false); if (sFirstartAfterUpdate) { preferences.edit().putBoolean("atlas_appIsUpdated", false); preferences.edit().commit(); } } return sFirstartAfterUpdate; } return false; } @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2) @Override public UiAutomation getUiAutomation() { return mBase.getUiAutomation(); } @Override public void onCreate(Bundle arguments) { mBase.onCreate(arguments); } @Override public void start() { mBase.start(); } @Override public void onStart() { mBase.onStart(); } @Override public boolean onException(Object obj, Throwable e) { if(obj instanceof BroadcastReceiver && (obj.getClass().getClassLoader().getClass().getName().equals(BundleClassLoader.class.getName()))){ try { Field locationField = BundleClassLoader.class.getDeclaredField("location"); locationField.setAccessible(true); String location = (String) locationField.get(obj.getClass().getClassLoader()); if(location!=null){ BundleImpl impl = (BundleImpl) Atlas.getInstance().getBundle(location); if(impl!=null && !impl.checkValidate()){ e.printStackTrace(); return true; } } }catch(Throwable e2){} } return mBase.onException(obj, e); } @Override public void sendStatus(int resultCode, Bundle results) { mBase.sendStatus(resultCode, results); } @Override public void finish(int resultCode, Bundle results) { mBase.finish(resultCode, results); } @Override public void setAutomaticPerformanceSnapshots() { mBase.setAutomaticPerformanceSnapshots(); } @Override public void startPerformanceSnapshot() { mBase.startPerformanceSnapshot(); } @Override public void endPerformanceSnapshot() { mBase.endPerformanceSnapshot(); } @Override public void onDestroy() { mBase.onDestroy(); } @Override public Context getContext() { return mBase.getContext(); } @Override public ComponentName getComponentName() { return mBase.getComponentName(); } @Override public Context getTargetContext() { return mBase.getTargetContext(); } @Override public boolean isProfiling() { return mBase.isProfiling(); } @Override public void startProfiling() { mBase.startProfiling(); } @Override public void stopProfiling() { mBase.stopProfiling(); } @Override public void setInTouchMode(boolean inTouch) { mBase.setInTouchMode(inTouch); } @Override public void waitForIdle(Runnable recipient) { mBase.waitForIdle(recipient); } @Override public void waitForIdleSync() { mBase.waitForIdleSync(); } @Override public void runOnMainSync(Runnable runner) { mBase.runOnMainSync(runner); } @Override public Activity startActivitySync(Intent intent) { return mBase.startActivitySync(intent); } @Override public void addMonitor(ActivityMonitor monitor) { mBase.addMonitor(monitor); } @Override public ActivityMonitor addMonitor(IntentFilter filter, ActivityResult result, boolean block) { return mBase.addMonitor(filter, result, block); } @Override public ActivityMonitor addMonitor(String cls, ActivityResult result, boolean block) { return mBase.addMonitor(cls, result, block); } @Override public boolean checkMonitorHit(ActivityMonitor monitor, int minHits) { return mBase.checkMonitorHit(monitor, minHits); } @Override public Activity waitForMonitor(ActivityMonitor monitor) { return mBase.waitForMonitor(monitor); } @Override public Activity waitForMonitorWithTimeout(ActivityMonitor monitor, long timeOut) { return mBase.waitForMonitorWithTimeout(monitor, timeOut); } @Override public void removeMonitor(ActivityMonitor monitor) { mBase.removeMonitor(monitor); } @Override public boolean invokeMenuActionSync(Activity targetActivity, int id, int flag) { return mBase.invokeMenuActionSync(targetActivity, id, flag); } @Override public boolean invokeContextMenuAction(Activity targetActivity, int id, int flag) { return mBase.invokeContextMenuAction(targetActivity, id, flag); } @Override public void sendStringSync(String text) { mBase.sendStringSync(text); } @Override public void sendKeySync(KeyEvent event) { mBase.sendKeySync(event); } @Override public void sendKeyDownUpSync(int key) { mBase.sendKeyDownUpSync(key); } @Override public void sendCharacterSync(int keyCode) { mBase.sendCharacterSync(keyCode); } @Override public void sendPointerSync(MotionEvent event) { mBase.sendPointerSync(event); } @Override public void sendTrackballEventSync(MotionEvent event) { mBase.sendTrackballEventSync(event); } @Override public Application newApplication(ClassLoader cl, String className, Context context) throws InstantiationException, IllegalAccessException, ClassNotFoundException { if(className!=null && className.equals(RuntimeVariables.androidApplication.getClass().getName())){ ActivityTaskMgr.getInstance().clearActivityStack(); android.os.Process.killProcess(android.os.Process.myPid()); } return mBase.newApplication(cl, className, context); } @Override public void callApplicationOnCreate(Application app) { mBase.callApplicationOnCreate(app); } @Override public void callActivityOnDestroy(Activity activity) { mBase.callActivityOnDestroy(activity); } @Override public void callActivityOnRestoreInstanceState(Activity activity, Bundle savedInstanceState) { Bundle saveInstance = isAppFirstStartAfterUpdated() ? null : savedInstanceState; if(saveInstance!=null){ mBase.callActivityOnRestoreInstanceState(activity, saveInstance); } } @Override public void callActivityOnPostCreate(Activity activity, Bundle savedInstanceState) { Bundle saveInstance = isAppFirstStartAfterUpdated() ? null : savedInstanceState; mBase.callActivityOnPostCreate(activity, saveInstance); } @Override public void callActivityOnNewIntent(Activity activity, Intent intent) { mBase.callActivityOnNewIntent(activity, intent); } @Override public void callActivityOnStart(Activity activity) { mBase.callActivityOnStart(activity); } @Override public void callActivityOnRestart(Activity activity) { mBase.callActivityOnRestart(activity); } @Override public void callActivityOnResume(Activity activity) { mBase.callActivityOnResume(activity); } @Override public void callActivityOnStop(Activity activity) { mBase.callActivityOnStop(activity); } @Override public void callActivityOnSaveInstanceState(Activity activity, Bundle outState) { outState.putString("atlas_real_activity",activity.getClass().getName()); if(!Framework.isUpdated()) { mBase.callActivityOnSaveInstanceState(activity, outState); } } @Override public void callActivityOnPause(Activity activity) { mBase.callActivityOnPause(activity); } @Override public void callActivityOnUserLeaving(Activity activity) { mBase.callActivityOnUserLeaving(activity); } @Override public void startAllocCounting() { mBase.startAllocCounting(); } @Override public void stopAllocCounting() { mBase.stopAllocCounting(); } @Override public Bundle getAllocCounts() { return mBase.getAllocCounts(); } @Override public Bundle getBinderCounts() { return mBase.getBinderCounts(); } }