diff options
author | Nicolas Prevot <nprevot@google.com> | 2014-03-24 13:44:38 +0000 |
---|---|---|
committer | Nicolas Prevot <nprevot@google.com> | 2014-04-30 19:24:52 +0100 |
commit | 10fa67c77e11699391e27975fc2d276a0b8c7cbb (patch) | |
tree | 8a3349d2424f13e5c89ea710da84aaec81a42d70 /core/java | |
parent | dfacf855fd91eb2d40891721ad4b92ed65d0b46d (diff) | |
download | frameworks_base-10fa67c77e11699391e27975fc2d276a0b8c7cbb.zip frameworks_base-10fa67c77e11699391e27975fc2d276a0b8c7cbb.tar.gz frameworks_base-10fa67c77e11699391e27975fc2d276a0b8c7cbb.tar.bz2 |
Introduce forwarding intents across profiles.
The package manager service maintains, for some user ids, a list of forwarding intent filters.
A forwarding intent filter is an intent filter with a destination (a user id).
If an intent matches the forwarding intent filter, then activities in the destination can also respond to the intent.
When the package manager service is asked for components that resolve an intent:
If the intent matches the forwarding intent filter, and at least one activity in the destination user can respond to the intent:
The package manager service also returns the IntentForwarderActivity.
This activity will forward the intent to the destination.
Change-Id: Id8957de3e4a4fdbc1e0dea073eadb45e04ef985a
Diffstat (limited to 'core/java')
4 files changed, 163 insertions, 0 deletions
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 68ab611..73e5b2a 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -172,6 +172,16 @@ public class DevicePolicyManager { @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String ACTION_SET_NEW_PASSWORD = "android.app.action.SET_NEW_PASSWORD"; + /** + * Flag for {@link #forwardMatchingIntents}: the intents will forwarded to the primary user. + */ + public static int FLAG_TO_PRIMARY_USER = 0x0001; + + /** + * Flag for {@link #forwardMatchingIntents}: the intents will be forwarded to the managed + * profile. + */ + public static int FLAG_TO_MANAGED_PROFILE = 0x0002; /** * Return true if the given administrator component is currently @@ -1953,6 +1963,39 @@ public class DevicePolicyManager { } /** + * Called by a profile owner to forward intents sent from the managed profile to the owner, or + * from the owner to the managed profile. + * If an intent matches this intent filter, then activities belonging to the other user can + * respond to this intent. + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param filter if an intent matches this IntentFilter, then it can be forwarded. + */ + public void forwardMatchingIntents(ComponentName admin, IntentFilter filter, int flags) { + if (mService != null) { + try { + mService.forwardMatchingIntents(admin, filter, flags); + } catch (RemoteException e) { + Log.w(TAG, "Failed talking with device policy service", e); + } + } + } + + /** + * Called by a profile owner to remove all the forwarding intent filters from the current user + * and from the owner. + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + */ + public void clearForwardingIntentFilters(ComponentName admin) { + if (mService != null) { + try { + mService.clearForwardingIntentFilters(admin); + } catch (RemoteException e) { + Log.w(TAG, "Failed talking with device policy service", e); + } + } + } + + /** * Called by a profile or device owner to get the application restrictions for a given target * application running in the managed profile. * diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index 72b3c20..eaf4016 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -121,4 +121,6 @@ interface IDevicePolicyManager { Bundle getApplicationRestrictions(in ComponentName who, in String packageName); void setUserRestriction(in ComponentName who, in String key, boolean enable); + void forwardMatchingIntents(in ComponentName admin, in IntentFilter filter, int flags); + void clearForwardingIntentFilters(in ComponentName admin); } diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index 488e25f..cf9a296 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -111,6 +111,8 @@ interface IPackageManager { ResolveInfo resolveIntent(in Intent intent, String resolvedType, int flags, int userId); + boolean canForwardTo(in Intent intent, String resolvedType, int userIdFrom, int userIdDest); + List<ResolveInfo> queryIntentActivities(in Intent intent, String resolvedType, int flags, int userId); @@ -245,6 +247,10 @@ interface IPackageManager { void clearPackagePersistentPreferredActivities(String packageName, int userId); + void addForwardingIntentFilter(in IntentFilter filter, int userIdOrig, int userIdDest); + + void clearForwardingIntentFilters(int userIdOrig); + /** * Report the set of 'Home' activity candidates, plus (if any) which of them * is the current "always use this one" setting. diff --git a/core/java/com/android/internal/app/IntentForwarderActivity.java b/core/java/com/android/internal/app/IntentForwarderActivity.java new file mode 100644 index 0000000..2f74372 --- /dev/null +++ b/core/java/com/android/internal/app/IntentForwarderActivity.java @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.app; + +import android.app.Activity; +import android.app.AppGlobals; +import android.os.Bundle; +import android.content.Context; +import android.content.Intent; +import android.content.pm.IPackageManager; +import android.content.pm.UserInfo; +import android.os.UserHandle; +import android.os.UserManager; +import android.app.ActivityManagerNative; +import android.os.RemoteException; +import android.util.Slog; +import java.util.List; +import java.util.Set; + + + + +/* + * This is used in conjunction with DevicePolicyManager.setForwardingIntents to enable intents to be + * passed in and out of a managed profile. + */ + +public class IntentForwarderActivity extends Activity { + + public static String TAG = "IntentForwarderActivity"; + + public static String FORWARD_INTENT_TO_USER_OWNER + = "com.android.internal.app.ForwardIntentToUserOwner"; + + public static String FORWARD_INTENT_TO_MANAGED_PROFILE + = "com.android.internal.app.ForwardIntentToManagedProfile"; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + Intent intentReceived = getIntent(); + + String className = intentReceived.getComponent().getClassName(); + final UserHandle userDest; + + if (className.equals(FORWARD_INTENT_TO_USER_OWNER)) { + userDest = UserHandle.OWNER; + } else if (className.equals(FORWARD_INTENT_TO_MANAGED_PROFILE)) { + userDest = getManagedProfile(); + } else { + Slog.wtf(TAG, IntentForwarderActivity.class.getName() + " cannot be called directly"); + userDest = null; + } + if (userDest == null) { // This covers the case where there is no managed profile. + finish(); + return; + } + Intent newIntent = new Intent(intentReceived); + newIntent.setComponent(null); + newIntent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT + |Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP); + int callingUserId = getUserId(); + IPackageManager ipm = AppGlobals.getPackageManager(); + String resolvedType = newIntent.resolveTypeIfNeeded(getContentResolver()); + boolean canForward = false; + try { + canForward = ipm.canForwardTo(newIntent, resolvedType, callingUserId, + userDest.getIdentifier()); + } catch (RemoteException e) { + Slog.e(TAG, "PackageManagerService is dead?"); + } + if (canForward) { + startActivityAsUser(newIntent, userDest); + } else { + Slog.wtf(TAG, "the intent: " + newIntent + "cannot be forwarded from user " + + callingUserId + " to user " + userDest.getIdentifier()); + } + finish(); + } + + /** + * Returns the managed profile for this device or null if there is no managed + * profile. + * + * TODO: Remove the assumption that there is only one managed profile + * on the device. + */ + private UserHandle getManagedProfile() { + UserManager userManager = (UserManager) getSystemService(Context.USER_SERVICE); + List<UserInfo> relatedUsers = userManager.getProfiles(UserHandle.USER_OWNER); + for (UserInfo userInfo : relatedUsers) { + if (userInfo.isManagedProfile()) return new UserHandle(userInfo.id); + } + Slog.wtf(TAG, FORWARD_INTENT_TO_MANAGED_PROFILE + + " has been called, but there is no managed profile"); + return null; + } +} |