public class Application extends android.content.ContextWrapper implements android.content.ComponentCallbacks2 {
ctor public Application();
- method public android.app.Activity instantiateActivity(java.lang.ClassLoader, java.lang.String, android.content.Intent);
- method public android.app.backup.BackupAgent instantiateBackupAgent(java.lang.ClassLoader, java.lang.String);
- method public android.app.Instrumentation instantiateInstrumentation(java.lang.ClassLoader, java.lang.String);
- method public android.content.ContentProvider instantiateProvider(java.lang.ClassLoader, java.lang.String);
- method public android.content.BroadcastReceiver instantiateReceiver(java.lang.ClassLoader, java.lang.String, android.content.Intent);
- method public android.app.Service instantiateService(java.lang.ClassLoader, java.lang.String, android.content.Intent);
method public void onConfigurationChanged(android.content.res.Configuration);
method public void onCreate();
method public void onLowMemory();
public static final class Call.RttCall {
method public int getRttAudioMode();
- method public java.lang.String read() throws java.io.IOException;
+ method public java.lang.String read();
method public java.lang.String readImmediately() throws java.io.IOException;
method public void setRttMode(int);
method public void write(java.lang.String) throws java.io.IOException;
method public java.util.List<android.accessibilityservice.AccessibilityServiceInfo> getEnabledAccessibilityServiceList(int);
method public java.util.List<android.accessibilityservice.AccessibilityServiceInfo> getInstalledAccessibilityServiceList();
method public void interrupt();
+ method public static boolean isAccessibilityButtonSupported();
method public boolean isEnabled();
method public boolean isTouchExplorationEnabled();
method public void removeAccessibilityRequestPreparer(android.view.accessibility.AccessibilityRequestPreparer);
public class Application extends android.content.ContextWrapper implements android.content.ComponentCallbacks2 {
ctor public Application();
- method public android.app.Activity instantiateActivity(java.lang.ClassLoader, java.lang.String, android.content.Intent);
- method public android.app.backup.BackupAgent instantiateBackupAgent(java.lang.ClassLoader, java.lang.String);
- method public android.app.Instrumentation instantiateInstrumentation(java.lang.ClassLoader, java.lang.String);
- method public android.content.ContentProvider instantiateProvider(java.lang.ClassLoader, java.lang.String);
- method public android.content.BroadcastReceiver instantiateReceiver(java.lang.ClassLoader, java.lang.String, android.content.Intent);
- method public android.app.Service instantiateService(java.lang.ClassLoader, java.lang.String, android.content.Intent);
method public void onConfigurationChanged(android.content.res.Configuration);
method public void onCreate();
method public void onLowMemory();
public static final class Call.RttCall {
method public int getRttAudioMode();
- method public java.lang.String read() throws java.io.IOException;
+ method public java.lang.String read();
method public java.lang.String readImmediately() throws java.io.IOException;
method public void setRttMode(int);
method public void write(java.lang.String) throws java.io.IOException;
public class Application extends android.content.ContextWrapper implements android.content.ComponentCallbacks2 {
ctor public Application();
- method public android.app.Activity instantiateActivity(java.lang.ClassLoader, java.lang.String, android.content.Intent);
- method public android.app.backup.BackupAgent instantiateBackupAgent(java.lang.ClassLoader, java.lang.String);
- method public android.app.Instrumentation instantiateInstrumentation(java.lang.ClassLoader, java.lang.String);
- method public android.content.ContentProvider instantiateProvider(java.lang.ClassLoader, java.lang.String);
- method public android.content.BroadcastReceiver instantiateReceiver(java.lang.ClassLoader, java.lang.String, android.content.Intent);
- method public android.app.Service instantiateService(java.lang.ClassLoader, java.lang.String, android.content.Intent);
method public void onConfigurationChanged(android.content.res.Configuration);
method public void onCreate();
method public void onLowMemory();
public static final class Call.RttCall {
method public int getRttAudioMode();
- method public java.lang.String read() throws java.io.IOException;
+ method public java.lang.String read();
method public java.lang.String readImmediately() throws java.io.IOException;
method public void setRttMode(int);
method public void write(java.lang.String) throws java.io.IOException;
method public java.util.List<android.accessibilityservice.AccessibilityServiceInfo> getEnabledAccessibilityServiceList(int);
method public java.util.List<android.accessibilityservice.AccessibilityServiceInfo> getInstalledAccessibilityServiceList();
method public void interrupt();
+ method public static boolean isAccessibilityButtonSupported();
method public boolean isEnabled();
method public boolean isTouchExplorationEnabled();
method public void removeAccessibilityRequestPreparer(android.view.accessibility.AccessibilityRequestPreparer);
Activity activity = null;
try {
java.lang.ClassLoader cl = appContext.getClassLoader();
- if (appContext.getApplicationContext() instanceof Application) {
- activity = ((Application) appContext.getApplicationContext())
- .instantiateActivity(cl, component.getClassName(), r.intent);
- }
- if (activity == null) {
- activity = mInstrumentation.newActivity(
- cl, component.getClassName(), r.intent);
- }
+ activity = mInstrumentation.newActivity(
+ cl, component.getClassName(), r.intent);
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
r.intent.prepareToEnterProcess();
data.intent.setExtrasClassLoader(cl);
data.intent.prepareToEnterProcess();
data.setExtrasClassLoader(cl);
- receiver = instantiate(cl, component, data.intent, app,
- Application::instantiateReceiver);
+ receiver = (BroadcastReceiver)cl.loadClass(component).newInstance();
} catch (Exception e) {
if (DEBUG_BROADCAST) Slog.i(TAG,
"Finishing failed broadcast to " + data.intent.getComponent());
} else {
try {
if (DEBUG_BACKUP) Slog.v(TAG, "Initializing agent class " + classname);
- ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
java.lang.ClassLoader cl = packageInfo.getClassLoader();
- agent = instantiate(cl, classname, context,
- Application::instantiateBackupAgent);
+ agent = (BackupAgent) cl.loadClass(classname).newInstance();
// set up the agent's context
+ ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
context.setOuterContext(agent);
agent.attach(context);
LoadedApk packageInfo = getPackageInfoNoCheck(
data.info.applicationInfo, data.compatInfo);
Service service = null;
- Application app = null;
try {
- app = packageInfo.makeApplication(false, mInstrumentation);
java.lang.ClassLoader cl = packageInfo.getClassLoader();
- service = instantiate(cl, data.info.name, data.intent, app,
- Application::instantiateService);
+ service = (Service) cl.loadClass(data.info.name).newInstance();
} catch (Exception e) {
if (!mInstrumentation.onException(service, e)) {
throw new RuntimeException(
ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
context.setOuterContext(service);
+ Application app = packageInfo.makeApplication(false, mInstrumentation);
service.attach(context, this, data.info.name, data.token, app,
ActivityManager.getService());
service.onCreate();
try {
final ClassLoader cl = instrContext.getClassLoader();
- mInstrumentation = instantiate(cl, data.instrumentationName.getClassName(),
- instrContext, Application::instantiateInstrumentation);
+ mInstrumentation = (Instrumentation)
+ cl.loadClass(data.instrumentationName.getClassName()).newInstance();
} catch (Exception e) {
throw new RuntimeException(
"Unable to instantiate instrumentation "
try {
final java.lang.ClassLoader cl = c.getClassLoader();
- localProvider = instantiate(cl, info.name, context,
- Application::instantiateProvider);
+ localProvider = (ContentProvider)cl.
+ loadClass(info.name).newInstance();
provider = localProvider.getIContentProvider();
if (provider == null) {
Slog.e(TAG, "Failed to instantiate class " +
}
}
- private <T> T instantiate(ClassLoader cl, String className, Context c,
- Instantiator<T> instantiator)
- throws ClassNotFoundException, IllegalAccessException, InstantiationException {
- Application app = getApp(c);
- if (app != null) {
- T a = instantiator.instantiate(app, cl, className);
- if (a != null) return a;
- }
- return (T) cl.loadClass(className).newInstance();
- }
-
- private <T> T instantiate(ClassLoader cl, String className, Intent intent, Context c,
- IntentInstantiator<T> instantiator)
- throws ClassNotFoundException, IllegalAccessException, InstantiationException {
- Application app = getApp(c);
- if (app != null) {
- T a = instantiator.instantiate(app, cl, className, intent);
- if (a != null) return a;
- }
- return (T) cl.loadClass(className).newInstance();
- }
-
- private Application getApp(Context c) {
- // We need this shortcut to avoid actually calling getApplicationContext() on an Application
- // because the Application may not return itself for getApplicationContext() because the
- // API doesn't enforce it.
- if (c instanceof Application) return (Application) c;
- if (c.getApplicationContext() instanceof Application) {
- return (Application) c.getApplicationContext();
- }
- return null;
- }
-
- private interface Instantiator<T> {
- T instantiate(Application app, ClassLoader cl, String className)
- throws ClassNotFoundException, IllegalAccessException, InstantiationException;
- }
-
- private interface IntentInstantiator<T> {
- T instantiate(Application app, ClassLoader cl, String className, Intent intent)
- throws ClassNotFoundException, IllegalAccessException, InstantiationException;
- }
-
private static class EventLoggingReporter implements EventLogger.Reporter {
@Override
public void report (int code, Object... list) {
package android.app;
+import java.util.ArrayList;
+
import android.annotation.CallSuper;
-import android.app.backup.BackupAgent;
-import android.content.BroadcastReceiver;
import android.content.ComponentCallbacks;
import android.content.ComponentCallbacks2;
-import android.content.ContentProvider;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Bundle;
-import java.util.ArrayList;
-
/**
* Base class for maintaining global application state. You can provide your own
* implementation by creating a subclass and specifying the fully-qualified name
}
}
}
-
- /**
- * Allows application to override the creation of activities. This can be used to
- * perform things such as dependency injection or class loader changes to these
- * classes. Return null to use the default creation flow.
- * @param cl The default classloader to use for instantiation.
- * @param className The class to be instantiated.
- * @param intent Intent creating the class.
- */
- public Activity instantiateActivity(ClassLoader cl, String className, Intent intent) {
- return null;
- }
-
- /**
- * Allows application to override the creation of receivers. This can be used to
- * perform things such as dependency injection or class loader changes to these
- * classes. Return null to use the default creation flow.
- * @param cl The default classloader to use for instantiation.
- * @param className The class to be instantiated.
- * @param intent Intent creating the class.
- */
- public BroadcastReceiver instantiateReceiver(ClassLoader cl, String className, Intent intent) {
- return null;
- }
-
- /**
- * Allows application to override the creation of services. This can be used to
- * perform things such as dependency injection or class loader changes to these
- * classes. Return null to use the default creation flow.
- * @param cl The default classloader to use for instantiation.
- * @param className The class to be instantiated.
- * @param intent Intent creating the class.
- */
- public Service instantiateService(ClassLoader cl, String className, Intent intent) {
- return null;
- }
-
- /**
- * Allows application to override the creation of providers. This can be used to
- * perform things such as dependency injection or class loader changes to these
- * classes. Return null to use the default creation flow.
- * @param cl The default classloader to use for instantiation.
- * @param className The class to be instantiated.
- */
- public ContentProvider instantiateProvider(ClassLoader cl, String className) {
- return null;
- }
-
- /**
- * Allows application to override the creation of backup agents. This can be used to
- * perform things such as dependency injection or class loader changes to these
- * classes. Return null to use the default creation flow.
- * @param cl The default classloader to use for instantiation.
- * @param className The class to be instantiated.
- */
- public BackupAgent instantiateBackupAgent(ClassLoader cl, String className) {
- return null;
- }
-
- /**
- * Allows application to override the creation of instrumentation. This can be used to
- * perform things such as dependency injection or class loader changes to these
- * classes. Return null to use the default creation flow.
- * @param cl The default classloader to use for instantiation.
- * @param className The class to be instantiated.
- */
- public Instrumentation instantiateInstrumentation(ClassLoader cl, String className) {
- return null;
- }
}
\ No newline at end of file
* Constant for {@link Builder#setGroupAlertBehavior(int)}, meaning that all children
* notification in a group should be silenced (no sound or vibration) even if they are posted
* to a {@link NotificationChannel} that has sound and/or vibration. Use this constant to
- * mute this notification if this notification is a group child.
+ * mute this notification if this notification is a group child. This must be applied to all
+ * children notifications you want to mute.
*
* <p> For example, you might want to use this constant if you post a number of children
* notifications at once (say, after a periodic sync), and only need to notify the user
* to mute this notification if this notification is a group summary.
*
* <p>For example, you might want to use this constant if only the children notifications
- * in your group have content and the summary is only used to visually group notifications.
+ * in your group have content and the summary is only used to visually group notifications
+ * rather than to alert the user that new information is available.
*/
public static final int GROUP_ALERT_CHILDREN = 2;
* Sets the group alert behavior for this notification. Use this method to mute this
* notification if alerts for this notification's group should be handled by a different
* notification. This is only applicable for notifications that belong to a
- * {@link #setGroup(String) group}.
+ * {@link #setGroup(String) group}. This must be called on all notifications you want to
+ * mute. For example, if you want only the summary of your group to make noise, all
+ * children in the group should have the group alert behavior {@link #GROUP_ALERT_SUMMARY}.
*
* <p> The default value is {@link #GROUP_ALERT_ALL}.</p>
*/
*/
package android.app;
-import android.annotation.StringRes;
import android.annotation.SystemApi;
import android.content.Intent;
-import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
-import android.service.notification.NotificationListenerService;
import android.text.TextUtils;
-import android.util.Slog;
import org.json.JSONException;
import org.json.JSONObject;
-import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlSerializer;
import java.io.IOException;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.List;
/**
return mName;
}
- /*
+ /**
* Returns the list of channels that belong to this group
- *
- * @hide
*/
public List<NotificationChannel> getChannels() {
return mChannels;
gatt = mBluetoothManager.getBluetoothGatt();
} catch (RemoteException e) {
Log.e(TAG, "Failed to get Bluetooth gatt - ", e);
- throw new IllegalStateException("Failed to get Bluetooth");
+ postStartSetFailure(handler, callback, AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR);
+ return;
}
IAdvertisingSetCallback wrapped = wrap(callback, handler);
periodicData, duration, maxExtendedAdvertisingEvents, wrapped);
} catch (RemoteException e) {
Log.e(TAG, "Failed to start advertising set - ", e);
- throw new IllegalStateException("Failed to start advertising set");
+ postStartSetFailure(handler, callback, AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR);
+ return;
}
}
gatt.stopAdvertisingSet(wrapped);
} catch (RemoteException e) {
Log.e(TAG, "Failed to stop advertising - ", e);
- throw new IllegalStateException("Failed to stop advertising");
- }
+ }
}
/**
};
}
+ private void postStartSetFailure(Handler handler, final AdvertisingSetCallback callback,
+ final int error) {
+ handler.post(new Runnable() {
+ @Override
+ public void run() {
+ callback.onAdvertisingSetStarted(null, 0, error);
+ }
+ });
+ }
+
private void postStartFailure(final AdvertiseCallback callback, final int error) {
mHandler.post(new Runnable() {
@Override
final String cacheKey = getCacheKey(packageFile, flags);
final File cacheFile = new File(mCacheDir, cacheKey);
- // If the cache is not up to date, return null.
- if (!isCacheUpToDate(packageFile, cacheFile)) {
- return null;
- }
-
try {
+ // If the cache is not up to date, return null.
+ if (!isCacheUpToDate(packageFile, cacheFile)) {
+ return null;
+ }
+
final byte[] bytes = IoUtils.readFileAsByteArray(cacheFile.getAbsolutePath());
Package p = fromCacheEntry(bytes);
if (mCallback != null) {
}
}
return p;
- } catch (Exception e) {
+ } catch (Throwable e) {
Slog.w(TAG, "Error reading package cache: ", e);
// If something went wrong while reading the cache entry, delete the cache file
return;
}
- final String cacheKey = getCacheKey(packageFile, flags);
- final File cacheFile = new File(mCacheDir, cacheKey);
+ try {
+ final String cacheKey = getCacheKey(packageFile, flags);
+ final File cacheFile = new File(mCacheDir, cacheKey);
- if (cacheFile.exists()) {
- if (!cacheFile.delete()) {
- Slog.e(TAG, "Unable to delete cache file: " + cacheFile);
+ if (cacheFile.exists()) {
+ if (!cacheFile.delete()) {
+ Slog.e(TAG, "Unable to delete cache file: " + cacheFile);
+ }
}
- }
- final byte[] cacheEntry = toCacheEntry(parsed);
+ final byte[] cacheEntry = toCacheEntry(parsed);
- if (cacheEntry == null) {
- return;
- }
+ if (cacheEntry == null) {
+ return;
+ }
- try (FileOutputStream fos = new FileOutputStream(cacheFile)) {
- fos.write(cacheEntry);
- } catch (IOException ioe) {
- Slog.w(TAG, "Error writing cache entry.", ioe);
- cacheFile.delete();
+ try (FileOutputStream fos = new FileOutputStream(cacheFile)) {
+ fos.write(cacheEntry);
+ } catch (IOException ioe) {
+ Slog.w(TAG, "Error writing cache entry.", ioe);
+ cacheFile.delete();
+ }
+ } catch (Throwable e) {
+ Slog.w(TAG, "Error saving package cache.", e);
}
}
import android.os.Parcelable;
import android.util.Pair;
+import java.net.Inet4Address;
+import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Arrays;
}
/**
+ * @hide
+ */
+ public boolean isIPv6() {
+ return getAddress() instanceof Inet6Address;
+ }
+
+ /**
+ * @hide
+ */
+ public boolean isIPv4() {
+ return getAddress() instanceof Inet4Address;
+ }
+
+ /**
* Returns a string representation of this {@code IpPrefix}.
*
* @return a string such as {@code "192.0.2.0/24"} or {@code "2001:db8:1:2::/64"}.
* RFC 6724 section 3.2.
* @hide
*/
- static int scopeForUnicastAddress(InetAddress addr) {
+ private static int scopeForUnicastAddress(InetAddress addr) {
if (addr.isAnyLocalAddress()) {
return RT_SCOPE_HOST;
}
* Per RFC 4193 section 8, fc00::/7 identifies these addresses.
*/
private boolean isIPv6ULA() {
- if (address instanceof Inet6Address) {
+ if (isIPv6()) {
byte[] bytes = address.getAddress();
return ((bytes[0] & (byte)0xfe) == (byte)0xfc);
}
}
/**
+ * @return true if the address is IPv6.
+ * @hide
+ */
+ public boolean isIPv6() {
+ return address instanceof Inet6Address;
+ }
+
+ /**
+ * @return true if the address is IPv4 or is a mapped IPv4 address.
+ * @hide
+ */
+ public boolean isIPv4() {
+ return address instanceof Inet4Address;
+ }
+
+ /**
* Utility function for the constructors.
*/
private void init(InetAddress address, int prefixLength, int flags, int scope) {
if (address == null ||
address.isMulticastAddress() ||
prefixLength < 0 ||
- ((address instanceof Inet4Address) && prefixLength > 32) ||
+ (address instanceof Inet4Address && prefixLength > 32) ||
(prefixLength > 128)) {
throw new IllegalArgumentException("Bad LinkAddress params " + address +
"/" + prefixLength);
*/
public LinkAddress(String address, int flags, int scope) {
// This may throw an IllegalArgumentException; catching it is the caller's responsibility.
+ // TODO: consider rejecting mapped IPv4 addresses such as "::ffff:192.0.2.5/24".
Pair<InetAddress, Integer> ipAndMask = NetworkUtils.parseIpAndMask(address);
init(ipAndMask.first, ipAndMask.second, flags, scope);
}
StringJoiner joiner = new StringJoiner(", ");
- // TODO: consider only enforcing that capabilities are not removed, allowing addition.
// Ignore NOT_METERED being added or removed as it is effectively dynamic. http://b/63326103
// TODO: properly support NOT_METERED as a mutable and requestable capability.
final long mask = ~MUTABLE_CAPABILITIES & ~(1 << NET_CAPABILITY_NOT_METERED);
* the local part to be at most 64 octets.
*/
private static final String EMAIL_ADDRESS_LOCAL_PART =
- "[" + EMAIL_CHAR + "]" + "(?:[" + EMAIL_CHAR + "\\.]{1,62}[" + EMAIL_CHAR + "])?";
+ "[" + EMAIL_CHAR + "]" + "(?:[" + EMAIL_CHAR + "\\.]{0,62}[" + EMAIL_CHAR + "])?";
/**
* Regular expression for the domain part of an email address. RFC5321 section 4.5.3.1.2 limits
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SdkConstant;
-import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.content.ComponentName;
import android.content.Context;
*
* @return {@code true} if the accessibility button is supported on this device,
* {@code false} otherwise
- * @hide
*/
- @SystemApi
public static boolean isAccessibilityButtonSupported() {
final Resources res = Resources.getSystem();
return res.getBoolean(com.android.internal.R.bool.config_showNavigationBar);
context.getString(R.string.notification_channel_usb),
NotificationManager.IMPORTANCE_MIN));
- channelsList.add(new NotificationChannel(
+ NotificationChannel foregroundChannel = new NotificationChannel(
FOREGROUND_SERVICE,
context.getString(R.string.notification_channel_foreground_service),
- NotificationManager.IMPORTANCE_LOW));
+ NotificationManager.IMPORTANCE_LOW);
+ foregroundChannel.setBlockableSystem(true);
+ channelsList.add(foregroundChannel);
nm.createNotificationChannels(channelsList);
}
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/assets/res/any/strings.xml
+**
+** Copyright 2006, 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.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="mmcc_imsi_unknown_in_hlr">SIM not provisioned MM#2</string>
+ <string name="mmcc_illegal_ms">SIM not allowed MM#3</string>
+</resources>
+++ /dev/null
-./values-mcc310-mnc150
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/assets/res/any/strings.xml
+**
+** Copyright 2006, 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.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="mmcc_imsi_unknown_in_hlr">SIM not provisioned MM#2</string>
+ <string name="mmcc_illegal_ms">SIM not allowed MM#3</string>
+</resources>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/assets/res/any/strings.xml
+**
+** Copyright 2006, 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.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="mmcc_imsi_unknown_in_hlr">SIM not provisioned MM#2</string>
+ <string name="mmcc_illegal_ms">SIM not allowed MM#3</string>
+</resources>
+++ /dev/null
-./values-mcc310-mnc150
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/assets/res/any/strings.xml
+**
+** Copyright 2006, 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.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="mmcc_imsi_unknown_in_hlr">SIM not provisioned MM#2</string>
+ <string name="mmcc_illegal_ms">SIM not allowed MM#3</string>
+</resources>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/assets/res/any/strings.xml
+**
+** Copyright 2006, 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.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="mmcc_imsi_unknown_in_hlr">SIM not provisioned MM#2</string>
+ <string name="mmcc_illegal_ms">SIM not allowed MM#3</string>
+</resources>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/assets/res/any/strings.xml
+**
+** Copyright 2006, 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.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="mmcc_imsi_unknown_in_hlr">SIM not provisioned MM#2</string>
+ <string name="mmcc_illegal_ms">SIM not allowed MM#3</string>
+</resources>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/assets/res/any/strings.xml
+**
+** Copyright 2006, 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.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="mmcc_imsi_unknown_in_hlr">SIM not provisioned MM#2</string>
+ <string name="mmcc_illegal_ms">SIM not allowed MM#3</string>
+</resources>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/assets/res/any/strings.xml
+**
+** Copyright 2006, 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.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="mmcc_imsi_unknown_in_hlr">SIM not provisioned MM#2</string>
+ <string name="mmcc_illegal_ms">SIM not allowed MM#3</string>
+</resources>
<!-- Integer parameters of the wifi to cellular handover feature
wifi should not stick to bad networks -->
<integer translatable="false" name="config_wifi_framework_wifi_score_bad_rssi_threshold_5GHz">-82</integer>
+ <integer translatable="false" name="config_wifi_framework_wifi_score_entry_rssi_threshold_5GHz">-82</integer>
<integer translatable="false" name="config_wifi_framework_wifi_score_low_rssi_threshold_5GHz">-70</integer>
<integer translatable="false" name="config_wifi_framework_wifi_score_good_rssi_threshold_5GHz">-57</integer>
<integer translatable="false" name="config_wifi_framework_wifi_score_bad_rssi_threshold_24GHz">-85</integer>
+ <integer translatable="false" name="config_wifi_framework_wifi_score_entry_rssi_threshold_24GHz">-85</integer>
<integer translatable="false" name="config_wifi_framework_wifi_score_low_rssi_threshold_24GHz">-73</integer>
<integer translatable="false" name="config_wifi_framework_wifi_score_good_rssi_threshold_24GHz">-60</integer>
<integer translatable="false" name="config_wifi_framework_wifi_score_bad_link_speed_24">6</integer>
<integer translatable="false" name="config_wifi_framework_wifi_score_bad_link_speed_5">12</integer>
<integer translatable="false" name="config_wifi_framework_wifi_score_good_link_speed_24">24</integer>
<integer translatable="false" name="config_wifi_framework_wifi_score_good_link_speed_5">36</integer>
+
<string translatable="false" name="config_wifi_random_mac_oui">DA-A1-19</string>
<string translatable="false" name="config_wifi_framework_sap_2G_channel_list">1,6,11</string>
<bool name="config_automatic_brightness_available">false</bool>
<!-- Fast brightness animation ramp rate in brightness units per second-->
- <integer translatable="false" name="config_brightness_ramp_rate_fast">200</integer>
+ <integer translatable="false" name="config_brightness_ramp_rate_fast">180</integer>
<!-- Slow brightness animation ramp rate in brightness units per second-->
- <integer translatable="false" name="config_brightness_ramp_rate_slow">40</integer>
+ <integer translatable="false" name="config_brightness_ramp_rate_slow">60</integer>
<!-- Don't name config resources like this. It should look like config_annoyDianne -->
<bool name="config_annoy_dianne">true</bool>
<!-- This is the label for the notification channel settings that controls the behavior
of the notification about applications that are running in the background (that is,
perhaps confusingly, running foreground services but not the foreground UI on the screen).
- [CHAR LIMIT=NONE] -->
- <string name="notification_channel_foreground_service">Apps running in background</string>
+ [CHAR LIMIT=NONE BACKUP_MESSAGE_ID=6665375982962336520] -->
+ <string name="notification_channel_foreground_service">Apps consuming battery</string>
- <!-- Label for foreground service notification when one app is running. [CHAR LIMIT=NONE] -->
+ <!-- Label for foreground service notification when one app is running.
+ [CHAR LIMIT=NONE BACKUP_MESSAGE_ID=6826789589341671842] -->
<string name="foreground_service_app_in_background"><xliff:g id="app_name">%1$s</xliff:g> is
- running in the background</string>
+ using battery</string>
<!-- Label for foreground service notification when multiple apps are running.
- [CHAR LIMIT=NONE] -->
+ [CHAR LIMIT=NONE BACKUP_MESSAGE_ID=7150914856893450380] -->
<string name="foreground_service_apps_in_background"><xliff:g id="number">%1$d</xliff:g> apps
- are running in the background</string>
+ are using battery</string>
<!-- Content for foreground service notification when one app is running.
[CHAR LIMIT=NONE] -->
<java-symbol type="integer" name="config_wifi_framework_associated_full_scan_max_total_dwell_time" />
<java-symbol type="integer" name="config_wifi_framework_associated_partial_scan_max_num_active_channels" />
<java-symbol type="integer" name="config_wifi_framework_wifi_score_bad_rssi_threshold_24GHz" />
+ <java-symbol type="integer" name="config_wifi_framework_wifi_score_entry_rssi_threshold_24GHz" />
<java-symbol type="integer" name="config_wifi_framework_wifi_score_low_rssi_threshold_24GHz" />
<java-symbol type="integer" name="config_wifi_framework_wifi_score_good_rssi_threshold_24GHz" />
<java-symbol type="integer" name="config_wifi_framework_wifi_score_bad_rssi_threshold_5GHz" />
+ <java-symbol type="integer" name="config_wifi_framework_wifi_score_entry_rssi_threshold_5GHz" />
<java-symbol type="integer" name="config_wifi_framework_wifi_score_low_rssi_threshold_5GHz" />
<java-symbol type="integer" name="config_wifi_framework_wifi_score_good_rssi_threshold_5GHz" />
<java-symbol type="integer" name="config_wifi_framework_wifi_score_bad_link_speed_24" />
<allow-implicit-broadcast action="android.intent.action.SIM_STATE_CHANGED" />
<allow-implicit-broadcast action="android.intent.action.PACKAGE_CHANGED" />
<allow-implicit-broadcast action="android.intent.action.MEDIA_SCANNER_SCAN_FILE" />
+ <allow-implicit-broadcast action="android.media.action.OPEN_AUDIO_EFFECT_CONTROL_SESSION" />
+ <allow-implicit-broadcast action="android.media.action.CLOSE_AUDIO_EFFECT_CONTROL_SESSION" />
<!-- Whitelist of what components are permitted as backup data transports. The
'service' attribute here is a flattened ComponentName string. -->
+++ /dev/null
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the
- * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
-
-package com.android.systemui.plugins;
-
-import android.app.Activity;
-import android.content.Context;
-import android.content.res.Resources;
-import android.os.Bundle;
-
-import com.android.systemui.plugins.annotations.ProvidesInterface;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * A PluginActivity is an activity that replaces another full activity (e.g. RecentsActivity)
- * at runtime within the sysui process.
- */
-@ProvidesInterface(version = PluginActivity.VERSION)
-public abstract class PluginActivity extends Activity implements Plugin {
-
- public static final int VERSION = 1;
-
- public static final String ACTION_RECENTS = "com.android.systemui.action.PLUGIN_RECENTS";
-
- private Context mSysuiContext;
- private boolean mSettingActionBar;
-
- @Override
- public final void onCreate(Context sysuiContext, Context pluginContext) {
- mSysuiContext = sysuiContext;
- super.attachBaseContext(pluginContext);
- }
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- Theme theme = getClass().getDeclaredAnnotation(Theme.class);
- if (theme != null && theme.value() != 0) {
- setTheme(theme.value());
- }
- mSettingActionBar = true;
- getActionBar();
- mSettingActionBar = false;
- }
-
- @Override
- public Resources getResources() {
- return mSettingActionBar ? mSysuiContext.getResources() : super.getResources();
- }
-
- @Override
- protected void attachBaseContext(Context newBase) {
- mSysuiContext = newBase;
- }
-
- @Override
- public void onDestroy() {
- super.onDestroy();
- }
-
- public Context getSysuiContext() {
- return mSysuiContext;
- }
-
- public Context getPluginContext() {
- return getBaseContext();
- }
-
- /**
- * Since PluginActivities are declared as services instead of activities (since they
- * are plugins), they can't have a theme attached to them. Instead a PluginActivity
- * can annotate itself with @Theme to specify the resource of the style it wants
- * to be themed with.
- */
- @Retention(RetentionPolicy.RUNTIME)
- public @interface Theme {
- int value();
- }
-}
public static final int VERSION = 1;
static DependencyProvider sProvider;
- /**
- * Allows a plugin to get a hold of static dependencies if they have declared dependence
- * on their interface. For one-shot plugins this will only work during onCreate and will
- * not work afterwards.
- */
public static <T> T get(Plugin p, Class<T> cls) {
return sProvider.get(p, cls);
}
<include layout="@layout/car_status_bar_header" />
<include layout="@layout/car_qs_footer" />
+
+ <com.android.systemui.statusbar.car.UserGridView
+ android:id="@+id/user_grid"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="@dimen/car_margin"
+ android:layout_marginRight="@dimen/car_margin" />
</LinearLayout>
import com.android.systemui.keyguard.ScreenLifecycle;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.plugins.ActivityStarter;
-import com.android.systemui.plugins.PluginActivityManager;
import com.android.systemui.plugins.PluginDependencyProvider;
import com.android.systemui.plugins.PluginManager;
import com.android.systemui.plugins.PluginManagerImpl;
mProviders.put(UiOffloadThread.class, UiOffloadThread::new);
- mProviders.put(PluginActivityManager.class,
- () -> new PluginActivityManager(mContext, getDependency(PluginManager.class)));
mProviders.put(PowerUI.WarningsUI.class, () -> new PowerNotificationWarnings(mContext));
package com.android.systemui;
-import android.app.Activity;
import android.app.ActivityThread;
import android.app.Application;
import android.content.BroadcastReceiver;
import com.android.systemui.plugins.GlobalActions;
import com.android.systemui.plugins.OverlayPlugin;
import com.android.systemui.plugins.Plugin;
-import com.android.systemui.plugins.PluginActivityManager;
import com.android.systemui.plugins.PluginListener;
import com.android.systemui.plugins.PluginManager;
import com.android.systemui.power.PowerUI;
public SystemUI[] getServices() {
return mServices;
}
-
- @Override
- public Activity instantiateActivity(ClassLoader cl, String className, Intent intent) {
- if (!mServicesStarted) return null;
- return Dependency.get(PluginActivityManager.class).instantiate(cl, className, intent);
- }
}
+++ /dev/null
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the
- * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
-
-package com.android.systemui.plugins;
-
-import android.app.Activity;
-import android.content.Context;
-import android.content.Intent;
-import android.text.TextUtils;
-import android.util.ArrayMap;
-
-public class PluginActivityManager {
-
- private final Context mContext;
- private final PluginManager mPluginManager;
- private final ArrayMap<String, String> mActionLookup = new ArrayMap<>();
-
- public PluginActivityManager(Context context, PluginManager pluginManager) {
- mContext = context;
- mPluginManager = pluginManager;
- }
-
- public void addActivityPlugin(String className, String action) {
- mActionLookup.put(className, action);
- }
-
- public Activity instantiate(ClassLoader cl, String className, Intent intent) {
- String action = mActionLookup.get(className);
- if (TextUtils.isEmpty(action)) return null;
- return mPluginManager.getOneShotPlugin(action, PluginActivity.class);
- }
-}
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.systemui.Dependency;
import com.android.systemui.plugins.PluginInstanceManager.PluginContextWrapper;
+import com.android.systemui.plugins.PluginInstanceManager.PluginInfo;
import com.android.systemui.plugins.annotations.ProvidesInterface;
import dalvik.system.PathClassLoader;
}
PluginInstanceManager<T> p = mFactory.createPluginInstanceManager(mContext, action, null,
false, mLooper, cls, this);
- PluginListener<Plugin> listener = new PluginListener<Plugin>() {
- @Override
- public void onPluginConnected(Plugin plugin, Context pluginContext) { }
- };
- mPluginMap.put(listener, p);
mPluginPrefs.addAction(action);
- PluginInstanceManager.PluginInfo<T> info = p.getPlugin();
+ PluginInfo<T> info = p.getPlugin();
if (info != null) {
mOneShotPackages.add(info.mPackage);
mHasOneShot = true;
startListening();
- mPluginMap.remove(listener);
return info.mPlugin;
}
- mPluginMap.remove(listener);
return null;
}
vpnWarning.setMovementMethod(new LinkMovementMethod());
}
+ // Note: if a new section is added, should update configSubtitleVisibility to include
+ // the handling of the subtitle
+ configSubtitleVisibility(managementMessage != null,
+ caCertsMessage != null,
+ networkLoggingMessage != null,
+ vpnMessage != null,
+ dialogView);
+
mDialog.show();
mDialog.getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
}
+ protected void configSubtitleVisibility(boolean showDeviceManagement, boolean showCaCerts,
+ boolean showNetworkLogging, boolean showVpn, View dialogView) {
+ // Device Management title should always been shown
+ // When there is a Device Management message, all subtitles should be shown
+ if (showDeviceManagement) {
+ return;
+ }
+ // Hide the subtitle if there is only 1 message shown
+ int mSectionCountExcludingDeviceMgt = 0;
+ if (showCaCerts) { mSectionCountExcludingDeviceMgt++; }
+ if (showNetworkLogging) { mSectionCountExcludingDeviceMgt++; }
+ if (showVpn) { mSectionCountExcludingDeviceMgt++; }
+
+ // No work needed if there is no sections or more than 1 section
+ if (mSectionCountExcludingDeviceMgt != 1) {
+ return;
+ }
+ if (showCaCerts) {
+ dialogView.findViewById(R.id.ca_certs_subtitle).setVisibility(View.GONE);
+ }
+ if (showNetworkLogging) {
+ dialogView.findViewById(R.id.network_logging_subtitle).setVisibility(View.GONE);
+ }
+ if (showVpn) {
+ dialogView.findViewById(R.id.vpn_subtitle).setVisibility(View.GONE);
+ }
+ }
+
private String getSettingsButton() {
return mContext.getString(R.string.monitoring_button_view_policies);
}
import android.graphics.drawable.Drawable;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
+import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.qs.QSFooter;
import com.android.systemui.qs.QSPanel;
+import com.android.systemui.statusbar.car.UserGridView;
import com.android.systemui.statusbar.phone.MultiUserSwitch;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.UserInfoController;
*/
public class CarQSFooter extends RelativeLayout implements QSFooter,
UserInfoController.OnUserInfoChangedListener {
+ private static final String TAG = "CarQSFooter";
+
private UserInfoController mUserInfoController;
private MultiUserSwitch mMultiUserSwitch;
private ImageView mMultiUserAvatar;
+ private UserGridView mUserGridView;
public CarQSFooter(Context context, AttributeSet attrs) {
super(context, attrs);
mUserInfoController = Dependency.get(UserInfoController.class);
+ mMultiUserSwitch.setOnClickListener(v -> {
+ if (mUserGridView == null) {
+ Log.e(TAG, "CarQSFooter not properly set up; cannot display user switcher.");
+ return;
+ }
+
+ if (!mUserGridView.isShowing()) {
+ mUserGridView.show();
+ } else {
+ mUserGridView.hide();
+ }
+ });
+
findViewById(R.id.settings_button).setOnClickListener(v -> {
ActivityStarter activityStarter = Dependency.get(ActivityStarter.class);
}
}
+ public void setUserGridView(UserGridView view) {
+ mUserGridView = view;
+ }
+
@Override
public void setListening(boolean listening) {
if (listening) {
import android.view.View.OnClickListener;
import android.view.ViewGroup;
+import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.plugins.qs.QS;
import com.android.systemui.qs.QSFooter;
+import com.android.systemui.statusbar.car.UserGridView;
+import com.android.systemui.statusbar.policy.UserSwitcherController;
/**
* A quick settings fragment for the car. For auto, there is no row for quick settings or ability
*/
public class CarQSFragment extends Fragment implements QS {
private View mHeader;
- private QSFooter mFooter;
+ private CarQSFooter mFooter;
+ private UserGridView mUserGridView;
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
super.onViewCreated(view, savedInstanceState);
mHeader = view.findViewById(R.id.header);
mFooter = view.findViewById(R.id.qs_footer);
+
+ mUserGridView = view.findViewById(R.id.user_grid);
+ mUserGridView.init(null, Dependency.get(UserSwitcherController.class),
+ false /* showInitially */);
+
+ mFooter.setUserGridView(mUserGridView);
}
@Override
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.systemui.Dependency;
import com.android.systemui.EventLogConstants;
import com.android.systemui.EventLogTags;
import com.android.systemui.R;
import com.android.systemui.RecentsComponent;
import com.android.systemui.SystemUI;
-import com.android.systemui.plugins.PluginActivity;
-import com.android.systemui.plugins.PluginActivityManager;
import com.android.systemui.recents.events.EventBus;
import com.android.systemui.recents.events.activity.ConfigurationChangedEvent;
import com.android.systemui.recents.events.activity.DockedTopTaskEvent;
registerWithSystemUser();
}
putComponent(Recents.class, this);
- Dependency.get(PluginActivityManager.class).addActivityPlugin(RecentsImpl.RECENTS_ACTIVITY,
- PluginActivity.ACTION_RECENTS);
}
@Override
mParent = containerStub.inflate();
mContainer = mParent.findViewById(R.id.container);
mUserGridView = mContainer.findViewById(R.id.user_grid);
- mUserGridView.init(statusBar, mUserSwitcherController);
+ mUserGridView.init(statusBar, mUserSwitcherController, true /* showInitially */);
mUserGridView.setUserSelectionListener(record -> {
if (!record.isCurrent) {
toggleSwitchInProgress(true);
package com.android.systemui.statusbar.car;
+import android.animation.Animator;
+import android.animation.Animator.AnimatorListener;
+import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
-import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
-import android.os.UserHandle;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
+import android.support.v4.view.animation.FastOutSlowInInterpolator;
import android.util.AttributeSet;
-import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
-import com.android.internal.util.UserIcons;
import com.android.systemui.R;
-import com.android.systemui.statusbar.UserUtil;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.policy.UserSwitcherController;
* One of the uses of this is for the lock screen in auto.
*/
public class UserGridView extends ViewPager {
+ private static final int EXPAND_ANIMATION_TIME_MS = 200;
+ private static final int HIDE_ANIMATION_TIME_MS = 133;
+
private StatusBar mStatusBar;
private UserSwitcherController mUserSwitcherController;
private Adapter mAdapter;
private UserSelectionListener mUserSelectionListener;
+ private ValueAnimator mHeightAnimator;
+ private int mTargetHeight;
+ private int mHeightChildren;
+ private boolean mShowing;
public UserGridView(Context context, AttributeSet attrs) {
super(context, attrs);
}
- public void init(StatusBar statusBar, UserSwitcherController userSwitcherController) {
+ public void init(StatusBar statusBar, UserSwitcherController userSwitcherController,
+ boolean showInitially) {
mStatusBar = statusBar;
mUserSwitcherController = userSwitcherController;
mAdapter = new Adapter(mUserSwitcherController);
addOnLayoutChangeListener(mAdapter);
setAdapter(mAdapter);
+ mShowing = showInitially;
+ }
+
+ public boolean isShowing() {
+ return mShowing;
+ }
+
+ public void show() {
+ mShowing = true;
+ animateHeightChange(getMeasuredHeight(), mHeightChildren);
+ }
+
+ public void hide() {
+ mShowing = false;
+ animateHeightChange(getMeasuredHeight(), 0);
}
public void onUserSwitched(int newUserId) {
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// Wrap content doesn't work in ViewPagers, so simulate the behavior in code.
int height = 0;
- for(int i = 0; i < getChildCount(); i++) {
- View child = getChildAt(i);
- child.measure(widthMeasureSpec,
- MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
- height = Math.max(child.getMeasuredHeight(), height);
+ if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY) {
+ height = MeasureSpec.getSize(heightMeasureSpec);
+ } else {
+ for (int i = 0; i < getChildCount(); i++) {
+ View child = getChildAt(i);
+ child.measure(widthMeasureSpec,
+ MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
+ height = Math.max(child.getMeasuredHeight(), height);
+ }
+
+ mHeightChildren = height;
+
+ // Override the height if it's not showing.
+ if (!mShowing) {
+ height = 0;
+ }
+
+ // Respect the AT_MOST request from parent.
+ if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST) {
+ height = Math.min(MeasureSpec.getSize(heightMeasureSpec), height);
+ }
}
heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
+
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
+ private void animateHeightChange(int oldHeight, int newHeight) {
+ // If there is no change in height or an animation is already in progress towards the
+ // desired height, then there's no need to make any changes.
+ if (oldHeight == newHeight || newHeight == mTargetHeight) {
+ return;
+ }
+
+ // Animation in progress is not going towards the new target, so cancel it.
+ if (mHeightAnimator != null){
+ mHeightAnimator.cancel();
+ }
+
+ mTargetHeight = newHeight;
+ mHeightAnimator = ValueAnimator.ofInt(oldHeight, mTargetHeight);
+ mHeightAnimator.addUpdateListener(valueAnimator -> {
+ ViewGroup.LayoutParams layoutParams = getLayoutParams();
+ layoutParams.height = (Integer) valueAnimator.getAnimatedValue();
+ requestLayout();
+ });
+ mHeightAnimator.addListener(new AnimatorListener() {
+ @Override
+ public void onAnimationStart(Animator animator) {}
+
+ @Override
+ public void onAnimationEnd(Animator animator) {
+ // ValueAnimator does not guarantee that the update listener will get an update
+ // to the final value, so here, the final value is set. Though the final calculated
+ // height (mTargetHeight) could be set, WRAP_CONTENT is more appropriate.
+ ViewGroup.LayoutParams layoutParams = getLayoutParams();
+ layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT;
+ requestLayout();
+ mHeightAnimator = null;
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animator) {}
+
+ @Override
+ public void onAnimationRepeat(Animator animator) {}
+ });
+
+ mHeightAnimator.setInterpolator(new FastOutSlowInInterpolator());
+ if (oldHeight < newHeight) {
+ // Expanding
+ mHeightAnimator.setDuration(EXPAND_ANIMATION_TIME_MS);
+ } else {
+ // Hiding
+ mHeightAnimator.setDuration(HIDE_ANIMATION_TIME_MS);
+ }
+ mHeightAnimator.start();
+ }
+
/**
* This is a ViewPager.PagerAdapter which deletegates the work to a
* UserSwitcherController.BaseUserAdapter. Java doesn't support multiple inheritance so we have
package com.android.systemui.statusbar.notification;
+import android.content.Context;
import android.graphics.Color;
+import android.os.UserHandle;
+import android.provider.Settings;
import android.view.View;
import android.widget.ImageView;
offsetView.getLocationOnScreen(sLocationOffset);
return sLocationOffset[1] - sLocationBase[1];
}
+
+ public static boolean isHapticFeedbackDisabled(Context context) {
+ return Settings.System.getIntForUser(context.getContentResolver(),
+ Settings.System.HAPTIC_FEEDBACK_ENABLED, 0, UserHandle.USER_CURRENT) == 0;
+ }
+
}
private boolean mFullyPulsing;
private float mAodFrontScrimOpacity = 0;
+ private Runnable mSetDozeInFrontAlphaDelayed;
public DozeScrimController(ScrimController scrimController, Context context) {
mContext = context;
mDozingAborted = false;
abortAnimations();
mScrimController.setDozeBehindAlpha(1f);
- mScrimController.setDozeInFrontAlpha(
- mDozeParameters.getAlwaysOn() ? mAodFrontScrimOpacity : 1f);
+ setDozeInFrontAlpha(mDozeParameters.getAlwaysOn() ? mAodFrontScrimOpacity : 1f);
} else {
cancelPulsing();
if (animate) {
} else {
abortAnimations();
mScrimController.setDozeBehindAlpha(0f);
- mScrimController.setDozeInFrontAlpha(0f);
+ setDozeInFrontAlpha(0f);
}
}
}
mAodFrontScrimOpacity = scrimOpacity;
if (mDozing && !isPulsing() && !mDozingAborted && !mWakeAndUnlocking
&& mDozeParameters.getAlwaysOn()) {
- mScrimController.setDozeInFrontAlpha(mAodFrontScrimOpacity);
+ setDozeInFrontAlpha(mAodFrontScrimOpacity);
}
}
if (!mWakeAndUnlocking) {
mWakeAndUnlocking = true;
mScrimController.setDozeBehindAlpha(0f);
- mScrimController.setDozeInFrontAlpha(0f);
+ setDozeInFrontAlpha(0f);
}
}
// be invoked when we're done so that the caller can drop the pulse wakelock.
mPulseCallback = callback;
mPulseReason = reason;
- mScrimController.setDozeInFrontAlpha(1f);
+ setDozeInFrontAlpha(1f);
mHandler.post(mPulseIn);
}
cancelPulsing();
if (mDozing && !mWakeAndUnlocking) {
mScrimController.setDozeBehindAlpha(1f);
- mScrimController.setDozeInFrontAlpha(
- mDozeParameters.getAlwaysOn() && !mDozingAborted ?
- mAodFrontScrimOpacity : 1f);
+ setDozeInFrontAlpha(mDozeParameters.getAlwaysOn() && !mDozingAborted
+ ? mAodFrontScrimOpacity : 1f);
}
}
: mScrimController.getDozeBehindAlpha();
}
+ private void setDozeInFrontAlpha(float opacity) {
+ setDozeInFrontAlphaDelayed(opacity, 0 /* delay */);
+
+ }
+
+ private void setDozeInFrontAlphaDelayed(float opacity, long delayMs) {
+ if (mSetDozeInFrontAlphaDelayed != null) {
+ mHandler.removeCallbacks(mSetDozeInFrontAlphaDelayed);
+ mSetDozeInFrontAlphaDelayed = null;
+ }
+ if (delayMs < 0) {
+ mScrimController.setDozeInFrontAlpha(opacity);
+ } else {
+ mHandler.postDelayed(mSetDozeInFrontAlphaDelayed = () -> {
+ setDozeInFrontAlpha(opacity);
+ }, delayMs);
+ }
+ }
+
private final Runnable mPulseIn = new Runnable() {
@Override
public void run() {
// Signal that the pulse is all finished so we can turn the screen off now.
DozeScrimController.this.pulseFinished();
if (mDozeParameters.getAlwaysOn()) {
- mScrimController.setDozeInFrontAlpha(mAodFrontScrimOpacity);
+ // Setting power states can happen after we push out the frame. Make sure we
+ // stay fully opaque until the power state request reaches the lower levels.
+ setDozeInFrontAlphaDelayed(mAodFrontScrimOpacity, 30);
}
}
};
if (mAccessibilityController == null) {
return;
}
- boolean clickToUnlock = mAccessibilityController.isTouchExplorationEnabled();
+ boolean clickToUnlock = mAccessibilityController.isAccessibilityEnabled();
boolean clickToForceLock = mUnlockMethodCache.isTrustManaged()
- && !mAccessibilityController.isAccessibilityEnabled();
+ && !clickToUnlock;
boolean longClickToForceLock = mUnlockMethodCache.isTrustManaged()
&& !clickToForceLock;
setClickable(clickToForceLock || clickToUnlock);
package com.android.systemui.statusbar.phone;
+import static com.android.systemui.statusbar.notification.NotificationUtils.isHapticFeedbackDisabled;
+
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.drawable.Icon;
+import android.os.AsyncTask;
+import android.os.UserHandle;
import android.os.VibrationEffect;
import android.os.Vibrator;
+import android.provider.Settings;
import android.support.v4.util.ArrayMap;
import android.support.v4.util.ArraySet;
import android.util.AttributeSet;
import com.android.systemui.R;
import com.android.systemui.statusbar.AlphaOptimizedFrameLayout;
import com.android.systemui.statusbar.StatusBarIconView;
+import com.android.systemui.statusbar.notification.NotificationUtils;
import com.android.systemui.statusbar.stack.AnimationFilter;
import com.android.systemui.statusbar.stack.AnimationProperties;
import com.android.systemui.statusbar.stack.StackStateAnimator;
boolean wasInShelf = icon.isInShelf();
boolean inShelf = iconAppearAmount == 1.0f;
icon.setIsInShelf(inShelf);
- if (mVibrateOnAnimation && !justAdded && mAnimationsEnabled
- && wasInShelf != inShelf) {
- mVibrator.vibrate(VibrationEffect.get(VibrationEffect.EFFECT_TICK));
+ if (shouldVibrateChange(wasInShelf != inShelf)) {
+ AsyncTask.execute(
+ () -> mVibrator.vibrate(VibrationEffect.get(
+ VibrationEffect.EFFECT_TICK)));
}
}
justAdded = false;
justUndarkened = false;
}
+ private boolean shouldVibrateChange(boolean inShelfChanged) {
+ if (!mVibrateOnAnimation) {
+ return false;
+ }
+ if (justAdded) {
+ return false;
+ }
+ if (!mAnimationsEnabled) {
+ return false;
+ }
+ if (!inShelfChanged) {
+ return false;
+ }
+ if (isHapticFeedbackDisabled(mContext)) {
+ return false;
+ }
+ return true;
+ }
+
public boolean hasCustomTransformHeight() {
return isLastExpandIcon && customTransformHeight != NO_VALUE;
}
package com.android.systemui.statusbar.phone;
+import static com.android.systemui.statusbar.notification.NotificationUtils.isHapticFeedbackDisabled;
+
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
+import android.os.AsyncTask;
import android.os.SystemClock;
+import android.os.UserHandle;
import android.os.VibrationEffect;
import android.os.Vibrator;
+import android.provider.Settings;
import android.util.AttributeSet;
import android.util.Log;
import android.view.InputDevice;
import com.android.systemui.doze.DozeLog;
import com.android.systemui.statusbar.FlingAnimationUtils;
import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.notification.NotificationUtils;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import java.io.FileDescriptor;
private float mMinExpandHeight;
private LockscreenGestureLogger mLockscreenGestureLogger = new LockscreenGestureLogger();
private boolean mPanelUpdateWhenAnimatorEnds;
+ private boolean mVibrateOnOpening;
private final void logf(String fmt, Object... args) {
Log.v(TAG, (mViewName != null ? (mViewName + ": ") : "") + String.format(fmt, args));
mNotificationsDragEnabled =
getResources().getBoolean(R.bool.config_enableNotificationShadeDrag);
mVibrator = mContext.getSystemService(Vibrator.class);
+ mVibrateOnOpening = mContext.getResources().getBoolean(
+ R.bool.config_vibrateOnIconAnimation);
}
protected void loadDimens() {
runPeekAnimation(INITIAL_OPENING_PEEK_DURATION, getOpeningHeight(),
false /* collapseWhenFinished */);
notifyBarPanelExpansionChanged();
- mVibrator.vibrate(VibrationEffect.get(VibrationEffect.EFFECT_CLICK));
+ if (mVibrateOnOpening && !isHapticFeedbackDisabled(mContext)) {
+ AsyncTask.execute(
+ () -> mVibrator.vibrate(VibrationEffect.get(VibrationEffect.EFFECT_TICK)));
+ }
}
protected abstract float getOpeningHeight();
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
+import android.support.test.annotation.UiThreadTest;
+import android.support.test.runner.AndroidJUnit4;
import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.systemui.Dependency;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.plugins.PluginInstanceManager.PluginInfo;
import com.android.systemui.plugins.annotations.ProvidesInterface;
+import com.android.systemui.plugins.PluginInstanceManager.PluginInfo;
import com.android.systemui.plugins.PluginManagerImpl.PluginInstanceManagerFactory;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import android.support.test.runner.AndroidJUnit4;
import android.test.suitebuilder.annotation.SmallTest;
import android.text.SpannableStringBuilder;
+import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
mFooter.getVpnMessage(false, true, VPN_PACKAGE, null));
}
+ @Test
+ public void testConfigSubtitleVisibility() {
+ View view = LayoutInflater.from(mContext)
+ .inflate(R.layout.quick_settings_footer_dialog, null);
+
+ // Device Management subtitle should be shown when there is Device Management section only
+ // Other sections visibility will be set somewhere else so it will not be tested here
+ mFooter.configSubtitleVisibility(true, false, false, false, view);
+ assertEquals(View.VISIBLE,
+ view.findViewById(R.id.device_management_subtitle).getVisibility());
+
+ // If there are multiple sections, all subtitles should be shown
+ mFooter.configSubtitleVisibility(true, true, false, false, view);
+ assertEquals(View.VISIBLE,
+ view.findViewById(R.id.device_management_subtitle).getVisibility());
+ assertEquals(View.VISIBLE,
+ view.findViewById(R.id.ca_certs_subtitle).getVisibility());
+
+ // If there are multiple sections, all subtitles should be shown
+ mFooter.configSubtitleVisibility(true, true, true, true, view);
+ assertEquals(View.VISIBLE,
+ view.findViewById(R.id.device_management_subtitle).getVisibility());
+ assertEquals(View.VISIBLE,
+ view.findViewById(R.id.ca_certs_subtitle).getVisibility());
+ assertEquals(View.VISIBLE,
+ view.findViewById(R.id.network_logging_subtitle).getVisibility());
+ assertEquals(View.VISIBLE,
+ view.findViewById(R.id.vpn_subtitle).getVisibility());
+
+ // If there are multiple sections, all subtitles should be shown, event if there is no
+ // Device Management section
+ mFooter.configSubtitleVisibility(false, true, true, true, view);
+ assertEquals(View.VISIBLE,
+ view.findViewById(R.id.ca_certs_subtitle).getVisibility());
+ assertEquals(View.VISIBLE,
+ view.findViewById(R.id.network_logging_subtitle).getVisibility());
+ assertEquals(View.VISIBLE,
+ view.findViewById(R.id.vpn_subtitle).getVisibility());
+
+ // If there is only 1 section, the title should be hidden
+ mFooter.configSubtitleVisibility(false, true, false, false, view);
+ assertEquals(View.GONE,
+ view.findViewById(R.id.ca_certs_subtitle).getVisibility());
+ mFooter.configSubtitleVisibility(false, false, true, false, view);
+ assertEquals(View.GONE,
+ view.findViewById(R.id.network_logging_subtitle).getVisibility());
+ mFooter.configSubtitleVisibility(false, false, false, true, view);
+ assertEquals(View.GONE,
+ view.findViewById(R.id.vpn_subtitle).getVisibility());
+ }
+
private CharSequence addLink(CharSequence description) {
final SpannableStringBuilder message = new SpannableStringBuilder();
message.append(description);
package com.android.systemui.utils.leaks;
+import android.content.Context;
import android.testing.LeakCheck;
import com.android.systemui.plugins.Plugin;
void onTimeout(RemoteFillService remoteService) {
// NOTE: Must make these 2 calls asynchronously, because the cancellation signal is
// handled by the service, which could block.
- remoteService.dispatchOnFillTimeout(mCancellation);
+ final ICancellationSignal cancellation = mCancellation;
+ if (cancellation != null) {
+ remoteService.dispatchOnFillTimeout(cancellation);
+ }
remoteService.dispatchOnFillRequestFailure(PendingFillRequest.this, null);
}
*/
private void updateCapabilities(
int oldScore, NetworkAgentInfo nai, NetworkCapabilities networkCapabilities) {
- // Sanity check: a NetworkAgent should not change its static capabilities or parameters.
- if (nai.everConnected) {
+ // Once a NetworkAgent is connected, complain if some immutable capabilities are removed.
+ if (nai.everConnected &&
+ !nai.networkCapabilities.satisfiedByNetworkCapabilities(networkCapabilities)) {
+ // TODO: consider not complaining when a network agent degrade its capabilities if this
+ // does not cause any request (that is not a listen) currently matching that agent to
+ // stop being matched by the updated agent.
String diff = nai.networkCapabilities.describeImmutableDifferences(networkCapabilities);
if (!TextUtils.isEmpty(diff)) {
- Slog.wtf(TAG, "BUG: " + nai + " changed immutable capabilities:" + diff);
+ Slog.wtf(TAG, "BUG: " + nai + " lost immutable capabilities:" + diff);
}
}
import static android.app.ActivityManager.RESIZE_MODE_PRESERVE_WINDOW;
import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.StackId.FIRST_DYNAMIC_STACK_ID;
import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
}
final void applyUpdateVrModeLocked(ActivityRecord r) {
+ // VR apps are expected to run in a main display. If an app is turning on VR for
+ // itself, but lives in a dynamic stack, then make sure that it is moved to the main
+ // fullscreen stack before enabling VR Mode.
+ // TODO: The goal of this code is to keep the VR app on the main display. When the
+ // stack implementation changes in the future, keep in mind that the use of the fullscreen
+ // stack is a means to move the activity to the main display and a moveActivityToDisplay()
+ // option would be a better choice here.
+ if (r.requestedVrComponent != null && r.getStackId() >= FIRST_DYNAMIC_STACK_ID) {
+ Slog.i(TAG, "Moving " + r.shortComponentName + " from stack " + r.getStackId()
+ + " to main stack for VR");
+ moveTaskToStack(r.getTask().taskId, FULLSCREEN_WORKSPACE_STACK_ID, true /* toTop */);
+ }
mHandler.sendMessage(
mHandler.obtainMessage(VR_MODE_CHANGE_MSG, 0, 0, r));
}
// the user leaves that mode.
mLastReportedMultiWindowMode = !task.mFullscreen;
mLastReportedPictureInPictureMode = (task.getStackId() == PINNED_STACK_ID);
-
- onOverrideConfigurationSent();
}
void removeWindowContainer() {
* a new merged configuration is sent to the client for this activity.
*/
void setLastReportedConfiguration(@NonNull MergedConfiguration config) {
- mLastReportedConfiguration.setTo(config);
+ setLastReportedConfiguration(config.getGlobalConfiguration(),
+ config.getOverrideConfiguration());
}
- /** Call when override config was sent to the Window Manager to update internal records. */
- // TODO(b/36505427): Why do we set last reported based on sending the config to WM? Seems like
- // we should only set this when we actually report to the activity which is what the method
- // setLastReportedMergedOverrideConfiguration() does. Investigate if this is really needed.
- void onOverrideConfigurationSent() {
- mLastReportedConfiguration.setOverrideConfiguration(getMergedOverrideConfiguration());
+ void setLastReportedConfiguration(Configuration global, Configuration override) {
+ mLastReportedConfiguration.setConfiguration(global, override);
}
@Override
return;
}
mWindowContainerController.onOverrideConfigurationChanged(newConfig, mBounds);
- // TODO(b/36505427): Can we consolidate the call points of onOverrideConfigurationSent()
- // to just use this method instead?
- onOverrideConfigurationSent();
}
// TODO(b/36505427): Consider moving this method and similar ones to ConfigurationContainer.
// Update last reported values.
final Configuration newMergedOverrideConfig = getMergedOverrideConfiguration();
- mLastReportedConfiguration.setConfiguration(service.getGlobalConfiguration(),
- newMergedOverrideConfig);
+
+ setLastReportedConfiguration(service.getGlobalConfiguration(), newMergedOverrideConfig);
if (changes == 0 && !forceNewConfig) {
if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
+import static android.provider.Settings.Global.DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES;
import static android.provider.Settings.Secure.USER_SETUP_COMPLETE;
import static android.view.Display.DEFAULT_DISPLAY;
// created controller for the activity we are starting yet.
mWindowContainerController.positionChildAt(appController, index);
}
- r.onOverrideConfigurationSent();
// Make sure the list of display UID whitelists is updated
// now that this record is in a new task.
// A task can not be docked even if it is considered resizeable because it only supports
// picture-in-picture mode but has a non-resizeable resizeMode
return mService.mSupportsSplitScreenMultiWindow
- && isResizeable(false /* checkSupportsPip */)
- && !ActivityInfo.isPreserveOrientationMode(mResizeMode);
+ && (mService.mForceResizableActivities
+ || (isResizeable(false /* checkSupportsPip */)
+ && !ActivityInfo.isPreserveOrientationMode(mResizeMode)));
}
/**
import static android.Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE;
import static android.Manifest.permission.READ_CONTACTS;
import static android.content.Context.KEYGUARD_SERVICE;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT;
import static com.android.internal.widget.LockPatternUtils.SYNTHETIC_PASSWORD_ENABLED_KEY;
import android.service.gatekeeper.IGateKeeperService;
import android.text.TextUtils;
import android.util.ArrayMap;
+import android.util.EventLog;
import android.util.Log;
import android.util.Slog;
@Override // binder interface
public void systemReady() {
+ if (mContext.checkCallingOrSelfPermission(PERMISSION) != PERMISSION_GRANTED) {
+ EventLog.writeEvent(0x534e4554, "28251513", getCallingUid(), ""); // SafetyNet
+ }
+ checkWritePermission(UserHandle.USER_SYSTEM);
migrateOldData();
try {
getGateKeeperService();
mContext.enforceCallingOrSelfPermission(PERMISSION, "LockSettingsRead");
}
+ private final void checkPasswordHavePermission(int userId) {
+ if (mContext.checkCallingOrSelfPermission(PERMISSION) != PERMISSION_GRANTED) {
+ EventLog.writeEvent(0x534e4554, "28251513", getCallingUid(), ""); // SafetyNet
+ }
+ mContext.enforceCallingOrSelfPermission(PERMISSION, "LockSettingsHave");
+ }
+
private final void checkReadPermission(String requestedKey, int userId) {
final int callingUid = Binder.getCallingUid();
@Override
public boolean havePassword(int userId) throws RemoteException {
+ checkPasswordHavePermission(userId);
synchronized (mSpManager) {
if (isSyntheticPasswordBasedCredentialLocked(userId)) {
long handle = getSyntheticPasswordHandleLocked(userId);
@Override
public boolean havePattern(int userId) throws RemoteException {
+ checkPasswordHavePermission(userId);
synchronized (mSpManager) {
if (isSyntheticPasswordBasedCredentialLocked(userId)) {
long handle = getSyntheticPasswordHandleLocked(userId);
updateRestrictBackgroundRulesOnUidStatusChangedUL(uid, oldUidState, uidState);
if (isProcStateAllowedWhileIdleOrPowerSaveMode(oldUidState)
!= isProcStateAllowedWhileIdleOrPowerSaveMode(uidState) ) {
- if (isUidIdle(uid)) {
- updateRuleForAppIdleUL(uid);
- }
+ updateRuleForAppIdleUL(uid);
if (mDeviceIdleMode) {
updateRuleForDeviceIdleUL(uid);
}
@Override
public void onServiceDisconnected(ComponentName name) {
+ mServicesBinding.remove(servicesBindingTag);
Slog.v(TAG, getCaption() + " connection lost: " + name);
}
};
return;
}
} catch (SecurityException ex) {
+ mServicesBinding.remove(servicesBindingTag);
Slog.e(TAG, "Unable to bind " + getCaption() + " service: " + intent, ex);
}
}
public void onReceive(Context context, Intent intent) {
if (Intent.ACTION_LOCALE_CHANGED.equals(intent.getAction())) {
mZenModeHelper.updateDefaultZenRules();
+ mRankingHelper.onLocaleChanged(context, ActivityManager.getCurrentUser());
}
}
};
}
}
if (summaryRecord != null && checkDisqualifyingFeatures(userId, MY_UID,
- summaryRecord.sbn.getId(), summaryRecord.sbn.getTag(), summaryRecord)) {
+ summaryRecord.sbn.getId(), summaryRecord.sbn.getTag(), summaryRecord, true)) {
mHandler.post(new EnqueueNotificationRunnable(userId, summaryRecord));
}
}
user, null, System.currentTimeMillis());
final NotificationRecord r = new NotificationRecord(getContext(), n, channel);
- if (!checkDisqualifyingFeatures(userId, notificationUid, id, tag, r)) {
+ if (!checkDisqualifyingFeatures(userId, notificationUid, id, tag, r,
+ r.sbn.getOverrideGroupKey() != null)) {
return;
}
* Has side effects.
*/
private boolean checkDisqualifyingFeatures(int userId, int callingUid, int id, String tag,
- NotificationRecord r) {
+ NotificationRecord r, boolean isAutogroup) {
final String pkg = r.sbn.getPackageName();
final String dialerPackage =
getContext().getSystemService(TelecomManager.class).getSystemDialerPackage();
// rate limit updates that aren't completed progress notifications
if (mNotificationsByKey.get(r.sbn.getKey()) != null
- && !r.getNotification().hasCompletedProgress()) {
+ && !r.getNotification().hasCompletedProgress()
+ && !isAutogroup) {
final float appEnqueueRate = mUsageStats.getAppEnqueueRate(pkg);
if (appEnqueueRate > mMaxPackageEnqueueRate) {
final long now = SystemClock.elapsedRealtime();
if ((now - mLastOverRateLogTime) > MIN_PACKAGE_OVERRATE_LOG_INTERVAL) {
Slog.e(TAG, "Package enqueue rate is " + appEnqueueRate
- + ". Shedding events. package=" + pkg);
+ + ". Shedding " + r.sbn.getKey() + ". package=" + pkg);
mLastOverRateLogTime = now;
}
return false;
}
}
+ protected void onLocaleChanged(Context context, int userId) {
+ synchronized (mRecords) {
+ int N = mRecords.size();
+ for (int i = 0; i < N; i++) {
+ Record record = mRecords.valueAt(i);
+ if (UserHandle.getUserId(record.uid) == userId) {
+ if (record.channels.containsKey(NotificationChannel.DEFAULT_CHANNEL_ID)) {
+ record.channels.get(NotificationChannel.DEFAULT_CHANNEL_ID).setName(
+ context.getResources().getString(
+ R.string.default_notification_channel_label));
+ }
+ }
+ }
+ }
+ }
+
public void onPackagesChanged(boolean removingPackage, int changeUserId, String[] pkgList,
int[] uidList) {
if (pkgList == null || pkgList.length == 0) {
pw.print(" enabled=");
pw.print(ps.getEnabled(user.id));
pw.print(" instant=");
- pw.println(ps.getInstantApp(user.id));
+ pw.print(ps.getInstantApp(user.id));
pw.print(" virtual=");
pw.println(ps.getVirtulalPreload(user.id));
mContainer.startingSurface = null;
mContainer.startingWindow = null;
mContainer.startingDisplayed = false;
- if (surface == null && DEBUG_STARTING_WINDOW) {
- Slog.v(TAG_WM, "startingWindow was set but startingSurface==null, couldn't "
- + "remove");
+ if (surface == null) {
+ if (DEBUG_STARTING_WINDOW) {
+ Slog.v(TAG_WM, "startingWindow was set but startingSurface==null, couldn't "
+ + "remove");
+ }
+ return;
}
} else {
if (DEBUG_STARTING_WINDOW) {
import android.app.NotificationManager;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
+import android.content.res.Resources;
import android.graphics.Color;
import android.media.AudioAttributes;
import android.net.Uri;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
when(mPm.getPackageUidAsUser(eq(UPDATED_PKG), anyInt())).thenReturn(UID2);
when(mContext.getResources()).thenReturn(
InstrumentationRegistry.getContext().getResources());
+ when(mContext.getContentResolver()).thenReturn(
+ InstrumentationRegistry.getContext().getContentResolver());
when(mContext.getPackageManager()).thenReturn(mPm);
when(mContext.getApplicationInfo()).thenReturn(legacy);
// most tests assume badging is enabled
assertFalse(mHelper.badgingEnabled(USER));
assertTrue(mHelper.badgingEnabled(USER2));
}
+
+ @Test
+ public void testOnLocaleChanged_updatesDefaultChannels() throws Exception {
+ String newLabel = "bananas!";
+ final NotificationChannel defaultChannel = mHelper.getNotificationChannel(PKG, UID,
+ NotificationChannel.DEFAULT_CHANNEL_ID, false);
+ assertFalse(newLabel.equals(defaultChannel.getName()));
+
+ Resources res = mock(Resources.class);
+ when(mContext.getResources()).thenReturn(res);
+ when(res.getString(com.android.internal.R.string.default_notification_channel_label))
+ .thenReturn(newLabel);
+
+ mHelper.onLocaleChanged(mContext, USER.getIdentifier());
+
+ assertEquals(newLabel, mHelper.getNotificationChannel(PKG, UID,
+ NotificationChannel.DEFAULT_CHANNEL_ID, false).getName());
+ }
}
* @return A string containing text sent by the remote user, or {@code null} if the
* conversation has been terminated or if there was an error while reading.
*/
- public String read() throws IOException {
- int numRead = mReceiveStream.read(mReadBuffer, 0, READ_BUFFER_SIZE);
- if (numRead < 0) {
+ public String read() {
+ try {
+ int numRead = mReceiveStream.read(mReadBuffer, 0, READ_BUFFER_SIZE);
+ if (numRead < 0) {
+ return null;
+ }
+ return new String(mReadBuffer, 0, numRead);
+ } catch (IOException e) {
+ Log.w(this, "Exception encountered when reading from InputStreamReader: %s", e);
return null;
}
- return new String(mReadBuffer, 0, numRead);
}
/**
*/
public String readImmediately() throws IOException {
if (mReceiveStream.ready()) {
- return read();
+ int numRead = mReceiveStream.read(mReadBuffer, 0, READ_BUFFER_SIZE);
+ if (numRead < 0) {
+ return null;
+ }
+ return new String(mReadBuffer, 0, numRead);
} else {
return null;
}
"carrier_data_call_retry_config_strings";
/**
- * Delay between trying APN from the pool
+ * Delay in milliseconds between trying APN from the pool
* @hide
*/
public static final String KEY_CARRIER_DATA_CALL_APN_DELAY_DEFAULT_LONG =
"carrier_data_call_apn_delay_default_long";
/**
- * Faster delay between trying APN from the pool
+ * Faster delay in milliseconds between trying APN from the pool
* @hide
*/
public static final String KEY_CARRIER_DATA_CALL_APN_DELAY_FASTER_LONG =
"carrier_data_call_apn_delay_faster_long";
/**
+ * Delay in milliseconds for retrying APN after disconnect
+ * @hide
+ */
+ public static final String KEY_CARRIER_DATA_CALL_APN_RETRY_AFTER_DISCONNECT_LONG =
+ "carrier_data_call_apn_retry_after_disconnect_long";
+
+ /**
* Data call setup permanent failure causes by the carrier
*/
public static final String KEY_CARRIER_DATA_CALL_PERMANENT_FAILURE_STRINGS =
/** @hide */
public static final int CDMA_ROAMING_MODE_AFFILIATED = 1;
/** @hide */
- public static final int IMSI_ENCRYPTION_DAYS_TIME_DISABLED = -1;
- /** @hide */
public static final int CDMA_ROAMING_MODE_ANY = 2;
/**
* Boolean indicating if support is provided for directly dialing FDN number from FDN list.
public static final String IMSI_KEY_DOWNLOAD_URL_STRING = "imsi_key_download_url_string";
/**
- * Time in days, after which the key will expire, and a new key will need to be downloaded.
- * default value is {@link IMSI_ENCRYPTION_DAYS_TIME_DISABLED}, and indicates that IMSI
- * encryption is not enabled by default for a carrier. Value of 0 indicates that the key
- * does not expire.
+ * Identifies if the key is available for WLAN or EPDG or both. The value is a bitmask.
+ * 0 indicates that neither EPDG or WLAN is enabled.
+ * 1 indicates that key type {@link TelephonyManager#KEY_TYPE_EPDG} is enabled.
+ * 2 indicates that key type {@link TelephonyManager#KEY_TYPE_WLAN} is enabled.
+ * 3 indicates that both are enabled.
* @hide
*/
- public static final String IMSI_KEY_EXPIRATION_DAYS_TIME_INT =
- "imsi_key_expiration_days_time_int";
+ public static final String IMSI_KEY_AVAILABILITY_INT = "imsi_key_availability_int";
+
/**
* Key identifying if the CDMA Caller ID presentation and suppression MMI codes
"others:max_retries=3, 5000, 5000, 5000"});
sDefaults.putLong(KEY_CARRIER_DATA_CALL_APN_DELAY_DEFAULT_LONG, 20000);
sDefaults.putLong(KEY_CARRIER_DATA_CALL_APN_DELAY_FASTER_LONG, 3000);
+ sDefaults.putLong(KEY_CARRIER_DATA_CALL_APN_RETRY_AFTER_DISCONNECT_LONG, 10000);
sDefaults.putString(KEY_CARRIER_ERI_FILE_NAME_STRING, "eri.xml");
sDefaults.putInt(KEY_DURATION_BLOCKING_DISABLED_AFTER_EMERGENCY_INT, 7200);
sDefaults.putStringArray(KEY_CARRIER_METERED_APN_TYPES_STRINGS,
sDefaults.putInt(KEY_LTE_EARFCNS_RSRP_BOOST_INT, 0);
sDefaults.putStringArray(KEY_BOOSTED_LTE_EARFCNS_STRING_ARRAY, null);
sDefaults.putBoolean(KEY_DISABLE_VOICE_BARRING_NOTIFICATION_BOOL, false);
- sDefaults.putInt(IMSI_KEY_EXPIRATION_DAYS_TIME_INT, IMSI_ENCRYPTION_DAYS_TIME_DISABLED);
+ sDefaults.putInt(IMSI_KEY_AVAILABILITY_INT, 0);
sDefaults.putString(IMSI_KEY_DOWNLOAD_URL_STRING, null);
sDefaults.putBoolean(KEY_CONVERT_CDMA_CALLER_ID_MMI_CODES_WHILE_ROAMING_ON_3GPP_BOOL,
false);
return rtString;
}
+ /**
+ * Convert RIL Service State to String
+ *
+ * @param serviceState
+ * @return String representation of the ServiceState
+ *
+ * @hide
+ */
+ public static String rilServiceStateToString(int serviceState) {
+ switch(serviceState) {
+ case STATE_IN_SERVICE:
+ return "IN_SERVICE";
+ case STATE_OUT_OF_SERVICE:
+ return "OUT_OF_SERVICE";
+ case STATE_EMERGENCY_ONLY:
+ return "EMERGENCY_ONLY";
+ case STATE_POWER_OFF:
+ return "POWER_OFF";
+ default:
+ return "UNKNOWN";
+ }
+ }
+
@Override
public String toString() {
- String radioTechnology = rilRadioTechnologyToString(mRilVoiceRadioTechnology);
- String dataRadioTechnology = rilRadioTechnologyToString(mRilDataRadioTechnology);
-
- return (mVoiceRegState + " " + mDataRegState
- + " "
- + "voice " + getRoamingLogString(mVoiceRoamingType)
- + " "
- + "data " + getRoamingLogString(mDataRoamingType)
- + " " + mVoiceOperatorAlphaLong
- + " " + mVoiceOperatorAlphaShort
- + " " + mVoiceOperatorNumeric
- + " " + mDataOperatorAlphaLong
- + " " + mDataOperatorAlphaShort
- + " " + mDataOperatorNumeric
- + " " + (mIsManualNetworkSelection ? "(manual)" : "")
- + " " + radioTechnology
- + " " + dataRadioTechnology
- + " " + (mCssIndicator ? "CSS supported" : "CSS not supported")
- + " " + mNetworkId
- + " " + mSystemId
- + " RoamInd=" + mCdmaRoamingIndicator
- + " DefRoamInd=" + mCdmaDefaultRoamingIndicator
- + " EmergOnly=" + mIsEmergencyOnly
- + " IsDataRoamingFromRegistration=" + mIsDataRoamingFromRegistration
- + " IsUsingCarrierAggregation=" + mIsUsingCarrierAggregation
- + " mLteEarfcnRsrpBoost=" + mLteEarfcnRsrpBoost);
+ return new StringBuilder().append("{mVoiceRegState=").append(mVoiceRegState)
+ .append("(" + rilServiceStateToString(mVoiceRegState) + ")")
+ .append(", mDataRegState=").append(mDataRegState)
+ .append("(" + rilServiceStateToString(mDataRegState) + ")")
+ .append(", mVoiceRoamingType=").append(getRoamingLogString(mVoiceRoamingType))
+ .append(", mDataRoamingType=").append(getRoamingLogString(mDataRoamingType))
+ .append(", mVoiceOperatorAlphaLong=").append(mVoiceOperatorAlphaLong)
+ .append(", mVoiceOperatorAlphaShort=").append(mVoiceOperatorAlphaShort)
+ .append(", mDataOperatorAlphaLong=").append(mDataOperatorAlphaLong)
+ .append(", mDataOperatorAlphaShort=").append(mDataOperatorAlphaShort)
+ .append(", isManualNetworkSelection=").append(mIsManualNetworkSelection)
+ .append(mIsManualNetworkSelection ? "(manual)" : "(automatic)")
+ .append(", mRilVoiceRadioTechnology=").append(mRilVoiceRadioTechnology)
+ .append("(" + rilRadioTechnologyToString(mRilVoiceRadioTechnology) + ")")
+ .append(", mRilDataRadioTechnology=").append(mRilDataRadioTechnology)
+ .append("(" + rilRadioTechnologyToString(mRilDataRadioTechnology) + ")")
+ .append(", mCssIndicator=").append(mCssIndicator ? "supported" : "unsupported")
+ .append(", mNetworkId=").append(mNetworkId)
+ .append(", mSystemId=").append(mSystemId)
+ .append(", mCdmaRoamingIndicator=").append(mCdmaRoamingIndicator)
+ .append(", mCdmaDefaultRoamingIndicator=").append(mCdmaDefaultRoamingIndicator)
+ .append(", mIsEmergencyOnly=").append(mIsEmergencyOnly)
+ .append(", mIsDataRoamingFromRegistration=").append(mIsDataRoamingFromRegistration)
+ .append(", mIsUsingCarrierAggregation=").append(mIsUsingCarrierAggregation)
+ .append(", mLteEarfcnRsrpBoost=").append(mLteEarfcnRsrpBoost)
+ .append("}").toString();
}
private void setNullState(int state) {
/** @hide */
- static public final int KEY_TYPE_EPDDG = 1;
+ static public final int KEY_TYPE_EPDG = 1;
/** @hide */
static public final int KEY_TYPE_WLAN = 2;
* Requires Permission:
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
* @param keyType whether the key is being used for wlan or epdg. Valid key types are
- * {@link TelephonyManager#KEY_TYPE_EPDDG} or
+ * {@link TelephonyManager#KEY_TYPE_EPDG} or
* {@link TelephonyManager#KEY_TYPE_WLAN}.
* @return ImsiEncryptionInfo Carrier specific information that will be used to encrypt the
* IMSI and IMPI. This includes the public key and the key identifier. This information
- * will be stored in the device keystore.
+ * will be stored in the device keystore. The system will return a null when no key was
+ * found, and the carrier does not require a key. The system will throw the following
+ * exceptions:
+ * 1. IllegalArgumentException when an invalid key is sent.
+ * 2. RuntimeException if the key is required but not found; and also if there was an
+ * internal exception.
* @hide
*/
public ImsiEncryptionInfo getCarrierInfoForImsiEncryption(int keyType) {
try {
IPhoneSubInfo info = getSubscriberInfo();
- if (info == null) return null;
+ if (info == null) {
+ throw new RuntimeException("IMSI error: Subscriber Info is null");
+ }
int subId = getSubId(SubscriptionManager.getDefaultDataSubscriptionId());
- if (keyType != KEY_TYPE_EPDDG && keyType != KEY_TYPE_WLAN) {
- throw new IllegalArgumentException("Invalid key type");
+ if (keyType != KEY_TYPE_EPDG && keyType != KEY_TYPE_WLAN) {
+ throw new IllegalArgumentException("IMSI error: Invalid key type");
+ }
+ ImsiEncryptionInfo imsiEncryptionInfo = info.getCarrierInfoForImsiEncryption(
+ subId, keyType, mContext.getOpPackageName());
+ if (imsiEncryptionInfo == null
+ && isImsiEncryptionRequired(subId, keyType)) {
+ Rlog.e(TAG, "IMSI error: key is required but not found");
+ throw new RuntimeException("IMSI error: key is required but not found");
}
- return info.getCarrierInfoForImsiEncryption(subId, keyType,
- mContext.getOpPackageName());
+ return imsiEncryptionInfo;
} catch (RemoteException ex) {
- Rlog.e(TAG, "getCarrierInfoForImsiEncryption RemoteException", ex);
- return null;
+ Rlog.e(TAG, "getCarrierInfoForImsiEncryption RemoteException" + ex);
+ throw new RuntimeException("IMSI error: Remote Exception");
} catch (NullPointerException ex) {
// This could happen before phone restarts due to crashing
- Rlog.e(TAG, "getCarrierInfoForImsiEncryption NullPointerException", ex);
- return null;
+ Rlog.e(TAG, "getCarrierInfoForImsiEncryption NullPointerException" + ex);
+ throw new RuntimeException("IMSI error: Null Pointer exception");
+ }
+ }
+
+ /**
+ * @param keyAvailability bitmask that defines the availabilty of keys for a type.
+ * @param keyType the key type which is being checked. (WLAN, EPDG)
+ * @return true if the digit at position keyType is 1, else false.
+ * @hide
+ */
+ private static boolean isKeyEnabled(int keyAvailability, int keyType) {
+ int returnValue = (keyAvailability >> (keyType - 1)) & 1;
+ return (returnValue == 1) ? true : false;
+ }
+
+ /**
+ * If Carrier requires Imsi to be encrypted.
+ * @hide
+ */
+ private boolean isImsiEncryptionRequired(int subId, int keyType) {
+ CarrierConfigManager configManager =
+ (CarrierConfigManager) mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE);
+ if (configManager == null) {
+ return false;
+ }
+ PersistableBundle pb = configManager.getConfigForSubId(subId);
+ if (pb == null) {
+ return false;
}
+ int keyAvailability = pb.getInt(CarrierConfigManager.IMSI_KEY_AVAILABILITY_INT);
+ return isKeyEnabled(keyAvailability, keyType);
}
/**
package android.net;
-import android.net.IpPrefix;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
import android.os.Parcel;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
import java.net.InetAddress;
import java.util.Random;
-import junit.framework.TestCase;
-import static android.test.MoreAsserts.assertNotEqual;
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
+import org.junit.runner.RunWith;
+import org.junit.Test;
-public class IpPrefixTest extends TestCase {
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class IpPrefixTest {
private static InetAddress Address(String addr) {
return InetAddress.parseNumericAddress(addr);
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xa0
};
- @SmallTest
+ @Test
public void testConstructor() {
IpPrefix p;
try {
} catch(IllegalArgumentException expected) {}
}
+ @Test
public void testTruncation() {
IpPrefix p;
assertFalse(o2.equals(o1));
}
- @SmallTest
+ @Test
public void testEquals() {
IpPrefix p1, p2;
assertAreNotEqual(p1, p2);
}
- @SmallTest
+ @Test
public void testContains() {
IpPrefix p = new IpPrefix("2001:db8:f00::ace:d00d/127");
assertTrue(p.contains(Address("2001:db8:f00::ace:d00c")));
assertFalse(ipv4Default.contains(Address("2001:db8::f00")));
}
- @SmallTest
+ @Test
public void testHashCode() {
IpPrefix p = new IpPrefix(new byte[4], 0);
Random random = new Random();
assertEquals(p.hashCode(), oldP.hashCode());
}
if (p.hashCode() != oldP.hashCode()) {
- assertNotEqual(p, oldP);
+ assertNotEquals(p, oldP);
}
}
}
- @SmallTest
+ @Test
public void testHashCodeIsNotConstant() {
IpPrefix[] prefixes = {
new IpPrefix("2001:db8:f00::ace:d00d/127"),
};
for (int i = 0; i < prefixes.length; i++) {
for (int j = i + 1; j < prefixes.length; j++) {
- assertNotEqual(prefixes[i].hashCode(), prefixes[j].hashCode());
+ assertNotEquals(prefixes[i].hashCode(), prefixes[j].hashCode());
}
}
}
- @SmallTest
+ @Test
public void testMappedAddressesAreBroken() {
// 192.0.2.0/24 != ::ffff:c000:0204/120, but because we use InetAddress,
// we are unable to comprehend that.
assertEquals(p, p2);
}
+ @Test
public void testParceling() {
IpPrefix p;
p = new IpPrefix("2001:4860:db8::/64");
assertParcelingIsLossless(p);
+ assertTrue(p.isIPv6());
p = new IpPrefix("192.0.2.0/25");
assertParcelingIsLossless(p);
+ assertTrue(p.isIPv4());
}
}
package android.net;
+import static android.system.OsConstants.IFA_F_DADFAILED;
+import static android.system.OsConstants.IFA_F_DEPRECATED;
+import static android.system.OsConstants.IFA_F_OPTIMISTIC;
+import static android.system.OsConstants.IFA_F_PERMANENT;
+import static android.system.OsConstants.IFA_F_TEMPORARY;
+import static android.system.OsConstants.IFA_F_TENTATIVE;
+import static android.system.OsConstants.RT_SCOPE_HOST;
+import static android.system.OsConstants.RT_SCOPE_LINK;
+import static android.system.OsConstants.RT_SCOPE_SITE;
+import static android.system.OsConstants.RT_SCOPE_UNIVERSE;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.util.Comparator;
import java.util.List;
-import android.net.LinkAddress;
import android.os.Parcel;
-import android.test.AndroidTestCase;
-import static android.test.MoreAsserts.assertNotEqual;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
-import static android.system.OsConstants.IFA_F_DADFAILED;
-import static android.system.OsConstants.IFA_F_DEPRECATED;
-import static android.system.OsConstants.IFA_F_OPTIMISTIC;
-import static android.system.OsConstants.IFA_F_PERMANENT;
-import static android.system.OsConstants.IFA_F_TEMPORARY;
-import static android.system.OsConstants.IFA_F_TENTATIVE;
-import static android.system.OsConstants.RT_SCOPE_HOST;
-import static android.system.OsConstants.RT_SCOPE_LINK;
-import static android.system.OsConstants.RT_SCOPE_SITE;
-import static android.system.OsConstants.RT_SCOPE_UNIVERSE;
+import org.junit.runner.RunWith;
+import org.junit.Test;
-/**
- * Tests for {@link LinkAddress}.
- */
-public class LinkAddressTest extends AndroidTestCase {
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class LinkAddressTest {
private static final String V4 = "192.0.2.1";
private static final String V6 = "2001:db8::1";
private static final InetAddress V4_ADDRESS = NetworkUtils.numericToInetAddress(V4);
private static final InetAddress V6_ADDRESS = NetworkUtils.numericToInetAddress(V6);
+ @Test
public void testConstants() {
// RT_SCOPE_UNIVERSE = 0, but all the other constants should be nonzero.
- assertNotEqual(0, RT_SCOPE_HOST);
- assertNotEqual(0, RT_SCOPE_LINK);
- assertNotEqual(0, RT_SCOPE_SITE);
+ assertNotEquals(0, RT_SCOPE_HOST);
+ assertNotEquals(0, RT_SCOPE_LINK);
+ assertNotEquals(0, RT_SCOPE_SITE);
- assertNotEqual(0, IFA_F_DEPRECATED);
- assertNotEqual(0, IFA_F_PERMANENT);
- assertNotEqual(0, IFA_F_TENTATIVE);
+ assertNotEquals(0, IFA_F_DEPRECATED);
+ assertNotEquals(0, IFA_F_PERMANENT);
+ assertNotEquals(0, IFA_F_TENTATIVE);
}
+ @Test
public void testConstructors() throws SocketException {
LinkAddress address;
assertEquals(25, address.getPrefixLength());
assertEquals(0, address.getFlags());
assertEquals(RT_SCOPE_UNIVERSE, address.getScope());
+ assertTrue(address.isIPv4());
address = new LinkAddress(V6_ADDRESS, 127);
assertEquals(V6_ADDRESS, address.getAddress());
assertEquals(127, address.getPrefixLength());
assertEquals(0, address.getFlags());
assertEquals(RT_SCOPE_UNIVERSE, address.getScope());
+ assertTrue(address.isIPv6());
// Nonsensical flags/scopes or combinations thereof are acceptable.
address = new LinkAddress(V6 + "/64", IFA_F_DEPRECATED | IFA_F_PERMANENT, RT_SCOPE_LINK);
assertEquals(64, address.getPrefixLength());
assertEquals(IFA_F_DEPRECATED | IFA_F_PERMANENT, address.getFlags());
assertEquals(RT_SCOPE_LINK, address.getScope());
+ assertTrue(address.isIPv6());
address = new LinkAddress(V4 + "/23", 123, 456);
assertEquals(V4_ADDRESS, address.getAddress());
assertEquals(23, address.getPrefixLength());
assertEquals(123, address.getFlags());
assertEquals(456, address.getScope());
+ assertTrue(address.isIPv4());
// InterfaceAddress doesn't have a constructor. Fetch some from an interface.
List<InterfaceAddress> addrs = NetworkInterface.getByName("lo").getInterfaceAddresses();
} catch(IllegalArgumentException expected) {}
}
+ @Test
public void testAddressScopes() {
assertEquals(RT_SCOPE_HOST, new LinkAddress("::/128").getScope());
assertEquals(RT_SCOPE_HOST, new LinkAddress("0.0.0.0/32").getScope());
assertFalse(l2 + " unexpectedly equal to " + l1, l2.equals(l1));
}
+ @Test
public void testEqualsAndSameAddressAs() {
LinkAddress l1, l2, l3;
assertIsSameAddressAs(l1, l2);
}
+ @Test
public void testHashCode() {
- LinkAddress l;
-
- l = new LinkAddress(V4_ADDRESS, 23);
- assertEquals(-982787, l.hashCode());
-
- l = new LinkAddress(V4_ADDRESS, 23, 0, RT_SCOPE_HOST);
- assertEquals(-971865, l.hashCode());
-
- l = new LinkAddress(V4_ADDRESS, 27);
- assertEquals(-982743, l.hashCode());
-
- l = new LinkAddress(V6_ADDRESS, 64);
- assertEquals(1076522926, l.hashCode());
+ LinkAddress l1, l2;
- l = new LinkAddress(V6_ADDRESS, 128);
- assertEquals(1076523630, l.hashCode());
+ l1 = new LinkAddress(V4_ADDRESS, 23);
+ l2 = new LinkAddress(V4_ADDRESS, 23, 0, RT_SCOPE_HOST);
+ assertNotEquals(l1.hashCode(), l2.hashCode());
- l = new LinkAddress(V6_ADDRESS, 128, IFA_F_TENTATIVE, RT_SCOPE_UNIVERSE);
- assertEquals(1076524846, l.hashCode());
+ l1 = new LinkAddress(V6_ADDRESS, 128);
+ l2 = new LinkAddress(V6_ADDRESS, 128, IFA_F_TENTATIVE, RT_SCOPE_UNIVERSE);
+ assertNotEquals(l1.hashCode(), l2.hashCode());
}
private LinkAddress passThroughParcel(LinkAddress l) {
assertEquals(l, l2);
}
+ @Test
public void testParceling() {
LinkAddress l;
assertFalse(msg, l.isGlobalPreferred());
}
+ @Test
public void testIsGlobalPreferred() {
LinkAddress l;
package android.net.wifi;
+import android.Manifest;
import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.annotation.SuppressLint;
};
}
+ @RequiresPermission(Manifest.permission.LOCATION_HARDWARE)
public RttCapabilities getRttCapabilities() {
synchronized (mCapabilitiesLock) {
if (mRttCapabilities == null) {
public void onAborted();
}
+ /**
+ * A parcelable that contains rtt client information.
+ *
+ * @hide
+ */
+ public static class RttClient implements Parcelable {
+ // Package name of RttClient.
+ private final String mPackageName;
+
+ public RttClient(String packageName) {
+ mPackageName = packageName;
+ }
+
+ protected RttClient(Parcel in) {
+ mPackageName = in.readString();
+ }
+
+ public static final Creator<RttManager.RttClient> CREATOR =
+ new Creator<RttManager.RttClient>() {
+ @Override
+ public RttManager.RttClient createFromParcel(Parcel in) {
+ return new RttManager.RttClient(in);
+ }
+
+ @Override
+ public RttManager.RttClient[] newArray(int size) {
+ return new RttManager.RttClient[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel parcel, int i) {
+ parcel.writeString(mPackageName);
+ }
+
+ public String getPackageName() {
+ return mPackageName;
+ }
+ }
+
private boolean rttParamSanity(RttParams params, int index) {
if (mRttCapabilities == null) {
if(getRttCapabilities() == null) {
mAsyncChannel.connectSync(mContext, handler, messenger);
// We cannot use fullyConnectSync because it sends the FULL_CONNECTION message
// synchronously, which causes RttService to receive the wrong replyTo value.
- mAsyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
+ mAsyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION,
+ new RttClient(context.getPackageName()));
mAsyncChannel.sendMessage(CMD_OP_REG_BINDER, key[0]);
}