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