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