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(); }