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