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