Merge "Fixed exceptions during test tearDown" into oc-dev
diff --git a/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java
index ca4b4d5..3fd0f50 100644
--- a/core/java/android/animation/AnimatorSet.java
+++ b/core/java/android/animation/AnimatorSet.java
@@ -28,6 +28,7 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
+import java.util.HashMap;
import java.util.List;
/**
@@ -1341,15 +1342,16 @@
// One problem is that the old node dependencies point to nodes in the old AnimatorSet.
// We need to track the old/new nodes in order to reconstruct the dependencies in the clone.
+ HashMap<Node, Node> clonesMap = new HashMap<>(nodeCount);
for (int n = 0; n < nodeCount; n++) {
final Node node = mNodes.get(n);
Node nodeClone = node.clone();
- node.mTmpClone = nodeClone;
+ clonesMap.put(node, nodeClone);
anim.mNodes.add(nodeClone);
anim.mNodeMap.put(nodeClone.mAnimation, nodeClone);
}
- anim.mRootNode = mRootNode.mTmpClone;
+ anim.mRootNode = clonesMap.get(mRootNode);
anim.mDelayAnim = (ValueAnimator) anim.mRootNode.mAnimation;
// Now that we've cloned all of the nodes, we're ready to walk through their
@@ -1357,25 +1359,22 @@
for (int i = 0; i < nodeCount; i++) {
Node node = mNodes.get(i);
// Update dependencies for node's clone
- node.mTmpClone.mLatestParent = node.mLatestParent == null ?
- null : node.mLatestParent.mTmpClone;
+ Node nodeClone = clonesMap.get(node);
+ nodeClone.mLatestParent = node.mLatestParent == null
+ ? null : clonesMap.get(node.mLatestParent);
int size = node.mChildNodes == null ? 0 : node.mChildNodes.size();
for (int j = 0; j < size; j++) {
- node.mTmpClone.mChildNodes.set(j, node.mChildNodes.get(j).mTmpClone);
+ nodeClone.mChildNodes.set(j, clonesMap.get(node.mChildNodes.get(j)));
}
size = node.mSiblings == null ? 0 : node.mSiblings.size();
for (int j = 0; j < size; j++) {
- node.mTmpClone.mSiblings.set(j, node.mSiblings.get(j).mTmpClone);
+ nodeClone.mSiblings.set(j, clonesMap.get(node.mSiblings.get(j)));
}
size = node.mParents == null ? 0 : node.mParents.size();
for (int j = 0; j < size; j++) {
- node.mTmpClone.mParents.set(j, node.mParents.get(j).mTmpClone);
+ nodeClone.mParents.set(j, clonesMap.get(node.mParents.get(j)));
}
}
-
- for (int n = 0; n < nodeCount; n++) {
- mNodes.get(n).mTmpClone = null;
- }
return anim;
}
@@ -1748,11 +1747,6 @@
ArrayList<Node> mChildNodes = null;
/**
- * Temporary field to hold the clone in AnimatorSet#clone. Cleaned after clone is complete
- */
- private Node mTmpClone = null;
-
- /**
* Flag indicating whether the animation in this node is finished. This flag
* is used by AnimatorSet to check, as each animation ends, whether all child animations
* are mEnded and it's time to send out an end event for the entire AnimatorSet.
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index e50c307..51c2246 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -1696,15 +1696,27 @@
@Override
public int installExistingPackage(String packageName) throws NameNotFoundException {
- return installExistingPackageAsUser(packageName, mContext.getUserId());
+ return installExistingPackage(packageName, PackageManager.INSTALL_REASON_UNKNOWN);
+ }
+
+ @Override
+ public int installExistingPackage(String packageName, int installReason)
+ throws NameNotFoundException {
+ return installExistingPackageAsUser(packageName, installReason, mContext.getUserId());
}
@Override
public int installExistingPackageAsUser(String packageName, int userId)
throws NameNotFoundException {
+ return installExistingPackageAsUser(packageName, PackageManager.INSTALL_REASON_UNKNOWN,
+ userId);
+ }
+
+ private int installExistingPackageAsUser(String packageName, int installReason, int userId)
+ throws NameNotFoundException {
try {
int res = mPM.installExistingPackageAsUser(packageName, userId, 0 /*installFlags*/,
- PackageManager.INSTALL_REASON_UNKNOWN);
+ installReason);
if (res == INSTALL_FAILED_INVALID_URI) {
throw new NameNotFoundException("Package " + packageName + " doesn't exist");
}
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 4294eab..ccbd5b4 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -2703,6 +2703,7 @@
private int mBackgroundColor = COLOR_INVALID;
private int mForegroundColor = COLOR_INVALID;
private int mBackgroundColorHint = COLOR_INVALID;
+ private boolean mRebuildStyledRemoteViews;
/**
* Constructs a new Builder with the defaults:
@@ -4251,7 +4252,7 @@
* @hide
*/
public RemoteViews createContentView(boolean increasedHeight) {
- if (mN.contentView != null && (mStyle == null || !mStyle.displayCustomViewInline())) {
+ if (mN.contentView != null && useExistingRemoteView()) {
return mN.contentView;
} else if (mStyle != null) {
final RemoteViews styleView = mStyle.makeContentView(increasedHeight);
@@ -4262,13 +4263,17 @@
return applyStandardTemplate(getBaseLayoutResource());
}
+ private boolean useExistingRemoteView() {
+ return mStyle == null || (!mStyle.displayCustomViewInline()
+ && !mRebuildStyledRemoteViews);
+ }
+
/**
* Construct a RemoteViews for the final big notification layout.
*/
public RemoteViews createBigContentView() {
RemoteViews result = null;
- if (mN.bigContentView != null
- && (mStyle == null || !mStyle.displayCustomViewInline())) {
+ if (mN.bigContentView != null && useExistingRemoteView()) {
return mN.bigContentView;
} else if (mStyle != null) {
result = mStyle.makeBigContentView();
@@ -4343,8 +4348,7 @@
* @hide
*/
public RemoteViews createHeadsUpContentView(boolean increasedHeight) {
- if (mN.headsUpContentView != null
- && (mStyle == null || !mStyle.displayCustomViewInline())) {
+ if (mN.headsUpContentView != null && useExistingRemoteView()) {
return mN.headsUpContentView;
} else if (mStyle != null) {
final RemoteViews styleView = mStyle.makeHeadsUpContentView(increasedHeight);
@@ -4806,7 +4810,7 @@
}
if (mContext.getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.N
- && (mStyle == null || !mStyle.displayCustomViewInline())) {
+ && (useExistingRemoteView())) {
if (mN.contentView == null) {
mN.contentView = createContentView();
mN.extras.putInt(EXTRA_REBUILD_CONTENT_VIEW_ACTION_COUNT,
@@ -4978,6 +4982,19 @@
public void setBackgroundColorHint(int backgroundColor) {
mBackgroundColorHint = backgroundColor;
}
+
+
+ /**
+ * Forces all styled remoteViews to be built from scratch and not use any cached
+ * RemoteViews.
+ * This is needed for legacy apps that are baking in their remoteviews into the
+ * notification.
+ *
+ * @hide
+ */
+ public void setRebuildStyledRemoteViews(boolean rebuild) {
+ mRebuildStyledRemoteViews = rebuild;
+ }
}
/**
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 40fe6af..fcf1931 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -95,7 +95,6 @@
import android.os.BatteryManager;
import android.os.BatteryStats;
import android.os.Build;
-import android.os.Debug;
import android.os.DropBoxManager;
import android.os.HardwarePropertiesManager;
import android.os.IBatteryPropertiesRegistrar;
@@ -118,8 +117,6 @@
import android.os.storage.StorageManager;
import android.print.IPrintManager;
import android.print.PrintManager;
-import android.view.autofill.AutofillManager;
-import android.view.autofill.IAutoFillManager;
import android.service.oemlock.IOemLockService;
import android.service.oemlock.OemLockManager;
import android.service.persistentdata.IPersistentDataBlockService;
@@ -136,6 +133,8 @@
import android.view.WindowManagerImpl;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.CaptioningManager;
+import android.view.autofill.AutofillManager;
+import android.view.autofill.IAutoFillManager;
import android.view.inputmethod.InputMethodManager;
import android.view.textclassifier.TextClassificationManager;
import android.view.textservice.TextServicesManager;
@@ -660,7 +659,7 @@
ServiceManager.getService(Context.COMPANION_DEVICE_SERVICE);
ICompanionDeviceManager service =
ICompanionDeviceManager.Stub.asInterface(iBinder);
- return new CompanionDeviceManager(service, ctx);
+ return new CompanionDeviceManager(service, ctx.getOuterContext());
}});
registerService(Context.CONSUMER_IR_SERVICE, ConsumerIrManager.class,
diff --git a/core/java/android/app/assist/AssistStructure.java b/core/java/android/app/assist/AssistStructure.java
index 1994206..eae9e1e 100644
--- a/core/java/android/app/assist/AssistStructure.java
+++ b/core/java/android/app/assist/AssistStructure.java
@@ -19,6 +19,7 @@
import android.os.RemoteException;
import android.os.SystemClock;
import android.service.autofill.FillContext;
+import android.service.autofill.FillRequest;
import android.text.TextUtils;
import android.util.Log;
import android.util.Pair;
@@ -494,7 +495,7 @@
ViewNodeBuilder builder = new ViewNodeBuilder(assist, mRoot, false);
if ((root.getWindowFlags() & WindowManager.LayoutParams.FLAG_SECURE) != 0) {
if (forAutoFill) {
- final int autofillFlags = (flags & AutofillManager.FLAG_MANUAL_REQUEST) != 0
+ final int autofillFlags = (flags & FillRequest.FLAG_MANUAL_REQUEST) != 0
? View.AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS : 0;
view.onProvideAutofillStructure(builder, autofillFlags);
} else {
@@ -506,7 +507,7 @@
}
}
if (forAutoFill) {
- final int autofillFlags = (flags & AutofillManager.FLAG_MANUAL_REQUEST) != 0
+ final int autofillFlags = (flags & FillRequest.FLAG_MANUAL_REQUEST) != 0
? View.AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS : 0;
view.dispatchProvideAutofillStructure(builder, autofillFlags);
} else {
diff --git a/core/java/android/companion/CompanionDeviceManager.java b/core/java/android/companion/CompanionDeviceManager.java
index fac9e13..4e70e3f 100644
--- a/core/java/android/companion/CompanionDeviceManager.java
+++ b/core/java/android/companion/CompanionDeviceManager.java
@@ -21,11 +21,14 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.Activity;
+import android.app.Application;
import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Context;
import android.content.IntentSender;
import android.content.pm.PackageManager;
+import android.os.Bundle;
import android.os.Handler;
import android.os.RemoteException;
import android.service.notification.NotificationListenerService;
@@ -137,26 +140,11 @@
}
checkNotNull(request, "Request cannot be null");
checkNotNull(callback, "Callback cannot be null");
- final Handler finalHandler = Handler.mainIfNull(handler);
try {
mService.associate(
request,
- //TODO implicit pointer to outer class -> =null onDestroy
- //TODO onStop if isFinishing -> stopScan
- new IFindDeviceCallback.Stub() {
- @Override
- public void onSuccess(PendingIntent launcher) {
- finalHandler.post(() -> {
- callback.onDeviceFound(launcher.getIntentSender());
- });
- }
-
- @Override
- public void onFailure(CharSequence reason) {
- finalHandler.post(() -> callback.onFailure(reason));
- }
- },
- mContext.getPackageName());
+ new CallbackProxy(request, callback, Handler.mainIfNull(handler)),
+ getCallingPackage());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -175,7 +163,7 @@
return Collections.emptyList();
}
try {
- return mService.getAssociations(mContext.getPackageName(), mContext.getUserId());
+ return mService.getAssociations(getCallingPackage(), mContext.getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -200,7 +188,7 @@
return;
}
try {
- mService.disassociate(deviceMacAddress, mContext.getPackageName());
+ mService.disassociate(deviceMacAddress, getCallingPackage());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -263,4 +251,57 @@
}
return featurePresent;
}
+
+ private Activity getActivity() {
+ return (Activity) mContext;
+ }
+
+ private String getCallingPackage() {
+ return mContext.getPackageName();
+ }
+
+ private class CallbackProxy extends IFindDeviceCallback.Stub
+ implements Application.ActivityLifecycleCallbacks {
+
+ private Callback mCallback;
+ private Handler mHandler;
+ private AssociationRequest mRequest;
+
+ private CallbackProxy(AssociationRequest request, Callback callback, Handler handler) {
+ mCallback = callback;
+ mHandler = handler;
+ mRequest = request;
+ getActivity().getApplication().registerActivityLifecycleCallbacks(this);
+ }
+
+ @Override
+ public void onSuccess(PendingIntent launcher) {
+ mHandler.post(() -> mCallback.onDeviceFound(launcher.getIntentSender()));
+ }
+
+ @Override
+ public void onFailure(CharSequence reason) {
+ mHandler.post(() -> mCallback.onFailure(reason));
+ }
+
+ @Override
+ public void onActivityDestroyed(Activity activity) {
+ try {
+ mService.stopScan(mRequest, this, getCallingPackage());
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ getActivity().getApplication().unregisterActivityLifecycleCallbacks(this);
+ mCallback = null;
+ mHandler = null;
+ mRequest = null;
+ }
+
+ @Override public void onActivityCreated(Activity activity, Bundle savedInstanceState) {}
+ @Override public void onActivityStarted(Activity activity) {}
+ @Override public void onActivityResumed(Activity activity) {}
+ @Override public void onActivityPaused(Activity activity) {}
+ @Override public void onActivityStopped(Activity activity) {}
+ @Override public void onActivitySaveInstanceState(Activity activity, Bundle outState) {}
+ }
}
diff --git a/core/java/android/companion/ICompanionDeviceManager.aidl b/core/java/android/companion/ICompanionDeviceManager.aidl
index d395208..561342e 100644
--- a/core/java/android/companion/ICompanionDeviceManager.aidl
+++ b/core/java/android/companion/ICompanionDeviceManager.aidl
@@ -30,6 +30,9 @@
void associate(in AssociationRequest request,
in IFindDeviceCallback callback,
in String callingPackage);
+ void stopScan(in AssociationRequest request,
+ in IFindDeviceCallback callback,
+ in String callingPackage);
List<String> getAssociations(String callingPackage, int userId);
void disassociate(String deviceMacAddress, String callingPackage);
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 1a4a1e5..a68c097 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -4630,6 +4630,14 @@
/**
* If there is already an application with the given package name installed
+ * on the system for other users, also install it for the calling user.
+ * @hide
+ */
+ public abstract int installExistingPackage(String packageName, @InstallReason int installReason)
+ throws NameNotFoundException;
+
+ /**
+ * If there is already an application with the given package name installed
* on the system for other users, also install it for the specified user.
* @hide
*/
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index b5fd116..3eea72d 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -203,6 +203,8 @@
private static final String APK_DATA = "apk";
private static final String PROCESS_DATA = "pr";
private static final String CPU_DATA = "cpu";
+ private static final String GLOBAL_CPU_FREQ_DATA = "gcf";
+ private static final String CPU_TIMES_AT_FREQ_DATA = "ctf";
private static final String SENSOR_DATA = "sr";
private static final String VIBRATOR_DATA = "vib";
private static final String FOREGROUND_DATA = "fg";
@@ -265,6 +267,13 @@
private final Formatter mFormatter = new Formatter(mFormatBuilder);
/**
+ * Indicates times spent by the uid at each cpu frequency in all process states.
+ *
+ * Other types might include times spent in foreground, background etc.
+ */
+ private final String UID_TIMES_TYPE_ALL = "A";
+
+ /**
* State for keeping track of counting information.
*/
public static abstract class Counter {
@@ -303,6 +312,24 @@
}
/**
+ * State for keeping track of array of long counting information.
+ */
+ public static abstract class LongCounterArray {
+ /**
+ * Returns the counts associated with this Counter for the
+ * selected type of statistics.
+ *
+ * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT
+ */
+ public abstract long[] getCountsLocked(int which);
+
+ /**
+ * Temporary for debugging.
+ */
+ public abstract void logState(Printer pw, String prefix);
+ }
+
+ /**
* Container class that aggregates counters for transmit, receive, and idle state of a
* radio controller.
*/
@@ -523,6 +550,9 @@
public abstract Timer getBluetoothScanBackgroundTimer();
public abstract Counter getBluetoothScanResultCounter();
+ public abstract long[] getCpuFreqTimes(int which);
+ public abstract long[] getScreenOffCpuFreqTimes(int which);
+
// Note: the following times are disjoint. They can be added together to find the
// total time a uid has had any processes running at all.
@@ -1077,6 +1107,8 @@
public abstract long getNextMaxDailyDeadline();
+ public abstract long[] getCpuFreqs();
+
public final static class HistoryTag {
public String string;
public int uid;
@@ -3274,6 +3306,15 @@
}
}
+ final long[] cpuFreqs = getCpuFreqs();
+ if (cpuFreqs != null) {
+ sb.setLength(0);
+ for (int i = 0; i < cpuFreqs.length; ++i) {
+ sb.append((i == 0 ? "" : ",") + cpuFreqs[i]);
+ }
+ dumpLine(pw, 0 /* uid */, category, GLOBAL_CPU_FREQ_DATA, sb.toString());
+ }
+
for (int iu = 0; iu < NU; iu++) {
final int uid = uidStats.keyAt(iu);
if (reqUid >= 0 && uid != reqUid) {
@@ -3506,6 +3547,27 @@
0 /* old cpu power, keep for compatibility */);
}
+ final long[] cpuFreqTimeMs = u.getCpuFreqTimes(which);
+ // If total cpuFreqTimes is null, then we don't need to check for screenOffCpuFreqTimes.
+ if (cpuFreqTimeMs != null) {
+ sb.setLength(0);
+ for (int i = 0; i < cpuFreqTimeMs.length; ++i) {
+ sb.append((i == 0 ? "" : ",") + cpuFreqTimeMs[i]);
+ }
+ final long[] screenOffCpuFreqTimeMs = u.getScreenOffCpuFreqTimes(which);
+ if (screenOffCpuFreqTimeMs != null) {
+ for (int i = 0; i < screenOffCpuFreqTimeMs.length; ++i) {
+ sb.append("," + screenOffCpuFreqTimeMs[i]);
+ }
+ } else {
+ for (int i = 0; i < cpuFreqTimeMs.length; ++i) {
+ sb.append(",0");
+ }
+ }
+ dumpLine(pw, uid, category, CPU_TIMES_AT_FREQ_DATA, UID_TIMES_TYPE_ALL,
+ cpuFreqTimeMs.length, sb.toString());
+ }
+
final ArrayMap<String, ? extends BatteryStats.Uid.Proc> processStats
= u.getProcessStats();
for (int ipr=processStats.size()-1; ipr>=0; ipr--) {
@@ -4373,6 +4435,16 @@
pw.println(sb.toString());
}
+ final long[] cpuFreqs = getCpuFreqs();
+ if (cpuFreqs != null) {
+ sb.setLength(0);
+ sb.append("CPU freqs:");
+ for (int i = 0; i < cpuFreqs.length; ++i) {
+ sb.append(" " + cpuFreqs[i]);
+ }
+ pw.println(sb.toString());
+ }
+
for (int iu=0; iu<NU; iu++) {
final int uid = uidStats.keyAt(iu);
if (reqUid >= 0 && uid != reqUid && uid != Process.SYSTEM_UID) {
@@ -4835,6 +4907,25 @@
pw.println(sb.toString());
}
+ final long[] cpuFreqTimes = u.getCpuFreqTimes(which);
+ if (cpuFreqTimes != null) {
+ sb.setLength(0);
+ sb.append(" Total cpu time per freq:");
+ for (int i = 0; i < cpuFreqTimes.length; ++i) {
+ sb.append(" " + cpuFreqTimes[i]);
+ }
+ pw.println(sb.toString());
+ }
+ final long[] screenOffCpuFreqTimes = u.getScreenOffCpuFreqTimes(which);
+ if (screenOffCpuFreqTimes != null) {
+ sb.setLength(0);
+ sb.append(" Total screen-off cpu time per freq:");
+ for (int i = 0; i < screenOffCpuFreqTimes.length; ++i) {
+ sb.append(" " + screenOffCpuFreqTimes[i]);
+ }
+ pw.println(sb.toString());
+ }
+
final ArrayMap<String, ? extends BatteryStats.Uid.Proc> processStats
= u.getProcessStats();
for (int ipr=processStats.size()-1; ipr>=0; ipr--) {
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index ba41933..3cd54b8 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -9955,7 +9955,8 @@
CALL_AUTO_RETRY,
DOCK_AUDIO_MEDIA_ENABLED,
ENCODED_SURROUND_OUTPUT,
- LOW_POWER_MODE_TRIGGER_LEVEL
+ LOW_POWER_MODE_TRIGGER_LEVEL,
+ BLUETOOTH_ON
};
private static final ContentProviderHolder sProviderHolder =
diff --git a/core/java/android/service/autofill/AutofillService.java b/core/java/android/service/autofill/AutofillService.java
index 5fd9458..9df315b 100644
--- a/core/java/android/service/autofill/AutofillService.java
+++ b/core/java/android/service/autofill/AutofillService.java
@@ -116,15 +116,7 @@
final IFillCallback callback = (IFillCallback) args.arg3;
final FillCallback fillCallback = new FillCallback(callback, request.getId());
args.recycle();
- // TODO(b/37563972): temporary try-catch hack to support old method
- try {
- onFillRequest(request, cancellation, fillCallback);
- } catch (AbstractMethodError e) {
- final List<FillContext> contexts = request.getFillContexts();
- onFillRequest(contexts.get(contexts.size() - 1).getStructure(),
- request.getClientState(), request.getFlags(), cancellation,
- fillCallback);
- }
+ onFillRequest(request, cancellation, fillCallback);
break;
} case MSG_ON_SAVE_REQUEST: {
final SomeArgs args = (SomeArgs) msg.obj;
@@ -132,14 +124,7 @@
final ISaveCallback callback = (ISaveCallback) args.arg2;
final SaveCallback saveCallback = new SaveCallback(callback);
args.recycle();
- // TODO(b/37563972): temporary try-catch hack to support old method
- try {
- onSaveRequest(request, saveCallback);
- } catch (AbstractMethodError e) {
- final List<FillContext> contexts = request.getFillContexts();
- onSaveRequest(contexts.get(contexts.size() - 1).getStructure(),
- request.getClientState(), saveCallback);
- }
+ onSaveRequest(request, saveCallback);
break;
} case MSG_DISCONNECT: {
onDisconnected();
@@ -201,37 +186,6 @@
@NonNull CancellationSignal cancellationSignal, @NonNull FillCallback callback);
/**
- * Called by the Android system do decide if an {@link Activity} can be autofilled by the
- * service.
- *
- * <p>Service must call one of the {@link FillCallback} methods (like
- * {@link FillCallback#onSuccess(FillResponse)}
- * or {@link FillCallback#onFailure(CharSequence)})
- * to notify the result of the request.
- *
- * @param structure {@link Activity}'s view structure.
- * @param data bundle containing data passed by the service in a last call to
- * {@link FillResponse.Builder#setExtras(Bundle)}, if any. This bundle allows your
- * service to keep state between fill and save requests as well as when filling different
- * sections of the UI as the system will try to aggressively unbind from the service to
- * conserve resources.
- * See {@link FillResponse} for examples of multiple-sections requests.
- * @param flags either {@code 0} or {@link AutofillManager#FLAG_MANUAL_REQUEST}.
- * @param cancellationSignal signal for observing cancellation requests. The system will use
- * this to notify you that the fill result is no longer needed and you should stop
- * handling this fill request in order to save resources.
- * @param callback object used to notify the result of the request.
- *
- * @hide
- */
- @Deprecated
- public void onFillRequest(@NonNull AssistStructure structure, @Nullable Bundle data,
- int flags, @NonNull CancellationSignal cancellationSignal,
- @NonNull FillCallback callback) {
-
- }
-
- /**
* Called when user requests service to save the fields of an {@link Activity}.
*
* <p>Service must call one of the {@link SaveCallback} methods (like
@@ -246,30 +200,6 @@
@NonNull SaveCallback callback);
/**
- * Called when user requests service to save the fields of an {@link Activity}.
- *
- * <p>Service must call one of the {@link SaveCallback} methods (like
- * {@link SaveCallback#onSuccess()} or {@link SaveCallback#onFailure(CharSequence)})
- * to notify the result of the request.
- *
- * @param structure {@link Activity}'s view structure.
- * @param data bundle containing data passed by the service in a last call to
- * {@link FillResponse.Builder#setExtras(Bundle)}, if any. This bundle allows your
- * service to keep state between fill and save requests as well as when filling different
- * sections of the UI as the system will try to aggressively unbind from the service to
- * conserve resources.
- * See {@link FillResponse} for examples of multiple-sections requests.
- * @param callback object used to notify the result of the request.
- *
- * @hide
- */
- @Deprecated
- public void onSaveRequest(@NonNull AssistStructure structure, @Nullable Bundle data,
- @NonNull SaveCallback callback) {
-
- }
-
- /**
* Called when the Android system disconnects from the service.
*
* <p> At this point this service may no longer be an active {@link AutofillService}.
diff --git a/core/java/android/service/autofill/SaveInfo.java b/core/java/android/service/autofill/SaveInfo.java
index 9487760..fa3f55b 100644
--- a/core/java/android/service/autofill/SaveInfo.java
+++ b/core/java/android/service/autofill/SaveInfo.java
@@ -326,15 +326,6 @@
return this;
}
- /** @hide */
- // TODO (b/37563972): Remove when callers migrate
- public @NonNull Builder setNegativeAction(@Nullable CharSequence title,
- @Nullable IntentSender listener) {
- throwIfDestroyed();
- setNegativeAction(NEGATIVE_BUTTON_STYLE_CANCEL, listener);
- return this;
- }
-
/**
* Sets the style and listener for the negative save action.
*
diff --git a/core/java/android/util/MemoryIntArray.java b/core/java/android/util/MemoryIntArray.java
index 749cf08..589edbc 100644
--- a/core/java/android/util/MemoryIntArray.java
+++ b/core/java/android/util/MemoryIntArray.java
@@ -56,7 +56,7 @@
private final boolean mIsOwner;
private final long mMemoryAddr;
- private int mFd;
+ private int mFd = -1;
/**
* Creates a new instance.
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 07258fc..02ac9bd 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -17306,15 +17306,14 @@
* item in a list view.
*
* @return Returns a Parcelable object containing the view's current dynamic
- * state, or null if there is nothing interesting to save. The
- * default implementation returns null.
+ * state, or null if there is nothing interesting to save.
* @see #onRestoreInstanceState(android.os.Parcelable)
* @see #saveHierarchyState(android.util.SparseArray)
* @see #dispatchSaveInstanceState(android.util.SparseArray)
* @see #setSaveEnabled(boolean)
*/
@CallSuper
- protected Parcelable onSaveInstanceState() {
+ @Nullable protected Parcelable onSaveInstanceState() {
mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
if (mStartActivityRequestWho != null || isAutofilled()
|| mAccessibilityViewId > LAST_APP_ACCESSIBILITY_ID) {
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index 75a9965..68c74da 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -16,6 +16,7 @@
package android.view.autofill;
+import static android.service.autofill.FillRequest.FLAG_MANUAL_REQUEST;
import static android.view.autofill.Helper.sDebug;
import static android.view.autofill.Helper.sVerbose;
@@ -99,14 +100,6 @@
static final String SESSION_ID_TAG = "android:sessionId";
static final String LAST_AUTOFILLED_DATA_TAG = "android:lastAutoFilledData";
- /**
- * @deprecated Use {@link android.service.autofill.FillRequest#FLAG_MANUAL_REQUEST}
- * @hide
- */
- // TODO(b/37563972): remove (and change value of private flags)
- @Deprecated
- public static final int FLAG_MANUAL_REQUEST = 0x1;
-
/** @hide */ public static final int ACTION_START_SESSION = 1;
/** @hide */ public static final int ACTION_VIEW_ENTERED = 2;
/** @hide */ public static final int ACTION_VIEW_EXITED = 3;
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 6b18591..be4df51 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -16,6 +16,7 @@
package com.android.internal.os;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.bluetooth.BluetoothActivityEnergyInfo;
@@ -87,6 +88,7 @@
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Iterator;
@@ -114,7 +116,7 @@
private static final int MAGIC = 0xBA757475; // 'BATSTATS'
// Current on-disk Parcel version
- private static final int VERSION = 156 + (USE_OLD_HISTORY ? 1000 : 0);
+ private static final int VERSION = 157 + (USE_OLD_HISTORY ? 1000 : 0);
// Maximum number of items we will record in the history.
private static final int MAX_HISTORY_ITEMS = 2000;
@@ -149,6 +151,8 @@
private final KernelUidCpuTimeReader mKernelUidCpuTimeReader = new KernelUidCpuTimeReader();
private KernelCpuSpeedReader[] mKernelCpuSpeedReaders;
+ private final KernelUidCpuFreqTimeReader mKernelUidCpuFreqTimeReader =
+ new KernelUidCpuFreqTimeReader();
private final KernelMemoryBandwidthStats mKernelMemoryBandwidthStats
= new KernelMemoryBandwidthStats();
@@ -570,6 +574,8 @@
private final NetworkStats.Entry mTmpNetworkStatsEntry = new NetworkStats.Entry();
+ private long[] mCpuFreqs;
+
private PowerProfile mPowerProfile;
/*
@@ -957,6 +963,131 @@
}
}
+ public static class LongSamplingCounterArray extends LongCounterArray implements TimeBaseObs {
+ final TimeBase mTimeBase;
+ long[] mCounts;
+ long[] mLoadedCounts;
+ long[] mUnpluggedCounts;
+ long[] mPluggedCounts;
+
+ LongSamplingCounterArray(TimeBase timeBase, Parcel in) {
+ mTimeBase = timeBase;
+ mPluggedCounts = in.createLongArray();
+ mCounts = copyArray(mPluggedCounts, mCounts);
+ mLoadedCounts = in.createLongArray();
+ mUnpluggedCounts = in.createLongArray();
+ timeBase.add(this);
+ }
+
+ LongSamplingCounterArray(TimeBase timeBase) {
+ mTimeBase = timeBase;
+ timeBase.add(this);
+ }
+
+ public void writeToParcel(Parcel out) {
+ out.writeLongArray(mCounts);
+ out.writeLongArray(mLoadedCounts);
+ out.writeLongArray(mUnpluggedCounts);
+ }
+
+ @Override
+ public void onTimeStarted(long elapsedRealTime, long baseUptime, long baseRealtime) {
+ mUnpluggedCounts = copyArray(mPluggedCounts, mUnpluggedCounts);
+ mCounts = copyArray(mPluggedCounts, mCounts);
+ }
+
+ @Override
+ public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
+ mPluggedCounts = copyArray(mCounts, mPluggedCounts);
+ }
+
+ @Override
+ public long[] getCountsLocked(int which) {
+ long[] val = copyArray(mTimeBase.isRunning() ? mCounts : mPluggedCounts, null);
+ if (which == STATS_SINCE_UNPLUGGED) {
+ subtract(val, mUnpluggedCounts);
+ } else if (which != STATS_SINCE_CHARGED) {
+ subtract(val, mLoadedCounts);
+ }
+ return val;
+ }
+
+ @Override
+ public void logState(Printer pw, String prefix) {
+ pw.println(prefix + "mCounts=" + Arrays.toString(mCounts)
+ + " mLoadedCounts=" + Arrays.toString(mLoadedCounts)
+ + " mUnpluggedCounts=" + Arrays.toString(mUnpluggedCounts)
+ + " mPluggedCounts=" + Arrays.toString(mPluggedCounts));
+ }
+
+ void addCountLocked(long[] counts) {
+ if (counts == null) {
+ return;
+ }
+ if (mCounts == null) {
+ mCounts = new long[counts.length];
+ }
+ for (int i = 0; i < counts.length; ++i) {
+ mCounts[i] += counts[i];
+ }
+ }
+
+ /**
+ * Clear state of this counter.
+ */
+ void reset(boolean detachIfReset) {
+ fillArray(mCounts, 0);
+ fillArray(mLoadedCounts, 0);
+ fillArray(mPluggedCounts, 0);
+ fillArray(mUnpluggedCounts, 0);
+ if (detachIfReset) {
+ detach();
+ }
+ }
+
+ void detach() {
+ mTimeBase.remove(this);
+ }
+
+ void writeSummaryFromParcelLocked(Parcel out) {
+ out.writeLongArray(mCounts);
+ }
+
+ void readSummaryFromParcelLocked(Parcel in) {
+ mCounts = in.createLongArray();
+ mLoadedCounts = copyArray(mCounts, mLoadedCounts);
+ mUnpluggedCounts = copyArray(mCounts, mUnpluggedCounts);
+ mPluggedCounts = copyArray(mCounts, mPluggedCounts);
+ }
+
+ private void fillArray(long[] a, long val) {
+ if (a != null) {
+ Arrays.fill(a, val);
+ }
+ }
+
+ private void subtract(@NonNull long[] val, long[] toSubtract) {
+ if (toSubtract == null) {
+ return;
+ }
+ for (int i = 0; i < val.length; i++) {
+ val[i] -= toSubtract[i];
+ }
+ }
+
+ private long[] copyArray(long[] src, long[] dest) {
+ if (src == null) {
+ return null;
+ } else {
+ if (dest == null) {
+ dest = new long[src.length];
+ }
+ System.arraycopy(src, 0, dest, 0, src.length);
+ return dest;
+ }
+ }
+ }
+
public static class LongSamplingCounter extends LongCounter implements TimeBaseObs {
final TimeBase mTimeBase;
long mCount;
@@ -5483,6 +5614,9 @@
LongSamplingCounter mSystemCpuTime;
LongSamplingCounter[][] mCpuClusterSpeed;
+ LongSamplingCounterArray mCpuFreqTimeMs;
+ LongSamplingCounterArray mScreenOffCpuFreqTimeMs;
+
/**
* The statistics we have collected for this uid's wake locks.
*/
@@ -5560,6 +5694,42 @@
}
@Override
+ public long[] getCpuFreqTimes(int which) {
+ if (mCpuFreqTimeMs == null) {
+ return null;
+ }
+ final long[] cpuFreqTimes = mCpuFreqTimeMs.getCountsLocked(which);
+ if (cpuFreqTimes == null) {
+ return null;
+ }
+ // Return cpuFreqTimes only if atleast one of the elements in non-zero.
+ for (int i = 0; i < cpuFreqTimes.length; ++i) {
+ if (cpuFreqTimes[i] != 0) {
+ return cpuFreqTimes;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public long[] getScreenOffCpuFreqTimes(int which) {
+ if (mScreenOffCpuFreqTimeMs == null) {
+ return null;
+ }
+ final long[] cpuFreqTimes = mScreenOffCpuFreqTimeMs.getCountsLocked(which);
+ if (cpuFreqTimes == null) {
+ return null;
+ }
+ // Return cpuFreqTimes only if atleast one of the elements in non-zero.
+ for (int i = 0; i < cpuFreqTimes.length; ++i) {
+ if (cpuFreqTimes[i] != 0) {
+ return cpuFreqTimes;
+ }
+ }
+ return null;
+ }
+
+ @Override
public ArrayMap<String, ? extends BatteryStats.Uid.Wakelock> getWakelockStats() {
return mWakelockStats.getMap();
}
@@ -6354,6 +6524,13 @@
}
}
+ if (mCpuFreqTimeMs != null) {
+ mCpuFreqTimeMs.reset(false);
+ }
+ if (mScreenOffCpuFreqTimeMs != null) {
+ mScreenOffCpuFreqTimeMs.reset(false);
+ }
+
resetLongCounterIfNotNull(mMobileRadioApWakeupCount, false);
resetLongCounterIfNotNull(mWifiRadioApWakeupCount, false);
@@ -6523,6 +6700,13 @@
}
}
+ if (mCpuFreqTimeMs != null) {
+ mCpuFreqTimeMs.detach();
+ }
+ if (mScreenOffCpuFreqTimeMs != null) {
+ mScreenOffCpuFreqTimeMs.detach();
+ }
+
detachLongCounterIfNotNull(mMobileRadioApWakeupCount);
detachLongCounterIfNotNull(mWifiRadioApWakeupCount);
}
@@ -6739,6 +6923,19 @@
out.writeInt(0);
}
+ if (mCpuFreqTimeMs != null) {
+ out.writeInt(1);
+ mCpuFreqTimeMs.writeToParcel(out);
+ } else {
+ out.writeInt(0);
+ }
+ if (mScreenOffCpuFreqTimeMs != null) {
+ out.writeInt(1);
+ mScreenOffCpuFreqTimeMs.writeToParcel(out);
+ } else {
+ out.writeInt(0);
+ }
+
if (mMobileRadioApWakeupCount != null) {
out.writeInt(1);
mMobileRadioApWakeupCount.writeToParcel(out);
@@ -6987,6 +7184,18 @@
}
if (in.readInt() != 0) {
+ mCpuFreqTimeMs = new LongSamplingCounterArray(mBsi.mOnBatteryTimeBase, in);
+ } else {
+ mCpuFreqTimeMs = null;
+ }
+ if (in.readInt() != 0) {
+ mScreenOffCpuFreqTimeMs = new LongSamplingCounterArray(
+ mBsi.mOnBatteryScreenOffTimeBase, in);
+ } else {
+ mScreenOffCpuFreqTimeMs = null;
+ }
+
+ if (in.readInt() != 0) {
mMobileRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
} else {
mMobileRadioApWakeupCount = null;
@@ -8192,6 +8401,10 @@
}
}
+ public long[] getCpuFreqs() {
+ return mCpuFreqs;
+ }
+
public BatteryStatsImpl(File systemDir, Handler handler, ExternalStatsSync externalSync) {
this(new SystemClocks(), systemDir, handler, externalSync, null);
}
@@ -9812,6 +10025,8 @@
}
});
+ readKernelUidCpuFreqTimesLocked();
+
final long elapse = (mClocks.elapsedRealtime() - startTimeMs);
if (DEBUG_ENERGY_CPU || (elapse >= 100)) {
Slog.d(TAG, "Reading cpu stats took " + elapse + " ms");
@@ -9900,6 +10115,30 @@
}
}
+ void readKernelUidCpuFreqTimesLocked() {
+ mKernelUidCpuFreqTimeReader.readDelta(!mOnBatteryInternal ? null :
+ new KernelUidCpuFreqTimeReader.Callback() {
+ @Override
+ public void onCpuFreqs(long[] cpuFreqs) {
+ mCpuFreqs = cpuFreqs;
+ }
+
+ @Override
+ public void onUidCpuFreqTime(int uid, long[] cpuFreqTimeMs) {
+ final Uid u = getUidStatsLocked(uid);
+ if (u.mCpuFreqTimeMs == null) {
+ u.mCpuFreqTimeMs = new LongSamplingCounterArray(mOnBatteryTimeBase);
+ }
+ u.mCpuFreqTimeMs.addCountLocked(cpuFreqTimeMs);
+ if (u.mScreenOffCpuFreqTimeMs == null) {
+ u.mScreenOffCpuFreqTimeMs = new LongSamplingCounterArray(
+ mOnBatteryScreenOffTimeBase);
+ }
+ u.mScreenOffCpuFreqTimeMs.addCountLocked(cpuFreqTimeMs);
+ }
+ });
+ }
+
boolean setChargingLocked(boolean charging) {
if (mCharging != charging) {
mCharging = charging;
@@ -10988,6 +11227,8 @@
}
}
+ mCpuFreqs = in.createLongArray();
+
final int NU = in.readInt();
if (NU > 10000) {
throw new ParcelFormatException("File corrupt: too many uids " + NU);
@@ -11111,6 +11352,20 @@
}
if (in.readInt() != 0) {
+ u.mCpuFreqTimeMs = new LongSamplingCounterArray(mOnBatteryTimeBase);
+ u.mCpuFreqTimeMs.readSummaryFromParcelLocked(in);
+ } else {
+ u.mCpuFreqTimeMs = null;
+ }
+ if (in.readInt() != 0) {
+ u.mScreenOffCpuFreqTimeMs = new LongSamplingCounterArray(
+ mOnBatteryScreenOffTimeBase);
+ u.mScreenOffCpuFreqTimeMs.readSummaryFromParcelLocked(in);
+ } else {
+ u.mScreenOffCpuFreqTimeMs = null;
+ }
+
+ if (in.readInt() != 0) {
u.mMobileRadioApWakeupCount = new LongSamplingCounter(mOnBatteryTimeBase);
u.mMobileRadioApWakeupCount.readSummaryFromParcelLocked(in);
} else {
@@ -11360,6 +11615,8 @@
}
}
+ out.writeLongArray(mCpuFreqs);
+
final int NU = mUidStats.size();
out.writeInt(NU);
for (int iu = 0; iu < NU; iu++) {
@@ -11504,6 +11761,19 @@
out.writeInt(0);
}
+ if (u.mCpuFreqTimeMs != null) {
+ out.writeInt(1);
+ u.mCpuFreqTimeMs.writeSummaryFromParcelLocked(out);
+ } else {
+ out.writeInt(0);
+ }
+ if (u.mScreenOffCpuFreqTimeMs != null) {
+ out.writeInt(1);
+ u.mScreenOffCpuFreqTimeMs.writeSummaryFromParcelLocked(out);
+ } else {
+ out.writeInt(0);
+ }
+
if (u.mMobileRadioApWakeupCount != null) {
out.writeInt(1);
u.mMobileRadioApWakeupCount.writeSummaryFromParcelLocked(out);
@@ -11794,6 +12064,8 @@
mFlashlightTurnedOnTimers.clear();
mCameraTurnedOnTimers.clear();
+ mCpuFreqs = in.createLongArray();
+
int numUids = in.readInt();
mUidStats.clear();
for (int i = 0; i < numUids; i++) {
@@ -11953,6 +12225,8 @@
}
}
+ out.writeLongArray(mCpuFreqs);
+
if (inclUids) {
int size = mUidStats.size();
out.writeInt(size);
diff --git a/core/java/com/android/internal/os/KernelUidCpuFreqTimeReader.java b/core/java/com/android/internal/os/KernelUidCpuFreqTimeReader.java
new file mode 100644
index 0000000..568c883
--- /dev/null
+++ b/core/java/com/android/internal/os/KernelUidCpuFreqTimeReader.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2017 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.os;
+
+import android.annotation.Nullable;
+import android.util.Slog;
+import android.util.SparseArray;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.io.IOException;
+
+/**
+ * Reads /proc/uid_time_in_state which has the format:
+ *
+ * uid: [freq1] [freq2] [freq3] ...
+ * [uid1]: [time in freq1] [time in freq2] [time in freq3] ...
+ * [uid2]: [time in freq1] [time in freq2] [time in freq3] ...
+ * ...
+ *
+ * This provides the times a UID's processes spent executing at each different cpu frequency.
+ * The file contains a monotonically increasing count of time for a single boot. This class
+ * maintains the previous results of a call to {@link #readDelta} in order to provide a proper
+ * delta.
+ */
+public class KernelUidCpuFreqTimeReader {
+ private static final String TAG = "KernelUidCpuFreqTimeReader";
+ private static final String UID_TIMES_PROC_FILE = "/proc/uid_time_in_state";
+
+ public interface Callback {
+ void onCpuFreqs(long[] cpuFreqs);
+ void onUidCpuFreqTime(int uid, long[] cpuFreqTimeMs);
+ }
+
+ private long[] mCpuFreqs;
+ private int mCpuFreqsCount;
+
+ private SparseArray<long[]> mLastUidCpuFreqTimeMs = new SparseArray<>();
+
+ public void readDelta(@Nullable Callback callback) {
+ try (BufferedReader reader = new BufferedReader(new FileReader(UID_TIMES_PROC_FILE))) {
+ readDelta(reader, callback);
+ } catch (IOException e) {
+ Slog.e(TAG, "Failed to read " + UID_TIMES_PROC_FILE + ": " + e);
+ }
+ }
+
+ @VisibleForTesting
+ public void readDelta(BufferedReader reader, @Nullable Callback callback) throws IOException {
+ String line = reader.readLine();
+ if (line == null) {
+ return;
+ }
+ readCpuFreqs(line, callback);
+ while ((line = reader.readLine()) != null) {
+ final int index = line.indexOf(' ');
+ final int uid = Integer.parseInt(line.substring(0, index - 1), 10);
+ readTimesForUid(uid, line.substring(index + 1, line.length()), callback);
+ }
+ }
+
+ private void readTimesForUid(int uid, String line, Callback callback) {
+ long[] uidTimeMs = mLastUidCpuFreqTimeMs.get(uid);
+ if (uidTimeMs == null) {
+ uidTimeMs = new long[mCpuFreqsCount];
+ mLastUidCpuFreqTimeMs.put(uid, uidTimeMs);
+ }
+ final String[] timesStr = line.split(" ");
+ final int size = timesStr.length;
+ if (size != uidTimeMs.length) {
+ Slog.e(TAG, "No. of readings don't match cpu freqs, readings: " + size
+ + " cpuFreqsCount: " + uidTimeMs.length);
+ return;
+ }
+ final long[] deltaUidTimeMs = new long[size];
+ for (int i = 0; i < size; ++i) {
+ // Times read will be in units of 10ms
+ final long totalTimeMs = Long.parseLong(timesStr[i], 10) * 10;
+ deltaUidTimeMs[i] = totalTimeMs - uidTimeMs[i];
+ uidTimeMs[i] = totalTimeMs;
+ }
+ if (callback != null) {
+ callback.onUidCpuFreqTime(uid, deltaUidTimeMs);
+ }
+ }
+
+ private void readCpuFreqs(String line, Callback callback) {
+ if (mCpuFreqs == null) {
+ final String[] freqStr = line.split(" ");
+ // First item would be "uid:" which needs to be ignored
+ mCpuFreqsCount = freqStr.length - 1;
+ mCpuFreqs = new long[mCpuFreqsCount];
+ for (int i = 0; i < mCpuFreqsCount; ++i) {
+ mCpuFreqs[i] = Long.parseLong(freqStr[i + 1], 10);
+ }
+ }
+ if (callback != null) {
+ callback.onCpuFreqs(mCpuFreqs);
+ }
+ }
+}
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index ee2f1ca..54d5285 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -37,8 +37,6 @@
/** Tests that ensure appropriate settings are backed up. */
@RunWith(AndroidJUnit4.class)
-// TODO(b/37684646): Can re-enable pre-submit once test is fixed.
-//@Presubmit
@SmallTest
public class SettingsBackupTest {
@@ -167,6 +165,7 @@
Settings.Global.DEVICE_IDLE_CONSTANTS_WATCH,
Settings.Global.BATTERY_SAVER_CONSTANTS,
Settings.Global.DEVICE_NAME,
+ Settings.Global.DEVICE_POLICY_CONSTANTS,
Settings.Global.DEVICE_PROVISIONED,
Settings.Global.DEVICE_PROVISIONING_MOBILE_DATA_ENABLED,
Settings.Global.DISK_FREE_CHANGE_REPORTING_THRESHOLD,
@@ -379,6 +378,7 @@
Settings.Global.WIFI_SUPPLICANT_SCAN_INTERVAL_MS,
Settings.Global.WIFI_SUSPEND_OPTIMIZATIONS_ENABLED,
Settings.Global.WIFI_VERBOSE_LOGGING_ENABLED,
+ Settings.Global.WIFI_WAKEUP_AVAILABLE,
Settings.Global.WIFI_WATCHDOG_ON,
Settings.Global.WIMAX_NETWORKS_AVAILABLE_NOTIFICATION_ON,
Settings.Global.WINDOW_ANIMATION_SCALE,
diff --git a/core/tests/coretests/src/com/android/internal/os/KernelUidCpuFreqTimeReaderTest.java b/core/tests/coretests/src/com/android/internal/os/KernelUidCpuFreqTimeReaderTest.java
new file mode 100644
index 0000000..ad8221b
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/os/KernelUidCpuFreqTimeReaderTest.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2017 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.os;
+
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
+
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.io.BufferedReader;
+
+/**
+ * Test class for {@link KernelUidCpuFreqTimeReader}.
+ *
+ * To run the tests, use
+ *
+ * runtest -c com.android.internal.os.KernelUidCpuFreqTimeReaderTest frameworks-core
+ *
+ * or the following steps:
+ *
+ * Build: m FrameworksCoreTests
+ * Install: adb install -r \
+ * ${ANDROID_PRODUCT_OUT}/data/app/FrameworksCoreTests/FrameworksCoreTests.apk
+ * Run: adb shell am instrument -e class com.android.internal.os.KernelUidCpuFreqTimeReaderTest -w \
+ * com.android.frameworks.coretests/android.support.test.runner.AndroidJUnitRunner
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class KernelUidCpuFreqTimeReaderTest {
+ @Mock private BufferedReader mBufferedReader;
+ @Mock private KernelUidCpuFreqTimeReader.Callback mCallback;
+
+ private KernelUidCpuFreqTimeReader mKernelUidCpuFreqTimeReader;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mKernelUidCpuFreqTimeReader = new KernelUidCpuFreqTimeReader();
+ }
+
+ @Test
+ public void testReadDelta() throws Exception {
+ final long[] freqs = {1, 12, 123, 1234, 12345, 123456};
+ final int[] uids = {1, 22, 333, 4444, 5555};
+ final long[][] times = new long[uids.length][freqs.length];
+ for (int i = 0; i < uids.length; ++i) {
+ for (int j = 0; j < freqs.length; ++j) {
+ times[i][j] = uids[i] * freqs[j] * 10;
+ }
+ }
+ final String[] uidsTimesLines = getUidTimesLines(uids, times);
+ final String[] lines = new String[uidsTimesLines.length + 1];
+ System.arraycopy(uidsTimesLines, 0, lines, 0, uidsTimesLines.length);
+ lines[uidsTimesLines.length] = null;
+ when(mBufferedReader.readLine())
+ .thenReturn(getFreqsLine(freqs), lines);
+ mKernelUidCpuFreqTimeReader.readDelta(mBufferedReader, mCallback);
+ verify(mCallback).onCpuFreqs(freqs);
+ for (int i = 0; i < uids.length; ++i) {
+ verify(mCallback).onUidCpuFreqTime(uids[i], times[i]);
+ }
+ verifyNoMoreInteractions(mCallback);
+ }
+
+ private String getFreqsLine(long[] freqs) {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("uid:");
+ for (int i = 0; i < freqs.length; ++i) {
+ sb.append(" " + freqs[i]);
+ }
+ return sb.toString();
+ }
+
+ private String[] getUidTimesLines(int[] uids, long[][] times) {
+ final String[] lines = new String[uids.length];
+ final StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < uids.length; ++i) {
+ sb.setLength(0);
+ sb.append(uids[i] + ":");
+ for (int j = 0; j < times[i].length; ++j) {
+ sb.append(" " + times[i][j] / 10);
+ }
+ lines[i] = sb.toString();
+ }
+ return lines;
+ }
+}
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index 40d36aa..d586db4 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -1879,15 +1879,22 @@
}
/**
- * Rebuilds any caches associated with the bitmap that are used for
- * drawing it. In the case of purgeable bitmaps, this call will attempt to
- * ensure that the pixels have been decoded.
- * If this is called on more than one bitmap in sequence, the priority is
- * given in LRU order (i.e. the last bitmap called will be given highest
- * priority).
+ * Builds caches associated with the bitmap that are used for drawing it.
*
- * For bitmaps with no associated caches, this call is effectively a no-op,
- * and therefore is harmless.
+ * <p>Starting in {@link android.os.Build.VERSION_CODES#N}, this call initiates an asynchronous
+ * upload to the GPU on RenderThread, if the Bitmap is not already uploaded. With Hardware
+ * Acceleration, Bitmaps must be uploaded to the GPU in order to be rendered. This is done by
+ * default the first time a Bitmap is drawn, but the process can take several milliseconds,
+ * depending on the size of the Bitmap. Each time a Bitmap is modified and drawn again, it must
+ * be re-uploaded.</p>
+ *
+ * <p>Calling this method in advance can save time in the first frame it's used. For example, it
+ * is recommended to call this on an image decoding worker thread when a decoded Bitmap is about
+ * to be displayed. It is recommended to make any pre-draw modifications to the Bitmap before
+ * calling this method, so the cached, uploaded copy may be reused without re-uploading.</p>
+ *
+ * In {@link android.os.Build.VERSION_CODES#KITKAT} and below, for purgeable bitmaps, this call
+ * would attempt to ensure that the pixels have been decoded.
*/
public void prepareToDraw() {
checkRecycled("Can't prepareToDraw on a recycled bitmap!");
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
index d1d59b2..1e171d3 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
@@ -62,11 +62,12 @@
*/
private static final ArraySet<String> sBroadcastOnRestore;
static {
- sBroadcastOnRestore = new ArraySet<String>(4);
+ sBroadcastOnRestore = new ArraySet<String>(5);
sBroadcastOnRestore.add(Settings.Secure.ENABLED_NOTIFICATION_LISTENERS);
sBroadcastOnRestore.add(Settings.Secure.ENABLED_VR_LISTENERS);
sBroadcastOnRestore.add(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
sBroadcastOnRestore.add(Settings.Secure.ENABLED_INPUT_METHODS);
+ sBroadcastOnRestore.add(Settings.Global.BLUETOOTH_ON);
}
private interface SettingsLookup {
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 1d743b4..5460304 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -58,6 +58,7 @@
<uses-permission android:name="android.permission.OVERRIDE_WIFI_CONFIG" />
<uses-permission android:name="android.permission.MANAGE_NETWORK_POLICY" />
<uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" />
+ <uses-permission android:name="android.permission.NETWORK_SETTINGS" />
<uses-permission android:name="android.permission.TETHER_PRIVILEGED" />
<uses-permission android:name="android.permission.READ_NETWORK_USAGE_HISTORY" />
<uses-permission android:name="android.permission.REQUEST_NETWORK_SCORES" />
diff --git a/packages/SystemUI/res/drawable/qs_background_primary.xml b/packages/SystemUI/res/drawable/qs_background_primary.xml
index 0bdbc5f..8ea9e06 100644
--- a/packages/SystemUI/res/drawable/qs_background_primary.xml
+++ b/packages/SystemUI/res/drawable/qs_background_primary.xml
@@ -15,6 +15,6 @@
-->
<inset xmlns:android="http://schemas.android.com/apk/res/android">
<shape>
- <solid android:color="?android:attr/colorPrimaryDark"/>
+ <solid android:color="?android:attr/colorPrimary"/>
</shape>
</inset>
diff --git a/packages/SystemUI/res/layout/qs_customize_panel.xml b/packages/SystemUI/res/layout/qs_customize_panel.xml
index 9ab8ac6..cbc2575 100644
--- a/packages/SystemUI/res/layout/qs_customize_panel.xml
+++ b/packages/SystemUI/res/layout/qs_customize_panel.xml
@@ -21,6 +21,7 @@
android:layout_width="match_parent"
android:layout_height="0dp"
android:orientation="vertical"
+ android:elevation="4dp"
android:background="@drawable/qs_customizer_background"
android:gravity="center_horizontal">
diff --git a/packages/SystemUI/res/layout/qs_detail.xml b/packages/SystemUI/res/layout/qs_detail.xml
index 1c087b3..f41c494 100644
--- a/packages/SystemUI/res/layout/qs_detail.xml
+++ b/packages/SystemUI/res/layout/qs_detail.xml
@@ -20,6 +20,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/qs_detail_background"
+ android:elevation="4dp"
android:clickable="true"
android:orientation="vertical"
android:paddingBottom="8dp"
diff --git a/packages/SystemUI/res/layout/qs_footer.xml b/packages/SystemUI/res/layout/qs_footer.xml
index 047f7aa..c92c811 100644
--- a/packages/SystemUI/res/layout/qs_footer.xml
+++ b/packages/SystemUI/res/layout/qs_footer.xml
@@ -21,6 +21,7 @@
android:id="@+id/header"
android:layout_width="match_parent"
android:layout_height="48dp"
+ android:elevation="4dp"
android:baselineAligned="false"
android:clickable="false"
android:clipChildren="false"
diff --git a/packages/SystemUI/res/layout/qs_panel.xml b/packages/SystemUI/res/layout/qs_panel.xml
index 3658313..fb47bbc 100644
--- a/packages/SystemUI/res/layout/qs_panel.xml
+++ b/packages/SystemUI/res/layout/qs_panel.xml
@@ -14,22 +14,28 @@
limitations under the License.
-->
<com.android.systemui.qs.QSContainerImpl
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/quick_settings_container"
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/quick_settings_container"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="?android:attr/colorPrimaryDark"
+ android:clipToPadding="false"
+ android:clipChildren="false">
+
+ <View
+ android:id="@+id/qs_background"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
+ android:layout_height="match_parent"
android:background="@drawable/qs_background_primary"
- android:clipToPadding="false"
- android:clipChildren="false"
- android:elevation="4dp">
+ android:elevation="4dp" />
<com.android.systemui.qs.QSPanel
- android:id="@+id/quick_settings_panel"
- android:background="#0000"
- android:layout_marginTop="28dp"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginBottom="48dp" />
+ android:id="@+id/quick_settings_panel"
+ android:layout_marginTop="28dp"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:elevation="4dp"
+ android:layout_marginBottom="48dp" />
<include layout="@layout/quick_status_bar_expanded_header" />
diff --git a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
index 520dab4..65344b7 100644
--- a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
@@ -24,6 +24,7 @@
android:layout_height="@dimen/status_bar_header_height"
android:layout_gravity="@integer/notification_panel_layout_gravity"
android:baselineAligned="false"
+ android:elevation="4dp"
android:clickable="false"
android:clipChildren="false"
android:clipToPadding="false"
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 63abee7..c00b562 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -775,4 +775,6 @@
<dimen name="signal_icon_size">17dp</dimen>
+ <dimen name="qs_gutter_height">6dp</dimen>
+
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 88e8b39..2504e36 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -675,9 +675,14 @@
mLockPatternUtils = new LockPatternUtils(mContext);
KeyguardUpdateMonitor.setCurrentUser(ActivityManager.getCurrentUser());
- // Assume keyguard is showing (unless it's disabled) until we know for sure...
- setShowingLocked(!shouldWaitForProvisioning() && !mLockPatternUtils.isLockScreenDisabled(
- KeyguardUpdateMonitor.getCurrentUser()), true /* forceCallbacks */);
+ // Assume keyguard is showing (unless it's disabled) until we know for sure, unless Keyguard
+ // is disabled.
+ if (mContext.getResources().getBoolean(
+ com.android.keyguard.R.bool.config_enableKeyguardService)) {
+ setShowingLocked(!shouldWaitForProvisioning()
+ && !mLockPatternUtils.isLockScreenDisabled(
+ KeyguardUpdateMonitor.getCurrentUser()), true /* forceCallbacks */);
+ }
mStatusBarKeyguardViewManager =
SystemUIFactory.getInstance().createStatusBarKeyguardViewManager(mContext,
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipNotification.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipNotification.java
index 727eb5a..5b54d85 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipNotification.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipNotification.java
@@ -44,6 +44,7 @@
*/
public class PipNotification {
private static final String TAG = "PipNotification";
+ private static final String NOTIFICATION_TAG = PipNotification.class.getName();
private static final boolean DEBUG = PipManager.DEBUG;
private static final String ACTION_MENU = "PipNotification.menu";
@@ -56,7 +57,7 @@
private MediaController mMediaController;
private String mDefaultTitle;
- private Icon mDefaultIcon;
+ private int mDefaultIconResId;
private boolean mNotified;
private String mTitle;
@@ -167,9 +168,8 @@
void onConfigurationChanged(Context context) {
Resources res = context.getResources();
mDefaultTitle = res.getString(R.string.pip_notification_unknown_title);
- mDefaultIcon = Icon.createWithResource(context,
- res.getConfiguration().getLayoutDirection() == View.LAYOUT_DIRECTION_LTR
- ? R.drawable.pip_expand_ll : R.drawable.pip_expand_lr);
+ mDefaultIconResId = res.getConfiguration().getLayoutDirection() == View.LAYOUT_DIRECTION_LTR
+ ? R.drawable.pip_expand_ll : R.drawable.pip_expand_lr;
if (mNotified) {
// update notification
notifyPipNotification();
@@ -181,12 +181,16 @@
mNotificationBuilder
.setShowWhen(true)
.setWhen(System.currentTimeMillis())
- // TODO: Sending bitmap doesn't work in launcher side. Once launcher supports it,
- // we can set icon.
- //.setSmallIcon(mArt != null ? Icon.createWithBitmap(mArt) : mDefaultIcon)
- .setSmallIcon(mDefaultIcon.getResId())
+ .setSmallIcon(mDefaultIconResId)
.setContentTitle(!TextUtils.isEmpty(mTitle) ? mTitle : mDefaultTitle);
- mNotificationManager.notify(SystemMessage.NOTE_TV_PIP, mNotificationBuilder.build());
+ if (mArt != null) {
+ mNotificationBuilder.setStyle(new Notification.BigPictureStyle()
+ .bigPicture(mArt));
+ } else {
+ mNotificationBuilder.setStyle(null);
+ }
+ mNotificationManager.notify(NOTIFICATION_TAG, SystemMessage.NOTE_TV_PIP,
+ mNotificationBuilder.build());
}
private void dismissPipNotification() {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
index 06264ba..189c04c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
@@ -17,11 +17,14 @@
package com.android.systemui.qs;
import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
import android.graphics.Point;
import android.util.AttributeSet;
import android.view.View;
import android.widget.FrameLayout;
+import com.android.settingslib.Utils;
import com.android.systemui.R;
import com.android.systemui.qs.customize.QSCustomizer;
@@ -39,6 +42,8 @@
protected float mQsExpansion;
private QSCustomizer mQSCustomizer;
private QSFooter mQSFooter;
+ private int mGutterHeight;
+ private View mBackground;
public QSContainerImpl(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -52,6 +57,8 @@
mHeader = findViewById(R.id.header);
mQSCustomizer = findViewById(R.id.qs_customize);
mQSFooter = findViewById(R.id.qs_footer);
+ mBackground = findViewById(R.id.qs_background);
+ mGutterHeight = getContext().getResources().getDimensionPixelSize(R.dimen.qs_gutter_height);
}
@Override
@@ -94,8 +101,9 @@
public void updateBottom() {
int height = calculateContainerHeight();
- setBottom(getTop() + height);
+ setBottom(getTop() + height + mGutterHeight);
mQSDetail.setBottom(getTop() + height);
+ mBackground.setBottom(mQSDetail.getBottom());
// Pin QS Footer to the bottom of the panel.
mQSFooter.setTranslationY(height - mQSFooter.getHeight());
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
index 406f107..5cf049a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
@@ -32,6 +32,7 @@
import com.android.systemui.Interpolators;
import com.android.systemui.R;
+import com.android.systemui.R.id;
import com.android.systemui.plugins.qs.QS;
import com.android.systemui.qs.customize.QSCustomizer;
import com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer;
@@ -61,6 +62,7 @@
private QSContainerImpl mContainer;
private int mLayoutDirection;
private QSFooter mFooter;
+ private int mGutterHeight;
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
@@ -75,7 +77,8 @@
mQSDetail = view.findViewById(R.id.qs_detail);
mHeader = view.findViewById(R.id.header);
mFooter = view.findViewById(R.id.qs_footer);
- mContainer = (QSContainerImpl) view;
+ mContainer = view.findViewById(id.quick_settings_container);
+ mGutterHeight = getContext().getResources().getDimensionPixelSize(R.dimen.qs_gutter_height);
mQSDetail.setQsPanel(mQSPanel, mHeader);
@@ -239,7 +242,8 @@
mContainer.setExpansion(expansion);
final float translationScaleY = expansion - 1;
if (!mHeaderAnimating) {
- getView().setTranslationY(mKeyguardShowing ? (translationScaleY * mHeader.getHeight())
+ int height = mHeader.getHeight() + mGutterHeight;
+ getView().setTranslationY(mKeyguardShowing ? (translationScaleY * height)
: headerTranslation);
}
mHeader.setExpansion(mKeyguardShowing ? 1 : expansion);
@@ -321,19 +325,19 @@
LayoutParams layoutParams = (LayoutParams) mQSPanel.getLayoutParams();
int panelHeight = layoutParams.topMargin + layoutParams.bottomMargin +
+ mQSPanel.getMeasuredHeight();
- return panelHeight + getView().getPaddingBottom();
+ return panelHeight + getView().getPaddingBottom() + mGutterHeight;
} else {
- return getView().getMeasuredHeight();
+ return getView().getMeasuredHeight() + mGutterHeight;
}
}
@Override
public void setHeightOverride(int desiredHeight) {
- mContainer.setHeightOverride(desiredHeight);
+ mContainer.setHeightOverride(desiredHeight - mGutterHeight);
}
public int getQsMinExpansionHeight() {
- return mHeader.getHeight();
+ return mHeader.getHeight() + mGutterHeight;
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
index 32af230..d12b16b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
@@ -340,10 +340,9 @@
switch (state) {
case Tile.STATE_UNAVAILABLE:
return Utils.getDisabled(context,
- Utils.getColorAttr(context, android.R.attr.textColorPrimary));
- case Tile.STATE_INACTIVE:
- return Utils.getDisabled(context,
Utils.getColorAttr(context, android.R.attr.colorForeground));
+ case Tile.STATE_INACTIVE:
+ return Utils.getColorAttr(context, android.R.attr.textColorHint);
case Tile.STATE_ACTIVE:
return Utils.getColorAttr(context, android.R.attr.textColorPrimary);
default:
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
index f5718d9..bae6a27 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
@@ -23,6 +23,7 @@
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
+import android.graphics.Color;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.MotionEvent;
@@ -177,6 +178,7 @@
* Similar to mDimmed but is also true if it's not dimmable but should be
*/
private boolean mNeedsDimming;
+ private int mDimmedAlpha;
public ActivatableNotificationView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -214,6 +216,8 @@
mBackgroundDimmed = findViewById(R.id.backgroundDimmed);
mBackgroundNormal.setCustomBackground(R.drawable.notification_material_bg);
mBackgroundDimmed.setCustomBackground(R.drawable.notification_material_bg_dim);
+ mDimmedAlpha = Color.alpha(mContext.getColor(
+ R.color.notification_material_background_dimmed_color));
updateBackground();
updateBackgroundTint();
updateOutlineAlpha();
@@ -492,10 +496,21 @@
* used and the background color not at all.
*/
public void setOverrideTintColor(int color, float overrideAmount) {
+ if (mDark) {
+ color = NO_COLOR;
+ overrideAmount = 0;
+ }
mOverrideTint = color;
mOverrideAmount = overrideAmount;
int newColor = calculateBgColor();
setBackgroundTintColor(newColor);
+ if (!isDimmable() && mNeedsDimming) {
+ mBackgroundNormal.setDrawableAlpha((int) NotificationUtils.interpolate(255,
+ mDimmedAlpha,
+ overrideAmount));
+ } else {
+ mBackgroundNormal.setDrawableAlpha(255);
+ }
}
protected void updateBackgroundTint() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java
index dea9e31f..194cdc7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java
@@ -144,4 +144,8 @@
ripple.setColor(ColorStateList.valueOf(color));
}
}
+
+ public void setDrawableAlpha(int drawableAlpha) {
+ mBackground.setAlpha(drawableAlpha);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index f2595e9..78a5194 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -202,7 +202,7 @@
// find the first view that doesn't overlap with the shelf
int notificationIndex = 0;
int notGoneIndex = 0;
- int colorOfViewBeforeLast = 0;
+ int colorOfViewBeforeLast = NO_COLOR;
boolean backgroundForceHidden = false;
if (mHideBackground && !mShelfState.hasItemsInStableShelf) {
backgroundForceHidden = true;
@@ -256,7 +256,10 @@
colorTwoBefore = previousColor;
transitionAmount = inShelfAmount;
}
- if (isLastChild && colorOfViewBeforeLast != NO_COLOR) {
+ if (isLastChild) {
+ if (colorOfViewBeforeLast == NO_COLOR) {
+ colorOfViewBeforeLast = ownColorUntinted;
+ }
row.setOverrideTintColor(colorOfViewBeforeLast, inShelfAmount);
} else {
colorOfViewBeforeLast = ownColorUntinted;
@@ -310,8 +313,9 @@
float fullTransitionAmount;
float iconTransitionAmount;
float shelfStart = getTranslationY();
- if (viewEnd >= shelfStart && (mAmbientState.isShadeExpanded()
- || (!row.isPinned() && !row.isHeadsUpAnimatingAway()))) {
+ if (viewEnd >= shelfStart && (!mAmbientState.isUnlockHintRunning() || row.isInShelf())
+ && (mAmbientState.isShadeExpanded()
+ || (!row.isPinned() && !row.isHeadsUpAnimatingAway()))) {
if (viewStart < shelfStart) {
float fullAmount = (shelfStart - viewStart) / fullHeight;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/MediaNotificationProcessor.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/MediaNotificationProcessor.java
index 52c053f..f6bd14c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/MediaNotificationProcessor.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/MediaNotificationProcessor.java
@@ -23,6 +23,7 @@
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
+import android.support.annotation.VisibleForTesting;
import android.support.v4.graphics.ColorUtils;
import android.support.v7.graphics.Palette;
import android.util.LayoutDirection;
@@ -57,9 +58,15 @@
private boolean mIsLowPriority;
public MediaNotificationProcessor(Context context, Context packageContext) {
+ this(context, packageContext, new ImageGradientColorizer());
+ }
+
+ @VisibleForTesting
+ MediaNotificationProcessor(Context context, Context packageContext,
+ ImageGradientColorizer colorizer) {
mContext = context;
mPackageContext = packageContext;
- mColorizer = new ImageGradientColorizer();
+ mColorizer = colorizer;
}
/**
@@ -74,6 +81,9 @@
Bitmap bitmap = null;
Drawable drawable = null;
if (largeIcon != null) {
+ // We're transforming the builder, let's make sure all baked in RemoteViews are
+ // rebuilt!
+ builder.setRebuildStyledRemoteViews(true);
drawable = largeIcon.loadDrawable(mPackageContext);
int backgroundColor = 0;
if (notification.isColorizedMedia()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 6a9bfae..0fa8afa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -1985,6 +1985,18 @@
}
@Override
+ protected void onUnlockHintFinished() {
+ super.onUnlockHintFinished();
+ mNotificationStackScroller.setUnlockHintRunning(false);
+ }
+
+ @Override
+ protected void onUnlockHintStarted() {
+ super.onUnlockHintStarted();
+ mNotificationStackScroller.setUnlockHintRunning(true);
+ }
+
+ @Override
public KeyguardAffordanceView getLeftIcon() {
return getLayoutDirection() == LAYOUT_DIRECTION_RTL
? mKeyguardBottomArea.getRightView()
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index d342635..e378e871 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -35,7 +35,6 @@
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.systemui.DejankUtils;
-import com.android.systemui.EventLogConstants;
import com.android.systemui.EventLogTags;
import com.android.systemui.Interpolators;
import com.android.keyguard.LatencyTracker;
@@ -1020,14 +1019,22 @@
@Override
public void run() {
notifyExpandingFinished();
- mStatusBar.onHintFinished();
+ onUnlockHintFinished();
mHintAnimationRunning = false;
}
});
- mStatusBar.onUnlockHintStarted();
+ onUnlockHintStarted();
mHintAnimationRunning = true;
}
+ protected void onUnlockHintFinished() {
+ mStatusBar.onHintFinished();
+ }
+
+ protected void onUnlockHintStarted() {
+ mStatusBar.onUnlockHintStarted();
+ }
+
/**
* Phase 1: Move everything upwards.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java
index b2b23a55..e409b9c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java
@@ -60,6 +60,7 @@
private boolean mExpansionChanging;
private boolean mPanelFullWidth;
private boolean mPulsing;
+ private boolean mUnlockHintRunning;
public AmbientState(Context context) {
reload(context);
@@ -305,4 +306,12 @@
public void setPanelFullWidth(boolean panelFullWidth) {
mPanelFullWidth = panelFullWidth;
}
+
+ public void setUnlockHintRunning(boolean unlockHintRunning) {
+ mUnlockHintRunning = unlockHintRunning;
+ }
+
+ public boolean isUnlockHintRunning() {
+ return mUnlockHintRunning;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 2f7a4ed..61fed2d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -4230,6 +4230,10 @@
mAmbientState.setPanelFullWidth(isFullWidth);
}
+ public void setUnlockHintRunning(boolean running) {
+ mAmbientState.setUnlockHintRunning(running);
+ }
+
/**
* A listener that is notified when some child locations might have changed.
*/
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/MediaNotificationProcessorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/MediaNotificationProcessorTest.java
new file mode 100644
index 0000000..5d3a86d
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/MediaNotificationProcessorTest.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2017 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.systemui.statusbar.notification;
+
+import static org.junit.Assert.assertNotSame;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+
+import android.app.Notification;
+import android.graphics.Bitmap;
+import android.graphics.drawable.Drawable;
+import android.support.test.runner.AndroidJUnit4;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.widget.RemoteViews;
+
+import com.android.systemui.R;
+import com.android.systemui.SysuiTestCase;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class MediaNotificationProcessorTest extends SysuiTestCase {
+
+ private MediaNotificationProcessor mProcessor;
+ private Bitmap mBitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
+ private ImageGradientColorizer mColorizer;
+
+ @Before
+ public void setUp() {
+ mColorizer = spy(new TestableColorizer(mBitmap));
+ mProcessor = new MediaNotificationProcessor(getContext(), getContext(), mColorizer);
+ }
+
+ @Test
+ public void testColorizedWithLargeIcon() {
+ Notification.Builder builder = new Notification.Builder(getContext()).setSmallIcon(
+ R.drawable.ic_person)
+ .setContentTitle("Title")
+ .setLargeIcon(mBitmap)
+ .setContentText("Text");
+ Notification notification = builder.build();
+ mProcessor.processNotification(notification, builder);
+ verify(mColorizer).colorize(any(), anyInt(), anyBoolean());
+ }
+
+ @Test
+ public void testNotColorizedWithoutLargeIcon() {
+ Notification.Builder builder = new Notification.Builder(getContext()).setSmallIcon(
+ R.drawable.ic_person)
+ .setContentTitle("Title")
+ .setContentText("Text");
+ Notification notification = builder.build();
+ mProcessor.processNotification(notification, builder);
+ verifyZeroInteractions(mColorizer);
+ }
+
+ @Test
+ public void testRemoteViewsReset() {
+ Notification.Builder builder = new Notification.Builder(getContext()).setSmallIcon(
+ R.drawable.ic_person)
+ .setContentTitle("Title")
+ .setStyle(new Notification.MediaStyle())
+ .setLargeIcon(mBitmap)
+ .setContentText("Text");
+ Notification notification = builder.build();
+ RemoteViews remoteViews = new RemoteViews(getContext().getPackageName(),
+ R.layout.custom_view_dark);
+ notification.contentView = remoteViews;
+ notification.bigContentView = remoteViews;
+ notification.headsUpContentView = remoteViews;
+ mProcessor.processNotification(notification, builder);
+ verify(mColorizer).colorize(any(), anyInt(), anyBoolean());
+ RemoteViews contentView = builder.createContentView();
+ assertNotSame(contentView, remoteViews);
+ contentView = builder.createBigContentView();
+ assertNotSame(contentView, remoteViews);
+ contentView = builder.createHeadsUpContentView();
+ assertNotSame(contentView, remoteViews);
+ }
+
+ public static class TestableColorizer extends ImageGradientColorizer {
+ private final Bitmap mBitmap;
+
+ private TestableColorizer(Bitmap bitmap) {
+ mBitmap = bitmap;
+ }
+
+ @Override
+ public Bitmap colorize(Drawable drawable, int backgroundColor, boolean isRtl) {
+ return mBitmap;
+ }
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationInflaterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationInflaterTest.java
index 15381b7..0c5bdea 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationInflaterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationInflaterTest.java
@@ -162,7 +162,7 @@
}
});
block.run();
- countDownLatch.await(5, java.util.concurrent.TimeUnit.SECONDS);
+ countDownLatch.await();
if (exceptionHolder.mException != null) {
throw exceptionHolder.mException;
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/notification/PropertyAnimatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/PropertyAnimatorTest.java
similarity index 94%
rename from packages/SystemUI/tests/src/com/android/systemui/notification/PropertyAnimatorTest.java
rename to packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/PropertyAnimatorTest.java
index 8484bed..eaa073c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/notification/PropertyAnimatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/PropertyAnimatorTest.java
@@ -1,18 +1,20 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2017 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
+ * 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.
+ * 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.systemui.notification;
+package com.android.systemui.statusbar.notification;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/notification/VisualStabilityManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/VisualStabilityManagerTest.java
similarity index 93%
rename from packages/SystemUI/tests/src/com/android/systemui/notification/VisualStabilityManagerTest.java
rename to packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/VisualStabilityManagerTest.java
index 76bb6c0..e4c43735 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/notification/VisualStabilityManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/VisualStabilityManagerTest.java
@@ -1,18 +1,20 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2017 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
+ * 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.
+ * 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.systemui.notification;
+package com.android.systemui.statusbar.notification;
import android.service.notification.StatusBarNotification;
import android.support.test.runner.AndroidJUnit4;
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
index faa6182..35371a7 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
@@ -621,16 +621,17 @@
@Override
protected Void doInBackground(Void... ignored) {
int numSessionsToRemove;
- ArrayMap<IBinder, Integer> sessionsToRemove;
+
+ SparseArray<IBinder> sessionsToRemove;
synchronized (mLock) {
numSessionsToRemove = mSessions.size();
- sessionsToRemove = new ArrayMap<>(numSessionsToRemove);
+ sessionsToRemove = new SparseArray<>(numSessionsToRemove);
for (int i = 0; i < numSessionsToRemove; i++) {
Session session = mSessions.valueAt(i);
- sessionsToRemove.put(session.getActivityTokenLocked(), session.id);
+ sessionsToRemove.put(session.id, session.getActivityTokenLocked());
}
}
@@ -640,7 +641,7 @@
for (int i = 0; i < numSessionsToRemove; i++) {
try {
// The activity manager cannot resolve activities that have been removed
- if (am.getActivityClassForToken(sessionsToRemove.keyAt(i)) != null) {
+ if (am.getActivityClassForToken(sessionsToRemove.valueAt(i)) != null) {
sessionsToRemove.removeAt(i);
i--;
numSessionsToRemove--;
@@ -652,9 +653,10 @@
synchronized (mLock) {
for (int i = 0; i < numSessionsToRemove; i++) {
- Session sessionToRemove = mSessions.get(sessionsToRemove.valueAt(i));
+ Session sessionToRemove = mSessions.get(sessionsToRemove.keyAt(i));
- if (sessionToRemove != null) {
+ if (sessionToRemove != null && sessionsToRemove.valueAt(i)
+ == sessionToRemove.getActivityTokenLocked()) {
if (sessionToRemove.isSavingLocked()) {
if (sVerbose) {
Slog.v(TAG, "Session " + sessionToRemove.id + " is saving");
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 4746ee9..6d58e72 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -1122,7 +1122,7 @@
private void notifyUnavailableToClient() {
synchronized (mLock) {
- if (!mHasCallback) return;
+ if (!mHasCallback || mCurrentViewId == null) return;
try {
mClient.notifyNoFillUi(id, mCurrentViewId);
} catch (RemoteException e) {
@@ -1371,10 +1371,15 @@
pw.print(prefix); pw.print("id: "); pw.println(id);
pw.print(prefix); pw.print("uid: "); pw.println(uid);
pw.print(prefix); pw.print("mActivityToken: "); pw.println(mActivityToken);
- pw.print(prefix); pw.print("mResponses: "); pw.println(mResponses.size());
- for (int i = 0; i < mResponses.size(); i++) {
- pw.print(prefix2); pw.print('#'); pw.print(i); pw.print(' ');
- pw.println(mResponses.valueAt(i));
+ pw.print(prefix); pw.print("mResponses: ");
+ if (mResponses == null) {
+ pw.println("null");
+ } else {
+ pw.println(mResponses.size());
+ for (int i = 0; i < mResponses.size(); i++) {
+ pw.print(prefix2); pw.print('#'); pw.print(i);
+ pw.print(' '); pw.println(mResponses.valueAt(i));
+ }
}
pw.print(prefix); pw.print("mCurrentViewId: "); pw.println(mCurrentViewId);
pw.print(prefix); pw.print("mViewStates size: "); pw.println(mViewStates.size());
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
index 6093241..73f1705 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
@@ -110,10 +110,15 @@
private final CompanionDeviceManagerImpl mImpl;
private final ConcurrentMap<Integer, AtomicFile> mUidToStorage = new ConcurrentHashMap<>();
private IDeviceIdleController mIdleController;
- private IFindDeviceCallback mFindDeviceCallback;
private ServiceConnection mServiceConnection;
private IAppOpsService mAppOpsManager;
+ private IFindDeviceCallback mFindDeviceCallback;
+ private AssociationRequest mRequest;
+ private String mCallingPackage;
+
+ private final Object mLock = new Object();
+
public CompanionDeviceManagerService(Context context) {
super(context);
mImpl = new CompanionDeviceManagerImpl();
@@ -156,8 +161,12 @@
}
private void cleanup() {
- mServiceConnection = unbind(mServiceConnection);
- mFindDeviceCallback = unlinkToDeath(mFindDeviceCallback, this, 0);
+ synchronized (mLock) {
+ mServiceConnection = unbind(mServiceConnection);
+ mFindDeviceCallback = unlinkToDeath(mFindDeviceCallback, this, 0);
+ mRequest = null;
+ mCallingPackage = null;
+ }
}
/**
@@ -222,6 +231,17 @@
}
@Override
+ public void stopScan(AssociationRequest request,
+ IFindDeviceCallback callback,
+ String callingPackage) {
+ if (Objects.equals(request, mRequest)
+ && Objects.equals(callback, mFindDeviceCallback)
+ && Objects.equals(callingPackage, mCallingPackage)) {
+ cleanup();
+ }
+ }
+
+ @Override
public List<String> getAssociations(String callingPackage, int userId)
throws RemoteException {
checkCallerIsSystemOr(callingPackage, userId);
@@ -340,7 +360,11 @@
"onServiceConnected(name = " + name + ", service = "
+ service + ")");
}
+
mFindDeviceCallback = findDeviceCallback;
+ mRequest = request;
+ mCallingPackage = callingPackage;
+
try {
mFindDeviceCallback.asBinder().linkToDeath(
CompanionDeviceManagerService.this, 0);
@@ -348,6 +372,7 @@
cleanup();
return;
}
+
try {
ICompanionDeviceDiscoveryService.Stub
.asInterface(service)
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index c785fb9..b65f54e 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -91,6 +91,7 @@
private static final String REASON_SYSTEM_BOOT = "system boot";
private static final String REASON_UNEXPECTED = "unexpected crash";
private static final String REASON_USER_SWITCH = "user switch";
+ private static final String REASON_RESTORE_USER_SETTING = "restore user setting";
private static final int TIMEOUT_BIND_MS = 3000; //Maximum msec to wait for a bind
//Maximum msec to wait for service restart
@@ -119,6 +120,10 @@
private static final int MESSAGE_USER_UNLOCKED = 301;
private static final int MESSAGE_ADD_PROXY_DELAYED = 400;
private static final int MESSAGE_BIND_PROFILE_SERVICE = 401;
+ private static final int MESSAGE_RESTORE_USER_SETTING = 500;
+
+ private static final int RESTORE_SETTING_TO_ON = 1;
+ private static final int RESTORE_SETTING_TO_OFF = 0;
private static final int MAX_ERROR_RESTART_RETRIES = 6;
@@ -318,6 +323,26 @@
} else {
if (DBG) Slog.e(TAG, "No Bluetooth Adapter address parameter found");
}
+ } else if (Intent.ACTION_SETTING_RESTORED.equals(action)) {
+ final String name = intent.getStringExtra(Intent.EXTRA_SETTING_NAME);
+ if (Settings.Global.BLUETOOTH_ON.equals(name)) {
+ // The Bluetooth On state may be changed during system restore.
+ final String prevValue = intent.getStringExtra(
+ Intent.EXTRA_SETTING_PREVIOUS_VALUE);
+ final String newValue = intent.getStringExtra(
+ Intent.EXTRA_SETTING_NEW_VALUE);
+
+ if (DBG) Slog.d(TAG, "ACTION_SETTING_RESTORED with BLUETOOTH_ON, prevValue=" +
+ prevValue + ", newValue=" + newValue);
+
+ if ((newValue != null) && (prevValue != null) && !prevValue.equals(newValue)) {
+ Message msg = mHandler.obtainMessage(MESSAGE_RESTORE_USER_SETTING,
+ newValue.equals("0") ?
+ RESTORE_SETTING_TO_OFF :
+ RESTORE_SETTING_TO_ON, 0);
+ mHandler.sendMessage(msg);
+ }
+ }
}
}
};
@@ -350,12 +375,14 @@
registerForBleScanModeChange();
mCallbacks = new RemoteCallbackList<IBluetoothManagerCallback>();
mStateChangeCallbacks = new RemoteCallbackList<IBluetoothStateChangeCallback>();
- IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED);
+
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED);
+ filter.addAction(BluetoothAdapter.ACTION_BLUETOOTH_ADDRESS_CHANGED);
+ filter.addAction(Intent.ACTION_SETTING_RESTORED);
filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
mContext.registerReceiver(mReceiver, filter);
- filter = new IntentFilter(BluetoothAdapter.ACTION_BLUETOOTH_ADDRESS_CHANGED);
- filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
- mContext.registerReceiver(mReceiver, filter);
+
loadStoredNameAndAddress();
if (isBluetoothPersistedStateOn()) {
if (DBG) Slog.d(TAG, "Startup: Bluetooth persisted state is ON.");
@@ -1421,6 +1448,20 @@
}
break;
+ case MESSAGE_RESTORE_USER_SETTING:
+ try {
+ if ((msg.arg1 == RESTORE_SETTING_TO_OFF) && mEnable) {
+ if (DBG) Slog.d(TAG, "Restore Bluetooth state to disabled");
+ disable(REASON_RESTORE_USER_SETTING, true);
+ } else if ((msg.arg1 == RESTORE_SETTING_TO_ON) && !mEnable) {
+ if (DBG) Slog.d(TAG, "Restore Bluetooth state to enabled");
+ enable(REASON_RESTORE_USER_SETTING);
+ }
+ } catch (RemoteException e) {
+ Slog.e(TAG,"Unable to change Bluetooth On setting", e);
+ }
+ break;
+
case MESSAGE_REGISTER_ADAPTER:
{
IBluetoothManagerCallback callback = (IBluetoothManagerCallback) msg.obj;
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 5283924..214edd0 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -14513,6 +14513,7 @@
// concurrently during execution of this method)
synchronized (this) {
sb.append("Process: ").append(processName).append("\n");
+ sb.append("PID: ").append(process.pid).append("\n");
int flags = process.info.flags;
IPackageManager pm = AppGlobals.getPackageManager();
sb.append("Flags: 0x").append(Integer.toHexString(flags)).append("\n");
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index f13dad7..4e00f2d 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -283,6 +283,7 @@
boolean visible; // does this activity's window need to be shown?
boolean visibleIgnoringKeyguard; // is this activity visible, ignoring the fact that Keyguard
// might hide this activity?
+ private boolean mLastSetWindowVisibility; // The last window visibility state that was set.
private boolean mDeferHidingClient; // If true we told WM to defer reporting to the client
// process that it is hidden.
boolean sleeping; // have we told the activity to sleep?
@@ -1581,6 +1582,10 @@
}
void setVisibility(boolean visible) {
+ if (mLastSetWindowVisibility == visible) {
+ return;
+ }
+ mLastSetWindowVisibility = visible;
mWindowContainerController.setVisibility(visible, mDeferHidingClient);
mStackSupervisor.mActivityMetricsLogger.notifyVisibilityChanged(this, visible);
}
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index c5d5867..c56e4ea 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -1933,7 +1933,7 @@
*
* @return true if {@param r} is visible taken Keyguard state into account, false otherwise
*/
- private boolean checkKeyguardVisibility(ActivityRecord r, boolean shouldBeVisible,
+ boolean checkKeyguardVisibility(ActivityRecord r, boolean shouldBeVisible,
boolean isTop) {
final boolean isInPinnedStack = r.getStack().getStackId() == PINNED_STACK_ID;
final boolean keyguardShowing = mStackSupervisor.mKeyguardController.isKeyguardShowing();
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 4049500..8210c07 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -1333,7 +1333,13 @@
}
r.startFreezingScreenLocked(app, 0);
- r.setVisibility(true);
+ if (r.getStack().checkKeyguardVisibility(r, true /* shouldBeVisible */, true /* isTop */)) {
+ // We only set the visibility to true if the activity is allowed to be visible based on
+ // keyguard state. This avoids setting this into motion in window manager that is later
+ // cancelled due to later calls to ensure visible activities that set visibility back to
+ // false.
+ r.setVisibility(true);
+ }
// schedule launch ticks to collect information about slow apps.
r.startLaunchTickingLocked();
diff --git a/services/core/java/com/android/server/job/JobStore.java b/services/core/java/com/android/server/job/JobStore.java
index 2e6cd3f..57b1ccc 100644
--- a/services/core/java/com/android/server/job/JobStore.java
+++ b/services/core/java/com/android/server/job/JobStore.java
@@ -807,7 +807,7 @@
ArrayList<JobStatus> result = new ArrayList<JobStatus>();
for (int i = mJobs.size() - 1; i >= 0; i--) {
if (UserHandle.getUserId(mJobs.keyAt(i)) == userId) {
- ArraySet<JobStatus> jobs = mJobs.get(i);
+ ArraySet<JobStatus> jobs = mJobs.valueAt(i);
if (jobs != null) {
result.addAll(jobs);
}
diff --git a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
index bb7ffda..6625331 100644
--- a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
@@ -724,6 +724,9 @@
grantRuntimePermissionsLPw(smsPackage, PHONE_PERMISSIONS, userId);
grantRuntimePermissionsLPw(smsPackage, CONTACTS_PERMISSIONS, userId);
grantRuntimePermissionsLPw(smsPackage, SMS_PERMISSIONS, userId);
+ grantRuntimePermissionsLPw(smsPackage, STORAGE_PERMISSIONS, userId);
+ grantRuntimePermissionsLPw(smsPackage, MICROPHONE_PERMISSIONS, userId);
+ grantRuntimePermissionsLPw(smsPackage, CAMERA_PERMISSIONS, userId);
}
}
@@ -737,6 +740,9 @@
grantRuntimePermissionsLPw(smsPackage, PHONE_PERMISSIONS, false, true, userId);
grantRuntimePermissionsLPw(smsPackage, CONTACTS_PERMISSIONS, false, true, userId);
grantRuntimePermissionsLPw(smsPackage, SMS_PERMISSIONS, false, true, userId);
+ grantRuntimePermissionsLPw(smsPackage, STORAGE_PERMISSIONS, false, true, userId);
+ grantRuntimePermissionsLPw(smsPackage, MICROPHONE_PERMISSIONS, false, true, userId);
+ grantRuntimePermissionsLPw(smsPackage, CAMERA_PERMISSIONS, false, true, userId);
}
}
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 1129076..8fcfc8f 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -29,7 +29,6 @@
import static com.android.server.pm.PackageInstallerService.prepareStageDir;
import android.app.admin.DevicePolicyManager;
-import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
@@ -46,7 +45,6 @@
import android.content.pm.PackageParser.PackageLite;
import android.content.pm.PackageParser.PackageParserException;
import android.content.pm.Signature;
-import android.content.pm.UserInfo;
import android.os.Binder;
import android.os.Bundle;
import android.os.FileBridge;
@@ -56,7 +54,6 @@
import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.os.Process;
-import android.os.ProxyFileDescriptorCallback;
import android.os.RemoteException;
import android.os.RevocableFileDescriptor;
import android.os.UserHandle;
@@ -1168,19 +1165,7 @@
// Send broadcast to default launcher only if it's a new install
final boolean isNewInstall = extras == null || !extras.getBoolean(Intent.EXTRA_REPLACING);
if (success && isNewInstall) {
- UserManagerService ums = UserManagerService.getInstance();
- if (ums != null) {
- final UserInfo parent = ums.getProfileParent(userId);
- final int launcherUid = (parent != null) ? parent.id : userId;
- final ComponentName launcherComponent = mPm.getDefaultHomeActivity(launcherUid);
- if (launcherComponent != null) {
- Intent launcherIntent = new Intent(PackageInstaller.ACTION_SESSION_COMMITTED)
- .putExtra(PackageInstaller.EXTRA_SESSION, generateInfo())
- .putExtra(Intent.EXTRA_USER, UserHandle.of(userId))
- .setPackage(launcherComponent.getPackageName());
- mContext.sendBroadcastAsUser(launcherIntent, UserHandle.of(launcherUid));
- }
- }
+ mPm.sendSessionCommitBroadcast(generateInfo(), userId);
}
mCallback.onSessionFinished(this, success);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 093cdbc..0e91d30 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -382,6 +382,8 @@
private static final boolean DEBUG_PACKAGE_SCANNING = false;
private static final boolean DEBUG_VERIFY = false;
private static final boolean DEBUG_FILTERS = false;
+ private static final boolean DEBUG_PERMISSIONS = false;
+ private static final boolean DEBUG_SHARED_LIBRARIES = false;
// Debug output for dexopting. This is shared between PackageManagerService, OtaDexoptService
// and PackageDexOptimizer. All these classes have their own flag to allow switching a single
@@ -2783,10 +2785,12 @@
// skip setup wizard; allow it to keep the high priority filter
continue;
}
- Slog.w(TAG, "Protected action; cap priority to 0;"
- + " package: " + filter.activity.info.packageName
- + " activity: " + filter.activity.className
- + " origPrio: " + filter.getPriority());
+ if (DEBUG_FILTERS) {
+ Slog.i(TAG, "Protected action; cap priority to 0;"
+ + " package: " + filter.activity.info.packageName
+ + " activity: " + filter.activity.className
+ + " origPrio: " + filter.getPriority());
+ }
filter.setPriority(0);
}
}
@@ -9298,8 +9302,8 @@
throw new PackageManagerException(INSTALL_FAILED_MISSING_SHARED_LIBRARY,
"Package " + packageName + " requires unavailable shared library "
+ libName + "; failing!");
- } else {
- Slog.w(TAG, "Package " + packageName
+ } else if (DEBUG_SHARED_LIBRARIES) {
+ Slog.i(TAG, "Package " + packageName
+ " desires unavailable shared library "
+ libName + "; ignoring!");
}
@@ -10662,13 +10666,13 @@
// Now that permission groups have a special meaning, we ignore permission
// groups for legacy apps to prevent unexpected behavior. In particular,
- // permissions for one app being granted to someone just becase they happen
+ // permissions for one app being granted to someone just because they happen
// to be in a group defined by another app (before this had no implications).
if (pkg.applicationInfo.targetSdkVersion > Build.VERSION_CODES.LOLLIPOP_MR1) {
p.group = mPermissionGroups.get(p.info.group);
// Warn for a permission in an unknown group.
- if (p.info.group != null && p.group == null) {
- Slog.w(TAG, "Permission " + p.info.name + " from package "
+ if (DEBUG_PERMISSIONS && p.info.group != null && p.group == null) {
+ Slog.i(TAG, "Permission " + p.info.name + " from package "
+ p.info.packageName + " in an unknown group " + p.info.group);
}
}
@@ -11021,12 +11025,14 @@
if (ps.pkg != null && ps.pkg.applicationInfo != null &&
!TextUtils.equals(adjustedAbi, ps.pkg.applicationInfo.primaryCpuAbi)) {
ps.pkg.applicationInfo.primaryCpuAbi = adjustedAbi;
- Slog.i(TAG, "Adjusting ABI for " + ps.name + " to " + adjustedAbi
- + " (requirer="
- + (requirer != null ? requirer.pkg : "null")
- + ", scannedPackage="
- + (scannedPackage != null ? scannedPackage : "null")
- + ")");
+ if (DEBUG_ABI_SELECTION) {
+ Slog.i(TAG, "Adjusting ABI for " + ps.name + " to " + adjustedAbi
+ + " (requirer="
+ + (requirer != null ? requirer.pkg : "null")
+ + ", scannedPackage="
+ + (scannedPackage != null ? scannedPackage : "null")
+ + ")");
+ }
try {
mInstaller.rmdex(ps.codePathString,
getDexCodeInstructionSet(getPreferredInstructionSet()));
@@ -11747,8 +11753,10 @@
if (bp == null || bp.packageSetting == null) {
if (packageOfInterest == null || packageOfInterest.equals(pkg.packageName)) {
- Slog.w(TAG, "Unknown permission " + name
- + " in package " + pkg.packageName);
+ if (DEBUG_PERMISSIONS) {
+ Slog.i(TAG, "Unknown permission " + name
+ + " in package " + pkg.packageName);
+ }
}
continue;
}
@@ -11756,14 +11764,18 @@
// Limit ephemeral apps to ephemeral allowed permissions.
if (pkg.applicationInfo.isInstantApp() && !bp.isInstant()) {
- Log.i(TAG, "Denying non-ephemeral permission " + bp.name + " for package "
- + pkg.packageName);
+ if (DEBUG_PERMISSIONS) {
+ Log.i(TAG, "Denying non-ephemeral permission " + bp.name + " for package "
+ + pkg.packageName);
+ }
continue;
}
if (bp.isRuntimeOnly() && !appSupportsRuntimePermissions) {
- Log.i(TAG, "Denying runtime-only permission " + bp.name + " for package "
- + pkg.packageName);
+ if (DEBUG_PERMISSIONS) {
+ Log.i(TAG, "Denying runtime-only permission " + bp.name + " for package "
+ + pkg.packageName);
+ }
continue;
}
@@ -11821,8 +11833,8 @@
} break;
}
- if (DEBUG_INSTALL) {
- Log.i(TAG, "Package " + pkg.packageName + " granting " + perm);
+ if (DEBUG_PERMISSIONS) {
+ Slog.i(TAG, "Granting permission " + perm + " to package " + pkg.packageName);
}
if (grant != GRANT_DENIED) {
@@ -11968,9 +11980,11 @@
default: {
if (packageOfInterest == null
|| packageOfInterest.equals(pkg.packageName)) {
- Slog.w(TAG, "Not granting permission " + perm
- + " to package " + pkg.packageName
- + " because it was previously installed without");
+ if (DEBUG_PERMISSIONS) {
+ Slog.i(TAG, "Not granting permission " + perm
+ + " to package " + pkg.packageName
+ + " because it was previously installed without");
+ }
}
} break;
}
@@ -11989,8 +12003,10 @@
} else if ((bp.protectionLevel&PermissionInfo.PROTECTION_FLAG_APPOP) == 0) {
// Don't print warning for app op permissions, since it is fine for them
// not to be granted, there is a UI for the user to decide.
- if (packageOfInterest == null || packageOfInterest.equals(pkg.packageName)) {
- Slog.w(TAG, "Not granting permission " + perm
+ if (DEBUG_PERMISSIONS
+ && (packageOfInterest == null
+ || packageOfInterest.equals(pkg.packageName))) {
+ Slog.i(TAG, "Not granting permission " + perm
+ " to package " + pkg.packageName
+ " (protectionLevel=" + bp.protectionLevel
+ " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags)
@@ -12359,10 +12375,12 @@
((applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0);
if (!privilegedApp) {
// non-privileged applications can never define a priority >0
- Slog.w(TAG, "Non-privileged app; cap priority to 0;"
- + " package: " + applicationInfo.packageName
- + " activity: " + intent.activity.className
- + " origPrio: " + intent.getPriority());
+ if (DEBUG_FILTERS) {
+ Slog.i(TAG, "Non-privileged app; cap priority to 0;"
+ + " package: " + applicationInfo.packageName
+ + " activity: " + intent.activity.className
+ + " origPrio: " + intent.getPriority());
+ }
intent.setPriority(0);
return;
}
@@ -12402,10 +12420,12 @@
// setup wizard gets whatever it wants
return;
}
- Slog.w(TAG, "Protected action; cap priority to 0;"
- + " package: " + intent.activity.info.packageName
- + " activity: " + intent.activity.className
- + " origPrio: " + intent.getPriority());
+ if (DEBUG_FILTERS) {
+ Slog.i(TAG, "Protected action; cap priority to 0;"
+ + " package: " + intent.activity.info.packageName
+ + " activity: " + intent.activity.className
+ + " origPrio: " + intent.getPriority());
+ }
intent.setPriority(0);
return;
}
@@ -13607,6 +13627,12 @@
int userId) {
final boolean isSystem = isSystemApp(pkgSetting) || isUpdatedSystemApp(pkgSetting);
sendPackageAddedForNewUsers(packageName, isSystem, pkgSetting.appId, userId);
+
+ // Send a session commit broadcast
+ final PackageInstaller.SessionInfo info = new PackageInstaller.SessionInfo();
+ info.installReason = pkgSetting.getInstallReason(userId);
+ info.appPackageName = packageName;
+ sendSessionCommitBroadcast(info, userId);
}
public void sendPackageAddedForNewUsers(String packageName, boolean isSystem, int appId, int... userIds) {
@@ -20122,11 +20148,27 @@
return getHomeActivitiesAsUser(allHomeCandidates, UserHandle.getCallingUserId());
}
+ public void sendSessionCommitBroadcast(PackageInstaller.SessionInfo sessionInfo, int userId) {
+ UserManagerService ums = UserManagerService.getInstance();
+ if (ums != null) {
+ final UserInfo parent = ums.getProfileParent(userId);
+ final int launcherUid = (parent != null) ? parent.id : userId;
+ final ComponentName launcherComponent = getDefaultHomeActivity(launcherUid);
+ if (launcherComponent != null) {
+ Intent launcherIntent = new Intent(PackageInstaller.ACTION_SESSION_COMMITTED)
+ .putExtra(PackageInstaller.EXTRA_SESSION, sessionInfo)
+ .putExtra(Intent.EXTRA_USER, UserHandle.of(userId))
+ .setPackage(launcherComponent.getPackageName());
+ mContext.sendBroadcastAsUser(launcherIntent, UserHandle.of(launcherUid));
+ }
+ }
+ }
+
/**
* Report the 'Home' activity which is currently set as "always use this one". If non is set
* then reports the most likely home activity or null if there are more than one.
*/
- public ComponentName getDefaultHomeActivity(int userId) {
+ private ComponentName getDefaultHomeActivity(int userId) {
List<ResolveInfo> allHomeCandidates = new ArrayList<>();
ComponentName cn = getHomeActivitiesAsUser(allHomeCandidates, userId);
if (cn != null) {
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index dd790a9..d64dc0e 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -115,8 +115,8 @@
mAnimationTick = () -> {
synchronized (mService.mWindowMap) {
mAnimationTickScheduled = false;
- animateLocked(mCurrentFrameTime);
}
+ animate(mCurrentFrameTime);
};
mAnimationFrameCallback = frameTimeNs -> {
synchronized (mService.mWindowMap) {
@@ -126,8 +126,8 @@
return;
}
mAnimationTickScheduled = true;
- mSfChoreographer.scheduleAtSfVsync(mAnimationTick);
}
+ mSfChoreographer.scheduleAtSfVsync(mAnimationTick);
};
}
@@ -151,142 +151,158 @@
mDisplayContentsAnimators.delete(displayId);
}
- /** Locked on mService.mWindowMap. */
- private void animateLocked(long frameTimeNs) {
- if (!mInitialized) {
- return;
- }
-
- mCurrentTime = frameTimeNs / TimeUtils.NANOS_PER_MS;
- mBulkUpdateParams = SET_ORIENTATION_CHANGE_COMPLETE;
- boolean wasAnimating = mAnimating;
- setAnimating(false);
- mAppWindowAnimating = false;
- if (DEBUG_WINDOW_TRACE) {
- Slog.i(TAG, "!!! animate: entry time=" + mCurrentTime);
- }
-
- if (SHOW_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION animateLocked");
- mService.openSurfaceTransaction();
- SurfaceControl.setAnimationTransaction();
+ /**
+ * DO NOT HOLD THE WINDOW MANAGER LOCK WHILE CALLING THIS METHOD. Reason: the method closes
+ * an animation transaction, that might be blocking until the next sf-vsync, so we want to make
+ * sure other threads can make progress if this happens.
+ */
+ private void animate(long frameTimeNs) {
+ boolean transactionOpen = false;
+ boolean wasAnimating = false;
try {
- final AccessibilityController accessibilityController =
- mService.mAccessibilityController;
- final int numDisplays = mDisplayContentsAnimators.size();
- for (int i = 0; i < numDisplays; i++) {
- final int displayId = mDisplayContentsAnimators.keyAt(i);
- final DisplayContent dc = mService.mRoot.getDisplayContentOrCreate(displayId);
- dc.stepAppWindowsAnimation(mCurrentTime);
- DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.valueAt(i);
+ synchronized (mService.mWindowMap) {
+ if (!mInitialized) {
+ return;
+ }
- final ScreenRotationAnimation screenRotationAnimation =
- displayAnimator.mScreenRotationAnimation;
- if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) {
- if (screenRotationAnimation.stepAnimationLocked(mCurrentTime)) {
- setAnimating(true);
- } else {
- mBulkUpdateParams |= SET_UPDATE_ROTATION;
- screenRotationAnimation.kill();
- displayAnimator.mScreenRotationAnimation = null;
+ mCurrentTime = frameTimeNs / TimeUtils.NANOS_PER_MS;
+ mBulkUpdateParams = SET_ORIENTATION_CHANGE_COMPLETE;
+ wasAnimating = mAnimating;
+ setAnimating(false);
+ mAppWindowAnimating = false;
+ if (DEBUG_WINDOW_TRACE) {
+ Slog.i(TAG, "!!! animate: entry time=" + mCurrentTime);
+ }
- //TODO (multidisplay): Accessibility supported only for the default display.
- if (accessibilityController != null && dc.isDefaultDisplay) {
- // We just finished rotation animation which means we did not announce
- // the rotation and waited for it to end, announce now.
- accessibilityController.onRotationChangedLocked(
- mService.getDefaultDisplayContentLocked());
+ if (SHOW_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION animate");
+ mService.openSurfaceTransaction();
+ transactionOpen = true;
+ SurfaceControl.setAnimationTransaction();
+
+ final AccessibilityController accessibilityController =
+ mService.mAccessibilityController;
+ final int numDisplays = mDisplayContentsAnimators.size();
+ for (int i = 0; i < numDisplays; i++) {
+ final int displayId = mDisplayContentsAnimators.keyAt(i);
+ final DisplayContent dc = mService.mRoot.getDisplayContentOrCreate(displayId);
+ dc.stepAppWindowsAnimation(mCurrentTime);
+ DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.valueAt(i);
+
+ final ScreenRotationAnimation screenRotationAnimation =
+ displayAnimator.mScreenRotationAnimation;
+ if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) {
+ if (screenRotationAnimation.stepAnimationLocked(mCurrentTime)) {
+ setAnimating(true);
+ } else {
+ mBulkUpdateParams |= SET_UPDATE_ROTATION;
+ screenRotationAnimation.kill();
+ displayAnimator.mScreenRotationAnimation = null;
+
+ //TODO (multidisplay): Accessibility supported only for the default
+ // display.
+ if (accessibilityController != null && dc.isDefaultDisplay) {
+ // We just finished rotation animation which means we did not
+ // announce the rotation and waited for it to end, announce now.
+ accessibilityController.onRotationChangedLocked(
+ mService.getDefaultDisplayContentLocked());
+ }
}
}
+
+ // Update animations of all applications, including those
+ // associated with exiting/removed apps
+ ++mAnimTransactionSequence;
+ dc.updateWindowsForAnimator(this);
+ dc.updateWallpaperForAnimator(this);
+ dc.prepareWindowSurfaces();
+ }
+
+ for (int i = 0; i < numDisplays; i++) {
+ final int displayId = mDisplayContentsAnimators.keyAt(i);
+ final DisplayContent dc = mService.mRoot.getDisplayContentOrCreate(displayId);
+
+ dc.checkAppWindowsReadyToShow();
+
+ final ScreenRotationAnimation screenRotationAnimation =
+ mDisplayContentsAnimators.valueAt(i).mScreenRotationAnimation;
+ if (screenRotationAnimation != null) {
+ screenRotationAnimation.updateSurfacesInTransaction();
+ }
+
+ orAnimating(dc.animateDimLayers());
+ orAnimating(dc.getDockedDividerController().animate(mCurrentTime));
+ //TODO (multidisplay): Magnification is supported only for the default display.
+ if (accessibilityController != null && dc.isDefaultDisplay) {
+ accessibilityController.drawMagnifiedRegionBorderIfNeededLocked();
+ }
}
- // Update animations of all applications, including those
- // associated with exiting/removed apps
- ++mAnimTransactionSequence;
- dc.updateWindowsForAnimator(this);
- dc.updateWallpaperForAnimator(this);
- dc.prepareWindowSurfaces();
- }
-
- for (int i = 0; i < numDisplays; i++) {
- final int displayId = mDisplayContentsAnimators.keyAt(i);
- final DisplayContent dc = mService.mRoot.getDisplayContentOrCreate(displayId);
-
- dc.checkAppWindowsReadyToShow();
-
- final ScreenRotationAnimation screenRotationAnimation =
- mDisplayContentsAnimators.valueAt(i).mScreenRotationAnimation;
- if (screenRotationAnimation != null) {
- screenRotationAnimation.updateSurfacesInTransaction();
+ if (mService.mDragState != null) {
+ mAnimating |= mService.mDragState.stepAnimationLocked(mCurrentTime);
}
- orAnimating(dc.animateDimLayers());
- orAnimating(dc.getDockedDividerController().animate(mCurrentTime));
- //TODO (multidisplay): Magnification is supported only for the default display.
- if (accessibilityController != null && dc.isDefaultDisplay) {
- accessibilityController.drawMagnifiedRegionBorderIfNeededLocked();
+ if (mAnimating) {
+ mService.scheduleAnimationLocked();
}
- }
- if (mService.mDragState != null) {
- mAnimating |= mService.mDragState.stepAnimationLocked(mCurrentTime);
- }
-
- if (mAnimating) {
- mService.scheduleAnimationLocked();
- }
-
- if (mService.mWatermark != null) {
- mService.mWatermark.drawIfNeeded();
+ if (mService.mWatermark != null) {
+ mService.mWatermark.drawIfNeeded();
+ }
}
} catch (RuntimeException e) {
Slog.wtf(TAG, "Unhandled exception in Window Manager", e);
} finally {
- mService.closeSurfaceTransaction();
- if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION animateLocked");
- }
-
- boolean hasPendingLayoutChanges = mService.mRoot.hasPendingLayoutChanges(this);
- boolean doRequest = false;
- if (mBulkUpdateParams != 0) {
- doRequest = mService.mRoot.copyAnimToLayoutParams();
- }
-
- if (hasPendingLayoutChanges || doRequest) {
- mWindowPlacerLocked.requestTraversal();
- }
-
- if (mAnimating && !wasAnimating) {
-
- // Usually app transitions but quite a load onto the system already (with all the things
- // happening in app), so pause task snapshot persisting to not increase the load.
- mService.mTaskSnapshotController.setPersisterPaused(true);
- if (Trace.isTagEnabled(Trace.TRACE_TAG_WINDOW_MANAGER)) {
- Trace.asyncTraceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "animating", 0);
+ if (transactionOpen) {
+ mService.closeSurfaceTransaction();
+ if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION animate");
}
}
- if (!mAnimating && wasAnimating) {
- mWindowPlacerLocked.requestTraversal();
- mService.mTaskSnapshotController.setPersisterPaused(false);
- if (Trace.isTagEnabled(Trace.TRACE_TAG_WINDOW_MANAGER)) {
- Trace.asyncTraceEnd(Trace.TRACE_TAG_WINDOW_MANAGER, "animating", 0);
+ synchronized (mService.mWindowMap) {
+ boolean hasPendingLayoutChanges = mService.mRoot.hasPendingLayoutChanges(this);
+ boolean doRequest = false;
+ if (mBulkUpdateParams != 0) {
+ doRequest = mService.mRoot.copyAnimToLayoutParams();
}
- }
- if (mRemoveReplacedWindows) {
- mService.mRoot.removeReplacedWindows();
- mRemoveReplacedWindows = false;
- }
+ if (hasPendingLayoutChanges || doRequest) {
+ mWindowPlacerLocked.requestTraversal();
+ }
- mService.stopUsingSavedSurfaceLocked();
- mService.destroyPreservedSurfaceLocked();
- mService.mWindowPlacerLocked.destroyPendingSurfaces();
+ if (mAnimating && !wasAnimating) {
- if (DEBUG_WINDOW_TRACE) {
- Slog.i(TAG, "!!! animate: exit mAnimating=" + mAnimating
- + " mBulkUpdateParams=" + Integer.toHexString(mBulkUpdateParams)
- + " mPendingLayoutChanges(DEFAULT_DISPLAY)="
- + Integer.toHexString(getPendingLayoutChanges(DEFAULT_DISPLAY)));
+ // Usually app transitions but quite a load onto the system already (with all the
+ // things happening in app), so pause task snapshot persisting to not increase the
+ // load.
+ mService.mTaskSnapshotController.setPersisterPaused(true);
+ if (Trace.isTagEnabled(Trace.TRACE_TAG_WINDOW_MANAGER)) {
+ Trace.asyncTraceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "animating", 0);
+ }
+ }
+
+ if (!mAnimating && wasAnimating) {
+ mWindowPlacerLocked.requestTraversal();
+ mService.mTaskSnapshotController.setPersisterPaused(false);
+ if (Trace.isTagEnabled(Trace.TRACE_TAG_WINDOW_MANAGER)) {
+ Trace.asyncTraceEnd(Trace.TRACE_TAG_WINDOW_MANAGER, "animating", 0);
+ }
+ }
+
+ if (mRemoveReplacedWindows) {
+ mService.mRoot.removeReplacedWindows();
+ mRemoveReplacedWindows = false;
+ }
+
+ mService.stopUsingSavedSurfaceLocked();
+ mService.destroyPreservedSurfaceLocked();
+ mService.mWindowPlacerLocked.destroyPendingSurfaces();
+
+ if (DEBUG_WINDOW_TRACE) {
+ Slog.i(TAG, "!!! animate: exit mAnimating=" + mAnimating
+ + " mBulkUpdateParams=" + Integer.toHexString(mBulkUpdateParams)
+ + " mPendingLayoutChanges(DEFAULT_DISPLAY)="
+ + Integer.toHexString(getPendingLayoutChanges(DEFAULT_DISPLAY)));
+ }
}
}
diff --git a/services/usb/Android.mk b/services/usb/Android.mk
index f6d212b..57bf57d 100644
--- a/services/usb/Android.mk
+++ b/services/usb/Android.mk
@@ -7,8 +7,9 @@
LOCAL_SRC_FILES += \
$(call all-java-files-under,java)
-LOCAL_JAVA_LIBRARIES := services.core
-LOCAL_STATIC_JAVA_LIBRARIES := android.hardware.usb-V1.0-java-static \
-android.hidl.manager-V1.0-java-static
+LOCAL_JAVA_LIBRARIES := services.core \
+android.hidl.manager-V1.0-java
+
+LOCAL_STATIC_JAVA_LIBRARIES := android.hardware.usb-V1.0-java
include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index eddcbda..0a67669 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -855,7 +855,7 @@
if (!mConnected) {
// restore defaults when USB is disconnected
Slog.i(TAG, "Disconnect, setting usb functions to null");
- setEnabledFunctions(null, true, false);
+ setEnabledFunctions(null, !mAdbEnabled, false);
}
updateUsbFunctions();
} else {
diff --git a/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java b/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java
index 5399bb9..840ae22 100644
--- a/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java
+++ b/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java
@@ -841,7 +841,7 @@
// Only one of device and accessory should be non-null.
private boolean packageMatchesLocked(ResolveInfo info, String metaDataName,
UsbDevice device, UsbAccessory accessory) {
- if (info.getComponentInfo().name.equals(FORWARD_INTENT_TO_MANAGED_PROFILE)) {
+ if (isForwardMatch(info)) {
return true;
}
@@ -902,6 +902,17 @@
}
/**
+ * If this match used to forward the intent to another profile?
+ *
+ * @param match The match
+ *
+ * @return {@code true} iff this is such a forward match
+ */
+ private boolean isForwardMatch(@NonNull ResolveInfo match) {
+ return match.getComponentInfo().name.equals(FORWARD_INTENT_TO_MANAGED_PROFILE);
+ }
+
+ /**
* Only return those matches with the highest priority.
*
* @param matches All matches, some might have lower priority
@@ -909,16 +920,23 @@
* @return The matches with the highest priority
*/
@NonNull
- private ArrayList<ResolveInfo> preferHighPriority(
- @NonNull ArrayList<ResolveInfo> matches) {
+ private ArrayList<ResolveInfo> preferHighPriority(@NonNull ArrayList<ResolveInfo> matches) {
SparseArray<ArrayList<ResolveInfo>> highestPriorityMatchesByUserId = new SparseArray<>();
SparseIntArray highestPriorityByUserId = new SparseIntArray();
+ ArrayList<ResolveInfo> forwardMatches = new ArrayList<>();
// Create list of highest priority matches per user in highestPriorityMatchesByUserId
int numMatches = matches.size();
for (int matchNum = 0; matchNum < numMatches; matchNum++) {
ResolveInfo match = matches.get(matchNum);
+ // Unnecessary forward matches are filtered out later, hence collect them all to add
+ // them below
+ if (isForwardMatch(match)) {
+ forwardMatches.add(match);
+ continue;
+ }
+
// If this a previously unknown user?
if (highestPriorityByUserId.indexOfKey(match.targetUserId) < 0) {
highestPriorityByUserId.put(match.targetUserId, Integer.MIN_VALUE);
@@ -940,9 +958,10 @@
}
}
- // Combine all users back together. This means that all matches have the same priority for a
- // user. Matches for different users might have different priority.
- ArrayList<ResolveInfo> combinedMatches = new ArrayList<>();
+ // Combine all users (+ forward matches) back together. This means that all non-forward
+ // matches have the same priority for a user. Matches for different users might have
+ // different priority.
+ ArrayList<ResolveInfo> combinedMatches = new ArrayList<>(forwardMatches);
int numMatchArrays = highestPriorityMatchesByUserId.size();
for (int matchArrayNum = 0; matchArrayNum < numMatchArrays; matchArrayNum++) {
combinedMatches.addAll(highestPriorityMatchesByUserId.valueAt(matchArrayNum));
@@ -951,6 +970,51 @@
return combinedMatches;
}
+ /**
+ * If there are no matches for a profile, remove the forward intent to this profile.
+ *
+ * @param rawMatches The matches that contain all forward intents
+ *
+ * @return The matches with the unnecessary forward intents removed
+ */
+ @NonNull private ArrayList<ResolveInfo> removeForwardIntentIfNotNeeded(
+ @NonNull ArrayList<ResolveInfo> rawMatches) {
+ final int numRawMatches = rawMatches.size();
+
+ // The raw matches contain the activities that can be started but also the intents to
+ // forward the intent to the other profile
+ int numParentActivityMatches = 0;
+ int numNonParentActivityMatches = 0;
+ for (int i = 0; i < numRawMatches; i++) {
+ final ResolveInfo rawMatch = rawMatches.get(i);
+ if (!isForwardMatch(rawMatch)) {
+ if (UserHandle.getUserHandleForUid(
+ rawMatch.activityInfo.applicationInfo.uid).equals(mParentUser)) {
+ numParentActivityMatches++;
+ } else {
+ numNonParentActivityMatches++;
+ }
+ }
+ }
+
+ // If only one profile has activity matches, we need to remove all switch intents
+ if (numParentActivityMatches == 0 || numNonParentActivityMatches == 0) {
+ ArrayList<ResolveInfo> matches = new ArrayList<>(
+ numParentActivityMatches + numNonParentActivityMatches);
+
+ for (int i = 0; i < numRawMatches; i++) {
+ ResolveInfo rawMatch = rawMatches.get(i);
+ if (!isForwardMatch(rawMatch)) {
+ matches.add(rawMatch);
+ }
+ }
+ return matches;
+
+ } else {
+ return rawMatches;
+ }
+ }
+
private final ArrayList<ResolveInfo> getDeviceMatchesLocked(UsbDevice device, Intent intent) {
ArrayList<ResolveInfo> matches = new ArrayList<ResolveInfo>();
List<ResolveInfo> resolveInfos = queryIntentActivitiesForAllProfiles(intent);
@@ -961,7 +1025,8 @@
matches.add(resolveInfo);
}
}
- return preferHighPriority(matches);
+
+ return removeForwardIntentIfNotNeeded(preferHighPriority(matches));
}
private final ArrayList<ResolveInfo> getAccessoryMatchesLocked(
@@ -975,7 +1040,8 @@
matches.add(resolveInfo);
}
}
- return preferHighPriority(matches);
+
+ return removeForwardIntentIfNotNeeded(preferHighPriority(matches));
}
public void deviceAttached(UsbDevice device) {
@@ -1067,34 +1133,16 @@
* Start the appropriate package when an device/accessory got attached.
*
* @param intent The intent to start the package
- * @param rawMatches The available resolutions of the intent
+ * @param matches The available resolutions of the intent
* @param defaultActivity The default activity for the device (if set)
* @param device The device if a device was attached
* @param accessory The accessory if a device was attached
*/
- private void resolveActivity(@NonNull Intent intent, @NonNull ArrayList<ResolveInfo> rawMatches,
+ private void resolveActivity(@NonNull Intent intent, @NonNull ArrayList<ResolveInfo> matches,
@Nullable ActivityInfo defaultActivity, @Nullable UsbDevice device,
@Nullable UsbAccessory accessory) {
- final int numRawMatches = rawMatches.size();
-
- // The raw matches contain the activities that can be started but also the intents to switch
- // between the profiles
- int numParentActivityMatches = 0;
- int numNonParentActivityMatches = 0;
- for (int i = 0; i < numRawMatches; i++) {
- final ResolveInfo rawMatch = rawMatches.get(i);
- if (!rawMatch.getComponentInfo().name.equals(FORWARD_INTENT_TO_MANAGED_PROFILE)) {
- if (UserHandle.getUserHandleForUid(
- rawMatch.activityInfo.applicationInfo.uid).equals(mParentUser)) {
- numParentActivityMatches++;
- } else {
- numNonParentActivityMatches++;
- }
- }
- }
-
// don't show the resolver activity if there are no choices available
- if (numParentActivityMatches + numNonParentActivityMatches == 0) {
+ if (matches.size() == 0) {
if (accessory != null) {
String uri = accessory.getUri();
if (uri != null && uri.length() > 0) {
@@ -1117,21 +1165,6 @@
return;
}
- // If only one profile has activity matches, we need to remove all switch intents
- ArrayList<ResolveInfo> matches;
- if (numParentActivityMatches == 0 || numNonParentActivityMatches == 0) {
- matches = new ArrayList<>(numParentActivityMatches + numNonParentActivityMatches);
-
- for (int i = 0; i < numRawMatches; i++) {
- ResolveInfo rawMatch = rawMatches.get(i);
- if (!rawMatch.getComponentInfo().name.equals(FORWARD_INTENT_TO_MANAGED_PROFILE)) {
- matches.add(rawMatch);
- }
- }
- } else {
- matches = rawMatches;
- }
-
if (defaultActivity != null) {
UsbUserSettingsManager defaultRIUserSettings = mSettingsManager.getSettingsForUser(
UserHandle.getUserId(defaultActivity.applicationInfo.uid));
@@ -1216,10 +1249,10 @@
if (matches.size() == 1) {
final ActivityInfo activityInfo = matches.get(0).activityInfo;
if (activityInfo != null) {
- // bypass dialog and launch the only matching activity
if (mDisablePermissionDialogs) {
return activityInfo;
}
+ // System apps are considered default unless there are other matches
if (activityInfo.applicationInfo != null
&& (activityInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM)
!= 0) {
diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java
index 2d3d79a..bcde519 100644
--- a/test-runner/src/android/test/mock/MockPackageManager.java
+++ b/test-runner/src/android/test/mock/MockPackageManager.java
@@ -986,6 +986,15 @@
* @hide
*/
@Override
+ public int installExistingPackage(String packageName, int installReason)
+ throws NameNotFoundException {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * @hide
+ */
+ @Override
public int installExistingPackageAsUser(String packageName, int userId)
throws NameNotFoundException {
throw new UnsupportedOperationException();
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java
index 764eeeb..1b5a54d 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java
@@ -621,6 +621,12 @@
}
@Override
+ public int installExistingPackage(String packageName, int installReason)
+ throws NameNotFoundException {
+ return 0;
+ }
+
+ @Override
public int installExistingPackageAsUser(String packageName, int userId)
throws NameNotFoundException {
return 0;