Search in sources :

Example 41 with LongSparseArray

use of android.util.LongSparseArray in project AndroidLife by CaMnter.

the class MonkeyPatcher method pruneResourceCache.

/**
 * 如果 < 6.0 会删除
 * ResourcesImpl 内的   mDrawableCache、mColorDrawableCache、mColorStateListCache 资源缓存
 * 同时,如果还是 4.3 的话,会额外删除
 * Resources 内的   sPreloadedDrawables、sPreloadedColorDrawables、sPreloadedColorStateLists
 * 资源缓存
 *
 * @param resources ResourcesImpl or Resources
 * @param fieldName 以上 field name
 * @return 是否清空
 */
private static boolean pruneResourceCache(@NonNull Object resources, @NonNull String fieldName) {
    try {
        /**
         * Step 1
         *
         * 从 ResourcesImpl or Resources 拿到对应的 fieldName 的 Field
         *
         * 当然,如果 ResourcesImpl 获取失败了,会 catch 。
         * 然后直接 Resources.class.getDeclaredField(fieldName) 去拿 Field
         */
        Class<?> resourcesClass = resources.getClass();
        Field cacheField;
        try {
            cacheField = resourcesClass.getDeclaredField(fieldName);
        } catch (NoSuchFieldException ignore) {
            cacheField = Resources.class.getDeclaredField(fieldName);
        }
        cacheField.setAccessible(true);
        Object cache = cacheField.get(resources);
        /**
         * Step 2
         *
         * 上面拿到的 Field
         * 然后判断 Field 的类型:
         *
         * 1 如果 < 4.1,有两种选择:
         *     1.1 如果属于 SparseArray 类型,直接 clear 清空,返回 true
         *     1.2 如果 => 4.0 并且 属于 LongSparseArray,也是直接 clear 清空,返回 true
         *
         * 2 如果 4.1 < x < 6.0,有四种选择:
         *     2.1 如果 Field 是 mColorStateListCache,并且属于 LongSparseArray,也是直接 clear 清空
         *     2.2 如果 Field 的类型实现了 ArrayMap 的超类( Map ),然后反射调用 Resource clearDrawableCachesLocked 方法
         *     2.3 如果 Field 是类型实现了 LongSparseArray 的超类 ( Cloneable ? ),然后反射调用 Resource clearDrawableCachesLocked 方法
         *         注: 2.2 与 2.3 的区别在于 clearDrawableCachesLocked 的参数不一样,一个是 ArrayMap,一个是 LongSparseArray
         *
         *     2.4 如果 Field 是类型实现是 数组类型,并且数组的 class 类型( getComponentType ) 实现了 LongSparseArray 的超类 ( Cloneable ? )
         *         然后强转为 LongSparseArray[] 类型,一个一个拿出 LongSparseArray,然后 clear
         *
         * 3. 如果 >= 6.0 ( 主要针对 Marshmallow: DrawableCache class )
         *    反射拿到该 Field 的 onConfigurationChange 的方法并且调用
         *      如果有就返回
         *      如果没有的话,继续拿到父类,继续反射拿到 onConfigurationChange 的方法并且调用。直到调用过一次 onConfigurationChange 为止
         *
         * 4. 如果 1-3 内又没一个选择的话,那么就是没有做任何 删除资源缓存操作 or 删除资源缓存失败了
         */
        // Find the class which defines the onConfigurationChange method
        Class<?> type = cacheField.getType();
        if (SDK_INT < JELLY_BEAN) {
            if (cache instanceof SparseArray) {
                ((SparseArray) cache).clear();
                return true;
            } else if (SDK_INT >= ICE_CREAM_SANDWICH && cache instanceof LongSparseArray) {
                // LongSparseArray has API level 16 but was private (and available inside
                // the framework) in 15 and is used for this cache.
                // noinspection AndroidLintNewApi
                ((LongSparseArray) cache).clear();
                return true;
            }
        } else if (SDK_INT < M) {
            // JellyBean, KitKat, Lollipop
            if ("mColorStateListCache".equals(fieldName)) {
                // this field
                if (cache instanceof LongSparseArray) {
                    // noinspection AndroidLintNewApi
                    ((LongSparseArray) cache).clear();
                }
            } else if (type.isAssignableFrom(ArrayMap.class)) {
                Method clearArrayMap = Resources.class.getDeclaredMethod("clearDrawableCachesLocked", ArrayMap.class, Integer.TYPE);
                clearArrayMap.setAccessible(true);
                clearArrayMap.invoke(resources, cache, -1);
                return true;
            } else if (type.isAssignableFrom(LongSparseArray.class)) {
                try {
                    Method clearSparseMap = Resources.class.getDeclaredMethod("clearDrawableCachesLocked", LongSparseArray.class, Integer.TYPE);
                    clearSparseMap.setAccessible(true);
                    clearSparseMap.invoke(resources, cache, -1);
                    return true;
                } catch (NoSuchMethodException e) {
                    if (cache instanceof LongSparseArray) {
                        // noinspection AndroidLintNewApi
                        ((LongSparseArray) cache).clear();
                        return true;
                    }
                }
            } else if (type.isArray() && type.getComponentType().isAssignableFrom(LongSparseArray.class)) {
                LongSparseArray[] arrays = (LongSparseArray[]) cache;
                for (LongSparseArray array : arrays) {
                    if (array != null) {
                        // noinspection AndroidLintNewApi
                        array.clear();
                    }
                }
                return true;
            }
        } else {
            // Marshmallow: DrawableCache class
            while (type != null) {
                try {
                    Method configChangeMethod = type.getDeclaredMethod("onConfigurationChange", Integer.TYPE);
                    configChangeMethod.setAccessible(true);
                    configChangeMethod.invoke(cache, -1);
                    return true;
                } catch (Throwable ignore) {
                }
                type = type.getSuperclass();
            }
        }
    } catch (Throwable ignore) {
    // Not logging these; while there is some checking of SDK_INT here to avoid
    // doing a lot of unnecessary field lookups, it's not entirely accurate and
    // errs on the side of caution (since different devices may have picked up
    // different snapshots of the framework); therefore, it's normal for this
    // to attempt to look up a field for a cache that isn't there; only if it's
    // really there will it continue to flush that particular cache.
    }
    return false;
}
Also used : Field(java.lang.reflect.Field) SparseArray(android.util.SparseArray) LongSparseArray(android.util.LongSparseArray) LongSparseArray(android.util.LongSparseArray) Method(java.lang.reflect.Method) Resources(android.content.res.Resources)

