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