Chromium Code Reviews| 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 apposed to the incremental apk- under-test). | |
|
dgn
2016/01/06 20:46:09
s/as apposed/as opposed/ ?
agrieve
2016/01/06 20:50:58
Done.
| |
| 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 |