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

Commit fe088650 authored by Kun Liang's avatar Kun Liang Committed by Shashank Mittal
Browse files

AppOps: Add support for whitelist of packages.

By default AppOps gives MODE_ASK permission to all strict operations.
This can degrade user experience for pre-installed apps.

This change adds support for passing a whitelist XML file to AppOps.
Operations requested by packages listed in whitelist file will be set
to MODE_ALLOWED by default.

User can still go into settings and override permissions of these
operations.

Whitelist XML file should have following format:
Example: whitelist_appops.xml

<whitelist-pkgs>
    <pkg name="com.android.settings"/>
    <pkg name="com.android.systemui"/>
    .
    .
    .
</whitelist-pkgs>

Change-Id: I78bf5e7baa95f0e86f9856fb38bf1ca238691303
parent 54ef59c8
Loading
Loading
Loading
Loading
+87 −1
Original line number Diff line number Diff line
@@ -70,6 +70,7 @@ public class AppOpsService extends IAppOpsService.Stub {
    static final String TAG = "AppOps";
    static final boolean DEBUG = false;
    static final int SHOW_PERMISSION_DIALOG = 1;
    static final String WHITELIST_FILE = "persist.sys.whitelist";

    // Write at most every 30 minutes.
    static final long WRITE_DELAY = DEBUG ? 1000 : 30*60*1000;
@@ -230,6 +231,7 @@ public class AppOpsService extends IAppOpsService.Stub {
                }
            }
        };
        readWhitelist();
        readState();
    }

@@ -1155,7 +1157,12 @@ public class AppOpsService extends IAppOpsService.Stub {
        if (!mStrictEnable)
            return false;

        return ((uid > Process.FIRST_APPLICATION_UID));
        return ((uid > Process.FIRST_APPLICATION_UID) &&
            !isInWhitelist(packageName));
    }

    private boolean isInWhitelist(String packageName) {
        return mWhitelist.contains(packageName);
    }

    private Result askOperationLocked(int code, int uid, String packageName,
@@ -1280,4 +1287,83 @@ public class AppOpsService extends IAppOpsService.Stub {
            }
        }
    }

    final ArrayList<String> mWhitelist = new ArrayList<String>();

    void readWhitelist() {
        // Read if whitelist file provided
        String whitelistFileName = SystemProperties.get(WHITELIST_FILE);
        if(!mStrictEnable || "".equals(whitelistFileName)) {
            return;
        }
        final File whitelistFile = new File(whitelistFileName);
        final AtomicFile mWhitelistFile = new AtomicFile(whitelistFile);
        synchronized (mWhitelistFile) {
            synchronized (this) {
                FileInputStream stream;
                try {
                    stream = mWhitelistFile.openRead();
                } catch (FileNotFoundException e) {
                    Slog.i(TAG, "No existing app ops whitelist " +
                        mWhitelistFile.getBaseFile());
                    return;
                }
                boolean success = false;
                try {
                    XmlPullParser parser = Xml.newPullParser();
                    parser.setInput(stream, null);
                    int type;
                    while ((type = parser.next()) != XmlPullParser.START_TAG
                            && type != XmlPullParser.END_DOCUMENT) {
                        ;
                    }

                    if (type != XmlPullParser.START_TAG) {
                        throw new IllegalStateException("no start tag found");
                    }

                    int outerDepth = parser.getDepth();
                    while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
                            && (type != XmlPullParser.END_TAG ||
                            parser.getDepth() > outerDepth)) {
                        if (type == XmlPullParser.END_TAG ||
                            type == XmlPullParser.TEXT) {
                            continue;
                        }

                        String tagName = parser.getName();
                        if (tagName.equals("pkg")) {
                            String pkgName = parser.getAttributeValue(null, "name");
                            mWhitelist.add(pkgName);
                        } else {
                            Slog.w(TAG, "Unknown element under <whitelist-pkgs>: "
                                    + parser.getName());
                            XmlUtils.skipCurrentTag(parser);
                        }
                    }
                    success = true;
                } catch (IllegalStateException e) {
                    Slog.w(TAG, "Failed parsing " + e);
                } catch (NullPointerException e) {
                    Slog.w(TAG, "Failed parsing " + e);
                } catch (NumberFormatException e) {
                    Slog.w(TAG, "Failed parsing " + e);
                } catch (XmlPullParserException e) {
                    Slog.w(TAG, "Failed parsing " + e);
                } catch (IOException e) {
                    Slog.w(TAG, "Failed parsing " + e);
                } catch (IndexOutOfBoundsException e) {
                    Slog.w(TAG, "Failed parsing " + e);
                } finally {
                    if (!success) {
                        mWhitelist.clear();
                    }
                    try {
                        stream.close();
                    } catch (IOException e) {
                    }
                }
            }
        }
    }
}