Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b58e5ae9 authored by Josh Guilfoyle's avatar Josh Guilfoyle
Browse files

Asset redirections are now managed by a system service.

Adjusted the asset redirection design to use a common system service
(AssetRedirectionManagerService) for synchronization and cache
management.  This replaces the old /data/res-cache design completely
(nothing is written to disk now).

This change also moves a large amount of code from the C++ layer to Java
for parsing the theme meta data and redirection XML files, though the
actual redirection still occurs at the native layer.

Change-Id: I8820e39425135269f5e723534c4b9c8dc6841779
parent cc45a6dc
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -153,6 +153,7 @@ LOCAL_SRC_FILES += \
	core/java/com/android/internal/app/IBatteryStats.aidl \
	core/java/com/android/internal/app/IBatteryStats.aidl \
	core/java/com/android/internal/app/IUsageStats.aidl \
	core/java/com/android/internal/app/IUsageStats.aidl \
	core/java/com/android/internal/app/IMediaContainerService.aidl \
	core/java/com/android/internal/app/IMediaContainerService.aidl \
	core/java/com/android/internal/app/IAssetRedirectionManager.aidl \
	core/java/com/android/internal/appwidget/IAppWidgetService.aidl \
	core/java/com/android/internal/appwidget/IAppWidgetService.aidl \
	core/java/com/android/internal/appwidget/IAppWidgetHost.aidl \
	core/java/com/android/internal/appwidget/IAppWidgetHost.aidl \
	core/java/com/android/internal/backup/IBackupTransport.aidl \
	core/java/com/android/internal/backup/IBackupTransport.aidl \
+62 −51
Original line number Original line Diff line number Diff line
@@ -17,6 +17,7 @@


package android.app;
package android.app;


