110fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevot/* 210fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevot * Copyright (C) 2014 The Android Open Source Project 310fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevot * 410fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevot * Licensed under the Apache License, Version 2.0 (the "License"); 510fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevot * you may not use this file except in compliance with the License. 610fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevot * You may obtain a copy of the License at 710fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevot * 810fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevot * http://www.apache.org/licenses/LICENSE-2.0 910fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevot * 1010fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevot * Unless required by applicable law or agreed to in writing, software 1110fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevot * distributed under the License is distributed on an "AS IS" BASIS, 1210fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevot * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1310fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevot * See the License for the specific language governing permissions and 1410fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevot * limitations under the License. 1510fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevot */ 1610fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevot 1710fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevotpackage com.android.internal.app; 1810fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevot 193ea4310a2245763de1ba29b8ce0a21e99a702746Robin Leeimport static android.content.pm.PackageManager.MATCH_DEFAULT_ONLY; 203ea4310a2245763de1ba29b8ce0a21e99a702746Robin Lee 2110fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevotimport android.app.Activity; 223ea4310a2245763de1ba29b8ce0a21e99a702746Robin Leeimport android.app.ActivityManagerNative; 239797880808320e3a7bae1f59bc7e0c5a13189e5fJeff Sharkeyimport android.app.ActivityThread; 2410fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevotimport android.app.AppGlobals; 259797880808320e3a7bae1f59bc7e0c5a13189e5fJeff Sharkeyimport android.app.admin.DevicePolicyManager; 2610fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevotimport android.content.Context; 2710fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevotimport android.content.Intent; 2810fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevotimport android.content.pm.IPackageManager; 2910fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevotimport android.content.pm.UserInfo; 309797880808320e3a7bae1f59bc7e0c5a13189e5fJeff Sharkeyimport android.os.Bundle; 313ea4310a2245763de1ba29b8ce0a21e99a702746Robin Leeimport android.os.RemoteException; 3210fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevotimport android.os.UserHandle; 3310fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevotimport android.os.UserManager; 3410fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevotimport android.util.Slog; 353ea4310a2245763de1ba29b8ce0a21e99a702746Robin Leeimport android.widget.Toast; 369797880808320e3a7bae1f59bc7e0c5a13189e5fJeff Sharkey 3710fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevotimport java.util.List; 3810fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevot 399797880808320e3a7bae1f59bc7e0c5a13189e5fJeff Sharkey/** 409797880808320e3a7bae1f59bc7e0c5a13189e5fJeff Sharkey * This is used in conjunction with 419797880808320e3a7bae1f59bc7e0c5a13189e5fJeff Sharkey * {@link DevicePolicyManager#addCrossProfileIntentFilter} to enable intents to 429797880808320e3a7bae1f59bc7e0c5a13189e5fJeff Sharkey * be passed in and out of a managed profile. 4310fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevot */ 4410fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevotpublic class IntentForwarderActivity extends Activity { 4510fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevot 4610fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevot public static String TAG = "IntentForwarderActivity"; 4710fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevot 48741abfc12074623d24297ebb67d98cb2d9126addNicolas Prevot public static String FORWARD_INTENT_TO_PARENT 49741abfc12074623d24297ebb67d98cb2d9126addNicolas Prevot = "com.android.internal.app.ForwardIntentToParent"; 5010fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevot 5110fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevot public static String FORWARD_INTENT_TO_MANAGED_PROFILE 5210fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevot = "com.android.internal.app.ForwardIntentToManagedProfile"; 5310fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevot 5410fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevot @Override 5510fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevot protected void onCreate(Bundle savedInstanceState) { 5610fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevot super.onCreate(savedInstanceState); 5710fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevot Intent intentReceived = getIntent(); 5810fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevot 5910fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevot String className = intentReceived.getComponent().getClassName(); 600e2b73f6858479ca963bd53c49f8955d98f14869Nicolas Prevot final int targetUserId; 613ea4310a2245763de1ba29b8ce0a21e99a702746Robin Lee final int userMessageId; 6210fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevot 63741abfc12074623d24297ebb67d98cb2d9126addNicolas Prevot if (className.equals(FORWARD_INTENT_TO_PARENT)) { 643ea4310a2245763de1ba29b8ce0a21e99a702746Robin Lee userMessageId = com.android.internal.R.string.forward_intent_to_owner; 65741abfc12074623d24297ebb67d98cb2d9126addNicolas Prevot targetUserId = getProfileParent(); 6610fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevot } else if (className.equals(FORWARD_INTENT_TO_MANAGED_PROFILE)) { 673ea4310a2245763de1ba29b8ce0a21e99a702746Robin Lee userMessageId = com.android.internal.R.string.forward_intent_to_work; 680e2b73f6858479ca963bd53c49f8955d98f14869Nicolas Prevot targetUserId = getManagedProfile(); 6910fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevot } else { 7010fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevot Slog.wtf(TAG, IntentForwarderActivity.class.getName() + " cannot be called directly"); 713ea4310a2245763de1ba29b8ce0a21e99a702746Robin Lee userMessageId = -1; 720e2b73f6858479ca963bd53c49f8955d98f14869Nicolas Prevot targetUserId = UserHandle.USER_NULL; 7310fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevot } 740e2b73f6858479ca963bd53c49f8955d98f14869Nicolas Prevot if (targetUserId == UserHandle.USER_NULL) { 75741abfc12074623d24297ebb67d98cb2d9126addNicolas Prevot // This covers the case where there is no parent / managed profile. 7610fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevot finish(); 7710fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevot return; 7810fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevot } 7910fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevot Intent newIntent = new Intent(intentReceived); 8010fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevot newIntent.setComponent(null); 81376e4ba96222163be1f1cf409dc697550be4a285Nicolas Prevot // Apps should not be allowed to target a specific package in the target user. 82376e4ba96222163be1f1cf409dc697550be4a285Nicolas Prevot newIntent.setPackage(null); 8310fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevot newIntent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT 8410fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevot |Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP); 8510fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevot int callingUserId = getUserId(); 860e2b73f6858479ca963bd53c49f8955d98f14869Nicolas Prevot 870e2b73f6858479ca963bd53c49f8955d98f14869Nicolas Prevot if (canForward(newIntent, targetUserId)) { 88decd9ea263d00087f6f90182fc0325953e50cfa4Nicolas Prevot if (Intent.ACTION_CHOOSER.equals(newIntent.getAction())) { 890e2b73f6858479ca963bd53c49f8955d98f14869Nicolas Prevot Intent innerIntent = (Intent) newIntent.getParcelableExtra(Intent.EXTRA_INTENT); 90decd9ea263d00087f6f90182fc0325953e50cfa4Nicolas Prevot // At this point, innerIntent is not null. Otherwise, canForward would have returned 91decd9ea263d00087f6f90182fc0325953e50cfa4Nicolas Prevot // false. 92107f7b7becdb5fe6d735a4f1355eb3421f068fb0Nicolas Prevot innerIntent.prepareToLeaveUser(callingUserId); 930e2b73f6858479ca963bd53c49f8955d98f14869Nicolas Prevot } else { 94107f7b7becdb5fe6d735a4f1355eb3421f068fb0Nicolas Prevot newIntent.prepareToLeaveUser(callingUserId); 950e2b73f6858479ca963bd53c49f8955d98f14869Nicolas Prevot } 963ea4310a2245763de1ba29b8ce0a21e99a702746Robin Lee 973ea4310a2245763de1ba29b8ce0a21e99a702746Robin Lee final android.content.pm.ResolveInfo ri = getPackageManager().resolveActivityAsUser( 980e2b73f6858479ca963bd53c49f8955d98f14869Nicolas Prevot newIntent, MATCH_DEFAULT_ONLY, targetUserId); 993ea4310a2245763de1ba29b8ce0a21e99a702746Robin Lee 1002b43c73e66d99a5ccc8a23fd1c4e2028f9dd05f2Kenny Guy // Don't show the disclosure if next activity is ResolverActivity or ChooserActivity 1012b43c73e66d99a5ccc8a23fd1c4e2028f9dd05f2Kenny Guy // as those will already have shown work / personal as neccesary etc. 1022b43c73e66d99a5ccc8a23fd1c4e2028f9dd05f2Kenny Guy final boolean shouldShowDisclosure = ri == null || ri.activityInfo == null || 1032b43c73e66d99a5ccc8a23fd1c4e2028f9dd05f2Kenny Guy !"android".equals(ri.activityInfo.packageName) || 1042b43c73e66d99a5ccc8a23fd1c4e2028f9dd05f2Kenny Guy !(ResolverActivity.class.getName().equals(ri.activityInfo.name) 105e7c74cc96eeecec52401d9bf720234d1421cfebcAdam Powell || ChooserActivity.class.getName().equals(ri.activityInfo.name)); 1063ea4310a2245763de1ba29b8ce0a21e99a702746Robin Lee 1079797880808320e3a7bae1f59bc7e0c5a13189e5fJeff Sharkey try { 108a7cfbe0e548ac76f20915b65851b8bc9095aa541Dianne Hackborn startActivityAsCaller(newIntent, null, false, targetUserId); 1099797880808320e3a7bae1f59bc7e0c5a13189e5fJeff Sharkey } catch (RuntimeException e) { 1109797880808320e3a7bae1f59bc7e0c5a13189e5fJeff Sharkey int launchedFromUid = -1; 1119797880808320e3a7bae1f59bc7e0c5a13189e5fJeff Sharkey String launchedFromPackage = "?"; 1129797880808320e3a7bae1f59bc7e0c5a13189e5fJeff Sharkey try { 1139797880808320e3a7bae1f59bc7e0c5a13189e5fJeff Sharkey launchedFromUid = ActivityManagerNative.getDefault().getLaunchedFromUid( 1149797880808320e3a7bae1f59bc7e0c5a13189e5fJeff Sharkey getActivityToken()); 1159797880808320e3a7bae1f59bc7e0c5a13189e5fJeff Sharkey launchedFromPackage = ActivityManagerNative.getDefault().getLaunchedFromPackage( 1169797880808320e3a7bae1f59bc7e0c5a13189e5fJeff Sharkey getActivityToken()); 1179797880808320e3a7bae1f59bc7e0c5a13189e5fJeff Sharkey } catch (RemoteException ignored) { 1189797880808320e3a7bae1f59bc7e0c5a13189e5fJeff Sharkey } 1199797880808320e3a7bae1f59bc7e0c5a13189e5fJeff Sharkey 1209797880808320e3a7bae1f59bc7e0c5a13189e5fJeff Sharkey Slog.wtf(TAG, "Unable to launch as UID " + launchedFromUid + " package " 1219797880808320e3a7bae1f59bc7e0c5a13189e5fJeff Sharkey + launchedFromPackage + ", while running in " 1229797880808320e3a7bae1f59bc7e0c5a13189e5fJeff Sharkey + ActivityThread.currentProcessName(), e); 1239797880808320e3a7bae1f59bc7e0c5a13189e5fJeff Sharkey } 1243ea4310a2245763de1ba29b8ce0a21e99a702746Robin Lee 1253ea4310a2245763de1ba29b8ce0a21e99a702746Robin Lee if (shouldShowDisclosure) { 1263ea4310a2245763de1ba29b8ce0a21e99a702746Robin Lee Toast.makeText(this, getString(userMessageId), Toast.LENGTH_LONG).show(); 1273ea4310a2245763de1ba29b8ce0a21e99a702746Robin Lee } 12810fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevot } else { 129decd9ea263d00087f6f90182fc0325953e50cfa4Nicolas Prevot Slog.wtf(TAG, "the intent: " + newIntent + " cannot be forwarded from user " 1300e2b73f6858479ca963bd53c49f8955d98f14869Nicolas Prevot + callingUserId + " to user " + targetUserId); 13110fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevot } 13210fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevot finish(); 13310fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevot } 13410fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevot 1350e2b73f6858479ca963bd53c49f8955d98f14869Nicolas Prevot boolean canForward(Intent intent, int targetUserId) { 1360e2b73f6858479ca963bd53c49f8955d98f14869Nicolas Prevot IPackageManager ipm = AppGlobals.getPackageManager(); 137decd9ea263d00087f6f90182fc0325953e50cfa4Nicolas Prevot if (Intent.ACTION_CHOOSER.equals(intent.getAction())) { 1380e2b73f6858479ca963bd53c49f8955d98f14869Nicolas Prevot // The EXTRA_INITIAL_INTENTS may not be allowed to be forwarded. 1390e2b73f6858479ca963bd53c49f8955d98f14869Nicolas Prevot if (intent.hasExtra(Intent.EXTRA_INITIAL_INTENTS)) { 1400e2b73f6858479ca963bd53c49f8955d98f14869Nicolas Prevot Slog.wtf(TAG, "An chooser intent with extra initial intents cannot be forwarded to" 1410e2b73f6858479ca963bd53c49f8955d98f14869Nicolas Prevot + " a different user"); 1420e2b73f6858479ca963bd53c49f8955d98f14869Nicolas Prevot return false; 1430e2b73f6858479ca963bd53c49f8955d98f14869Nicolas Prevot } 1440e2b73f6858479ca963bd53c49f8955d98f14869Nicolas Prevot if (intent.hasExtra(Intent.EXTRA_REPLACEMENT_EXTRAS)) { 1450e2b73f6858479ca963bd53c49f8955d98f14869Nicolas Prevot Slog.wtf(TAG, "A chooser intent with replacement extras cannot be forwarded to a" 1460e2b73f6858479ca963bd53c49f8955d98f14869Nicolas Prevot + " different user"); 1470e2b73f6858479ca963bd53c49f8955d98f14869Nicolas Prevot return false; 1480e2b73f6858479ca963bd53c49f8955d98f14869Nicolas Prevot } 1490e2b73f6858479ca963bd53c49f8955d98f14869Nicolas Prevot intent = (Intent) intent.getParcelableExtra(Intent.EXTRA_INTENT); 150decd9ea263d00087f6f90182fc0325953e50cfa4Nicolas Prevot if (intent == null) { 151decd9ea263d00087f6f90182fc0325953e50cfa4Nicolas Prevot Slog.wtf(TAG, "Cannot forward a chooser intent with no extra " 152decd9ea263d00087f6f90182fc0325953e50cfa4Nicolas Prevot + Intent.EXTRA_INTENT); 153decd9ea263d00087f6f90182fc0325953e50cfa4Nicolas Prevot return false; 154decd9ea263d00087f6f90182fc0325953e50cfa4Nicolas Prevot } 1550e2b73f6858479ca963bd53c49f8955d98f14869Nicolas Prevot } 1560e2b73f6858479ca963bd53c49f8955d98f14869Nicolas Prevot String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); 1570e2b73f6858479ca963bd53c49f8955d98f14869Nicolas Prevot if (intent.getSelector() != null) { 1580e2b73f6858479ca963bd53c49f8955d98f14869Nicolas Prevot intent = intent.getSelector(); 1590e2b73f6858479ca963bd53c49f8955d98f14869Nicolas Prevot } 1600e2b73f6858479ca963bd53c49f8955d98f14869Nicolas Prevot try { 1610e2b73f6858479ca963bd53c49f8955d98f14869Nicolas Prevot return ipm.canForwardTo(intent, resolvedType, getUserId(), 1620e2b73f6858479ca963bd53c49f8955d98f14869Nicolas Prevot targetUserId); 1630e2b73f6858479ca963bd53c49f8955d98f14869Nicolas Prevot } catch (RemoteException e) { 1640e2b73f6858479ca963bd53c49f8955d98f14869Nicolas Prevot Slog.e(TAG, "PackageManagerService is dead?"); 1650e2b73f6858479ca963bd53c49f8955d98f14869Nicolas Prevot return false; 1660e2b73f6858479ca963bd53c49f8955d98f14869Nicolas Prevot } 1670e2b73f6858479ca963bd53c49f8955d98f14869Nicolas Prevot } 1680e2b73f6858479ca963bd53c49f8955d98f14869Nicolas Prevot 16910fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevot /** 1700e2b73f6858479ca963bd53c49f8955d98f14869Nicolas Prevot * Returns the userId of the managed profile for this device or UserHandle.USER_NULL if there is 1710e2b73f6858479ca963bd53c49f8955d98f14869Nicolas Prevot * no managed profile. 17210fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevot * 17310fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevot * TODO: Remove the assumption that there is only one managed profile 17410fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevot * on the device. 17510fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevot */ 1760e2b73f6858479ca963bd53c49f8955d98f14869Nicolas Prevot private int getManagedProfile() { 17710fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevot UserManager userManager = (UserManager) getSystemService(Context.USER_SERVICE); 178741abfc12074623d24297ebb67d98cb2d9126addNicolas Prevot List<UserInfo> relatedUsers = userManager.getProfiles(UserHandle.myUserId()); 17910fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevot for (UserInfo userInfo : relatedUsers) { 1800e2b73f6858479ca963bd53c49f8955d98f14869Nicolas Prevot if (userInfo.isManagedProfile()) return userInfo.id; 18110fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevot } 18210fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevot Slog.wtf(TAG, FORWARD_INTENT_TO_MANAGED_PROFILE 18310fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevot + " has been called, but there is no managed profile"); 1840e2b73f6858479ca963bd53c49f8955d98f14869Nicolas Prevot return UserHandle.USER_NULL; 18510fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevot } 186741abfc12074623d24297ebb67d98cb2d9126addNicolas Prevot 187741abfc12074623d24297ebb67d98cb2d9126addNicolas Prevot /** 188741abfc12074623d24297ebb67d98cb2d9126addNicolas Prevot * Returns the userId of the profile parent or UserHandle.USER_NULL if there is 189741abfc12074623d24297ebb67d98cb2d9126addNicolas Prevot * no parent. 190741abfc12074623d24297ebb67d98cb2d9126addNicolas Prevot */ 191741abfc12074623d24297ebb67d98cb2d9126addNicolas Prevot private int getProfileParent() { 192741abfc12074623d24297ebb67d98cb2d9126addNicolas Prevot UserManager userManager = (UserManager) getSystemService(Context.USER_SERVICE); 193741abfc12074623d24297ebb67d98cb2d9126addNicolas Prevot UserInfo parent = userManager.getProfileParent(UserHandle.myUserId()); 194741abfc12074623d24297ebb67d98cb2d9126addNicolas Prevot if (parent == null) { 195741abfc12074623d24297ebb67d98cb2d9126addNicolas Prevot Slog.wtf(TAG, FORWARD_INTENT_TO_PARENT 196741abfc12074623d24297ebb67d98cb2d9126addNicolas Prevot + " has been called, but there is no parent"); 197741abfc12074623d24297ebb67d98cb2d9126addNicolas Prevot return UserHandle.USER_NULL; 198741abfc12074623d24297ebb67d98cb2d9126addNicolas Prevot } 199741abfc12074623d24297ebb67d98cb2d9126addNicolas Prevot return parent.id; 200741abfc12074623d24297ebb67d98cb2d9126addNicolas Prevot } 20110fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevot} 202