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