Merge "Make JobSchedulerService encryption aware."
diff --git a/core/java/android/content/pm/ComponentInfo.java b/core/java/android/content/pm/ComponentInfo.java
index a295cc5..63a163d 100644
--- a/core/java/android/content/pm/ComponentInfo.java
+++ b/core/java/android/content/pm/ComponentInfo.java
@@ -16,6 +16,7 @@
package android.content.pm;
+import android.content.ComponentName;
import android.graphics.drawable.Drawable;
import android.os.Parcel;
import android.os.Parcelable;
@@ -148,6 +149,11 @@
return banner != 0 ? banner : applicationInfo.banner;
}
+ /** {@hide} */
+ public ComponentName getComponentName() {
+ return new ComponentName(packageName, name);
+ }
+
protected void dumpFront(Printer pw, String prefix) {
super.dumpFront(pw, prefix);
if (processName != null && !packageName.equals(processName)) {
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 1882f8d..69f508e 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -253,6 +253,14 @@
| MATCH_ENCRYPTION_UNAWARE_ONLY;
/**
+ * {@link PackageInfo} flag: include only components from applications that
+ * are marked with {@link ApplicationInfo#FLAG_SYSTEM}.
+ *
+ * @hide
+ */
+ public static final int MATCH_SYSTEM_ONLY = 0x00100000;
+
+ /**
* {@link PackageInfo} flag: use the default encryption matching behavior
* based on user state. Internal flag used to indicate that a system
* component has done their homework and verified their encryption-aware
@@ -260,7 +268,7 @@
*
* @hide
*/
- public static final int MATCH_ENCRYPTION_DEFAULT = 0x00100000;
+ public static final int MATCH_ENCRYPTION_DEFAULT = 0x10000000;
/**
* Flag for {@link addCrossProfileIntentFilter}: if this flag is set:
diff --git a/core/java/com/android/internal/util/ArrayUtils.java b/core/java/com/android/internal/util/ArrayUtils.java
index e8970bc..16bf9dd 100644
--- a/core/java/com/android/internal/util/ArrayUtils.java
+++ b/core/java/com/android/internal/util/ArrayUtils.java
@@ -125,28 +125,28 @@
/**
* Checks if given array is null or has zero elements.
*/
- public static <T> boolean isEmpty(T[] array) {
+ public static <T> boolean isEmpty(@Nullable T[] array) {
return array == null || array.length == 0;
}
/**
* Checks if given array is null or has zero elements.
*/
- public static boolean isEmpty(int[] array) {
+ public static boolean isEmpty(@Nullable int[] array) {
return array == null || array.length == 0;
}
/**
* Checks if given array is null or has zero elements.
*/
- public static boolean isEmpty(long[] array) {
+ public static boolean isEmpty(@Nullable long[] array) {
return array == null || array.length == 0;
}
/**
* Checks if given array is null or has zero elements.
*/
- public static boolean isEmpty(byte[] array) {
+ public static boolean isEmpty(@Nullable byte[] array) {
return array == null || array.length == 0;
}
@@ -156,7 +156,7 @@
* @param value the value to check for
* @return true if the value is present in the array
*/
- public static <T> boolean contains(T[] array, T value) {
+ public static <T> boolean contains(@Nullable T[] array, T value) {
return indexOf(array, value) != -1;
}
@@ -164,7 +164,7 @@
* Return first index of {@code value} in {@code array}, or {@code -1} if
* not found.
*/
- public static <T> int indexOf(T[] array, T value) {
+ public static <T> int indexOf(@Nullable T[] array, T value) {
if (array == null) return -1;
for (int i = 0; i < array.length; i++) {
if (Objects.equals(array[i], value)) return i;
@@ -175,7 +175,7 @@
/**
* Test if all {@code check} items are contained in {@code array}.
*/
- public static <T> boolean containsAll(T[] array, T[] check) {
+ public static <T> boolean containsAll(@Nullable T[] array, T[] check) {
if (check == null) return true;
for (T checkItem : check) {
if (!contains(array, checkItem)) {
@@ -185,7 +185,7 @@
return true;
}
- public static boolean contains(int[] array, int value) {
+ public static boolean contains(@Nullable int[] array, int value) {
if (array == null) return false;
for (int element : array) {
if (element == value) {
@@ -195,7 +195,7 @@
return false;
}
- public static boolean contains(long[] array, long value) {
+ public static boolean contains(@Nullable long[] array, long value) {
if (array == null) return false;
for (long element : array) {
if (element == value) {
@@ -205,10 +205,12 @@
return false;
}
- public static long total(long[] array) {
+ public static long total(@Nullable long[] array) {
long total = 0;
- for (long value : array) {
- total += value;
+ if (array != null) {
+ for (long value : array) {
+ total += value;
+ }
}
return total;
}
@@ -366,11 +368,11 @@
return cur;
}
- public static long[] cloneOrNull(long[] array) {
+ public static @Nullable long[] cloneOrNull(@Nullable long[] array) {
return (array != null) ? array.clone() : null;
}
- public static <T> ArraySet<T> add(ArraySet<T> cur, T val) {
+ public static @NonNull <T> ArraySet<T> add(@Nullable ArraySet<T> cur, T val) {
if (cur == null) {
cur = new ArraySet<>();
}
@@ -378,7 +380,7 @@
return cur;
}
- public static <T> ArraySet<T> remove(ArraySet<T> cur, T val) {
+ public static @Nullable <T> ArraySet<T> remove(@Nullable ArraySet<T> cur, T val) {
if (cur == null) {
return null;
}
@@ -390,11 +392,11 @@
}
}
- public static <T> boolean contains(ArraySet<T> cur, T val) {
+ public static <T> boolean contains(@Nullable ArraySet<T> cur, T val) {
return (cur != null) ? cur.contains(val) : false;
}
- public static <T> ArrayList<T> add(ArrayList<T> cur, T val) {
+ public static @NonNull <T> ArrayList<T> add(@Nullable ArrayList<T> cur, T val) {
if (cur == null) {
cur = new ArrayList<>();
}
@@ -402,7 +404,7 @@
return cur;
}
- public static <T> ArrayList<T> remove(ArrayList<T> cur, T val) {
+ public static @Nullable <T> ArrayList<T> remove(@Nullable ArrayList<T> cur, T val) {
if (cur == null) {
return null;
}
@@ -414,7 +416,7 @@
}
}
- public static <T> boolean contains(ArrayList<T> cur, T val) {
+ public static <T> boolean contains(@Nullable ArrayList<T> cur, T val) {
return (cur != null) ? cur.contains(val) : false;
}
diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java
index ad829d0..80ad6bb 100644
--- a/services/core/java/com/android/server/MountService.java
+++ b/services/core/java/com/android/server/MountService.java
@@ -24,6 +24,7 @@
import static com.android.internal.util.XmlUtils.writeIntAttribute;
import static com.android.internal.util.XmlUtils.writeLongAttribute;
import static com.android.internal.util.XmlUtils.writeStringAttribute;
+
import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
import static org.xmlpull.v1.XmlPullParser.START_TAG;
@@ -89,9 +90,6 @@
import android.util.TimeUtils;
import android.util.Xml;
-import libcore.io.IoUtils;
-import libcore.util.EmptyArray;
-
import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.IMediaContainerService;
import com.android.internal.os.SomeArgs;
@@ -106,6 +104,9 @@
import com.android.server.NativeDaemonConnector.SensitiveArg;
import com.android.server.pm.PackageManagerService;
+import libcore.io.IoUtils;
+import libcore.util.EmptyArray;
+
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 9f74fc6..ee8aab6 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -978,7 +978,7 @@
final PackageManager pm = mContext.getPackageManager();
Intent intent = new Intent(InputManager.ACTION_QUERY_KEYBOARD_LAYOUTS);
for (ResolveInfo resolveInfo : pm.queryBroadcastReceivers(intent,
- PackageManager.GET_META_DATA)) {
+ PackageManager.GET_META_DATA | PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE)) {
final ActivityInfo activityInfo = resolveInfo.activityInfo;
final int priority = resolveInfo.priority;
visitKeyboardLayoutsInPackage(pm, activityInfo, null, priority, visitor);
@@ -993,7 +993,8 @@
try {
ActivityInfo receiver = pm.getReceiverInfo(
new ComponentName(d.packageName, d.receiverName),
- PackageManager.GET_META_DATA);
+ PackageManager.GET_META_DATA
+ | PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE);
visitKeyboardLayoutsInPackage(pm, receiver, d.keyboardLayoutName, 0, visitor);
} catch (NameNotFoundException ex) {
}
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index 309bec8..c5e6e7c 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -16,20 +16,14 @@
package com.android.server.job;
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
import android.app.ActivityManager;
import android.app.ActivityManagerNative;
import android.app.AppGlobals;
import android.app.IUidObserver;
+import android.app.job.IJobScheduler;
import android.app.job.JobInfo;
import android.app.job.JobScheduler;
import android.app.job.JobService;
-import android.app.job.IJobScheduler;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
@@ -53,6 +47,7 @@
import android.util.SparseArray;
import com.android.internal.app.IBatteryStats;
+import com.android.internal.util.ArrayUtils;
import com.android.server.DeviceIdleController;
import com.android.server.LocalServices;
import com.android.server.job.controllers.AppIdleController;
@@ -63,6 +58,15 @@
import com.android.server.job.controllers.StateController;
import com.android.server.job.controllers.TimeController;
+import libcore.util.EmptyArray;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+
/**
* Responsible for taking jobs representing work to be performed by a client app, and determining
* based on the criteria specified when that job should be run against the client application's
@@ -126,7 +130,7 @@
*/
final ArrayList<JobStatus> mPendingJobs = new ArrayList<>();
- final ArrayList<Integer> mStartedUsers = new ArrayList<>();
+ int[] mStartedUsers = EmptyArray.INT;
final JobHandler mHandler;
final JobSchedulerStub mJobSchedulerStub;
@@ -201,14 +205,20 @@
@Override
public void onStartUser(int userHandle) {
- mStartedUsers.add(userHandle);
+ mStartedUsers = ArrayUtils.appendInt(mStartedUsers, userHandle);
+ // Let's kick any outstanding jobs for this user.
+ mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget();
+ }
+
+ @Override
+ public void onUnlockUser(int userHandle) {
// Let's kick any outstanding jobs for this user.
mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget();
}
@Override
public void onStopUser(int userHandle) {
- mStartedUsers.remove(Integer.valueOf(userHandle));
+ mStartedUsers = ArrayUtils.removeInt(mStartedUsers, userHandle);
}
/**
@@ -744,7 +754,7 @@
*/
private void maybeQueueReadyJobsForExecutionLockedH() {
int chargingCount = 0;
- int idleCount = 0;
+ int idleCount = 0;
int backoffCount = 0;
int connectivityCount = 0;
List<JobStatus> runnableJobs = null;
@@ -812,18 +822,31 @@
* - It's not pending.
* - It's not already running on a JSC.
* - The user that requested the job is running.
+ * - The component is enabled and runnable.
*/
private boolean isReadyToBeExecutedLocked(JobStatus job) {
final boolean jobReady = job.isReady();
final boolean jobPending = mPendingJobs.contains(job);
final boolean jobActive = isCurrentlyActiveLocked(job);
- final boolean userRunning = mStartedUsers.contains(job.getUserId());
+
+ final int userId = job.getUserId();
+ final boolean userStarted = ArrayUtils.contains(mStartedUsers, userId);
+ final boolean componentPresent;
+ try {
+ componentPresent = (AppGlobals.getPackageManager().getServiceInfo(
+ job.getServiceComponent(), PackageManager.MATCH_ENCRYPTION_DEFAULT,
+ userId) != null);
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+
if (DEBUG) {
Slog.v(TAG, "isReadyToBeExecutedLocked: " + job.toShortString()
+ " ready=" + jobReady + " pending=" + jobPending
- + " active=" + jobActive + " userRunning=" + userRunning);
+ + " active=" + jobActive + " userStarted=" + userStarted
+ + " componentPresent=" + componentPresent);
}
- return userRunning && jobReady && !jobPending && !jobActive;
+ return userStarted && componentPresent && jobReady && !jobPending && !jobActive;
}
/**
@@ -901,7 +924,8 @@
final IPackageManager pm = AppGlobals.getPackageManager();
final ComponentName service = job.getService();
try {
- ServiceInfo si = pm.getServiceInfo(service, 0, UserHandle.getUserId(uid));
+ ServiceInfo si = pm.getServiceInfo(service, PackageManager.MATCH_ENCRYPTION_DEFAULT,
+ UserHandle.getUserId(uid));
if (si == null) {
throw new IllegalArgumentException("No such service " + service);
}
@@ -1014,16 +1038,12 @@
Binder.restoreCallingIdentity(identityToken);
}
}
- };
+ }
void dumpInternal(PrintWriter pw) {
final long now = SystemClock.elapsedRealtime();
synchronized (mJobs) {
- pw.print("Started users: ");
- for (int i=0; i<mStartedUsers.size(); i++) {
- pw.print("u" + mStartedUsers.get(i) + " ");
- }
- pw.println();
+ pw.println("Started users: " + Arrays.toString(mStartedUsers));
pw.println("Registered jobs:");
if (mJobs.size() > 0) {
ArraySet<JobStatus> jobs = mJobs.getJobs();
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 4b77923..7bb6d1d 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -3227,7 +3227,7 @@
PackageParser.Activity a = mActivities.mActivities.get(component);
if (DEBUG_PACKAGE_INFO) Log.v(TAG, "getActivityInfo " + component + ": " + a);
- if (a != null && mSettings.isEnabledAndVisibleLPr(a.info, flags, userId)) {
+ if (a != null && mSettings.isEnabledAndMatchLPr(a.info, flags, userId)) {
PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
if (ps == null) return null;
return PackageParser.generateActivityInfo(a, flags, ps.readUserState(userId),
@@ -3272,7 +3272,7 @@
PackageParser.Activity a = mReceivers.mActivities.get(component);
if (DEBUG_PACKAGE_INFO) Log.v(
TAG, "getReceiverInfo " + component + ": " + a);
- if (a != null && mSettings.isEnabledAndVisibleLPr(a.info, flags, userId)) {
+ if (a != null && mSettings.isEnabledAndMatchLPr(a.info, flags, userId)) {
PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
if (ps == null) return null;
return PackageParser.generateActivityInfo(a, flags, ps.readUserState(userId),
@@ -3291,7 +3291,7 @@
PackageParser.Service s = mServices.mServices.get(component);
if (DEBUG_PACKAGE_INFO) Log.v(
TAG, "getServiceInfo " + component + ": " + s);
- if (s != null && mSettings.isEnabledAndVisibleLPr(s.info, flags, userId)) {
+ if (s != null && mSettings.isEnabledAndMatchLPr(s.info, flags, userId)) {
PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
if (ps == null) return null;
return PackageParser.generateServiceInfo(s, flags, ps.readUserState(userId),
@@ -3310,7 +3310,7 @@
PackageParser.Provider p = mProviders.mProviders.get(component);
if (DEBUG_PACKAGE_INFO) Log.v(
TAG, "getProviderInfo " + component + ": " + p);
- if (p != null && mSettings.isEnabledAndVisibleLPr(p.info, flags, userId)) {
+ if (p != null && mSettings.isEnabledAndMatchLPr(p.info, flags, userId)) {
PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
if (ps == null) return null;
return PackageParser.generateProviderInfo(p, flags, ps.readUserState(userId),
@@ -5751,7 +5751,6 @@
public ParceledListSlice<PackageInfo> getPackagesHoldingPermissions(
String[] permissions, int flags, int userId) {
if (!sUserManager.exists(userId)) return null;
- flags = augmentFlagsForUser(flags, userId, null);
final boolean listUninstalled = (flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0;
// writer
@@ -5779,7 +5778,6 @@
@Override
public ParceledListSlice<ApplicationInfo> getInstalledApplications(int flags, int userId) {
if (!sUserManager.exists(userId)) return null;
- flags = augmentFlagsForUser(flags, userId, null);
final boolean listUninstalled = (flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0;
// writer
@@ -5930,7 +5928,7 @@
? mSettings.mPackages.get(provider.owner.packageName)
: null;
return ps != null
- && mSettings.isEnabledAndVisibleLPr(provider.info, flags, userId)
+ && mSettings.isEnabledAndMatchLPr(provider.info, flags, userId)
&& (!mSafeMode || (provider.info.applicationInfo.flags
&ApplicationInfo.FLAG_SYSTEM) != 0)
? PackageParser.generateProviderInfo(provider, flags,
@@ -5987,7 +5985,7 @@
&& (processName == null
|| (p.info.processName.equals(processName)
&& UserHandle.isSameApp(p.info.applicationInfo.uid, uid)))
- && mSettings.isEnabledAndVisibleLPr(p.info, flags, userId)
+ && mSettings.isEnabledAndMatchLPr(p.info, flags, userId)
&& (!mSafeMode
|| (p.info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0)) {
if (finalList == null) {
@@ -9253,7 +9251,7 @@
protected ResolveInfo newResult(PackageParser.ActivityIntentInfo info,
int match, int userId) {
if (!sUserManager.exists(userId)) return null;
- if (!mSettings.isEnabledAndVisibleLPr(info.activity.info, mFlags, userId)) {
+ if (!mSettings.isEnabledAndMatchLPr(info.activity.info, mFlags, userId)) {
return null;
}
final PackageParser.Activity activity = info.activity;
@@ -9477,7 +9475,7 @@
int match, int userId) {
if (!sUserManager.exists(userId)) return null;
final PackageParser.ServiceIntentInfo info = (PackageParser.ServiceIntentInfo)filter;
- if (!mSettings.isEnabledAndVisibleLPr(info.service.info, mFlags, userId)) {
+ if (!mSettings.isEnabledAndMatchLPr(info.service.info, mFlags, userId)) {
return null;
}
final PackageParser.Service service = info.service;
@@ -9700,7 +9698,7 @@
if (!sUserManager.exists(userId))
return null;
final PackageParser.ProviderIntentInfo info = filter;
- if (!mSettings.isEnabledAndVisibleLPr(info.provider.info, mFlags, userId)) {
+ if (!mSettings.isEnabledAndMatchLPr(info.provider.info, mFlags, userId)) {
return null;
}
final PackageParser.Provider provider = info.provider;
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 5612aba..7c952a5 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -3790,17 +3790,16 @@
return cmp != null ? Arrays.toString(cmp.toArray()) : "[]";
}
- boolean isEnabledAndVisibleLPr(ComponentInfo componentInfo, int flags, int userId) {
+ boolean isEnabledAndMatchLPr(ComponentInfo componentInfo, int flags, int userId) {
return isEnabledLPr(componentInfo, flags, userId)
- && isVisibleLPr(componentInfo, flags);
+ && isMatchLPr(componentInfo, flags);
}
private boolean isEnabledLPr(ComponentInfo componentInfo, int flags, int userId) {
if ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
return true;
}
- final String pkgName = componentInfo.packageName;
- final PackageSetting packageSettings = mPackages.get(pkgName);
+ final PackageSetting packageSettings = mPackages.get(componentInfo.packageName);
if (PackageManagerService.DEBUG_SETTINGS) {
Log.v(PackageManagerService.TAG, "isEnabledLock - packageName = "
+ componentInfo.packageName + " componentName = " + componentInfo.name);
@@ -3836,12 +3835,19 @@
return componentInfo.enabled;
}
- private boolean isVisibleLPr(ComponentInfo componentInfo, int flags) {
- final boolean matchUnaware = ((flags & PackageManager.MATCH_ENCRYPTION_UNAWARE_ONLY) != 0)
+ private boolean isMatchLPr(ComponentInfo componentInfo, int flags) {
+ if ((flags & PackageManager.MATCH_SYSTEM_ONLY) != 0) {
+ final PackageSetting ps = mPackages.get(componentInfo.packageName);
+ if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0) {
+ return false;
+ }
+ }
+
+ final boolean matchesUnaware = ((flags & PackageManager.MATCH_ENCRYPTION_UNAWARE_ONLY) != 0)
&& !componentInfo.encryptionAware;
- final boolean matchAware = ((flags & PackageManager.MATCH_ENCRYPTION_AWARE_ONLY) != 0)
+ final boolean matchesAware = ((flags & PackageManager.MATCH_ENCRYPTION_AWARE_ONLY) != 0)
&& componentInfo.encryptionAware;
- return matchUnaware || matchAware;
+ return matchesUnaware || matchesAware;
}
String getInstallerPackageNameLPr(String packageName) {
diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
index c0dfbcb..29e3c63 100644
--- a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
+++ b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
@@ -126,6 +126,7 @@
final ComponentName keyguardComponent = ComponentName.unflattenFromString(
resources.getString(com.android.internal.R.string.config_keyguardComponent));
+ intent.addFlags(Intent.FLAG_DEBUG_ENCRYPTION_TRIAGED);
intent.setComponent(keyguardComponent);
if (!context.bindServiceAsUser(intent, mKeyguardConnection,