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

Commit c3596412 authored by Youming Ye's avatar Youming Ye Committed by android-build-merger
Browse files

Merge "Allow injection jar to be located in product folder" am: ff68cbd0 am: 81956e75

am: 6d6c471f

Change-Id: I6d802ba6f6aff4f2da7309396213041ac5b4b3f5
parents 6a5e92cd 6d6c471f
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));
        }
    }