diff options
| -rw-r--r-- | include/utils/ResourceTypes.h | 4 | ||||
| -rw-r--r-- | libs/utils/ResourceTypes.cpp | 134 | ||||
| -rw-r--r-- | services/java/com/android/server/AttributeCache.java | 114 | ||||
| -rw-r--r-- | services/java/com/android/server/PackageManagerService.java | 1 | ||||
| -rw-r--r-- | services/java/com/android/server/am/ActivityManagerService.java | 11 | 
5 files changed, 157 insertions, 107 deletions
| diff --git a/include/utils/ResourceTypes.h b/include/utils/ResourceTypes.h index 5c41ead..eb4151a 100644 --- a/include/utils/ResourceTypes.h +++ b/include/utils/ResourceTypes.h @@ -1441,7 +1441,7 @@ struct ResTable_type   * This is the beginning of information about an entry in the resource   * table.  It holds the reference to the name of this entry, and is   * immediately followed by one of: - *   * A Res_value structures, if FLAG_COMPLEX is -not- set. + *   * A Res_value structure, if FLAG_COMPLEX is -not- set.   *   * An array of ResTable_map structures, if FLAG_COMPLEX is set.   *     These supply a set of name/value mappings of data.   */ @@ -1843,6 +1843,8 @@ private:      status_t parsePackage(          const ResTable_package* const pkg, const Header* const header); +    void print_value(const Package* pkg, const Res_value& value) const; +          mutable Mutex               mLock;      status_t                    mError; diff --git a/libs/utils/ResourceTypes.cpp b/libs/utils/ResourceTypes.cpp index 7a33220..4a5063a 100644 --- a/libs/utils/ResourceTypes.cpp +++ b/libs/utils/ResourceTypes.cpp @@ -3845,7 +3845,7 @@ void print_complex(uint32_t complex, bool isFraction)                              & Res_value::COMPLEX_RADIX_MASK];      printf("%f", value); -    if (isFraction) { +    if (!isFraction) {          switch ((complex>>Res_value::COMPLEX_UNIT_SHIFT)&Res_value::COMPLEX_UNIT_MASK) {              case Res_value::COMPLEX_UNIT_PX: printf("px"); break;              case Res_value::COMPLEX_UNIT_DIP: printf("dp"); break; @@ -3864,6 +3864,49 @@ void print_complex(uint32_t complex, bool isFraction)      }  } +void ResTable::print_value(const Package* pkg, const Res_value& value) const +{ +    if (value.dataType == Res_value::TYPE_NULL) { +        printf("(null)\n"); +    } else if (value.dataType == Res_value::TYPE_REFERENCE) { +        printf("(reference) 0x%08x\n", value.data); +    } else if (value.dataType == Res_value::TYPE_ATTRIBUTE) { +        printf("(attribute) 0x%08x\n", value.data); +    } else if (value.dataType == Res_value::TYPE_STRING) { +        size_t len; +        const char16_t* str = pkg->header->values.stringAt( +                value.data, &len); +        if (str == NULL) { +            printf("(string) null\n"); +        } else { +            printf("(string) \"%s\"\n", +                    String8(str, len).string()); +        }  +    } else if (value.dataType == Res_value::TYPE_FLOAT) { +        printf("(float) %g\n", *(const float*)&value.data); +    } else if (value.dataType == Res_value::TYPE_DIMENSION) { +        printf("(dimension) "); +        print_complex(value.data, false); +        printf("\n"); +    } else if (value.dataType == Res_value::TYPE_FRACTION) { +        printf("(fraction) "); +        print_complex(value.data, true); +        printf("\n"); +    } else if (value.dataType >= Res_value::TYPE_FIRST_COLOR_INT +            || value.dataType <= Res_value::TYPE_LAST_COLOR_INT) { +        printf("(color) #%08x\n", value.data); +    } else if (value.dataType == Res_value::TYPE_INT_BOOLEAN) { +        printf("(boolean) %s\n", value.data ? "true" : "false"); +    } else if (value.dataType >= Res_value::TYPE_FIRST_INT +            || value.dataType <= Res_value::TYPE_LAST_INT) { +        printf("(int) 0x%08x or %d\n", value.data, value.data); +    } else { +        printf("(unknown type) t=0x%02x d=0x%08x (s=0x%04x r=0x%02x)\n", +               (int)value.dataType, (int)value.data, +               (int)value.size, (int)value.res0); +    } +} +  void ResTable::print(bool inclValues) const  {      if (mError != 0) { @@ -3985,27 +4028,31 @@ void ResTable::print(bool inclValues) const                              continue;                          } -                        const Res_value* value = NULL; +                        uint16_t esize = dtohs(ent->size); +                        if ((esize&0x3) != 0) { +                            printf("NON-INTEGER ResTable_entry SIZE: %p\n", (void*)esize); +                            continue; +                        } +                        if ((thisOffset+esize) > typeSize) { +                            printf("ResTable_entry OUT OF BOUNDS: %p+%p+%p (size is %p)\n", +                                   (void*)entriesStart, (void*)thisOffset, +                                   (void*)esize, (void*)typeSize); +                            continue; +                        } +                             +                        const Res_value* valuePtr = NULL; +                        const ResTable_map_entry* bagPtr = NULL; +                        Res_value value;                          if ((dtohs(ent->flags)&ResTable_entry::FLAG_COMPLEX) != 0) {                              printf("<bag>"); +                            bagPtr = (const ResTable_map_entry*)ent;                          } else { -                            uint16_t esize = dtohs(ent->size); -                            if ((esize&0x3) != 0) { -                                printf("NON-INTEGER ResTable_entry SIZE: %p\n", (void*)esize); -                                continue; -                            } -                            if ((thisOffset+esize) > typeSize) { -                                printf("ResTable_entry OUT OF BOUNDS: %p+%p+%p (size is %p)\n", -                                       (void*)entriesStart, (void*)thisOffset, -                                       (void*)esize, (void*)typeSize); -                                continue; -                            } -                             -                            value = (const Res_value*) +                            valuePtr = (const Res_value*)                                  (((const uint8_t*)ent) + esize); +                            value.copyFrom_dtoh(*valuePtr);                              printf("t=0x%02x d=0x%08x (s=0x%04x r=0x%02x)", -                                   (int)value->dataType, (int)dtohl(value->data), -                                   (int)dtohs(value->size), (int)value->res0); +                                   (int)value.dataType, (int)value.data, +                                   (int)value.size, (int)value.res0);                          }                          if ((dtohs(ent->flags)&ResTable_entry::FLAG_PUBLIC) != 0) { @@ -4014,44 +4061,23 @@ void ResTable::print(bool inclValues) const                          printf("\n");                          if (inclValues) { -                            if (value != NULL) { +                            if (valuePtr != NULL) {                                  printf("          "); -                                if (value->dataType == Res_value::TYPE_NULL) { -                                    printf("(null)\n"); -                                } else if (value->dataType == Res_value::TYPE_REFERENCE) { -                                    printf("(reference) 0x%08x\n", value->data); -                                } else if (value->dataType == Res_value::TYPE_ATTRIBUTE) { -                                    printf("(attribute) 0x%08x\n", value->data); -                                } else if (value->dataType == Res_value::TYPE_STRING) { -                                    size_t len; -                                    const char16_t* str = pkg->header->values.stringAt( -                                            value->data, &len); -                                    if (str == NULL) { -                                        printf("(string) null\n"); -                                    } else { -                                        printf("(string) \"%s\"\n", -                                                String8(str, len).string()); -                                    }  -                                } else if (value->dataType == Res_value::TYPE_FLOAT) { -                                    printf("(float) %g\n", *(const float*)&value->data); -                                } else if (value->dataType == Res_value::TYPE_DIMENSION) { -                                    printf("(dimension) "); -                                    print_complex(value->data, false); -                                    printf("\n"); -                                } else if (value->dataType == Res_value::TYPE_FRACTION) { -                                    printf("(fraction) "); -                                    print_complex(value->data, true); -                                    printf("\n"); -                                } else if (value->dataType >= Res_value::TYPE_FIRST_COLOR_INT -                                        || value->dataType <= Res_value::TYPE_LAST_COLOR_INT) { -                                    printf("(color) #%08x\n", value->data); -                                } else if (value->dataType == Res_value::TYPE_INT_BOOLEAN) { -                                    printf("(boolean) %s\n", value->data ? "true" : "false"); -                                } else if (value->dataType >= Res_value::TYPE_FIRST_INT -                                        || value->dataType <= Res_value::TYPE_LAST_INT) { -                                    printf("(int) 0x%08x or %d\n", value->data, value->data); -                                } else { -                                    printf("(unknown type)\n"); +                                print_value(pkg, value); +                            } else if (bagPtr != NULL) { +                                const int N = dtohl(bagPtr->count); +                                const ResTable_map* mapPtr = (const ResTable_map*) +                                        (((const uint8_t*)ent) + esize); +                                printf("          Parent=0x%08x, Count=%d\n", +                                    dtohl(bagPtr->parent.ident), N); +                                for (int i=0; i<N; i++) { +                                    printf("          #%i (Key=0x%08x): ", +                                        i, dtohl(mapPtr->name.ident)); +                                    value.copyFrom_dtoh(mapPtr->value); +                                    print_value(pkg, value); +                                    const size_t size = dtohs(mapPtr->value.size); +                                    mapPtr = (ResTable_map*)(((const uint8_t*)mapPtr) +                                            + size + sizeof(*mapPtr)-sizeof(mapPtr->value));                                  }                              }                          } diff --git a/services/java/com/android/server/AttributeCache.java b/services/java/com/android/server/AttributeCache.java index 459ae52..81378dc 100644 --- a/services/java/com/android/server/AttributeCache.java +++ b/services/java/com/android/server/AttributeCache.java @@ -17,56 +17,36 @@  package com.android.server; -import android.content.ComponentName; -import android.content.ContentResolver;  import android.content.Context; -import android.content.SharedPreferences; -import android.content.Intent; -import android.content.BroadcastReceiver; +import android.content.pm.ActivityInfo;  import android.content.pm.PackageManager; +import android.content.res.Configuration;  import android.content.res.Resources;  import android.content.res.TypedArray; -import android.provider.Settings; -import android.util.Config; -import android.util.Log; +import android.util.SparseArray; +import java.util.HashMap;  import java.util.WeakHashMap; -public final class AttributeCache extends BroadcastReceiver { +/** + * TODO: This should be better integrated into the system so it doesn't need + * special calls from the activity manager to clear it. + */ +public final class AttributeCache {      private static AttributeCache sInstance = null;      private final Context mContext; -    private final WeakHashMap<Key, Entry> mMap = -            new WeakHashMap<Key, Entry>(); -    private final WeakHashMap<String, Context> mContexts = -            new WeakHashMap<String, Context>(); +    private final WeakHashMap<String, Package> mPackages = +            new WeakHashMap<String, Package>(); +    private final Configuration mConfiguration = new Configuration(); -    final static class Key { -        public final String packageName; -        public final int resId; -        public final int[] styleable; -         -        public Key(String inPackageName, int inResId, int[] inStyleable) { -            packageName = inPackageName; -            resId = inResId; -            styleable = inStyleable; -        } +    public final static class Package { +        public final Context context; +        private final SparseArray<HashMap<int[], Entry>> mMap +                = new SparseArray<HashMap<int[], Entry>>(); -        @Override public boolean equals(Object obj) { -            try { -                if (obj != null) { -                    Key other = (Key)obj; -                    return packageName.equals(other.packageName) -                            && resId == other.resId -                            && styleable == other.styleable; -                } -            } catch (ClassCastException e) { -            } -            return false; -        } - -        @Override public int hashCode() { -            return packageName.hashCode() + resId; +        public Package(Context c) { +            context = c;          }      } @@ -94,36 +74,68 @@ public final class AttributeCache extends BroadcastReceiver {          mContext = context;      } -    public Entry get(String packageName, int resId, int[] styleable) { +    public void removePackage(String packageName) {          synchronized (this) { -            Key key = new Key(packageName, resId, styleable); -            Entry ent = mMap.get(key); -            if (ent != null) { -                return ent; +            mPackages.remove(packageName); +        } +    } +     +    public void updateConfiguration(Configuration config) { +        synchronized (this) { +            int changes = mConfiguration.updateFrom(config); +            if ((changes & ~(ActivityInfo.CONFIG_FONT_SCALE | +                    ActivityInfo.CONFIG_KEYBOARD_HIDDEN | +                    ActivityInfo.CONFIG_ORIENTATION)) != 0) { +                // The configurations being masked out are ones that commonly +                // change so we don't want flushing the cache... all others +                // will flush the cache. +                mPackages.clear();              } -            Context context = mContexts.get(packageName); -            if (context == null) { +        } +    } +     +    public Entry get(String packageName, int resId, int[] styleable) { +        synchronized (this) { +            Package pkg = mPackages.get(packageName); +            HashMap<int[], Entry> map = null; +            Entry ent = null; +            if (pkg != null) { +                map = pkg.mMap.get(resId); +                if (map != null) { +                    ent = map.get(styleable); +                    if (ent != null) { +                        return ent; +                    } +                } +            } else { +                Context context;                  try {                      context = mContext.createPackageContext(packageName, 0);                      if (context == null) {                          return null;                      } -                    mContexts.put(packageName, context);                  } catch (PackageManager.NameNotFoundException e) {                      return null;                  } +                pkg = new Package(context); +                mPackages.put(packageName, pkg);              } +             +            if (map == null) { +                map = new HashMap<int[], Entry>(); +                pkg.mMap.put(resId, map); +            } +                          try { -                ent = new Entry(context, -                        context.obtainStyledAttributes(resId, styleable)); -                mMap.put(key, ent); +                ent = new Entry(pkg.context, +                        pkg.context.obtainStyledAttributes(resId, styleable)); +                map.put(styleable, ent);              } catch (Resources.NotFoundException e) {                  return null;              } +                          return ent;          }      } -    @Override public void onReceive(Context context, Intent intent) { -    }  } diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java index 972aa98..4ea2831 100644 --- a/services/java/com/android/server/PackageManagerService.java +++ b/services/java/com/android/server/PackageManagerService.java @@ -3292,6 +3292,7 @@ class PackageManagerService extends IPackageManager.Stub {                  if (extras != null) {                      intent.putExtras(extras);                  } +                intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);                  am.broadcastIntent(                      null, intent,                              null, null, 0, null, null, null, false, false); diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index 6d04b6b..f716571 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -17,6 +17,7 @@  package com.android.server.am;  import com.android.internal.os.BatteryStatsImpl; +import com.android.server.AttributeCache;  import com.android.server.IntentResolver;  import com.android.server.ProcessMap;  import com.android.server.ProcessStats; @@ -61,7 +62,6 @@ import android.content.pm.ServiceInfo;  import android.content.res.Configuration;  import android.graphics.Bitmap;  import android.net.Uri; -import android.os.BatteryStats;  import android.os.Binder;  import android.os.Bundle;  import android.os.Environment; @@ -10715,6 +10715,10 @@ public final class ActivityManagerService extends ActivityManagerNative implemen                          if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {                              uninstallPackageLocked(ssp,                                      intent.getIntExtra(Intent.EXTRA_UID, -1), false); +                            AttributeCache ac = AttributeCache.instance(); +                            if (ac != null) { +                                ac.removePackage(ssp); +                            }                          }                      }                  } @@ -11765,6 +11769,11 @@ public final class ActivityManagerService extends ActivityManagerNative implemen                  Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);                  broadcastIntentLocked(null, null, intent, null, null, 0, null, null,                          null, false, false, MY_PID, Process.SYSTEM_UID); +                 +                AttributeCache ac = AttributeCache.instance(); +                if (ac != null) { +                    ac.updateConfiguration(mConfiguration); +                }              }          } | 