import com.android.internal.app.IAssetRedirectionManager;
import com.android.internal.os.BinderInternal;
import com.android.internal.os.BinderInternal;
import com.android.internal.os.RuntimeInit;
import com.android.internal.os.RuntimeInit;
import com.android.internal.os.SamplingProfilerIntegration;
import com.android.internal.os.SamplingProfilerIntegration;
@@ -41,11 +42,11 @@ import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager;
import android.content.pm.ProviderInfo;
import android.content.pm.ProviderInfo;
import android.content.pm.ServiceInfo;
import android.content.pm.ServiceInfo;
import android.content.pm.ThemeInfo;
import android.content.res.AssetManager;
import android.content.res.AssetManager;
import android.content.res.CompatibilityInfo;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.content.res.Configuration;
import android.content.res.CustomTheme;
import android.content.res.CustomTheme;
import android.content.res.PackageRedirectionMap;
import android.content.res.Resources;
import android.content.res.Resources;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDebug;
import android.database.sqlite.SQLiteDebug;
@@ -138,6 +139,7 @@ public final class ActivityThread {
    static ContextImpl mSystemContext = null;
    static ContextImpl mSystemContext = null;


    static IPackageManager sPackageManager;
    static IPackageManager sPackageManager;
    static IAssetRedirectionManager sAssetRedirectionManager;


    final ApplicationThread mAppThread = new ApplicationThread();
    final ApplicationThread mAppThread = new ApplicationThread();
    final Looper mLooper = Looper.myLooper();
    final Looper mLooper = Looper.myLooper();
@@ -1145,6 +1147,18 @@ public final class ActivityThread {
        return sPackageManager;
        return sPackageManager;
    }
    }


    // NOTE: this method can return null if the SystemServer is still
    // initializing (for example, of another SystemServer component is accessing
    // a resources object)
    public static IAssetRedirectionManager getAssetRedirectionManager() {
        if (sAssetRedirectionManager != null) {
            return sAssetRedirectionManager;
        }
        IBinder b = ServiceManager.getService("assetredirection");
        sAssetRedirectionManager = IAssetRedirectionManager.Stub.asInterface(b);
        return sAssetRedirectionManager;
    }

    DisplayMetrics getDisplayMetricsLocked(boolean forceUpdate) {
    DisplayMetrics getDisplayMetricsLocked(boolean forceUpdate) {
        if (mDisplayMetrics != null && !forceUpdate) {
        if (mDisplayMetrics != null && !forceUpdate) {
            return mDisplayMetrics;
            return mDisplayMetrics;
@@ -1237,6 +1251,17 @@ public final class ActivityThread {
        }
        }
    }
    }


    private void detachThemeAssets(AssetManager assets) {
        String themePackageName = assets.getThemePackageName();
        int themeCookie = assets.getThemeCookie();
        if (!TextUtils.isEmpty(themePackageName) && themeCookie != 0) {
            assets.removeAssetPath(themePackageName, themeCookie);
            assets.setThemePackageName(null);
            assets.setThemeCookie(0);
            assets.clearRedirections();
        }
    }

    /**
    /**
     * Attach the necessary theme asset paths and meta information to convert an
     * Attach the necessary theme asset paths and meta information to convert an
     * AssetManager to being globally "theme-aware".
     * AssetManager to being globally "theme-aware".
@@ -1252,21 +1277,16 @@ public final class ActivityThread {
     *         the framework default.
     *         the framework default.
     */
     */
    private boolean attachThemeAssets(AssetManager assets, CustomTheme theme, boolean updating) {
    private boolean attachThemeAssets(AssetManager assets, CustomTheme theme, boolean updating) {
        IAssetRedirectionManager rm = getAssetRedirectionManager();
        if (rm == null) {
            return false;
        }
        PackageInfo pi = null;
        PackageInfo pi = null;
        try {
        try {
            pi = getPackageManager().getPackageInfo(theme.getThemePackageName(), 0);
            pi = getPackageManager().getPackageInfo(theme.getThemePackageName(), 0);
        } catch (RemoteException e) {
        } catch (RemoteException e) {
        }
        }
        if (pi != null && pi.applicationInfo != null && pi.themeInfos != null) {
        if (pi != null && pi.applicationInfo != null && pi.themeInfos != null) {
            /*
             * It's important that this is called before
             * updateResourcesWithAssetPath as it depends on the result of
             * getThemePackageName to figure out what to do with the resource
             * redirection table.
             */
            assets.setThemePackageInfo(theme.getThemePackageName(),
                    findThemeResourceId(pi.themeInfos, theme));

            String themeResDir = pi.applicationInfo.publicSourceDir;
            String themeResDir = pi.applicationInfo.publicSourceDir;
            int cookie;
            int cookie;
            if (updating) {
            if (updating) {
@@ -1275,41 +1295,44 @@ public final class ActivityThread {
                cookie = assets.addAssetPath(themeResDir);
                cookie = assets.addAssetPath(themeResDir);
            }
            }
            if (cookie != 0) {
            if (cookie != 0) {
                assets.setThemeCookie(cookie);
                String themePackageName = theme.getThemePackageName();
                return true;
                String themeId = theme.getThemeId();
            } else {
                int N = assets.getBasePackageCount();
                Log.e(TAG, "Unable to " + (updating ? "update" : "add") + " theme assets at " +
                for (int i = 0; i < N; i++) {
                        themeResDir);
                    String packageName = assets.getBasePackageName(i);
                    int packageId = assets.getBasePackageId(i);


                /* Roll back the theme package info. */
                    /*
                assets.setThemePackageInfo(null, 0);
                     * For now, we only consider redirections coming from the
                     * framework or regular android packages. This excludes
                     * themes and other specialty APKs we are not aware of.
                     */
                    if (packageId != 0x01 && packageId != 0x7f) {
                        continue;
                    }
                    }

                    try {
                        PackageRedirectionMap map = rm.getPackageRedirectionMap(themePackageName, themeId,
                                packageName);
                        if (map != null) {
                            assets.addRedirections(map);
                        }
                        }
                    } catch (RemoteException e) {
                        Log.e(TAG, "Failure accessing package redirection map, removing theme support.");
                        assets.removeAssetPath(themePackageName, cookie);
                        return false;
                        return false;
                    }
                    }

    /**
     * Searches for the high-level theme resource id for the specific
     * &lt;theme&gt; tag being applied.
     * <p>
     * An individual theme package can contain multiple &lt;theme&gt; tags, each
     * representing a separate theme choice from the user's perspective, even
     * though the most common case is for there to be only 1.
     *
     * @return The style resource id or 0 if no match was found.
     */
    private int findThemeResourceId(ThemeInfo[] themeInfos, CustomTheme theme) {
        String needle = theme.getThemeId();
        if (themeInfos != null && !TextUtils.isEmpty(needle)) {
            int n = themeInfos.length;
            for (int i = 0; i < n; i++) {
                ThemeInfo info = themeInfos[i];
                if (needle.equals(info.themeId)) {
                    return info.styleResourceId;
                }
                }

                assets.setThemePackageName(theme.getThemePackageName());
                assets.setThemeCookie(cookie);
                return true;
            } else {
                Log.e(TAG, "Unable to " + (updating ? "update" : "add") + " theme assets at " +
                        themeResDir);
            }
            }
        }
        }
        return 0;
        return false;
    }
    }


    /**
    /**
@@ -3060,20 +3083,8 @@ public final class ActivityThread {
                boolean themeChanged = (changes & ActivityInfo.CONFIG_THEME_RESOURCE) != 0;
                boolean themeChanged = (changes & ActivityInfo.CONFIG_THEME_RESOURCE) != 0;
                if (themeChanged) {
                if (themeChanged) {
                    AssetManager am = r.getAssets();
                    AssetManager am = r.getAssets();
                    /*
                     * Dynamically modify the AssetManager object to
                     * replace the old asset path with the new one. This
                     * is made possibly by native layer changes made by
                     * T-Mobile.
                     */
                    if (am.hasThemeSupport()) {
                    if (am.hasThemeSupport()) {
                        String oldThemePackage = am.getThemePackageName();
                        detachThemeAssets(am);
                        int themeCookie = am.getThemeCookie();
                        if (!TextUtils.isEmpty(oldThemePackage) && themeCookie != 0) {
                            am.setThemePackageInfo(null, 0);
                            am.removeAssetPath(oldThemePackage, themeCookie);
                            am.setThemeCookie(0);
                        }
                        if (!TextUtils.isEmpty(config.customTheme.getThemePackageName())) {
                        if (!TextUtils.isEmpty(config.customTheme.getThemePackageName())) {
                            attachThemeAssets(am, config.customTheme, true);
                            attachThemeAssets(am, config.customTheme, true);
                        }
                        }
+67 −2
Original line number Original line Diff line number Diff line
@@ -20,6 +20,7 @@ package android.content.res;
import android.os.ParcelFileDescriptor;
import android.os.ParcelFileDescriptor;
import android.util.Config;
import android.util.Config;
import android.util.Log;
import android.util.Log;
import android.util.SparseArray;
import android.util.TypedValue;
import android.util.TypedValue;


import java.io.FileNotFoundException;
import java.io.FileNotFoundException;
@@ -83,8 +84,16 @@ public final class AssetManager {
    private String mAppName;
    private String mAppName;


    private boolean mThemeSupport;
    private boolean mThemeSupport;
    private String mThemePackageName;
    private int mThemeCookie;
    private int mThemeCookie;


    /**
     * Organize all added redirection maps using Java strong references to keep
     * the native layer cleanup simple (that is, finalize() in Java will be
     * responsible for delete in C++).
     */
    private SparseArray<PackageRedirectionMap> mRedirections;

    /**
    /**
     * Create a new AssetManager containing only the basic system assets.
     * Create a new AssetManager containing only the basic system assets.
     * Applications will not generally use this method, instead retrieving the
     * Applications will not generally use this method, instead retrieving the
@@ -691,17 +700,31 @@ public final class AssetManager {
        return mThemeSupport;
        return mThemeSupport;
    }
    }


    /**
     * Apply a heuristic to match-up all attributes from the source style with
     * attributes in the destination style. For each match, an entry in the
     * package redirection map will be inserted.
     *
     * {@hide}
     */
    public native final boolean generateStyleRedirections(int resMapNative, int sourceStyle,
            int destStyle);

    /**
    /**
     * Get package name of current theme (may return null).
     * Get package name of current theme (may return null).
     * {@hide}
     * {@hide}
     */
     */
    public native final String getThemePackageName();
    public String getThemePackageName() {
        return mThemePackageName;
    }


    /**
    /**
     * Sets package name and highest level style id for current theme (null, 0 is allowed).
     * Sets package name and highest level style id for current theme (null, 0 is allowed).
     * {@hide}
     * {@hide}
     */
     */
    public native final void setThemePackageInfo(String packageName, int styleId);
    public void setThemePackageName(String packageName) {
        mThemePackageName = packageName;
    }


    /**
    /**
     * Get asset cookie for current theme (may return 0).
     * Get asset cookie for current theme (may return 0).
@@ -719,6 +742,30 @@ public final class AssetManager {
        mThemeCookie = cookie;
        mThemeCookie = cookie;
    }
    }


    /**
     * Add a redirection map to the asset manager. All future resource lookups
     * will consult this map.
     * {@hide}
     */
    public void addRedirections(PackageRedirectionMap map) {
        if (mRedirections == null) {
            mRedirections = new SparseArray<PackageRedirectionMap>(2);
        }
        mRedirections.append(map.getPackageId(), map);
        addRedirectionsNative(map.getNativePointer());
    }

    /**
     * Clear redirection map for the asset manager.
     * {@hide}
     */
    public void clearRedirections() {
        if (mRedirections != null) {
            mRedirections.clear();
        }
        clearRedirectionsNative();
    }

    /**
    /**
     * Determine whether the state in this asset manager is up-to-date with
     * Determine whether the state in this asset manager is up-to-date with
     * the files on the filesystem.  If false is returned, you need to
     * the files on the filesystem.  If false is returned, you need to
@@ -837,6 +884,24 @@ public final class AssetManager {


    private native final int splitThemePackage(String srcFileName, String dstFileName, String [] drmProtectedAssetNames);
    private native final int splitThemePackage(String srcFileName, String dstFileName, String [] drmProtectedAssetNames);


    /**
     * {@hide}
     */
    public native final int getBasePackageCount();

    /**
     * {@hide}
     */
    public native final String getBasePackageName(int index);

    /**
     * {@hide}
     */
    public native final int getBasePackageId(int index);

    private native final void addRedirectionsNative(int redirectionMapNativePointer);
    private native final void clearRedirectionsNative();

    private native final void init();
    private native final void init();
    private native final void destroy();
    private native final void destroy();


+22 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2011, T-Mobile USA, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.content.res;

/**
 * @hide
 */
parcelable PackageRedirectionMap;
+90 −0
Original line number Original line Diff line number Diff line
package android.content.res;

import android.os.Parcel;
import android.os.Parcelable;

/**
 * Native transport for package asset redirection information coming from the
 * AssetRedirectionManagerService.
 *
 * @hide
 */
public class PackageRedirectionMap implements Parcelable {
    private final int mNativePointer;

    public static final Parcelable.Creator<PackageRedirectionMap> CREATOR
            = new Parcelable.Creator<PackageRedirectionMap>() {
        public PackageRedirectionMap createFromParcel(Parcel in) {
            return new PackageRedirectionMap(in);
        }

        public PackageRedirectionMap[] newArray(int size) {
            return new PackageRedirectionMap[size];
        }
    };

    public PackageRedirectionMap() {
        this(nativeConstructor());
    }

    private PackageRedirectionMap(Parcel in) {
        this(nativeCreateFromParcel(in));
    }

    private PackageRedirectionMap(int nativePointer) {
        if (nativePointer == 0) {
            throw new RuntimeException();
        }
        mNativePointer = nativePointer;
    }

    @Override
    protected void finalize() throws Throwable {
        nativeDestructor(mNativePointer);
    }

    public int getNativePointer() {
        return mNativePointer;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        if (!nativeWriteToParcel(mNativePointer, dest)) {
            throw new RuntimeException();
        }
    }

    public int getPackageId() {
        return nativeGetPackageId(mNativePointer);
    }

    public void addRedirection(int fromIdent, int toIdent) {
        nativeAddRedirection(mNativePointer, fromIdent, toIdent);
    }

    // Used for debugging purposes only.
    public int[] getRedirectionKeys() {
        return nativeGetRedirectionKeys(mNativePointer);
    }

    // Used for debugging purposes only.
    public int lookupRedirection(int fromIdent) {
        return nativeLookupRedirection(mNativePointer, fromIdent);
    }

    private static native int nativeConstructor();
    private static native void nativeDestructor(int nativePointer);

    private static native int nativeCreateFromParcel(Parcel p);
    private static native boolean nativeWriteToParcel(int nativePointer, Parcel p);

    private native void nativeAddRedirection(int nativePointer, int fromIdent, int toIdent);
    private native int nativeGetPackageId(int nativePointer);
    private native int[] nativeGetRedirectionKeys(int nativePointer);
    private native int nativeLookupRedirection(int nativePointer, int fromIdent);
}
Loading