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 17 package com.android.server.am; 18 19 import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY; 20 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.Binder; 31 import android.os.Bundle; 32 import android.os.Handler; 33 import android.os.Message; 34 import android.os.Process; 35 import android.os.UserHandle; 36 import android.util.Slog; 37 38 import com.android.internal.R; 39 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; 40 import com.android.internal.notification.SystemNotificationChannels; 41 import com.android.internal.util.ProgressReporter; 42 import com.android.server.UiThread; 43 44 import java.util.List; 45 46 /** 47 * Simple broadcaster that sends {@link Intent#ACTION_PRE_BOOT_COMPLETED} to all 48 * system apps that register for it. Override {@link #onFinished()} to handle 49 * when all broadcasts are finished. 50 */ 51 public abstract class PreBootBroadcaster extends IIntentReceiver.Stub { 52 private static final String TAG = "PreBootBroadcaster"; 53 54 private final ActivityManagerService mService; 55 private final int mUserId; 56 private final ProgressReporter mProgress; 57 private final boolean mQuiet; 58 59 private final Intent mIntent; 60 private final List<ResolveInfo> mTargets; 61 62 private int mIndex = 0; 63 64 public PreBootBroadcaster(ActivityManagerService service, int userId, 65 ProgressReporter progress, boolean quiet) { 66 mService = service; 67 mUserId = userId; 68 mProgress = progress; 69 mQuiet = quiet; 70 71 mIntent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED); 72 mIntent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE | Intent.FLAG_DEBUG_TRIAGED_MISSING); 73 74 mTargets = mService.mContext.getPackageManager().queryBroadcastReceiversAsUser(mIntent, 75 MATCH_SYSTEM_ONLY, UserHandle.of(userId)); 76 } 77 78 public void sendNext() { 79 if (mIndex >= mTargets.size()) { 80 mHandler.obtainMessage(MSG_HIDE).sendToTarget(); 81 onFinished(); 82 return; 83 } 84 85 if (!mService.isUserRunning(mUserId, 0)) { 86 Slog.i(TAG, "User " + mUserId + " is no longer running; skipping remaining receivers"); 87 mHandler.obtainMessage(MSG_HIDE).sendToTarget(); 88 onFinished(); 89 return; 90 } 91 92 if (!mQuiet) { 93 mHandler.obtainMessage(MSG_SHOW, mTargets.size(), mIndex).sendToTarget(); 94 } 95 96 final ResolveInfo ri = mTargets.get(mIndex++); 97 final ComponentName componentName = ri.activityInfo.getComponentName(); 98 99 if (mProgress != null) { 100 final CharSequence label = ri.activityInfo 101 .loadLabel(mService.mContext.getPackageManager()); 102 mProgress.setProgress(mIndex, mTargets.size(), 103 mService.mContext.getString(R.string.android_preparing_apk, label)); 104 } 105 106 Slog.i(TAG, "Pre-boot of " + componentName.toShortString() + " for user " + mUserId); 107 EventLogTags.writeAmPreBoot(mUserId, componentName.getPackageName()); 108 109 mIntent.setComponent(componentName); 110 synchronized (mService) { 111 mService.broadcastIntentLocked(null, null, mIntent, null, this, 0, null, null, null, 112 AppOpsManager.OP_NONE, null, true, false, ActivityManagerService.MY_PID, 113 Process.SYSTEM_UID, Binder.getCallingUid(), Binder.getCallingPid(), mUserId); 114 } 115 } 116 117 @Override 118 public void performReceive(Intent intent, int resultCode, String data, Bundle extras, 119 boolean ordered, boolean sticky, int sendingUser) { 120 sendNext(); 121 } 122 123 private static final int MSG_SHOW = 1; 124 private static final int MSG_HIDE = 2; 125 126 private Handler mHandler = new Handler(UiThread.get().getLooper(), null, true) { 127 @Override 128 public void handleMessage(Message msg) { 129 final Context context = mService.mContext; 130 final NotificationManager notifManager = context 131 .getSystemService(NotificationManager.class); 132 final int max = msg.arg1; 133 final int index = msg.arg2; 134 135 switch (msg.what) { 136 case MSG_SHOW: 137 final CharSequence title = context 138 .getText(R.string.android_upgrading_notification_title); 139 140 final Intent intent = new Intent(); 141 intent.setClassName("com.android.settings", 142 "com.android.settings.HelpTrampoline"); 143 intent.putExtra(Intent.EXTRA_TEXT, "help_url_upgrading"); 144 145 final PendingIntent contentIntent; 146 if (context.getPackageManager().resolveActivity(intent, 0) != null) { 147 contentIntent = PendingIntent.getActivity(context, 0, intent, 0); 148 } else { 149 contentIntent = null; 150 } 151 152 final Notification notif = 153 new Notification.Builder(mService.mContext, 154 SystemNotificationChannels.UPDATES) 155 .setSmallIcon(R.drawable.stat_sys_adb) 156 .setWhen(0) 157 .setOngoing(true) 158 .setTicker(title) 159 .setColor(context.getColor( 160 com.android.internal.R.color.system_notification_accent_color)) 161 .setContentTitle(title) 162 .setContentIntent(contentIntent) 163 .setVisibility(Notification.VISIBILITY_PUBLIC) 164 .setProgress(max, index, false) 165 .build(); 166 notifManager.notifyAsUser(TAG, SystemMessage.NOTE_SYSTEM_UPGRADING, notif, 167 UserHandle.of(mUserId)); 168 break; 169 170 case MSG_HIDE: 171 notifManager.cancelAsUser(TAG, SystemMessage.NOTE_SYSTEM_UPGRADING, 172 UserHandle.of(mUserId)); 173 break; 174 } 175 } 176 }; 177 178 public abstract void onFinished(); 179 } 180