OSDN Git Service

DO NOT MERGE. Grant MMS Uri permissions as the calling UID.
[android-x86/frameworks-base.git] / services / core / java / com / android / server / am / PreBootBroadcaster.java
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.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;
36
37 import com.android.internal.R;
38 import com.android.internal.util.ProgressReporter;
39 import com.android.server.UiThread;
40
41 import java.util.List;
42
43 /**
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.
47  */
48 public abstract class PreBootBroadcaster extends IIntentReceiver.Stub {
49     private static final String TAG = "PreBootBroadcaster";
50
51     private final ActivityManagerService mService;
52     private final int mUserId;
53     private final ProgressReporter mProgress;
54     private final boolean mQuiet;
55
56     private final Intent mIntent;
57     private final List<ResolveInfo> mTargets;
58
59     private int mIndex = 0;
60
61     public PreBootBroadcaster(ActivityManagerService service, int userId,
62             ProgressReporter progress, boolean quiet) {
63         mService = service;
64         mUserId = userId;
65         mProgress = progress;
66         mQuiet = quiet;
67
68         mIntent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
69         mIntent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE | Intent.FLAG_DEBUG_TRIAGED_MISSING);
70
71         mTargets = mService.mContext.getPackageManager().queryBroadcastReceiversAsUser(mIntent,
72                 MATCH_SYSTEM_ONLY, UserHandle.of(userId));
73     }
74
75     public void sendNext() {
76         if (mIndex >= mTargets.size()) {
77             mHandler.obtainMessage(MSG_HIDE).sendToTarget();
78             onFinished();
79             return;
80         }
81
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();
85             onFinished();
86             return;
87         }
88
89         if (!mQuiet) {
90             mHandler.obtainMessage(MSG_SHOW, mTargets.size(), mIndex).sendToTarget();
91         }
92
93         final ResolveInfo ri = mTargets.get(mIndex++);
94         final ComponentName componentName = ri.activityInfo.getComponentName();
95
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));
101         }
102
103         Slog.i(TAG, "Pre-boot of " + componentName.toShortString() + " for user " + mUserId);
104         EventLogTags.writeAmPreBoot(mUserId, componentName.getPackageName());
105
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);
110     }
111
112     @Override
113     public void performReceive(Intent intent, int resultCode, String data, Bundle extras,
114             boolean ordered, boolean sticky, int sendingUser) {
115         sendNext();
116     }
117
118     private static final int MSG_SHOW = 1;
119     private static final int MSG_HIDE = 2;
120
121     private Handler mHandler = new Handler(UiThread.get().getLooper(), null, true) {
122         @Override
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;
129
130             switch (msg.what) {
131                 case MSG_SHOW:
132                     final CharSequence title = context
133                             .getText(R.string.android_upgrading_notification_title);
134
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");
139
140                     final PendingIntent contentIntent;
141                     if (context.getPackageManager().resolveActivity(intent, 0) != null) {
142                         contentIntent = PendingIntent.getActivity(context, 0, intent, 0);
143                     } else {
144                         contentIntent = null;
145                     }
146
147                     final Notification notif = new Notification.Builder(mService.mContext)
148                             .setSmallIcon(R.drawable.stat_sys_adb)
149                             .setWhen(0)
150                             .setOngoing(true)
151                             .setTicker(title)
152                             .setDefaults(0)
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)
160                             .build();
161                     notifManager.notifyAsUser(TAG, 0, notif, UserHandle.of(mUserId));
162                     break;
163
164                 case MSG_HIDE:
165                     notifManager.cancelAsUser(TAG, 0, UserHandle.of(mUserId));
166                     break;
167             }
168         }
169     };
170
171     public abstract void onFinished();
172 }