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