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