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

Commit d54e1126 authored by Hunter Knepshield's avatar Hunter Knepshield Committed by Gerrit Code Review
Browse files

Merge "Create CarrierPrivilegesListener callback."

parents 8581d274 866d3a4d
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -12001,6 +12001,7 @@ package android.telephony {
  }
  public class TelephonyManager {
    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void addCarrierPrivilegesListener(int, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CarrierPrivilegesListener);
    method @RequiresPermission(anyOf={android.Manifest.permission.MODIFY_PHONE_STATE, android.Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION}) @WorkerThread public void bootstrapAuthenticationRequest(int, @NonNull android.net.Uri, @NonNull android.telephony.gba.UaSecurityProtocolIdentifier, boolean, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.BootstrapAuthenticationCallback);
    method @Deprecated @RequiresPermission(android.Manifest.permission.CALL_PHONE) public void call(String, String);
    method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public android.telephony.PinResult changeIccLockPin(@NonNull String, @NonNull String);
@@ -12095,6 +12096,7 @@ package android.telephony {
    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void notifyOtaEmergencyNumberDbInstalled();
    method @RequiresPermission(android.Manifest.permission.REBOOT) public int prepareForUnattendedReboot();
    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean rebootRadio();
    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void removeCarrierPrivilegesListener(@NonNull android.telephony.TelephonyManager.CarrierPrivilegesListener);
    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void reportDefaultNetworkStatus(boolean);
    method @RequiresPermission(allOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.MODIFY_PHONE_STATE}) public void requestCellInfoUpdate(@NonNull android.os.WorkSource, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CellInfoCallback);
    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void requestModemActivityInfo(@NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<android.telephony.ModemActivityInfo,android.telephony.TelephonyManager.ModemActivityInfoException>);
@@ -12270,6 +12272,10 @@ package android.telephony {
    field public static final int RESULT_SUCCESS = 0; // 0x0
  }
  public static interface TelephonyManager.CarrierPrivilegesListener {
    method public void onCarrierPrivilegesChanged(@NonNull java.util.List<java.lang.String>, @NonNull int[]);
  }
  public static class TelephonyManager.ModemActivityInfoException extends java.lang.Exception {
    method public int getErrorCode();
    field public static final int ERROR_INVALID_INFO_RECEIVED = 2; // 0x2
+119 −0
Original line number Diff line number Diff line
@@ -36,18 +36,24 @@ import android.telephony.Annotation.PreciseDisconnectCauses;
import android.telephony.Annotation.RadioPowerState;
import android.telephony.Annotation.SimActivationState;
import android.telephony.Annotation.SrvccState;
import android.telephony.TelephonyManager.CarrierPrivilegesListener;
import android.telephony.emergency.EmergencyNumber;
import android.telephony.ims.ImsReasonInfo;
import android.util.ArraySet;
import android.util.Log;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.listeners.ListenerExecutor;
import com.android.internal.telephony.ICarrierPrivilegesListener;
import com.android.internal.telephony.IOnSubscriptionsChangedListener;
import com.android.internal.telephony.ITelephonyRegistry;

import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
import java.util.concurrent.Executor;

/**
@@ -1214,4 +1220,117 @@ public class TelephonyRegistryManager {
        listenFromCallback(false, false, subId,
                pkgName, attributionTag, callback, new int[0], notifyNow);
    }

    private static class CarrierPrivilegesListenerWrapper extends ICarrierPrivilegesListener.Stub
            implements ListenerExecutor {
        private final WeakReference<CarrierPrivilegesListener> mListener;
        private final Executor mExecutor;

        CarrierPrivilegesListenerWrapper(CarrierPrivilegesListener listener, Executor executor) {
            mListener = new WeakReference<>(listener);
            mExecutor = executor;
        }

        @Override
        public void onCarrierPrivilegesChanged(
                List<String> privilegedPackageNames, int[] privilegedUids) {
            Binder.withCleanCallingIdentity(
                    () ->
                            executeSafely(
                                    mExecutor,
                                    mListener::get,
                                    cpl ->
                                            cpl.onCarrierPrivilegesChanged(
                                                    privilegedPackageNames, privilegedUids)));
        }
    }

    @GuardedBy("sCarrierPrivilegeListeners")
    private static final WeakHashMap<
                    CarrierPrivilegesListener, WeakReference<CarrierPrivilegesListenerWrapper>>
            sCarrierPrivilegeListeners = new WeakHashMap<>();

    /**
     * Registers a {@link CarrierPrivilegesListener} on the given {@code logicalSlotIndex} to
     * receive callbacks when the set of packages with carrier privileges changes. The callback will
     * immediately be called with the latest state.
     *
     * @param logicalSlotIndex The SIM slot to listen on
     * @param executor The executor where {@code listener} will be invoked
     * @param listener The callback to register
     */
    public void addCarrierPrivilegesListener(
            int logicalSlotIndex,
            @NonNull @CallbackExecutor Executor executor,
            @NonNull CarrierPrivilegesListener listener) {
        if (listener == null || executor == null) {
            throw new IllegalArgumentException("listener and executor must be non-null");
        }
        synchronized (sCarrierPrivilegeListeners) {
            WeakReference<CarrierPrivilegesListenerWrapper> existing =
                    sCarrierPrivilegeListeners.get(listener);
            if (existing != null && existing.get() != null) {
                Log.d(TAG, "addCarrierPrivilegesListener: listener already registered");
                return;
            }
            CarrierPrivilegesListenerWrapper wrapper =
                    new CarrierPrivilegesListenerWrapper(listener, executor);
            sCarrierPrivilegeListeners.put(listener, new WeakReference<>(wrapper));
            try {
                sRegistry.addCarrierPrivilegesListener(
                        logicalSlotIndex,
                        wrapper,
                        mContext.getOpPackageName(),
                        mContext.getAttributionTag());
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
    }

    /**
     * Unregisters a {@link CarrierPrivilegesListener}.
     *
     * @param listener The callback to unregister
     */
    public void removeCarrierPrivilegesListener(@NonNull CarrierPrivilegesListener listener) {
        if (listener == null) {
            throw new IllegalArgumentException("listener must be non-null");
        }
        synchronized (sCarrierPrivilegeListeners) {
            WeakReference<CarrierPrivilegesListenerWrapper> ref =
                    sCarrierPrivilegeListeners.remove(listener);
            if (ref == null) return;
            CarrierPrivilegesListenerWrapper wrapper = ref.get();
            if (wrapper == null) return;
            try {
                sRegistry.removeCarrierPrivilegesListener(wrapper, mContext.getOpPackageName());
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
    }

    /**
     * Notify listeners that the set of packages with carrier privileges has changed.
     *
     * @param logicalSlotIndex The SIM slot the change occurred on
     * @param privilegedPackageNames The updated set of packages names with carrier privileges
     * @param privilegedUids The updated set of UIDs with carrier privileges
     */
    public void notifyCarrierPrivilegesChanged(
            int logicalSlotIndex,
            @NonNull List<String> privilegedPackageNames,
            @NonNull int[] privilegedUids) {
        if (privilegedPackageNames == null || privilegedUids == null) {
            throw new IllegalArgumentException(
                    "privilegedPackageNames and privilegedUids must be non-null");
        }
        try {
            sRegistry.notifyCarrierPrivilegesChanged(
                    logicalSlotIndex, privilegedPackageNames, privilegedUids);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }
}
+22 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.internal.telephony;

oneway interface ICarrierPrivilegesListener {
    void onCarrierPrivilegesChanged(
            in List<String> privilegedPackageNames, in int[] privilegedUids);
}
+7 −0
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ import android.telephony.PreciseDataConnectionState;
import android.telephony.ServiceState;
import android.telephony.SignalStrength;
import android.telephony.emergency.EmergencyNumber;
import com.android.internal.telephony.ICarrierPrivilegesListener;
import com.android.internal.telephony.IPhoneStateListener;
import com.android.internal.telephony.IOnSubscriptionsChangedListener;

@@ -100,4 +101,10 @@ interface ITelephonyRegistry {
    void notifyAllowedNetworkTypesChanged(in int phoneId, in int subId, in int reason, in long allowedNetworkType);
    void notifyLinkCapacityEstimateChanged(in int phoneId, in int subId,
            in List<LinkCapacityEstimate> linkCapacityEstimateList);

    void addCarrierPrivilegesListener(
            int phoneId, ICarrierPrivilegesListener callback, String pkg, String featureId);
    void removeCarrierPrivilegesListener(ICarrierPrivilegesListener callback, String pkg);
    void notifyCarrierPrivilegesChanged(
            int phoneId, in List<String> privilegedPackageNames, in int[] privilegedUids);
}
+127 −2
Original line number Diff line number Diff line
@@ -91,6 +91,7 @@ import android.util.Pair;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.IBatteryStats;
import com.android.internal.telephony.ICarrierPrivilegesListener;
import com.android.internal.telephony.IOnSubscriptionsChangedListener;
import com.android.internal.telephony.IPhoneStateListener;
import com.android.internal.telephony.ITelephonyRegistry;
@@ -106,6 +107,7 @@ import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -149,6 +151,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
        IPhoneStateListener callback;
        IOnSubscriptionsChangedListener onSubscriptionsChangedListenerCallback;
        IOnSubscriptionsChangedListener onOpportunisticSubscriptionsChangedListenerCallback;
        ICarrierPrivilegesListener carrierPrivilegesListener;

        int callerUid;
        int callerPid;
@@ -173,6 +176,10 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
            return (onOpportunisticSubscriptionsChangedListenerCallback != null);
        }

        boolean matchCarrierPrivilegesListener() {
            return carrierPrivilegesListener != null;
        }

        boolean canReadCallLog() {
            try {
                return TelephonyPermissions.checkReadCallLog(
@@ -189,8 +196,9 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
                    + " onSubscriptionsChangedListenererCallback="
                    + onSubscriptionsChangedListenerCallback
                    + " onOpportunisticSubscriptionsChangedListenererCallback="
                    + onOpportunisticSubscriptionsChangedListenerCallback + " subId=" + subId
                    + " phoneId=" + phoneId + " events=" + eventList + "}";
                    + onOpportunisticSubscriptionsChangedListenerCallback
                    + " carrierPrivilegesListener=" + carrierPrivilegesListener
                    + " subId=" + subId + " phoneId=" + phoneId + " events=" + eventList + "}";
        }
    }

@@ -402,6 +410,10 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
     */
    private List<Map<Pair<Integer, ApnSetting>, PreciseDataConnectionState>>
            mPreciseDataConnectionStates;

    /** Per-phoneId snapshot of privileged packages (names + UIDs). */
    private List<Pair<List<String>, int[]>> mCarrierPrivilegeStates;

    /**
     * Support backward compatibility for {@link android.telephony.TelephonyDisplayInfo}.
     */
@@ -689,6 +701,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
            cutListToSize(mBarringInfo, mNumPhones);
            cutListToSize(mPhysicalChannelConfigs, mNumPhones);
            cutListToSize(mLinkCapacityEstimateLists, mNumPhones);
            cutListToSize(mCarrierPrivilegeStates, mNumPhones);
            return;
        }

@@ -729,6 +742,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
            mAllowedNetworkTypeReason[i] = -1;
            mAllowedNetworkTypeValue[i] = -1;
            mLinkCapacityEstimateLists.add(i, INVALID_LCE_LIST);
            mCarrierPrivilegeStates.add(i, new Pair<>(Collections.emptyList(), new int[0]));
        }
    }

@@ -794,6 +808,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
        mIsDataEnabled = new boolean[numPhones];
        mDataEnabledReason = new int[numPhones];
        mLinkCapacityEstimateLists = new ArrayList<>();
        mCarrierPrivilegeStates = new ArrayList<>();

        for (int i = 0; i < numPhones; i++) {
            mCallState[i] =  TelephonyManager.CALL_STATE_IDLE;
@@ -831,6 +846,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
            mAllowedNetworkTypeReason[i] = -1;
            mAllowedNetworkTypeValue[i] = -1;
            mLinkCapacityEstimateLists.add(i, INVALID_LCE_LIST);
            mCarrierPrivilegeStates.add(i, new Pair<>(Collections.emptyList(), new int[0]));
        }

        mAppOps = mContext.getSystemService(AppOpsManager.class);
@@ -2765,6 +2781,104 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
        }
    }

    @Override
    public void addCarrierPrivilegesListener(
            int phoneId,
            ICarrierPrivilegesListener callback,
            String callingPackage,
            String callingFeatureId) {
        int callerUserId = UserHandle.getCallingUserId();
        mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
        mContext.enforceCallingOrSelfPermission(
                android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
                "addCarrierPrivilegesListener");
        if (VDBG) {
            log(
                    "listen carrier privs: E pkg=" + pii(callingPackage) + " phoneId=" + phoneId
                            + " uid=" + Binder.getCallingUid()
                            + " myUserId=" + UserHandle.myUserId() + " callerUserId=" + callerUserId
                            + " callback=" + callback
                            + " callback.asBinder=" + callback.asBinder());
        }
        if (!validatePhoneId(phoneId)) {
            throw new IllegalArgumentException("Invalid slot index: " + phoneId);
        }

        synchronized (mRecords) {
            Record r = add(
                    callback.asBinder(), Binder.getCallingUid(), Binder.getCallingPid(), false);

            if (r == null) return;

            r.context = mContext;
            r.carrierPrivilegesListener = callback;
            r.callingPackage = callingPackage;
            r.callingFeatureId = callingFeatureId;
            r.callerUid = Binder.getCallingUid();
            r.callerPid = Binder.getCallingPid();
            r.phoneId = phoneId;
            r.eventList = new ArraySet<>();
            if (DBG) {
                log("listen carrier privs: Register r=" + r);
            }

            Pair<List<String>, int[]> state = mCarrierPrivilegeStates.get(phoneId);
            try {
                r.carrierPrivilegesListener.onCarrierPrivilegesChanged(
                        Collections.unmodifiableList(state.first),
                        Arrays.copyOf(state.second, state.second.length));
            } catch (RemoteException ex) {
                remove(r.binder);
            }
        }
    }

    @Override
    public void removeCarrierPrivilegesListener(
            ICarrierPrivilegesListener callback, String callingPackage) {
        mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
        mContext.enforceCallingOrSelfPermission(
                android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
                "removeCarrierPrivilegesListener");
        remove(callback.asBinder());
    }

    @Override
    public void notifyCarrierPrivilegesChanged(
            int phoneId, List<String> privilegedPackageNames, int[] privilegedUids) {
        if (!checkNotifyPermission("notifyCarrierPrivilegesChanged")) {
            return;
        }
        if (!validatePhoneId(phoneId)) return;
        if (VDBG) {
            log(
                    "notifyCarrierPrivilegesChanged: phoneId=" + phoneId
                            + ", <packages=" + pii(privilegedPackageNames)
                            + ", uids=" + Arrays.toString(privilegedUids) + ">");
        }
        synchronized (mRecords) {
            mCarrierPrivilegeStates.set(
                    phoneId, new Pair<>(privilegedPackageNames, privilegedUids));
            for (Record r : mRecords) {
                // Listeners are per-slot, not per-subscription. This is to provide a stable
                // view across SIM profile switches.
                if (!r.matchCarrierPrivilegesListener()
                        || !idMatch(r, SubscriptionManager.INVALID_SUBSCRIPTION_ID, phoneId)) {
                    continue;
                }
                try {
                    // Make sure even in-process listeners can't modify the values.
                    r.carrierPrivilegesListener.onCarrierPrivilegesChanged(
                            Collections.unmodifiableList(privilegedPackageNames),
                            Arrays.copyOf(privilegedUids, privilegedUids.length));
                } catch (RemoteException ex) {
                    mRemoveList.add(r.binder);
                }
            }
            handleRemoveListLocked();
        }
    }

    @Override
    public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
        final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ");
@@ -2814,6 +2928,11 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
                pw.println("mAllowedNetworkTypeValue=" + mAllowedNetworkTypeValue[i]);
                pw.println("mPhysicalChannelConfigs=" + mPhysicalChannelConfigs.get(i));
                pw.println("mLinkCapacityEstimateList=" + mLinkCapacityEstimateLists.get(i));
                // We need to obfuscate package names, and primitive arrays' native toString is ugly
                Pair<List<String>, int[]> carrierPrivilegeState = mCarrierPrivilegeStates.get(i);
                pw.println(
                        "mCarrierPrivilegeState=<packages=" + pii(carrierPrivilegeState.first)
                                + ", uids=" + Arrays.toString(carrierPrivilegeState.second) + ">");
                pw.decreaseIndent();
            }

@@ -3540,4 +3659,10 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
    private static String pii(String packageName) {
        return Build.IS_DEBUGGABLE ? packageName : "***";
    }

    /** Redacts an entire list of package names if necessary. */
    private static String pii(List<String> packageNames) {
        if (packageNames.isEmpty() || Build.IS_DEBUGGABLE) return packageNames.toString();
        return "[***, size=" + packageNames.size() + "]";
    }
}
Loading