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.ide.common.rendering.api.ILayoutPullParser; 20 import com.android.ide.common.rendering.api.IProjectCallback; 21 import com.android.ide.common.rendering.api.LayoutLog; 22 import com.android.ide.common.rendering.api.RenderResources; 23 import com.android.ide.common.rendering.api.ResourceReference; 24 import com.android.ide.common.rendering.api.ResourceValue; 25 import com.android.ide.common.rendering.api.StyleResourceValue; 26 import com.android.layoutlib.bridge.Bridge; 27 import com.android.layoutlib.bridge.BridgeConstants; 28 import com.android.layoutlib.bridge.android.view.WindowManagerImpl; 29 import com.android.layoutlib.bridge.impl.ParserFactory; 30 import com.android.layoutlib.bridge.impl.Stack; 31 import com.android.resources.ResourceType; 32 import com.android.util.Pair; 33 34 import org.xmlpull.v1.XmlPullParser; 35 import org.xmlpull.v1.XmlPullParserException; 36 37 import android.content.BroadcastReceiver; 38 import android.content.ComponentName; 39 import android.content.ContentResolver; 40 import android.content.Context; 41 import android.content.Intent; 42 import android.content.IntentFilter; 43 import android.content.IntentSender; 44 import android.content.ServiceConnection; 45 import android.content.SharedPreferences; 46 import android.content.pm.ApplicationInfo; 47 import android.content.pm.PackageManager; 48 import android.content.res.AssetManager; 49 import android.content.res.BridgeResources; 50 import android.content.res.BridgeTypedArray; 51 import android.content.res.Configuration; 52 import android.content.res.Resources; 53 import android.content.res.Resources.Theme; 54 import android.content.res.TypedArray; 55 import android.database.DatabaseErrorHandler; 56 import android.database.sqlite.SQLiteDatabase; 57 import android.database.sqlite.SQLiteDatabase.CursorFactory; 58 import android.graphics.Bitmap; 59 import android.graphics.drawable.Drawable; 60 import android.net.Uri; 61 import android.os.Bundle; 62 import android.os.Handler; 63 import android.os.Looper; 64 import android.os.PowerManager; 65 import android.os.UserHandle; 66 import android.util.AttributeSet; 67 import android.util.DisplayMetrics; 68 import android.util.TypedValue; 69 import android.view.BridgeInflater; 70 import android.view.CompatibilityInfoHolder; 71 import android.view.Display; 72 import android.view.View; 73 import android.view.ViewGroup; 74 import android.view.WindowManager; 75 import android.view.textservice.TextServicesManager; 76 77 import java.io.File; 78 import java.io.FileInputStream; 79 import java.io.FileNotFoundException; 80 import java.io.FileOutputStream; 81 import java.io.IOException; 82 import java.io.InputStream; 83 import java.util.ArrayList; 84 import java.util.HashMap; 85 import java.util.IdentityHashMap; 86 import java.util.List; 87 import java.util.Map; 88 89 /** 90 * Custom implementation of Context/Activity to handle non compiled resources. 91 */ 92 public final class BridgeContext extends Context { 93 94 private Resources mSystemResources; 95 private final HashMap<View, Object> mViewKeyMap = new HashMap<View, Object>(); 96 private final Object mProjectKey; 97 private final DisplayMetrics mMetrics; 98 private final RenderResources mRenderResources; 99 private final Configuration mConfig; 100 private final ApplicationInfo mApplicationInfo; 101 private final IProjectCallback mProjectCallback; 102 private final WindowManager mWindowManager; 103 104 private Resources.Theme mTheme; 105 106 private final Map<Object, Map<String, String>> mDefaultPropMaps = 107 new IdentityHashMap<Object, Map<String,String>>(); 108 109 // maps for dynamically generated id representing style objects (StyleResourceValue) 110 private Map<Integer, StyleResourceValue> mDynamicIdToStyleMap; 111 private Map<StyleResourceValue, Integer> mStyleToDynamicIdMap; 112 private int mDynamicIdGenerator = 0x01030000; // Base id for framework R.style 113 114 // cache for TypedArray generated from IStyleResourceValue object 115 private Map<int[], Map<Integer, TypedArray>> mTypedArrayCache; 116 private BridgeInflater mBridgeInflater; 117 118 private BridgeContentResolver mContentResolver; 119 120 private final Stack<BridgeXmlBlockParser> mParserStack = new Stack<BridgeXmlBlockParser>(); 121 122 /** 123 * @param projectKey An Object identifying the project. This is used for the cache mechanism. 124 * @param metrics the {@link DisplayMetrics}. 125 * @param renderResources the configured resources (both framework and projects) for this 126 * render. 127 * @param projectCallback 128 * @param config the Configuration object for this render. 129 * @param targetSdkVersion the targetSdkVersion of the application. 130 */ 131 public BridgeContext(Object projectKey, DisplayMetrics metrics, 132 RenderResources renderResources, 133 IProjectCallback projectCallback, 134 Configuration config, 135 int targetSdkVersion) { 136 mProjectKey = projectKey; 137 mMetrics = metrics; 138 mProjectCallback = projectCallback; 139 140 mRenderResources = renderResources; 141 mConfig = config; 142 143 mApplicationInfo = new ApplicationInfo(); 144 mApplicationInfo.targetSdkVersion = targetSdkVersion; 145 146 mWindowManager = new WindowManagerImpl(mMetrics); 147 } 148 149 /** 150 * Initializes the {@link Resources} singleton to be linked to this {@link Context}, its 151 * {@link DisplayMetrics}, {@link Configuration}, and {@link IProjectCallback}. 152 * 153 * @see #disposeResources() 154 */ 155 public void initResources() { 156 AssetManager assetManager = AssetManager.getSystem(); 157 158 mSystemResources = BridgeResources.initSystem( 159 this, 160 assetManager, 161 mMetrics, 162 mConfig, 163 mProjectCallback); 164 mTheme = mSystemResources.newTheme(); 165 } 166 167 /** 168 * Disposes the {@link Resources} singleton. 169 */ 170 public void disposeResources() { 171 BridgeResources.disposeSystem(); 172 } 173 174 public void setBridgeInflater(BridgeInflater inflater) { 175 mBridgeInflater = inflater; 176 } 177 178 public void addViewKey(View view, Object viewKey) { 179 mViewKeyMap.put(view, viewKey); 180 } 181 182 public Object getViewKey(View view) { 183 return mViewKeyMap.get(view); 184 } 185 186 public Object getProjectKey() { 187 return mProjectKey; 188 } 189 190 public DisplayMetrics getMetrics() { 191 return mMetrics; 192 } 193 194 public IProjectCallback getProjectCallback() { 195 return mProjectCallback; 196 } 197 198 public RenderResources getRenderResources() { 199 return mRenderResources; 200 } 201 202 public Map<String, String> getDefaultPropMap(Object key) { 203 return mDefaultPropMaps.get(key); 204 } 205 206 public Configuration getConfiguration() { 207 return mConfig; 208 } 209 210 /** 211 * Adds a parser to the stack. 212 * @param parser the parser to add. 213 */ 214 public void pushParser(BridgeXmlBlockParser parser) { 215 if (ParserFactory.LOG_PARSER) { 216 System.out.println("PUSH " + parser.getParser().toString()); 217 } 218 mParserStack.push(parser); 219 } 220 221 /** 222 * Removes the parser at the top of the stack 223 */ 224 public void popParser() { 225 BridgeXmlBlockParser parser = mParserStack.pop(); 226 if (ParserFactory.LOG_PARSER) { 227 System.out.println("POPD " + parser.getParser().toString()); 228 } 229 } 230 231 /** 232 * Returns the current parser at the top the of the stack. 233 * @return a parser or null. 234 */ 235 public BridgeXmlBlockParser getCurrentParser() { 236 return mParserStack.peek(); 237 } 238 239 /** 240 * Returns the previous parser. 241 * @return a parser or null if there isn't any previous parser 242 */ 243 public BridgeXmlBlockParser getPreviousParser() { 244 if (mParserStack.size() < 2) { 245 return null; 246 } 247 return mParserStack.get(mParserStack.size() - 2); 248 } 249 250 public boolean resolveThemeAttribute(int resid, TypedValue outValue, boolean resolveRefs) { 251 Pair<ResourceType, String> resourceInfo = Bridge.resolveResourceId(resid); 252 boolean isFrameworkRes = true; 253 if (resourceInfo == null) { 254 resourceInfo = mProjectCallback.resolveResourceId(resid); 255 isFrameworkRes = false; 256 } 257 258 if (resourceInfo == null) { 259 return false; 260 } 261 262 ResourceValue value = mRenderResources.findItemInTheme(resourceInfo.getSecond(), 263 isFrameworkRes); 264 if (resolveRefs) { 265 value = mRenderResources.resolveResValue(value); 266 } 267 268 // check if this is a style resource 269 if (value instanceof StyleResourceValue) { 270 // get the id that will represent this style. 271 outValue.resourceId = getDynamicIdByStyle((StyleResourceValue)value); 272 return true; 273 } 274 275 276 int a; 277 // if this is a framework value. 278 if (value.isFramework()) { 279 // look for idName in the android R classes. 280 // use 0 a default res value as it's not a valid id value. 281 a = getFrameworkResourceValue(value.getResourceType(), value.getName(), 0 /*defValue*/); 282 } else { 283 // look for idName in the project R class. 284 // use 0 a default res value as it's not a valid id value. 285 a = getProjectResourceValue(value.getResourceType(), value.getName(), 0 /*defValue*/); 286 } 287 288 if (a != 0) { 289 outValue.resourceId = a; 290 return true; 291 } 292 293 return false; 294 } 295 296 297 public ResourceReference resolveId(int id) { 298 // first get the String related to this id in the framework 299 Pair<ResourceType, String> resourceInfo = Bridge.resolveResourceId(id); 300 301 if (resourceInfo != null) { 302 return new ResourceReference(resourceInfo.getSecond(), true); 303 } 304 305 // didn't find a match in the framework? look in the project. 306 if (mProjectCallback != null) { 307 resourceInfo = mProjectCallback.resolveResourceId(id); 308 309 if (resourceInfo != null) { 310 return new ResourceReference(resourceInfo.getSecond(), false); 311 } 312 } 313 314 return null; 315 } 316 317 public Pair<View, Boolean> inflateView(ResourceReference resource, ViewGroup parent, 318 boolean attachToRoot, boolean skipCallbackParser) { 319 boolean isPlatformLayout = resource.isFramework(); 320 321 if (isPlatformLayout == false && skipCallbackParser == false) { 322 // check if the project callback can provide us with a custom parser. 323 ILayoutPullParser parser = getParser(resource); 324 325 if (parser != null) { 326 BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser(parser, 327 this, resource.isFramework()); 328 try { 329 pushParser(blockParser); 330 return Pair.of( 331 mBridgeInflater.inflate(blockParser, parent, attachToRoot), 332 true); 333 } finally { 334 popParser(); 335 } 336 } 337 } 338 339 ResourceValue resValue; 340 if (resource instanceof ResourceValue) { 341 resValue = (ResourceValue) resource; 342 } else { 343 if (isPlatformLayout) { 344 resValue = mRenderResources.getFrameworkResource(ResourceType.LAYOUT, 345 resource.getName()); 346 } else { 347 resValue = mRenderResources.getProjectResource(ResourceType.LAYOUT, 348 resource.getName()); 349 } 350 } 351 352 if (resValue != null) { 353 354 File xml = new File(resValue.getValue()); 355 if (xml.isFile()) { 356 // we need to create a pull parser around the layout XML file, and then 357 // give that to our XmlBlockParser 358 try { 359 XmlPullParser parser = ParserFactory.create(xml); 360 361 // set the resource ref to have correct view cookies 362 mBridgeInflater.setResourceReference(resource); 363 364 BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser(parser, 365 this, resource.isFramework()); 366 try { 367 pushParser(blockParser); 368 return Pair.of( 369 mBridgeInflater.inflate(blockParser, parent, attachToRoot), 370 false); 371 } finally { 372 popParser(); 373 } 374 } catch (XmlPullParserException e) { 375 Bridge.getLog().error(LayoutLog.TAG_BROKEN, 376 "Failed to configure parser for " + xml, e, null /*data*/); 377 // we'll return null below. 378 } catch (FileNotFoundException e) { 379 // this shouldn't happen since we check above. 380 } finally { 381 mBridgeInflater.setResourceReference(null); 382 } 383 } else { 384 Bridge.getLog().error(LayoutLog.TAG_BROKEN, 385 String.format("File %s is missing!", xml), null); 386 } 387 } else { 388 Bridge.getLog().error(LayoutLog.TAG_BROKEN, 389 String.format("Layout %s%s does not exist.", isPlatformLayout ? "android:" : "", 390 resource.getName()), null); 391 } 392 393 return Pair.of(null, false); 394 } 395 396 @SuppressWarnings("deprecation") 397 private ILayoutPullParser getParser(ResourceReference resource) { 398 ILayoutPullParser parser; 399 if (resource instanceof ResourceValue) { 400 parser = mProjectCallback.getParser((ResourceValue) resource); 401 } else { 402 parser = mProjectCallback.getParser(resource.getName()); 403 } 404 return parser; 405 } 406 407 // ------------ Context methods 408 409 @Override 410 public Resources getResources() { 411 return mSystemResources; 412 } 413 414 @Override 415 public Theme getTheme() { 416 return mTheme; 417 } 418 419 @Override 420 public ClassLoader getClassLoader() { 421 return this.getClass().getClassLoader(); 422 } 423 424 @Override 425 public Object getSystemService(String service) { 426 if (LAYOUT_INFLATER_SERVICE.equals(service)) { 427 return mBridgeInflater; 428 } 429 430 if (TEXT_SERVICES_MANAGER_SERVICE.equals(service)) { 431 // we need to return a valid service to avoid NPE 432 return TextServicesManager.getInstance(); 433 } 434 435 if (WINDOW_SERVICE.equals(service)) { 436 return mWindowManager; 437 } 438 439 // needed by SearchView 440 if (INPUT_METHOD_SERVICE.equals(service)) { 441 return null; 442 } 443 444 if (POWER_SERVICE.equals(service)) { 445 return new PowerManager(this, new BridgePowerManager(), new Handler()); 446 } 447 448 throw new UnsupportedOperationException("Unsupported Service: " + service); 449 } 450 451 452 @Override 453 public final TypedArray obtainStyledAttributes(int[] attrs) { 454 return createStyleBasedTypedArray(mRenderResources.getCurrentTheme(), attrs); 455 } 456 457 @Override 458 public final TypedArray obtainStyledAttributes(int resid, int[] attrs) 459 throws Resources.NotFoundException { 460 // get the StyleResourceValue based on the resId; 461 StyleResourceValue style = getStyleByDynamicId(resid); 462 463 if (style == null) { 464 throw new Resources.NotFoundException(); 465 } 466 467 if (mTypedArrayCache == null) { 468 mTypedArrayCache = new HashMap<int[], Map<Integer,TypedArray>>(); 469 470 Map<Integer, TypedArray> map = new HashMap<Integer, TypedArray>(); 471 mTypedArrayCache.put(attrs, map); 472 473 BridgeTypedArray ta = createStyleBasedTypedArray(style, attrs); 474 map.put(resid, ta); 475 476 return ta; 477 } 478 479 // get the 2nd map 480 Map<Integer, TypedArray> map = mTypedArrayCache.get(attrs); 481 if (map == null) { 482 map = new HashMap<Integer, TypedArray>(); 483 mTypedArrayCache.put(attrs, map); 484 } 485 486 // get the array from the 2nd map 487 TypedArray ta = map.get(resid); 488 489 if (ta == null) { 490 ta = createStyleBasedTypedArray(style, attrs); 491 map.put(resid, ta); 492 } 493 494 return ta; 495 } 496 497 @Override 498 public final TypedArray obtainStyledAttributes(AttributeSet set, int[] attrs) { 499 return obtainStyledAttributes(set, attrs, 0, 0); 500 } 501 502 @Override 503 public TypedArray obtainStyledAttributes(AttributeSet set, int[] attrs, 504 int defStyleAttr, int defStyleRes) { 505 506 Map<String, String> defaultPropMap = null; 507 boolean isPlatformFile = true; 508 509 // Hint: for XmlPullParser, attach source //DEVICE_SRC/dalvik/libcore/xml/src/java 510 if (set instanceof BridgeXmlBlockParser) { 511 BridgeXmlBlockParser parser = null; 512 parser = (BridgeXmlBlockParser)set; 513 514 isPlatformFile = parser.isPlatformFile(); 515 516 Object key = parser.getViewCookie(); 517 if (key != null) { 518 defaultPropMap = mDefaultPropMaps.get(key); 519 if (defaultPropMap == null) { 520 defaultPropMap = new HashMap<String, String>(); 521 mDefaultPropMaps.put(key, defaultPropMap); 522 } 523 } 524 525 } else if (set instanceof BridgeLayoutParamsMapAttributes) { 526 // this is only for temp layout params generated dynamically, so this is never 527 // platform content. 528 isPlatformFile = false; 529 } else if (set != null) { // null parser is ok 530 // really this should not be happening since its instantiated in Bridge 531 Bridge.getLog().error(LayoutLog.TAG_BROKEN, 532 "Parser is not a BridgeXmlBlockParser!", null /*data*/); 533 return null; 534 } 535 536 List<Pair<String, Boolean>> attributeList = searchAttrs(attrs); 537 538 BridgeTypedArray ta = ((BridgeResources) mSystemResources).newTypeArray(attrs.length, 539 isPlatformFile); 540 541 // look for a custom style. 542 String customStyle = null; 543 if (set != null) { 544 customStyle = set.getAttributeValue(null /* namespace*/, "style"); 545 } 546 547 StyleResourceValue customStyleValues = null; 548 if (customStyle != null) { 549 ResourceValue item = mRenderResources.findResValue(customStyle, 550 false /*forceFrameworkOnly*/); 551 552 // resolve it in case it links to something else 553 item = mRenderResources.resolveResValue(item); 554 555 if (item instanceof StyleResourceValue) { 556 customStyleValues = (StyleResourceValue)item; 557 } 558 } 559 560 // resolve the defStyleAttr value into a IStyleResourceValue 561 StyleResourceValue defStyleValues = null; 562 563 if (defStyleAttr != 0) { 564 // get the name from the int. 565 Pair<String, Boolean> defStyleAttribute = searchAttr(defStyleAttr); 566 567 if (defaultPropMap != null) { 568 String defStyleName = defStyleAttribute.getFirst(); 569 if (defStyleAttribute.getSecond()) { 570 defStyleName = "android:" + defStyleName; 571 } 572 defaultPropMap.put("style", defStyleName); 573 } 574 575 // look for the style in the current theme, and its parent: 576 ResourceValue item = mRenderResources.findItemInTheme(defStyleAttribute.getFirst(), 577 defStyleAttribute.getSecond()); 578 579 if (item != null) { 580 // item is a reference to a style entry. Search for it. 581 item = mRenderResources.findResValue(item.getValue(), 582 false /*forceFrameworkOnly*/); 583 584 if (item instanceof StyleResourceValue) { 585 defStyleValues = (StyleResourceValue)item; 586 } 587 } else { 588 Bridge.getLog().error(LayoutLog.TAG_RESOURCES_RESOLVE_THEME_ATTR, 589 String.format( 590 "Failed to find style '%s' in current theme", 591 defStyleAttribute.getFirst()), 592 null /*data*/); 593 } 594 } else if (defStyleRes != 0) { 595 boolean isFrameworkRes = true; 596 Pair<ResourceType, String> value = Bridge.resolveResourceId(defStyleRes); 597 if (value == null) { 598 value = mProjectCallback.resolveResourceId(defStyleRes); 599 isFrameworkRes = false; 600 } 601 602 if (value != null) { 603 if (value.getFirst() == ResourceType.STYLE) { 604 // look for the style in the current theme, and its parent: 605 ResourceValue item = mRenderResources.findItemInTheme(value.getSecond(), 606 isFrameworkRes); 607 if (item != null) { 608 if (item instanceof StyleResourceValue) { 609 if (defaultPropMap != null) { 610 defaultPropMap.put("style", item.getName()); 611 } 612 613 defStyleValues = (StyleResourceValue)item; 614 } 615 } else { 616 Bridge.getLog().error(null, 617 String.format( 618 "Style with id 0x%x (resolved to '%s') does not exist.", 619 defStyleRes, value.getSecond()), 620 null /*data*/); 621 } 622 } else { 623 Bridge.getLog().error(null, 624 String.format( 625 "Resouce id 0x%x is not of type STYLE (instead %s)", 626 defStyleRes, value.getFirst().toString()), 627 null /*data*/); 628 } 629 } else { 630 Bridge.getLog().error(null, 631 String.format( 632 "Failed to find style with id 0x%x in current theme", 633 defStyleRes), 634 null /*data*/); 635 } 636 } 637 638 String appNamespace = mProjectCallback.getNamespace(); 639 640 if (attributeList != null) { 641 for (int index = 0 ; index < attributeList.size() ; index++) { 642 Pair<String, Boolean> attribute = attributeList.get(index); 643 644 if (attribute == null) { 645 continue; 646 } 647 648 String attrName = attribute.getFirst(); 649 boolean frameworkAttr = attribute.getSecond().booleanValue(); 650 String value = null; 651 if (set != null) { 652 value = set.getAttributeValue( 653 frameworkAttr ? BridgeConstants.NS_RESOURCES : appNamespace, 654 attrName); 655 656 // if this is an app attribute, and the first get fails, try with the 657 // new res-auto namespace as well 658 if (frameworkAttr == false && value == null) { 659 value = set.getAttributeValue(BridgeConstants.NS_APP_RES_AUTO, attrName); 660 } 661 } 662 663 // if there's no direct value for this attribute in the XML, we look for default 664 // values in the widget defStyle, and then in the theme. 665 if (value == null) { 666 ResourceValue resValue = null; 667 668 // look for the value in the custom style first (and its parent if needed) 669 if (customStyleValues != null) { 670 resValue = mRenderResources.findItemInStyle(customStyleValues, 671 attrName, frameworkAttr); 672 } 673 674 // then look for the value in the default Style (and its parent if needed) 675 if (resValue == null && defStyleValues != null) { 676 resValue = mRenderResources.findItemInStyle(defStyleValues, 677 attrName, frameworkAttr); 678 } 679 680 // if the item is not present in the defStyle, we look in the main theme (and 681 // its parent themes) 682 if (resValue == null) { 683 resValue = mRenderResources.findItemInTheme(attrName, frameworkAttr); 684 } 685 686 // if we found a value, we make sure this doesn't reference another value. 687 // So we resolve it. 688 if (resValue != null) { 689 // put the first default value, before the resolution. 690 if (defaultPropMap != null) { 691 defaultPropMap.put(attrName, resValue.getValue()); 692 } 693 694 resValue = mRenderResources.resolveResValue(resValue); 695 } 696 697 ta.bridgeSetValue(index, attrName, frameworkAttr, resValue); 698 } else { 699 // there is a value in the XML, but we need to resolve it in case it's 700 // referencing another resource or a theme value. 701 ta.bridgeSetValue(index, attrName, frameworkAttr, 702 mRenderResources.resolveValue(null, attrName, value, isPlatformFile)); 703 } 704 } 705 } 706 707 ta.sealArray(); 708 709 return ta; 710 } 711 712 @Override 713 public Looper getMainLooper() { 714 return Looper.myLooper(); 715 } 716 717 718 // ------------- private new methods 719 720 /** 721 * Creates a {@link BridgeTypedArray} by filling the values defined by the int[] with the 722 * values found in the given style. 723 * @see #obtainStyledAttributes(int, int[]) 724 */ 725 private BridgeTypedArray createStyleBasedTypedArray(StyleResourceValue style, int[] attrs) 726 throws Resources.NotFoundException { 727 728 List<Pair<String, Boolean>> attributes = searchAttrs(attrs); 729 730 BridgeTypedArray ta = ((BridgeResources) mSystemResources).newTypeArray(attrs.length, 731 false); 732 733 // for each attribute, get its name so that we can search it in the style 734 for (int i = 0 ; i < attrs.length ; i++) { 735 Pair<String, Boolean> attribute = attributes.get(i); 736 737 if (attribute != null) { 738 // look for the value in the given style 739 ResourceValue resValue = mRenderResources.findItemInStyle(style, 740 attribute.getFirst(), attribute.getSecond()); 741 742 if (resValue != null) { 743 // resolve it to make sure there are no references left. 744 ta.bridgeSetValue(i, attribute.getFirst(), attribute.getSecond(), 745 mRenderResources.resolveResValue(resValue)); 746 } 747 } 748 } 749 750 ta.sealArray(); 751 752 return ta; 753 } 754 755 756 /** 757 * The input int[] attrs is a list of attributes. The returns a list of information about 758 * each attributes. The information is (name, isFramework) 759 * <p/> 760 * 761 * @param attrs An attribute array reference given to obtainStyledAttributes. 762 * @return List of attribute information. 763 */ 764 private List<Pair<String, Boolean>> searchAttrs(int[] attrs) { 765 List<Pair<String, Boolean>> results = new ArrayList<Pair<String, Boolean>>(attrs.length); 766 767 // for each attribute, get its name so that we can search it in the style 768 for (int i = 0 ; i < attrs.length ; i++) { 769 Pair<ResourceType, String> resolvedResource = Bridge.resolveResourceId(attrs[i]); 770 boolean isFramework = false; 771 if (resolvedResource != null) { 772 isFramework = true; 773 } else { 774 resolvedResource = mProjectCallback.resolveResourceId(attrs[i]); 775 } 776 777 if (resolvedResource != null) { 778 results.add(Pair.of(resolvedResource.getSecond(), isFramework)); 779 } else { 780 results.add(null); 781 } 782 } 783 784 return results; 785 } 786 787 /** 788 * Searches for the attribute referenced by its internal id. 789 * 790 * @param attr An attribute reference given to obtainStyledAttributes such as defStyle. 791 * @return A (name, isFramework) pair describing the attribute if found. Returns null 792 * if nothing is found. 793 */ 794 public Pair<String, Boolean> searchAttr(int attr) { 795 Pair<ResourceType, String> info = Bridge.resolveResourceId(attr); 796 if (info != null) { 797 return Pair.of(info.getSecond(), Boolean.TRUE); 798 } 799 800 info = mProjectCallback.resolveResourceId(attr); 801 if (info != null) { 802 return Pair.of(info.getSecond(), Boolean.FALSE); 803 } 804 805 return null; 806 } 807 808 public int getDynamicIdByStyle(StyleResourceValue resValue) { 809 if (mDynamicIdToStyleMap == null) { 810 // create the maps. 811 mDynamicIdToStyleMap = new HashMap<Integer, StyleResourceValue>(); 812 mStyleToDynamicIdMap = new HashMap<StyleResourceValue, Integer>(); 813 } 814 815 // look for an existing id 816 Integer id = mStyleToDynamicIdMap.get(resValue); 817 818 if (id == null) { 819 // generate a new id 820 id = Integer.valueOf(++mDynamicIdGenerator); 821 822 // and add it to the maps. 823 mDynamicIdToStyleMap.put(id, resValue); 824 mStyleToDynamicIdMap.put(resValue, id); 825 } 826 827 return id; 828 } 829 830 private StyleResourceValue getStyleByDynamicId(int i) { 831 if (mDynamicIdToStyleMap != null) { 832 return mDynamicIdToStyleMap.get(i); 833 } 834 835 return null; 836 } 837 838 public int getFrameworkResourceValue(ResourceType resType, String resName, int defValue) { 839 Integer value = Bridge.getResourceId(resType, resName); 840 if (value != null) { 841 return value.intValue(); 842 } 843 844 return defValue; 845 } 846 847 public int getProjectResourceValue(ResourceType resType, String resName, int defValue) { 848 if (mProjectCallback != null) { 849 Integer value = mProjectCallback.getResourceId(resType, resName); 850 if (value != null) { 851 return value.intValue(); 852 } 853 } 854 855 return defValue; 856 } 857 858 //------------ NOT OVERRIDEN -------------------- 859 860 @Override 861 public boolean bindService(Intent arg0, ServiceConnection arg1, int arg2) { 862 // pass 863 return false; 864 } 865 866 @Override 867 public int checkCallingOrSelfPermission(String arg0) { 868 // pass 869 return 0; 870 } 871 872 @Override 873 public int checkCallingOrSelfUriPermission(Uri arg0, int arg1) { 874 // pass 875 return 0; 876 } 877 878 @Override 879 public int checkCallingPermission(String arg0) { 880 // pass 881 return 0; 882 } 883 884 @Override 885 public int checkCallingUriPermission(Uri arg0, int arg1) { 886 // pass 887 return 0; 888 } 889 890 @Override 891 public int checkPermission(String arg0, int arg1, int arg2) { 892 // pass 893 return 0; 894 } 895 896 @Override 897 public int checkUriPermission(Uri arg0, int arg1, int arg2, int arg3) { 898 // pass 899 return 0; 900 } 901 902 @Override 903 public int checkUriPermission(Uri arg0, String arg1, String arg2, int arg3, 904 int arg4, int arg5) { 905 // pass 906 return 0; 907 } 908 909 @Override 910 public void clearWallpaper() { 911 // pass 912 913 } 914 915 @Override 916 public Context createPackageContext(String arg0, int arg1) { 917 // pass 918 return null; 919 } 920 921 @Override 922 public Context createPackageContextAsUser(String arg0, int arg1, UserHandle user) { 923 // pass 924 return null; 925 } 926 927 @Override 928 public Context createConfigurationContext(Configuration overrideConfiguration) { 929 // pass 930 return null; 931 } 932 933 @Override 934 public Context createDisplayContext(Display display) { 935 // pass 936 return null; 937 } 938 939 @Override 940 public String[] databaseList() { 941 // pass 942 return null; 943 } 944 945 @Override 946 public boolean deleteDatabase(String arg0) { 947 // pass 948 return false; 949 } 950 951 @Override 952 public boolean deleteFile(String arg0) { 953 // pass 954 return false; 955 } 956 957 @Override 958 public void enforceCallingOrSelfPermission(String arg0, String arg1) { 959 // pass 960 961 } 962 963 @Override 964 public void enforceCallingOrSelfUriPermission(Uri arg0, int arg1, 965 String arg2) { 966 // pass 967 968 } 969 970 @Override 971 public void enforceCallingPermission(String arg0, String arg1) { 972 // pass 973 974 } 975 976 @Override 977 public void enforceCallingUriPermission(Uri arg0, int arg1, String arg2) { 978 // pass 979 980 } 981 982 @Override 983 public void enforcePermission(String arg0, int arg1, int arg2, String arg3) { 984 // pass 985 986 } 987 988 @Override 989 public void enforceUriPermission(Uri arg0, int arg1, int arg2, int arg3, 990 String arg4) { 991 // pass 992 993 } 994 995 @Override 996 public void enforceUriPermission(Uri arg0, String arg1, String arg2, 997 int arg3, int arg4, int arg5, String arg6) { 998 // pass 999 1000 } 1001 1002 @Override 1003 public String[] fileList() { 1004 // pass 1005 return null; 1006 } 1007 1008 @Override 1009 public AssetManager getAssets() { 1010 // pass 1011 return null; 1012 } 1013 1014 @Override 1015 public File getCacheDir() { 1016 // pass 1017 return null; 1018 } 1019 1020 @Override 1021 public File getExternalCacheDir() { 1022 // pass 1023 return null; 1024 } 1025 1026 @Override 1027 public ContentResolver getContentResolver() { 1028 if (mContentResolver == null) { 1029 mContentResolver = new BridgeContentResolver(this); 1030 } 1031 return mContentResolver; 1032 } 1033 1034 @Override 1035 public File getDatabasePath(String arg0) { 1036 // pass 1037 return null; 1038 } 1039 1040 @Override 1041 public File getDir(String arg0, int arg1) { 1042 // pass 1043 return null; 1044 } 1045 1046 @Override 1047 public File getFileStreamPath(String arg0) { 1048 // pass 1049 return null; 1050 } 1051 1052 @Override 1053 public File getFilesDir() { 1054 // pass 1055 return null; 1056 } 1057 1058 @Override 1059 public File getExternalFilesDir(String type) { 1060 // pass 1061 return null; 1062 } 1063 1064 @Override 1065 public String getPackageCodePath() { 1066 // pass 1067 return null; 1068 } 1069 1070 @Override 1071 public PackageManager getPackageManager() { 1072 // pass 1073 return null; 1074 } 1075 1076 @Override 1077 public String getPackageName() { 1078 // pass 1079 return null; 1080 } 1081 1082 @Override 1083 public String getBasePackageName() { 1084 // pass 1085 return null; 1086 } 1087 1088 @Override 1089 public ApplicationInfo getApplicationInfo() { 1090 return mApplicationInfo; 1091 } 1092 1093 @Override 1094 public String getPackageResourcePath() { 1095 // pass 1096 return null; 1097 } 1098 1099 @Override 1100 public File getSharedPrefsFile(String name) { 1101 // pass 1102 return null; 1103 } 1104 1105 @Override 1106 public SharedPreferences getSharedPreferences(String arg0, int arg1) { 1107 // pass 1108 return null; 1109 } 1110 1111 @Override 1112 public Drawable getWallpaper() { 1113 // pass 1114 return null; 1115 } 1116 1117 @Override 1118 public int getWallpaperDesiredMinimumWidth() { 1119 return -1; 1120 } 1121 1122 @Override 1123 public int getWallpaperDesiredMinimumHeight() { 1124 return -1; 1125 } 1126 1127 @Override 1128 public void grantUriPermission(String arg0, Uri arg1, int arg2) { 1129 // pass 1130 1131 } 1132 1133 @Override 1134 public FileInputStream openFileInput(String arg0) throws FileNotFoundException { 1135 // pass 1136 return null; 1137 } 1138 1139 @Override 1140 public FileOutputStream openFileOutput(String arg0, int arg1) throws FileNotFoundException { 1141 // pass 1142 return null; 1143 } 1144 1145 @Override 1146 public SQLiteDatabase openOrCreateDatabase(String arg0, int arg1, CursorFactory arg2) { 1147 // pass 1148 return null; 1149 } 1150 1151 @Override 1152 public SQLiteDatabase openOrCreateDatabase(String arg0, int arg1, 1153 CursorFactory arg2, DatabaseErrorHandler arg3) { 1154 // pass 1155 return null; 1156 } 1157 1158 @Override 1159 public Drawable peekWallpaper() { 1160 // pass 1161 return null; 1162 } 1163 1164 @Override 1165 public Intent registerReceiver(BroadcastReceiver arg0, IntentFilter arg1) { 1166 // pass 1167 return null; 1168 } 1169 1170 @Override 1171 public Intent registerReceiver(BroadcastReceiver arg0, IntentFilter arg1, 1172 String arg2, Handler arg3) { 1173 // pass 1174 return null; 1175 } 1176 1177 @Override 1178 public Intent registerReceiverAsUser(BroadcastReceiver arg0, UserHandle arg0p5, 1179 IntentFilter arg1, String arg2, Handler arg3) { 1180 // pass 1181 return null; 1182 } 1183 1184 @Override 1185 public void removeStickyBroadcast(Intent arg0) { 1186 // pass 1187 1188 } 1189 1190 @Override 1191 public void revokeUriPermission(Uri arg0, int arg1) { 1192 // pass 1193 1194 } 1195 1196 @Override 1197 public void sendBroadcast(Intent arg0) { 1198 // pass 1199 1200 } 1201 1202 @Override 1203 public void sendBroadcast(Intent arg0, String arg1) { 1204 // pass 1205 1206 } 1207 1208 @Override 1209 public void sendBroadcast(Intent intent, String receiverPermission, int appOp) { 1210 // pass 1211 } 1212 1213 @Override 1214 public void sendOrderedBroadcast(Intent arg0, String arg1) { 1215 // pass 1216 1217 } 1218 1219 @Override 1220 public void sendOrderedBroadcast(Intent arg0, String arg1, 1221 BroadcastReceiver arg2, Handler arg3, int arg4, String arg5, 1222 Bundle arg6) { 1223 // pass 1224 1225 } 1226 1227 @Override 1228 public void sendOrderedBroadcast(Intent intent, String receiverPermission, int appOp, 1229 BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, 1230 String initialData, Bundle initialExtras) { 1231 // pass 1232 } 1233 1234 @Override 1235 public void sendBroadcastAsUser(Intent intent, UserHandle user) { 1236 // pass 1237 } 1238 1239 @Override 1240 public void sendBroadcastAsUser(Intent intent, UserHandle user, 1241 String receiverPermission) { 1242 // pass 1243 } 1244 1245 @Override 1246 public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user, 1247 String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler, 1248 int initialCode, String initialData, Bundle initialExtras) { 1249 // pass 1250 } 1251 1252 @Override 1253 public void sendStickyBroadcast(Intent arg0) { 1254 // pass 1255 1256 } 1257 1258 @Override 1259 public void sendStickyOrderedBroadcast(Intent intent, 1260 BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, 1261 Bundle initialExtras) { 1262 // pass 1263 } 1264 1265 @Override 1266 public void sendStickyBroadcastAsUser(Intent intent, UserHandle user) { 1267 // pass 1268 } 1269 1270 @Override 1271 public void sendStickyOrderedBroadcastAsUser(Intent intent, 1272 UserHandle user, BroadcastReceiver resultReceiver, 1273 Handler scheduler, int initialCode, String initialData, 1274 Bundle initialExtras) { 1275 // pass 1276 } 1277 1278 @Override 1279 public void removeStickyBroadcastAsUser(Intent intent, UserHandle user) { 1280 // pass 1281 } 1282 1283 @Override 1284 public void setTheme(int arg0) { 1285 // pass 1286 1287 } 1288 1289 @Override 1290 public void setWallpaper(Bitmap arg0) throws IOException { 1291 // pass 1292 1293 } 1294 1295 @Override 1296 public void setWallpaper(InputStream arg0) throws IOException { 1297 // pass 1298 1299 } 1300 1301 @Override 1302 public void startActivity(Intent arg0) { 1303 // pass 1304 } 1305 1306 @Override 1307 public void startActivity(Intent arg0, Bundle arg1) { 1308 // pass 1309 } 1310 1311 @Override 1312 public void startIntentSender(IntentSender intent, 1313 Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags) 1314 throws IntentSender.SendIntentException { 1315 // pass 1316 } 1317 1318 @Override 1319 public void startIntentSender(IntentSender intent, 1320 Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags, 1321 Bundle options) throws IntentSender.SendIntentException { 1322 // pass 1323 } 1324 1325 @Override 1326 public boolean startInstrumentation(ComponentName arg0, String arg1, 1327 Bundle arg2) { 1328 // pass 1329 return false; 1330 } 1331 1332 @Override 1333 public ComponentName startService(Intent arg0) { 1334 // pass 1335 return null; 1336 } 1337 1338 @Override 1339 public boolean stopService(Intent arg0) { 1340 // pass 1341 return false; 1342 } 1343 1344 @Override 1345 public ComponentName startServiceAsUser(Intent arg0, UserHandle arg1) { 1346 // pass 1347 return null; 1348 } 1349 1350 @Override 1351 public boolean stopServiceAsUser(Intent arg0, UserHandle arg1) { 1352 // pass 1353 return false; 1354 } 1355 1356 @Override 1357 public void unbindService(ServiceConnection arg0) { 1358 // pass 1359 1360 } 1361 1362 @Override 1363 public void unregisterReceiver(BroadcastReceiver arg0) { 1364 // pass 1365 1366 } 1367 1368 @Override 1369 public Context getApplicationContext() { 1370 return this; 1371 } 1372 1373 @Override 1374 public void startActivities(Intent[] arg0) { 1375 // pass 1376 1377 } 1378 1379 @Override 1380 public void startActivities(Intent[] arg0, Bundle arg1) { 1381 // pass 1382 1383 } 1384 1385 @Override 1386 public boolean isRestricted() { 1387 return false; 1388 } 1389 1390 @Override 1391 public File getObbDir() { 1392 Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED, "OBB not supported", null); 1393 return null; 1394 } 1395 1396 @Override 1397 public CompatibilityInfoHolder getCompatibilityInfo(int displayId) { 1398 // pass 1399 return null; 1400 } 1401 1402 /** 1403 * @hide 1404 */ 1405 @Override 1406 public int getUserId() { 1407 return 0; // not used 1408 } 1409 } 1410