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

Commit 4ec6368f authored by Amith Yamasani's avatar Amith Yamasani
Browse files

Optimize calls to TelephonyManager to check for privileged apps

Calling into TelephonyManager each of hundreds of apps to check
if the app is carrier privileged was very expensive, especially
when there aren't even any carrier access rules specified. This
change fetches all the carrier privileged apps in one call,
reducing the number of IPC calls to the radio process and checks
the package names locally.

If the carrier rules change or packages are modified, the list
will be computed and fetched again.

Other optimizations in Telephony help speed up the individual calls
to check if a package is privileged, as well.

Bug: 27271861
Change-Id: I5a77b6da4f2cdc603d2a73bd8569c5c38f06b42d
parent b799d3f1
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -33,4 +33,5 @@ interface IUsageStatsManager {
    void setAppInactive(String packageName, boolean inactive, int userId);
    boolean isAppInactive(String packageName, int userId);
    void whitelistAppTemporarily(String packageName, long duration, int userId);
    void onCarrierPrivilegedAppsChanged();
}
+11 −0
Original line number Diff line number Diff line
@@ -267,4 +267,15 @@ public final class UsageStatsManager {
        } catch (RemoteException re) {
        }
    }

    /**
     * Inform usage stats that the carrier privileged apps access rules have changed.
     * @hide
     */
    public void onCarrierPrivilegedAppsChanged() {
        try {
            mService.onCarrierPrivilegedAppsChanged();
        } catch (RemoteException re) {
        }
    }
}
+66 −10
Original line number Diff line number Diff line
@@ -151,6 +151,8 @@ public class UsageStatsService extends SystemService implements
    private ArrayList<UsageStatsManagerInternal.AppIdleStateChangeListener>
            mPackageAccessListeners = new ArrayList<>();

    private List<String> mCarrierPrivilegedApps;

    public UsageStatsService(Context context) {
        super(context);
    }
@@ -170,10 +172,18 @@ public class UsageStatsService extends SystemService implements
                    + mUsageStatsDir.getAbsolutePath());
        }

        IntentFilter userActions = new IntentFilter(Intent.ACTION_USER_REMOVED);
        userActions.addAction(Intent.ACTION_USER_STARTED);
        getContext().registerReceiverAsUser(new UserActionsReceiver(), UserHandle.ALL, userActions,
                null, null);
        IntentFilter filter = new IntentFilter(Intent.ACTION_USER_REMOVED);
        filter.addAction(Intent.ACTION_USER_STARTED);
        getContext().registerReceiverAsUser(new UserActionsReceiver(), UserHandle.ALL, filter,
                null, mHandler);

        IntentFilter packageFilter = new IntentFilter();
        packageFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
        packageFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
        packageFilter.addDataScheme("package");

        getContext().registerReceiverAsUser(new PackageReceiver(), UserHandle.ALL, packageFilter,
                null, mHandler);

        mAppIdleEnabled = getContext().getResources().getBoolean(
                com.android.internal.R.bool.config_enableAutoPowerModes);
@@ -232,15 +242,15 @@ public class UsageStatsService extends SystemService implements
    }

    private class UserActionsReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
            if (Intent.ACTION_USER_REMOVED.equals(intent.getAction())) {
            final String action = intent.getAction();
            if (Intent.ACTION_USER_REMOVED.equals(action)) {
                if (userId >= 0) {
                    mHandler.obtainMessage(MSG_REMOVE_USER, userId, 0).sendToTarget();
                }
            } else if (Intent.ACTION_USER_STARTED.equals(intent.getAction())) {
            } else if (Intent.ACTION_USER_STARTED.equals(action)) {
                if (userId >=0) {
                    postCheckIdleStates(userId);
                }
@@ -248,6 +258,17 @@ public class UsageStatsService extends SystemService implements
        }
    }

    private class PackageReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            final String action = intent.getAction();
            if (Intent.ACTION_PACKAGE_ADDED.equals(action)
                    || Intent.ACTION_PACKAGE_CHANGED.equals(action)) {
                clearCarrierPrivilegedApps();
            }
        }
    }

    private class DeviceStateReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
@@ -890,9 +911,30 @@ public class UsageStatsService extends SystemService implements
    }

    private boolean isCarrierApp(String packageName) {
        TelephonyManager telephonyManager = getContext().getSystemService(TelephonyManager.class);
        return telephonyManager.checkCarrierPrivilegesForPackageAnyPhone(packageName)
                    == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
        synchronized (mLock) {
            if (mCarrierPrivilegedApps == null) {
                fetchCarrierPrivilegedAppsLocked();
            }
        }
        return mCarrierPrivilegedApps.contains(packageName);
    }

    void clearCarrierPrivilegedApps() {
        if (DEBUG) {
            Slog.i(TAG, "Clearing carrier privileged apps list");
        }
        synchronized (mLock) {
            mCarrierPrivilegedApps = null; // Need to be refetched.
        }
    }

    private void fetchCarrierPrivilegedAppsLocked() {
        TelephonyManager telephonyManager =
                getContext().getSystemService(TelephonyManager.class);
        mCarrierPrivilegedApps = telephonyManager.getPackagesWithCarrierPrivileges();
        if (DEBUG) {
            Slog.d(TAG, "apps with carrier privilege " + mCarrierPrivilegedApps);
        }
    }

    private boolean isActiveNetworkScorer(String packageName) {
@@ -962,6 +1004,9 @@ public class UsageStatsService extends SystemService implements
                idpw.decreaseIndent();
            }

            pw.println();
            pw.println("Carrier privileged apps: " + mCarrierPrivilegedApps);

            pw.println();
            pw.println("Settings:");

@@ -1256,6 +1301,17 @@ public class UsageStatsService extends SystemService implements
                    reason.toString());
        }

        @Override
        public void onCarrierPrivilegedAppsChanged() {
            if (DEBUG) {
                Slog.i(TAG, "Carrier privileged apps changed");
            }
            getContext().enforceCallingOrSelfPermission(
                    android.Manifest.permission.BIND_CARRIER_SERVICES,
                    "onCarrierPrivilegedAppsChanged can only be called by privileged apps.");
            UsageStatsService.this.clearCarrierPrivilegedApps();
        }

        @Override
        protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
            if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
+16 −0
Original line number Diff line number Diff line
@@ -47,6 +47,7 @@ import com.android.internal.telephony.TelephonyProperties;

import java.io.FileInputStream;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -3856,6 +3857,21 @@ public class TelephonyManager {
        return null;
    }

    /** @hide */
    public List<String> getPackagesWithCarrierPrivileges() {
        try {
            ITelephony telephony = getITelephony();
            if (telephony != null) {
                return telephony.getPackagesWithCarrierPrivileges();
            }
        } catch (RemoteException ex) {
            Rlog.e(TAG, "getPackagesWithCarrierPrivileges RemoteException", ex);
        } catch (NullPointerException ex) {
            Rlog.e(TAG, "getPackagesWithCarrierPrivileges NPE", ex);
        }
        return Collections.EMPTY_LIST;
    }

    /** @hide */
    @SystemApi
    public void dial(String number) {
+5 −0
Original line number Diff line number Diff line
@@ -1028,4 +1028,9 @@ interface ITelephony {
     * @return {@code true} if the vibration is set for this PhoneAccount, {@code false} otherwise.
     */
    boolean isVoicemailVibrationEnabled(in PhoneAccountHandle accountHandle);

    /**
     * Returns a list of packages that have carrier privileges.
     */
    List<String> getPackagesWithCarrierPrivileges();
}