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