1 /* 2 * Copyright (C) 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.devicelockcontroller.receivers; 18 19 import android.content.BroadcastReceiver; 20 import android.content.ComponentName; 21 import android.content.Context; 22 import android.content.Intent; 23 import android.content.pm.PackageManager; 24 25 import androidx.annotation.VisibleForTesting; 26 27 import com.android.devicelockcontroller.schedule.DeviceLockControllerScheduler; 28 import com.android.devicelockcontroller.schedule.DeviceLockControllerSchedulerProvider; 29 import com.android.devicelockcontroller.util.LogUtil; 30 31 import com.google.common.util.concurrent.ListenableFuture; 32 33 import java.util.concurrent.Executor; 34 import java.util.concurrent.Executors; 35 36 /** 37 * Boot completed broadcast receiver to enqueue the check-in work for provision when device boots 38 * for the first time. 39 * 40 * Only runs on system user and is disabled after check-in completes successfully. 41 */ 42 public final class CheckInBootCompletedReceiver extends BroadcastReceiver { 43 44 private static final String TAG = "CheckInBootCompletedReceiver"; 45 private final Executor mExecutor; 46 CheckInBootCompletedReceiver()47 public CheckInBootCompletedReceiver() { 48 mExecutor = Executors.newSingleThreadExecutor(); 49 } 50 51 @VisibleForTesting CheckInBootCompletedReceiver(Executor executor)52 CheckInBootCompletedReceiver(Executor executor) { 53 mExecutor = executor; 54 } 55 56 @Override onReceive(Context context, Intent intent)57 public void onReceive(Context context, Intent intent) { 58 if (!intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) return; 59 60 LogUtil.i(TAG, "Received boot completed intent"); 61 62 if (!context.getUser().isSystem()) { 63 // This is not *supposed* to happen since the receiver is marked systemUserOnly but 64 // there seems to be some edge case where it does. See b/304318606. 65 // In this case, we'll just disable and return early. 66 LogUtil.w(TAG, "Called check in boot receiver on non-system user!"); 67 disableCheckInBootCompletedReceiver(context); 68 return; 69 } 70 71 final DeviceLockControllerSchedulerProvider schedulerProvider = 72 (DeviceLockControllerSchedulerProvider) context.getApplicationContext(); 73 final DeviceLockControllerScheduler scheduler = 74 schedulerProvider.getDeviceLockControllerScheduler(); 75 76 ListenableFuture<Void> scheduleCheckIn = scheduler.maybeScheduleInitialCheckIn(); 77 78 final PendingResult pendingResult = goAsync(); 79 80 scheduleCheckIn.addListener(pendingResult::finish, mExecutor); 81 } 82 83 /** 84 * Disable the receiver for the current user 85 * 86 * @param context context of current user 87 */ disableCheckInBootCompletedReceiver(Context context)88 public static void disableCheckInBootCompletedReceiver(Context context) { 89 context.getPackageManager().setComponentEnabledSetting( 90 new ComponentName(context, CheckInBootCompletedReceiver.class), 91 PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP); 92 } 93 } 94