OSDN Git Service

Merge "Revert "Sanitize app op service inputs"" into nyc-dev
[android-x86/frameworks-base.git] / services / core / java / com / android / server / am / ActivityStartInterceptor.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.app.ActivityManager.INTENT_SENDER_ACTIVITY;
20 import static android.app.PendingIntent.FLAG_CANCEL_CURRENT;
21 import static android.app.PendingIntent.FLAG_IMMUTABLE;
22 import static android.app.PendingIntent.FLAG_ONE_SHOT;
23 import static android.content.Context.KEYGUARD_SERVICE;
24 import static android.content.Intent.EXTRA_INTENT;
25 import static android.content.Intent.EXTRA_PACKAGE_NAME;
26 import static android.content.Intent.EXTRA_TASK_ID;
27 import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
28 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
29 import static android.content.pm.ApplicationInfo.FLAG_SUSPENDED;
30
31 import android.app.KeyguardManager;
32 import android.app.admin.DevicePolicyManagerInternal;
33 import android.content.IIntentSender;
34 import android.content.Intent;
35 import android.content.IntentSender;
36 import android.content.pm.ActivityInfo;
37 import android.content.pm.ResolveInfo;
38 import android.content.pm.UserInfo;
39 import android.os.Binder;
40 import android.os.UserHandle;
41 import android.os.UserManager;
42
43 import com.android.internal.app.UnlaunchableAppActivity;
44 import com.android.server.LocalServices;
45
46 /**
47  * A class that contains activity intercepting logic for {@link ActivityStarter#startActivityLocked}
48  * It's initialized
49  */
50 class ActivityStartInterceptor {
51
52     private final ActivityManagerService mService;
53     private UserManager mUserManager;
54     private final ActivityStackSupervisor mSupervisor;
55
56     /*
57      * Per-intent states loaded from ActivityStarter than shouldn't be changed by any
58      * interception routines.
59      */
60     private int mRealCallingPid;
61     private int mRealCallingUid;
62     private int mUserId;
63     private int mStartFlags;
64     private String mCallingPackage;
65
66     /*
67      * Per-intent states that were load from ActivityStarter and are subject to modifications
68      * by the interception routines. After calling {@link #intercept} the caller should assign
69      * these values back to {@link ActivityStarter#startActivityLocked}'s local variables.
70      */
71     Intent mIntent;
72     int mCallingPid;
73     int mCallingUid;
74     ResolveInfo mRInfo;
75     ActivityInfo mAInfo;
76     String mResolvedType;
77     TaskRecord mInTask;
78
79     ActivityStartInterceptor(ActivityManagerService service, ActivityStackSupervisor supervisor) {
80         mService = service;
81         mSupervisor = supervisor;
82     }
83
84     void setStates(int userId, int realCallingPid, int realCallingUid, int startFlags,
85             String callingPackage) {
86         mRealCallingPid = realCallingPid;
87         mRealCallingUid = realCallingUid;
88         mUserId = userId;
89         mStartFlags = startFlags;
90         mCallingPackage = callingPackage;
91     }
92
93     void intercept(Intent intent, ResolveInfo rInfo, ActivityInfo aInfo, String resolvedType,
94             TaskRecord inTask, int callingPid, int callingUid) {
95         mUserManager = UserManager.get(mService.mContext);
96         mIntent = intent;
97         mCallingPid = callingPid;
98         mCallingUid = callingUid;
99         mRInfo = rInfo;
100         mAInfo = aInfo;
101         mResolvedType = resolvedType;
102         mInTask = inTask;
103         if (interceptSuspendPackageIfNeed()) {
104             // Skip the rest of interceptions as the package is suspended by device admin so
105             // no user action can undo this.
106             return;
107         }
108         if (interceptQuietProfileIfNeeded()) {
109             // If work profile is turned off, skip the work challenge since the profile can only
110             // be unlocked when profile's user is running.
111             return;
112         }
113         interceptWorkProfileChallengeIfNeeded();
114     }
115
116     private boolean interceptQuietProfileIfNeeded() {
117         // Do not intercept if the user has not turned off the profile
118         if (!mUserManager.isQuietModeEnabled(UserHandle.of(mUserId))) {
119             return false;
120         }
121         mIntent = UnlaunchableAppActivity.createInQuietModeDialogIntent(mUserId);
122         mCallingPid = mRealCallingPid;
123         mCallingUid = mRealCallingUid;
124         mResolvedType = null;
125
126         final UserInfo parent = mUserManager.getProfileParent(mUserId);
127         mRInfo = mSupervisor.resolveIntent(mIntent, mResolvedType, parent.id);
128         mAInfo = mSupervisor.resolveActivity(mIntent, mRInfo, mStartFlags, null /*profilerInfo*/);
129         return true;
130     }
131
132     private boolean interceptSuspendPackageIfNeed() {
133         // Do not intercept if the admin did not suspend the package
134         if (mAInfo == null || mAInfo.applicationInfo == null ||
135                 (mAInfo.applicationInfo.flags & FLAG_SUSPENDED) == 0) {
136             return false;
137         }
138         DevicePolicyManagerInternal devicePolicyManager = LocalServices.getService(
139                 DevicePolicyManagerInternal.class);
140         mIntent = devicePolicyManager.createPackageSuspendedDialogIntent(
141                 mAInfo.packageName, mUserId);
142         mCallingPid = mRealCallingPid;
143         mCallingUid = mRealCallingUid;
144         mResolvedType = null;
145
146         final UserInfo parent = mUserManager.getProfileParent(mUserId);
147         if (parent != null) {
148             mRInfo = mSupervisor.resolveIntent(mIntent, mResolvedType, parent.id);
149         } else {
150             mRInfo = mSupervisor.resolveIntent(mIntent, mResolvedType, mUserId);
151         }
152         mAInfo = mSupervisor.resolveActivity(mIntent, mRInfo, mStartFlags, null /*profilerInfo*/);
153         return true;
154     }
155
156     private boolean interceptWorkProfileChallengeIfNeeded() {
157         final Intent interceptingIntent = interceptWithConfirmCredentialsIfNeeded(mIntent,
158                 mResolvedType, mAInfo, mCallingPackage, mUserId);
159         if (interceptingIntent == null) {
160             return false;
161         }
162         mIntent = interceptingIntent;
163         mCallingPid = mRealCallingPid;
164         mCallingUid = mRealCallingUid;
165         mResolvedType = null;
166         // If we are intercepting and there was a task, convert it into an extra for the
167         // ConfirmCredentials intent and unassign it, as otherwise the task will move to
168         // front even if ConfirmCredentials is cancelled.
169         if (mInTask != null) {
170             mIntent.putExtra(EXTRA_TASK_ID, mInTask.taskId);
171             mInTask = null;
172         }
173
174         final UserInfo parent = mUserManager.getProfileParent(mUserId);
175         mRInfo = mSupervisor.resolveIntent(mIntent, mResolvedType, parent.id);
176         mAInfo = mSupervisor.resolveActivity(mIntent, mRInfo, mStartFlags, null /*profilerInfo*/);
177         return true;
178     }
179
180     /**
181      * Creates an intent to intercept the current activity start with Confirm Credentials if needed.
182      *
183      * @return The intercepting intent if needed.
184      */
185     private Intent interceptWithConfirmCredentialsIfNeeded(Intent intent, String resolvedType,
186             ActivityInfo aInfo, String callingPackage, int userId) {
187         if (!mService.mUserController.shouldConfirmCredentials(userId)) {
188             return null;
189         }
190         final IIntentSender target = mService.getIntentSenderLocked(
191                 INTENT_SENDER_ACTIVITY, callingPackage,
192                 Binder.getCallingUid(), userId, null, null, 0, new Intent[]{ intent },
193                 new String[]{ resolvedType },
194                 FLAG_CANCEL_CURRENT | FLAG_ONE_SHOT | FLAG_IMMUTABLE, null);
195         final int flags = intent.getFlags();
196         final KeyguardManager km = (KeyguardManager) mService.mContext
197                 .getSystemService(KEYGUARD_SERVICE);
198         final Intent newIntent = km.createConfirmDeviceCredentialIntent(null, null, userId);
199         if (newIntent == null) {
200             return null;
201         }
202         newIntent.setFlags(flags | FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
203         newIntent.putExtra(EXTRA_PACKAGE_NAME, aInfo.packageName);
204         newIntent.putExtra(EXTRA_INTENT, new IntentSender(target));
205         return newIntent;
206     }
207
208 }