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