2 * Copyright (C) 2016 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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
17 package com.android.server.am;
19 import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
21 import android.app.AppOpsManager;
22 import android.app.Notification;
23 import android.app.NotificationManager;
24 import android.app.PendingIntent;
25 import android.content.ComponentName;
26 import android.content.Context;
27 import android.content.IIntentReceiver;
28 import android.content.Intent;
29 import android.content.pm.ResolveInfo;
30 import android.os.Bundle;
31 import android.os.Handler;
32 import android.os.Message;
33 import android.os.Process;
34 import android.os.UserHandle;
35 import android.util.Slog;
37 import com.android.internal.R;
38 import com.android.internal.util.ProgressReporter;
39 import com.android.server.UiThread;
41 import java.util.List;
44 * Simple broadcaster that sends {@link Intent#ACTION_PRE_BOOT_COMPLETED} to all
45 * system apps that register for it. Override {@link #onFinished()} to handle
46 * when all broadcasts are finished.
48 public abstract class PreBootBroadcaster extends IIntentReceiver.Stub {
49 private static final String TAG = "PreBootBroadcaster";
51 private final ActivityManagerService mService;
52 private final int mUserId;
53 private final ProgressReporter mProgress;
54 private final boolean mQuiet;
56 private final Intent mIntent;
57 private final List<ResolveInfo> mTargets;
59 private int mIndex = 0;
61 public PreBootBroadcaster(ActivityManagerService service, int userId,
62 ProgressReporter progress, boolean quiet) {
68 mIntent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
69 mIntent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE | Intent.FLAG_DEBUG_TRIAGED_MISSING);
71 mTargets = mService.mContext.getPackageManager().queryBroadcastReceiversAsUser(mIntent,
72 MATCH_SYSTEM_ONLY, UserHandle.of(userId));
75 public void sendNext() {
76 if (mIndex >= mTargets.size()) {
77 mHandler.obtainMessage(MSG_HIDE).sendToTarget();
82 if (!mService.isUserRunning(mUserId, 0)) {
83 Slog.i(TAG, "User " + mUserId + " is no longer running; skipping remaining receivers");
84 mHandler.obtainMessage(MSG_HIDE).sendToTarget();
90 mHandler.obtainMessage(MSG_SHOW, mTargets.size(), mIndex).sendToTarget();
93 final ResolveInfo ri = mTargets.get(mIndex++);
94 final ComponentName componentName = ri.activityInfo.getComponentName();
96 if (mProgress != null) {
97 final CharSequence label = ri.activityInfo
98 .loadLabel(mService.mContext.getPackageManager());
99 mProgress.setProgress(mIndex, mTargets.size(),
100 mService.mContext.getString(R.string.android_preparing_apk, label));
103 Slog.i(TAG, "Pre-boot of " + componentName.toShortString() + " for user " + mUserId);
104 EventLogTags.writeAmPreBoot(mUserId, componentName.getPackageName());
106 mIntent.setComponent(componentName);
107 mService.broadcastIntentLocked(null, null, mIntent, null, this, 0, null, null, null,
108 AppOpsManager.OP_NONE, null, true, false, ActivityManagerService.MY_PID,
109 Process.SYSTEM_UID, mUserId);
113 public void performReceive(Intent intent, int resultCode, String data, Bundle extras,
114 boolean ordered, boolean sticky, int sendingUser) {
118 private static final int MSG_SHOW = 1;
119 private static final int MSG_HIDE = 2;
121 private Handler mHandler = new Handler(UiThread.get().getLooper(), null, true) {
123 public void handleMessage(Message msg) {
124 final Context context = mService.mContext;
125 final NotificationManager notifManager = context
126 .getSystemService(NotificationManager.class);
127 final int max = msg.arg1;
128 final int index = msg.arg2;
132 final CharSequence title = context
133 .getText(R.string.android_upgrading_notification_title);
135 final Intent intent = new Intent();
136 intent.setClassName("com.android.settings",
137 "com.android.settings.HelpTrampoline");
138 intent.putExtra(Intent.EXTRA_TEXT, "help_url_upgrading");
140 final PendingIntent contentIntent;
141 if (context.getPackageManager().resolveActivity(intent, 0) != null) {
142 contentIntent = PendingIntent.getActivity(context, 0, intent, 0);
144 contentIntent = null;
147 final Notification notif = new Notification.Builder(mService.mContext)
148 .setSmallIcon(R.drawable.stat_sys_adb)
153 .setPriority(Notification.PRIORITY_MAX)
154 .setColor(context.getColor(
155 com.android.internal.R.color.system_notification_accent_color))
156 .setContentTitle(title)
157 .setContentIntent(contentIntent)
158 .setVisibility(Notification.VISIBILITY_PUBLIC)
159 .setProgress(max, index, false)
161 notifManager.notifyAsUser(TAG, 0, notif, UserHandle.of(mUserId));
165 notifManager.cancelAsUser(TAG, 0, UserHandle.of(mUserId));
171 public abstract void onFinished();