Merge "Check for null inputs in the ctor."
diff --git a/api/current.txt b/api/current.txt
index de54869..e2720f2 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -26087,7 +26087,7 @@
method public java.lang.String getSubscriptionType();
method public android.net.wifi.hotspot2.pps.UpdateParameter getSubscriptionUpdate();
method public java.util.Map<java.lang.String, byte[]> getTrustRootCertList();
- method public int getUpdateIdentififer();
+ method public int getUpdateIdentifier();
method public long getUsageLimitDataLimit();
method public long getUsageLimitStartTimeInMs();
method public long getUsageLimitTimeLimitInMinutes();
@@ -26129,7 +26129,7 @@
method public int describeContents();
method public java.security.cert.X509Certificate getCaCertificate();
method public android.net.wifi.hotspot2.pps.Credential.CertificateCredential getCertCredential();
- method public boolean getCheckAaaServerStatus();
+ method public boolean getCheckAaaServerCertStatus();
method public java.security.cert.X509Certificate[] getClientCertificateChain();
method public java.security.PrivateKey getClientPrivateKey();
method public long getCreationTimeInMs();
@@ -26210,7 +26210,7 @@
method public java.util.Map<java.lang.String, java.lang.Long> getHomeNetworkIds();
method public java.lang.String getIconUrl();
method public long[] getMatchAllOis();
- method public long[] getMatchAnysOis();
+ method public long[] getMatchAnyOis();
method public java.lang.String[] getOtherHomePartners();
method public long[] getRoamingConsortiumOis();
method public void setFqdn(java.lang.String);
@@ -26232,7 +26232,7 @@
method public int describeContents();
method public java.lang.String[] getExcludedSsidList();
method public int getMaximumBssLoadValue();
- method public long getMinHomeDownlinkBandWidht();
+ method public long getMinHomeDownlinkBandwidth();
method public long getMinHomeUplinkBandwidth();
method public long getMinRoamingDownlinkBandwidth();
method public long getMinRoamingUplinkBandwidth();
@@ -36758,6 +36758,7 @@
method public boolean onKeyUp(int, android.view.KeyEvent);
method public void onLockscreenShown();
method public void onLowMemory();
+ method public void onPrepareShow(android.os.Bundle, int);
method public void onRequestAbortVoice(android.service.voice.VoiceInteractionSession.AbortVoiceRequest);
method public void onRequestCommand(android.service.voice.VoiceInteractionSession.CommandRequest);
method public void onRequestCompleteVoice(android.service.voice.VoiceInteractionSession.CompleteVoiceRequest);
@@ -36771,6 +36772,7 @@
method public void setDisabledShowContext(int);
method public void setKeepAwake(boolean);
method public void setTheme(int);
+ method public void setUiEnabled(boolean);
method public void show(android.os.Bundle, int);
method public void startVoiceActivity(android.content.Intent);
field public static final int SHOW_SOURCE_ACTIVITY = 16; // 0x10
@@ -44754,7 +44756,7 @@
method public final void requestUnbufferedDispatch(android.view.MotionEvent);
method public static int resolveSize(int, int);
method public static int resolveSizeAndState(int, int, int);
- method public boolean restoreDefaultFocus(int);
+ method public boolean restoreDefaultFocus();
method public void restoreHierarchyState(android.util.SparseArray<android.os.Parcelable>);
method public void saveHierarchyState(android.util.SparseArray<android.os.Parcelable>);
method public void scheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable, long);
diff --git a/api/system-current.txt b/api/system-current.txt
index bdf06db..14120af 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -28797,7 +28797,7 @@
method public java.lang.String getSubscriptionType();
method public android.net.wifi.hotspot2.pps.UpdateParameter getSubscriptionUpdate();
method public java.util.Map<java.lang.String, byte[]> getTrustRootCertList();
- method public int getUpdateIdentififer();
+ method public int getUpdateIdentifier();
method public long getUsageLimitDataLimit();
method public long getUsageLimitStartTimeInMs();
method public long getUsageLimitTimeLimitInMinutes();
@@ -28839,7 +28839,7 @@
method public int describeContents();
method public java.security.cert.X509Certificate getCaCertificate();
method public android.net.wifi.hotspot2.pps.Credential.CertificateCredential getCertCredential();
- method public boolean getCheckAaaServerStatus();
+ method public boolean getCheckAaaServerCertStatus();
method public java.security.cert.X509Certificate[] getClientCertificateChain();
method public java.security.PrivateKey getClientPrivateKey();
method public long getCreationTimeInMs();
@@ -28920,7 +28920,7 @@
method public java.util.Map<java.lang.String, java.lang.Long> getHomeNetworkIds();
method public java.lang.String getIconUrl();
method public long[] getMatchAllOis();
- method public long[] getMatchAnysOis();
+ method public long[] getMatchAnyOis();
method public java.lang.String[] getOtherHomePartners();
method public long[] getRoamingConsortiumOis();
method public void setFqdn(java.lang.String);
@@ -28942,7 +28942,7 @@
method public int describeContents();
method public java.lang.String[] getExcludedSsidList();
method public int getMaximumBssLoadValue();
- method public long getMinHomeDownlinkBandWidht();
+ method public long getMinHomeDownlinkBandwidth();
method public long getMinHomeUplinkBandwidth();
method public long getMinRoamingDownlinkBandwidth();
method public long getMinRoamingUplinkBandwidth();
@@ -39856,6 +39856,7 @@
method public boolean onKeyUp(int, android.view.KeyEvent);
method public void onLockscreenShown();
method public void onLowMemory();
+ method public void onPrepareShow(android.os.Bundle, int);
method public void onRequestAbortVoice(android.service.voice.VoiceInteractionSession.AbortVoiceRequest);
method public void onRequestCommand(android.service.voice.VoiceInteractionSession.CommandRequest);
method public void onRequestCompleteVoice(android.service.voice.VoiceInteractionSession.CompleteVoiceRequest);
@@ -39869,6 +39870,7 @@
method public void setDisabledShowContext(int);
method public void setKeepAwake(boolean);
method public void setTheme(int);
+ method public void setUiEnabled(boolean);
method public void show(android.os.Bundle, int);
method public void startVoiceActivity(android.content.Intent);
field public static final int SHOW_SOURCE_ACTIVITY = 16; // 0x10
@@ -48170,7 +48172,7 @@
method public final void requestUnbufferedDispatch(android.view.MotionEvent);
method public static int resolveSize(int, int);
method public static int resolveSizeAndState(int, int, int);
- method public boolean restoreDefaultFocus(int);
+ method public boolean restoreDefaultFocus();
method public void restoreHierarchyState(android.util.SparseArray<android.os.Parcelable>);
method public void saveHierarchyState(android.util.SparseArray<android.os.Parcelable>);
method public void scheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable, long);
diff --git a/api/test-current.txt b/api/test-current.txt
index 0f6502b..4fb669a 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -26179,7 +26179,7 @@
method public java.lang.String getSubscriptionType();
method public android.net.wifi.hotspot2.pps.UpdateParameter getSubscriptionUpdate();
method public java.util.Map<java.lang.String, byte[]> getTrustRootCertList();
- method public int getUpdateIdentififer();
+ method public int getUpdateIdentifier();
method public long getUsageLimitDataLimit();
method public long getUsageLimitStartTimeInMs();
method public long getUsageLimitTimeLimitInMinutes();
@@ -26221,7 +26221,7 @@
method public int describeContents();
method public java.security.cert.X509Certificate getCaCertificate();
method public android.net.wifi.hotspot2.pps.Credential.CertificateCredential getCertCredential();
- method public boolean getCheckAaaServerStatus();
+ method public boolean getCheckAaaServerCertStatus();
method public java.security.cert.X509Certificate[] getClientCertificateChain();
method public java.security.PrivateKey getClientPrivateKey();
method public long getCreationTimeInMs();
@@ -26302,7 +26302,7 @@
method public java.util.Map<java.lang.String, java.lang.Long> getHomeNetworkIds();
method public java.lang.String getIconUrl();
method public long[] getMatchAllOis();
- method public long[] getMatchAnysOis();
+ method public long[] getMatchAnyOis();
method public java.lang.String[] getOtherHomePartners();
method public long[] getRoamingConsortiumOis();
method public void setFqdn(java.lang.String);
@@ -26324,7 +26324,7 @@
method public int describeContents();
method public java.lang.String[] getExcludedSsidList();
method public int getMaximumBssLoadValue();
- method public long getMinHomeDownlinkBandWidht();
+ method public long getMinHomeDownlinkBandwidth();
method public long getMinHomeUplinkBandwidth();
method public long getMinRoamingDownlinkBandwidth();
method public long getMinRoamingUplinkBandwidth();
@@ -36893,6 +36893,7 @@
method public boolean onKeyUp(int, android.view.KeyEvent);
method public void onLockscreenShown();
method public void onLowMemory();
+ method public void onPrepareShow(android.os.Bundle, int);
method public void onRequestAbortVoice(android.service.voice.VoiceInteractionSession.AbortVoiceRequest);
method public void onRequestCommand(android.service.voice.VoiceInteractionSession.CommandRequest);
method public void onRequestCompleteVoice(android.service.voice.VoiceInteractionSession.CompleteVoiceRequest);
@@ -36906,6 +36907,7 @@
method public void setDisabledShowContext(int);
method public void setKeepAwake(boolean);
method public void setTheme(int);
+ method public void setUiEnabled(boolean);
method public void show(android.os.Bundle, int);
method public void startVoiceActivity(android.content.Intent);
field public static final int SHOW_SOURCE_ACTIVITY = 16; // 0x10
@@ -45061,7 +45063,7 @@
method public final void requestUnbufferedDispatch(android.view.MotionEvent);
method public static int resolveSize(int, int);
method public static int resolveSizeAndState(int, int, int);
- method public boolean restoreDefaultFocus(int);
+ method public boolean restoreDefaultFocus();
method public void restoreHierarchyState(android.util.SparseArray<android.os.Parcelable>);
method public void saveHierarchyState(android.util.SparseArray<android.os.Parcelable>);
method public void scheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable, long);
diff --git a/cmds/telecom/src/com/android/commands/telecom/Telecom.java b/cmds/telecom/src/com/android/commands/telecom/Telecom.java
index 63f6c92..8e9b91d 100644
--- a/cmds/telecom/src/com/android/commands/telecom/Telecom.java
+++ b/cmds/telecom/src/com/android/commands/telecom/Telecom.java
@@ -20,7 +20,6 @@
import android.content.Context;
import android.net.Uri;
import android.os.IUserManager;
-import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
@@ -51,6 +50,7 @@
private static final String COMMAND_SET_DEFAULT_DIALER = "set-default-dialer";
private static final String COMMAND_GET_DEFAULT_DIALER = "get-default-dialer";
private static final String COMMAND_GET_SYSTEM_DIALER = "get-system-dialer";
+ private static final String COMMAND_WAIT_ON_HANDLERS = "wait-on-handlers";
private ComponentName mComponent;
private String mAccountId;
@@ -69,6 +69,7 @@
"usage: telecom set-default-dialer <PACKAGE>\n" +
"usage: telecom get-default-dialer\n" +
"usage: telecom get-system-dialer\n" +
+ "usage: telecom wait-on-handlers\n" +
"\n" +
"telecom set-phone-account-enabled: Enables the given phone account, if it has \n" +
" already been registered with Telecom.\n" +
@@ -80,7 +81,9 @@
"\n" +
"telecom get-default-dialer: Displays the current default dialer. \n" +
"\n" +
- "telecom get-system-dialer: Displays the current system dialer. \n"
+ "telecom get-system-dialer: Displays the current system dialer. \n" +
+ "\n" +
+ "telecom wait-on-handlers: Wait until all handlers finish their work. \n"
);
}
@@ -125,6 +128,9 @@
case COMMAND_GET_SYSTEM_DIALER:
runGetSystemDialer();
break;
+ case COMMAND_WAIT_ON_HANDLERS:
+ runWaitOnHandler();
+ break;
default:
throw new IllegalArgumentException ("unknown command '" + command + "'");
}
@@ -192,6 +198,10 @@
System.out.println(mTelecomService.getSystemDialerPackage());
}
+ private void runWaitOnHandler() throws RemoteException {
+
+ }
+
private PhoneAccountHandle getPhoneAccountHandleFromArgs() throws RemoteException{
final ComponentName component = parseComponentName(nextArgRequired());
final String accountId = nextArgRequired();
diff --git a/core/java/android/app/BackStackRecord.java b/core/java/android/app/BackStackRecord.java
index 66b2355..c88448a 100644
--- a/core/java/android/app/BackStackRecord.java
+++ b/core/java/android/app/BackStackRecord.java
@@ -813,8 +813,11 @@
/**
* Reverses the execution of the operations within this transaction. The Fragment states will
* only be modified if optimizations are not allowed.
+ *
+ * @param moveToState {@code true} if added fragments should be moved to their final state
+ * in unoptimized transactions
*/
- void executePopOps() {
+ void executePopOps(boolean moveToState) {
for (int opNum = mOps.size() - 1; opNum >= 0; opNum--) {
final Op op = mOps.get(opNum);
Fragment f = op.fragment;
@@ -860,7 +863,7 @@
mManager.moveFragmentToExpectedState(f);
}
}
- if (!mAllowOptimization) {
+ if (!mAllowOptimization && moveToState) {
mManager.moveToState(mManager.mCurState, true);
}
}
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index b7c0737..d32cf3c 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -2170,7 +2170,7 @@
if (isPop) {
record.executeOps();
} else {
- record.executePopOps();
+ record.executePopOps(false);
}
// move to the end
@@ -2280,7 +2280,10 @@
final boolean isPop = isRecordPop.get(i);
if (isPop) {
record.bumpBackStackNesting(-1);
- record.executePopOps();
+ // Only execute the add operations at the end of
+ // all transactions.
+ boolean moveToState = i == (endIndex - 1);
+ record.executePopOps(moveToState);
} else {
record.bumpBackStackNesting(1);
record.executeOps();
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index 58cd310..cc6f6e1 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -40,7 +40,7 @@
{
void cancelAllNotifications(String pkg, int userId);
- void clearData(String pkg, int uid);
+ void clearData(String pkg, int uid, boolean fromApp);
void enqueueToast(String pkg, ITransientNotification callback, int duration);
void cancelToast(String pkg, ITransientNotification callback);
void enqueueNotificationWithTag(String pkg, String opPkg, String tag, int id,
diff --git a/core/java/android/app/NotificationChannelGroup.java b/core/java/android/app/NotificationChannelGroup.java
index 68cac27..8854adc 100644
--- a/core/java/android/app/NotificationChannelGroup.java
+++ b/core/java/android/app/NotificationChannelGroup.java
@@ -170,6 +170,11 @@
}
@Override
+ public NotificationChannelGroup clone() {
+ return new NotificationChannelGroup(getId(), getName());
+ }
+
+ @Override
public int hashCode() {
int result = getId() != null ? getId().hashCode() : 0;
result = 31 * result + (getName() != null ? getName().hashCode() : 0);
diff --git a/core/java/android/net/INetworkScoreService.aidl b/core/java/android/net/INetworkScoreService.aidl
index 82432c7..9cc256e 100644
--- a/core/java/android/net/INetworkScoreService.aidl
+++ b/core/java/android/net/INetworkScoreService.aidl
@@ -18,6 +18,7 @@
import android.net.INetworkScoreCache;
import android.net.NetworkKey;
+import android.net.NetworkScorerAppManager;
import android.net.RecommendationRequest;
import android.net.RecommendationResult;
import android.net.ScoredNetwork;
@@ -130,4 +131,6 @@
*/
oneway void requestRecommendationAsync(in RecommendationRequest request,
in RemoteCallback remoteCallback);
+
+ NetworkScorerAppManager.NetworkScorerAppData getActiveScorer();
}
diff --git a/core/java/android/net/NetworkScoreManager.java b/core/java/android/net/NetworkScoreManager.java
index 57cf1a5..2875580 100644
--- a/core/java/android/net/NetworkScoreManager.java
+++ b/core/java/android/net/NetworkScoreManager.java
@@ -186,6 +186,20 @@
}
/**
+ * Returns metadata about the active scorer or <code>null</code> if there is no active scorer.
+ *
+ * @hide
+ */
+ @Nullable
+ public NetworkScorerAppData getActiveScorer() {
+ try {
+ return mService.getActiveScorer();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Update network scores.
*
* <p>This may be called at any time to re-score active networks. Scores will generally be
diff --git a/core/java/android/net/NetworkScorerAppManager.aidl b/core/java/android/net/NetworkScorerAppManager.aidl
new file mode 100644
index 0000000..d968343
--- /dev/null
+++ b/core/java/android/net/NetworkScorerAppManager.aidl
@@ -0,0 +1,19 @@
+/**
+ * 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 android.net;
+
+parcelable NetworkScorerAppManager.NetworkScorerAppData;
diff --git a/core/java/android/net/NetworkScorerAppManager.java b/core/java/android/net/NetworkScorerAppManager.java
index 9dcf4f4..f3cbb52 100644
--- a/core/java/android/net/NetworkScorerAppManager.java
+++ b/core/java/android/net/NetworkScorerAppManager.java
@@ -24,6 +24,8 @@
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
+import android.os.Parcel;
+import android.os.Parcelable;
import android.os.UserHandle;
import android.provider.Settings;
import android.text.TextUtils;
@@ -54,7 +56,7 @@
/**
* Holds metadata about a discovered network scorer/recommendation application.
*/
- public static class NetworkScorerAppData {
+ public static final class NetworkScorerAppData implements Parcelable {
/** UID of the scorer app. */
public final int packageUid;
private final ComponentName mRecommendationService;
@@ -64,6 +66,35 @@
this.mRecommendationService = recommendationServiceComp;
}
+ protected NetworkScorerAppData(Parcel in) {
+ packageUid = in.readInt();
+ mRecommendationService = ComponentName.readFromParcel(in);
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(packageUid);
+ ComponentName.writeToParcel(mRecommendationService, dest);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ public static final Creator<NetworkScorerAppData> CREATOR =
+ new Creator<NetworkScorerAppData>() {
+ @Override
+ public NetworkScorerAppData createFromParcel(Parcel in) {
+ return new NetworkScorerAppData(in);
+ }
+
+ @Override
+ public NetworkScorerAppData[] newArray(int size) {
+ return new NetworkScorerAppData[size];
+ }
+ };
+
public String getRecommendationServicePackageName() {
return mRecommendationService.getPackageName();
}
diff --git a/core/java/android/net/ScoredNetwork.java b/core/java/android/net/ScoredNetwork.java
index d396b50..ba0a8b5 100644
--- a/core/java/android/net/ScoredNetwork.java
+++ b/core/java/android/net/ScoredNetwork.java
@@ -106,7 +106,7 @@
* the Network Recommendation Provider.
*
* @see #ATTRIBUTES_KEY_HAS_CAPTIVE_PORTAL
- * @see #ATTRIBUTES_KEY_RANKING_SCORE_OFFSET_KEY
+ * @see #ATTRIBUTES_KEY_RANKING_SCORE_OFFSET
*/
@Nullable
public final Bundle attributes;
diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java
index 210ddb6..e05bd89 100644
--- a/core/java/android/os/Debug.java
+++ b/core/java/android/os/Debug.java
@@ -2219,11 +2219,13 @@
}
/**
- * Have the stack traces of the given native process dumped to the
- * specified file. Will be appended to the file.
+ * Append the stack traces of a given native process to a specified file.
+ * @param pid pid to dump.
+ * @param file path of file to append dump to.
+ * @param timeoutSecs time to wait in seconds, or 0 to wait forever.
* @hide
*/
- public static native void dumpNativeBacktraceToFile(int pid, String file);
+ public static native void dumpNativeBacktraceToFileTimeout(int pid, String file, int timeoutSecs);
/**
* Get description of unreachable native memory.
diff --git a/core/java/android/service/voice/VoiceInteractionSession.java b/core/java/android/service/voice/VoiceInteractionSession.java
index e9bbc2d..ca736e3 100644
--- a/core/java/android/service/voice/VoiceInteractionSession.java
+++ b/core/java/android/service/voice/VoiceInteractionSession.java
@@ -135,6 +135,7 @@
FrameLayout mContentFrame;
SoftInputWindow mWindow;
+ boolean mUiEnabled = true;
boolean mInitialized;
boolean mWindowAdded;
boolean mWindowVisible;
@@ -1001,35 +1002,40 @@
try {
mInShowWindow = true;
+ onPrepareShow(args, flags);
if (!mWindowVisible) {
- if (!mWindowAdded) {
- mWindowAdded = true;
- View v = onCreateContentView();
- if (v != null) {
- setContentView(v);
- }
- }
+ ensureWindowAdded();
}
onShow(args, flags);
if (!mWindowVisible) {
mWindowVisible = true;
- mWindow.show();
+ if (mUiEnabled) {
+ mWindow.show();
+ }
}
if (showCallback != null) {
- mRootView.invalidate();
- mRootView.getViewTreeObserver().addOnPreDrawListener(
- new ViewTreeObserver.OnPreDrawListener() {
- @Override
- public boolean onPreDraw() {
- mRootView.getViewTreeObserver().removeOnPreDrawListener(this);
- try {
- showCallback.onShown();
- } catch (RemoteException e) {
- Log.w(TAG, "Error calling onShown", e);
+ if (mUiEnabled) {
+ mRootView.invalidate();
+ mRootView.getViewTreeObserver().addOnPreDrawListener(
+ new ViewTreeObserver.OnPreDrawListener() {
+ @Override
+ public boolean onPreDraw() {
+ mRootView.getViewTreeObserver().removeOnPreDrawListener(this);
+ try {
+ showCallback.onShown();
+ } catch (RemoteException e) {
+ Log.w(TAG, "Error calling onShown", e);
+ }
+ return true;
}
- return true;
- }
- });
+ });
+ } else {
+ try {
+ showCallback.onShown();
+ } catch (RemoteException e) {
+ Log.w(TAG, "Error calling onShown", e);
+ }
+ }
}
} finally {
mWindowWasVisible = true;
@@ -1039,7 +1045,7 @@
void doHide() {
if (mWindowVisible) {
- mWindow.hide();
+ ensureWindowHidden();
mWindowVisible = false;
onHide();
}
@@ -1058,19 +1064,56 @@
}
}
- void initViews() {
+ void ensureWindowCreated() {
+ if (mInitialized) {
+ return;
+ }
+
+ if (!mUiEnabled) {
+ throw new IllegalStateException("setUiEnabled is false");
+ }
+
mInitialized = true;
+ mInflater = (LayoutInflater)mContext.getSystemService(
+ Context.LAYOUT_INFLATER_SERVICE);
+ mWindow = new SoftInputWindow(mContext, "VoiceInteractionSession", mTheme,
+ mCallbacks, this, mDispatcherState,
+ WindowManager.LayoutParams.TYPE_VOICE_INTERACTION, Gravity.BOTTOM, true);
+ mWindow.getWindow().addFlags(
+ WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED |
+ WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN |
+ WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR);
mThemeAttrs = mContext.obtainStyledAttributes(android.R.styleable.VoiceInteractionSession);
mRootView = mInflater.inflate(
com.android.internal.R.layout.voice_interaction_session, null);
mRootView.setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
- | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
+ | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
mWindow.setContentView(mRootView);
mRootView.getViewTreeObserver().addOnComputeInternalInsetsListener(mInsetsComputer);
mContentFrame = (FrameLayout)mRootView.findViewById(android.R.id.content);
+
+ mWindow.getWindow().setLayout(MATCH_PARENT, MATCH_PARENT);
+ mWindow.setToken(mToken);
+ }
+
+ void ensureWindowAdded() {
+ if (mUiEnabled && !mWindowAdded) {
+ mWindowAdded = true;
+ ensureWindowCreated();
+ View v = onCreateContentView();
+ if (v != null) {
+ setContentView(v);
+ }
+ }
+ }
+
+ void ensureWindowHidden() {
+ if (mWindow != null) {
+ mWindow.hide();
+ }
}
/**
@@ -1151,6 +1194,24 @@
}
/**
+ * Control whether the UI layer for this session is enabled. It is enabled by default.
+ * If set to false, you will not be able to provide a UI through {@link #onCreateContentView()}.
+ */
+ public void setUiEnabled(boolean enabled) {
+ if (mUiEnabled != enabled) {
+ mUiEnabled = enabled;
+ if (mWindowVisible) {
+ if (enabled) {
+ ensureWindowAdded();
+ mWindow.show();
+ } else {
+ ensureWindowHidden();
+ }
+ }
+ }
+ }
+
+ /**
* You can call this to customize the theme used by your IME's window.
* This must be set before {@link #onCreate}, so you
* will typically call it in your constructor with the resource ID
@@ -1242,6 +1303,7 @@
* Convenience for inflating views.
*/
public LayoutInflater getLayoutInflater() {
+ ensureWindowCreated();
return mInflater;
}
@@ -1249,6 +1311,7 @@
* Retrieve the window being used to show the session's UI.
*/
public Dialog getWindow() {
+ ensureWindowCreated();
return mWindow;
}
@@ -1278,18 +1341,17 @@
private void doOnCreate() {
mTheme = mTheme != 0 ? mTheme
: com.android.internal.R.style.Theme_DeviceDefault_VoiceInteractionSession;
- mInflater = (LayoutInflater)mContext.getSystemService(
- Context.LAYOUT_INFLATER_SERVICE);
- mWindow = new SoftInputWindow(mContext, "VoiceInteractionSession", mTheme,
- mCallbacks, this, mDispatcherState,
- WindowManager.LayoutParams.TYPE_VOICE_INTERACTION, Gravity.BOTTOM, true);
- mWindow.getWindow().addFlags(
- WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED |
- WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN |
- WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR);
- initViews();
- mWindow.getWindow().setLayout(MATCH_PARENT, MATCH_PARENT);
- mWindow.setToken(mToken);
+ }
+
+ /**
+ * Called prior to {@link #onShow} before any UI setup has occurred. Not generally useful.
+ *
+ * @param args The arguments that were supplied to
+ * {@link VoiceInteractionService#showSession VoiceInteractionService.showSession}.
+ * @param showFlags The show flags originally provided to
+ * {@link VoiceInteractionService#showSession VoiceInteractionService.showSession}.
+ */
+ public void onPrepareShow(Bundle args, int showFlags) {
}
/**
@@ -1327,6 +1389,7 @@
}
public void setContentView(View view) {
+ ensureWindowCreated();
mContentFrame.removeAllViews();
mContentFrame.addView(view, new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
@@ -1623,7 +1686,8 @@
public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
writer.print(prefix); writer.print("mToken="); writer.println(mToken);
writer.print(prefix); writer.print("mTheme=#"); writer.println(Integer.toHexString(mTheme));
- writer.print(prefix); writer.print("mInitialized="); writer.println(mInitialized);
+ writer.print(prefix); writer.print("mUiEnabled="); writer.println(mUiEnabled);
+ writer.print(" mInitialized="); writer.println(mInitialized);
writer.print(prefix); writer.print("mWindowAdded="); writer.print(mWindowAdded);
writer.print(" mWindowVisible="); writer.println(mWindowVisible);
writer.print(prefix); writer.print("mWindowWasVisible="); writer.print(mWindowWasVisible);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 039237a..b06c3fd 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -6125,9 +6125,7 @@
if (mParent != null) {
mParent.requestChildFocus(this, this);
- if (mParent instanceof ViewGroup) {
- ((ViewGroup) mParent).setDefaultFocus(this);
- }
+ setFocusedInCluster();
}
if (mAttachInfo != null) {
@@ -9245,6 +9243,19 @@
}
/**
+ * Sets this View as the one which receives focus the next time cluster navigation jumps
+ * to the cluster containing this View. This does NOT change focus even if the cluster
+ * containing this view is current.
+ *
+ * @hide
+ */
+ public void setFocusedInCluster() {
+ if (mParent instanceof ViewGroup) {
+ ((ViewGroup) mParent).setFocusInCluster(this);
+ }
+ }
+
+ /**
* Returns whether this View should receive focus when the focus is restored for the view
* hierarchy containing this view.
* <p>
@@ -9290,7 +9301,7 @@
if (isFocusedByDefault) {
((ViewGroup) mParent).setDefaultFocus(this);
} else {
- ((ViewGroup) mParent).cleanDefaultFocus(this);
+ ((ViewGroup) mParent).clearDefaultFocus(this);
}
}
}
@@ -9670,15 +9681,27 @@
}
/**
+ * Public for testing. This will request focus for whichever View was last focused within this
+ * cluster before a focus-jump out of it.
+ *
+ * @hide
+ */
+ public boolean restoreFocusInCluster(@FocusRealDirection int direction) {
+ // Prioritize focusableByDefault over algorithmic focus selection.
+ if (restoreDefaultFocus()) {
+ return true;
+ }
+ return requestFocus(direction);
+ }
+
+ /**
* Gives focus to the default-focus view in the view hierarchy that has this view as a root.
* If the default-focus view cannot be found, falls back to calling {@link #requestFocus(int)}.
- * Nested keyboard navigation clusters are excluded from the hierarchy.
*
- * @param direction The direction of the focus
* @return Whether this view or one of its descendants actually took focus
*/
- public boolean restoreDefaultFocus(@FocusDirection int direction) {
- return requestFocus(direction);
+ public boolean restoreDefaultFocus() {
+ return requestFocus(View.FOCUS_DOWN);
}
/**
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index af095cf..fd3ff82 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -141,6 +141,8 @@
// The view contained within this ViewGroup (excluding nested keyboard navigation clusters)
// that is or contains a default-focus view.
private View mDefaultFocus;
+ // The last child of this ViewGroup which held focus within the current cluster
+ private View mFocusedInCluster;
/**
* A Transformation used when drawing children, to
@@ -724,7 +726,7 @@
if (mFocused != null) {
mFocused.unFocus(this);
mFocused = null;
- mDefaultFocus = null;
+ mFocusedInCluster = null;
}
super.handleFocusGainInternal(direction, previouslyFocusedRect);
}
@@ -754,14 +756,9 @@
}
}
- /**
- * Sets the specified child view as the default focus for this view and all its ancestors.
- * If the view is inside a keyboard navigation cluster, stops at the root of the cluster since
- * the cluster forms a separate keyboard navigation hierarchy from the default focus point of
- * view.
- */
void setDefaultFocus(View child) {
- if (child.isKeyboardNavigationCluster()) {
+ // Stop at any higher view which is explicitly focused-by-default
+ if (mDefaultFocus != null && mDefaultFocus.isFocusedByDefault()) {
return;
}
@@ -773,10 +770,56 @@
}
/**
- * Destroys the default focus chain.
+ * Clears the default-focus chain from {@param child} up to the first parent which has another
+ * default-focusable branch below it or until there is no default-focus chain.
+ *
+ * @param child
*/
- void cleanDefaultFocus(View child) {
- if (mDefaultFocus != child) {
+ void clearDefaultFocus(View child) {
+ // Stop at any higher view which is explicitly focused-by-default
+ if (mDefaultFocus != child && mDefaultFocus != null
+ && mDefaultFocus.isFocusedByDefault()) {
+ return;
+ }
+
+ mDefaultFocus = null;
+
+ // Search child siblings for default focusables.
+ for (int i = 0; i < mChildrenCount; ++i) {
+ View sibling = mChildren[i];
+ if (sibling.isFocusedByDefault()) {
+ mDefaultFocus = sibling;
+ return;
+ } else if (mDefaultFocus == null && sibling.hasDefaultFocus()) {
+ mDefaultFocus = sibling;
+ }
+ }
+
+ if (mParent instanceof ViewGroup) {
+ ((ViewGroup) mParent).clearDefaultFocus(this);
+ }
+ }
+
+ @Override
+ boolean hasDefaultFocus() {
+ return mDefaultFocus != null || super.hasDefaultFocus();
+ }
+
+ void setFocusInCluster(View child) {
+ // Stop at the root of the cluster
+ if (child.isKeyboardNavigationCluster()) {
+ return;
+ }
+
+ mFocusedInCluster = child;
+
+ if (mParent instanceof ViewGroup) {
+ ((ViewGroup) mParent).setFocusInCluster(this);
+ }
+ }
+
+ void clearFocusInCluster(View child) {
+ if (mFocusedInCluster != child) {
return;
}
@@ -784,19 +827,14 @@
return;
}
- mDefaultFocus = null;
+ mFocusedInCluster = null;
if (mParent instanceof ViewGroup) {
- ((ViewGroup) mParent).cleanDefaultFocus(this);
+ ((ViewGroup) mParent).clearFocusInCluster(this);
}
}
@Override
- boolean hasDefaultFocus() {
- return mDefaultFocus != null || super.hasDefaultFocus();
- }
-
- @Override
public void focusableViewAvailable(View v) {
if (mParent != null
// shortcut: don't report a new focusable view if we block our descendants from
@@ -3115,14 +3153,28 @@
}
@Override
- public boolean restoreDefaultFocus(@FocusDirection int direction) {
- if (mDefaultFocus != null && !mDefaultFocus.isKeyboardNavigationCluster()
+ public boolean restoreDefaultFocus() {
+ if (mDefaultFocus != null
&& getDescendantFocusability() != FOCUS_BLOCK_DESCENDANTS
&& (mDefaultFocus.mViewFlags & VISIBILITY_MASK) == VISIBLE
- && mDefaultFocus.restoreDefaultFocus(direction)) {
+ && mDefaultFocus.restoreDefaultFocus()) {
return true;
}
- return super.restoreDefaultFocus(direction);
+ return super.restoreDefaultFocus();
+ }
+
+ /**
+ * @hide
+ */
+ @Override
+ public boolean restoreFocusInCluster(@FocusRealDirection int direction) {
+ if (mFocusedInCluster != null && !mFocusedInCluster.isKeyboardNavigationCluster()
+ && getDescendantFocusability() != FOCUS_BLOCK_DESCENDANTS
+ && (mFocusedInCluster.mViewFlags & VISIBILITY_MASK) == VISIBLE
+ && mFocusedInCluster.restoreFocusInCluster(direction)) {
+ return true;
+ }
+ return super.restoreFocusInCluster(direction);
}
/**
@@ -5004,8 +5056,8 @@
view.unFocus(null);
clearChildFocus = true;
}
- if (view == mDefaultFocus) {
- mDefaultFocus = null;
+ if (view == mFocusedInCluster) {
+ clearFocusInCluster(view);
}
view.clearAccessibilityFocus();
@@ -5028,6 +5080,9 @@
removeFromArray(index);
+ if (view == mDefaultFocus) {
+ clearDefaultFocus(view);
+ }
if (clearChildFocus) {
clearChildFocus(view);
if (!rootViewRequestFocus()) {
@@ -5103,6 +5158,7 @@
final View focused = mFocused;
final boolean detach = mAttachInfo != null;
boolean clearChildFocus = false;
+ View clearDefaultFocus = null;
final View[] children = mChildren;
@@ -5118,7 +5174,10 @@
clearChildFocus = true;
}
if (view == mDefaultFocus) {
- mDefaultFocus = null;
+ clearDefaultFocus = view;
+ }
+ if (view == mFocusedInCluster) {
+ clearFocusInCluster(view);
}
view.clearAccessibilityFocus();
@@ -5144,6 +5203,9 @@
removeFromArray(start, count);
+ if (clearDefaultFocus != null) {
+ clearDefaultFocus(clearDefaultFocus);
+ }
if (clearChildFocus) {
clearChildFocus(focused);
if (!rootViewRequestFocus()) {
@@ -5193,7 +5255,6 @@
boolean clearChildFocus = false;
needGlobalAttributesUpdate(false);
- mDefaultFocus = null;
for (int i = count - 1; i >= 0; i--) {
final View view = children[i];
@@ -5229,6 +5290,9 @@
children[i] = null;
}
+ if (mDefaultFocus != null) {
+ clearDefaultFocus(mDefaultFocus);
+ }
if (clearChildFocus) {
clearChildFocus(focused);
if (!rootViewRequestFocus()) {
@@ -5266,7 +5330,10 @@
child.clearFocus();
}
if (child == mDefaultFocus) {
- mDefaultFocus = null;
+ clearDefaultFocus(child);
+ }
+ if (child == mFocusedInCluster) {
+ clearFocusInCluster(child);
}
child.clearAccessibilityFocus();
@@ -6251,6 +6318,12 @@
Log.d(VIEW_LOG_TAG, output);
mDefaultFocus.debug(depth + 1);
}
+ if (mFocusedInCluster != null) {
+ output = debugIndent(depth);
+ output += "mFocusedInCluster";
+ Log.d(VIEW_LOG_TAG, output);
+ mFocusedInCluster.debug(depth + 1);
+ }
if (mChildrenCount != 0) {
output = debugIndent(depth);
output += "{";
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 9e8dda8..cb29053 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -2162,7 +2162,7 @@
+ mView.hasFocus());
if (mView != null) {
if (!mView.hasFocus()) {
- mView.restoreDefaultFocus(View.FOCUS_FORWARD);
+ mView.restoreDefaultFocus();
if (DEBUG_INPUT_RESIZE) Log.v(mTag, "First: requested focused view="
+ mView.findFocus());
} else {
@@ -4441,7 +4441,14 @@
? focused.keyboardNavigationClusterSearch(null, direction)
: keyboardNavigationClusterSearch(null, direction);
- if (cluster != null && cluster.restoreDefaultFocus(View.FOCUS_DOWN)) {
+ // Since requestFocus only takes "real" focus directions (and therefore also
+ // restoreFocusInCluster), convert forward/backward focus into FOCUS_DOWN.
+ int realDirection = direction;
+ if (direction == View.FOCUS_FORWARD || direction == View.FOCUS_BACKWARD) {
+ realDirection = View.FOCUS_DOWN;
+ }
+
+ if (cluster != null && cluster.restoreFocusInCluster(realDirection)) {
return true;
}
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 8cb2d23..45b5570 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -149,10 +149,10 @@
private static final int MENU_ITEM_ORDER_ASSIST = 1;
private static final int MENU_ITEM_ORDER_UNDO = 2;
private static final int MENU_ITEM_ORDER_REDO = 3;
- private static final int MENU_ITEM_ORDER_SHARE = 4;
- private static final int MENU_ITEM_ORDER_CUT = 5;
- private static final int MENU_ITEM_ORDER_COPY = 6;
- private static final int MENU_ITEM_ORDER_PASTE = 7;
+ private static final int MENU_ITEM_ORDER_CUT = 4;
+ private static final int MENU_ITEM_ORDER_COPY = 5;
+ private static final int MENU_ITEM_ORDER_PASTE = 6;
+ private static final int MENU_ITEM_ORDER_SHARE = 7;
private static final int MENU_ITEM_ORDER_PASTE_AS_PLAIN_TEXT = 8;
private static final int MENU_ITEM_ORDER_SELECT_ALL = 9;
private static final int MENU_ITEM_ORDER_REPLACE = 10;
@@ -3876,7 +3876,7 @@
final Intent intent = textClassificationResult.getIntent();
if ((icon != null || !TextUtils.isEmpty(label))
&& (onClickListener != null || intent != null)) {
- menu.add(Menu.NONE, TextView.ID_ASSIST, MENU_ITEM_ORDER_ASSIST, label)
+ menu.add(TextView.ID_ASSIST, TextView.ID_ASSIST, MENU_ITEM_ORDER_ASSIST, label)
.setIcon(icon)
.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
}
diff --git a/core/java/com/android/internal/widget/FloatingToolbar.java b/core/java/com/android/internal/widget/FloatingToolbar.java
index 58e694a..854d013 100644
--- a/core/java/com/android/internal/widget/FloatingToolbar.java
+++ b/core/java/com/android/internal/widget/FloatingToolbar.java
@@ -32,6 +32,7 @@
import android.graphics.drawable.Drawable;
import android.text.TextUtils;
import android.util.Size;
+import android.util.TypedValue;
import android.view.ContextThemeWrapper;
import android.view.Gravity;
import android.view.LayoutInflater;
@@ -1113,6 +1114,7 @@
mMainPanel.removeAllViews();
mMainPanel.setPaddingRelative(0, 0, 0, 0);
+ int lastGroupId = -1;
boolean isFirstItem = true;
while (!remainingMenuItems.isEmpty()) {
final MenuItem menuItem = remainingMenuItems.peek();
@@ -1125,11 +1127,11 @@
menuItemButton.getPaddingTop(),
menuItemButton.getPaddingEnd(),
menuItemButton.getPaddingBottom());
- isFirstItem = false;
}
// Adding additional end padding for the last button to even out button spacing.
- if (remainingMenuItems.size() == 1) {
+ boolean isLastItem = remainingMenuItems.size() == 1;
+ if (isLastItem) {
menuItemButton.setPaddingRelative(
menuItemButton.getPaddingStart(),
menuItemButton.getPaddingTop(),
@@ -1138,25 +1140,64 @@
}
menuItemButton.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
- int menuItemButtonWidth = Math.min(menuItemButton.getMeasuredWidth(), toolbarWidth);
+ final int menuItemButtonWidth = Math.min(menuItemButton.getMeasuredWidth(), toolbarWidth);
+
+ final boolean isNewGroup = !isFirstItem && lastGroupId != menuItem.getGroupId();
+ final int extraPadding = isNewGroup ? menuItemButton.getPaddingEnd() * 2 : 0;
+
// Check if we can fit an item while reserving space for the overflowButton.
boolean canFitWithOverflow =
- menuItemButtonWidth <= availableWidth - mOverflowButtonSize.getWidth();
+ menuItemButtonWidth <=
+ availableWidth - mOverflowButtonSize.getWidth() - extraPadding;
boolean canFitNoOverflow =
- remainingMenuItems.size() == 1 && menuItemButtonWidth <= availableWidth;
+ isLastItem && menuItemButtonWidth <= availableWidth - extraPadding;
if (canFitWithOverflow || canFitNoOverflow) {
+ if (isNewGroup) {
+ final View border = createBorder(mContext);
+ final int borderWidth = border.getLayoutParams().width;
+
+ // Add extra padding to the end of the previous button.
+ // Half of the extra padding (less borderWidth) goes to the previous button.
+ View previousButton = mMainPanel.getChildAt(mMainPanel.getChildCount() - 1);
+ final int prevPaddingEnd = previousButton.getPaddingEnd()
+ + extraPadding / 2 - borderWidth;
+ previousButton.setPaddingRelative(
+ previousButton.getPaddingStart(),
+ previousButton.getPaddingTop(),
+ prevPaddingEnd,
+ previousButton.getPaddingBottom());
+ final ViewGroup.LayoutParams prevParams = previousButton.getLayoutParams();
+ prevParams.width += extraPadding / 2 - borderWidth;
+ previousButton.setLayoutParams(prevParams);
+
+ // Add extra padding to the start of this button.
+ // Other half of the extra padding goes to this button.
+ final int paddingStart = menuItemButton.getPaddingStart()
+ + extraPadding / 2;
+ menuItemButton.setPaddingRelative(
+ paddingStart,
+ menuItemButton.getPaddingTop(),
+ menuItemButton.getPaddingEnd(),
+ menuItemButton.getPaddingBottom());
+
+ // Include a border.
+ mMainPanel.addView(border);
+ }
+
setButtonTagAndClickListener(menuItemButton, menuItem);
mMainPanel.addView(menuItemButton);
- ViewGroup.LayoutParams params = menuItemButton.getLayoutParams();
- params.width = menuItemButtonWidth;
+ final ViewGroup.LayoutParams params = menuItemButton.getLayoutParams();
+ params.width = menuItemButtonWidth + extraPadding / 2;
menuItemButton.setLayoutParams(params);
- availableWidth -= menuItemButtonWidth;
+ availableWidth -= menuItemButtonWidth + extraPadding;
remainingMenuItems.pop();
} else {
// Reserve space for overflowButton.
mMainPanel.setPaddingRelative(0, 0, mOverflowButtonSize.getWidth(), 0);
break;
}
+ lastGroupId = menuItem.getGroupId();
+ isFirstItem = false;
}
mMainPanelSize = measure(mMainPanel);
return remainingMenuItems;
@@ -1688,6 +1729,23 @@
return popupWindow;
}
+ private static View createBorder(Context context) {
+ // TODO: Inflate this instead.
+ View border = new View(context);
+ int _1dp = (int) TypedValue.applyDimension(
+ TypedValue.COMPLEX_UNIT_DIP, 1, context.getResources().getDisplayMetrics());
+ LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
+ _1dp, ViewGroup.LayoutParams.MATCH_PARENT);
+ params.setMarginsRelative(0, _1dp * 10, 0, _1dp * 10);
+ border.setLayoutParams(params);
+ border.setBackgroundColor(Color.parseColor("#9E9E9E"));
+ border.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
+ border.setEnabled(false);
+ border.setFocusable(false);
+ border.setContentDescription(null);
+ return border;
+ }
+
/**
* Creates an "appear" animation for the specified view.
*
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index be3a87b..eaf9e91 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -1006,9 +1006,8 @@
ALOGD("Native heap dump complete.\n");
}
-
-static void android_os_Debug_dumpNativeBacktraceToFile(JNIEnv* env, jobject clazz,
- jint pid, jstring fileName)
+static void android_os_Debug_dumpNativeBacktraceToFileTimeout(JNIEnv* env, jobject clazz,
+ jint pid, jstring fileName, jint timeoutSecs)
{
if (fileName == NULL) {
jniThrowNullPointerException(env, "file == null");
@@ -1031,7 +1030,7 @@
if (lseek(fd, 0, SEEK_END) < 0) {
fprintf(stderr, "lseek: %s\n", strerror(errno));
} else {
- dump_backtrace_to_file(pid, fd);
+ dump_backtrace_to_file_timeout(pid, fd, timeoutSecs);
}
close(fd);
@@ -1077,8 +1076,8 @@
(void*)android_os_Debug_getProxyObjectCount },
{ "getBinderDeathObjectCount", "()I",
(void*)android_os_Debug_getDeathObjectCount },
- { "dumpNativeBacktraceToFile", "(ILjava/lang/String;)V",
- (void*)android_os_Debug_dumpNativeBacktraceToFile },
+ { "dumpNativeBacktraceToFileTimeout", "(ILjava/lang/String;I)V",
+ (void*)android_os_Debug_dumpNativeBacktraceToFileTimeout },
{ "getUnreachableMemory", "(IZ)Ljava/lang/String;",
(void*)android_os_Debug_getUnreachableMemory },
};
diff --git a/core/jni/android_os_GraphicsEnvironment.cpp b/core/jni/android_os_GraphicsEnvironment.cpp
index 905a85a..399dec8 100644
--- a/core/jni/android_os_GraphicsEnvironment.cpp
+++ b/core/jni/android_os_GraphicsEnvironment.cpp
@@ -16,7 +16,7 @@
#define LOG_TAG "GraphicsEnvironment"
-#include <gui/GraphicsEnv.h>
+#include <ui/GraphicsEnv.h>
#include <nativehelper/ScopedUtfChars.h>
#include "core_jni_helpers.h"
diff --git a/core/jni/android_os_seccomp.cpp b/core/jni/android_os_seccomp.cpp
index 02c0c62..3f021ae 100644
--- a/core/jni/android_os_seccomp.cpp
+++ b/core/jni/android_os_seccomp.cpp
@@ -216,6 +216,9 @@
AllowSyscall(f, 8); // __NR_creat
AllowSyscall(f, 10); // __NR_unlink
+ // b/35059702
+ AllowSyscall(f, 196); // __NR_lstat64
+
Trap(f);
return install_filter(f);
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index de5fc95..640e74d 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -461,12 +461,12 @@
<dimen name="floating_toolbar_height">48dp</dimen>
<dimen name="floating_toolbar_menu_image_button_width">56dp</dimen>
<dimen name="floating_toolbar_menu_image_button_vertical_padding">12dp</dimen>
- <dimen name="floating_toolbar_menu_button_side_padding">16dp</dimen>
+ <dimen name="floating_toolbar_menu_button_side_padding">11dp</dimen>
<dimen name="floating_toolbar_overflow_image_button_width">60dp</dimen>
<dimen name="floating_toolbar_overflow_side_padding">18dp</dimen>
<dimen name="floating_toolbar_text_size">14sp</dimen>
<dimen name="floating_toolbar_menu_button_minimum_width">48dp</dimen>
- <dimen name="floating_toolbar_preferred_width">328dp</dimen>
+ <dimen name="floating_toolbar_preferred_width">400dp</dimen>
<dimen name="floating_toolbar_minimum_overflow_height">96dp</dimen>
<dimen name="floating_toolbar_maximum_overflow_height">192dp</dimen>
<dimen name="floating_toolbar_horizontal_margin">16dp</dimen>
diff --git a/packages/SettingsLib/res/values/dimens.xml b/packages/SettingsLib/res/values/dimens.xml
index b72bcc7..aa36617 100644
--- a/packages/SettingsLib/res/values/dimens.xml
+++ b/packages/SettingsLib/res/values/dimens.xml
@@ -58,8 +58,8 @@
<dimen name="drawer_item_top_bottom_margin">4dp</dimen>
<dimen name="drawer_spacer_height">32dp</dimen>
- <dimen name="battery_height">48dp</dimen>
- <dimen name="battery_width">38dp</dimen>
+ <dimen name="battery_height">14.5dp</dimen>
+ <dimen name="battery_width">9.5dp</dimen>
<!-- Margin on the right side of the system icon group on Keyguard. -->
<fraction name="battery_button_height_fraction">10.5%</fraction>
diff --git a/packages/SettingsLib/src/com/android/settingslib/Utils.java b/packages/SettingsLib/src/com/android/settingslib/Utils.java
index ae6ada2a..11e2a71 100644
--- a/packages/SettingsLib/src/com/android/settingslib/Utils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/Utils.java
@@ -6,8 +6,8 @@
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.UserInfo;
import android.content.pm.Signature;
+import android.content.pm.UserInfo;
import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.content.res.TypedArray;
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawable/UserIconDrawable.java b/packages/SettingsLib/src/com/android/settingslib/drawable/UserIconDrawable.java
index 32478a7..7f469b5 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawable/UserIconDrawable.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawable/UserIconDrawable.java
@@ -34,6 +34,7 @@
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader;
+import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import com.android.settingslib.R;
@@ -273,6 +274,11 @@
super.invalidateSelf();
}
+ @Override
+ public ConstantState getConstantState() {
+ return new BitmapDrawable(mBitmap).getConstantState();
+ }
+
/**
* This 'bakes' the current state of this icon into a bitmap and removes/recycles the source
* bitmap/drawable. Use this when no more changes will be made and an intrinsic size is set.
diff --git a/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java b/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java
index d25bb2e..fd2e7ca 100755
--- a/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java
+++ b/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java
@@ -37,14 +37,13 @@
private static final float ASPECT_RATIO = 9.5f / 14.5f;
public static final String TAG = BatteryMeterDrawableBase.class.getSimpleName();
- public static final String SHOW_PERCENT_SETTING = "status_bar_show_battery_percent";
protected final Context mContext;
- protected int mLevel = -1;
- protected boolean mPluggedIn;
- protected boolean mPowerSaveEnabled;
- protected boolean mShowPercent;
+ private int mLevel = -1;
+ private boolean mPluggedIn;
+ private boolean mPowerSaveEnabled;
+ private boolean mShowPercent;
private static final boolean SINGLE_DIGIT_PERCENT = false;
@@ -104,7 +103,7 @@
}
levels.recycle();
colors.recycle();
- updateShowPercent();
+
mWarningString = context.getString(R.string.battery_meter_very_low_overlay_symbol);
mCriticalLevel = mContext.getResources().getInteger(
com.android.internal.R.integer.config_criticalBatteryWarningLevel);
@@ -143,10 +142,10 @@
mBoltPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mBoltPaint.setColor(Utils.getDefaultColor(mContext, R.color.batterymeter_bolt_color));
- mBoltPoints = loadBoltPoints(res);
+ mBoltPoints = loadPoints(res, R.array.batterymeter_bolt_points);
mPlusPaint = new Paint(mBoltPaint);
- mPlusPoints = loadPlusPoints(res);
+ mPlusPoints = loadPoints(res, R.array.batterymeter_plus_points);
mDarkModeBackgroundColor =
Utils.getDefaultColor(mContext, R.color.dark_mode_icon_color_dual_tone_background);
@@ -171,32 +170,34 @@
return mIntrinsicWidth;
}
- public void disableShowPercent() {
- mShowPercent = false;
+ public void setShowPercent(boolean show) {
+ mShowPercent = show;
postInvalidate();
}
+ public void setPluggedIn(boolean val) {
+ mPluggedIn = val;
+ postInvalidate();
+ }
+
+ public void setBatteryLevel(int val) {
+ mLevel = val;
+ postInvalidate();
+ }
+
+ public void setPowerSave(boolean val) {
+ mPowerSaveEnabled = val;
+ postInvalidate();
+ }
+
+ // an approximation of View.postInvalidate()
protected void postInvalidate() {
+ unscheduleSelf(this::invalidateSelf);
scheduleSelf(this::invalidateSelf, 0);
}
- private static float[] loadBoltPoints(Resources res) {
- final int[] pts = res.getIntArray(R.array.batterymeter_bolt_points);
- int maxX = 0, maxY = 0;
- for (int i = 0; i < pts.length; i += 2) {
- maxX = Math.max(maxX, pts[i]);
- maxY = Math.max(maxY, pts[i + 1]);
- }
- final float[] ptsF = new float[pts.length];
- for (int i = 0; i < pts.length; i += 2) {
- ptsF[i] = (float) pts[i] / maxX;
- ptsF[i + 1] = (float) pts[i + 1] / maxY;
- }
- return ptsF;
- }
-
- private static float[] loadPlusPoints(Resources res) {
- final int[] pts = res.getIntArray(R.array.batterymeter_plus_points);
+ private static float[] loadPoints(Resources res, int pointArrayRes) {
+ final int[] pts = res.getIntArray(pointArrayRes);
int maxX = 0, maxY = 0;
for (int i = 0; i < pts.length; i += 2) {
maxX = Math.max(maxX, pts[i]);
@@ -219,10 +220,6 @@
mWarningTextHeight = -mWarningTextPaint.getFontMetrics().ascent;
}
- protected void updateShowPercent() {
- mShowPercent = true;
- }
-
private int getColorForLevel(int percent) {
// If we are in power save mode, always use the normal color.
if (mPowerSaveEnabled) {
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/graph/BatteryMeterDrawableBaseTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/graph/BatteryMeterDrawableBaseTest.java
index fab00da..4de2c12 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/graph/BatteryMeterDrawableBaseTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/graph/BatteryMeterDrawableBaseTest.java
@@ -48,4 +48,24 @@
verify(canvas, never()).drawPath(any(), any());
verify(canvas, never()).drawText(anyString(), anyFloat(), anyFloat(), any());
}
+
+ @Test
+ public void testDrawingForTypicalValues() {
+ final Canvas canvas = mock(Canvas.class);
+ final int levels[] = { 0, 1, 5, 10, 25, 50, 75, 90, 95, 99, 100 };
+ final boolean bools[] = { false, true };
+ for (int l : levels) {
+ for (boolean plugged : bools) {
+ for (boolean saver : bools) {
+ for (boolean percent : bools) {
+ mBatteryDrawable.setBatteryLevel(l);
+ mBatteryDrawable.setPowerSave(saver);
+ mBatteryDrawable.setPluggedIn(plugged);
+ mBatteryDrawable.setShowPercent(percent);
+ mBatteryDrawable.draw(canvas);
+ }
+ }
+ }
+ }
+ }
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/SuggestionParserTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/SuggestionParserTest.java
index 0032cf0..7729dec 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/SuggestionParserTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/SuggestionParserTest.java
@@ -16,39 +16,35 @@
package com.android.settingslib;
-import android.util.Log;
-import android.content.Context;
import android.content.ComponentName;
+import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
-import android.os.Bundle;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
+import android.os.Bundle;
import android.preference.PreferenceManager;
+import com.android.settingslib.drawer.Tile;
+import com.android.settingslib.drawer.TileUtilsTest;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
-import com.android.settingslib.drawer.Tile;
-import com.android.settingslib.drawer.TileUtilsTest;
-
import java.util.ArrayList;
import java.util.List;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
-import org.robolectric.RuntimeEnvironment;
-
@RunWith(SettingLibRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class SuggestionParserTest {
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawable/UserIconDrawableTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawable/UserIconDrawableTest.java
new file mode 100644
index 0000000..a21390a
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawable/UserIconDrawableTest.java
@@ -0,0 +1,48 @@
+/*
+ * 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.settingslib.drawable;
+
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+
+import com.android.settingslib.R;
+import com.android.settingslib.SettingLibRobolectricTestRunner;
+import com.android.settingslib.TestConfig;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+import static com.google.common.truth.Truth.assertThat;
+
+@RunWith(SettingLibRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class UserIconDrawableTest {
+
+ private UserIconDrawable mDrawable;
+
+ @Test
+ public void getConstantState_shouldNotBeNull() {
+ final Bitmap b = BitmapFactory.decodeResource(
+ RuntimeEnvironment.application.getResources(),
+ R.drawable.home);
+ mDrawable = new UserIconDrawable(100 /* size */).setIcon(b).bake();
+
+ assertThat(mDrawable.getConstantState()).isNotNull();
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/BatteryMeterDrawable.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterDrawable.java
index 2bdb2f33..9068079 100644
--- a/packages/SystemUI/src/com/android/systemui/BatteryMeterDrawable.java
+++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterDrawable.java
@@ -27,6 +27,8 @@
public class BatteryMeterDrawable extends BatteryMeterDrawableBase implements
BatteryController.BatteryStateChangeCallback {
+ public static final String SHOW_PERCENT_SETTING = "status_bar_show_battery_percent";
+
private BatteryController mBatteryController;
private SettingObserver mSettingObserver;
@@ -38,16 +40,13 @@
@Override
public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
- mLevel = level;
- mPluggedIn = pluggedIn;
-
- postInvalidate();
+ setBatteryLevel(level);
+ setPluggedIn(pluggedIn);
}
@Override
public void onPowerSaveChanged(boolean isPowerSave) {
- mPowerSaveEnabled = isPowerSave;
- invalidateSelf();
+ setPowerSave(isPowerSave);
}
public void startListening() {
@@ -62,15 +61,14 @@
mBatteryController.removeCallback(this);
}
- @Override
protected void updateShowPercent() {
- mShowPercent = 0 != Settings.System.getInt(mContext.getContentResolver(),
- SHOW_PERCENT_SETTING, 0);
+ setShowPercent(0 != Settings.System.getInt(mContext.getContentResolver(),
+ SHOW_PERCENT_SETTING, 0));
}
public void setBatteryController(BatteryController batteryController) {
mBatteryController = batteryController;
- mPowerSaveEnabled = mBatteryController.isPowerSave();
+ setPowerSave(mBatteryController.isPowerSave());
}
private final class SettingObserver extends ContentObserver {
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java
index beec137..0259e3e 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java
@@ -25,11 +25,14 @@
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnLayoutChangeListener;
+import android.view.ViewGroup;
import android.view.WindowManager;
+import android.view.WindowManager.LayoutParams;
import android.widget.FrameLayout;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
+import com.android.systemui.recents.misc.SystemServicesProxy;
public class PipDismissViewController {
@@ -65,8 +68,10 @@
public void createDismissTarget() {
if (mDismissView == null) {
// Determine sizes for the gradient
- Point windowSize = new Point();
- mWindowManager.getDefaultDisplay().getSize(windowSize);
+ final Rect stableInsets = new Rect();
+ SystemServicesProxy.getInstance(mContext).getStableInsets(stableInsets);
+ final Point windowSize = new Point();
+ mWindowManager.getDefaultDisplay().getRealSize(windowSize);
mMinHeight = windowSize.y * DISMISS_GRADIENT_MIN_HEIGHT_PERCENT;
mMaxHeight = windowSize.y * DISMISS_GRADIENT_MAX_HEIGHT_PERCENT;
@@ -74,13 +79,16 @@
LayoutInflater inflater = LayoutInflater.from(mContext);
mDismissView = inflater.inflate(R.layout.pip_dismiss_view, null);
mGradientView = mDismissView.findViewById(R.id.gradient_view);
- FrameLayout.LayoutParams glp = (android.widget.FrameLayout.LayoutParams) mGradientView
- .getLayoutParams();
+ FrameLayout.LayoutParams glp =
+ (FrameLayout.LayoutParams) mGradientView.getLayoutParams();
glp.height = (int) mMaxHeight;
mGradientView.setLayoutParams(glp);
mGradientView.setPivotY(windowSize.y);
mGradientView.setScaleY(mMaxHeight / mMinHeight); // Set to min height via scaling
mDismissContainer = mDismissView.findViewById(R.id.pip_dismiss_container);
+ FrameLayout.LayoutParams clp =
+ (FrameLayout.LayoutParams) mDismissContainer.getLayoutParams();
+ clp.bottomMargin = stableInsets.bottom;
mDismissContainer.addOnLayoutChangeListener(new OnLayoutChangeListener() {
@Override
public void onLayoutChange(View v, int left, int top, int right, int bottom,
@@ -92,15 +100,16 @@
});
// Add the target to the window
- WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
- windowSize.x,
- (int) mMaxHeight,
- WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG,
- WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
- | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
- | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
+ LayoutParams lp = new LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT, (int) mMaxHeight,
+ 0, windowSize.y - (int) mMaxHeight,
+ LayoutParams.TYPE_SYSTEM_DIALOG,
+ LayoutParams.FLAG_LAYOUT_IN_SCREEN
+ | LayoutParams.FLAG_LAYOUT_NO_LIMITS
+ | LayoutParams.FLAG_NOT_TOUCHABLE
+ | LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT);
- lp.gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL;
+ lp.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL;
mWindowManager.addView(mDismissView, lp);
}
mDismissView.animate().cancel();
@@ -132,7 +141,7 @@
.withEndAction(new Runnable() {
@Override
public void run() {
- mWindowManager.removeView(mDismissView);
+ mWindowManager.removeViewImmediate(mDismissView);
mDismissView = null;
}
})
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
index 3d36868..471c3ae 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
@@ -34,6 +34,7 @@
import android.text.format.DateUtils;
import android.util.Log;
import android.util.Slog;
+import com.android.internal.logging.MetricsLogger;
import com.android.systemui.R;
import com.android.systemui.SystemUI;
import com.android.systemui.statusbar.phone.StatusBar;
@@ -45,6 +46,8 @@
static final String TAG = "PowerUI";
static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
private static final long TEMPERATURE_INTERVAL = 30 * DateUtils.SECOND_IN_MILLIS;
+ private static final long TEMPERATURE_LOGGING_INTERVAL = DateUtils.HOUR_IN_MILLIS;
+ private static final int MAX_RECENT_TEMPS = 125; // TEMPERATURE_LOGGING_INTERVAL plus a buffer
private final Handler mHandler = new Handler();
private final Receiver mReceiver = new Receiver();
@@ -62,7 +65,10 @@
private long mScreenOffTime = -1;
- private float mThrottlingTemp;
+ private float mThresholdTemp;
+ private float[] mRecentTemps = new float[MAX_RECENT_TEMPS];
+ private int mNumTemps;
+ private long mNextLogTime;
public void start() {
mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
@@ -229,10 +235,10 @@
return;
}
- mThrottlingTemp = Settings.Global.getFloat(resolver, Settings.Global.WARNING_TEMPERATURE,
+ mThresholdTemp = Settings.Global.getFloat(resolver, Settings.Global.WARNING_TEMPERATURE,
resources.getInteger(R.integer.config_warningTemperature));
- if (mThrottlingTemp < 0f) {
+ if (mThresholdTemp < 0f) {
// Get the throttling temperature. No need to check if we're not throttling.
float[] throttlingTemps = mHardwarePropertiesManager.getDeviceTemperatures(
HardwarePropertiesManager.DEVICE_TEMPERATURE_SKIN,
@@ -242,41 +248,86 @@
|| throttlingTemps[0] == HardwarePropertiesManager.UNDEFINED_TEMPERATURE) {
return;
}
- mThrottlingTemp = throttlingTemps[0];
+ mThresholdTemp = throttlingTemps[0];
}
+ setNextLogTime();
// We have passed all of the checks, start checking the temp
updateTemperatureWarning();
}
private void updateTemperatureWarning() {
- StatusBar statusBar = getComponent(StatusBar.class);
- if (statusBar != null && statusBar.isDeviceInVrMode()) {
- // ensure the warning isn't showing, since VR shows its own warning
- mWarnings.dismissTemperatureWarning();
- } else {
- float[] temps = mHardwarePropertiesManager.getDeviceTemperatures(
- HardwarePropertiesManager.DEVICE_TEMPERATURE_SKIN,
- HardwarePropertiesManager.TEMPERATURE_CURRENT);
- boolean shouldShowTempWarning = false;
- for (float temp : temps) {
- if (temp >= mThrottlingTemp) {
- Slog.i(TAG, "currentTemp=" + temp + ", throttlingTemp=" + mThrottlingTemp);
- shouldShowTempWarning = true;
- break;
- }
- }
- if (shouldShowTempWarning) {
+ float[] temps = mHardwarePropertiesManager.getDeviceTemperatures(
+ HardwarePropertiesManager.DEVICE_TEMPERATURE_SKIN,
+ HardwarePropertiesManager.TEMPERATURE_CURRENT);
+ if (temps.length != 0) {
+ float temp = temps[0];
+ mRecentTemps[mNumTemps++] = temp;
+
+ StatusBar statusBar = getComponent(StatusBar.class);
+ if (statusBar != null && !statusBar.isDeviceInVrMode()
+ && temp >= mThresholdTemp) {
+ logAtTemperatureThreshold(temp);
mWarnings.showTemperatureWarning();
} else {
mWarnings.dismissTemperatureWarning();
}
}
- // TODO: skip this when in VR mode since we already get a callback
+ logTemperatureStats();
+
mHandler.postDelayed(this::updateTemperatureWarning, TEMPERATURE_INTERVAL);
}
+ private void logAtTemperatureThreshold(float temp) {
+ StringBuilder sb = new StringBuilder();
+ sb.append("currentTemp=").append(temp)
+ .append(",thresholdTemp=").append(mThresholdTemp)
+ .append(",batteryStatus=").append(mBatteryStatus)
+ .append(",recentTemps=");
+ for (int i = 0; i < mNumTemps; i++) {
+ sb.append(mRecentTemps[i]).append(',');
+ }
+ Slog.i(TAG, sb.toString());
+ }
+
+ /**
+ * Calculates and logs min, max, and average
+ * {@link HardwarePropertiesManager#DEVICE_TEMPERATURE_SKIN} over the past
+ * {@link #TEMPERATURE_LOGGING_INTERVAL}.
+ */
+ private void logTemperatureStats() {
+ if (mNextLogTime > System.currentTimeMillis() && mNumTemps != MAX_RECENT_TEMPS) {
+ return;
+ }
+
+ if (mNumTemps > 0) {
+ float sum = mRecentTemps[0], min = mRecentTemps[0], max = mRecentTemps[0];
+ for (int i = 1; i < mNumTemps; i++) {
+ float temp = mRecentTemps[i];
+ sum += temp;
+ if (temp > max) {
+ max = temp;
+ }
+ if (temp < min) {
+ min = temp;
+ }
+ }
+
+ float avg = sum / mNumTemps;
+ Slog.i(TAG, "avg=" + avg + ",min=" + min + ",max=" + max);
+ MetricsLogger.histogram(mContext, "device_skin_temp_avg", (int) avg);
+ MetricsLogger.histogram(mContext, "device_skin_temp_min", (int) min);
+ MetricsLogger.histogram(mContext, "device_skin_temp_max", (int) max);
+ }
+ setNextLogTime();
+ mNumTemps = 0;
+ }
+
+ private void setNextLogTime() {
+ mNextLogTime = System.currentTimeMillis() + TEMPERATURE_LOGGING_INTERVAL;
+ }
+
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.print("mLowBatteryAlertCloseLevel=");
pw.println(mLowBatteryAlertCloseLevel);
@@ -303,8 +354,10 @@
Settings.Global.LOW_BATTERY_SOUND_TIMEOUT, 0));
pw.print("bucket: ");
pw.println(Integer.toString(findBatteryLevelBucket(mBatteryLevel)));
- pw.print("mThrottlingTemp=");
- pw.println(Float.toString(mThrottlingTemp));
+ pw.print("mThresholdTemp=");
+ pw.println(Float.toString(mThresholdTemp));
+ pw.print("mNextLogTime=");
+ pw.println(Long.toString(mNextLogTime));
mWarnings.dump(pw);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java
index 6f1f977..fff8305 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java
@@ -197,7 +197,7 @@
}
mDrawable.onBatteryLevelChanged(100, false, false);
mDrawable.onPowerSaveChanged(true);
- mDrawable.disableShowPercent();
+ mDrawable.setShowPercent(false);
((ImageView) mCurrentView.findViewById(android.R.id.icon)).setImageDrawable(mDrawable);
Checkable checkbox = (Checkable) mCurrentView.findViewById(android.R.id.toggle);
checkbox.setChecked(mPowerSave);
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/BatteryPreference.java b/packages/SystemUI/src/com/android/systemui/tuner/BatteryPreference.java
index ee0116e..3058c0a 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/BatteryPreference.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/BatteryPreference.java
@@ -25,7 +25,7 @@
import com.android.systemui.Dependency;
import com.android.systemui.statusbar.phone.StatusBarIconController;
-import static com.android.settingslib.graph.BatteryMeterDrawableBase.SHOW_PERCENT_SETTING;
+import static com.android.systemui.BatteryMeterDrawable.SHOW_PERCENT_SETTING;
public class BatteryPreference extends DropDownPreference implements TunerService.Tunable {
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java
index 7acd888..489c05b 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java
@@ -38,12 +38,10 @@
import android.util.ArrayMap;
import android.util.ArraySet;
-import com.android.settingslib.graph.BatteryMeterDrawableBase;
+import static com.android.systemui.BatteryMeterDrawable.SHOW_PERCENT_SETTING;
import com.android.systemui.DemoMode;
import com.android.systemui.Dependency;
import com.android.systemui.R;
-import com.android.systemui.SystemUI;
-import com.android.systemui.SystemUIApplication;
import com.android.systemui.settings.CurrentUserTracker;
import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.statusbar.phone.SystemUIDialog;
@@ -201,7 +199,7 @@
// A couple special cases.
Settings.Global.putString(mContentResolver, DemoMode.DEMO_MODE_ALLOWED, null);
Settings.System.putString(mContentResolver,
- BatteryMeterDrawableBase.SHOW_PERCENT_SETTING, null);
+ SHOW_PERCENT_SETTING, null);
Intent intent = new Intent(DemoMode.ACTION_DEMO);
intent.putExtra(DemoMode.EXTRA_COMMAND, DemoMode.COMMAND_EXIT);
mContext.sendBroadcast(intent);
diff --git a/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java
index 8c74532..859e1a1 100644
--- a/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java
@@ -552,6 +552,11 @@
Slog.wtf(TAG, "showSaveLocked(): no mStructure");
return;
}
+ if (mCurrentResponse == null) {
+ // Happens when the activity / session was finished before the service replied.
+ Slog.d(TAG, "showSaveLocked(): no mCurrentResponse yet");
+ return;
+ }
final ArraySet<AutoFillId> savableIds = mCurrentResponse.getSavableIds();
if (VERBOSE) Slog.v(TAG, "showSaveLocked(): savableIds=" + savableIds);
@@ -573,7 +578,6 @@
Slog.d(TAG, "finishSessionLocked(): found a change on " + id + ": "
+ state.mAutoFillValue);
}
-
mUi.showSaveUi();
return;
}
diff --git a/services/core/java/com/android/server/NetworkScoreService.java b/services/core/java/com/android/server/NetworkScoreService.java
index 5fe8b1a..0ac51b9 100644
--- a/services/core/java/com/android/server/NetworkScoreService.java
+++ b/services/core/java/com/android/server/NetworkScoreService.java
@@ -53,6 +53,7 @@
import android.os.IRemoteCallback;
import android.os.Looper;
import android.os.Message;
+import android.os.Process;
import android.os.RemoteCallback;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
@@ -676,6 +677,10 @@
}
}
+ private boolean isCallerSystemProcess(int callingUid) {
+ return callingUid == Process.SYSTEM_UID;
+ }
+
/**
* Obtain the package name of the current active network scorer.
*
@@ -692,6 +697,27 @@
return null;
}
+
+ /**
+ * Returns metadata about the active scorer or <code>null</code> if there is no active scorer.
+ */
+ @Override
+ public NetworkScorerAppData getActiveScorer() {
+ // Only the system can access this data.
+ if (isCallerSystemProcess(getCallingUid()) || callerCanRequestScores()) {
+ synchronized (mServiceConnectionLock) {
+ if (mServiceConnection != null) {
+ return mServiceConnection.mAppData;
+ }
+ }
+ } else {
+ throw new SecurityException(
+ "Caller is neither the system process nor a score requester.");
+ }
+
+ return null;
+ }
+
@Override
public void disableScoring() {
// Only the active scorer or the system should be allowed to disable scoring.
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 93fb911..1726747 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -5326,7 +5326,8 @@
for (int pid : pids) {
if (DEBUG_ANR) Slog.d(TAG, "Collecting stacks for native pid " + pid);
final long sime = SystemClock.elapsedRealtime();
- Debug.dumpNativeBacktraceToFile(pid, tracesPath);
+
+ Debug.dumpNativeBacktraceToFileTimeout(pid, tracesPath, 10);
if (DEBUG_ANR) Slog.d(TAG, "Done with native pid " + pid
+ " in " + (SystemClock.elapsedRealtime()-sime) + "ms");
}
@@ -5563,7 +5564,7 @@
// Reset notification settings.
INotificationManager inm = NotificationManager.getService();
- inm.clearData(packageName, pkgUidF);
+ inm.clearData(packageName, pkgUidF, uid == pkgUidF);
} catch (RemoteException e) {
}
} finally {
diff --git a/services/core/java/com/android/server/audio/MediaFocusControl.java b/services/core/java/com/android/server/audio/MediaFocusControl.java
index a1c5653..b4feef3 100644
--- a/services/core/java/com/android/server/audio/MediaFocusControl.java
+++ b/services/core/java/com/android/server/audio/MediaFocusControl.java
@@ -49,11 +49,18 @@
* that they lost focus.
*/
static final boolean ENFORCE_DUCKING = false;
+ /**
+ * set to true so the framework enforces muting media/game itself when the device is ringing
+ * or in a call.
+ */
+ static final boolean ENFORCE_MUTING_FOR_RING_OR_CALL = true;
private final Context mContext;
private final AppOpsManager mAppOps;
private PlayerFocusEnforcer mFocusEnforcer; // never null
+ private boolean mRingOrCallActive = false;
+
protected MediaFocusControl(Context cntxt, PlayerFocusEnforcer pfe) {
mContext = cntxt;
mAppOps = (AppOpsManager)mContext.getSystemService(Context.APP_OPS_SERVICE);
@@ -78,6 +85,16 @@
mFocusEnforcer.unduckPlayers(winner);
}
+ @Override
+ public void mutePlayersForCall(int[] usagesToMute) {
+ mFocusEnforcer.mutePlayersForCall(usagesToMute);
+ }
+
+ @Override
+ public void unmutePlayersForCall() {
+ mFocusEnforcer.unmutePlayersForCall();
+ }
+
//==========================================================================================
// AudioFocus
//==========================================================================================
@@ -139,7 +156,9 @@
stackIterator.next().dump(pw);
}
}
- pw.println("\n Notify on duck: " + mNotifyFocusOwnerOnDuck +"\n");
+ pw.println("\n");
+ pw.println(" Notify on duck: " + mNotifyFocusOwnerOnDuck + "\n");
+ pw.println(" In ring or call: " + mRingOrCallActive + "\n");
}
/**
@@ -401,6 +420,18 @@
}
/**
+ * Delay after entering ringing or call mode after which the framework will mute streams
+ * that are still playing.
+ */
+ private static final int RING_CALL_MUTING_ENFORCEMENT_DELAY_MS = 100;
+
+ /**
+ * Usages to mute when the device rings or is in a call
+ */
+ private final static int[] USAGES_TO_MUTE_IN_RING_OR_CALL =
+ { AudioAttributes.USAGE_MEDIA, AudioAttributes.USAGE_GAME };
+
+ /**
* Return the volume ramp time expected before playback with the given AudioAttributes would
* start after gaining audio focus.
* @param attr attributes of the sound about to start playing
@@ -452,6 +483,10 @@
}
synchronized(mAudioFocusLock) {
+ boolean enteringRingOrCall = !mRingOrCallActive
+ & (AudioSystem.IN_VOICE_COMM_FOCUS_ID.compareTo(clientId) == 0);
+ if (enteringRingOrCall) { mRingOrCallActive = true; }
+
boolean focusGrantDelayed = false;
if (!canReassignAudioFocus()) {
if ((flags & AudioManager.AUDIOFOCUS_FLAG_DELAY_OK) == 0) {
@@ -523,6 +558,9 @@
notifyExtPolicyFocusGrant_syncAf(nfr.toAudioFocusInfo(),
AudioManager.AUDIOFOCUS_REQUEST_GRANTED);
+ if (ENFORCE_MUTING_FOR_RING_OR_CALL & enteringRingOrCall) {
+ runAudioCheckerForRingOrCallAsync(true/*enteringRingOrCall*/);
+ }
}//synchronized(mAudioFocusLock)
return AudioManager.AUDIOFOCUS_REQUEST_GRANTED;
@@ -539,7 +577,15 @@
try {
// this will take care of notifying the new focus owner if needed
synchronized(mAudioFocusLock) {
+ boolean exitingRingOrCall = mRingOrCallActive
+ & (AudioSystem.IN_VOICE_COMM_FOCUS_ID.compareTo(clientId) == 0);
+ if (exitingRingOrCall) { mRingOrCallActive = false; }
+
removeFocusStackEntry(clientId, true /*signal*/, true /*notifyFocusFollowers*/);
+
+ if (ENFORCE_MUTING_FOR_RING_OR_CALL & exitingRingOrCall) {
+ runAudioCheckerForRingOrCallAsync(false/*enteringRingOrCall*/);
+ }
}
} catch (java.util.ConcurrentModificationException cme) {
// Catching this exception here is temporary. It is here just to prevent
@@ -559,4 +605,26 @@
}
}
+ private void runAudioCheckerForRingOrCallAsync(final boolean enteringRingOrCall) {
+ new Thread() {
+ public void run() {
+ if (enteringRingOrCall) {
+ try {
+ Thread.sleep(RING_CALL_MUTING_ENFORCEMENT_DELAY_MS);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ synchronized (mAudioFocusLock) {
+ // since the new thread starting running the state could have changed, so
+ // we need to check again mRingOrCallActive, not enteringRingOrCall
+ if (mRingOrCallActive) {
+ mFocusEnforcer.mutePlayersForCall(USAGES_TO_MUTE_IN_RING_OR_CALL);
+ } else {
+ mFocusEnforcer.unmutePlayersForCall();
+ }
+ }
+ }
+ }.start();
+ }
}
diff --git a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
index 4930c53..3f8bbe5 100644
--- a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
+++ b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
@@ -147,6 +147,11 @@
for (int piid : mDuckedPlayers) {
pw.println(" " + piid);
}
+ // players muted due to the device ringing or being in a call
+ pw.println("\n muted player piids:");
+ for (int piid : mMutedPlayers) {
+ pw.println(" " + piid);
+ }
}
}
@@ -231,6 +236,7 @@
//=================================================================
// PlayerFocusEnforcer implementation
private final ArrayList<Integer> mDuckedPlayers = new ArrayList<Integer>();
+ private final ArrayList<Integer> mMutedPlayers = new ArrayList<Integer>();
@Override
public boolean duckPlayers(FocusRequester winner, FocusRequester loser) {
@@ -290,9 +296,9 @@
&& winner.hasSameUid(apc.getClientUid())) {
try {
if (DEBUG) { Log.v(TAG, "unducking player" + piid); }
+ mDuckedPlayers.remove(new Integer(piid));
//FIXME just a test before we have VolumeShape
apc.getPlayerProxy().setPan(0.0f);
- mDuckedPlayers.remove(new Integer(piid));
} catch (Exception e) {
Log.e(TAG, "Error unducking player " + piid, e);
}
@@ -303,6 +309,65 @@
}
}
+ @Override
+ public void mutePlayersForCall(int[] usagesToMute) {
+ if (DEBUG) {
+ String log = new String("mutePlayersForCall: usages=");
+ for (int usage : usagesToMute) { log += " " + usage; }
+ Log.v(TAG, log);
+ }
+ synchronized (mPlayerLock) {
+ final Set<Integer> piidSet = mPlayers.keySet();
+ final Iterator<Integer> piidIterator = piidSet.iterator();
+ // find which players to mute
+ while (piidIterator.hasNext()) {
+ final Integer piid = piidIterator.next();
+ final AudioPlaybackConfiguration apc = mPlayers.get(piid);
+ final int playerUsage = apc.getAudioAttributes().getUsage();
+ boolean mute = false;
+ for (int usageToMute : usagesToMute) {
+ if (playerUsage == usageToMute) {
+ mute = true;
+ break;
+ }
+ }
+ if (mute) {
+ try {
+ if (DEBUG) { Log.v(TAG, "muting player" + piid); }
+ apc.getPlayerProxy().setVolume(0.0f);
+ mMutedPlayers.add(piid);
+ } catch (Exception e) {
+ Log.e(TAG, "Error muting player " + piid, e);
+ }
+ }
+ }
+ }
+ }
+
+ @Override
+ public void unmutePlayersForCall() {
+ if (DEBUG) {
+ Log.v(TAG, "unmutePlayersForCall()");
+ }
+ synchronized (mPlayerLock) {
+ if (mMutedPlayers.isEmpty()) {
+ return;
+ }
+ for (int piid : mMutedPlayers) {
+ final AudioPlaybackConfiguration apc = mPlayers.get(piid);
+ if (apc != null) {
+ try {
+ if (DEBUG) { Log.v(TAG, "unmuting player" + piid); }
+ apc.getPlayerProxy().setVolume(1.0f);
+ mMutedPlayers.remove(new Integer(piid));
+ } catch (Exception e) {
+ Log.e(TAG, "Error unmuting player " + piid, e);
+ }
+ }
+ }
+ }
+ }
+
//=================================================================
// Track playback activity listeners
diff --git a/services/core/java/com/android/server/audio/PlayerFocusEnforcer.java b/services/core/java/com/android/server/audio/PlayerFocusEnforcer.java
index acb4f0d..0733eca 100644
--- a/services/core/java/com/android/server/audio/PlayerFocusEnforcer.java
+++ b/services/core/java/com/android/server/audio/PlayerFocusEnforcer.java
@@ -28,4 +28,8 @@
public boolean duckPlayers(FocusRequester winner, FocusRequester loser);
public void unduckPlayers(FocusRequester winner);
+
+ public void mutePlayersForCall(int[] usagesToMute);
+
+ public void unmutePlayersForCall();
}
\ No newline at end of file
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 32c98a1..cc3fc00 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -1698,7 +1698,7 @@
@Override
- public void clearData(String packageName, int uid) throws RemoteException {
+ public void clearData(String packageName, int uid, boolean fromApp) throws RemoteException {
checkCallerIsSystem();
// Cancel posted notifications
@@ -1713,8 +1713,10 @@
mConditionProviders.onPackagesChanged(true, new String[] {packageName});
// Reset notification preferences
- mRankingHelper.onPackagesChanged(true, UserHandle.getCallingUserId(),
- new String[] {packageName}, new int[] {uid});
+ if (!fromApp) {
+ mRankingHelper.onPackagesChanged(true, UserHandle.getCallingUserId(),
+ new String[]{packageName}, new int[]{uid});
+ }
savePolicyFile();
}
diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java
index 4cbeec8..46c449b 100644
--- a/services/core/java/com/android/server/notification/RankingHelper.java
+++ b/services/core/java/com/android/server/notification/RankingHelper.java
@@ -674,7 +674,7 @@
public ParceledListSlice<NotificationChannelGroup> getNotificationChannelGroups(String pkg,
int uid, boolean includeDeleted) {
Preconditions.checkNotNull(pkg);
- List<NotificationChannelGroup> groups = new ArrayList<>();
+ Map<String, NotificationChannelGroup> groups = new ArrayMap<>();
Record r = getRecord(pkg, uid);
if (r == null) {
return ParceledListSlice.emptyList();
@@ -685,23 +685,21 @@
final NotificationChannel nc = r.channels.valueAt(i);
if (includeDeleted || !nc.isDeleted()) {
if (nc.getGroup() != null) {
- // lazily populate channel list
- NotificationChannelGroup ncg = r.groups.get(nc.getGroup());
+ NotificationChannelGroup ncg = groups.get(nc.getGroup());
+ if (ncg == null ) {
+ ncg = r.groups.get(nc.getGroup()).clone();
+ groups.put(nc.getGroup(), ncg);
+ }
ncg.addChannel(nc);
} else {
nonGrouped.addChannel(nc);
}
}
}
- for (NotificationChannelGroup group : r.groups.values()) {
- if (group.getChannels().size() > 0) {
- groups.add(group);
- }
- }
if (nonGrouped.getChannels().size() > 0) {
- groups.add(nonGrouped);
+ groups.put(null, nonGrouped);
}
- return new ParceledListSlice<>(groups);
+ return new ParceledListSlice<>(new ArrayList<>(groups.values()));
}
@Override
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 9d8372a..5075a41 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -1887,7 +1887,10 @@
private void setDeviceOwnerSystemPropertyLocked() {
// Device owner may still be provisioned, do not set the read-only system property yet.
- if (mInjector.settingsGlobalGetInt(Settings.Global.DEVICE_PROVISIONED, 0) == 0) {
+ // Wear devices don't set device_provisioned until the device is paired, so allow
+ // device_owner property to be set without that.
+ if (!mIsWatch
+ && mInjector.settingsGlobalGetInt(Settings.Global.DEVICE_PROVISIONED, 0) == 0) {
return;
}
// Still at the first stage of CryptKeeper double bounce, mOwners.hasDeviceOwner is
diff --git a/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java b/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java
index e20b571..9ea9ce9 100644
--- a/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java
+++ b/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java
@@ -15,6 +15,8 @@
*/
package com.android.server.notification;
+import static android.app.NotificationManager.IMPORTANCE_LOW;
+
import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.fail;
@@ -56,6 +58,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -168,7 +171,7 @@
private NotificationChannel getDefaultChannel() {
return new NotificationChannel(NotificationChannel.DEFAULT_CHANNEL_ID, "name",
- NotificationManager.IMPORTANCE_LOW);
+ IMPORTANCE_LOW);
}
private ByteArrayOutputStream writeXmlAndPurge(String pkg, int uid, String... channelIds)
@@ -260,7 +263,7 @@
NotificationChannel channel1 =
new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH);
NotificationChannel channel2 =
- new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
+ new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
channel2.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes);
channel2.enableLights(true);
channel2.setBypassDnd(true);
@@ -294,10 +297,26 @@
mHelper.getNotificationChannel(pkg, uid, channel2.getId(), false));
assertNotNull(mHelper.getNotificationChannel(
pkg, uid, NotificationChannel.DEFAULT_CHANNEL_ID, false));
- assertEquals(ncg.getId(),
- mHelper.getNotificationChannelGroups(pkg, uid, false).getList().get(0).getId());
- assertEquals(channel2.getGroup(), mHelper.getNotificationChannelGroups(
- pkg, uid, false).getList().get(0).getChannels().get(0).getGroup());
+
+ List<NotificationChannelGroup> actualGroups =
+ mHelper.getNotificationChannelGroups(pkg, uid, false).getList();
+ boolean foundNcg = false;
+ for (NotificationChannelGroup actual : actualGroups) {
+ if (ncg.getId().equals(actual.getId())) {
+ foundNcg = true;
+ break;
+ }
+ }
+ assertTrue(foundNcg);
+
+ boolean foundChannel2Group = false;
+ for (NotificationChannelGroup actual : actualGroups) {
+ if (channel2.getGroup().equals(actual.getChannels().get(0).getGroup())) {
+ foundChannel2Group = true;
+ break;
+ }
+ }
+ assertTrue(foundChannel2Group);
}
@Test
@@ -332,7 +351,7 @@
final NotificationChannel defaultChannel = mHelper.getNotificationChannel(
pkg, uid, NotificationChannel.DEFAULT_CHANNEL_ID, false);
- defaultChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
+ defaultChannel.setImportance(IMPORTANCE_LOW);
mHelper.updateNotificationChannel(pkg, uid, defaultChannel);
ByteArrayOutputStream baos = writeXmlAndPurge(pkg, uid, channel1.getId(),
@@ -344,7 +363,7 @@
parser.nextTag();
mHelper.readXml(parser, false);
- assertEquals(NotificationManager.IMPORTANCE_LOW, mHelper.getNotificationChannel(
+ assertEquals(IMPORTANCE_LOW, mHelper.getNotificationChannel(
pkg, uid, NotificationChannel.DEFAULT_CHANNEL_ID, false).getImportance());
}
@@ -376,7 +395,7 @@
final NotificationChannel updated2 = mHelper.getNotificationChannel(
pkg2, uid2, NotificationChannel.DEFAULT_CHANNEL_ID, false);
// clamped
- assertEquals(NotificationManager.IMPORTANCE_LOW, updated2.getImportance());
+ assertEquals(IMPORTANCE_LOW, updated2.getImportance());
assertFalse(updated2.canBypassDnd());
assertEquals(Notification.VISIBILITY_PRIVATE, updated2.getLockscreenVisibility());
assertEquals(NotificationChannel.USER_LOCKED_VISIBILITY, updated2.getUserLockedFields());
@@ -388,7 +407,7 @@
try {
mHelper.createNotificationChannel(pkg, uid,
- new NotificationChannel(pkg, "", NotificationManager.IMPORTANCE_LOW), true);
+ new NotificationChannel(pkg, "", IMPORTANCE_LOW), true);
fail("Channel creation should fail");
} catch (IllegalArgumentException e) {
// pass
@@ -399,7 +418,7 @@
public void testUpdate_userLockedImportance() throws Exception {
// all fields locked by user
final NotificationChannel channel =
- new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
+ new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
channel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);
mHelper.createNotificationChannel(pkg, uid, channel, false);
@@ -418,7 +437,7 @@
public void testUpdate_userLockedVisibility() throws Exception {
// all fields locked by user
final NotificationChannel channel =
- new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
+ new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
channel.lockFields(NotificationChannel.USER_LOCKED_VISIBILITY);
@@ -439,7 +458,7 @@
public void testUpdate_userLockedVibration() throws Exception {
// all fields locked by user
final NotificationChannel channel =
- new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
+ new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
channel.enableLights(false);
channel.lockFields(NotificationChannel.USER_LOCKED_VIBRATION);
@@ -461,7 +480,7 @@
public void testUpdate_userLockedLights() throws Exception {
// all fields locked by user
final NotificationChannel channel =
- new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
+ new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
channel.enableLights(false);
channel.lockFields(NotificationChannel.USER_LOCKED_LIGHTS);
@@ -482,7 +501,7 @@
public void testUpdate_userLockedPriority() throws Exception {
// all fields locked by user
final NotificationChannel channel =
- new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
+ new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
channel.setBypassDnd(true);
channel.lockFields(NotificationChannel.USER_LOCKED_PRIORITY);
@@ -503,7 +522,7 @@
public void testUpdate_userLockedRingtone() throws Exception {
// all fields locked by user
final NotificationChannel channel =
- new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
+ new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes);
channel.lockFields(NotificationChannel.USER_LOCKED_SOUND);
@@ -523,7 +542,7 @@
@Test
public void testUpdate_userLockedBadge() throws Exception {
final NotificationChannel channel =
- new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
+ new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
channel.setShowBadge(true);
channel.lockFields(NotificationChannel.USER_LOCKED_SHOW_BADGE);
@@ -543,7 +562,7 @@
public void testUpdate() throws Exception {
// no fields locked by user
final NotificationChannel channel =
- new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
+ new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes);
channel.enableLights(true);
channel.setBypassDnd(true);
@@ -575,7 +594,7 @@
@Test
public void testCreateChannel_CannotChangeHiddenFields() throws Exception {
final NotificationChannel channel =
- new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
+ new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes);
channel.enableLights(true);
channel.setBypassDnd(true);
@@ -602,7 +621,7 @@
@Test
public void testCreateChannel_CannotChangeHiddenFieldsAssistant() throws Exception {
final NotificationChannel channel =
- new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
+ new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes);
channel.enableLights(true);
channel.setBypassDnd(true);
@@ -629,7 +648,7 @@
@Test
public void testGetDeletedChannel() throws Exception {
NotificationChannel channel =
- new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
+ new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes);
channel.enableLights(true);
channel.setBypassDnd(true);
@@ -655,7 +674,7 @@
public void testGetDeletedChannels() throws Exception {
Map<String, NotificationChannel> channelMap = new HashMap<>();
NotificationChannel channel =
- new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
+ new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes);
channel.enableLights(true);
channel.setBypassDnd(true);
@@ -694,7 +713,7 @@
@Test
public void testUpdateDeletedChannels() throws Exception {
NotificationChannel channel =
- new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
+ new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
mHelper.createNotificationChannel(pkg, uid, channel, true);
mHelper.deleteNotificationChannel(pkg, uid, channel.getId());
@@ -719,7 +738,7 @@
public void testCreateDeletedChannel() throws Exception {
long[] vibration = new long[]{100, 67, 145, 156};
NotificationChannel channel =
- new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
+ new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
channel.setVibrationPattern(vibration);
mHelper.createNotificationChannel(pkg, uid, channel, true);
@@ -740,7 +759,7 @@
public void testCreateChannel_alreadyExists() throws Exception {
long[] vibration = new long[]{100, 67, 145, 156};
NotificationChannel channel =
- new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
+ new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
channel.setVibrationPattern(vibration);
mHelper.createNotificationChannel(pkg, uid, channel, true);
@@ -761,7 +780,7 @@
NotificationChannel channel1 =
new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH);
NotificationChannel channel2 =
- new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
+ new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
mHelper.createNotificationChannel(pkg, uid, channel1, true);
mHelper.createNotificationChannel(pkg, uid, channel2, false);
@@ -900,4 +919,29 @@
}
}
}
+
+ @Test
+ public void testGetChannelGroups_noSideEffects() throws Exception {
+ NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1");
+ mHelper.createNotificationChannelGroup(pkg, uid, ncg, true);
+
+ NotificationChannel channel1 =
+ new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH);
+ channel1.setGroup(ncg.getId());
+ mHelper.createNotificationChannel(pkg, uid, channel1, true);
+ mHelper.getNotificationChannelGroups(pkg, uid, true).getList();
+
+ channel1.setImportance(IMPORTANCE_LOW);
+ mHelper.updateNotificationChannel(pkg, uid, channel1);
+
+ List<NotificationChannelGroup> actual =
+ mHelper.getNotificationChannelGroups(pkg, uid, true).getList();
+
+ assertEquals(2, actual.size());
+ for (NotificationChannelGroup group : actual) {
+ if (Objects.equals(group.getId(),ncg.getId())) {
+ assertEquals(1, group.getChannels().size());
+ }
+ }
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
index fa9e9a8..3a88e9c 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
@@ -829,6 +829,50 @@
assertEquals(expectedList, actualList);
}
+ @Test
+ public void testGetActiveScorer_notConnected_canRequestScores() throws Exception {
+ when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
+ .thenReturn(PackageManager.PERMISSION_GRANTED);
+ assertNull(mNetworkScoreService.getActiveScorer());
+ }
+
+ @Test
+ public void testGetActiveScorer_notConnected_canNotRequestScores() throws Exception {
+ when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
+ .thenReturn(PackageManager.PERMISSION_DENIED);
+ try {
+ mNetworkScoreService.getActiveScorer();
+ fail("SecurityException expected.");
+ } catch (SecurityException e) {
+ // expected
+ }
+ }
+
+ @Test
+ public void testGetActiveScorer_connected_canRequestScores()
+ throws Exception {
+ when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
+ .thenReturn(PackageManager.PERMISSION_GRANTED);
+ NetworkScorerAppData expectedAppData =
+ new NetworkScorerAppData(Binder.getCallingUid(), RECOMMENDATION_SERVICE_COMP);
+ bindToScorer(expectedAppData);
+ assertEquals(expectedAppData, mNetworkScoreService.getActiveScorer());
+ }
+
+ @Test
+ public void testGetActiveScorer_connected_canNotRequestScores()
+ throws Exception {
+ when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
+ .thenReturn(PackageManager.PERMISSION_DENIED);
+ bindToScorer(false);
+ try {
+ mNetworkScoreService.getActiveScorer();
+ fail("SecurityException expected.");
+ } catch (SecurityException e) {
+ // expected
+ }
+ }
+
// "injects" the mock INetworkRecommendationProvider into the NetworkScoreService.
private void injectProvider() {
when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(NEW_SCORER);
@@ -849,9 +893,13 @@
}
private void bindToScorer(boolean callerIsScorer) {
- final int callingUid = callerIsScorer ? Binder.getCallingUid() : 0;
+ final int callingUid = callerIsScorer ? Binder.getCallingUid() : Binder.getCallingUid() + 1;
NetworkScorerAppData appData =
new NetworkScorerAppData(callingUid, RECOMMENDATION_SERVICE_COMP);
+ bindToScorer(appData);
+ }
+
+ private void bindToScorer(NetworkScorerAppData appData) {
when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(appData);
when(mContext.bindServiceAsUser(isA(Intent.class), isA(ServiceConnection.class), anyInt(),
isA(UserHandle.class))).thenReturn(true);
diff --git a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
index 6ca0bc5..d9465dc 100644
--- a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
+++ b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
@@ -259,4 +259,9 @@
* @see TelecomServiceImpl#isOutgoingCallPermitted
*/
boolean isOutgoingCallPermitted(in PhoneAccountHandle phoneAccountHandle);
+
+ /**
+ * @see TelecomServiceImpl#waitOnHandler
+ */
+ void waitOnHandlers();
}
diff --git a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java
index 5767f11..0401737 100644
--- a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java
+++ b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java
@@ -172,12 +172,10 @@
@Override
public void onHandleAssist(Bundle data, AssistStructure structure, AssistContent content) {
mAssistStructure = structure;
- if (mAssistStructure != null) {
- if (mAssistVisualizer != null) {
+ if (mAssistVisualizer != null) {
+ if (mAssistStructure != null) {
mAssistVisualizer.setAssistStructure(mAssistStructure);
- }
- } else {
- if (mAssistVisualizer != null) {
+ } else {
mAssistVisualizer.clearAssistData();
}
}
@@ -207,19 +205,24 @@
@Override
public void onHandleScreenshot(Bitmap screenshot) {
- if (screenshot != null) {
- mScreenshot.setImageBitmap(screenshot);
- mScreenshot.setAdjustViewBounds(true);
- mScreenshot.setMaxWidth(screenshot.getWidth() / 3);
- mScreenshot.setMaxHeight(screenshot.getHeight() / 3);
- mFullScreenshot.setImageBitmap(screenshot);
- } else {
- mScreenshot.setImageDrawable(null);
- mFullScreenshot.setImageDrawable(null);
+ if (mScreenshot != null) {
+ if (screenshot != null) {
+ mScreenshot.setImageBitmap(screenshot);
+ mScreenshot.setAdjustViewBounds(true);
+ mScreenshot.setMaxWidth(screenshot.getWidth() / 3);
+ mScreenshot.setMaxHeight(screenshot.getHeight() / 3);
+ mFullScreenshot.setImageBitmap(screenshot);
+ } else {
+ mScreenshot.setImageDrawable(null);
+ mFullScreenshot.setImageDrawable(null);
+ }
}
}
void updateState() {
+ if (mTopContent == null) {
+ return;
+ }
if (mState == STATE_IDLE) {
mTopContent.setVisibility(View.VISIBLE);
mBottomContent.setVisibility(View.GONE);
diff --git a/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
index 7b73b4b..1f661c4 100644
--- a/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
+++ b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
@@ -120,7 +120,7 @@
public void setUpdateIdentifier(int updateIdentifier) {
mUpdateIdentifier = updateIdentifier;
}
- public int getUpdateIdentififer() {
+ public int getUpdateIdentifier() {
return mUpdateIdentifier;
}
diff --git a/wifi/java/android/net/wifi/hotspot2/pps/Credential.java b/wifi/java/android/net/wifi/hotspot2/pps/Credential.java
index 025d4d3..620759d 100644
--- a/wifi/java/android/net/wifi/hotspot2/pps/Credential.java
+++ b/wifi/java/android/net/wifi/hotspot2/pps/Credential.java
@@ -100,7 +100,7 @@
public void setCheckAaaServerCertStatus(boolean checkAaaServerCertStatus) {
mCheckAaaServerCertStatus = checkAaaServerCertStatus;
}
- public boolean getCheckAaaServerStatus() {
+ public boolean getCheckAaaServerCertStatus() {
return mCheckAaaServerCertStatus;
}
diff --git a/wifi/java/android/net/wifi/hotspot2/pps/HomeSp.java b/wifi/java/android/net/wifi/hotspot2/pps/HomeSp.java
index 7a46129..8ec40c0 100644
--- a/wifi/java/android/net/wifi/hotspot2/pps/HomeSp.java
+++ b/wifi/java/android/net/wifi/hotspot2/pps/HomeSp.java
@@ -131,7 +131,7 @@
public void setMatchAnyOis(long[] matchAnyOis) {
mMatchAnyOis = matchAnyOis;
}
- public long[] getMatchAnysOis() {
+ public long[] getMatchAnyOis() {
return mMatchAnyOis;
}
diff --git a/wifi/java/android/net/wifi/hotspot2/pps/Policy.java b/wifi/java/android/net/wifi/hotspot2/pps/Policy.java
index caca0e4b..63238e8 100644
--- a/wifi/java/android/net/wifi/hotspot2/pps/Policy.java
+++ b/wifi/java/android/net/wifi/hotspot2/pps/Policy.java
@@ -77,7 +77,7 @@
public void setMinHomeDownlinkBandwidth(long minHomeDownlinkBandwidth) {
mMinHomeDownlinkBandwidth = minHomeDownlinkBandwidth;
}
- public long getMinHomeDownlinkBandWidht() {
+ public long getMinHomeDownlinkBandwidth() {
return mMinHomeDownlinkBandwidth;
}
private long mMinHomeUplinkBandwidth = Long.MIN_VALUE;