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