/*
*
* 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();
}
}