| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 package org.chromium.incrementalinstall; | 5 package org.chromium.incrementalinstall; |
| 6 | 6 |
| 7 import android.app.Application; | 7 import android.app.Application; |
| 8 import android.app.Instrumentation; | 8 import android.app.Instrumentation; |
| 9 import android.content.ComponentName; | 9 import android.content.ComponentName; |
| 10 import android.content.Context; | 10 import android.content.Context; |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 111 } | 111 } |
| 112 | 112 |
| 113 /** | 113 /** |
| 114 * Returns the fully-qualified class name for the given key, stored in a | 114 * Returns the fully-qualified class name for the given key, stored in a |
| 115 * <meta> witin the manifest. | 115 * <meta> witin the manifest. |
| 116 */ | 116 */ |
| 117 private String getClassNameFromMetadata(String key) throws NameNotFoundExcep
tion { | 117 private String getClassNameFromMetadata(String key) throws NameNotFoundExcep
tion { |
| 118 ApplicationInfo appInfo = getPackageManager().getApplicationInfo(getPack
ageName(), | 118 ApplicationInfo appInfo = getPackageManager().getApplicationInfo(getPack
ageName(), |
| 119 PackageManager.GET_META_DATA); | 119 PackageManager.GET_META_DATA); |
| 120 String value = appInfo.metaData.getString(key); | 120 String value = appInfo.metaData.getString(key); |
| 121 if (!value.contains(".")) { | 121 if (value != null && !value.contains(".")) { |
| 122 value = getPackageName() + "." + value; | 122 value = getPackageName() + "." + value; |
| 123 } | 123 } |
| 124 return value; | 124 return value; |
| 125 } | 125 } |
| 126 | 126 |
| 127 /** | 127 /** |
| 128 * Instantiates and initializes mRealInstrumentation (the real Instrumentati
on class). | 128 * Instantiates and initializes mRealInstrumentation (the real Instrumentati
on class). |
| 129 */ | 129 */ |
| 130 private void initInstrumentation(String realInstrumentationName) | 130 private void initInstrumentation(String realInstrumentationName) |
| 131 throws ReflectiveOperationException { | 131 throws ReflectiveOperationException { |
| 132 Instrumentation oldInstrumentation = |
| 133 (Instrumentation) Reflect.getField(mActivityThread, "mInstrument
ation"); |
| 134 if (realInstrumentationName == null) { |
| 135 // This is the case when an incremental app is used as a target for
an instrumentation |
| 136 // test. In this case, ActivityThread can instantiate the proper cla
ss just fine since |
| 137 // it exists within the test apk (as opposed to the incremental apk-
under-test). |
| 138 Log.i(TAG, "Running with external instrumentation"); |
| 139 mRealInstrumentation = oldInstrumentation; |
| 140 return; |
| 141 } |
| 142 // For unit tests, the instrumentation class is replaced in the manifest
by a build step |
| 143 // because ActivityThread tries to instantiate it before we get a chance
to load the |
| 144 // incremental dex files. |
| 132 Log.i(TAG, "Instantiating instrumentation " + realInstrumentationName); | 145 Log.i(TAG, "Instantiating instrumentation " + realInstrumentationName); |
| 133 mRealInstrumentation = (Instrumentation) Reflect.newInstance( | 146 mRealInstrumentation = (Instrumentation) Reflect.newInstance( |
| 134 Class.forName(realInstrumentationName)); | 147 Class.forName(realInstrumentationName)); |
| 135 Instrumentation oldInstrumentation = | |
| 136 (Instrumentation) Reflect.getField(mActivityThread, "mInstrument
ation"); | |
| 137 | 148 |
| 138 // Initialize the fields that are set by Instrumentation.init(). | 149 // Initialize the fields that are set by Instrumentation.init(). |
| 139 String[] initFields = {"mThread", "mMessageQueue", "mInstrContext", "mAp
pContext", | 150 String[] initFields = {"mThread", "mMessageQueue", "mInstrContext", "mAp
pContext", |
| 140 "mWatcher", "mUiAutomationConnection"}; | 151 "mWatcher", "mUiAutomationConnection"}; |
| 141 for (String fieldName : initFields) { | 152 for (String fieldName : initFields) { |
| 142 Reflect.setField(mRealInstrumentation, fieldName, | 153 Reflect.setField(mRealInstrumentation, fieldName, |
| 143 Reflect.getField(oldInstrumentation, fieldName)); | 154 Reflect.getField(oldInstrumentation, fieldName)); |
| 144 } | 155 } |
| 145 // But make sure the correct ComponentName is used. | 156 // But make sure the correct ComponentName is used. |
| 146 ComponentName newName = new ComponentName( | 157 ComponentName newName = new ComponentName( |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 226 for (Map.Entry<String, WeakReference<?>> entry : packageMap.entrySet
()) { | 237 for (Map.Entry<String, WeakReference<?>> entry : packageMap.entrySet
()) { |
| 227 Object loadedApk = entry.getValue().get(); | 238 Object loadedApk = entry.getValue().get(); |
| 228 if (loadedApk != null && Reflect.getField(loadedApk, "mApplicati
on") == this) { | 239 if (loadedApk != null && Reflect.getField(loadedApk, "mApplicati
on") == this) { |
| 229 Reflect.setField(loadedApk, "mApplication", mRealApplication
); | 240 Reflect.setField(loadedApk, "mApplication", mRealApplication
); |
| 230 Reflect.setField(mRealApplication, "mLoadedApk", loadedApk); | 241 Reflect.setField(mRealApplication, "mLoadedApk", loadedApk); |
| 231 } | 242 } |
| 232 } | 243 } |
| 233 } | 244 } |
| 234 } | 245 } |
| 235 } | 246 } |
| OLD | NEW |