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 |