1 /* 2 * Copyright (C) 2014 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.internal.app; 18 19 import static android.content.pm.PackageManager.MATCH_DEFAULT_ONLY; 20 21 import android.app.Activity; 22 import android.app.ActivityManagerNative; 23 import android.app.ActivityThread; 24 import android.app.AppGlobals; 25 import android.app.admin.DevicePolicyManager; 26 import android.content.Context; 27 import android.content.Intent; 28 import android.content.pm.IPackageManager; 29 import android.content.pm.UserInfo; 30 import android.os.Bundle; 31 import android.os.Process; 32 import android.os.RemoteException; 33 import android.os.UserHandle; 34 import android.os.UserManager; 35 import android.util.Slog; 36 import android.widget.Toast; 37 38 import java.util.List; 39 40 /** 41 * This is used in conjunction with 42 * {@link DevicePolicyManager#addCrossProfileIntentFilter} to enable intents to 43 * be passed in and out of a managed profile. 44 */ 45 public class IntentForwarderActivity extends Activity { 46 47 public static String TAG = "IntentForwarderActivity"; 48 49 public static String FORWARD_INTENT_TO_USER_OWNER 50 = "com.android.internal.app.ForwardIntentToUserOwner"; 51 52 public static String FORWARD_INTENT_TO_MANAGED_PROFILE 53 = "com.android.internal.app.ForwardIntentToManagedProfile"; 54 55 @Override onCreate(Bundle savedInstanceState)56 protected void onCreate(Bundle savedInstanceState) { 57 super.onCreate(savedInstanceState); 58 Intent intentReceived = getIntent(); 59 60 String className = intentReceived.getComponent().getClassName(); 61 final int targetUserId; 62 final int userMessageId; 63 64 if (className.equals(FORWARD_INTENT_TO_USER_OWNER)) { 65 userMessageId = com.android.internal.R.string.forward_intent_to_owner; 66 targetUserId = UserHandle.USER_OWNER; 67 } else if (className.equals(FORWARD_INTENT_TO_MANAGED_PROFILE)) { 68 userMessageId = com.android.internal.R.string.forward_intent_to_work; 69 targetUserId = getManagedProfile(); 70 } else { 71 Slog.wtf(TAG, IntentForwarderActivity.class.getName() + " cannot be called directly"); 72 userMessageId = -1; 73 targetUserId = UserHandle.USER_NULL; 74 } 75 if (targetUserId == UserHandle.USER_NULL) { 76 // This covers the case where there is no managed profile. 77 finish(); 78 return; 79 } 80 Intent newIntent = new Intent(intentReceived); 81 newIntent.setComponent(null); 82 // Apps should not be allowed to target a specific package in the target user. 83 newIntent.setPackage(null); 84 newIntent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT 85 |Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP); 86 int callingUserId = getUserId(); 87 88 if (canForward(newIntent, targetUserId)) { 89 if (newIntent.getAction().equals(Intent.ACTION_CHOOSER)) { 90 Intent innerIntent = (Intent) newIntent.getParcelableExtra(Intent.EXTRA_INTENT); 91 innerIntent.setContentUserHint(callingUserId); 92 } else { 93 newIntent.setContentUserHint(callingUserId); 94 } 95 96 final android.content.pm.ResolveInfo ri = getPackageManager().resolveActivityAsUser( 97 newIntent, MATCH_DEFAULT_ONLY, targetUserId); 98 99 // Don't show the disclosure if next activity is ResolverActivity or ChooserActivity 100 // as those will already have shown work / personal as neccesary etc. 101 final boolean shouldShowDisclosure = ri == null || ri.activityInfo == null || 102 !"android".equals(ri.activityInfo.packageName) || 103 !(ResolverActivity.class.getName().equals(ri.activityInfo.name) 104 || ChooserActivity.class.getName().equals(ri.activityInfo.name)); 105 106 try { 107 startActivityAsCaller(newIntent, null, targetUserId); 108 } catch (RuntimeException e) { 109 int launchedFromUid = -1; 110 String launchedFromPackage = "?"; 111 try { 112 launchedFromUid = ActivityManagerNative.getDefault().getLaunchedFromUid( 113 getActivityToken()); 114 launchedFromPackage = ActivityManagerNative.getDefault().getLaunchedFromPackage( 115 getActivityToken()); 116 } catch (RemoteException ignored) { 117 } 118 119 Slog.wtf(TAG, "Unable to launch as UID " + launchedFromUid + " package " 120 + launchedFromPackage + ", while running in " 121 + ActivityThread.currentProcessName(), e); 122 } 123 124 if (shouldShowDisclosure) { 125 Toast.makeText(this, getString(userMessageId), Toast.LENGTH_LONG).show(); 126 } 127 } else { 128 Slog.wtf(TAG, "the intent: " + newIntent + "cannot be forwarded from user " 129 + callingUserId + " to user " + targetUserId); 130 } 131 finish(); 132 } 133 canForward(Intent intent, int targetUserId)134 boolean canForward(Intent intent, int targetUserId) { 135 IPackageManager ipm = AppGlobals.getPackageManager(); 136 if (intent.getAction().equals(Intent.ACTION_CHOOSER)) { 137 // The EXTRA_INITIAL_INTENTS may not be allowed to be forwarded. 138 if (intent.hasExtra(Intent.EXTRA_INITIAL_INTENTS)) { 139 Slog.wtf(TAG, "An chooser intent with extra initial intents cannot be forwarded to" 140 + " a different user"); 141 return false; 142 } 143 if (intent.hasExtra(Intent.EXTRA_REPLACEMENT_EXTRAS)) { 144 Slog.wtf(TAG, "A chooser intent with replacement extras cannot be forwarded to a" 145 + " different user"); 146 return false; 147 } 148 intent = (Intent) intent.getParcelableExtra(Intent.EXTRA_INTENT); 149 } 150 String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); 151 if (intent.getSelector() != null) { 152 intent = intent.getSelector(); 153 } 154 try { 155 return ipm.canForwardTo(intent, resolvedType, getUserId(), 156 targetUserId); 157 } catch (RemoteException e) { 158 Slog.e(TAG, "PackageManagerService is dead?"); 159 return false; 160 } 161 } 162 163 /** 164 * Returns the userId of the managed profile for this device or UserHandle.USER_NULL if there is 165 * no managed profile. 166 * 167 * TODO: Remove the assumption that there is only one managed profile 168 * on the device. 169 */ getManagedProfile()170 private int getManagedProfile() { 171 UserManager userManager = (UserManager) getSystemService(Context.USER_SERVICE); 172 List<UserInfo> relatedUsers = userManager.getProfiles(UserHandle.USER_OWNER); 173 for (UserInfo userInfo : relatedUsers) { 174 if (userInfo.isManagedProfile()) return userInfo.id; 175 } 176 Slog.wtf(TAG, FORWARD_INTENT_TO_MANAGED_PROFILE 177 + " has been called, but there is no managed profile"); 178 return UserHandle.USER_NULL; 179 } 180 } 181