Example 42 with LongSparseArray

use of android.util.LongSparseArray in project Douya by DreaminginCodeZH.

the class ResourcesFlusher method flushThemedResourceCache.

@MainThread
@RequiresApi(Build.VERSION_CODES.M)
@SuppressLint("PrivateApi")
private static void flushThemedResourceCache(@NonNull Object themedResourceCache) {
    if (!sThemedResourceCacheClassInitialized) {
        try {
            sThemedResourceCacheClass = Class.forName("android.content.res.ThemedResourceCache");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        sThemedResourceCacheClassInitialized = true;
    }
    if (sThemedResourceCacheClass == null) {
        return;
    }
    if (!sThemedResourceCacheMThemedEntriesFieldInitialized) {
        try {
            sThemedResourceCacheMThemedEntriesField = sThemedResourceCacheClass.getDeclaredField("mThemedEntries");
            sThemedResourceCacheMThemedEntriesField.setAccessible(true);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
        sThemedResourceCacheMThemedEntriesFieldInitialized = true;
    }
    if (sThemedResourceCacheMThemedEntriesField != null) {
        ArrayMap themedEntries = null;
        try {
            themedEntries = (ArrayMap) sThemedResourceCacheMThemedEntriesField.get(themedResourceCache);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        if (themedEntries != null) {
            themedEntries.clear();
        }
    }
    if (!sThemedResourceCacheMUnthemedEntriesFieldInitialized) {
        try {
            sThemedResourceCacheMUnthemedEntriesField = sThemedResourceCacheClass.getDeclaredField("mUnthemedEntries");
            sThemedResourceCacheMUnthemedEntriesField.setAccessible(true);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
        sThemedResourceCacheMUnthemedEntriesFieldInitialized = true;
    }
    if (sThemedResourceCacheMUnthemedEntriesField != null) {
        LongSparseArray unthemedEntries = null;
        try {
            unthemedEntries = (LongSparseArray) sThemedResourceCacheMUnthemedEntriesField.get(themedResourceCache);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        if (unthemedEntries != null) {
            unthemedEntries.clear();
        }
    }
    if (!sThemedResourceCacheMNullThemedEntriesFieldInitialized) {
        try {
            sThemedResourceCacheMNullThemedEntriesField = sThemedResourceCacheClass.getDeclaredField("mNullThemedEntries");
            sThemedResourceCacheMNullThemedEntriesField.setAccessible(true);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
        sThemedResourceCacheMNullThemedEntriesFieldInitialized = true;
    }
    if (sThemedResourceCacheMNullThemedEntriesField != null) {
        LongSparseArray nullThemedEntries = null;
        try {
            nullThemedEntries = (LongSparseArray) sThemedResourceCacheMNullThemedEntriesField.get(themedResourceCache);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        if (nullThemedEntries != null) {
            nullThemedEntries.clear();
        }
    }
}
Also used : LongSparseArray(android.util.LongSparseArray) ArrayMap(android.util.ArrayMap) MainThread(androidx.annotation.MainThread) RequiresApi(androidx.annotation.RequiresApi) SuppressLint(android.annotation.SuppressLint)

Example 43 with LongSparseArray

use of android.util.LongSparseArray in project robolectric by robolectric.

the class ShadowAppOpsManager method toOpEntry.

protected OpEntry toOpEntry(Integer op, int mode) {
    if (RuntimeEnvironment.getApiLevel() < Build.VERSION_CODES.M) {
        return ReflectionHelpers.callConstructor(OpEntry.class, ClassParameter.from(int.class, op), ClassParameter.from(int.class, mode), ClassParameter.from(long.class, OP_TIME), ClassParameter.from(long.class, REJECT_TIME), ClassParameter.from(int.class, DURATION));
    } else if (RuntimeEnvironment.getApiLevel() < Build.VERSION_CODES.Q) {
        return ReflectionHelpers.callConstructor(OpEntry.class, ClassParameter.from(int.class, op), ClassParameter.from(int.class, mode), ClassParameter.from(long.class, OP_TIME), ClassParameter.from(long.class, REJECT_TIME), ClassParameter.from(int.class, DURATION), ClassParameter.from(int.class, PROXY_UID), ClassParameter.from(String.class, PROXY_PACKAGE));
    } else if (RuntimeEnvironment.getApiLevel() < Build.VERSION_CODES.R) {
        final long key = AppOpsManager.makeKey(AppOpsManager.UID_STATE_TOP, AppOpsManager.OP_FLAG_SELF);
        final LongSparseLongArray accessTimes = new LongSparseLongArray();
        accessTimes.put(key, OP_TIME);
        final LongSparseLongArray rejectTimes = new LongSparseLongArray();
        rejectTimes.put(key, REJECT_TIME);
        final LongSparseLongArray durations = new LongSparseLongArray();
        durations.put(key, DURATION);
        final LongSparseLongArray proxyUids = new LongSparseLongArray();
        proxyUids.put(key, PROXY_UID);
        final LongSparseArray<String> proxyPackages = new LongSparseArray<>();
        proxyPackages.put(key, PROXY_PACKAGE);
        return ReflectionHelpers.callConstructor(OpEntry.class, ClassParameter.from(int.class, op), ClassParameter.from(boolean.class, false), ClassParameter.from(int.class, mode), ClassParameter.from(LongSparseLongArray.class, accessTimes), ClassParameter.from(LongSparseLongArray.class, rejectTimes), ClassParameter.from(LongSparseLongArray.class, durations), ClassParameter.from(LongSparseLongArray.class, proxyUids), ClassParameter.from(LongSparseArray.class, proxyPackages));
    } else {
        final long key = AppOpsManager.makeKey(AppOpsManager.UID_STATE_TOP, AppOpsManager.OP_FLAG_SELF);
        LongSparseArray<NoteOpEvent> accessEvents = new LongSparseArray<>();
        LongSparseArray<NoteOpEvent> rejectEvents = new LongSparseArray<>();
        accessEvents.put(key, new NoteOpEvent(OP_TIME, DURATION, new OpEventProxyInfo(PROXY_UID, PROXY_PACKAGE, null)));
        rejectEvents.put(key, new NoteOpEvent(REJECT_TIME, -1, null));
        return new OpEntry(op, mode, Collections.singletonMap(null, new AttributedOpEntry(op, false, accessEvents, rejectEvents)));
    }
}
Also used : LongSparseLongArray(android.util.LongSparseLongArray) LongSparseArray(android.util.LongSparseArray) NoteOpEvent(android.app.AppOpsManager.NoteOpEvent) AttributedOpEntry(android.app.AppOpsManager.AttributedOpEntry) OpEntry(android.app.AppOpsManager.OpEntry) OpEventProxyInfo(android.app.AppOpsManager.OpEventProxyInfo) AttributedOpEntry(android.app.AppOpsManager.AttributedOpEntry)

Example 44 with LongSparseArray

use of android.util.LongSparseArray in project robolectric by robolectric.

the class ShadowResourcesImpl method obtainResettableArrays.

private static List<LongSparseArray<?>> obtainResettableArrays() {
    List<LongSparseArray<?>> resettableArrays = new ArrayList<>();
    Field[] allFields = Resources.class.getDeclaredFields();
    for (Field field : allFields) {
        if (Modifier.isStatic(field.getModifiers()) && field.getType().equals(LongSparseArray.class)) {
            field.setAccessible(true);
            try {
                LongSparseArray<?> longSparseArray = (LongSparseArray<?>) field.get(null);
                if (longSparseArray != null) {
                    resettableArrays.add(longSparseArray);
                }
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            }
        }
    }
    return resettableArrays;
}
Also used : Field(java.lang.reflect.Field) LongSparseArray(android.util.LongSparseArray) ArrayList(java.util.ArrayList)

Example 45 with LongSparseArray

use of android.util.LongSparseArray in project Resurrection_packages_apps_Settings by ResurrectionRemix.

the class ProcStatsData method getProcs.

private ArrayList<ProcStatsEntry> getProcs(ProcessDataCollection bgTotals, ProcessDataCollection runTotals) {
    final ArrayList<ProcStatsEntry> procEntries = new ArrayList<>();
    if (DEBUG)
        Log.d(TAG, "-------------------- PULLING PROCESSES");
    final ProcessMap<ProcStatsEntry> entriesMap = new ProcessMap<ProcStatsEntry>();
    for (int ipkg = 0, N = mStats.mPackages.getMap().size(); ipkg < N; ipkg++) {
        final SparseArray<LongSparseArray<ProcessStats.PackageState>> pkgUids = mStats.mPackages.getMap().valueAt(ipkg);
        for (int iu = 0; iu < pkgUids.size(); iu++) {
            final LongSparseArray<ProcessStats.PackageState> vpkgs = pkgUids.valueAt(iu);
            for (int iv = 0; iv < vpkgs.size(); iv++) {
                final ProcessStats.PackageState st = vpkgs.valueAt(iv);
                for (int iproc = 0; iproc < st.mProcesses.size(); iproc++) {
                    final ProcessState pkgProc = st.mProcesses.valueAt(iproc);
                    final ProcessState proc = mStats.mProcesses.get(pkgProc.getName(), pkgProc.getUid());
                    if (proc == null) {
                        Log.w(TAG, "No process found for pkg " + st.mPackageName + "/" + st.mUid + " proc name " + pkgProc.getName());
                        continue;
                    }
                    ProcStatsEntry ent = entriesMap.get(proc.getName(), proc.getUid());
                    if (ent == null) {
                        ent = new ProcStatsEntry(proc, st.mPackageName, bgTotals, runTotals, mUseUss);
                        if (ent.mRunWeight > 0) {
                            if (DEBUG)
                                Log.d(TAG, "Adding proc " + proc.getName() + "/" + proc.getUid() + ": time=" + ProcessStatsUi.makeDuration(ent.mRunDuration) + " (" + ((((double) ent.mRunDuration) / memTotalTime) * 100) + "%)" + " pss=" + ent.mAvgRunMem);
                            entriesMap.put(proc.getName(), proc.getUid(), ent);
                            procEntries.add(ent);
                        }
                    } else {
                        ent.addPackage(st.mPackageName);
                    }
                }
            }
        }
    }
    if (DEBUG)
        Log.d(TAG, "-------------------- MAPPING SERVICES");
    // Add in service info.
    for (int ip = 0, N = mStats.mPackages.getMap().size(); ip < N; ip++) {
        SparseArray<LongSparseArray<ProcessStats.PackageState>> uids = mStats.mPackages.getMap().valueAt(ip);
        for (int iu = 0; iu < uids.size(); iu++) {
            LongSparseArray<ProcessStats.PackageState> vpkgs = uids.valueAt(iu);
            for (int iv = 0; iv < vpkgs.size(); iv++) {
                ProcessStats.PackageState ps = vpkgs.valueAt(iv);
                for (int is = 0, NS = ps.mServices.size(); is < NS; is++) {
                    ServiceState ss = ps.mServices.valueAt(is);
                    if (ss.getProcessName() != null) {
                        ProcStatsEntry ent = entriesMap.get(ss.getProcessName(), uids.keyAt(iu));
                        if (ent != null) {
                            if (DEBUG)
                                Log.d(TAG, "Adding service " + ps.mPackageName + "/" + ss.getName() + "/" + uids.keyAt(iu) + " to proc " + ss.getProcessName());
                            ent.addService(ss);
                        } else {
                            Log.w(TAG, "No process " + ss.getProcessName() + "/" + uids.keyAt(iu) + " for service " + ss.getName());
                        }
                    }
                }
            }
        }
    }
    return procEntries;
}
Also used : LongSparseArray(android.util.LongSparseArray) IProcessStats(com.android.internal.app.procstats.IProcessStats) ProcessStats(com.android.internal.app.procstats.ProcessStats) ServiceState(com.android.internal.app.procstats.ServiceState) ArrayList(java.util.ArrayList) ProcessState(com.android.internal.app.procstats.ProcessState) ProcessMap(com.android.internal.app.ProcessMap)

Aggregations

LongSparseArray (android.util.LongSparseArray)46 Field (java.lang.reflect.Field)23 ArrayList (java.util.ArrayList)12 Parcelable (android.os.Parcelable)7 Editable (android.text.Editable)7 View (android.view.View)7 PendingHostUpdate (android.appwidget.PendingHostUpdate)5 ParceledListSlice (android.content.pm.ParceledListSlice)5 Point (android.graphics.Point)5 IAppWidgetHost (com.android.internal.appwidget.IAppWidgetHost)5 Resources (android.content.res.Resources)4 SparseArray (android.util.SparseArray)4 Method (java.lang.reflect.Method)4 ContactEntry (com.android.contacts.common.list.ContactEntry)2 ProcessMap (com.android.internal.app.ProcessMap)2 IProcessStats (com.android.internal.app.procstats.IProcessStats)2 ProcessState (com.android.internal.app.procstats.ProcessState)2 ProcessStats (com.android.internal.app.procstats.ProcessStats)2 ServiceState (com.android.internal.app.procstats.ServiceState)2 Element (de.westnordost.osmapi.map.data.Element)2