IntentForwarderActivity.java revision ce673ffd228234bdcb986bc44ecd40a201283571
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 17package com.android.internal.app; 18 19import static android.content.pm.PackageManager.MATCH_DEFAULT_ONLY; 20 21import android.app.Activity; 22import android.app.ActivityManagerNative; 23import android.app.AppGlobals; 24import android.os.Bundle; 25import android.content.Context; 26import android.content.Intent; 27import android.content.pm.IPackageManager; 28import android.content.pm.UserInfo; 29import android.os.Process; 30import android.os.RemoteException; 31import android.os.UserHandle; 32import android.os.UserManager; 33import android.util.Slog; 34import android.widget.Toast; 35import java.util.List; 36import java.util.Set; 37 38/* 39 * This is used in conjunction with the {@link setCrossProfileIntentFilter} method of 40 * {@link DevicePolicyManager} to enable intents to be passed in and out of a managed profile. 41 */ 42 43public class IntentForwarderActivity extends Activity { 44 45 public static String TAG = "IntentForwarderActivity"; 46 47 public static String FORWARD_INTENT_TO_USER_OWNER 48 = "com.android.internal.app.ForwardIntentToUserOwner"; 49 50 public static String FORWARD_INTENT_TO_MANAGED_PROFILE 51 = "com.android.internal.app.ForwardIntentToManagedProfile"; 52 53 @Override 54 protected void onCreate(Bundle savedInstanceState) { 55 super.onCreate(savedInstanceState); 56 Intent intentReceived = getIntent(); 57 58 String className = intentReceived.getComponent().getClassName(); 59 final UserHandle userDest; 60 final int userMessageId; 61 62 if (className.equals(FORWARD_INTENT_TO_USER_OWNER)) { 63 userMessageId = com.android.internal.R.string.forward_intent_to_owner; 64 userDest = UserHandle.OWNER; 65 } else if (className.equals(FORWARD_INTENT_TO_MANAGED_PROFILE)) { 66 userMessageId = com.android.internal.R.string.forward_intent_to_work; 67 userDest = getManagedProfile(); 68 } else { 69 Slog.wtf(TAG, IntentForwarderActivity.class.getName() + " cannot be called directly"); 70 userMessageId = -1; 71 userDest = null; 72 } 73 if (userDest == null) { // This covers the case where there is no managed profile. 74 finish(); 75 return; 76 } 77 Intent newIntent = new Intent(intentReceived); 78 newIntent.setComponent(null); 79 newIntent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT 80 |Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP); 81 int callingUserId = getUserId(); 82 IPackageManager ipm = AppGlobals.getPackageManager(); 83 String resolvedType = newIntent.resolveTypeIfNeeded(getContentResolver()); 84 boolean canForward = false; 85 try { 86 Intent selector = newIntent.getSelector(); 87 if (selector == null) { 88 selector = newIntent; 89 } 90 canForward = ipm.canForwardTo(selector, resolvedType, callingUserId, 91 userDest.getIdentifier()); 92 } catch (RemoteException e) { 93 Slog.e(TAG, "PackageManagerService is dead?"); 94 } 95 if (canForward) { 96 newIntent.setContentUserHint(callingUserId); 97 98 final android.content.pm.ResolveInfo ri = getPackageManager().resolveActivityAsUser( 99 newIntent, MATCH_DEFAULT_ONLY, userDest.getIdentifier()); 100 101 // Only show a disclosure if this is a normal (non-OS) app 102 final boolean shouldShowDisclosure = 103 !UserHandle.isSameApp(ri.activityInfo.applicationInfo.uid, Process.SYSTEM_UID); 104 105 startActivityAsUser(newIntent, userDest); 106 107 if (shouldShowDisclosure) { 108 Toast.makeText(this, getString(userMessageId), Toast.LENGTH_LONG).show(); 109 } 110 } else { 111 Slog.wtf(TAG, "the intent: " + newIntent + "cannot be forwarded from user " 112 + callingUserId + " to user " + userDest.getIdentifier()); 113 } 114 finish(); 115 } 116 117 /** 118 * Returns the managed profile for this device or null if there is no managed 119 * profile. 120 * 121 * TODO: Remove the assumption that there is only one managed profile 122 * on the device. 123 */ 124 private UserHandle getManagedProfile() { 125 UserManager userManager = (UserManager) getSystemService(Context.USER_SERVICE); 126 List<UserInfo> relatedUsers = userManager.getProfiles(UserHandle.USER_OWNER); 127 for (UserInfo userInfo : relatedUsers) { 128 if (userInfo.isManagedProfile()) return new UserHandle(userInfo.id); 129 } 130 Slog.wtf(TAG, FORWARD_INTENT_TO_MANAGED_PROFILE 131 + " has been called, but there is no managed profile"); 132 return null; 133 } 134} 135