summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/java/android/app/ApplicationPackageManager.java11
-rw-r--r--core/java/android/content/pm/IPackageManager.aidl4
-rw-r--r--core/java/android/content/pm/PackageManager.java7
-rw-r--r--core/res/res/drawable/stat_notify_protected.xml28
-rw-r--r--core/res/res/values/cm_strings.xml3
-rw-r--r--core/res/res/values/cm_symbols.xml4
-rw-r--r--core/tests/coretests/src/android/content/pm/PackageManagerTests.java18
-rwxr-xr-xservices/core/java/com/android/server/am/ActivityManagerService.java64
-rw-r--r--services/core/java/com/android/server/am/ActivityStackSupervisor.java17
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java48
-rw-r--r--test-runner/src/android/test/mock/MockPackageManager.java9
11 files changed, 213 insertions, 0 deletions
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index c0cd9ec..db4e123 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -2046,6 +2046,17 @@ final class ApplicationPackageManager extends PackageManager {
}
}
+ /** @hide */
+ @Override
+ public boolean isComponentProtected(String callingPackage, ComponentName componentName) {
+ try {
+ return mPM.isComponentProtected(callingPackage, componentName, mContext.getUserId());
+ } catch (RemoteException re) {
+ Log.e(TAG, "Failed to get component protected setting", re);
+ return false;
+ }
+ }
+
@Override
public PackageInstaller getPackageInstaller() {
synchronized (mLock) {
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 7c77f54..6d8b5cb 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -519,4 +519,8 @@ interface IPackageManager {
void updateIconMapping(String pkgName);
ComposedIconInfo getComposedIconInfo();
int processThemeResources(String themePkgName);
+
+ /** Protected Apps */
+ boolean isComponentProtected(in String callingPackage, in ComponentName componentName,
+ int userId);
}
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 8928ad3..529d641 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -4561,6 +4561,13 @@ public abstract class PackageManager {
public abstract void setComponentProtectedSetting(ComponentName componentName, boolean newState);
/**
+ * Return whether or not a specific component is protected
+ * @hide
+ */
+ public abstract boolean isComponentProtected(String callingPackage,
+ ComponentName componentName);
+
+ /**
* Adds a {@link CrossProfileIntentFilter}. After calling this method all intents sent from the
* user with id sourceUserId can also be be resolved by activities in the user with id
* targetUserId if they match the specified intent filter.
diff --git a/core/res/res/drawable/stat_notify_protected.xml b/core/res/res/drawable/stat_notify_protected.xml
new file mode 100644
index 0000000..d67a348
--- /dev/null
+++ b/core/res/res/drawable/stat_notify_protected.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (C) 2016 The CyanogenMod 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="26dp"
+ android:height="24dp"
+ android:viewportWidth="26"
+ android:viewportHeight="24">
+
+ <path
+ android:pathData="M0 0h24v24H0z" />
+ <path
+ android:fillColor="#000000"
+ android:pathData="M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z" />
+</vector> \ No newline at end of file
diff --git a/core/res/res/values/cm_strings.xml b/core/res/res/values/cm_strings.xml
index 38b98c6..f9bfff1 100644
--- a/core/res/res/values/cm_strings.xml
+++ b/core/res/res/values/cm_strings.xml
@@ -246,4 +246,7 @@
with spaces on either side. [CHAR LIMIT=3] -->
<string name="kg_sub_separator" translatable="false">" | "</string>
+ <!-- Protected Apps Notification -->
+ <string name="notify_package_component_protected_title">Activity launch blocked</string>
+ <string name="notify_package_component_protected_text"><xliff:g id="app_name">%1$s</xliff:g> is protected from being launched. Click to authenticate and launch the application.</string>
</resources>
diff --git a/core/res/res/values/cm_symbols.xml b/core/res/res/values/cm_symbols.xml
index b0a1105..3afb3e7 100644
--- a/core/res/res/values/cm_symbols.xml
+++ b/core/res/res/values/cm_symbols.xml
@@ -149,4 +149,8 @@
<!-- KeyGuard -->
<java-symbol type="string" name="kg_sub_separator" />
+ <!-- Protected Apps -->
+ <java-symbol type="drawable" name="stat_notify_protected" />
+ <java-symbol type="string" name="notify_package_component_protected_title" />
+ <java-symbol type="string" name="notify_package_component_protected_text" />
</resources>
diff --git a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
index a4214cf..8b4030a 100644
--- a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
+++ b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
@@ -27,6 +27,7 @@ import static android.system.OsConstants.S_IXOTH;
import android.app.PackageInstallObserver;
import android.content.BroadcastReceiver;
+import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -3847,4 +3848,21 @@ public class PackageManagerTests extends AndroidTestCase {
* how to do tests on updated system apps?
* verify updates to system apps cannot be installed on the sdcard.
*/
+
+ //CM Tests
+ public void testIsComponentProtectedFromSamePackage() {
+ ComponentName testComponentName = new ComponentName("com.android.test",
+ "com.android.test.component.protected");
+ getPm().setComponentProtectedSetting(testComponentName, true);
+ assertFalse(getPm().isComponentProtected(testComponentName.getPackageName(),
+ testComponentName));
+ }
+
+ public void testIsComponentProtectedFromManagers() {
+ ComponentName testComponentName = new ComponentName("com.android.test",
+ "com.android.test.component.protected");
+ getPm().setComponentProtectedSetting(testComponentName, true);
+ assertFalse(getPm().isComponentProtected(testComponentName.getPackageName(),
+ testComponentName));
+ }
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index bb61149..b40882d 100755
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -1399,6 +1399,7 @@ public final class ActivityManagerService extends ActivityManagerNative
static final int CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG = 59;
static final int POST_PRIVACY_NOTIFICATION_MSG = 60;
static final int CANCEL_PRIVACY_NOTIFICATION_MSG = 61;
+ static final int POST_COMPONENT_PROTECTED_MSG = 62;
static final int FIRST_ACTIVITY_STACK_MSG = 100;
static final int FIRST_BROADCAST_QUEUE_MSG = 200;
@@ -2167,6 +2168,69 @@ public final class ActivityManagerService extends ActivityManagerNative
} catch (RemoteException e) {
}
} break;
+ case POST_COMPONENT_PROTECTED_MSG: {
+ INotificationManager inm = NotificationManager.getService();
+ if (inm == null) {
+ return;
+ }
+
+ Intent targetIntent = (Intent) msg.obj;
+ if (targetIntent == null) {
+ return;
+ }
+
+ int targetUserId = targetIntent.getIntExtra(
+ "com.android.settings.PROTECTED_APPS_USER_ID", mCurrentUserId);
+ // Resolve for labels and whatnot
+ ActivityInfo root = resolveActivityInfo(targetIntent, targetIntent.getFlags(),
+ targetUserId);
+
+ try {
+ Intent protectedAppIntent = new Intent();
+ protectedAppIntent.setComponent(
+ new ComponentName("com.android.settings",
+ "com.android.settings.applications.ProtectedAppsActivity"));
+ protectedAppIntent.putExtra(
+ "com.android.settings.PROTECTED_APP_TARGET_INTENT",
+ targetIntent);
+ Context context = mContext.createPackageContext("com.android.settings", 0);
+ String title = mContext.getString(
+ com.android.internal.R.string
+ .notify_package_component_protected_title);
+ String text = mContext.getString(
+ com.android.internal.R.string
+ .notify_package_component_protected_text,
+ root.applicationInfo.loadLabel(mContext.getPackageManager()));
+ Notification notification = new Notification.Builder(context)
+ .setSmallIcon(com.android.internal.R.drawable.stat_notify_protected)
+ .setWhen(0)
+ .setTicker(title)
+ .setColor(mContext.getColor(
+ com.android.internal.R.color
+ .system_notification_accent_color))
+ .setContentTitle(title)
+ .setContentText(text)
+ .setDefaults(Notification.DEFAULT_VIBRATE)
+ .setPriority(Notification.PRIORITY_MAX)
+ .setStyle(new Notification.BigTextStyle().bigText(text))
+ .setContentIntent(PendingIntent.getActivityAsUser(mContext, 0,
+ protectedAppIntent, PendingIntent.FLAG_CANCEL_CURRENT, null,
+ new UserHandle(mCurrentUserId)))
+ .build();
+ try {
+ int[] outId = new int[1];
+ inm.enqueueNotificationWithTag("android", "android", null,
+ R.string.notify_package_component_protected_title,
+ notification, outId, mCurrentUserId);
+ } catch (RuntimeException e) {
+ Slog.w(ActivityManagerService.TAG,
+ "Error showing notification for protected app component", e);
+ } catch (RemoteException e) {
+ }
+ } catch (NameNotFoundException e) {
+ Slog.w(TAG, "Unable to create context for protected app notification", e);
+ }
+ } break;
}
}
};
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index be90dc8..cb281ec 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -971,6 +971,23 @@ public final class ActivityStackSupervisor implements DisplayListener {
// Cannot start a child activity if the parent is not resumed.
return ActivityManager.START_CANCELED;
}
+
+ try {
+ //TODO: This needs to be a flushed out API in the future.
+ if (AppGlobals.getPackageManager()
+ .isComponentProtected(callingPackage, intent.getComponent(), userId)) {
+ Message msg = mService.mHandler.obtainMessage(
+ ActivityManagerService.POST_COMPONENT_PROTECTED_MSG);
+ //Store start flags, userid
+ intent.setFlags(startFlags);
+ intent.putExtra("com.android.settings.PROTECTED_APPS_USER_ID", userId);
+ msg.obj = intent;
+ mService.mHandler.sendMessage(msg);
+ return ActivityManager.START_NOT_CURRENT_USER_ACTIVITY;
+ }
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
final int realCallingPid = Binder.getCallingPid();
final int realCallingUid = Binder.getCallingUid();
int callingPid;
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index c1fe38e..4987c9e 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -336,6 +336,7 @@ public class PackageManagerService extends IPackageManager.Stub {
private static final boolean DEBUG_DEXOPT = false;
private static final boolean DEBUG_ABI_SELECTION = false;
private static final boolean DEBUG_PREBUNDLED_SCAN = false;
+ private static final boolean DEBUG_PROTECTED = false;
static final boolean CLEAR_RUNTIME_PERMISSIONS_ON_UPGRADE = false;
@@ -17195,6 +17196,53 @@ public class PackageManagerService extends IPackageManager.Stub {
}
@Override
+ public boolean isComponentProtected(String callingPackage,
+ ComponentName componentName, int userId) {
+ if (DEBUG_PROTECTED) Log.d(TAG, "Checking if component is protected "
+ + componentName.flattenToShortString() + " from calling package " + callingPackage);
+ enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "set protected");
+
+ //Allow managers full access
+ List<String> protectedComponentManagers =
+ CMSettings.Secure.getDelimitedStringAsList(mContext.getContentResolver(),
+ CMSettings.Secure.PROTECTED_COMPONENT_MANAGERS, "|");
+ if (protectedComponentManagers.contains(callingPackage)) {
+ if (DEBUG_PROTECTED) Log.d(TAG, "Calling package is a protected manager, allow");
+ return false;
+ }
+
+ String packageName = componentName.getPackageName();
+ String className = componentName.getClassName();
+
+ //If this component is launched from the same package, allow it.
+ if (TextUtils.equals(packageName, callingPackage)) {
+ if (DEBUG_PROTECTED) Log.d(TAG, "Calling package is same as target, allow");
+ return false;
+ }
+
+ PackageSetting pkgSetting;
+ ArraySet<String> components;
+
+ synchronized (mPackages) {
+ pkgSetting = mSettings.mPackages.get(packageName);
+
+ if (pkgSetting == null) {
+ if (className == null) {
+ throw new IllegalArgumentException(
+ "Unknown package: " + packageName);
+ }
+ throw new IllegalArgumentException(
+ "Unknown component: " + packageName
+ + "/" + className);
+ }
+ // Get all the protected components
+ components = pkgSetting.getProtectedComponents(userId);
+ if (DEBUG_PROTECTED) Log.d(TAG, "Got " + components.size() + " protected components");
+ return components.size() > 0;
+ }
+ }
+
+ @Override
public boolean isStorageLow() {
final long token = Binder.clearCallingIdentity();
try {
diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java
index 7aacb23..d3e2bfd 100644
--- a/test-runner/src/android/test/mock/MockPackageManager.java
+++ b/test-runner/src/android/test/mock/MockPackageManager.java
@@ -891,6 +891,7 @@ public class MockPackageManager extends PackageManager {
public boolean isUpgrade() {
throw new UnsupportedOperationException();
}
+
/**
* @hide
*/
@@ -903,6 +904,14 @@ public class MockPackageManager extends PackageManager {
* @hide
*/
@Override
+ public boolean isComponentProtected(String callingPackage, ComponentName componentName) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * @hide
+ */
+ @Override
public void installPackage(Uri packageURI, PackageInstallObserver observer,
int flags, String installerPackageName) {
throw new UnsupportedOperationException();