| /* |
| * Copyright (C) 2018 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 android.app.admin; |
| |
| import static android.app.admin.DeviceAdminReceiver.ACTION_CHOOSE_PRIVATE_KEY_ALIAS; |
| import static android.app.admin.DeviceAdminReceiver.ACTION_NETWORK_LOGS_AVAILABLE; |
| import static android.app.admin.DeviceAdminReceiver.EXTRA_CHOOSE_PRIVATE_KEY_ALIAS; |
| import static android.app.admin.DeviceAdminReceiver.EXTRA_CHOOSE_PRIVATE_KEY_SENDER_UID; |
| import static android.app.admin.DeviceAdminReceiver.EXTRA_CHOOSE_PRIVATE_KEY_URI; |
| import static android.app.admin.DeviceAdminReceiver.EXTRA_NETWORK_LOGS_COUNT; |
| import static android.app.admin.DeviceAdminReceiver.EXTRA_NETWORK_LOGS_TOKEN; |
| |
| import android.annotation.IntRange; |
| import android.annotation.NonNull; |
| import android.annotation.Nullable; |
| import android.app.Service; |
| import android.content.BroadcastReceiver; |
| import android.content.Context; |
| import android.content.Intent; |
| import android.net.Uri; |
| import android.security.KeyChain; |
| import android.util.Log; |
| |
| /** |
| * Base class for delegated apps to handle callbacks related to their delegated capabilities. |
| * |
| * <p>Delegated apps are apps that receive additional capabilities from the profile owner or |
| * device owner apps. Some of these capabilities involve the framework calling into the apps. |
| * To receive these callbacks, delegated apps should subclass this class and override the |
| * appropriate methods here. The subclassed receiver needs to be published in the app's |
| * manifest, with appropriate intent filters to mark which callbacks the receiver is interested |
| * in. An app can have multiple receivers as long as they listen for disjoint set of callbacks. |
| * For the manifest definitions, it must be protected by the |
| * {@link android.Manifest.permission#BIND_DEVICE_ADMIN} permission to ensure only |
| * the system can trigger these callbacks. |
| * |
| * <p>The callback methods happen on the main thread of the process. Thus long running |
| * operations must be done on another thread. Note that because a receiver |
| * is done once returning from its onReceive function, such long-running operations |
| * should probably be done in a {@link Service}. |
| * |
| * @see DevicePolicyManager#setDelegatedScopes |
| * @see DeviceAdminReceiver |
| */ |
| public class DelegatedAdminReceiver extends BroadcastReceiver { |
| private static final String TAG = "DelegatedAdminReceiver"; |
| |
| /** |
| * Allows this receiver to select the alias for a private key and certificate pair for |
| * authentication. If this method returns null, the default {@link android.app.Activity} will |
| * be shown that lets the user pick a private key and certificate pair. |
| * |
| * <p> This callback is only applicable if the delegated app has |
| * {@link DevicePolicyManager#DELEGATION_CERT_SELECTION} capability. Additionally, it must |
| * declare an intent filter for {@link DeviceAdminReceiver#ACTION_CHOOSE_PRIVATE_KEY_ALIAS} |
| * in the receiver's manifest in order to receive this callback. The default implementation |
| * simply throws {@link UnsupportedOperationException}. |
| * |
| * @param context The running context as per {@link #onReceive}. |
| * @param intent The received intent as per {@link #onReceive}. |
| * @param uid The uid of the app asking for the private key and certificate pair. |
| * @param uri The URI to authenticate, may be null. |
| * @param alias The alias preselected by the client, or null. |
| * @return The private key alias to return and grant access to. |
| * @see KeyChain#choosePrivateKeyAlias |
| */ |
| public @Nullable String onChoosePrivateKeyAlias(@NonNull Context context, |
| @NonNull Intent intent, int uid, @Nullable Uri uri, @Nullable String alias) { |
| throw new UnsupportedOperationException("onChoosePrivateKeyAlias should be implemented"); |
| } |
| |
| /** |
| * Called each time a new batch of network logs can be retrieved. This callback method will only |
| * ever be called when network logging is enabled. The logs can only be retrieved while network |
| * logging is enabled. |
| * |
| * <p>If a secondary user or profile is created, this callback won't be received until all users |
| * become affiliated again (even if network logging is enabled). It will also no longer be |
| * possible to retrieve the network logs batch with the most recent {@code batchToken} provided |
| * by this callback. See {@link DevicePolicyManager#setAffiliationIds}. |
| * |
| * <p> This callback is only applicable if the delegated app has |
| * {@link DevicePolicyManager#DELEGATION_NETWORK_LOGGING} capability. Additionally, it must |
| * declare an intent filter for {@link DeviceAdminReceiver#ACTION_NETWORK_LOGS_AVAILABLE} in the |
| * receiver's manifest in order to receive this callback. The default implementation |
| * simply throws {@link UnsupportedOperationException}. |
| * |
| * @param context The running context as per {@link #onReceive}. |
| * @param intent The received intent as per {@link #onReceive}. |
| * @param batchToken The token representing the current batch of network logs. |
| * @param networkLogsCount The total count of events in the current batch of network logs. |
| * @see DevicePolicyManager#retrieveNetworkLogs |
| */ |
| public void onNetworkLogsAvailable(@NonNull Context context, @NonNull Intent intent, |
| long batchToken, @IntRange(from = 1) int networkLogsCount) { |
| throw new UnsupportedOperationException("onNetworkLogsAvailable should be implemented"); |
| } |
| |
| /** |
| * Intercept delegated device administrator broadcasts. Implementations should not override |
| * this method; implement the convenience callbacks for each action instead. |
| */ |
| @Override |
| public final void onReceive(@NonNull Context context, @NonNull Intent intent) { |
| String action = intent.getAction(); |
| |
| if (ACTION_CHOOSE_PRIVATE_KEY_ALIAS.equals(action)) { |
| int uid = intent.getIntExtra(EXTRA_CHOOSE_PRIVATE_KEY_SENDER_UID, -1); |
| Uri uri = intent.getParcelableExtra(EXTRA_CHOOSE_PRIVATE_KEY_URI); |
| String alias = intent.getStringExtra(EXTRA_CHOOSE_PRIVATE_KEY_ALIAS); |
| String chosenAlias = onChoosePrivateKeyAlias(context, intent, uid, uri, alias); |
| setResultData(chosenAlias); |
| } else if (ACTION_NETWORK_LOGS_AVAILABLE.equals(action)) { |
| long batchToken = intent.getLongExtra(EXTRA_NETWORK_LOGS_TOKEN, -1); |
| int networkLogsCount = intent.getIntExtra(EXTRA_NETWORK_LOGS_COUNT, 0); |
| onNetworkLogsAvailable(context, intent, batchToken, networkLogsCount); |
| } else { |
| Log.w(TAG, "Unhandled broadcast: " + action); |
| } |
| } |
| } |