Loading core/java/android/permission/RuntimePermissionPresenter.java +168 −153 Original line number Diff line number Diff line Loading @@ -16,27 +16,28 @@ package android.permission; import static android.permission.RuntimePermissionPresenterService.SERVICE_INTERFACE; import static com.android.internal.util.Preconditions.checkCollectionElementsNotNull; import static com.android.internal.util.Preconditions.checkNotNull; import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.content.pm.ResolveInfo; import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.os.RemoteCallback; import android.os.RemoteException; import android.os.UserHandle; import android.util.Log; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.function.pooled.PooledLambda; import com.android.internal.infra.AbstractMultiplePendingRequestsRemoteService; import com.android.internal.infra.AbstractRemoteService; import java.util.ArrayList; import java.util.Collections; import java.util.List; Loading Loading @@ -80,7 +81,7 @@ public final class RuntimePermissionPresenter { */ public interface OnCountPermissionAppsResultCallback { /** * The result for {@link #countPermissionApps(List, boolean, * The result for {@link #countPermissionApps(List, boolean, boolean, * OnCountPermissionAppsResultCallback, Handler)}. * * @param numApps The number of apps that have one of the permissions Loading Loading @@ -110,8 +111,13 @@ public final class RuntimePermissionPresenter { } } private RuntimePermissionPresenter(Context context) { mRemoteService = new RemoteService(context); private RuntimePermissionPresenter(@NonNull Context context) { Intent intent = new Intent(SERVICE_INTERFACE); intent.setPackage(context.getPackageManager().getPermissionControllerPackageName()); ResolveInfo serviceInfo = context.getPackageManager().resolveService(intent, 0); mRemoteService = new RemoteService(context, serviceInfo.getComponentInfo().getComponentName()); } /** Loading @@ -126,8 +132,8 @@ public final class RuntimePermissionPresenter { checkNotNull(packageName); checkNotNull(callback); mRemoteService.processMessage(obtainMessage(RemoteService::getAppPermissions, mRemoteService, packageName, callback, handler)); mRemoteService.scheduleRequest(new PendingGetAppPermissionRequest(mRemoteService, packageName, callback, handler == null ? mRemoteService.getHandler() : handler)); } /** Loading @@ -141,8 +147,8 @@ public final class RuntimePermissionPresenter { checkNotNull(packageName); checkNotNull(permissionName); mRemoteService.processMessage(obtainMessage(RemoteService::revokeAppPermissions, mRemoteService, packageName, permissionName)); mRemoteService.scheduleAsyncRequest(new PendingRevokeAppPermissionRequest(packageName, permissionName)); } /** Loading @@ -160,76 +166,87 @@ public final class RuntimePermissionPresenter { checkCollectionElementsNotNull(permissionNames, "permissionNames"); checkNotNull(callback); mRemoteService.processMessage(obtainMessage(RemoteService::countPermissionApps, mRemoteService, permissionNames, countOnlyGranted, countSystem, callback, handler)); mRemoteService.scheduleRequest(new PendingCountPermissionAppsRequest(mRemoteService, permissionNames, countOnlyGranted, countSystem, callback, handler == null ? mRemoteService.getHandler() : handler)); } private static final class RemoteService extends Handler implements ServiceConnection { /** * A connection to the remote service */ static final class RemoteService extends AbstractMultiplePendingRequestsRemoteService<RemoteService, IRuntimePermissionPresenter> { private static final long UNBIND_TIMEOUT_MILLIS = 10000; private static final long MESSAGE_TIMEOUT_MILLIS = 30000; public static final int MSG_UNBIND = 0; private final Object mLock = new Object(); private final Context mContext; @GuardedBy("mLock") private final List<Message> mPendingWork = new ArrayList<>(); @GuardedBy("mLock") private IRuntimePermissionPresenter mRemoteInstance; @GuardedBy("mLock") private boolean mBound; RemoteService(Context context) { super(context.getMainLooper(), null, false); mContext = context; /** * Create a connection to the remote service * * @param context A context to use * @param componentName The component of the service to connect to */ RemoteService(@NonNull Context context, @NonNull ComponentName componentName) { super(context, SERVICE_INTERFACE, componentName, UserHandle.myUserId(), service -> Log.e(TAG, "RuntimePermPresenterService " + service + " died"), false, false, 1); } public void processMessage(Message message) { synchronized (mLock) { if (!mBound) { Intent intent = new Intent( RuntimePermissionPresenterService.SERVICE_INTERFACE); intent.setPackage(mContext.getPackageManager() .getPermissionControllerPackageName()); mBound = mContext.bindService(intent, this, Context.BIND_AUTO_CREATE); } mPendingWork.add(message); scheduleNextMessageIfNeededLocked(); } /** * @return The default handler used by this service. */ Handler getHandler() { return mHandler; } @Override public void onServiceConnected(ComponentName name, IBinder service) { synchronized (mLock) { mRemoteInstance = IRuntimePermissionPresenter.Stub.asInterface(service); scheduleNextMessageIfNeededLocked(); protected @NonNull IRuntimePermissionPresenter getServiceInterface( @NonNull IBinder binder) { return IRuntimePermissionPresenter.Stub.asInterface(binder); } @Override protected long getTimeoutIdleBindMillis() { return UNBIND_TIMEOUT_MILLIS; } @Override public void onServiceDisconnected(ComponentName name) { synchronized (mLock) { mRemoteInstance = null; protected long getRemoteRequestMillis() { return MESSAGE_TIMEOUT_MILLIS; } @Override public void scheduleRequest(@NonNull PendingRequest<RemoteService, IRuntimePermissionPresenter> pendingRequest) { super.scheduleRequest(pendingRequest); } private void getAppPermissions(@NonNull String packageName, @NonNull OnGetAppPermissionResultCallback callback, @Nullable Handler handler) { final IRuntimePermissionPresenter remoteInstance; synchronized (mLock) { remoteInstance = mRemoteInstance; @Override public void scheduleAsyncRequest( @NonNull AsyncRequest<IRuntimePermissionPresenter> request) { super.scheduleAsyncRequest(request); } if (remoteInstance == null) { return; } try { remoteInstance.getAppPermissions(packageName, new RemoteCallback(result -> { /** * Request for {@link #getAppPermissions} */ private static final class PendingGetAppPermissionRequest extends AbstractRemoteService.PendingRequest<RemoteService, IRuntimePermissionPresenter> { private final @NonNull String mPackageName; private final @NonNull OnGetAppPermissionResultCallback mCallback; private final @NonNull RemoteCallback mRemoteCallback; private PendingGetAppPermissionRequest(@NonNull RemoteService service, @NonNull String packageName, @NonNull OnGetAppPermissionResultCallback callback, @NonNull Handler handler) { super(service); mPackageName = packageName; mCallback = callback; mRemoteCallback = new RemoteCallback(result -> { final List<RuntimePermissionPresentationInfo> reportedPermissions; List<RuntimePermissionPresentationInfo> permissions = null; if (result != null) { Loading @@ -239,58 +256,76 @@ public final class RuntimePermissionPresenter { permissions = Collections.emptyList(); } reportedPermissions = permissions; if (handler != null) { handler.post( () -> callback.onGetAppPermissions(reportedPermissions)); } else { callback.onGetAppPermissions(reportedPermissions); } }, this)); } catch (RemoteException re) { Log.e(TAG, "Error getting app permissions", re); } scheduleUnbind(); synchronized (mLock) { scheduleNextMessageIfNeededLocked(); } finish(); }, handler); } private void revokeAppPermissions(@NonNull String packageName, @NonNull String permissionName) { final IRuntimePermissionPresenter remoteInstance; synchronized (mLock) { remoteInstance = mRemoteInstance; } if (remoteInstance == null) { return; @Override protected void onTimeout(RemoteService remoteService) { mCallback.onGetAppPermissions(Collections.emptyList()); } @Override public void run() { try { remoteInstance.revokeRuntimePermission(packageName, permissionName); } catch (RemoteException re) { Log.e(TAG, "Error getting app permissions", re); getService().getServiceInterface().getAppPermissions(mPackageName, mRemoteCallback); } catch (RemoteException e) { Log.e(TAG, "Error getting app permission", e); } synchronized (mLock) { scheduleNextMessageIfNeededLocked(); } } private void countPermissionApps(@NonNull List<String> permissionNames, boolean countOnlyGranted, boolean countSystem, @NonNull OnCountPermissionAppsResultCallback callback, @Nullable Handler handler) { final IRuntimePermissionPresenter remoteInstance; /** * Request for {@link #revokeRuntimePermission} */ private static final class PendingRevokeAppPermissionRequest implements AbstractRemoteService.AsyncRequest<IRuntimePermissionPresenter> { private final @NonNull String mPackageName; private final @NonNull String mPermissionName; synchronized (mLock) { remoteInstance = mRemoteInstance; } if (remoteInstance == null) { return; private PendingRevokeAppPermissionRequest(@NonNull String packageName, @NonNull String permissionName) { mPackageName = packageName; mPermissionName = permissionName; } @Override public void run(IRuntimePermissionPresenter remoteInterface) { try { remoteInstance.countPermissionApps(permissionNames, countOnlyGranted, countSystem, new RemoteCallback(result -> { remoteInterface.revokeRuntimePermission(mPackageName, mPermissionName); } catch (RemoteException e) { Log.e(TAG, "Error revoking app permission", e); } } } /** * Request for {@link #countPermissionApps} */ private static final class PendingCountPermissionAppsRequest extends AbstractRemoteService.PendingRequest<RemoteService, IRuntimePermissionPresenter> { private final @NonNull List<String> mPermissionNames; private final @NonNull OnCountPermissionAppsResultCallback mCallback; private final boolean mCountOnlyGranted; private final boolean mCountSystem; private final @NonNull RemoteCallback mRemoteCallback; private PendingCountPermissionAppsRequest(@NonNull RemoteService service, @NonNull List<String> permissionNames, boolean countOnlyGranted, boolean countSystem, @NonNull OnCountPermissionAppsResultCallback callback, @NonNull Handler handler) { super(service); mPermissionNames = permissionNames; mCountOnlyGranted = countOnlyGranted; mCountSystem = countSystem; mCallback = callback; mRemoteCallback = new RemoteCallback(result -> { final int numApps; if (result != null) { numApps = result.getInt(KEY_RESULT); Loading @@ -298,45 +333,25 @@ public final class RuntimePermissionPresenter { numApps = 0; } if (handler != null) { handler.post(() -> callback.onCountPermissionApps(numApps)); } else { callback.onCountPermissionApps(numApps); } }, this)); } catch (RemoteException re) { Log.e(TAG, "Error counting permission apps", re); } scheduleUnbind(); synchronized (mLock) { scheduleNextMessageIfNeededLocked(); } finish(); }, handler); } private void unbind() { synchronized (mLock) { if (mBound) { mContext.unbindService(this); mBound = false; } mRemoteInstance = null; } @Override protected void onTimeout(RemoteService remoteService) { mCallback.onCountPermissionApps(0); } @GuardedBy("mLock") private void scheduleNextMessageIfNeededLocked() { if (mBound && mRemoteInstance != null && !mPendingWork.isEmpty()) { Message nextMessage = mPendingWork.remove(0); sendMessage(nextMessage); } @Override public void run() { try { getService().getServiceInterface().countPermissionApps(mPermissionNames, mCountOnlyGranted, mCountSystem, mRemoteCallback); } catch (RemoteException e) { Log.e(TAG, "Error counting permission apps", e); } private void scheduleUnbind() { removeMessages(MSG_UNBIND); sendMessageDelayed(PooledLambda.obtainMessage(RemoteService::unbind, this) .setWhat(MSG_UNBIND), UNBIND_TIMEOUT_MILLIS); } } } core/java/com/android/internal/infra/AbstractRemoteService.java +10 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.internal.infra; import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.ComponentName; import android.content.Context; import android.content.Intent; Loading Loading @@ -164,6 +165,15 @@ public abstract class AbstractRemoteService<S extends AbstractRemoteService<S, I */ protected abstract long getRemoteRequestMillis(); /** * Gets the currently registered service interface or {@code null} if the service is not * connected. */ @Nullable public final I getServiceInterface() { return mService; } private void handleDestroy() { if (checkIfDestroyed()) return; handleOnDestroy(); Loading Loading
core/java/android/permission/RuntimePermissionPresenter.java +168 −153 Original line number Diff line number Diff line Loading @@ -16,27 +16,28 @@ package android.permission; import static android.permission.RuntimePermissionPresenterService.SERVICE_INTERFACE; import static com.android.internal.util.Preconditions.checkCollectionElementsNotNull; import static com.android.internal.util.Preconditions.checkNotNull; import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.content.pm.ResolveInfo; import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.os.RemoteCallback; import android.os.RemoteException; import android.os.UserHandle; import android.util.Log; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.function.pooled.PooledLambda; import com.android.internal.infra.AbstractMultiplePendingRequestsRemoteService; import com.android.internal.infra.AbstractRemoteService; import java.util.ArrayList; import java.util.Collections; import java.util.List; Loading Loading @@ -80,7 +81,7 @@ public final class RuntimePermissionPresenter { */ public interface OnCountPermissionAppsResultCallback { /** * The result for {@link #countPermissionApps(List, boolean, * The result for {@link #countPermissionApps(List, boolean, boolean, * OnCountPermissionAppsResultCallback, Handler)}. * * @param numApps The number of apps that have one of the permissions Loading Loading @@ -110,8 +111,13 @@ public final class RuntimePermissionPresenter { } } private RuntimePermissionPresenter(Context context) { mRemoteService = new RemoteService(context); private RuntimePermissionPresenter(@NonNull Context context) { Intent intent = new Intent(SERVICE_INTERFACE); intent.setPackage(context.getPackageManager().getPermissionControllerPackageName()); ResolveInfo serviceInfo = context.getPackageManager().resolveService(intent, 0); mRemoteService = new RemoteService(context, serviceInfo.getComponentInfo().getComponentName()); } /** Loading @@ -126,8 +132,8 @@ public final class RuntimePermissionPresenter { checkNotNull(packageName); checkNotNull(callback); mRemoteService.processMessage(obtainMessage(RemoteService::getAppPermissions, mRemoteService, packageName, callback, handler)); mRemoteService.scheduleRequest(new PendingGetAppPermissionRequest(mRemoteService, packageName, callback, handler == null ? mRemoteService.getHandler() : handler)); } /** Loading @@ -141,8 +147,8 @@ public final class RuntimePermissionPresenter { checkNotNull(packageName); checkNotNull(permissionName); mRemoteService.processMessage(obtainMessage(RemoteService::revokeAppPermissions, mRemoteService, packageName, permissionName)); mRemoteService.scheduleAsyncRequest(new PendingRevokeAppPermissionRequest(packageName, permissionName)); } /** Loading @@ -160,76 +166,87 @@ public final class RuntimePermissionPresenter { checkCollectionElementsNotNull(permissionNames, "permissionNames"); checkNotNull(callback); mRemoteService.processMessage(obtainMessage(RemoteService::countPermissionApps, mRemoteService, permissionNames, countOnlyGranted, countSystem, callback, handler)); mRemoteService.scheduleRequest(new PendingCountPermissionAppsRequest(mRemoteService, permissionNames, countOnlyGranted, countSystem, callback, handler == null ? mRemoteService.getHandler() : handler)); } private static final class RemoteService extends Handler implements ServiceConnection { /** * A connection to the remote service */ static final class RemoteService extends AbstractMultiplePendingRequestsRemoteService<RemoteService, IRuntimePermissionPresenter> { private static final long UNBIND_TIMEOUT_MILLIS = 10000; private static final long MESSAGE_TIMEOUT_MILLIS = 30000; public static final int MSG_UNBIND = 0; private final Object mLock = new Object(); private final Context mContext; @GuardedBy("mLock") private final List<Message> mPendingWork = new ArrayList<>(); @GuardedBy("mLock") private IRuntimePermissionPresenter mRemoteInstance; @GuardedBy("mLock") private boolean mBound; RemoteService(Context context) { super(context.getMainLooper(), null, false); mContext = context; /** * Create a connection to the remote service * * @param context A context to use * @param componentName The component of the service to connect to */ RemoteService(@NonNull Context context, @NonNull ComponentName componentName) { super(context, SERVICE_INTERFACE, componentName, UserHandle.myUserId(), service -> Log.e(TAG, "RuntimePermPresenterService " + service + " died"), false, false, 1); } public void processMessage(Message message) { synchronized (mLock) { if (!mBound) { Intent intent = new Intent( RuntimePermissionPresenterService.SERVICE_INTERFACE); intent.setPackage(mContext.getPackageManager() .getPermissionControllerPackageName()); mBound = mContext.bindService(intent, this, Context.BIND_AUTO_CREATE); } mPendingWork.add(message); scheduleNextMessageIfNeededLocked(); } /** * @return The default handler used by this service. */ Handler getHandler() { return mHandler; } @Override public void onServiceConnected(ComponentName name, IBinder service) { synchronized (mLock) { mRemoteInstance = IRuntimePermissionPresenter.Stub.asInterface(service); scheduleNextMessageIfNeededLocked(); protected @NonNull IRuntimePermissionPresenter getServiceInterface( @NonNull IBinder binder) { return IRuntimePermissionPresenter.Stub.asInterface(binder); } @Override protected long getTimeoutIdleBindMillis() { return UNBIND_TIMEOUT_MILLIS; } @Override public void onServiceDisconnected(ComponentName name) { synchronized (mLock) { mRemoteInstance = null; protected long getRemoteRequestMillis() { return MESSAGE_TIMEOUT_MILLIS; } @Override public void scheduleRequest(@NonNull PendingRequest<RemoteService, IRuntimePermissionPresenter> pendingRequest) { super.scheduleRequest(pendingRequest); } private void getAppPermissions(@NonNull String packageName, @NonNull OnGetAppPermissionResultCallback callback, @Nullable Handler handler) { final IRuntimePermissionPresenter remoteInstance; synchronized (mLock) { remoteInstance = mRemoteInstance; @Override public void scheduleAsyncRequest( @NonNull AsyncRequest<IRuntimePermissionPresenter> request) { super.scheduleAsyncRequest(request); } if (remoteInstance == null) { return; } try { remoteInstance.getAppPermissions(packageName, new RemoteCallback(result -> { /** * Request for {@link #getAppPermissions} */ private static final class PendingGetAppPermissionRequest extends AbstractRemoteService.PendingRequest<RemoteService, IRuntimePermissionPresenter> { private final @NonNull String mPackageName; private final @NonNull OnGetAppPermissionResultCallback mCallback; private final @NonNull RemoteCallback mRemoteCallback; private PendingGetAppPermissionRequest(@NonNull RemoteService service, @NonNull String packageName, @NonNull OnGetAppPermissionResultCallback callback, @NonNull Handler handler) { super(service); mPackageName = packageName; mCallback = callback; mRemoteCallback = new RemoteCallback(result -> { final List<RuntimePermissionPresentationInfo> reportedPermissions; List<RuntimePermissionPresentationInfo> permissions = null; if (result != null) { Loading @@ -239,58 +256,76 @@ public final class RuntimePermissionPresenter { permissions = Collections.emptyList(); } reportedPermissions = permissions; if (handler != null) { handler.post( () -> callback.onGetAppPermissions(reportedPermissions)); } else { callback.onGetAppPermissions(reportedPermissions); } }, this)); } catch (RemoteException re) { Log.e(TAG, "Error getting app permissions", re); } scheduleUnbind(); synchronized (mLock) { scheduleNextMessageIfNeededLocked(); } finish(); }, handler); } private void revokeAppPermissions(@NonNull String packageName, @NonNull String permissionName) { final IRuntimePermissionPresenter remoteInstance; synchronized (mLock) { remoteInstance = mRemoteInstance; } if (remoteInstance == null) { return; @Override protected void onTimeout(RemoteService remoteService) { mCallback.onGetAppPermissions(Collections.emptyList()); } @Override public void run() { try { remoteInstance.revokeRuntimePermission(packageName, permissionName); } catch (RemoteException re) { Log.e(TAG, "Error getting app permissions", re); getService().getServiceInterface().getAppPermissions(mPackageName, mRemoteCallback); } catch (RemoteException e) { Log.e(TAG, "Error getting app permission", e); } synchronized (mLock) { scheduleNextMessageIfNeededLocked(); } } private void countPermissionApps(@NonNull List<String> permissionNames, boolean countOnlyGranted, boolean countSystem, @NonNull OnCountPermissionAppsResultCallback callback, @Nullable Handler handler) { final IRuntimePermissionPresenter remoteInstance; /** * Request for {@link #revokeRuntimePermission} */ private static final class PendingRevokeAppPermissionRequest implements AbstractRemoteService.AsyncRequest<IRuntimePermissionPresenter> { private final @NonNull String mPackageName; private final @NonNull String mPermissionName; synchronized (mLock) { remoteInstance = mRemoteInstance; } if (remoteInstance == null) { return; private PendingRevokeAppPermissionRequest(@NonNull String packageName, @NonNull String permissionName) { mPackageName = packageName; mPermissionName = permissionName; } @Override public void run(IRuntimePermissionPresenter remoteInterface) { try { remoteInstance.countPermissionApps(permissionNames, countOnlyGranted, countSystem, new RemoteCallback(result -> { remoteInterface.revokeRuntimePermission(mPackageName, mPermissionName); } catch (RemoteException e) { Log.e(TAG, "Error revoking app permission", e); } } } /** * Request for {@link #countPermissionApps} */ private static final class PendingCountPermissionAppsRequest extends AbstractRemoteService.PendingRequest<RemoteService, IRuntimePermissionPresenter> { private final @NonNull List<String> mPermissionNames; private final @NonNull OnCountPermissionAppsResultCallback mCallback; private final boolean mCountOnlyGranted; private final boolean mCountSystem; private final @NonNull RemoteCallback mRemoteCallback; private PendingCountPermissionAppsRequest(@NonNull RemoteService service, @NonNull List<String> permissionNames, boolean countOnlyGranted, boolean countSystem, @NonNull OnCountPermissionAppsResultCallback callback, @NonNull Handler handler) { super(service); mPermissionNames = permissionNames; mCountOnlyGranted = countOnlyGranted; mCountSystem = countSystem; mCallback = callback; mRemoteCallback = new RemoteCallback(result -> { final int numApps; if (result != null) { numApps = result.getInt(KEY_RESULT); Loading @@ -298,45 +333,25 @@ public final class RuntimePermissionPresenter { numApps = 0; } if (handler != null) { handler.post(() -> callback.onCountPermissionApps(numApps)); } else { callback.onCountPermissionApps(numApps); } }, this)); } catch (RemoteException re) { Log.e(TAG, "Error counting permission apps", re); } scheduleUnbind(); synchronized (mLock) { scheduleNextMessageIfNeededLocked(); } finish(); }, handler); } private void unbind() { synchronized (mLock) { if (mBound) { mContext.unbindService(this); mBound = false; } mRemoteInstance = null; } @Override protected void onTimeout(RemoteService remoteService) { mCallback.onCountPermissionApps(0); } @GuardedBy("mLock") private void scheduleNextMessageIfNeededLocked() { if (mBound && mRemoteInstance != null && !mPendingWork.isEmpty()) { Message nextMessage = mPendingWork.remove(0); sendMessage(nextMessage); } @Override public void run() { try { getService().getServiceInterface().countPermissionApps(mPermissionNames, mCountOnlyGranted, mCountSystem, mRemoteCallback); } catch (RemoteException e) { Log.e(TAG, "Error counting permission apps", e); } private void scheduleUnbind() { removeMessages(MSG_UNBIND); sendMessageDelayed(PooledLambda.obtainMessage(RemoteService::unbind, this) .setWhat(MSG_UNBIND), UNBIND_TIMEOUT_MILLIS); } } }
core/java/com/android/internal/infra/AbstractRemoteService.java +10 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.internal.infra; import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.ComponentName; import android.content.Context; import android.content.Intent; Loading Loading @@ -164,6 +165,15 @@ public abstract class AbstractRemoteService<S extends AbstractRemoteService<S, I */ protected abstract long getRemoteRequestMillis(); /** * Gets the currently registered service interface or {@code null} if the service is not * connected. */ @Nullable public final I getServiceInterface() { return mService; } private void handleDestroy() { if (checkIfDestroyed()) return; handleOnDestroy(); Loading