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