From 4ec6368f13a53906757283d50a17ed3ed43eccc4 Mon Sep 17 00:00:00 2001 From: Amith Yamasani Date: Fri, 19 Feb 2016 12:55:27 -0800 Subject: [PATCH] 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 --- .../android/app/usage/IUsageStatsManager.aidl | 1 + .../android/app/usage/UsageStatsManager.java | 11 +++ .../server/usage/UsageStatsService.java | 76 ++++++++++++++++--- .../android/telephony/TelephonyManager.java | 16 ++++ .../internal/telephony/ITelephony.aidl | 5 ++ 5 files changed, 99 insertions(+), 10 deletions(-) diff --git a/core/java/android/app/usage/IUsageStatsManager.aidl b/core/java/android/app/usage/IUsageStatsManager.aidl index a9328bce06129..342c2858ab0f8 100644 --- a/core/java/android/app/usage/IUsageStatsManager.aidl +++ b/core/java/android/app/usage/IUsageStatsManager.aidl @@ -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(); } diff --git a/core/java/android/app/usage/UsageStatsManager.java b/core/java/android/app/usage/UsageStatsManager.java index c74b0f2d8e43e..2aeecfabd48c7 100644 --- a/core/java/android/app/usage/UsageStatsManager.java +++ b/core/java/android/app/usage/UsageStatsManager.java @@ -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) { + } + } } diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java index 8e891bfcbabcc..8b250f4c18d87 100644 --- a/services/usage/java/com/android/server/usage/UsageStatsService.java +++ b/services/usage/java/com/android/server/usage/UsageStatsService.java @@ -151,6 +151,8 @@ public class UsageStatsService extends SystemService implements private ArrayList mPackageAccessListeners = new ArrayList<>(); + private List 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) diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index fcb42a48048fe..daffb88d5ae3b 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -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 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) { diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl index 62f294c3a197a..ad511a7efccb5 100644 --- a/telephony/java/com/android/internal/telephony/ITelephony.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl @@ -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 getPackagesWithCarrierPrivileges(); }