PreBootBroadcaster.java revision 100bd9c24a06e3b139ad51526c3eec9cbcff68ee
1/*
2 * Copyright (C) 2016 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
17package com.android.server.am;
18
19import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
20
21import android.app.AppOpsManager;
22import android.content.ComponentName;
23import android.content.IIntentReceiver;
24import android.content.Intent;
25import android.content.pm.ResolveInfo;
26import android.os.Bundle;
27import android.os.Process;
28import android.os.UserHandle;
29import android.util.Slog;
30
31import com.android.internal.R;
32import com.android.internal.util.ProgressReporter;
33
34import java.util.List;
35
36/**
37 * Simple broadcaster that sends {@link Intent#ACTION_PRE_BOOT_COMPLETED} to all
38 * system apps that register for it. Override {@link #onFinished()} to handle
39 * when all broadcasts are finished.
40 */
41public abstract class PreBootBroadcaster extends IIntentReceiver.Stub {
42    private static final String TAG = "PreBootBroadcaster";
43
44    private final ActivityManagerService mService;
45    private final int mUserId;
46    private final ProgressReporter mProgress;
47
48    private final Intent mIntent;
49    private final List<ResolveInfo> mTargets;
50
51    private int mIndex = 0;
52
53    public PreBootBroadcaster(ActivityManagerService service, int userId,
54            ProgressReporter progress) {
55        mService = service;
56        mUserId = userId;
57        mProgress = progress;
58
59        mIntent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
60        mIntent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE | Intent.FLAG_DEBUG_TRIAGED_MISSING);
61
62        mTargets = mService.mContext.getPackageManager().queryBroadcastReceiversAsUser(mIntent,
63                MATCH_SYSTEM_ONLY, UserHandle.of(userId));
64    }
65
66    public void sendNext() {
67        if (mIndex >= mTargets.size()) {
68            onFinished();
69            return;
70        }
71
72        if (!mService.isUserRunning(mUserId, 0)) {
73            Slog.i(TAG, "User " + mUserId + " is no longer running; skipping remaining receivers");
74            onFinished();
75            return;
76        }
77
78        final ResolveInfo ri = mTargets.get(mIndex++);
79        final ComponentName componentName = ri.activityInfo.getComponentName();
80
81        final CharSequence label = ri.activityInfo.loadLabel(mService.mContext.getPackageManager());
82        mProgress.setProgress(mIndex, mTargets.size(),
83                mService.mContext.getString(R.string.android_preparing_apk, label));
84
85        Slog.i(TAG, "Pre-boot of " + componentName.toShortString() + " for user " + mUserId);
86        EventLogTags.writeAmPreBoot(mUserId, componentName.getPackageName());
87
88        mIntent.setComponent(componentName);
89        mService.broadcastIntentLocked(null, null, mIntent, null, this, 0, null, null, null,
90                AppOpsManager.OP_NONE, null, true, false, ActivityManagerService.MY_PID,
91                Process.SYSTEM_UID, mUserId);
92    }
93
94    @Override
95    public void performReceive(Intent intent, int resultCode, String data, Bundle extras,
96            boolean ordered, boolean sticky, int sendingUser) {
97        sendNext();
98    }
99
100    public abstract void onFinished();
101}
102