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

Commit ff68cbd0 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "Allow injection jar to be located in product folder"

parents bc656998 a187041f
Loading
Loading
Loading
Loading
+36 −18
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.internal.telephony;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.content.res.XmlResourceParser;
import android.database.Cursor;
@@ -50,10 +51,13 @@ import dalvik.system.PathClassLoader;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.function.Consumer;
import java.util.stream.Collectors;



@@ -77,6 +81,7 @@ public class TelephonyComponentFactory {
        private static final String TAG_COMPONENTS = "components";
        private static final String TAG_COMPONENT = "component";
        private static final String SYSTEM = "/system/";
        private static final String PRODUCT = "/product/";

        private final Set<String> mComponentNames = new HashSet<>();
        private TelephonyComponentFactory mInjectedInstance;
@@ -84,29 +89,41 @@ public class TelephonyComponentFactory {
        private String mJarPath;

        /**
         * @return if jar path is correctly configured to inject.
         * @return paths correctly configured to inject.
         * 1) PackageName and JarPath mustn't be empty.
         * 2) JarPath is restricted under /system only
         * 2) JarPath is restricted under /system or /product only.
         * 3) JarPath is on a READ-ONLY partition.
         */
        private boolean isConfigValid() {
            return !TextUtils.isEmpty(mPackageName) && !TextUtils.isEmpty(mJarPath)
                    && mJarPath.startsWith(SYSTEM);
        private @Nullable String getValidatedPaths() {
            if (TextUtils.isEmpty(mPackageName) || TextUtils.isEmpty(mJarPath)) {
                return null;
            }
            // filter out invalid paths
            return Arrays.stream(mJarPath.split(File.pathSeparator))
                    .filter(s -> (s.startsWith(SYSTEM) || s.startsWith(PRODUCT)))
                    .filter(s -> {
                        try {
                            // This will also throw an error if the target doesn't exist.
                            StructStatVfs vfs = Os.statvfs(s);
                            return (vfs.f_flag & OsConstants.ST_RDONLY) != 0;
                        } catch (ErrnoException e) {
                            Rlog.w(TAG, "Injection jar is not protected , path: " + s
                                    + e.getMessage());
                            return false;
                        }
                    }).distinct()
                    .collect(Collectors.joining(File.pathSeparator));
        }

        private void makeInjectedInstance() {
            if (isConfigValid()) {
            String validatedPaths = getValidatedPaths();
            Rlog.d(TAG, "validated paths: " + validatedPaths);
            if (!TextUtils.isEmpty(validatedPaths)) {
                try {
                    StructStatVfs vfs = Os.statvfs(mJarPath);
                    if ((vfs.f_flag & OsConstants.ST_RDONLY) != 0) {
                        PathClassLoader classLoader = new PathClassLoader(mJarPath,
                    PathClassLoader classLoader = new PathClassLoader(validatedPaths,
                            ClassLoader.getSystemClassLoader());
                    Class<?> cls = classLoader.loadClass(mPackageName);
                    mInjectedInstance = (TelephonyComponentFactory) cls.newInstance();
                    } else {
                        Rlog.w(TAG, "Injection jar is not protected");
                    }
                } catch (ErrnoException e) {
                    Rlog.e(TAG, "failed file mount, " + e.getMessage());
                } catch (ClassNotFoundException e) {
                    Rlog.e(TAG, "failed: " + e.getMessage());
                } catch (IllegalAccessException | InstantiationException e) {
@@ -233,7 +250,8 @@ public class TelephonyComponentFactory {
            mInjectedComponents = new InjectedComponents();
            mInjectedComponents.parseXml(parser);
            mInjectedComponents.makeInjectedInstance();
            Rlog.d(TAG, "Total components injected: " + (mInjectedComponents.isConfigValid()
            boolean injectSuccessful = !TextUtils.isEmpty(mInjectedComponents.getValidatedPaths());
            Rlog.d(TAG, "Total components injected: " + (injectSuccessful
                    ? mInjectedComponents.mComponentNames.size() : 0));
        }
    }