1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.layoutlib.bridge.android; 18 19 import com.android.ide.common.rendering.api.AndroidConstants; 20 import com.android.ide.common.rendering.api.AssetRepository; 21 import com.android.ide.common.rendering.api.ILayoutLog; 22 import com.android.ide.common.rendering.api.ILayoutPullParser; 23 import com.android.ide.common.rendering.api.LayoutlibCallback; 24 import com.android.ide.common.rendering.api.RenderResources; 25 import com.android.ide.common.rendering.api.ResourceNamespace; 26 import com.android.ide.common.rendering.api.ResourceNamespace.Resolver; 27 import com.android.ide.common.rendering.api.ResourceReference; 28 import com.android.ide.common.rendering.api.ResourceValue; 29 import com.android.ide.common.rendering.api.ResourceValueImpl; 30 import com.android.ide.common.rendering.api.StyleResourceValue; 31 import com.android.layoutlib.bridge.Bridge; 32 import com.android.layoutlib.bridge.BridgeConstants; 33 import com.android.layoutlib.bridge.SessionInteractiveData; 34 import com.android.layoutlib.bridge.impl.ParserFactory; 35 import com.android.layoutlib.bridge.impl.ResourceHelper; 36 import com.android.layoutlib.bridge.impl.Stack; 37 import com.android.resources.ResourceType; 38 import com.android.tools.layoutlib.annotations.NotNull; 39 40 import org.xmlpull.v1.XmlPullParser; 41 import org.xmlpull.v1.XmlPullParserException; 42 43 import android.animation.AnimationHandler; 44 import android.annotation.NonNull; 45 import android.annotation.Nullable; 46 import android.app.ActivityManager; 47 import android.app.ActivityManager_Accessor; 48 import android.app.AppOpsManager; 49 import android.app.AppOpsManager_Accessor; 50 import android.app.SystemServiceRegistry; 51 import android.app.UiModeManager; 52 import android.app.UiModeManager_Accessor; 53 import android.content.BroadcastReceiver; 54 import android.content.ClipboardManager; 55 import android.content.ComponentCallbacks; 56 import android.content.ComponentName; 57 import android.content.ContentResolver; 58 import android.content.Context; 59 import android.content.ContextWrapper; 60 import android.content.Intent; 61 import android.content.IntentFilter; 62 import android.content.IntentSender; 63 import android.content.ServiceConnection; 64 import android.content.SharedPreferences; 65 import android.content.pm.ApplicationInfo; 66 import android.content.pm.PackageManager; 67 import android.content.res.AssetManager; 68 import android.content.res.BridgeAssetManager; 69 import android.content.res.BridgeTypedArray; 70 import android.content.res.Configuration; 71 import android.content.res.Resources; 72 import android.content.res.Resources.Theme; 73 import android.content.res.Resources_Delegate; 74 import android.database.DatabaseErrorHandler; 75 import android.database.sqlite.SQLiteDatabase; 76 import android.database.sqlite.SQLiteDatabase.CursorFactory; 77 import android.graphics.Bitmap; 78 import android.graphics.drawable.Drawable; 79 import android.hardware.EmptySensorManager; 80 import android.hardware.display.DisplayManager; 81 import android.hardware.input.InputManager; 82 import android.media.AudioManager; 83 import android.net.ConnectivityManager; 84 import android.net.Uri; 85 import android.os.Bundle; 86 import android.os.Handler; 87 import android.os.IBinder; 88 import android.os.IInterface; 89 import android.os.Looper; 90 import android.os.NullVibrator; 91 import android.os.NullVibratorManager; 92 import android.os.Parcel; 93 import android.os.PowerManager; 94 import android.os.RemoteException; 95 import android.os.ResultReceiver; 96 import android.os.ShellCallback; 97 import android.os.UserHandle; 98 import android.util.AttributeSet; 99 import android.util.DisplayMetrics; 100 import android.util.Pair; 101 import android.util.TypedValue; 102 import android.view.BridgeInflater; 103 import android.view.Display; 104 import android.view.DisplayAdjustments; 105 import android.view.View; 106 import android.view.ViewGroup; 107 import android.view.WindowManager; 108 import android.view.WindowManagerImpl; 109 import android.view.accessibility.AccessibilityManager; 110 import android.view.autofill.AutofillManager; 111 import android.view.autofill.IAutoFillManager.Default; 112 import android.view.inputmethod.InputMethodManager; 113 import android.view.textservice.TextServicesManager; 114 115 import java.io.File; 116 import java.io.FileDescriptor; 117 import java.io.FileInputStream; 118 import java.io.FileNotFoundException; 119 import java.io.FileOutputStream; 120 import java.io.IOException; 121 import java.io.InputStream; 122 import java.util.ArrayList; 123 import java.util.HashMap; 124 import java.util.IdentityHashMap; 125 import java.util.List; 126 import java.util.Map; 127 import java.util.concurrent.Executor; 128 129 import static android.os._Original_Build.VERSION_CODES.JELLY_BEAN_MR1; 130 131 /** 132 * Custom implementation of Context/Activity to handle non compiled resources. 133 */ 134 public class BridgeContext extends Context { 135 private static final String PREFIX_THEME_APPCOMPAT = "Theme.AppCompat"; 136 137 private static final Map<String, ResourceValue> FRAMEWORK_PATCHED_VALUES = new HashMap<>(2); 138 private static final Map<String, ResourceValue> FRAMEWORK_REPLACE_VALUES = new HashMap<>(3); 139 private static final int MAX_PARSER_STACK_SIZE = Integer.getInteger( 140 "layoutlib.max.parser.stack.size", 1000); 141 142 static { 143 FRAMEWORK_PATCHED_VALUES.put("animateFirstView", 144 new ResourceValueImpl(ResourceNamespace.ANDROID, ResourceType.BOOL, 145 "animateFirstView", "false")); 146 FRAMEWORK_PATCHED_VALUES.put("animateLayoutChanges", 147 new ResourceValueImpl(ResourceNamespace.ANDROID, ResourceType.BOOL, 148 "animateLayoutChanges", "false")); 149 150 151 FRAMEWORK_REPLACE_VALUES.put("textEditSuggestionItemLayout", 152 new ResourceValueImpl(ResourceNamespace.ANDROID, ResourceType.LAYOUT, 153 "textEditSuggestionItemLayout", "text_edit_suggestion_item")); 154 FRAMEWORK_REPLACE_VALUES.put("textEditSuggestionContainerLayout", 155 new ResourceValueImpl(ResourceNamespace.ANDROID, ResourceType.LAYOUT, 156 "textEditSuggestionContainerLayout", "text_edit_suggestion_container")); 157 FRAMEWORK_REPLACE_VALUES.put("textEditSuggestionHighlightStyle", 158 new ResourceValueImpl(ResourceNamespace.ANDROID, ResourceType.STYLE, 159 "textEditSuggestionHighlightStyle", 160 "TextAppearance.Holo.SuggestionHighlight")); 161 } 162 163 /** The map adds cookies to each view so that IDE can link xml tags to views. */ 164 private final HashMap<View, Object> mViewKeyMap = new HashMap<>(); 165 /** 166 * In some cases, when inflating an xml, some objects are created. Then later, the objects are 167 * converted to views. This map stores the mapping from objects to cookies which can then be 168 * used to populate the mViewKeyMap. 169 */ 170 private final HashMap<Object, Object> mViewKeyHelpMap = new HashMap<>(); 171 private final BridgeAssetManager mAssets; 172 private Resources mSystemResources; 173 private final Object mProjectKey; 174 private final DisplayMetrics mMetrics; 175 private final DynamicRenderResources mRenderResources; 176 private final Configuration mConfig; 177 private final ApplicationInfo mApplicationInfo; 178 private final LayoutlibCallback mLayoutlibCallback; 179 private final WindowManager mWindowManager; 180 private final DisplayManager mDisplayManager; 181 private AutofillManager mAutofillManager; 182 private final ClipboardManager mClipboardManager; 183 private final ActivityManager mActivityManager; 184 private final ConnectivityManager mConnectivityManager; 185 private final AudioManager mAudioManager; 186 private final InputManager mInputManager; 187 private final AppOpsManager mAppOpsManager; 188 private final UiModeManager mUiModeManager; 189 private final HashMap<View, Integer> mScrollYPos = new HashMap<>(); 190 private final HashMap<View, Integer> mScrollXPos = new HashMap<>(); 191 192 private Resources.Theme mTheme; 193 194 private final Map<Object, Map<ResourceReference, ResourceValue>> mDefaultPropMaps = 195 new IdentityHashMap<>(); 196 private final Map<Object, ResourceReference> mDefaultStyleMap = new IdentityHashMap<>(); 197 198 // cache for TypedArray generated from StyleResourceValue object 199 private TypedArrayCache mTypedArrayCache; 200 private BridgeInflater mBridgeInflater; 201 202 private BridgeContentResolver mContentResolver; 203 204 private final Stack<BridgeXmlBlockParser> mParserStack = new Stack<>(); 205 private SharedPreferences mSharedPreferences; 206 private ClassLoader mClassLoader; 207 private IBinder mBinder; 208 private PackageManager mPackageManager; 209 private Boolean mIsThemeAppCompat; 210 private boolean mUseThemedIcon; 211 private Context mApplicationContext; 212 private AccessibilityManager mAccessibilityManager; 213 private final ResourceNamespace mAppCompatNamespace; 214 private final Map<Key<?>, Object> mUserData = new HashMap<>(); 215 216 private final SessionInteractiveData mSessionInteractiveData; 217 private final ThreadLocal<AnimationHandler> mAnimationHandlerThreadLocal = new ThreadLocal<>(); 218 219 /** 220 * Some applications that target both pre API 17 and post API 17, set the newer attrs to 221 * reference the older ones. For example, android:paddingStart will resolve to 222 * android:paddingLeft. This way the apps need to only define paddingLeft at any other place. 223 * This a map from value to attribute name. Warning for missing references shouldn't be logged 224 * if value and attr name pair is the same as an entry in this map. 225 */ 226 private static Map<String, String> RTL_ATTRS = new HashMap<>(10); 227 228 static { 229 RTL_ATTRS.put("?android:attr/paddingLeft", "paddingStart"); 230 RTL_ATTRS.put("?android:attr/paddingRight", "paddingEnd"); 231 RTL_ATTRS.put("?android:attr/layout_marginLeft", "layout_marginStart"); 232 RTL_ATTRS.put("?android:attr/layout_marginRight", "layout_marginEnd"); 233 RTL_ATTRS.put("?android:attr/layout_toLeftOf", "layout_toStartOf"); 234 RTL_ATTRS.put("?android:attr/layout_toRightOf", "layout_toEndOf"); 235 RTL_ATTRS.put("?android:attr/layout_alignParentLeft", "layout_alignParentStart"); 236 RTL_ATTRS.put("?android:attr/layout_alignParentRight", "layout_alignParentEnd"); 237 RTL_ATTRS.put("?android:attr/drawableLeft", "drawableStart"); 238 RTL_ATTRS.put("?android:attr/drawableRight", "drawableEnd"); 239 } 240 241 /** 242 * @param projectKey An Object identifying the project. This is used for the cache mechanism. 243 * @param metrics the {@link DisplayMetrics}. 244 * @param renderResources the configured resources (both framework and projects) for this 245 * render. 246 * @param config the Configuration object for this render. 247 * @param targetSdkVersion the targetSdkVersion of the application. 248 */ BridgeContext(Object projectKey, @NonNull DisplayMetrics metrics, @NonNull RenderResources renderResources, @NonNull AssetRepository assets, @NonNull LayoutlibCallback layoutlibCallback, @NonNull Configuration config, int targetSdkVersion, boolean hasRtlSupport)249 public BridgeContext(Object projectKey, @NonNull DisplayMetrics metrics, 250 @NonNull RenderResources renderResources, 251 @NonNull AssetRepository assets, 252 @NonNull LayoutlibCallback layoutlibCallback, 253 @NonNull Configuration config, 254 int targetSdkVersion, 255 boolean hasRtlSupport) { 256 mProjectKey = projectKey; 257 mMetrics = metrics; 258 mLayoutlibCallback = layoutlibCallback; 259 260 mRenderResources = new DynamicRenderResources(renderResources); 261 mConfig = config; 262 AssetManager systemAssetManager = AssetManager.getSystem(); 263 if (systemAssetManager instanceof BridgeAssetManager) { 264 mAssets = (BridgeAssetManager) systemAssetManager; 265 } else { 266 throw new AssertionError("Creating BridgeContext without initializing Bridge"); 267 } 268 mAssets.setAssetRepository(assets); 269 270 mApplicationInfo = new ApplicationInfo(); 271 mApplicationInfo.targetSdkVersion = targetSdkVersion; 272 if (hasRtlSupport) { 273 mApplicationInfo.flags = mApplicationInfo.flags | ApplicationInfo.FLAG_SUPPORTS_RTL; 274 } 275 276 mWindowManager = new WindowManagerImpl(this, mMetrics); 277 mDisplayManager = new DisplayManager(this); 278 mClipboardManager = new ClipboardManager(this, null); 279 mActivityManager = ActivityManager_Accessor.getActivityManagerInstance(this); 280 mConnectivityManager = new ConnectivityManager(this, null); 281 mAudioManager = new AudioManager(this); 282 mInputManager = new InputManager(this); 283 mAppOpsManager = AppOpsManager_Accessor.getAppOpsManagerInstance(this); 284 mUiModeManager = UiModeManager_Accessor.getUiModeManagerInstance(this); 285 286 if (mLayoutlibCallback.isResourceNamespacingRequired()) { 287 if (mLayoutlibCallback.hasAndroidXAppCompat()) { 288 mAppCompatNamespace = ResourceNamespace.APPCOMPAT; 289 } else { 290 mAppCompatNamespace = ResourceNamespace.APPCOMPAT_LEGACY; 291 } 292 } else { 293 mAppCompatNamespace = ResourceNamespace.RES_AUTO; 294 } 295 296 mSessionInteractiveData = new SessionInteractiveData(); 297 } 298 299 /** 300 * Initializes the {@link Resources} singleton to be linked to this {@link Context}, its 301 * {@link DisplayMetrics}, {@link Configuration}, and {@link LayoutlibCallback}. 302 * 303 * @see #disposeResources() 304 */ initResources(@onNull AssetRepository assetRepository)305 public void initResources(@NonNull AssetRepository assetRepository) { 306 AssetManager assetManager = AssetManager.getSystem(); 307 308 mAssets.setAssetRepository(assetRepository); 309 310 mSystemResources = Resources_Delegate.initSystem( 311 this, 312 assetManager, 313 mMetrics, 314 mConfig, 315 mLayoutlibCallback); 316 mTheme = mSystemResources.newTheme(); 317 } 318 319 /** 320 * Disposes the {@link Resources} singleton and the AssetRepository inside BridgeAssetManager. 321 */ disposeResources()322 public void disposeResources() { 323 Resources_Delegate.disposeSystem(); 324 325 // The BridgeAssetManager pointed to by the mAssets field is a long-lived object, but 326 // the AssetRepository is not. To prevent it from leaking clear a reference to it from 327 // the BridgeAssetManager. 328 mAssets.releaseAssetRepository(); 329 } 330 setBridgeInflater(BridgeInflater inflater)331 public void setBridgeInflater(BridgeInflater inflater) { 332 mBridgeInflater = inflater; 333 } 334 addViewKey(View view, Object viewKey)335 public void addViewKey(View view, Object viewKey) { 336 mViewKeyMap.put(view, viewKey); 337 } 338 getViewKey(View view)339 public Object getViewKey(View view) { 340 return mViewKeyMap.get(view); 341 } 342 addCookie(Object o, Object cookie)343 public void addCookie(Object o, Object cookie) { 344 mViewKeyHelpMap.put(o, cookie); 345 } 346 getCookie(Object o)347 public Object getCookie(Object o) { 348 return mViewKeyHelpMap.get(o); 349 } 350 getProjectKey()351 public Object getProjectKey() { 352 return mProjectKey; 353 } 354 getMetrics()355 public DisplayMetrics getMetrics() { 356 return mMetrics; 357 } 358 getLayoutlibCallback()359 public LayoutlibCallback getLayoutlibCallback() { 360 return mLayoutlibCallback; 361 } 362 getRenderResources()363 public RenderResources getRenderResources() { 364 return mRenderResources; 365 } 366 getDefaultProperties()367 public Map<Object, Map<ResourceReference, ResourceValue>> getDefaultProperties() { 368 return mDefaultPropMaps; 369 } 370 getDefaultNamespacedStyles()371 public Map<Object, ResourceReference> getDefaultNamespacedStyles() { 372 return mDefaultStyleMap; 373 } 374 getConfiguration()375 public Configuration getConfiguration() { 376 return mConfig; 377 } 378 379 /** 380 * Adds a parser to the stack. 381 * @param parser the parser to add. 382 */ pushParser(BridgeXmlBlockParser parser)383 public void pushParser(BridgeXmlBlockParser parser) { 384 if (ParserFactory.LOG_PARSER) { 385 System.out.println("PUSH " + parser.getParser().toString()); 386 } 387 if (mParserStack.size() > MAX_PARSER_STACK_SIZE) { 388 throw new RuntimeException("Potential cycle encountered during inflation"); 389 } 390 mParserStack.push(parser); 391 } 392 393 /** 394 * Removes the parser at the top of the stack 395 */ popParser()396 public void popParser() { 397 BridgeXmlBlockParser parser = mParserStack.pop(); 398 if (ParserFactory.LOG_PARSER) { 399 System.out.println("POPD " + parser.getParser().toString()); 400 } 401 } 402 403 /** 404 * Returns the current parser at the top the of the stack. 405 * @return a parser or null. 406 */ getCurrentParser()407 private BridgeXmlBlockParser getCurrentParser() { 408 return mParserStack.peek(); 409 } 410 411 /** 412 * Returns the previous parser. 413 * @return a parser or null if there isn't any previous parser 414 */ getPreviousParser()415 public BridgeXmlBlockParser getPreviousParser() { 416 if (mParserStack.size() < 2) { 417 return null; 418 } 419 return mParserStack.get(mParserStack.size() - 2); 420 } 421 resolveThemeAttribute(int resId, TypedValue outValue, boolean resolveRefs)422 public boolean resolveThemeAttribute(int resId, TypedValue outValue, boolean resolveRefs) { 423 ResourceReference resourceInfo = Bridge.resolveResourceId(resId); 424 if (resourceInfo == null) { 425 resourceInfo = mLayoutlibCallback.resolveResourceId(resId); 426 } 427 428 if (resourceInfo == null || resourceInfo.getResourceType() != ResourceType.ATTR) { 429 return false; 430 } 431 432 ResourceValue value = mRenderResources.findItemInTheme(resourceInfo); 433 if (resolveRefs) { 434 value = mRenderResources.resolveResValue(value); 435 } 436 437 if (value == null) { 438 // unable to find the attribute. 439 return false; 440 } 441 442 // check if this is a style resource 443 if (value instanceof StyleResourceValue) { 444 // get the id that will represent this style. 445 outValue.resourceId = getDynamicIdByStyle((StyleResourceValue) value); 446 return true; 447 } 448 449 String stringValue = value.getValue(); 450 if (!stringValue.isEmpty()) { 451 if (stringValue.charAt(0) == '#') { 452 outValue.data = ResourceHelper.getColor(stringValue); 453 switch (stringValue.length()) { 454 case 4: 455 outValue.type = TypedValue.TYPE_INT_COLOR_RGB4; 456 break; 457 case 5: 458 outValue.type = TypedValue.TYPE_INT_COLOR_ARGB4; 459 break; 460 case 7: 461 outValue.type = TypedValue.TYPE_INT_COLOR_RGB8; 462 break; 463 default: 464 outValue.type = TypedValue.TYPE_INT_COLOR_ARGB8; 465 } 466 } 467 else if (stringValue.charAt(0) == '@') { 468 outValue.type = TypedValue.TYPE_REFERENCE; 469 } 470 else if ("true".equals(stringValue) || "false".equals(stringValue)) { 471 outValue.type = TypedValue.TYPE_INT_BOOLEAN; 472 outValue.data = "true".equals(stringValue) ? 1 : 0; 473 } 474 else { 475 try { 476 outValue.data = Integer.parseInt(stringValue); 477 outValue.type = TypedValue.TYPE_INT_DEC; 478 } 479 catch (NumberFormatException e) { 480 if (!ResourceHelper.parseFloatAttribute(null, stringValue, outValue, false)) { 481 outValue.type = TypedValue.TYPE_STRING; 482 outValue.string = stringValue; 483 } 484 } 485 } 486 } 487 488 int a = getResourceId(value.asReference(), 0 /*defValue*/); 489 490 if (a != 0) { 491 outValue.resourceId = a; 492 return true; 493 } 494 495 // If the value is not a valid reference, fallback to pass the value as a string. 496 outValue.string = stringValue; 497 return true; 498 } 499 500 resolveId(int id)501 public ResourceReference resolveId(int id) { 502 // first get the String related to this id in the framework 503 ResourceReference resourceInfo = Bridge.resolveResourceId(id); 504 505 if (resourceInfo != null) { 506 return resourceInfo; 507 } 508 509 // didn't find a match in the framework? look in the project. 510 if (mLayoutlibCallback != null) { 511 resourceInfo = mLayoutlibCallback.resolveResourceId(id); 512 513 if (resourceInfo != null) { 514 return resourceInfo; 515 } 516 } 517 518 return null; 519 } 520 inflateView(ResourceReference layout, ViewGroup parent, @SuppressWarnings("SameParameterValue") boolean attachToRoot, boolean skipCallbackParser)521 public Pair<View, Boolean> inflateView(ResourceReference layout, ViewGroup parent, 522 @SuppressWarnings("SameParameterValue") boolean attachToRoot, 523 boolean skipCallbackParser) { 524 boolean isPlatformLayout = layout.getNamespace().equals(ResourceNamespace.ANDROID); 525 526 if (!isPlatformLayout && !skipCallbackParser) { 527 // check if the project callback can provide us with a custom parser. 528 ILayoutPullParser parser = null; 529 ResourceValue layoutValue = mRenderResources.getResolvedResource(layout); 530 if (layoutValue != null) { 531 parser = getLayoutlibCallback().getParser(layoutValue); 532 } 533 534 if (parser != null) { 535 BridgeXmlBlockParser blockParser = 536 new BridgeXmlBlockParser(parser, this, layout.getNamespace()); 537 try { 538 pushParser(blockParser); 539 return Pair.create( 540 mBridgeInflater.inflate(blockParser, parent, attachToRoot), 541 Boolean.TRUE); 542 } finally { 543 popParser(); 544 } 545 } 546 } 547 548 ResourceValue resValue = mRenderResources.getResolvedResource(layout); 549 550 if (resValue != null) { 551 String path = resValue.getValue(); 552 // We need to create a pull parser around the layout XML file, and then 553 // give that to our XmlBlockParser. 554 try { 555 XmlPullParser parser = ParserFactory.create(path, true); 556 if (parser != null) { 557 // Set the layout ref to have correct view cookies. 558 mBridgeInflater.setResourceReference(layout); 559 560 BridgeXmlBlockParser blockParser = 561 new BridgeXmlBlockParser(parser, this, layout.getNamespace()); 562 try { 563 pushParser(blockParser); 564 return Pair.create(mBridgeInflater.inflate(blockParser, parent, 565 attachToRoot), 566 Boolean.FALSE); 567 } finally { 568 popParser(); 569 } 570 } else { 571 Bridge.getLog().error(ILayoutLog.TAG_BROKEN, 572 String.format("File %s is missing!", path), null, null); 573 } 574 } catch (XmlPullParserException e) { 575 Bridge.getLog().error(ILayoutLog.TAG_BROKEN, 576 "Failed to parse file " + path, e, null, null /*data*/); 577 // we'll return null below. 578 } finally { 579 mBridgeInflater.setResourceReference(null); 580 } 581 } else { 582 Bridge.getLog().error(ILayoutLog.TAG_BROKEN, 583 String.format("Layout %s%s does not exist.", isPlatformLayout ? "android:" : "", 584 layout.getName()), null, null); 585 } 586 587 return Pair.create(null, Boolean.FALSE); 588 } 589 590 /** 591 * Returns whether the current selected theme is based on AppCompat 592 */ isAppCompatTheme()593 public boolean isAppCompatTheme() { 594 // If a cached value exists, return it. 595 if (mIsThemeAppCompat != null) { 596 return mIsThemeAppCompat; 597 } 598 // Ideally, we should check if the corresponding activity extends 599 // android.support.v7.app.ActionBarActivity, and not care about the theme name at all. 600 StyleResourceValue defaultTheme = mRenderResources.getDefaultTheme(); 601 // We can't simply check for parent using resources.themeIsParentOf() since the 602 // inheritance structure isn't really what one would expect. The first common parent 603 // between Theme.AppCompat.Light and Theme.AppCompat is Theme.Material (for v21). 604 boolean isThemeAppCompat = false; 605 for (int i = 0; i < 50; i++) { 606 if (defaultTheme == null) { 607 break; 608 } 609 // for loop ensures that we don't run into cyclic theme inheritance. 610 if (defaultTheme.getName().startsWith(PREFIX_THEME_APPCOMPAT)) { 611 isThemeAppCompat = true; 612 break; 613 } 614 defaultTheme = mRenderResources.getParent(defaultTheme); 615 } 616 mIsThemeAppCompat = isThemeAppCompat; 617 return isThemeAppCompat; 618 } 619 getAccessibilityManager()620 public AccessibilityManager getAccessibilityManager() { 621 if (mAccessibilityManager == null) { 622 mAccessibilityManager = new AccessibilityManager(this, null, UserHandle.USER_CURRENT); 623 } 624 return mAccessibilityManager; 625 } 626 627 // ------------ Context methods 628 629 @Override getResources()630 public Resources getResources() { 631 return mSystemResources; 632 } 633 634 @Override getTheme()635 public Theme getTheme() { 636 return mTheme; 637 } 638 639 @Override getClassLoader()640 public ClassLoader getClassLoader() { 641 // The documentation for this method states that it should return a class loader one can 642 // use to retrieve classes in this package. However, when called by LayoutInflater, we do 643 // not want the class loader to return app's custom views. 644 // This is so that the IDE can instantiate the custom views and also generate proper error 645 // messages in case of failure. This also enables the IDE to fallback to MockView in case 646 // there's an exception thrown when trying to inflate the custom view. 647 // To work around this issue, LayoutInflater is modified via LayoutLib Create tool to 648 // replace invocations of this method to a new method: getFrameworkClassLoader(). Also, 649 // the method is injected into Context. The implementation of getFrameworkClassLoader() is: 650 // "return getClass().getClassLoader();". This means that when LayoutInflater asks for 651 // the context ClassLoader, it gets only LayoutLib's ClassLoader which doesn't have 652 // access to the apps's custom views. 653 // This method can now return the right ClassLoader, which CustomViews can use to do the 654 // right thing. 655 if (mClassLoader == null) { 656 mClassLoader = new ClassLoader(getClass().getClassLoader()) { 657 @Override 658 protected Class<?> findClass(String name) throws ClassNotFoundException { 659 for (String prefix : BridgeInflater.getClassPrefixList()) { 660 if (name.startsWith(prefix)) { 661 // These are framework classes and should not be loaded from the app. 662 throw new ClassNotFoundException(name + " not found"); 663 } 664 } 665 return BridgeContext.this.mLayoutlibCallback.findClass(name); 666 } 667 }; 668 } 669 return mClassLoader; 670 } 671 672 @Override getSystemService(String service)673 public Object getSystemService(String service) { 674 switch (service) { 675 case LAYOUT_INFLATER_SERVICE: 676 return mBridgeInflater; 677 678 case TEXT_SERVICES_MANAGER_SERVICE: 679 // we need to return a valid service to avoid NPE 680 return TextServicesManager.getInstance(); 681 682 case WINDOW_SERVICE: 683 return mWindowManager; 684 685 case POWER_SERVICE: 686 return new PowerManager(this, new BridgePowerManager(), new BridgeThermalService(), 687 new Handler()); 688 689 case DISPLAY_SERVICE: 690 return mDisplayManager; 691 692 case ACCESSIBILITY_SERVICE: 693 return AccessibilityManager.getInstance(this); 694 695 case INPUT_METHOD_SERVICE: // needed by SearchView and Compose 696 return InputMethodManager.forContext(this); 697 698 case AUTOFILL_MANAGER_SERVICE: 699 if (mAutofillManager == null) { 700 mAutofillManager = new AutofillManager(this, new Default()); 701 } 702 return mAutofillManager; 703 704 case CLIPBOARD_SERVICE: 705 return mClipboardManager; 706 707 case ACTIVITY_SERVICE: 708 return mActivityManager; 709 710 case CONNECTIVITY_SERVICE: 711 return mConnectivityManager; 712 713 case AUDIO_SERVICE: 714 return mAudioManager; 715 716 case INPUT_SERVICE: 717 return mInputManager; 718 719 case VIBRATOR_SERVICE: 720 return NullVibrator.getInstance(); 721 722 case VIBRATOR_MANAGER_SERVICE: 723 return NullVibratorManager.getInstance(); 724 725 case SENSOR_SERVICE: 726 return EmptySensorManager.getInstance(); 727 728 case APP_OPS_SERVICE: 729 return mAppOpsManager; 730 731 case UI_MODE_SERVICE: 732 return mUiModeManager; 733 734 case TEXT_CLASSIFICATION_SERVICE: 735 case CONTENT_CAPTURE_MANAGER_SERVICE: 736 case ALARM_SERVICE: 737 return null; 738 default: 739 // Only throw exception if the required service is unsupported but recognized as 740 // an existing system service. 741 assert SystemServiceRegistry.getSystemServiceClassName(service) == null : 742 "Unsupported Service: " + service; 743 Bridge.getLog().warning(ILayoutLog.TAG_UNSUPPORTED, "Service " + service + 744 " was not found or is unsupported", null, null); 745 } 746 747 return null; 748 } 749 750 @Override getSystemServiceName(Class<?> serviceClass)751 public String getSystemServiceName(Class<?> serviceClass) { 752 return SystemServiceRegistry.getSystemServiceName(serviceClass); 753 } 754 755 /** 756 * Same as Context#obtainStyledAttributes. We do not override the base method to give the 757 * original Context the chance to override the theme when needed. 758 */ 759 @NonNull internalObtainStyledAttributes(int resId, int[] attrs)760 public final BridgeTypedArray internalObtainStyledAttributes(int resId, int[] attrs) 761 throws Resources.NotFoundException { 762 StyleResourceValue style = null; 763 // get the StyleResourceValue based on the resId; 764 if (resId != 0) { 765 style = getStyleByDynamicId(resId); 766 767 if (style == null) { 768 // In some cases, style may not be a dynamic id, so we do a full search. 769 ResourceReference ref = resolveId(resId); 770 if (ref != null) { 771 style = mRenderResources.getStyle(ref); 772 } 773 } 774 775 if (style == null) { 776 Bridge.getLog().warning(ILayoutLog.TAG_INFO, 777 "Failed to find style with " + resId, null, null); 778 } 779 } 780 781 if (mTypedArrayCache == null) { 782 mTypedArrayCache = new TypedArrayCache(); 783 } 784 785 List<StyleResourceValue> currentThemes = mRenderResources.getAllThemes(); 786 787 Pair<BridgeTypedArray, Map<ResourceReference, ResourceValue>> typeArrayAndPropertiesPair = 788 mTypedArrayCache.get(attrs, currentThemes, resId); 789 790 if (typeArrayAndPropertiesPair == null) { 791 typeArrayAndPropertiesPair = createStyleBasedTypedArray(style, attrs); 792 mTypedArrayCache.put(attrs, currentThemes, resId, typeArrayAndPropertiesPair); 793 } 794 // Add value to defaultPropsMap if needed 795 if (typeArrayAndPropertiesPair.second != null) { 796 BridgeXmlBlockParser parser = getCurrentParser(); 797 Object key = parser != null ? parser.getViewCookie() : null; 798 if (key != null) { 799 Map<ResourceReference, ResourceValue> defaultPropMap = mDefaultPropMaps.get(key); 800 if (defaultPropMap == null) { 801 defaultPropMap = typeArrayAndPropertiesPair.second; 802 mDefaultPropMaps.put(key, defaultPropMap); 803 } else { 804 defaultPropMap.putAll(typeArrayAndPropertiesPair.second); 805 } 806 } 807 } 808 return typeArrayAndPropertiesPair.first; 809 } 810 811 /** 812 * Same as Context#obtainStyledAttributes. We do not override the base method to give the 813 * original Context the chance to override the theme when needed. 814 */ 815 @Nullable internalObtainStyledAttributes(@ullable AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes)816 public BridgeTypedArray internalObtainStyledAttributes(@Nullable AttributeSet set, int[] attrs, 817 int defStyleAttr, int defStyleRes) { 818 819 Map<ResourceReference, ResourceValue> defaultPropMap = null; 820 Object key = null; 821 822 ResourceNamespace currentFileNamespace; 823 ResourceNamespace.Resolver resolver; 824 825 // Hint: for XmlPullParser, attach source //DEVICE_SRC/dalvik/libcore/xml/src/java 826 if (set instanceof BridgeXmlBlockParser) { 827 BridgeXmlBlockParser parser; 828 parser = (BridgeXmlBlockParser)set; 829 830 key = parser.getViewCookie(); 831 if (key != null) { 832 defaultPropMap = mDefaultPropMaps.computeIfAbsent(key, k -> new HashMap<>()); 833 } 834 835 currentFileNamespace = parser.getFileResourceNamespace(); 836 resolver = new XmlPullParserResolver(parser, mLayoutlibCallback.getImplicitNamespaces()); 837 } else if (set instanceof BridgeLayoutParamsMapAttributes) { 838 // This is for temp layout params generated dynamically in MockView. The set contains 839 // hardcoded values and we don't need to worry about resolving them. 840 currentFileNamespace = ResourceNamespace.RES_AUTO; 841 resolver = Resolver.EMPTY_RESOLVER; 842 } else if (set != null) { 843 // really this should not be happening since its instantiated in Bridge 844 Bridge.getLog().error(ILayoutLog.TAG_BROKEN, 845 "Parser is not a BridgeXmlBlockParser!", null, null); 846 return null; 847 } else { 848 // `set` is null, so there will be no values to resolve. 849 currentFileNamespace = ResourceNamespace.RES_AUTO; 850 resolver = Resolver.EMPTY_RESOLVER; 851 } 852 853 List<AttributeHolder> attributeList = searchAttrs(attrs); 854 855 BridgeTypedArray ta = 856 Resources_Delegate.newTypeArray(mSystemResources, attrs.length); 857 858 // Look for a custom style. 859 StyleResourceValue customStyleValues = null; 860 if (set != null) { 861 String customStyle = set.getAttributeValue(null, "style"); 862 if (customStyle != null) { 863 ResourceValue resolved = mRenderResources.resolveResValue( 864 new UnresolvedResourceValue(customStyle, currentFileNamespace, resolver)); 865 866 if (resolved instanceof StyleResourceValue) { 867 customStyleValues = (StyleResourceValue) resolved; 868 } 869 } 870 } 871 872 // resolve the defStyleAttr value into a StyleResourceValue 873 StyleResourceValue defStyleValues = null; 874 875 if (defStyleAttr != 0) { 876 // get the name from the int. 877 ResourceReference defStyleAttribute = searchAttr(defStyleAttr); 878 879 if (defStyleAttribute == null) { 880 // This should be rare. Happens trying to map R.style.foo to @style/foo fails. 881 // This will happen if the user explicitly used a non existing int value for 882 // defStyleAttr or there's something wrong with the project structure/build. 883 Bridge.getLog().error(ILayoutLog.TAG_RESOURCES_RESOLVE, 884 "Failed to find the style corresponding to the id " + defStyleAttr, null, 885 null); 886 } else { 887 // look for the style in the current theme, and its parent: 888 ResourceValue item = mRenderResources.findItemInTheme(defStyleAttribute); 889 890 if (item != null) { 891 if (key != null) { 892 mDefaultStyleMap.put(key, defStyleAttribute); 893 } 894 // item is a reference to a style entry. Search for it. 895 item = mRenderResources.resolveResValue(item); 896 if (item instanceof StyleResourceValue) { 897 defStyleValues = (StyleResourceValue) item; 898 } 899 } 900 } 901 } 902 903 if (defStyleValues == null && defStyleRes != 0) { 904 StyleResourceValue item = getStyleByDynamicId(defStyleRes); 905 if (item != null) { 906 defStyleValues = item; 907 } else { 908 ResourceReference value = Bridge.resolveResourceId(defStyleRes); 909 if (value == null) { 910 value = mLayoutlibCallback.resolveResourceId(defStyleRes); 911 } 912 913 if (value != null) { 914 if ((value.getResourceType() == ResourceType.STYLE)) { 915 // look for the style in all resources: 916 item = mRenderResources.getStyle(value); 917 if (item != null) { 918 if (key != null) { 919 mDefaultStyleMap.put(key, item.asReference()); 920 } 921 922 defStyleValues = item; 923 } else { 924 Bridge.getLog().error(null, 925 String.format( 926 "Style with id 0x%x (resolved to '%s') does not exist.", 927 defStyleRes, value.getName()), 928 null, null); 929 } 930 } else { 931 Bridge.getLog().error(null, 932 String.format( 933 "Resource id 0x%x is not of type STYLE (instead %s)", 934 defStyleRes, value.getResourceType().name()), 935 null, null); 936 } 937 } else { 938 Bridge.getLog().error(null, 939 String.format( 940 "Failed to find style with id 0x%x in current theme", 941 defStyleRes), 942 null, null); 943 } 944 } 945 } 946 947 if (attributeList != null) { 948 for (int index = 0 ; index < attributeList.size() ; index++) { 949 AttributeHolder attributeHolder = attributeList.get(index); 950 951 if (attributeHolder == null) { 952 continue; 953 } 954 955 String attrName = attributeHolder.getName(); 956 String value = null; 957 if (set != null) { 958 value = set.getAttributeValue( 959 attributeHolder.getNamespace().getXmlNamespaceUri(), attrName); 960 961 // if this is an app attribute, and the first get fails, try with the 962 // new res-auto namespace as well 963 if (attributeHolder.getNamespace() != ResourceNamespace.ANDROID && value == null) { 964 value = set.getAttributeValue(BridgeConstants.NS_APP_RES_AUTO, attrName); 965 } 966 } 967 968 // Calculate the default value from the Theme in two cases: 969 // - If defaultPropMap is not null, get the default value to add it to the list 970 // of default values of properties. 971 // - If value is null, it means that the attribute is not directly set as an 972 // attribute in the XML so try to get the default value. 973 ResourceValue defaultValue = null; 974 if (defaultPropMap != null || value == null) { 975 // look for the value in the custom style first (and its parent if needed) 976 ResourceReference attrRef = attributeHolder.asReference(); 977 if (customStyleValues != null) { 978 defaultValue = 979 mRenderResources.findItemInStyle(customStyleValues, attrRef); 980 } 981 982 // then look for the value in the default Style (and its parent if needed) 983 if (defaultValue == null && defStyleValues != null) { 984 defaultValue = 985 mRenderResources.findItemInStyle(defStyleValues, attrRef); 986 } 987 988 // if the item is not present in the defStyle, we look in the main theme (and 989 // its parent themes) 990 if (defaultValue == null) { 991 defaultValue = 992 mRenderResources.findItemInTheme(attrRef); 993 } 994 995 // if we found a value, we make sure this doesn't reference another value. 996 // So we resolve it. 997 if (defaultValue != null) { 998 if (defaultPropMap != null) { 999 defaultPropMap.put(attrRef, defaultValue); 1000 } 1001 1002 defaultValue = mRenderResources.resolveResValue(defaultValue); 1003 } 1004 } 1005 // Done calculating the defaultValue. 1006 1007 // If there's no direct value for this attribute in the XML, we look for default 1008 // values in the widget defStyle, and then in the theme. 1009 if (value == null) { 1010 if (attributeHolder.getNamespace() == ResourceNamespace.ANDROID) { 1011 // For some framework values, layoutlib patches the actual value in the 1012 // theme when it helps to improve the final preview. In most cases 1013 // we just disable animations. 1014 ResourceValue patchedValue = FRAMEWORK_PATCHED_VALUES.get(attrName); 1015 if (patchedValue != null) { 1016 defaultValue = patchedValue; 1017 } 1018 } 1019 1020 // If we found a value, we make sure this doesn't reference another value. 1021 // So we resolve it. 1022 if (defaultValue != null) { 1023 // If the value is a reference to another theme attribute that doesn't 1024 // exist, we should log a warning and omit it. 1025 String val = defaultValue.getValue(); 1026 if (val != null && val.startsWith(AndroidConstants.PREFIX_THEME_REF)) { 1027 // Because we always use the latest framework code, some resources might 1028 // fail to resolve when using old themes (they haven't been backported). 1029 // Since this is an artifact caused by us using always the latest 1030 // code, we check for some of those values and replace them here. 1031 ResourceReference reference = defaultValue.getReference(); 1032 defaultValue = FRAMEWORK_REPLACE_VALUES.get(attrName); 1033 1034 // Only log a warning if the referenced value isn't one of the RTL 1035 // attributes, or the app targets old API. 1036 if (defaultValue == null && 1037 (getApplicationInfo().targetSdkVersion < JELLY_BEAN_MR1 || 1038 !attrName.equals(RTL_ATTRS.get(val)))) { 1039 if (reference != null) { 1040 val = reference.getResourceUrl().toString(); 1041 } 1042 Bridge.getLog().warning(ILayoutLog.TAG_RESOURCES_RESOLVE_THEME_ATTR, 1043 String.format("Failed to find '%s' in current theme.", val), 1044 null, val); 1045 } 1046 } 1047 } 1048 1049 ta.bridgeSetValue( 1050 index, 1051 attrName, attributeHolder.getNamespace(), 1052 attributeHolder.getResourceId(), 1053 defaultValue); 1054 } else { 1055 // There is a value in the XML, but we need to resolve it in case it's 1056 // referencing another resource or a theme value. 1057 ta.bridgeSetValue( 1058 index, 1059 attrName, attributeHolder.getNamespace(), 1060 attributeHolder.getResourceId(), 1061 mRenderResources.resolveResValue( 1062 new UnresolvedResourceValue( 1063 value, currentFileNamespace, resolver))); 1064 } 1065 } 1066 } 1067 1068 ta.sealArray(); 1069 1070 return ta; 1071 } 1072 1073 @Override getMainLooper()1074 public Looper getMainLooper() { 1075 return Looper.myLooper(); 1076 } 1077 1078 1079 @Override getPackageName()1080 public String getPackageName() { 1081 if (mApplicationInfo.packageName == null) { 1082 mApplicationInfo.packageName = mLayoutlibCallback.getApplicationId(); 1083 } 1084 return mApplicationInfo.packageName; 1085 } 1086 1087 @Override getPackageManager()1088 public PackageManager getPackageManager() { 1089 if (mPackageManager == null) { 1090 mPackageManager = new BridgePackageManager(this); 1091 } 1092 return mPackageManager; 1093 } 1094 1095 @Override registerComponentCallbacks(ComponentCallbacks callback)1096 public void registerComponentCallbacks(ComponentCallbacks callback) {} 1097 1098 @Override unregisterComponentCallbacks(ComponentCallbacks callback)1099 public void unregisterComponentCallbacks(ComponentCallbacks callback) {} 1100 1101 // ------------- private new methods 1102 1103 /** 1104 * Creates a {@link BridgeTypedArray} by filling the values defined by the int[] with the 1105 * values found in the given style. If no style is specified, the default theme, along with the 1106 * styles applied to it are used. 1107 * 1108 * @see #obtainStyledAttributes(int, int[]) 1109 */ createStyleBasedTypedArray( @ullable StyleResourceValue style, int[] attrs)1110 private Pair<BridgeTypedArray, Map<ResourceReference, ResourceValue>> createStyleBasedTypedArray( 1111 @Nullable StyleResourceValue style, int[] attrs) throws Resources.NotFoundException { 1112 List<AttributeHolder> attributes = searchAttrs(attrs); 1113 1114 BridgeTypedArray ta = 1115 Resources_Delegate.newTypeArray(mSystemResources, attrs.length); 1116 1117 Map<ResourceReference, ResourceValue> defaultPropMap = new HashMap<>(); 1118 // for each attribute, get its name so that we can search it in the style 1119 for (int i = 0; i < attrs.length; i++) { 1120 AttributeHolder attrHolder = attributes.get(i); 1121 1122 if (attrHolder != null) { 1123 // look for the value in the given style 1124 ResourceValue resValue; 1125 if (style != null) { 1126 resValue = mRenderResources.findItemInStyle(style, attrHolder.asReference()); 1127 } else { 1128 resValue = mRenderResources.findItemInTheme(attrHolder.asReference()); 1129 } 1130 1131 if (resValue != null) { 1132 defaultPropMap.put(attrHolder.asReference(), resValue); 1133 // resolve it to make sure there are no references left. 1134 resValue = mRenderResources.resolveResValue(resValue); 1135 ta.bridgeSetValue( 1136 i, attrHolder.getName(), attrHolder.getNamespace(), 1137 attrHolder.getResourceId(), 1138 resValue); 1139 } 1140 } 1141 } 1142 1143 ta.sealArray(); 1144 1145 return Pair.create(ta, defaultPropMap); 1146 } 1147 1148 /** 1149 * The input int[] attributeIds is a list of attributes. The returns a list of information about 1150 * each attributes. The information is (name, isFramework) 1151 * <p/> 1152 * 1153 * @param attributeIds An attribute array reference given to obtainStyledAttributes. 1154 * @return List of attribute information. 1155 */ searchAttrs(int[] attributeIds)1156 private List<AttributeHolder> searchAttrs(int[] attributeIds) { 1157 List<AttributeHolder> results = new ArrayList<>(attributeIds.length); 1158 1159 // for each attribute, get its name so that we can search it in the style 1160 for (int id : attributeIds) { 1161 ResourceReference refForId = Bridge.resolveResourceId(id); 1162 if (refForId == null) { 1163 refForId = mLayoutlibCallback.resolveResourceId(id); 1164 } 1165 1166 if (refForId != null) { 1167 results.add(new AttributeHolder(id, refForId)); 1168 } else { 1169 results.add(null); 1170 } 1171 } 1172 1173 return results; 1174 } 1175 1176 /** 1177 * Searches for the attribute referenced by its internal id. 1178 */ searchAttr(int attrId)1179 private ResourceReference searchAttr(int attrId) { 1180 ResourceReference attr = Bridge.resolveResourceId(attrId); 1181 if (attr == null) { 1182 attr = mLayoutlibCallback.resolveResourceId(attrId); 1183 } 1184 1185 return attr; 1186 } 1187 1188 /** 1189 * Maps a given style to a numeric id. 1190 * 1191 * <p>For now Bridge handles numeric ids (both fixed and dynamic) for framework and the callback 1192 * for non-framework. TODO(b/156609434): teach the IDE about fixed framework ids and handle this 1193 * all in the callback. 1194 */ getDynamicIdByStyle(StyleResourceValue resValue)1195 public int getDynamicIdByStyle(StyleResourceValue resValue) { 1196 if (resValue.isFramework()) { 1197 return Bridge.getResourceId(resValue.getResourceType(), resValue.getName()); 1198 } else { 1199 return mLayoutlibCallback.getOrGenerateResourceId(resValue.asReference()); 1200 } 1201 } 1202 1203 /** 1204 * Maps a numeric id back to {@link StyleResourceValue}. 1205 * 1206 * <p>For now framework numeric ids are handled by Bridge, so try there first and fall back to 1207 * the callback, which manages ids for non-framework resources. TODO(b/156609434): manage all 1208 * ids in the IDE. 1209 * 1210 * <p>Once we the resource for the given id, we ask the IDE to get the 1211 * {@link StyleResourceValue} for it. 1212 */ 1213 @Nullable getStyleByDynamicId(int id)1214 private StyleResourceValue getStyleByDynamicId(int id) { 1215 ResourceReference reference = Bridge.resolveResourceId(id); 1216 if (reference == null) { 1217 reference = mLayoutlibCallback.resolveResourceId(id); 1218 } 1219 1220 if (reference == null) { 1221 return null; 1222 } 1223 1224 return mRenderResources.getStyle(reference); 1225 } 1226 getResourceId(@onNull ResourceReference resource, int defValue)1227 public int getResourceId(@NonNull ResourceReference resource, int defValue) { 1228 if (getRenderResources().getUnresolvedResource(resource) != null) { 1229 if (resource.getNamespace().equals(ResourceNamespace.ANDROID)) { 1230 return Bridge.getResourceId(resource.getResourceType(), resource.getName()); 1231 } else if (mLayoutlibCallback != null) { 1232 return mLayoutlibCallback.getOrGenerateResourceId(resource); 1233 } 1234 } 1235 1236 return defValue; 1237 } 1238 getBaseContext(Context context)1239 public static Context getBaseContext(Context context) { 1240 while (context instanceof ContextWrapper) { 1241 context = ((ContextWrapper) context).getBaseContext(); 1242 } 1243 return context; 1244 } 1245 1246 /** 1247 * Returns the Framework attr resource reference with the given name. 1248 */ 1249 @NonNull createFrameworkAttrReference(@onNull String name)1250 public static ResourceReference createFrameworkAttrReference(@NonNull String name) { 1251 return createFrameworkResourceReference(ResourceType.ATTR, name); 1252 } 1253 1254 /** 1255 * Returns the Framework resource reference with the given type and name. 1256 */ 1257 @NonNull createFrameworkResourceReference(@onNull ResourceType type, @NonNull String name)1258 public static ResourceReference createFrameworkResourceReference(@NonNull ResourceType type, 1259 @NonNull String name) { 1260 return new ResourceReference(ResourceNamespace.ANDROID, type, name); 1261 } 1262 1263 /** 1264 * Returns the AppCompat attr resource reference with the given name. 1265 */ 1266 @NonNull createAppCompatAttrReference(@onNull String name)1267 public ResourceReference createAppCompatAttrReference(@NonNull String name) { 1268 return createAppCompatResourceReference(ResourceType.ATTR, name); 1269 } 1270 1271 /** 1272 * Returns the AppCompat resource reference with the given type and name. 1273 */ 1274 @NonNull createAppCompatResourceReference(@onNull ResourceType type, @NonNull String name)1275 public ResourceReference createAppCompatResourceReference(@NonNull ResourceType type, 1276 @NonNull String name) { 1277 return new ResourceReference(mAppCompatNamespace, type, name); 1278 } 1279 getBinder()1280 public IBinder getBinder() { 1281 if (mBinder == null) { 1282 // create a no-op binder. We only need it be not null. 1283 mBinder = new IBinder() { 1284 @Override 1285 public String getInterfaceDescriptor() throws RemoteException { 1286 return null; 1287 } 1288 1289 @Override 1290 public boolean pingBinder() { 1291 return false; 1292 } 1293 1294 @Override 1295 public boolean isBinderAlive() { 1296 return false; 1297 } 1298 1299 @Override 1300 public IInterface queryLocalInterface(String descriptor) { 1301 return null; 1302 } 1303 1304 @Override 1305 public void dump(FileDescriptor fd, String[] args) throws RemoteException { 1306 1307 } 1308 1309 @Override 1310 public void dumpAsync(FileDescriptor fd, String[] args) throws RemoteException { 1311 1312 } 1313 1314 @Override 1315 public boolean transact(int code, Parcel data, Parcel reply, int flags) 1316 throws RemoteException { 1317 return false; 1318 } 1319 1320 @Override 1321 public void linkToDeath(DeathRecipient recipient, int flags) 1322 throws RemoteException { 1323 1324 } 1325 1326 @Override 1327 public boolean unlinkToDeath(DeathRecipient recipient, int flags) { 1328 return false; 1329 } 1330 1331 @Override 1332 public void shellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, 1333 String[] args, ShellCallback shellCallback, ResultReceiver resultReceiver) { 1334 } 1335 }; 1336 } 1337 return mBinder; 1338 } 1339 1340 //------------ NOT OVERRIDEN -------------------- 1341 1342 @Override bindService(Intent arg0, ServiceConnection arg1, int arg2)1343 public boolean bindService(Intent arg0, ServiceConnection arg1, int arg2) { 1344 // pass 1345 return false; 1346 } 1347 1348 @Override bindService(Intent arg0, int arg1, Executor arg2, ServiceConnection arg3)1349 public boolean bindService(Intent arg0, int arg1, Executor arg2, ServiceConnection arg3) { 1350 return false; 1351 } 1352 1353 @Override bindIsolatedService(Intent arg0, int arg1, String arg2, Executor arg3, ServiceConnection arg4)1354 public boolean bindIsolatedService(Intent arg0, 1355 int arg1, String arg2, Executor arg3, ServiceConnection arg4) { 1356 return false; 1357 } 1358 1359 @Override checkCallingOrSelfPermission(String arg0)1360 public int checkCallingOrSelfPermission(String arg0) { 1361 // pass 1362 return 0; 1363 } 1364 1365 @Override checkCallingOrSelfUriPermission(Uri arg0, int arg1)1366 public int checkCallingOrSelfUriPermission(Uri arg0, int arg1) { 1367 // pass 1368 return 0; 1369 } 1370 1371 @Override checkCallingPermission(String arg0)1372 public int checkCallingPermission(String arg0) { 1373 // pass 1374 return 0; 1375 } 1376 1377 @Override checkCallingUriPermission(Uri arg0, int arg1)1378 public int checkCallingUriPermission(Uri arg0, int arg1) { 1379 // pass 1380 return 0; 1381 } 1382 1383 @Override checkPermission(String arg0, int arg1, int arg2)1384 public int checkPermission(String arg0, int arg1, int arg2) { 1385 // pass 1386 return 0; 1387 } 1388 1389 @Override checkSelfPermission(String arg0)1390 public int checkSelfPermission(String arg0) { 1391 // pass 1392 return 0; 1393 } 1394 1395 @Override checkPermission(String arg0, int arg1, int arg2, IBinder arg3)1396 public int checkPermission(String arg0, int arg1, int arg2, IBinder arg3) { 1397 // pass 1398 return 0; 1399 } 1400 1401 @Override checkUriPermission(Uri arg0, int arg1, int arg2, int arg3)1402 public int checkUriPermission(Uri arg0, int arg1, int arg2, int arg3) { 1403 // pass 1404 return 0; 1405 } 1406 1407 @Override checkUriPermission(Uri arg0, int arg1, int arg2, int arg3, IBinder arg4)1408 public int checkUriPermission(Uri arg0, int arg1, int arg2, int arg3, IBinder arg4) { 1409 // pass 1410 return 0; 1411 } 1412 1413 @Override checkUriPermission(Uri arg0, String arg1, String arg2, int arg3, int arg4, int arg5)1414 public int checkUriPermission(Uri arg0, String arg1, String arg2, int arg3, 1415 int arg4, int arg5) { 1416 // pass 1417 return 0; 1418 } 1419 1420 @Override clearWallpaper()1421 public void clearWallpaper() { 1422 // pass 1423 1424 } 1425 1426 @Override createPackageContext(String arg0, int arg1)1427 public Context createPackageContext(String arg0, int arg1) { 1428 // pass 1429 return null; 1430 } 1431 1432 @Override createPackageContextAsUser(String arg0, int arg1, UserHandle user)1433 public Context createPackageContextAsUser(String arg0, int arg1, UserHandle user) { 1434 // pass 1435 return null; 1436 } 1437 1438 @Override createConfigurationContext(Configuration overrideConfiguration)1439 public Context createConfigurationContext(Configuration overrideConfiguration) { 1440 // pass 1441 return null; 1442 } 1443 1444 @Override createDisplayContext(Display display)1445 public Context createDisplayContext(Display display) { 1446 // pass 1447 return null; 1448 } 1449 1450 @Override createContextForSplit(String splitName)1451 public Context createContextForSplit(String splitName) { 1452 // pass 1453 return null; 1454 } 1455 1456 @Override databaseList()1457 public String[] databaseList() { 1458 // pass 1459 return null; 1460 } 1461 1462 @Override createApplicationContext(ApplicationInfo application, int flags)1463 public Context createApplicationContext(ApplicationInfo application, int flags) 1464 throws PackageManager.NameNotFoundException { 1465 return null; 1466 } 1467 1468 @Override moveDatabaseFrom(Context sourceContext, String name)1469 public boolean moveDatabaseFrom(Context sourceContext, String name) { 1470 // pass 1471 return false; 1472 } 1473 1474 @Override deleteDatabase(String arg0)1475 public boolean deleteDatabase(String arg0) { 1476 // pass 1477 return false; 1478 } 1479 1480 @Override deleteFile(String arg0)1481 public boolean deleteFile(String arg0) { 1482 // pass 1483 return false; 1484 } 1485 1486 @Override enforceCallingOrSelfPermission(String arg0, String arg1)1487 public void enforceCallingOrSelfPermission(String arg0, String arg1) { 1488 // pass 1489 1490 } 1491 1492 @Override enforceCallingOrSelfUriPermission(Uri arg0, int arg1, String arg2)1493 public void enforceCallingOrSelfUriPermission(Uri arg0, int arg1, 1494 String arg2) { 1495 // pass 1496 1497 } 1498 1499 @Override enforceCallingPermission(String arg0, String arg1)1500 public void enforceCallingPermission(String arg0, String arg1) { 1501 // pass 1502 1503 } 1504 1505 @Override enforceCallingUriPermission(Uri arg0, int arg1, String arg2)1506 public void enforceCallingUriPermission(Uri arg0, int arg1, String arg2) { 1507 // pass 1508 1509 } 1510 1511 @Override enforcePermission(String arg0, int arg1, int arg2, String arg3)1512 public void enforcePermission(String arg0, int arg1, int arg2, String arg3) { 1513 // pass 1514 1515 } 1516 1517 @Override enforceUriPermission(Uri arg0, int arg1, int arg2, int arg3, String arg4)1518 public void enforceUriPermission(Uri arg0, int arg1, int arg2, int arg3, 1519 String arg4) { 1520 // pass 1521 1522 } 1523 1524 @Override enforceUriPermission(Uri arg0, String arg1, String arg2, int arg3, int arg4, int arg5, String arg6)1525 public void enforceUriPermission(Uri arg0, String arg1, String arg2, 1526 int arg3, int arg4, int arg5, String arg6) { 1527 // pass 1528 1529 } 1530 1531 @Override fileList()1532 public String[] fileList() { 1533 // pass 1534 return null; 1535 } 1536 1537 @Override getAssets()1538 public BridgeAssetManager getAssets() { 1539 return mAssets; 1540 } 1541 1542 @Override getCacheDir()1543 public File getCacheDir() { 1544 // pass 1545 return null; 1546 } 1547 1548 @Override getCodeCacheDir()1549 public File getCodeCacheDir() { 1550 // pass 1551 return null; 1552 } 1553 1554 @Override getExternalCacheDir()1555 public File getExternalCacheDir() { 1556 // pass 1557 return null; 1558 } 1559 1560 @Override getPreloadsFileCache()1561 public File getPreloadsFileCache() { 1562 // pass 1563 return null; 1564 } 1565 1566 @Override getContentResolver()1567 public ContentResolver getContentResolver() { 1568 if (mContentResolver == null) { 1569 mContentResolver = new BridgeContentResolver(getApplicationContext()); 1570 } 1571 return mContentResolver; 1572 } 1573 1574 @Override getDatabasePath(String arg0)1575 public File getDatabasePath(String arg0) { 1576 // pass 1577 return null; 1578 } 1579 1580 @Override getDir(String arg0, int arg1)1581 public File getDir(String arg0, int arg1) { 1582 // pass 1583 return null; 1584 } 1585 1586 @Override getFileStreamPath(String arg0)1587 public File getFileStreamPath(String arg0) { 1588 // pass 1589 return null; 1590 } 1591 1592 @Override getSharedPreferencesPath(String name)1593 public File getSharedPreferencesPath(String name) { 1594 // pass 1595 return null; 1596 } 1597 1598 @Override getDataDir()1599 public File getDataDir() { 1600 // pass 1601 return null; 1602 } 1603 1604 @Override getFilesDir()1605 public File getFilesDir() { 1606 // pass 1607 return null; 1608 } 1609 1610 @Override getNoBackupFilesDir()1611 public File getNoBackupFilesDir() { 1612 // pass 1613 return null; 1614 } 1615 1616 @Override getExternalFilesDir(String type)1617 public File getExternalFilesDir(String type) { 1618 // pass 1619 return null; 1620 } 1621 1622 @Override getPackageCodePath()1623 public String getPackageCodePath() { 1624 // pass 1625 return null; 1626 } 1627 1628 @Override getBasePackageName()1629 public String getBasePackageName() { 1630 // pass 1631 return null; 1632 } 1633 1634 @Override getOpPackageName()1635 public String getOpPackageName() { 1636 // pass 1637 return null; 1638 } 1639 1640 @Override getApplicationInfo()1641 public ApplicationInfo getApplicationInfo() { 1642 return mApplicationInfo; 1643 } 1644 1645 @Override getPackageResourcePath()1646 public String getPackageResourcePath() { 1647 // pass 1648 return null; 1649 } 1650 1651 @Override getSharedPreferences(String arg0, int arg1)1652 public SharedPreferences getSharedPreferences(String arg0, int arg1) { 1653 if (mSharedPreferences == null) { 1654 mSharedPreferences = new BridgeSharedPreferences(); 1655 } 1656 return mSharedPreferences; 1657 } 1658 1659 @Override getSharedPreferences(File arg0, int arg1)1660 public SharedPreferences getSharedPreferences(File arg0, int arg1) { 1661 if (mSharedPreferences == null) { 1662 mSharedPreferences = new BridgeSharedPreferences(); 1663 } 1664 return mSharedPreferences; 1665 } 1666 1667 @Override reloadSharedPreferences()1668 public void reloadSharedPreferences() { 1669 // intentional noop 1670 } 1671 1672 @Override moveSharedPreferencesFrom(Context sourceContext, String name)1673 public boolean moveSharedPreferencesFrom(Context sourceContext, String name) { 1674 // pass 1675 return false; 1676 } 1677 1678 @Override deleteSharedPreferences(String name)1679 public boolean deleteSharedPreferences(String name) { 1680 // pass 1681 return false; 1682 } 1683 1684 @Override getWallpaper()1685 public Drawable getWallpaper() { 1686 // pass 1687 return null; 1688 } 1689 1690 @Override getWallpaperDesiredMinimumWidth()1691 public int getWallpaperDesiredMinimumWidth() { 1692 return -1; 1693 } 1694 1695 @Override getWallpaperDesiredMinimumHeight()1696 public int getWallpaperDesiredMinimumHeight() { 1697 return -1; 1698 } 1699 1700 @Override grantUriPermission(String arg0, Uri arg1, int arg2)1701 public void grantUriPermission(String arg0, Uri arg1, int arg2) { 1702 // pass 1703 1704 } 1705 1706 @Override openFileInput(String arg0)1707 public FileInputStream openFileInput(String arg0) throws FileNotFoundException { 1708 // pass 1709 return null; 1710 } 1711 1712 @Override openFileOutput(String arg0, int arg1)1713 public FileOutputStream openFileOutput(String arg0, int arg1) throws FileNotFoundException { 1714 // pass 1715 return null; 1716 } 1717 1718 @Override openOrCreateDatabase(String arg0, int arg1, CursorFactory arg2)1719 public SQLiteDatabase openOrCreateDatabase(String arg0, int arg1, CursorFactory arg2) { 1720 // pass 1721 return null; 1722 } 1723 1724 @Override openOrCreateDatabase(String arg0, int arg1, CursorFactory arg2, DatabaseErrorHandler arg3)1725 public SQLiteDatabase openOrCreateDatabase(String arg0, int arg1, 1726 CursorFactory arg2, DatabaseErrorHandler arg3) { 1727 // pass 1728 return null; 1729 } 1730 1731 @Override peekWallpaper()1732 public Drawable peekWallpaper() { 1733 // pass 1734 return null; 1735 } 1736 1737 @Override registerReceiver(BroadcastReceiver arg0, IntentFilter arg1)1738 public Intent registerReceiver(BroadcastReceiver arg0, IntentFilter arg1) { 1739 // pass 1740 return null; 1741 } 1742 1743 @Override registerReceiver(BroadcastReceiver arg0, IntentFilter arg1, int arg2)1744 public Intent registerReceiver(BroadcastReceiver arg0, IntentFilter arg1, int arg2) { 1745 // pass 1746 return null; 1747 } 1748 1749 @Override registerReceiver(BroadcastReceiver arg0, IntentFilter arg1, String arg2, Handler arg3)1750 public Intent registerReceiver(BroadcastReceiver arg0, IntentFilter arg1, 1751 String arg2, Handler arg3) { 1752 // pass 1753 return null; 1754 } 1755 1756 @Override registerReceiver(BroadcastReceiver arg0, IntentFilter arg1, String arg2, Handler arg3, int arg4)1757 public Intent registerReceiver(BroadcastReceiver arg0, IntentFilter arg1, 1758 String arg2, Handler arg3, int arg4) { 1759 // pass 1760 return null; 1761 } 1762 1763 @Override registerReceiverAsUser(BroadcastReceiver arg0, UserHandle arg0p5, IntentFilter arg1, String arg2, Handler arg3)1764 public Intent registerReceiverAsUser(BroadcastReceiver arg0, UserHandle arg0p5, 1765 IntentFilter arg1, String arg2, Handler arg3) { 1766 // pass 1767 return null; 1768 } 1769 1770 @Override registerReceiverAsUser(BroadcastReceiver arg0, UserHandle arg0p5, IntentFilter arg1, String arg2, Handler arg3, int arg4)1771 public Intent registerReceiverAsUser(BroadcastReceiver arg0, UserHandle arg0p5, 1772 IntentFilter arg1, String arg2, Handler arg3, int arg4) { 1773 // pass 1774 return null; 1775 } 1776 1777 @Override removeStickyBroadcast(Intent arg0)1778 public void removeStickyBroadcast(Intent arg0) { 1779 // pass 1780 1781 } 1782 1783 @Override revokeUriPermission(Uri arg0, int arg1)1784 public void revokeUriPermission(Uri arg0, int arg1) { 1785 // pass 1786 1787 } 1788 1789 @Override revokeUriPermission(String arg0, Uri arg1, int arg2)1790 public void revokeUriPermission(String arg0, Uri arg1, int arg2) { 1791 // pass 1792 1793 } 1794 1795 @Override sendBroadcast(Intent arg0)1796 public void sendBroadcast(Intent arg0) { 1797 // pass 1798 1799 } 1800 1801 @Override sendBroadcast(Intent arg0, String arg1)1802 public void sendBroadcast(Intent arg0, String arg1) { 1803 // pass 1804 1805 } 1806 1807 @Override sendBroadcastMultiplePermissions(Intent intent, String[] receiverPermissions)1808 public void sendBroadcastMultiplePermissions(Intent intent, String[] receiverPermissions) { 1809 // pass 1810 1811 } 1812 1813 @Override sendBroadcastAsUserMultiplePermissions(Intent intent, UserHandle user, String[] receiverPermissions)1814 public void sendBroadcastAsUserMultiplePermissions(Intent intent, UserHandle user, 1815 String[] receiverPermissions) { 1816 // pass 1817 1818 } 1819 1820 @Override sendBroadcast(Intent arg0, String arg1, Bundle arg2)1821 public void sendBroadcast(Intent arg0, String arg1, Bundle arg2) { 1822 // pass 1823 1824 } 1825 1826 @Override sendBroadcast(Intent intent, String receiverPermission, int appOp)1827 public void sendBroadcast(Intent intent, String receiverPermission, int appOp) { 1828 // pass 1829 } 1830 1831 @Override sendOrderedBroadcast(Intent arg0, String arg1)1832 public void sendOrderedBroadcast(Intent arg0, String arg1) { 1833 // pass 1834 1835 } 1836 1837 @Override sendOrderedBroadcast(Intent arg0, String arg1, BroadcastReceiver arg2, Handler arg3, int arg4, String arg5, Bundle arg6)1838 public void sendOrderedBroadcast(Intent arg0, String arg1, 1839 BroadcastReceiver arg2, Handler arg3, int arg4, String arg5, 1840 Bundle arg6) { 1841 // pass 1842 1843 } 1844 1845 @Override sendOrderedBroadcast(Intent arg0, String arg1, Bundle arg7, BroadcastReceiver arg2, Handler arg3, int arg4, String arg5, Bundle arg6)1846 public void sendOrderedBroadcast(Intent arg0, String arg1, 1847 Bundle arg7, BroadcastReceiver arg2, Handler arg3, int arg4, String arg5, 1848 Bundle arg6) { 1849 // pass 1850 1851 } 1852 1853 @Override sendOrderedBroadcast(Intent intent, String receiverPermission, int appOp, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras)1854 public void sendOrderedBroadcast(Intent intent, String receiverPermission, int appOp, 1855 BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, 1856 String initialData, Bundle initialExtras) { 1857 // pass 1858 } 1859 1860 @Override sendBroadcastAsUser(Intent intent, UserHandle user)1861 public void sendBroadcastAsUser(Intent intent, UserHandle user) { 1862 // pass 1863 } 1864 1865 @Override sendBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission)1866 public void sendBroadcastAsUser(Intent intent, UserHandle user, 1867 String receiverPermission) { 1868 // pass 1869 } 1870 1871 @Override sendBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission, Bundle options)1872 public void sendBroadcastAsUser(Intent intent, UserHandle user, 1873 String receiverPermission, Bundle options) { 1874 // pass 1875 } 1876 sendBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission, int appOp)1877 public void sendBroadcastAsUser(Intent intent, UserHandle user, 1878 String receiverPermission, int appOp) { 1879 // pass 1880 } 1881 1882 @Override sendOrderedBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras)1883 public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user, 1884 String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler, 1885 int initialCode, String initialData, Bundle initialExtras) { 1886 // pass 1887 } 1888 1889 @Override sendOrderedBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission, int appOp, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras)1890 public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user, 1891 String receiverPermission, int appOp, BroadcastReceiver resultReceiver, 1892 Handler scheduler, 1893 int initialCode, String initialData, Bundle initialExtras) { 1894 // pass 1895 } 1896 1897 @Override sendOrderedBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission, int appOp, Bundle options, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras)1898 public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user, 1899 String receiverPermission, int appOp, Bundle options, BroadcastReceiver resultReceiver, 1900 Handler scheduler, 1901 int initialCode, String initialData, Bundle initialExtras) { 1902 // pass 1903 } 1904 1905 @Override sendStickyBroadcast(Intent arg0)1906 public void sendStickyBroadcast(Intent arg0) { 1907 // pass 1908 1909 } 1910 1911 @Override sendStickyOrderedBroadcast(Intent intent, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras)1912 public void sendStickyOrderedBroadcast(Intent intent, 1913 BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, 1914 Bundle initialExtras) { 1915 // pass 1916 } 1917 1918 @Override sendStickyBroadcastAsUser(Intent intent, UserHandle user)1919 public void sendStickyBroadcastAsUser(Intent intent, UserHandle user) { 1920 // pass 1921 } 1922 1923 @Override sendStickyBroadcastAsUser(Intent intent, UserHandle user, Bundle options)1924 public void sendStickyBroadcastAsUser(Intent intent, UserHandle user, Bundle options) { 1925 // pass 1926 } 1927 1928 @Override sendStickyOrderedBroadcastAsUser(Intent intent, UserHandle user, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras)1929 public void sendStickyOrderedBroadcastAsUser(Intent intent, 1930 UserHandle user, BroadcastReceiver resultReceiver, 1931 Handler scheduler, int initialCode, String initialData, 1932 Bundle initialExtras) { 1933 // pass 1934 } 1935 1936 @Override removeStickyBroadcastAsUser(Intent intent, UserHandle user)1937 public void removeStickyBroadcastAsUser(Intent intent, UserHandle user) { 1938 // pass 1939 } 1940 1941 @Override setTheme(int arg0)1942 public void setTheme(int arg0) { 1943 // pass 1944 1945 } 1946 1947 @Override setWallpaper(Bitmap arg0)1948 public void setWallpaper(Bitmap arg0) throws IOException { 1949 // pass 1950 1951 } 1952 1953 @Override setWallpaper(InputStream arg0)1954 public void setWallpaper(InputStream arg0) throws IOException { 1955 // pass 1956 1957 } 1958 1959 @Override startActivity(Intent arg0)1960 public void startActivity(Intent arg0) { 1961 // pass 1962 } 1963 1964 @Override startActivity(Intent arg0, Bundle arg1)1965 public void startActivity(Intent arg0, Bundle arg1) { 1966 // pass 1967 } 1968 1969 @Override startIntentSender(IntentSender intent, Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags)1970 public void startIntentSender(IntentSender intent, 1971 Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags) 1972 throws IntentSender.SendIntentException { 1973 // pass 1974 } 1975 1976 @Override startIntentSender(IntentSender intent, Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags, Bundle options)1977 public void startIntentSender(IntentSender intent, 1978 Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags, 1979 Bundle options) throws IntentSender.SendIntentException { 1980 // pass 1981 } 1982 1983 @Override startInstrumentation(ComponentName arg0, String arg1, Bundle arg2)1984 public boolean startInstrumentation(ComponentName arg0, String arg1, 1985 Bundle arg2) { 1986 // pass 1987 return false; 1988 } 1989 1990 @Override startService(Intent arg0)1991 public ComponentName startService(Intent arg0) { 1992 // pass 1993 return null; 1994 } 1995 1996 @Override startForegroundService(Intent service)1997 public ComponentName startForegroundService(Intent service) { 1998 // pass 1999 return null; 2000 } 2001 2002 @Override startForegroundServiceAsUser(Intent service, UserHandle user)2003 public ComponentName startForegroundServiceAsUser(Intent service, UserHandle user) { 2004 // pass 2005 return null; 2006 } 2007 2008 @Override stopService(Intent arg0)2009 public boolean stopService(Intent arg0) { 2010 // pass 2011 return false; 2012 } 2013 2014 @Override startServiceAsUser(Intent arg0, UserHandle arg1)2015 public ComponentName startServiceAsUser(Intent arg0, UserHandle arg1) { 2016 // pass 2017 return null; 2018 } 2019 2020 @Override stopServiceAsUser(Intent arg0, UserHandle arg1)2021 public boolean stopServiceAsUser(Intent arg0, UserHandle arg1) { 2022 // pass 2023 return false; 2024 } 2025 2026 @Override updateServiceGroup(@onNull ServiceConnection conn, int group, int importance)2027 public void updateServiceGroup(@NonNull ServiceConnection conn, int group, 2028 int importance) { 2029 // pass 2030 } 2031 2032 @Override unbindService(ServiceConnection arg0)2033 public void unbindService(ServiceConnection arg0) { 2034 // pass 2035 2036 } 2037 2038 @Override unregisterReceiver(BroadcastReceiver arg0)2039 public void unregisterReceiver(BroadcastReceiver arg0) { 2040 // pass 2041 2042 } 2043 2044 @Override getApplicationContext()2045 public Context getApplicationContext() { 2046 if (mApplicationContext == null) { 2047 mApplicationContext = new ApplicationContext(this); 2048 } 2049 return mApplicationContext; 2050 } 2051 2052 @Override startActivities(Intent[] arg0)2053 public void startActivities(Intent[] arg0) { 2054 // pass 2055 2056 } 2057 2058 @Override startActivities(Intent[] arg0, Bundle arg1)2059 public void startActivities(Intent[] arg0, Bundle arg1) { 2060 // pass 2061 2062 } 2063 2064 @Override isRestricted()2065 public boolean isRestricted() { 2066 return false; 2067 } 2068 2069 @Override getObbDir()2070 public File getObbDir() { 2071 Bridge.getLog().error(ILayoutLog.TAG_UNSUPPORTED, "OBB not supported", null, null); 2072 return null; 2073 } 2074 2075 @Override getDisplayAdjustments(int displayId)2076 public DisplayAdjustments getDisplayAdjustments(int displayId) { 2077 // pass 2078 return null; 2079 } 2080 2081 @Override getDisplay()2082 public Display getDisplay() { 2083 // pass 2084 return null; 2085 } 2086 2087 @Override getDisplayId()2088 public int getDisplayId() { 2089 // pass 2090 return 0; 2091 } 2092 2093 @Override updateDisplay(int displayId)2094 public void updateDisplay(int displayId) { 2095 // pass 2096 } 2097 2098 @Override getUserId()2099 public int getUserId() { 2100 return 0; // not used 2101 } 2102 2103 @Override getExternalFilesDirs(String type)2104 public File[] getExternalFilesDirs(String type) { 2105 // pass 2106 return new File[0]; 2107 } 2108 2109 @Override getObbDirs()2110 public File[] getObbDirs() { 2111 // pass 2112 return new File[0]; 2113 } 2114 2115 @Override getExternalCacheDirs()2116 public File[] getExternalCacheDirs() { 2117 // pass 2118 return new File[0]; 2119 } 2120 2121 @Override getExternalMediaDirs()2122 public File[] getExternalMediaDirs() { 2123 // pass 2124 return new File[0]; 2125 } 2126 setScrollYPos(@onNull View view, int scrollPos)2127 public void setScrollYPos(@NonNull View view, int scrollPos) { 2128 mScrollYPos.put(view, scrollPos); 2129 } 2130 getScrollYPos(@onNull View view)2131 public int getScrollYPos(@NonNull View view) { 2132 Integer pos = mScrollYPos.get(view); 2133 return pos != null ? pos : 0; 2134 } 2135 setScrollXPos(@onNull View view, int scrollPos)2136 public void setScrollXPos(@NonNull View view, int scrollPos) { 2137 mScrollXPos.put(view, scrollPos); 2138 } 2139 getScrollXPos(@onNull View view)2140 public int getScrollXPos(@NonNull View view) { 2141 Integer pos = mScrollXPos.get(view); 2142 return pos != null ? pos : 0; 2143 } 2144 2145 @Override createDeviceProtectedStorageContext()2146 public Context createDeviceProtectedStorageContext() { 2147 // pass 2148 return null; 2149 } 2150 2151 @Override createCredentialProtectedStorageContext()2152 public Context createCredentialProtectedStorageContext() { 2153 // pass 2154 return null; 2155 } 2156 2157 @Override isDeviceProtectedStorage()2158 public boolean isDeviceProtectedStorage() { 2159 return false; 2160 } 2161 2162 @Override isCredentialProtectedStorage()2163 public boolean isCredentialProtectedStorage() { 2164 return false; 2165 } 2166 2167 @Override canLoadUnsafeResources()2168 public boolean canLoadUnsafeResources() { 2169 return true; 2170 } 2171 2172 @Override isUiContext()2173 public boolean isUiContext() { 2174 return true; 2175 } 2176 putUserData(@onNull Key<T> key, @Nullable T data)2177 public <T> void putUserData(@NonNull Key<T> key, @Nullable T data) { 2178 mUserData.put(key, data); 2179 } 2180 2181 @SuppressWarnings("unchecked") 2182 @Nullable getUserData(@onNull Key<T> key)2183 public <T> T getUserData(@NonNull Key<T> key) { 2184 return (T) mUserData.get(key); 2185 } 2186 2187 /** Logs an error message to the error log of the host application. */ error(@onNull String message, @NonNull String... details)2188 public void error(@NonNull String message, @NonNull String... details) { 2189 mLayoutlibCallback.error(message, details); 2190 } 2191 2192 /** Logs an error message to the error log of the host application. */ error(@onNull String message, @Nullable Throwable t)2193 public void error(@NonNull String message, @Nullable Throwable t) { 2194 mLayoutlibCallback.error(message, t); 2195 } 2196 2197 /** Logs an error message to the error log of the host application. */ error(@onNull Throwable t)2198 public void error(@NonNull Throwable t) { 2199 mLayoutlibCallback.error(t); 2200 } 2201 2202 /** Logs a warning to the log of the host application. */ warn(@onNull String message, @Nullable Throwable t)2203 public void warn(@NonNull String message, @Nullable Throwable t) { 2204 mLayoutlibCallback.warn(message, t); 2205 } 2206 2207 /** Logs a warning to the log of the host application. */ warn(@onNull Throwable t)2208 public void warn(@NonNull Throwable t) { 2209 mLayoutlibCallback.warn(t); 2210 } 2211 2212 /** 2213 * No two Key instances are considered equal. 2214 * 2215 * @param <T> the type of values associated with the key 2216 */ 2217 public static final class Key<T> { 2218 private final String name; 2219 2220 @NonNull create(@onNull String name)2221 public static <T> Key<T> create(@NonNull String name) { 2222 return new Key<T>(name); 2223 } 2224 Key(@onNull String name)2225 private Key(@NonNull String name) { 2226 this.name = name; 2227 } 2228 2229 /** For debugging only. */ 2230 @Override toString()2231 public String toString() { 2232 return name; 2233 } 2234 } 2235 2236 private class AttributeHolder { 2237 private final int resourceId; 2238 @NonNull private final ResourceReference reference; 2239 AttributeHolder(int resourceId, @NonNull ResourceReference reference)2240 private AttributeHolder(int resourceId, @NonNull ResourceReference reference) { 2241 this.resourceId = resourceId; 2242 this.reference = reference; 2243 } 2244 2245 @NonNull asReference()2246 private ResourceReference asReference() { 2247 return reference; 2248 } 2249 getResourceId()2250 private int getResourceId() { 2251 return resourceId; 2252 } 2253 2254 @NonNull getName()2255 private String getName() { 2256 return reference.getName(); 2257 } 2258 2259 @NonNull getNamespace()2260 private ResourceNamespace getNamespace() { 2261 return reference.getNamespace(); 2262 } 2263 } 2264 2265 /** 2266 * The cached value depends on 2267 * <ol> 2268 * <li>{@code int[]}: the attributes for which TypedArray is created </li> 2269 * <li>{@code List<StyleResourceValue>}: the themes set on the context at the time of 2270 * creation of the TypedArray</li> 2271 * <li>{@code Integer}: the default style used at the time of creation</li> 2272 * </ol> 2273 * 2274 * The class is created by using nested maps resolving one dependency at a time. 2275 * <p/> 2276 * The final value of the nested maps is a pair of the typed array and a map of properties 2277 * that should be added to {@link #mDefaultPropMaps}, if needed. 2278 */ 2279 private static class TypedArrayCache { 2280 2281 private Map<int[], 2282 Map<List<StyleResourceValue>, 2283 Map<Integer, Pair<BridgeTypedArray, 2284 Map<ResourceReference, ResourceValue>>>>> mCache; 2285 TypedArrayCache()2286 private TypedArrayCache() { 2287 mCache = new IdentityHashMap<>(); 2288 } 2289 get(int[] attrs, List<StyleResourceValue> themes, int resId)2290 public Pair<BridgeTypedArray, Map<ResourceReference, ResourceValue>> get(int[] attrs, 2291 List<StyleResourceValue> themes, int resId) { 2292 Map<List<StyleResourceValue>, Map<Integer, Pair<BridgeTypedArray, Map<ResourceReference, 2293 ResourceValue>>>> 2294 cacheFromThemes = mCache.get(attrs); 2295 if (cacheFromThemes != null) { 2296 Map<Integer, Pair<BridgeTypedArray, Map<ResourceReference, ResourceValue>>> cacheFromResId = 2297 cacheFromThemes.get(themes); 2298 if (cacheFromResId != null) { 2299 return cacheFromResId.get(resId); 2300 } 2301 } 2302 return null; 2303 } 2304 put(int[] attrs, List<StyleResourceValue> themes, int resId, Pair<BridgeTypedArray, Map<ResourceReference, ResourceValue>> value)2305 public void put(int[] attrs, List<StyleResourceValue> themes, int resId, 2306 Pair<BridgeTypedArray, Map<ResourceReference, ResourceValue>> value) { 2307 Map<List<StyleResourceValue>, Map<Integer, Pair<BridgeTypedArray, Map<ResourceReference, 2308 ResourceValue>>>> 2309 cacheFromThemes = mCache.computeIfAbsent(attrs, k -> new HashMap<>()); 2310 Map<Integer, Pair<BridgeTypedArray, Map<ResourceReference, ResourceValue>>> cacheFromResId = 2311 cacheFromThemes.computeIfAbsent(themes, k -> new HashMap<>()); 2312 cacheFromResId.put(resId, value); 2313 } 2314 2315 } 2316 2317 @NotNull getSessionInteractiveData()2318 public SessionInteractiveData getSessionInteractiveData() { 2319 return mSessionInteractiveData; 2320 } 2321 useThemedIcon()2322 public boolean useThemedIcon() { 2323 return mUseThemedIcon && mRenderResources.hasDynamicColors(); 2324 } 2325 setUseThemedIcon(boolean useThemedIcon)2326 public void setUseThemedIcon(boolean useThemedIcon) { 2327 mUseThemedIcon = useThemedIcon; 2328 } 2329 applyWallpaper(String wallpaperPath)2330 public void applyWallpaper(String wallpaperPath) { 2331 mRenderResources.setWallpaper(wallpaperPath, mConfig.isNightModeActive()); 2332 } 2333 2334 @NotNull getAnimationHandlerThreadLocal()2335 public ThreadLocal<AnimationHandler> getAnimationHandlerThreadLocal() { 2336 return mAnimationHandlerThreadLocal; 2337 } 2338 } 2339