Loading include/utils/ResourceTypes.h +3 −1 Original line number Diff line number Diff line Loading @@ -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. */ Loading Loading @@ -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; Loading libs/utils/ResourceTypes.cpp +80 −54 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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) { Loading Loading @@ -3985,10 +4028,6 @@ void ResTable::print(bool inclValues) const continue; } const Res_value* value = NULL; if ((dtohs(ent->flags)&ResTable_entry::FLAG_COMPLEX) != 0) { printf("<bag>"); } else { uint16_t esize = dtohs(ent->size); if ((esize&0x3) != 0) { printf("NON-INTEGER ResTable_entry SIZE: %p\n", (void*)esize); Loading @@ -4001,11 +4040,19 @@ void ResTable::print(bool inclValues) const continue; } value = (const Res_value*) 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 { 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) { Loading @@ -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)); } } } Loading services/java/com/android/server/AttributeCache.java +63 −51 Original line number Diff line number Diff line Loading @@ -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>(); 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; } private final WeakHashMap<String, Package> mPackages = new WeakHashMap<String, Package>(); private final Configuration mConfiguration = new Configuration(); @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; } public final static class Package { public final Context context; private final SparseArray<HashMap<int[], Entry>> mMap = new SparseArray<HashMap<int[], Entry>>(); @Override public int hashCode() { return packageName.hashCode() + resId; public Package(Context c) { context = c; } } Loading Loading @@ -94,36 +74,68 @@ public final class AttributeCache extends BroadcastReceiver { mContext = context; } public void removePackage(String packageName) { synchronized (this) { 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(); } } } public Entry get(String packageName, int resId, int[] styleable) { synchronized (this) { Key key = new Key(packageName, resId, styleable); Entry ent = mMap.get(key); 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; } Context context = mContexts.get(packageName); if (context == null) { } } 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) { } } services/java/com/android/server/PackageManagerService.java +1 −0 Original line number Diff line number Diff line Loading @@ -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); Loading services/java/com/android/server/am/ActivityManagerService.java +10 −1 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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); } } } } Loading Loading @@ -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); } } } Loading Loading
include/utils/ResourceTypes.h +3 −1 Original line number Diff line number Diff line Loading @@ -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. */ Loading Loading @@ -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; Loading
libs/utils/ResourceTypes.cpp +80 −54 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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) { Loading Loading @@ -3985,10 +4028,6 @@ void ResTable::print(bool inclValues) const continue; } const Res_value* value = NULL; if ((dtohs(ent->flags)&ResTable_entry::FLAG_COMPLEX) != 0) { printf("<bag>"); } else { uint16_t esize = dtohs(ent->size); if ((esize&0x3) != 0) { printf("NON-INTEGER ResTable_entry SIZE: %p\n", (void*)esize); Loading @@ -4001,11 +4040,19 @@ void ResTable::print(bool inclValues) const continue; } value = (const Res_value*) 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 { 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) { Loading @@ -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)); } } } Loading
services/java/com/android/server/AttributeCache.java +63 −51 Original line number Diff line number Diff line Loading @@ -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>(); 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; } private final WeakHashMap<String, Package> mPackages = new WeakHashMap<String, Package>(); private final Configuration mConfiguration = new Configuration(); @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; } public final static class Package { public final Context context; private final SparseArray<HashMap<int[], Entry>> mMap = new SparseArray<HashMap<int[], Entry>>(); @Override public int hashCode() { return packageName.hashCode() + resId; public Package(Context c) { context = c; } } Loading Loading @@ -94,36 +74,68 @@ public final class AttributeCache extends BroadcastReceiver { mContext = context; } public void removePackage(String packageName) { synchronized (this) { 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(); } } } public Entry get(String packageName, int resId, int[] styleable) { synchronized (this) { Key key = new Key(packageName, resId, styleable); Entry ent = mMap.get(key); 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; } Context context = mContexts.get(packageName); if (context == null) { } } 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) { } }
services/java/com/android/server/PackageManagerService.java +1 −0 Original line number Diff line number Diff line Loading @@ -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); Loading
services/java/com/android/server/am/ActivityManagerService.java +10 −1 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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); } } } } Loading Loading @@ -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); } } } Loading