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