diff options
270 files changed, 13557 insertions, 538 deletions
diff --git a/Android.bp b/Android.bp index 286be8212694..482b58eb43e8 100644..100755 --- a/Android.bp +++ b/Android.bp @@ -649,6 +649,8 @@ java_defaults { "packages/services/Proxy/com/android/net/IProxyPortListener.aidl", "core/java/android/service/quicksettings/IQSService.aidl", "core/java/android/service/quicksettings/IQSTileService.aidl", + "telephony/java/com/android/internal/telephony/ISmsSecurityService.aidl", + "telephony/java/com/android/internal/telephony/ISmsSecurityAgent.aidl", ":libupdate_engine_aidl", diff --git a/Android.mk b/Android.mk index e4053452a9c5..e4053452a9c5 100644..100755 --- a/Android.mk +++ b/Android.mk diff --git a/api/system-current.txt b/api/system-current.txt index 8d7c44447918..af3b97781e6e 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -7458,6 +7458,7 @@ package android.telephony.ims { method public void callSessionResumed(android.telephony.ims.ImsCallProfile); method public void callSessionRttAudioIndicatorChanged(android.telephony.ims.ImsStreamMediaProfile); method public void callSessionRttMessageReceived(String); + method public void callSessionPropertyChanged(int); method public void callSessionRttModifyRequestReceived(android.telephony.ims.ImsCallProfile); method public void callSessionRttModifyResponseReceived(int); method public void callSessionSuppServiceReceived(android.telephony.ims.ImsSuppServiceNotification); @@ -8202,6 +8203,7 @@ package android.telephony.ims.stub { public class ImsUtImplBase { ctor public ImsUtImplBase(); method public void close(); + method public int queryCFForServiceClass(int, java.lang.String, int); method public int queryCallBarring(int); method public int queryCallBarringForServiceClass(int, int); method public int queryCallForward(int, String); diff --git a/cmds/app_process/Android.mk b/cmds/app_process/Android.mk index 72fe0516f480..6acf655c972a 100644 --- a/cmds/app_process/Android.mk +++ b/cmds/app_process/Android.mk @@ -2,6 +2,7 @@ LOCAL_PATH:= $(call my-dir) app_process_common_shared_libs := \ libandroid_runtime \ + libbase \ libbinder \ libcutils \ libdl \ diff --git a/cmds/app_process/app_main.cpp b/cmds/app_process/app_main.cpp index 12083b6fe20b..002df808501c 100644 --- a/cmds/app_process/app_main.cpp +++ b/cmds/app_process/app_main.cpp @@ -21,8 +21,11 @@ #include <cutils/properties.h> #include <cutils/trace.h> #include <android_runtime/AndroidRuntime.h> +#include <android-base/properties.h> #include <private/android_filesystem_config.h> // for AID_SYSTEM +using android::base::GetProperty; + namespace android { static void app_usage() @@ -172,6 +175,13 @@ static const char ZYGOTE_NICE_NAME[] = "zygote"; int main(int argc, char* const argv[]) { + std::string bootmode = GetProperty("ro.bootmode", ""); + + if ((strncmp(bootmode.c_str(), "ffbm-00", 7) == 0) + || (strncmp(bootmode.c_str(), "ffbm-01", 7) == 0)) { + return 0; + } + if (!LOG_NDEBUG) { String8 argv_String; for (int i = 0; i < argc; ++i) { diff --git a/cmds/idmap/scan.cpp b/cmds/idmap/scan.cpp index d69dd79555a1..0926b5899468 100644..100755 --- a/cmds/idmap/scan.cpp +++ b/cmds/idmap/scan.cpp @@ -233,9 +233,6 @@ namespace { int idmap_scan(const char *target_package_name, const char *target_apk_path, const char *idmap_dir, const android::Vector<const char *> *overlay_dirs) { - String8 filename = String8(idmap_dir); - filename.appendPath("overlays.list"); - SortedVector<Overlay> overlayVector; const size_t N = overlay_dirs->size(); for (size_t i = 0; i < N; ++i) { @@ -250,39 +247,58 @@ int idmap_scan(const char *target_package_name, const char *target_apk_path, struct stat st; char overlay_apk_path[PATH_MAX + 1]; snprintf(overlay_apk_path, PATH_MAX, "%s/%s", overlay_dir, dirent->d_name); + if (stat(overlay_apk_path, &st) < 0) { continue; } - if (!S_ISREG(st.st_mode)) { - continue; - } - int priority = parse_apk(overlay_apk_path, target_package_name); - if (priority < 0) { + if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode)) { continue; } - String8 idmap_path(idmap_dir); - idmap_path.appendPath(flatten_path(overlay_apk_path + 1)); - idmap_path.append("@idmap"); + if (S_ISDIR(st.st_mode)) { + String8 dir_name = String8(overlay_apk_path).getPathLeaf(); + if (dir_name == "." || dir_name == "..") { + // Skip the "." and ".." dir. + continue; + } + android::Vector<const char *> ovector; + ovector.push(overlay_apk_path); + idmap_scan(target_package_name, target_apk_path, idmap_dir, &ovector); + } else { + int priority = parse_apk(overlay_apk_path, target_package_name); + if (priority < 0) { + continue; + } - if (idmap_create_path(target_apk_path, overlay_apk_path, idmap_path.string()) != 0) { - ALOGE("error: failed to create idmap for target=%s overlay=%s idmap=%s\n", - target_apk_path, overlay_apk_path, idmap_path.string()); - continue; - } + String8 filename = String8(idmap_dir); + filename.appendPath("overlays.list"); + if (unlink(filename.string()) != 0 && errno != ENOENT) { + return EXIT_FAILURE; + } + + String8 idmap_path(idmap_dir); + idmap_path.appendPath(flatten_path(overlay_apk_path + 1)); + idmap_path.append("@idmap"); + if (idmap_create_path(target_apk_path, overlay_apk_path, + idmap_path.string()) != 0) { + ALOGE("error: failed to create idmap for target=%s overlay=%s idmap=%s\n", + target_apk_path, overlay_apk_path, idmap_path.string()); + continue; + } + + Overlay overlay(String8(overlay_apk_path), idmap_path, priority); + overlayVector.add(overlay); - Overlay overlay(String8(overlay_apk_path), idmap_path, priority); - overlayVector.add(overlay); + if (!writePackagesList(filename.string(), overlayVector)) { + return EXIT_FAILURE; + } + } } closedir(dir); } - if (!writePackagesList(filename.string(), overlayVector)) { - return EXIT_FAILURE; - } - return EXIT_SUCCESS; } diff --git a/config/hiddenapi-greylist.txt b/config/hiddenapi-greylist.txt index 13f8dd924d4a..765b7f991e90 100644 --- a/config/hiddenapi-greylist.txt +++ b/config/hiddenapi-greylist.txt @@ -2935,7 +2935,6 @@ Lcom/android/internal/telephony/IccPhoneBookInterfaceManager;->DBG:Z Lcom/android/internal/telephony/IccPhoneBookInterfaceManager;->logd(Ljava/lang/String;)V Lcom/android/internal/telephony/IccPhoneBookInterfaceManager;->loge(Ljava/lang/String;)V Lcom/android/internal/telephony/IccPhoneBookInterfaceManager;->mAdnCache:Lcom/android/internal/telephony/uicc/AdnRecordCache; -Lcom/android/internal/telephony/IccPhoneBookInterfaceManager;->mBaseHandler:Landroid/os/Handler; Lcom/android/internal/telephony/IccPhoneBookInterfaceManager;->mCurrentApp:Lcom/android/internal/telephony/uicc/UiccCardApplication; Lcom/android/internal/telephony/IccPhoneBookInterfaceManager;->mIs3gCard:Z Lcom/android/internal/telephony/IccPhoneBookInterfaceManager;->mLock:Ljava/lang/Object; @@ -2991,7 +2990,6 @@ Lcom/android/internal/telephony/imsphone/ImsExternalCallTracker$ExternalCallStat Lcom/android/internal/telephony/imsphone/ImsExternalCallTracker$ExternalConnectionListener;-><init>(Lcom/android/internal/telephony/imsphone/ImsExternalCallTracker;)V Lcom/android/internal/telephony/imsphone/ImsExternalConnection;->rebuildCapabilities()V Lcom/android/internal/telephony/imsphone/ImsExternalConnection;->setActive()V -Lcom/android/internal/telephony/imsphone/ImsPhone$Cf;-><init>(Ljava/lang/String;ZLandroid/os/Message;)V Lcom/android/internal/telephony/imsphone/ImsPhone;->getActionFromCFAction(I)I Lcom/android/internal/telephony/imsphone/ImsPhone;->getBackgroundCall()Lcom/android/internal/telephony/imsphone/ImsPhoneCall; Lcom/android/internal/telephony/imsphone/ImsPhone;->getCallForwardingOption(ILandroid/os/Message;)V diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java index 26c2c0cfdd5d..a387576c6059 100644 --- a/core/java/android/accounts/AccountManager.java +++ b/core/java/android/accounts/AccountManager.java @@ -478,6 +478,7 @@ public class AccountManager { * @return The account's password, null if none or if the account doesn't exist */ public String getPassword(final Account account) { + android.util.SeempLog.record(22); if (account == null) throw new IllegalArgumentException("account is null"); try { return mService.getPassword(account); @@ -508,6 +509,7 @@ public class AccountManager { * @return The user data, null if the account, key doesn't exist, or the user is locked */ public String getUserData(final Account account, final String key) { + android.util.SeempLog.record(23); if (account == null) throw new IllegalArgumentException("account is null"); if (key == null) throw new IllegalArgumentException("key is null"); try { @@ -730,6 +732,7 @@ public class AccountManager { return new Future2Task<String>(handler, callback) { @Override public void doWork() throws RemoteException { + android.util.SeempLog.record(31); mService.getAuthTokenLabel(mResponse, accountType, authTokenType); } @@ -774,6 +777,7 @@ public class AccountManager { return new Future2Task<Boolean>(handler, callback) { @Override public void doWork() throws RemoteException { + android.util.SeempLog.record(31); mService.hasFeatures(mResponse, account, features, mContext.getOpPackageName()); } @Override @@ -834,6 +838,7 @@ public class AccountManager { return new Future2Task<Account[]>(handler, callback) { @Override public void doWork() throws RemoteException { + android.util.SeempLog.record(31); mService.getAccountsByFeatures(mResponse, type, features, mContext.getOpPackageName()); } @@ -878,6 +883,7 @@ public class AccountManager { * already exists, the account is null, the user is locked, or another error occurs. */ public boolean addAccountExplicitly(Account account, String password, Bundle userdata) { + android.util.SeempLog.record(24); if (account == null) throw new IllegalArgumentException("account is null"); try { return mService.addAccountExplicitly(account, password, userdata); @@ -1095,6 +1101,7 @@ public class AccountManager { return new Future2Task<Account>(handler, callback) { @Override public void doWork() throws RemoteException { + android.util.SeempLog.record(31); mService.renameAccount(mResponse, account, newName); } @Override @@ -1155,10 +1162,12 @@ public class AccountManager { @Deprecated public AccountManagerFuture<Boolean> removeAccount(final Account account, AccountManagerCallback<Boolean> callback, Handler handler) { + android.util.SeempLog.record(25); if (account == null) throw new IllegalArgumentException("account is null"); return new Future2Task<Boolean>(handler, callback) { @Override public void doWork() throws RemoteException { + android.util.SeempLog.record(31); mService.removeAccount(mResponse, account, false); } @Override @@ -1214,10 +1223,12 @@ public class AccountManager { */ public AccountManagerFuture<Bundle> removeAccount(final Account account, final Activity activity, AccountManagerCallback<Bundle> callback, Handler handler) { + android.util.SeempLog.record(28); if (account == null) throw new IllegalArgumentException("account is null"); return new AmsTask(activity, handler, callback) { @Override public void doWork() throws RemoteException { + android.util.SeempLog.record(34); mService.removeAccount(mResponse, account, activity != null); } }.start(); @@ -1239,6 +1250,7 @@ public class AccountManager { return new Future2Task<Boolean>(handler, callback) { @Override public void doWork() throws RemoteException { + android.util.SeempLog.record(31); mService.removeAccountAsUser(mResponse, account, false, userHandle.getIdentifier()); } @Override @@ -1265,6 +1277,7 @@ public class AccountManager { return new AmsTask(activity, handler, callback) { @Override public void doWork() throws RemoteException { + android.util.SeempLog.record(34); mService.removeAccountAsUser(mResponse, account, activity != null, userHandle.getIdentifier()); } @@ -1378,6 +1391,7 @@ public class AccountManager { * @param password The password to set, null to clear the password */ public void setPassword(final Account account, final String password) { + android.util.SeempLog.record(26); if (account == null) throw new IllegalArgumentException("account is null"); try { mService.setPassword(account, password); @@ -1406,6 +1420,7 @@ public class AccountManager { * @param account The account whose password to clear */ public void clearPassword(final Account account) { + android.util.SeempLog.record(27); if (account == null) throw new IllegalArgumentException("account is null"); try { mService.clearPassword(account); @@ -1433,6 +1448,7 @@ public class AccountManager { * @param value String value to set, {@code null} to clear this user data key */ public void setUserData(final Account account, final String key, final String value) { + android.util.SeempLog.record(28); if (account == null) throw new IllegalArgumentException("account is null"); if (key == null) throw new IllegalArgumentException("key is null"); try { @@ -1583,6 +1599,7 @@ public class AccountManager { return new AmsTask(activity, handler, callback) { @Override public void doWork() throws RemoteException { + android.util.SeempLog.record(31); mService.getAuthToken(mResponse, account, authTokenType, false /* notifyOnAuthFailure */, true /* expectActivityLaunch */, optionsIn); @@ -1754,6 +1771,7 @@ public class AccountManager { return new AmsTask(null, handler, callback) { @Override public void doWork() throws RemoteException { + android.util.SeempLog.record(31); mService.getAuthToken(mResponse, account, authTokenType, notifyAuthFailure, false /* expectActivityLaunch */, optionsIn); } @@ -1814,6 +1832,7 @@ public class AccountManager { final String authTokenType, final String[] requiredFeatures, final Bundle addAccountOptions, final Activity activity, AccountManagerCallback<Bundle> callback, Handler handler) { + android.util.SeempLog.record(29); if (accountType == null) throw new IllegalArgumentException("accountType is null"); final Bundle optionsIn = new Bundle(); if (addAccountOptions != null) { @@ -1824,6 +1843,7 @@ public class AccountManager { return new AmsTask(activity, handler, callback) { @Override public void doWork() throws RemoteException { + android.util.SeempLog.record(31); mService.addAccount(mResponse, accountType, authTokenType, requiredFeatures, activity != null, optionsIn); } @@ -1849,6 +1869,7 @@ public class AccountManager { return new AmsTask(activity, handler, callback) { @Override public void doWork() throws RemoteException { + android.util.SeempLog.record(31); mService.addAccountAsUser(mResponse, accountType, authTokenType, requiredFeatures, activity != null, optionsIn, userHandle.getIdentifier()); } @@ -1898,6 +1919,7 @@ public class AccountManager { return new Future2Task<Boolean>(handler, callback) { @Override public void doWork() throws RemoteException { + android.util.SeempLog.record(34); mService.copyAccountToUser( mResponse, account, fromUser.getIdentifier(), toUser.getIdentifier()); } @@ -2025,6 +2047,7 @@ public class AccountManager { return new AmsTask(activity, handler, callback) { @Override public void doWork() throws RemoteException { + android.util.SeempLog.record(31); mService.confirmCredentialsAsUser(mResponse, account, options, activity != null, userId); } @@ -2138,10 +2161,12 @@ public class AccountManager { public AccountManagerFuture<Bundle> editProperties(final String accountType, final Activity activity, final AccountManagerCallback<Bundle> callback, final Handler handler) { + android.util.SeempLog.record(30); if (accountType == null) throw new IllegalArgumentException("accountType is null"); return new AmsTask(activity, handler, callback) { @Override public void doWork() throws RemoteException { + android.util.SeempLog.record(31); mService.editProperties(mResponse, accountType, activity != null); } }.start(); @@ -2568,6 +2593,7 @@ public class AccountManager { @Override public void doWork() throws RemoteException { + android.util.SeempLog.record(31); getAccountByTypeAndFeatures(mAccountType, mFeatures, new AccountManagerCallback<Bundle>() { @Override diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 7767f0491a16..b4d20c35e6e3 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -123,6 +123,7 @@ import android.system.OsConstants; import android.system.StructStat; import android.util.AndroidRuntimeException; import android.util.ArrayMap; +import android.util.BoostFramework; import android.util.DisplayMetrics; import android.util.EventLog; import android.util.Log; @@ -5781,6 +5782,8 @@ public final class ActivityThread extends ClientTransactionHandler { @UnsupportedAppUsage private void handleBindApplication(AppBindData data) { + long st_bindApp = SystemClock.uptimeMillis(); + BoostFramework ux_perf = null; // Register the UI Thread as a sensitive thread to the runtime. VMRuntime.registerSensitiveThread(); if (data.trackAllocation) { @@ -5869,10 +5872,17 @@ public final class ActivityThread extends ClientTransactionHandler { /** * Switch this process to density compatibility mode if needed. */ - if ((data.appInfo.flags&ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) + if ((data.appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) == 0) { mDensityCompatMode = true; Bitmap.setDefaultDensity(DisplayMetrics.DENSITY_DEFAULT); + } else { + int overrideDensity = data.appInfo.getOverrideDensity(); + if(overrideDensity != 0) { + Log.d(TAG, "override app density from " + DisplayMetrics.DENSITY_DEVICE + " to " + overrideDensity); + mDensityCompatMode = true; + Bitmap.setDefaultDensity(overrideDensity); + } } updateDefaultDensity(); @@ -6002,6 +6012,15 @@ public final class ActivityThread extends ClientTransactionHandler { mResourcesManager.getConfiguration().getLocales()); if (!Process.isIsolated()) { + final int old_mask = StrictMode.allowThreadDiskWritesMask(); + try { + ux_perf = new BoostFramework(appContext); + } finally { + StrictMode.setThreadPolicyMask(old_mask); + } + } + + if (!Process.isIsolated()) { final int oldMask = StrictMode.allowThreadDiskWritesMask(); try { setupGraphicsSupport(appContext); @@ -6146,6 +6165,15 @@ public final class ActivityThread extends ClientTransactionHandler { throw e.rethrowFromSystemServer(); } } + long end_bindApp = SystemClock.uptimeMillis(); + int bindApp_dur = (int) (end_bindApp - st_bindApp); + String pkg_name = null; + if (appContext != null) { + pkg_name = appContext.getPackageName(); + } + if (ux_perf != null && !Process.isIsolated() && pkg_name != null) { + ux_perf.perfUXEngine_events(BoostFramework.UXE_EVENT_BINDAPP, 0, pkg_name, bindApp_dur); + } } /*package*/ final void finishInstrumentation(int resultCode, Bundle results) { diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java index dda5569a26b3..dd32e08fcd5a 100644 --- a/core/java/android/app/Instrumentation.java +++ b/core/java/android/app/Instrumentation.java @@ -489,6 +489,7 @@ public class Instrumentation { */ @NonNull public Activity startActivitySync(@NonNull Intent intent, @Nullable Bundle options) { + android.util.SeempLog.record_str(376, intent.toString()); validateNotAppThread(); synchronized (mSync) { @@ -1667,6 +1668,7 @@ public class Instrumentation { public ActivityResult execStartActivity( Context who, IBinder contextThread, IBinder token, Activity target, Intent intent, int requestCode, Bundle options) { + android.util.SeempLog.record_str(377, intent.toString()); IApplicationThread whoThread = (IApplicationThread) contextThread; Uri referrer = target != null ? target.onProvideReferrer() : null; if (referrer != null) { @@ -1740,6 +1742,7 @@ public class Instrumentation { public int execStartActivitiesAsUser(Context who, IBinder contextThread, IBinder token, Activity target, Intent[] intents, Bundle options, int userId) { + android.util.SeempLog.record_str(378, intents.toString()); IApplicationThread whoThread = (IApplicationThread) contextThread; if (mActivityMonitors != null) { synchronized (mSync) { @@ -1812,6 +1815,7 @@ public class Instrumentation { public ActivityResult execStartActivity( Context who, IBinder contextThread, IBinder token, String target, Intent intent, int requestCode, Bundle options) { + android.util.SeempLog.record_str(377, intent.toString()); IApplicationThread whoThread = (IApplicationThread) contextThread; if (mActivityMonitors != null) { synchronized (mSync) { @@ -1880,6 +1884,7 @@ public class Instrumentation { public ActivityResult execStartActivity( Context who, IBinder contextThread, IBinder token, String resultWho, Intent intent, int requestCode, Bundle options, UserHandle user) { + android.util.SeempLog.record_str(377, intent.toString()); IApplicationThread whoThread = (IApplicationThread) contextThread; if (mActivityMonitors != null) { synchronized (mSync) { @@ -1974,6 +1979,7 @@ public class Instrumentation { public void execStartActivityFromAppTask( Context who, IBinder contextThread, IAppTask appTask, Intent intent, Bundle options) { + android.util.SeempLog.record_str(380, intent.toString()); IApplicationThread whoThread = (IApplicationThread) contextThread; if (mActivityMonitors != null) { synchronized (mSync) { diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java index 1945b2fd51de..d94b188fbebe 100644 --- a/core/java/android/bluetooth/BluetoothAdapter.java +++ b/core/java/android/bluetooth/BluetoothAdapter.java @@ -706,6 +706,7 @@ public final class BluetoothAdapter { * @throws IllegalArgumentException if address is invalid */ public BluetoothDevice getRemoteDevice(String address) { + android.util.SeempLog.record(62); return new BluetoothDevice(address); } @@ -721,6 +722,7 @@ public final class BluetoothAdapter { * @throws IllegalArgumentException if address is invalid */ public BluetoothDevice getRemoteDevice(byte[] address) { + android.util.SeempLog.record(62); if (address == null || address.length != 6) { throw new IllegalArgumentException("Bluetooth address must have 6 bytes"); } @@ -952,6 +954,7 @@ public final class BluetoothAdapter { @RequiresPermission(Manifest.permission.BLUETOOTH) @AdapterState public int getState() { + android.util.SeempLog.record(63); int state = BluetoothAdapter.STATE_OFF; try { @@ -1055,6 +1058,7 @@ public final class BluetoothAdapter { */ @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) public boolean enable() { + android.util.SeempLog.record(56); if (isEnabled()) { if (DBG) { Log.d(TAG, "enable(): BT already enabled!"); @@ -1092,6 +1096,7 @@ public final class BluetoothAdapter { */ @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) public boolean disable() { + android.util.SeempLog.record(57); try { return mManagerService.disable(ActivityThread.currentPackageName(), true); } catch (RemoteException e) { @@ -1111,6 +1116,7 @@ public final class BluetoothAdapter { */ @UnsupportedAppUsage public boolean disable(boolean persist) { + android.util.SeempLog.record(57); try { return mManagerService.disable(ActivityThread.currentPackageName(), persist); @@ -1165,10 +1171,10 @@ public final class BluetoothAdapter { public boolean factoryReset() { try { mServiceLock.readLock().lock(); - if (mService != null) { - return mService.factoryReset(); + if (mManagerService != null) { + SystemProperties.set("persist.bluetooth.factoryreset", "true"); + return mManagerService.factoryReset(); } - SystemProperties.set("persist.bluetooth.factoryreset", "true"); } catch (RemoteException e) { Log.e(TAG, "", e); } finally { @@ -1589,6 +1595,7 @@ public final class BluetoothAdapter { */ @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) public boolean startDiscovery() { + android.util.SeempLog.record(58); if (getState() != STATE_ON) { return false; } @@ -1984,6 +1991,7 @@ public final class BluetoothAdapter { */ @RequiresPermission(Manifest.permission.BLUETOOTH) public Set<BluetoothDevice> getBondedDevices() { + android.util.SeempLog.record(61); if (getState() != STATE_ON) { return toDeviceSet(new BluetoothDevice[0]); } @@ -2076,6 +2084,7 @@ public final class BluetoothAdapter { */ @RequiresPermission(Manifest.permission.BLUETOOTH) public int getProfileConnectionState(int profile) { + android.util.SeempLog.record(64); if (getState() != STATE_ON) { return BluetoothProfile.STATE_DISCONNECTED; } @@ -2207,6 +2216,7 @@ public final class BluetoothAdapter { @RequiresPermission(Manifest.permission.BLUETOOTH) public BluetoothServerSocket listenUsingInsecureRfcommWithServiceRecord(String name, UUID uuid) throws IOException { + android.util.SeempLog.record(59); return createNewRfcommSocketAndRecord(name, uuid, false, false); } @@ -2476,6 +2486,9 @@ public final class BluetoothAdapter { } else if (profile == BluetoothProfile.PAN) { BluetoothPan pan = new BluetoothPan(context, listener); return true; + } else if (profile == BluetoothProfile.DUN) { + BluetoothDun dun = new BluetoothDun(context, listener); + return true; } else if (profile == BluetoothProfile.HEALTH) { Log.e(TAG, "getProfileProxy(): BluetoothHealth is deprecated"); return false; @@ -2500,6 +2513,9 @@ public final class BluetoothAdapter { } else if (profile == BluetoothProfile.HEARING_AID) { BluetoothHearingAid hearingAid = new BluetoothHearingAid(context, listener); return true; + } else if (profile == BluetoothProfile.BA_TRANSMITTER) { + BluetoothBATransmitter baTransmitter = new BluetoothBATransmitter(context, listener); + return true; } else { return false; } @@ -2545,6 +2561,10 @@ public final class BluetoothAdapter { BluetoothPan pan = (BluetoothPan) proxy; pan.close(); break; + case BluetoothProfile.DUN: + BluetoothDun dun = (BluetoothDun)proxy; + dun.close(); + break; case BluetoothProfile.GATT: BluetoothGatt gatt = (BluetoothGatt) proxy; gatt.close(); @@ -2580,6 +2600,11 @@ public final class BluetoothAdapter { case BluetoothProfile.HEARING_AID: BluetoothHearingAid hearingAid = (BluetoothHearingAid) proxy; hearingAid.close(); + break; + case BluetoothProfile.BA_TRANSMITTER: + BluetoothBATransmitter baTransmitter = (BluetoothBATransmitter) proxy; + baTransmitter.close(); + break; } } @@ -2631,6 +2656,8 @@ public final class BluetoothAdapter { } synchronized (mProxyServiceStateCallbacks) { + Log.d(TAG, "onBluetoothServiceDown: Sending callbacks to " + + mProxyServiceStateCallbacks.size() + " clients"); for (IBluetoothManagerCallback cb : mProxyServiceStateCallbacks) { try { if (cb != null) { @@ -2643,6 +2670,7 @@ public final class BluetoothAdapter { } } } + Log.d(TAG, "onBluetoothServiceDown: Finished sending callbacks to registered clients"); } public void onBrEdrDown() { @@ -2735,6 +2763,22 @@ public final class BluetoothAdapter { } } + /** + * @hide + */ + public void unregisterAdapter() { + try { + //mServiceLock.writeLock().lock(); + if (mManagerService != null){ + mManagerService.unregisterAdapter(mManagerCallback); + } + } catch (RemoteException e) { + Log.e(TAG, "", e); + } finally { + //mServiceLock.writeLock().unlock(); + } + } + private Set<BluetoothDevice> toDeviceSet(BluetoothDevice[] devices) { Set<BluetoothDevice> deviceSet = new HashSet<BluetoothDevice>(Arrays.asList(devices)); return Collections.unmodifiableSet(deviceSet); diff --git a/core/java/android/bluetooth/BluetoothBAEncryptionKey.java b/core/java/android/bluetooth/BluetoothBAEncryptionKey.java new file mode 100644 index 000000000000..0b00e6000a2b --- /dev/null +++ b/core/java/android/bluetooth/BluetoothBAEncryptionKey.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2017, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package android.bluetooth; + +import android.os.Parcel; +import android.os.Parcelable; +import android.util.Log; + + +/** + * Class used to identify 128 bit Encryption Key for BA. + * + * {@hide} + */ +public final class BluetoothBAEncryptionKey implements Parcelable { + public static final String TAG = "BluetoothBAEncryptionKey"; + + private int mFlagType; + public static int ENCRYPTION_KEY_LENGTH = 16;// key len in bytes + public static int SECURITY_KEY_TYPE_PRIVATE = 0x0001; + public static int SECURITY_KEY_TYPE_TEMP = 0x0002; + public static int SECURITY_KEY_FORWARD_ENABLED = 0x0080; + private byte[] mEncryptionKey = new byte[ENCRYPTION_KEY_LENGTH]; + + public int describeContents() { + return 0; + } + + public void writeToParcel(Parcel out, int flags) { + for (int k =0; k < ENCRYPTION_KEY_LENGTH; k++) { + out.writeByte(mEncryptionKey[k]); + } + out.writeInt(mFlagType); + } + + public static final Parcelable.Creator<BluetoothBAEncryptionKey> CREATOR + = new Parcelable.Creator<BluetoothBAEncryptionKey>() { + public BluetoothBAEncryptionKey createFromParcel(Parcel in) { + return new BluetoothBAEncryptionKey(in); + } + + public BluetoothBAEncryptionKey[] newArray(int size) { + return new BluetoothBAEncryptionKey[size]; + } + }; + + private BluetoothBAEncryptionKey(Parcel in) { + for (int i = 0; i < ENCRYPTION_KEY_LENGTH; i++) { + mEncryptionKey[i] = in.readByte(); + } + mFlagType = in.readInt(); + } + + /** + * Create a new BluetoothBAEncryptionKey object. + * + * @param byte array contianing encryption key + */ + public BluetoothBAEncryptionKey(byte[] mEncKey, int flagType) { + for (int i = 0; i < ENCRYPTION_KEY_LENGTH; i++) { + mEncryptionKey[i] = mEncKey[i]; + } + mFlagType = flagType; + } + + /** + * Get the encryption key. + * + * @return byte array containing encryption key. + */ + public byte[] getEncryptionKey() { + return mEncryptionKey; + } + + public int getFlagType() { + return mFlagType; + } + +} diff --git a/core/java/android/bluetooth/BluetoothBAStreamServiceRecord.java b/core/java/android/bluetooth/BluetoothBAStreamServiceRecord.java new file mode 100644 index 000000000000..cab8db80a2f2 --- /dev/null +++ b/core/java/android/bluetooth/BluetoothBAStreamServiceRecord.java @@ -0,0 +1,310 @@ +/* + * Copyright (c) 2017, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package android.bluetooth; + +import android.os.Parcel; +import android.os.Parcelable; +import android.util.Log; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import java.util.List; + +/** + * Class used to send Broadcast Audio Stream Service Records. + * + * {@hide} + */ +public final class BluetoothBAStreamServiceRecord implements Parcelable { + public static final String TAG = "BluetoothBAStreamServiceRecord"; + + public static final int BSSR_TYPE_STREAM_ID = 0; + public static final int BSSR_TYPE_STREAM_ID_LEN = 1; + // actual values would be returned + + // security feilds + public static final int BSSR_TYPE_SECURITY_ID = 1; + public static final int BSSR_TYPE_SECURITY_ID_LEN = 2; + //This stream uses the private key + public static final long BSSR_SECURITY_KEY_TYPE_PRIVATE = 0x0001; + //This stream uses the temporary key + public static final long BSSR_SECURITY_KEY_TYPE_TEMP = 0x0002; + //This stream does not use encryption + public static final long BSSR_SECURITY_ENCRYPT_TYPE_NONE = 0x0100; + //This stream uses AESCCM encryption + public static final long BSSR_SECURITY_ENCRYPT_TYPE_AESCCM = 0x0200; + + // codec type feilds + public static final int BSSR_TYPE_CODEC_TYPE_ID = 2; + public static final int BSSR_TYPE_CODEC_TYPE_ID_LEN = 1; + public static final long BSSR_CODEC_TYPE_CELT = 0x01; // CELT CODEC + + // CELT config values, defined below. + public static final int BSSR_TYPE_CODEC_CONFIG_CELT_ID = 3;// this values is further divided + // into 3 values freq, frame_size and frame_samples. + public static final int BSSR_TYPE_CODEC_CONFIG_CELT_ID_LEN = 6; + + public static final int BSSR_TYPE_SCMST_SUPPORT_ID = 5; + public static final int BSSR_TYPE_SCMST_SUPPORT_ID_LEN = 1; + //The recipient must not copy the data in this stream + public static final long BSSR_SCMST_SUPPORT_COPY = 0x01; + //The recipient must not forward the data in this stream. + public static final long BSSR_SCMST_SUPPORT_FORWARD = 0x02; + + // Erasure Coding values + public static final int BSSR_TYPE_ERASURE_CODE_ID = 6; + public static final int BSSR_TYPE_ERASURE_CODE_ID_LEN = 1; + public static final long BSSR_ERASURE_CODE_NONE = 0x00;//No erasure coding in this stream + public static final long BSSR_ERASURE_CODE_2_5 = 0x01;//The stream has a 2,5 coding scheme + public static final long BSSR_ERASURE_CODE_3_7 = 0x02;//The stream has a 3,7 coding scheme + public static final long BSSR_ERASURE_CODE_3_8 = 0x03;//The stream has a 3,8 coding scheme + public static final long BSSR_ERASURE_CODE_3_9 = 0x04;//The stream has a 3,9 coding scheme + + public static final int BSSR_TYPE_CHANNELS_ID = 7; + public static final int BSSR_TYPE_CHANNELS_ID_LEN = 2; + public static final long BSSR_CHANNELS_MONO = 0x0001;//This stream is mono + public static final long BSSR_CHANNELS_STEREO = 0x0004;//This stream is stereo + + public static final int BSSR_TYPE_SAMPLE_SIZE_ID = 8; + public static final int BSSR_TYPE_SAMPLE_SIZE_ID_LEN = 1; + public static final long BSSR_SAMPLE_SIZE_8_BIT = 0x01;//This stream is 8-bit samples + public static final long BSSR_SAMPLE_SIZE_16_BIT = 0x02;//This stream is 16-bit samples + public static final long BSSR_SAMPLE_SIZE_24_BIT = 0x04;//This stream id 24-bit samples + + public static final int BSSR_TYPE_AFH_UPDATE_METHOD_ID = 9; + public static final int BSSR_TYPE_AFH_UPDATE_METHOD_ID_LEN = 1; + //This stream does not support AFH channel map updates + public static final long BSSR_AFH_CHANNEL_MAP_UPDATE_METHOD_NONE = 0x00; + //This stream uses SCM to transport AFH channel map updates from broadcaster to receivers. + public static final long BSSR_AFH_CHANNEL_MAP_UPDATE_METHOD_SCM = 0x01; + //This stream uses the triggered CSB sync train method to transport AFH channel map + // updates from broadcaster to receivers. + public static final long BSSR_AFH_CHANNEL_MAP_UPDATE_METHOD_TRIGGERED_SYNC_TRAIN = 0x02; + + public static final int BSSR_TYPE_CODEC_CONFIG_CELT_FREQ_ID = 10; + public static final int BSSR_TYPE_CODEC_CONFIG_CELT_FREQ_ID_LEN = 2; + public static final long BSSR_CODEC_FREQ_8KHZ = 0x0001; + public static final long BSSR_CODEC_FREQ_11025HZ = 0x0002; + public static final long BSSR_CODEC_FREQ_12KHZ = 0x0004; + public static final long BSSR_CODEC_FREQ_16KHZ = 0x0008; + public static final long BSSR_CODEC_FREQ_22050HZ = 0x0010; + public static final long BSSR_CODEC_FREQ_24KHZ = 0x0020; + public static final long BSSR_CODEC_FREQ_32KHZ = 0x0040; + public static final long BSSR_CODEC_FREQ_44100HZ = 0x0080; + public static final long BSSR_CODEC_FREQ_48KHZ = 0x0100; + public static final long BSSR_CODEC_FREQ_64KHZ = 0x0200; + public static final long BSSR_CODEC_FREQ_88200HZ = 0x0400; + public static final long BSSR_CODEC_FREQ_96KHZ = 0x0800; + public static final long BSSR_CODEC_FREQ_128KHZ = 0x1000; + public static final long BSSR_CODEC_FREQ_176400HZ = 0x2000; + public static final long BSSR_CODEC_FREQ_192KHZ = 0x4000; + + public static final int BSSR_TYPE_CODEC_CONFIG_CELT_FRAME_SIZE_ID = 11; + public static final int BSSR_TYPE_CODEC_CONFIG_CELT_FRAME_SIZE_ID_LEN = 2; + // actual values would be returned + + public static final int BSSR_TYPE_CODEC_CONFIG_CELT_FRAME_SAMPLES_ID = 12; + public static final int BSSR_TYPE_CODEC_CONFIG_CELT_FRAME_SAMPLES_ID_LEN = 2; + // actual values would be returned + + + /* + * Every single record will be a HashMap of a number of record. + * We will have a List of HashMap to send all possible values of stream records. + */ + //private Map<Integer, Long> mServiceRecord = new HashMap<Integer, Long>(); + int mNumRecords; + private List<Map<Integer, Long>> mServiceRecordList = new ArrayList<Map<Integer, Long>>(); + + public int describeContents() { + return 0; + } + + public void writeToParcel(Parcel out, int flags) { + out.writeInt(mServiceRecordList.size());// number of records + for (Map<Integer, Long> mServiceRecord : mServiceRecordList) { + // first put size of this entry + out.writeInt(mServiceRecord.size()); + for(Map.Entry<Integer, Long>entry: mServiceRecord.entrySet()) { + // lets write key, value pair + out.writeInt(entry.getKey()); + out.writeLong(entry.getValue()); + } + } + } + + public static final Parcelable.Creator<BluetoothBAStreamServiceRecord> CREATOR + = new Parcelable.Creator<BluetoothBAStreamServiceRecord>() { + public BluetoothBAStreamServiceRecord createFromParcel(Parcel in) { + return new BluetoothBAStreamServiceRecord(in); + } + + public BluetoothBAStreamServiceRecord[] newArray(int size) { + return new BluetoothBAStreamServiceRecord[size]; + } + }; + + private BluetoothBAStreamServiceRecord(Parcel in) { + mNumRecords = in.readInt(); + int recordSize = 0; + for (int i = 0; i < mNumRecords; i++) { + Map<Integer, Long> mServiceRecord = new HashMap<Integer, Long>(); + recordSize = in.readInt(); + for (int k = 0; k <recordSize; k++ ) { + mServiceRecord.put(in.readInt(), in.readLong()); + } + mServiceRecordList.add(mServiceRecord); + } + } + + /** + * Create a new BA Service Record Object. + * + * @param number of records + */ + public BluetoothBAStreamServiceRecord(int numRec) { + mNumRecords = numRec; + } + + /** + * Get number of records. + * + * @return number of records + */ + public int getNumRecords() { + return mNumRecords; + } + + /** + * Add a record value. + * + * @param streamId: streamId of the record. + * @param recordAttribId: one of the record attribute as mentioned above. + * @param recordAttribVal: one of the record attribute values as mentioned above. + */ + public void addServiceRecordValue(Long streamId, int recordAttribId, Long recordAttribVal) { + // find streamId in the list. + if (!mServiceRecordList.isEmpty()) { + for (Map<Integer, Long> mServiceRecord: mServiceRecordList) { + if (mServiceRecord.containsKey(BSSR_TYPE_STREAM_ID) && + mServiceRecord.get(BSSR_TYPE_STREAM_ID).equals(streamId)) { + mServiceRecord.put(recordAttribId, recordAttribVal); + return; + } + } + } + // either list is empty or matching record not found. + Map<Integer, Long> mServiceRecord = new HashMap<Integer, Long>(); + mServiceRecord.put(BSSR_TYPE_STREAM_ID, streamId); + mServiceRecord.put(recordAttribId, recordAttribVal); + mServiceRecordList.add(mServiceRecord); + } + + /** + * Add a record . + * + * @param serviceRecord: a Map of service attribute id and attribute values. + */ + public void addServiceRecord(Map<Integer, Long> mServiceRecord) { + // if a record with same stream_id is existing, we will remove old record and add new one. + // We are not going to change this record. + if(mServiceRecordList.isEmpty()) { + mServiceRecordList.add(mServiceRecord); + return; + } + // check if we have record with same stream id + for (Map<Integer, Long> mRecord: mServiceRecordList) { + if (mRecord.containsKey(BSSR_TYPE_STREAM_ID) && + mRecord.get(BSSR_TYPE_STREAM_ID).equals(mServiceRecord.get(BSSR_TYPE_STREAM_ID))) { + // delete this record from List + mServiceRecordList.remove(mRecord); + } + } + // either record is not found, or removed. + mServiceRecordList.add(mServiceRecord); + } + + /** + * Get record values. + * + * @param streamId: streamId of the record. + * @param recordAttribId: one of the record attribute as mentioned above. + * @return one of the record attribute values as mentioned above, 0 otherwise + */ + public Long getServiceRecordValue(Long streamId, int recordAttribId) { + // find streamId in the list. + if (!mServiceRecordList.isEmpty()) { + for (Map<Integer, Long> mServiceRecord: mServiceRecordList) { + if (mServiceRecord.containsKey(BSSR_TYPE_STREAM_ID) && + mServiceRecord.get(BSSR_TYPE_STREAM_ID).equals(streamId)) { + return mServiceRecord.get(recordAttribId); + } + } + } + // either list is empty or matching record not found. + return new Long(0); + } + + /** + * Get record . + * + * @param streamId: streamId of the Record to be fetched. + * @return servicerecord if streamId matches, empty record otherwise; + */ + public Map<Integer, Long> getServiceRecord( Long streamId) { + if(mServiceRecordList.isEmpty()) + return null; + for (Map<Integer, Long> mServiceRecord: mServiceRecordList) { + if (mServiceRecord.containsKey(BSSR_TYPE_STREAM_ID) && + mServiceRecord.get(BSSR_TYPE_STREAM_ID).equals(streamId)) { + return mServiceRecord; + } + } + // can't find record, return empty record + return null; + } + + /** + * Get all stored streamIds . + * + * @return array of all streamIds + */ + public Long[] getStreamIds() { + if(mServiceRecordList.isEmpty()) + return null; + Long[] streamIdList = new Long[mServiceRecordList.size()]; + int k = 0; + for (Map<Integer, Long> mServiceRecord: mServiceRecordList) { + if (mServiceRecord.containsKey(BSSR_TYPE_STREAM_ID)) + streamIdList[k++] = mServiceRecord.get(BSSR_TYPE_STREAM_ID); + } + return streamIdList; + } +} diff --git a/core/java/android/bluetooth/BluetoothBATransmitter.java b/core/java/android/bluetooth/BluetoothBATransmitter.java new file mode 100644 index 000000000000..68a06aef539a --- /dev/null +++ b/core/java/android/bluetooth/BluetoothBATransmitter.java @@ -0,0 +1,519 @@ +/* + * Copyright (c) 2017, The Linux Foundation. All rights reserved. + * Not a Contribution. + */ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.bluetooth; + +import android.Manifest; +import android.annotation.RequiresPermission; +import android.annotation.SdkConstant; +import android.annotation.SdkConstant.SdkConstantType; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.media.AudioManager; +import android.os.Binder; +import android.os.IBinder; +import android.os.ParcelUuid; +import android.os.RemoteException; +import android.util.Log; + +import com.android.internal.annotations.GuardedBy; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.locks.ReentrantReadWriteLock; + + +/** + * This class provides the public APIs to control the Bluetooth Broadcast Audio Transmitter + * profile. + * + *<p>BluetoothBroadcastAudio is a proxy object for controlling the Bluetooth Broadcast Audio + * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get + * the BluetoothA2dp proxy object. + * + * @hide + */ +public final class BluetoothBATransmitter implements BluetoothProfile { + private static final String TAG = "BluetoothBAT"; + private static final boolean DBG = true; + private static final boolean VDBG = false; + + /** + * Intent used to update state change of Broadcast Audio Transmitter. + * + * This intent will have 2 extras: + * #EXTRA_STATE - The current state of the profile. + * #EXTRA_PREVIOUS_STATE - The previous state of the profile. + * + * value of states can be any of + * STATE_DISABLED: Broadcast Audio is disabled. + * STATE_PAUSED: Broadcast Audio is enabled but streaming is paused. + * STATE_PLAYING: Broadcast Audio is enabled but streaming is ongoing. + * + */ + public static final String ACTION_BAT_STATE_CHANGED = + "android.bluetooth.bat.profile.action.BA_STATE_CHANGED"; + public static final String EXTRA_STATE = + "android.bluetooth.bat.profile.extra.STATE"; + + /** + * Intent used to update encryption key . + * + * This intent will have 1 extra: + * #EXTRA_ENCRYPTION_KEY - The current value of encryption key. + * + * value of EncyptionKey would be 128-bit value. This value would change + * on every new BA session. We will send BluetoothBAEncryptionKey object. + * + */ + public static final String ACTION_BAT_ENCRYPTION_KEY_CHANGED = + "android.bluetooth.bat.profile.action.BA_ENC_KEY_CHANGED"; + public static final String EXTRA_ECNRYPTION_KEY = + "android.bluetooth.bat.profile.extra.ENC_KEY"; + + /** + * Intent used to update DIV value . + * + * This intent will have 1 extras: + * #EXTRA_DIV_VALUE - The current value of DIV. + * + * value of DIV would be 2 byte value. This value would change + * on every new BA session. We will send integer value. + * + */ + public static final String ACTION_BAT_DIV_CHANGED = + "android.bluetooth.bat.profile.action.BA_DIV_CHANGED"; + public static final String EXTRA_DIV_VALUE = + "android.bluetooth.bat.profile.extra.DIV"; + + /** + * Intent used to update active stream id for Broadcast Audio Transmitter. + * + * This intent will have 1 extra: + * #EXTRA_STREAM_ID - The active streaming id. + * + * value of states can be any of + * 0: Broadcast Audio is not in STATE_PLAYING. + * valid streaming id: Valid streaming id if BA is in STATE_PLAYING. + */ + public static final String ACTION_BAT_STREAMING_ID_CHANGED = + "android.bluetooth.bat.profile.action.BA_STR_ID_CHANGED"; + public static final String EXTRA_STREAM_ID = + "android.bluetooth.bat.profile.extra.STR_ID"; + + /** + * Intent used to update Vendor Specific AVRCP Command. + * + * This intent will be sent whenever there is Vendor Specific AVRCP command + * received from primary headset. + * + * This intent will have 2 extra: + * #EXTRA_AVRCP_VS_ENABLE_BA - value describing enable/disable of BA. + * #EXTRA_AVRCP_VS_ENABLE_RA - value describing enable/disable of receiver + * association mode. + * + * value of states can be any of + * 0: Disable BA/RA. + * 1: ENABLE BA/RA. + */ + public static final String ACTION_BAT_AVRCP_VS_CMD = + "android.bluetooth.bat.profile.action.BA_AVRCP_VS_CMD"; + public static final String EXTRA_AVRCP_VS_ENABLE_BA = + "android.bluetooth.bat.profile.extra.ENABLE_BA"; + public static final String EXTRA_AVRCP_VS_ENABLE_RA = + "android.bluetooth.bat.profile.extra.ENABLE_RA"; + + + public static final int STATE_DISABLED = 0; + public static final int STATE_PAUSED = 1; + public static final int STATE_PLAYING = 2; + + public static final int ENABLE_BA_TRANSMITTER = 0; + public static final int DISABLE_BA_TRANSMITTER = 1; + + public static final int INVALID_DIV = 0xFFFF; + + private Context mContext; + private ServiceListener mServiceListener; + private final ReentrantReadWriteLock mServiceLock = new ReentrantReadWriteLock(); + @GuardedBy("mServiceLock") private IBluetoothBATransmitter mService; + private BluetoothAdapter mAdapter; + + final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback = + new IBluetoothStateChangeCallback.Stub() { + public void onBluetoothStateChange(boolean up) { + if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up); + if (!up) { + if (DBG) Log.d(TAG, "Unbinding service..."); + try { + mServiceLock.writeLock().lock(); + mService = null; + mContext.unbindService(mConnection); + } catch (Exception re) { + Log.e(TAG, "", re); + } finally { + mServiceLock.writeLock().unlock(); + } + } else { + try { + mServiceLock.readLock().lock(); + if (mService == null) { + if (DBG) Log.d(TAG,"Binding service..."); + doBind(); + } + } catch (Exception re) { + Log.e(TAG,"",re); + } finally { + mServiceLock.readLock().unlock(); + } + } + } + }; + /** + * Create a BluetoothBAT proxy object for interacting with the local + * Bluetooth Broadcast Audio Transmitter service. + * + */ + /*package*/ BluetoothBATransmitter(Context context, ServiceListener l) { + mContext = context; + mServiceListener = l; + mAdapter = BluetoothAdapter.getDefaultAdapter(); + IBluetoothManager mgr = mAdapter.getBluetoothManager(); + if (mgr != null) { + try { + mgr.registerStateChangeCallback(mBluetoothStateChangeCallback); + } catch (RemoteException e) { + Log.e(TAG,"",e); + } + } + + doBind(); + } + + boolean doBind() { + Intent intent = new Intent(IBluetoothBATransmitter.class.getName()); + ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); + intent.setComponent(comp); + if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0, + android.os.Process.myUserHandle())) { + Log.e(TAG, "Could not bind to Bluetooth Broadcast Audio Transmitter Service " + intent); + return false; + } + return true; + } + + /*package*/ void close() { + mServiceListener = null; + IBluetoothManager mgr = mAdapter.getBluetoothManager(); + if (mgr != null) { + try { + mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback); + } catch (Exception e) { + Log.e(TAG,"",e); + } + } + + try { + mServiceLock.writeLock().lock(); + if (mService != null) { + mService = null; + mContext.unbindService(mConnection); + } + } catch (Exception re) { + Log.e(TAG, "", re); + } finally { + mServiceLock.writeLock().unlock(); + } + } + + public void finalize() { + // The empty finalize needs to be kept or the + // cts signature tests would fail. + } + + /** + * Enable/Diasble BroadcastAudio Transmitter session. + * + * This API returns false if Broadcast Audio Transmitter is in + * same state as requested or Bluetooth is not turned on. + * When this API returns true, it is guaranteed that + * state change intent would be sent with the current state. + * Users can get the current state of BA_Transmitter + * from this intent. + * + * @param state: ENABLE_BA_TRANSMITTER/DISABLE_BA_TRANSMITTER + * @return false on immediate error, + * true otherwise + * @hide + */ + public boolean setBATState(int state) { + if (DBG) log("setBATState(" + state + ")"); + try { + mServiceLock.readLock().lock(); + if (mService != null && isEnabled()) { + return mService.setBATState(state); + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return false; + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + return false; + } finally { + mServiceLock.readLock().unlock(); + } + } + + /** + * get the current state of Broadcast Audio Transmitter. + * + * This API returns current state of BA Transmitter, which + * is one of the values mentioned above. + * STATE_DISABLED, STATE_PAUSED, STATE_PLAYING + * If BT is turned off or BATService is not launched, we would + * always return STATE_DISABLED + * + * @return current state of BA, if BT is on and BA Service launched + * STATE_DISABLED otherwise + * @hide + */ + public int getBATState() { + if (DBG) log("getBATState"); + try { + mServiceLock.readLock().lock(); + if (mService != null && isEnabled()) { + return mService.getBATState(); + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return STATE_DISABLED; + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + return STATE_DISABLED; + } finally { + mServiceLock.readLock().unlock(); + } + } + + /** + * get the current of Dynamic Interrupt Vector for this BA SESSION. + * + * This API returns current value of DIV for ongoing BA session. + * Only last 2 bytes are significant. + * If BA is in STATE_DISABLED, or Bluetooth is not turned on + * this api would return INVALID_DIV as defined above. + * + * @return current value of DIV, if BT is on and BA is not in disabled state. + * INVALID_DIV otherwise + * @hide + */ + public int getDIV() { + if (DBG) log("getDIV"); + try { + mServiceLock.readLock().lock(); + if (mService != null && isEnabled()) { + return mService.getDIV(); + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return INVALID_DIV; + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + return INVALID_DIV; + } finally { + mServiceLock.readLock().unlock(); + } + } + + /** + * get the current stream ID. + * + * This API returns current value of stream id if BA is in STATE_PLAYING. + * Otherwise it will always return 0 + * + * @return current value of stream id, if BT is on and BA is in STATE_PLAYING. + * 0 otherwise + * @hide + */ + public long getStreamId() { + if (DBG) log("getStreamId"); + try { + mServiceLock.readLock().lock(); + if (mService != null && isEnabled()) { + return mService.getStreamId(); + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return 0; + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + return 0; + } finally { + mServiceLock.readLock().unlock(); + } + } + + /** + * get the current encryption key. + * + * This API returns current value of encryption key if BA is not in in STATE_DISABLED. + * Otherwise it will always return null + * + * @return current value of encryption key(BluetoothBAEncryptionKey), if BT is on and + * BA is not in STATE_DISABLED, null otherwise + * + * @hide + */ + public BluetoothBAEncryptionKey getEncryptionKey() { + if (DBG) log("getEncryptionKey"); + try { + mServiceLock.readLock().lock(); + if (mService != null && isEnabled()) { + return mService.getEncryptionKey(); + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return null; + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + return null; + } finally { + mServiceLock.readLock().unlock(); + } + } + + /** + * Refreshes current Encryption Key. + * + * This API refreshes encryption key BA is not in in STATE_DISABLED, or BT is enabled + * if request is accepted, a guranteed intent would be posted with new value of Encryption key + * + * @return immediate value of request , true if BT is on and + * BA is not in STATE_DISABLED, false otherwise + * + * @hide + */ + public boolean refreshEncryptionKey() { + if (DBG) log("getEncryptionKey"); + try { + mServiceLock.readLock().lock(); + if (mService != null && isEnabled()) { + return mService.refreshEncryptionKey(); + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return false; + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + return false; + } finally { + mServiceLock.readLock().unlock(); + } + } + + /** + * get supported service records. + * + * This API returns supported service record, if BT is on and BAService is running. + * Otherwise it will always return null + * + * @return supported service record, if BT is on and BAService is running. + * null otherwise + * @hide + */ + public BluetoothBAStreamServiceRecord getBAServiceRecord() { + if (DBG) log("getBAServiceRecord"); + try { + mServiceLock.readLock().lock(); + if (mService != null && isEnabled()) { + return mService.getBAServiceRecord(); + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return null; + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + return null; + } finally { + mServiceLock.readLock().unlock(); + } + } + + /** + * this is dummpy implementation, because we have to inherit an interface BluetoothProfile + * This will always return empty list. + */ + public List<BluetoothDevice> getConnectedDevices() { + if (DBG) log("getConnectedDevices() dummy impl"); + return new ArrayList<BluetoothDevice>(); + } + + /** + * this is dummpy implementation, because we have to inherit an interface BluetoothProfile + * This will always return empty list. + */ + public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { + if (DBG) log("getDevicesMatchingStates() dummy impl"); + return new ArrayList<BluetoothDevice>(); + } + + /** + * this is dummpy implementation, because we have to inherit an interface BluetoothProfile + * This will always return STATE_DISCONNECTED as there is no connection in BA. + */ + public int getConnectionState(BluetoothDevice device) { + if (DBG) log("getConnectionState() dummy impl"); + return BluetoothProfile.STATE_DISCONNECTED; + } + + private final ServiceConnection mConnection = new ServiceConnection() { + public void onServiceConnected(ComponentName className, IBinder service) { + if (DBG) Log.d(TAG, "Proxy object connected"); + try { + mServiceLock.writeLock().lock(); + mService = IBluetoothBATransmitter.Stub.asInterface(Binder.allowBlocking(service)); + } finally { + mServiceLock.writeLock().unlock(); + } + + if (mServiceListener != null) { + mServiceListener.onServiceConnected(BluetoothProfile.BA_TRANSMITTER, + BluetoothBATransmitter.this); + } + } + + public void onServiceDisconnected(ComponentName className) { + if (DBG) Log.d(TAG, "Proxy object disconnected"); + try { + mServiceLock.writeLock().lock(); + mService = null; + } finally { + mServiceLock.writeLock().unlock(); + } + if (mServiceListener != null) { + mServiceListener.onServiceDisconnected(BluetoothProfile.BA_TRANSMITTER); + } + } + }; + + private boolean isEnabled() { + if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true; + return false; + } + + private static void log(String msg) { + Log.d(TAG, msg); + } +} diff --git a/core/java/android/bluetooth/BluetoothCodecConfig.java b/core/java/android/bluetooth/BluetoothCodecConfig.java index c9d0ef247ca5..5a8270e45092 100644 --- a/core/java/android/bluetooth/BluetoothCodecConfig.java +++ b/core/java/android/bluetooth/BluetoothCodecConfig.java @@ -44,7 +44,9 @@ public final class BluetoothCodecConfig implements Parcelable { @UnsupportedAppUsage public static final int SOURCE_CODEC_TYPE_LDAC = 4; @UnsupportedAppUsage - public static final int SOURCE_CODEC_TYPE_MAX = 5; + public static final int SOURCE_CODEC_TYPE_APTX_ADAPTIVE = 5; + @UnsupportedAppUsage + public static final int SOURCE_CODEC_TYPE_MAX = 6; @UnsupportedAppUsage public static final int SOURCE_CODEC_TYPE_INVALID = 1000 * 1000; @@ -301,6 +303,8 @@ public final class BluetoothCodecConfig implements Parcelable { return "aptX HD"; case SOURCE_CODEC_TYPE_LDAC: return "LDAC"; + case SOURCE_CODEC_TYPE_APTX_ADAPTIVE: + return "aptX Adaptive"; case SOURCE_CODEC_TYPE_INVALID: return "INVALID CODEC"; default: diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java index 235dc5c59c2a..c9cfcf6f28b2 100644 --- a/core/java/android/bluetooth/BluetoothDevice.java +++ b/core/java/android/bluetooth/BluetoothDevice.java @@ -1,4 +1,39 @@ /* + * Copyright (C) 2017, The Linux Foundation. All rights reserved. + * Not a Contribution. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted (subject to the limitations in the + * disclaimer below) provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE + * GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT + * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* * Copyright (C) 2009 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -191,6 +226,18 @@ public final class BluetoothDevice implements Parcelable { public static final String ACTION_BOND_STATE_CHANGED = "android.bluetooth.device.action.BOND_STATE_CHANGED"; + /** + * Broadcast Action: Broadcast details of IOT device when an IOT + * related issue is observed. + * <p>Always contains the extra fields {@link #EXTRA_NAME}. + * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive. + * @hide + **/ + + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_REMOTE_ISSUE_OCCURRED = + "org.codeaurora.intent.bluetooth.action.REMOTE_ISSUE_OCCURRED"; + /** * Broadcast Action: Indicates the battery level of a remote device has * been retrieved for the first time, or changed since the last retrieval @@ -223,6 +270,17 @@ public final class BluetoothDevice implements Parcelable { public static final int BATTERY_LEVEL_UNKNOWN = -1; /** + * Broadcast Action: Indicates the remote devices are TWS plus earbuds pair. + * <p>Always contains the extra fields {@link #EXTRA_TWS_PLUS_DEVICE1}, + * {@link #EXTRA_TWS_PLUS_DEVICE2}. + * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive. + * @hide + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_TWS_PLUS_DEVICE_PAIR = + "android.bluetooth.device.action.TWS_PLUS_DEVICE_PAIR"; + + /** * Used as a Parcelable {@link BluetoothDevice} extra field in every intent * broadcast by this class. It contains the {@link BluetoothDevice} that * the intent applies to. @@ -236,6 +294,70 @@ public final class BluetoothDevice implements Parcelable { public static final String EXTRA_NAME = "android.bluetooth.device.extra.NAME"; /** + * Used as a String extra field in {@link #ACTION_REMOTE_ISSUE_OCCURRED} + * intents. It contains the type of IOT issue that occurred. + * @hide + */ + public static final String EXTRA_ISSUE_TYPE = "android.bluetooth.qti.extra.ERROR_TYPE"; + + /** + * Used as a String extra field in {@link #ACTION_REMOTE_ISSUE_OCCURRED} intents. + * It contains the details of details of the issue. + * @hide + */ + public static final String EXTRA_ERROR_CODE = "android.bluetooth.qti.extra.ERROR_CODE"; + + /** + * Used as a String extra field in {@link #ACTION_REMOTE_ISSUE_OCCURRED} intents. + * It contains the SoC event mask when issue occurred. + * @hide + */ + public static final String EXTRA_ERROR_EVENT_MASK = "android.bluetooth.qti.extra.ERROR_EVENT_MASK"; + + /** + * Used as a String extra field in {@link #ACTION_REMOTE_ISSUE_OCCURRED} intents. + * It contains the LMP Version of IOT device. + * @hide + */ + public static final String EXTRA_LMP_VERSION = "android.bluetooth.qti.extra.EXTRA_LMP_VERSION"; + + /** + * Used as a String extra field in {@link #ACTION_REMOTE_ISSUE_OCCURRED} intents. + * It contains the LMP Sub Version of IOT device. + * @hide + */ + public static final String EXTRA_LMP_SUBVER = "android.bluetooth.qti.extra.EXTRA_LMP_SUBVER"; + + /** + * Used as a String extra field in {@link #ACTION_REMOTE_ISSUE_OCCURRED} intents. + * It contains the Manufacturer ID of IOT device. + * @hide + */ + public static final String EXTRA_MANUFACTURER = "android.bluetooth.qti.extra.EXTRA_MANUFACTURER"; + + /** + * Used as a String extra field in {@link #ACTION_REMOTE_ISSUE_OCCURRED} intents. + * It contains the Power level. + * @hide + */ + public static final String EXTRA_POWER_LEVEL = "android.bluetooth.qti.extra.EXTRA_POWER_LEVEL"; + + /** + * Used as a String extra field in {@link #ACTION_REMOTE_ISSUE_OCCURRED} intents. + * It contains the Link Quality of the connection. + * @hide + */ + public static final String EXTRA_LINK_QUALITY = "android.bluetooth.qti.extra.EXTRA_LINK_QUALITY"; + + /** + * Used as a String extra field in {@link #ACTION_REMOTE_ISSUE_OCCURRED} intents. + * It contains the coutnt of glitches occured since last broadcast. + * @hide + */ + public static final String EXTRA_GLITCH_COUNT = "android.bluetooth.qti.extra.EXTRA_GLITCH_COUNT"; + + + /** * Used as an optional short extra field in {@link #ACTION_FOUND} intents. * Contains the RSSI value of the remote device as reported by the * Bluetooth hardware. @@ -267,6 +389,23 @@ public final class BluetoothDevice implements Parcelable { */ public static final String EXTRA_PREVIOUS_BOND_STATE = "android.bluetooth.device.extra.PREVIOUS_BOND_STATE"; + + /** + * Used as a String extra field in {@link #ACTION_TWS+_DEVICE_PAIR} + * intents. It contains the first TWS+ earbud address of pair. + * @hide + */ + public static final String EXTRA_TWS_PLUS_DEVICE1 = + "android.bluetooth.device.extra.EXTRA_TWS_PLUS_DEVICE1"; + + /** + * Used as a String extra field in {@link #ACTION_TWS+_DEVICE_PAIR} + * intents. It contains the second TWS+ earbud address of pair. + * @hide + */ + public static final String EXTRA_TWS_PLUS_DEVICE2 = + "android.bluetooth.device.extra.EXTRA_TWS_PLUS_DEVICE2"; + /** * Indicates the remote device is not bonded (paired). * <p>There is no shared link key with the remote device, so communication @@ -736,9 +875,10 @@ public final class BluetoothDevice implements Parcelable { public void onBluetoothServiceUp(IBluetooth bluetoothService) throws RemoteException { synchronized (BluetoothDevice.class) { - if (sService == null) { - sService = bluetoothService; + if (sService != null) { + Log.w(TAG, "sService is not NULL"); } + sService = bluetoothService; } } @@ -1343,6 +1483,41 @@ public final class BluetoothDevice implements Parcelable { } /** + * Returns whether if the device is TWS+ device. + * + * @return True if the devcie is TWS+ device. + * @hide + */ + public boolean isTwsPlusDevice() { + if (sService == null) { + Log.e(TAG, "BT not enabled. Cannot query remote device sdp records"); + return false; + } + try { + return sService.isTwsPlusDevice(this); + } catch (RemoteException e) {Log.e(TAG, "", e);} + return false; + } + + /** + * Get the TWS+ peer address of the remote device. + * + * @return the TWS+ peer address of the remote device if available, otherwise + * null. + * @hide + */ + public String getTwsPlusPeerAddress() { + if (sService == null) { + Log.e(TAG, "BT not enabled. Cannot get Remote Device name"); + return null; + } + try { + return sService.getTwsPlusPeerAddress(this); + } catch (RemoteException e) {Log.e(TAG, "", e);} + return null; + } + + /** * Set the pin during pairing when the pairing method is {@link #PAIRING_VARIANT_PIN} * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}. * diff --git a/core/java/android/bluetooth/BluetoothDun.java b/core/java/android/bluetooth/BluetoothDun.java new file mode 100644 index 000000000000..cbf44e54dd77 --- /dev/null +++ b/core/java/android/bluetooth/BluetoothDun.java @@ -0,0 +1,296 @@ +/* +*Copyright (c) 2018, The Linux Foundation. All rights reserved. +* +*Redistribution and use in source and binary forms, with or without +*modification, are permitted provided that the following conditions are +*met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of The Linux Foundation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +*THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +*WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +*MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +*ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +*BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +*CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +*SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +*BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +*WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +*OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +*IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +package android.bluetooth; + +import android.annotation.SdkConstant; +import android.annotation.SdkConstant.SdkConstantType; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.IBinder; +import android.os.RemoteException; +import android.util.Log; + +import java.util.ArrayList; +import java.util.List; + +/** + * This class provides the APIs to control the Bluetooth Dun + * Profile. + * + *<p>BluetoothDun is a proxy object for controlling the Bluetooth DUN + * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get + * the BluetoothDun proxy object. + * + *<p>Each method is protected with its appropriate permission. + *@hide + */ +public final class BluetoothDun implements BluetoothProfile { + private static final String TAG = "BluetoothDun"; + private static final boolean DBG = false; + private static final boolean VDBG = false; + + /** + * Intent used to broadcast the change in connection state of the Dun + * profile. + * + * <p>This intent will have 3 extras: + * <ul> + * <li> {@link #EXTRA_STATE} - The current state of the profile. </li> + * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.</li> + * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li> + * </ul> + * + * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of + * {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTED}. + * + * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to + * receive. + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_CONNECTION_STATE_CHANGED = + "codeaurora.bluetooth.dun.profile.action.CONNECTION_STATE_CHANGED"; + + private Context mContext; + private ServiceListener mServiceListener; + private BluetoothAdapter mAdapter; + private IBluetoothDun mDunService; + + /** + * Create a BluetoothDun proxy object for interacting with the local + * Bluetooth Service which handles the Dun profile + * + */ + /*package*/ BluetoothDun(Context context, ServiceListener l) { + mContext = context; + mServiceListener = l; + mAdapter = BluetoothAdapter.getDefaultAdapter(); + try { + mAdapter.getBluetoothManager().registerStateChangeCallback(mStateChangeCallback); + } catch (RemoteException re) { + Log.w(TAG,"Unable to register BluetoothStateChangeCallback",re); + } + Log.d(TAG, "BluetoothDun() call bindService"); + doBind(); + } + + boolean doBind() { + Intent intent = new Intent(IBluetoothDun.class.getName()); + ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); + intent.setComponent(comp); + if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0, + android.os.Process.myUserHandle())) { + Log.e(TAG, "Could not bind to Bluetooth Dun Service with " + intent); + return false; + } + return true; + } + + + /*package*/ void close() { + if (VDBG) log("close()"); + mServiceListener = null; + IBluetoothManager mgr = mAdapter.getBluetoothManager(); + if (mgr != null) { + try { + mgr.unregisterStateChangeCallback(mStateChangeCallback); + } catch (RemoteException re) { + Log.w(TAG,"Unable to unregister BluetoothStateChangeCallback",re); + } + } + + synchronized (mConnection) { + if ( mDunService != null) { + try { + mDunService = null; + mContext.unbindService(mConnection); + } catch (Exception re) { + Log.e(TAG,"",re); + } + } + } + } + + protected void finalize() { + close(); + } + + private IBluetoothStateChangeCallback mStateChangeCallback = + new IBluetoothStateChangeCallback.Stub() { + + @Override + public void onBluetoothStateChange(boolean on) { + //Handle enable request to bind again. + Log.d(TAG, "onBluetoothStateChange on: " + on); + if (on) { + try { + if (mDunService == null) { + Log.d(TAG, "onBluetoothStateChange call bindService"); + doBind(); + } + } catch (IllegalStateException e) { + Log.e(TAG,"onBluetoothStateChange: could not bind to DUN service: ", e); + } catch (SecurityException e) { + Log.e(TAG,"onBluetoothStateChange: could not bind to DUN service: ", e); + } + } else { + if (VDBG) Log.d(TAG,"Unbinding service..."); + synchronized (mConnection) { + if ( mDunService != null) { + try { + mDunService = null; + mContext.unbindService(mConnection); + } catch (Exception re) { + Log.e(TAG,"",re); + } + } + } + } + } + }; + + /** + * Initiate disconnection from DUN server. + * + * <p> Once the disconnection is initiated by any device either local host + * or remote device, the state will transition from {@link #STATE_CONNECTED} + * to {@link #STATE_DISCONNECTED}. + * + * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} + * permission. + * + * @param device Remote Bluetooth Device + * @return false on immediate error, + * true otherwise + * @hide + */ + public boolean disconnect(BluetoothDevice device) { + if (DBG) log("disconnect(" + device + ")"); + if (mDunService != null && isEnabled() && + isValidDevice(device)) { + try { + return mDunService.disconnect(device); + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + return false; + } + } + if (mDunService == null) Log.w(TAG, "Proxy not attached to service"); + return false; + } + /** + * {@inheritDoc} + */ + public List<BluetoothDevice> getConnectedDevices() { + if (VDBG) log("getConnectedDevices()"); + if (mDunService != null && isEnabled()) { + try { + return mDunService.getConnectedDevices(); + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + return new ArrayList<BluetoothDevice>(); + } + } + if (mDunService == null) Log.w(TAG, "Proxy not attached to service"); + return new ArrayList<BluetoothDevice>(); + } + + /** + * {@inheritDoc} + */ + public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { + if (VDBG) log("getDevicesMatchingStates()"); + if (mDunService != null && isEnabled()) { + try { + return mDunService.getDevicesMatchingConnectionStates(states); + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + return new ArrayList<BluetoothDevice>(); + } + } + if (mDunService == null) Log.w(TAG, "Proxy not attached to service"); + return new ArrayList<BluetoothDevice>(); + } + + /** + * {@inheritDoc} + */ + public int getConnectionState(BluetoothDevice device) { + if (VDBG) log("getState(" + device + ")"); + if (mDunService != null && isEnabled() + && isValidDevice(device)) { + try { + return mDunService.getConnectionState(device); + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + return BluetoothProfile.STATE_DISCONNECTED; + } + } + if (mDunService == null) Log.w(TAG, "Proxy not attached to service"); + return BluetoothProfile.STATE_DISCONNECTED; + } + + private ServiceConnection mConnection = new ServiceConnection() { + public void onServiceConnected(ComponentName className, IBinder service) { + if (DBG) Log.d(TAG, "BluetoothDUN Proxy object connected"); + mDunService = IBluetoothDun.Stub.asInterface(service); + + if (mServiceListener != null) { + mServiceListener.onServiceConnected(BluetoothProfile.DUN, + BluetoothDun.this); + } + } + public void onServiceDisconnected(ComponentName className) { + if (DBG) Log.d(TAG, "BluetoothDUN Proxy object disconnected"); + mDunService = null; + if (mServiceListener != null) { + mServiceListener.onServiceDisconnected(BluetoothProfile.DUN); + } + } + }; + + private boolean isEnabled() { + if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true; + return false; + } + + private boolean isValidDevice(BluetoothDevice device) { + if (device == null) return false; + + if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true; + return false; + } + + private static void log(String msg) { + Log.d(TAG, msg); + } +} diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java index 8d9d340ee68b..6122be902bbc 100644 --- a/core/java/android/bluetooth/BluetoothHeadset.java +++ b/core/java/android/bluetooth/BluetoothHeadset.java @@ -33,8 +33,11 @@ import android.os.Message; import android.os.RemoteException; import android.util.Log; +import com.android.internal.annotations.GuardedBy; + import java.util.ArrayList; import java.util.List; +import java.util.concurrent.locks.ReentrantReadWriteLock; /** * Public API for controlling the Bluetooth Headset Service. This includes both @@ -329,7 +332,8 @@ public final class BluetoothHeadset implements BluetoothProfile { private Context mContext; private ServiceListener mServiceListener; - private volatile IBluetoothHeadset mService; + private final ReentrantReadWriteLock mServiceLock = new ReentrantReadWriteLock(); + @GuardedBy("mServiceLock") private IBluetoothHeadset mService; private BluetoothAdapter mAdapter; private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback = @@ -386,13 +390,11 @@ public final class BluetoothHeadset implements BluetoothProfile { void doUnbind() { synchronized (mConnection) { - if (mService != null) { - try { - mAdapter.getBluetoothManager().unbindBluetoothProfileService( - BluetoothProfile.HEADSET, mConnection); - } catch (RemoteException e) { - Log.e(TAG, "Unable to unbind HeadsetService", e); - } + try { + mAdapter.getBluetoothManager().unbindBluetoothProfileService( + BluetoothProfile.HEADSET, mConnection); + } catch (RemoteException e) { + Log.e(TAG, "Unable to unbind HeadsetService", e); } } } @@ -419,6 +421,10 @@ public final class BluetoothHeadset implements BluetoothProfile { doUnbind(); } + protected void finalize() { + close(); + } + /** * Initiate connection to a profile of the remote bluetooth device. * @@ -505,17 +511,22 @@ public final class BluetoothHeadset implements BluetoothProfile { @Override public List<BluetoothDevice> getConnectedDevices() { if (VDBG) log("getConnectedDevices()"); - final IBluetoothHeadset service = mService; - if (service != null && isEnabled()) { - try { - return service.getConnectedDevices(); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); - return new ArrayList<BluetoothDevice>(); + try { + mServiceLock.readLock().lock(); + final IBluetoothHeadset service = mService; + if (service != null && isEnabled()) { + try { + return service.getConnectedDevices(); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + return new ArrayList<BluetoothDevice>(); + } } + if (service == null) Log.w(TAG, "Proxy not attached to service"); + return new ArrayList<BluetoothDevice>(); + } finally { + mServiceLock.readLock().unlock(); } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return new ArrayList<BluetoothDevice>(); } /** @@ -695,14 +706,19 @@ public final class BluetoothHeadset implements BluetoothProfile { public boolean isAudioConnected(BluetoothDevice device) { if (VDBG) log("isAudioConnected()"); final IBluetoothHeadset service = mService; - if (service != null && isEnabled() && isValidDevice(device)) { - try { - return service.isAudioConnected(device); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); + try { + mServiceLock.readLock().lock(); + if (service != null && isEnabled() && isValidDevice(device)) { + try { + return service.isAudioConnected(device); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + } } + if (service == null) Log.w(TAG, "Proxy not attached to service"); + } finally { + mServiceLock.readLock().unlock(); } - if (service == null) Log.w(TAG, "Proxy not attached to service"); return false; } @@ -1161,17 +1177,27 @@ public final class BluetoothHeadset implements BluetoothProfile { @Override public void onServiceConnected(ComponentName className, IBinder service) { if (DBG) Log.d(TAG, "Proxy object connected"); - mService = IBluetoothHeadset.Stub.asInterface(Binder.allowBlocking(service)); - mHandler.sendMessage(mHandler.obtainMessage( - MESSAGE_HEADSET_SERVICE_CONNECTED)); + try { + mServiceLock.writeLock().lock(); + mService = IBluetoothHeadset.Stub.asInterface(Binder.allowBlocking(service)); + mHandler.sendMessage(mHandler.obtainMessage( + MESSAGE_HEADSET_SERVICE_CONNECTED)); + } finally { + mServiceLock.writeLock().unlock(); + } } @Override public void onServiceDisconnected(ComponentName className) { if (DBG) Log.d(TAG, "Proxy object disconnected"); - mService = null; - mHandler.sendMessage(mHandler.obtainMessage( - MESSAGE_HEADSET_SERVICE_DISCONNECTED)); + try { + mServiceLock.writeLock().lock(); + mService = null; + mHandler.sendMessage(mHandler.obtainMessage( + MESSAGE_HEADSET_SERVICE_DISCONNECTED)); + } finally { + mServiceLock.writeLock().unlock(); + } } }; diff --git a/core/java/android/bluetooth/BluetoothHearingAid.java b/core/java/android/bluetooth/BluetoothHearingAid.java index 6ed7942492b2..5b07dfd51056 100644 --- a/core/java/android/bluetooth/BluetoothHearingAid.java +++ b/core/java/android/bluetooth/BluetoothHearingAid.java @@ -158,8 +158,10 @@ public final class BluetoothHearingAid implements BluetoothProfile { if (VDBG) Log.d(TAG, "Unbinding service..."); try { mServiceLock.writeLock().lock(); - mService = null; - mContext.unbindService(mConnection); + if (mService != null) { + mService = null; + mContext.unbindService(mConnection); + } } catch (Exception re) { Log.e(TAG, "", re); } finally { diff --git a/core/java/android/bluetooth/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java index 3c87c739e1f6..7302756507a4 100644 --- a/core/java/android/bluetooth/BluetoothProfile.java +++ b/core/java/android/bluetooth/BluetoothProfile.java @@ -190,12 +190,24 @@ public interface BluetoothProfile { int HEARING_AID = 21; /** + * DUN + * @hide + */ + public static final int DUN = 22; + + /** + * BroadcastAudio Transmitter + * @hide + */ + int BA_TRANSMITTER = 23; + + /** * Max profile ID. This value should be updated whenever a new profile is added to match * the largest value assigned to a profile. * * @hide */ - int MAX_PROFILE_ID = 21; + int MAX_PROFILE_ID = 23; /** * Default priority for devices that we try to auto-connect to and diff --git a/core/java/android/bluetooth/BluetoothSocket.java b/core/java/android/bluetooth/BluetoothSocket.java index 3a1e2f58c99d..f5e39ae1c2bc 100644 --- a/core/java/android/bluetooth/BluetoothSocket.java +++ b/core/java/android/bluetooth/BluetoothSocket.java @@ -22,7 +22,6 @@ import android.os.ParcelFileDescriptor; import android.os.ParcelUuid; import android.os.RemoteException; import android.util.Log; - import java.io.Closeable; import java.io.FileDescriptor; import java.io.IOException; @@ -267,6 +266,7 @@ public final class BluetoothSocket implements Closeable { as.mSocketOS = as.mSocket.getOutputStream(); as.mAddress = remoteAddr; as.mDevice = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(remoteAddr); + as.mPort = mPort; return as; } @@ -802,5 +802,59 @@ public final class BluetoothSocket implements Closeable { return ret; } + /** + * setSocketOpt for the Buetooth Socket. + * + * @param optionName socket option name + * @param optionVal socket option value + * @param optionLen socket option length + * @return -1 on immediate error, + * 0 otherwise + * @hide + */ + public int setSocketOpt(int optionName, byte [] optionVal, int optionLen) throws IOException { + int ret = 0; + if (mSocketState == SocketState.CLOSED) throw new IOException("socket closed"); + IBluetooth bluetoothProxy = BluetoothAdapter.getDefaultAdapter().getBluetoothService(null); + if (bluetoothProxy == null) { + Log.e(TAG, "setSocketOpt fail, reason: bluetooth is off"); + return -1; + } + try { + if(VDBG) Log.d(TAG, "setSocketOpt(), mType: " + mType + " mPort: " + mPort); + ret = bluetoothProxy.setSocketOpt(mType, mPort, optionName, optionVal, optionLen); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + return -1; + } + return ret; + } + + /** + * getSocketOpt for the Buetooth Socket. + * + * @param optionName socket option name + * @param optionVal socket option value + * @return -1 on immediate error, + * length of returned socket option otherwise + * @hide + */ + public int getSocketOpt(int optionName, byte [] optionVal) throws IOException { + int ret = 0; + if (mSocketState == SocketState.CLOSED) throw new IOException("socket closed"); + IBluetooth bluetoothProxy = BluetoothAdapter.getDefaultAdapter().getBluetoothService(null); + if (bluetoothProxy == null) { + Log.e(TAG, "getSocketOpt fail, reason: bluetooth is off"); + return -1; + } + try { + if(VDBG) Log.d(TAG, "getSocketOpt(), mType: " + mType + " mPort: " + mPort); + ret = bluetoothProxy.getSocketOpt(mType, mPort, optionName, optionVal); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + return -1; + } + return ret; + } } diff --git a/core/java/android/bluetooth/le/AdvertiseData.java b/core/java/android/bluetooth/le/AdvertiseData.java index b65c31d1dcf7..c79f03ce1891 100644 --- a/core/java/android/bluetooth/le/AdvertiseData.java +++ b/core/java/android/bluetooth/le/AdvertiseData.java @@ -47,17 +47,20 @@ public final class AdvertiseData implements Parcelable { private final Map<ParcelUuid, byte[]> mServiceData; private final boolean mIncludeTxPowerLevel; private final boolean mIncludeDeviceName; + private final byte[] mTransportDiscoveryData; private AdvertiseData(List<ParcelUuid> serviceUuids, SparseArray<byte[]> manufacturerData, Map<ParcelUuid, byte[]> serviceData, boolean includeTxPowerLevel, - boolean includeDeviceName) { + boolean includeDeviceName, + byte[] transportDiscoveryData) { mServiceUuids = serviceUuids; mManufacturerSpecificData = manufacturerData; mServiceData = serviceData; mIncludeTxPowerLevel = includeTxPowerLevel; mIncludeDeviceName = includeDeviceName; + mTransportDiscoveryData = transportDiscoveryData; } /** @@ -98,12 +101,20 @@ public final class AdvertiseData implements Parcelable { } /** + * Returns an array of Transport Discovery data. + * @hide + */ + public byte[] getTransportDiscoveryData() { + return mTransportDiscoveryData; + } + + /** * @hide */ @Override public int hashCode() { return Objects.hash(mServiceUuids, mManufacturerSpecificData, mServiceData, - mIncludeDeviceName, mIncludeTxPowerLevel); + mIncludeDeviceName, mIncludeTxPowerLevel, mTransportDiscoveryData); } /** @@ -123,7 +134,8 @@ public final class AdvertiseData implements Parcelable { other.mManufacturerSpecificData) && BluetoothLeUtils.equals(mServiceData, other.mServiceData) && mIncludeDeviceName == other.mIncludeDeviceName - && mIncludeTxPowerLevel == other.mIncludeTxPowerLevel; + && mIncludeTxPowerLevel == other.mIncludeTxPowerLevel + && BluetoothLeUtils.equals(mTransportDiscoveryData, other.mTransportDiscoveryData); } @Override @@ -132,7 +144,8 @@ public final class AdvertiseData implements Parcelable { + BluetoothLeUtils.toString(mManufacturerSpecificData) + ", mServiceData=" + BluetoothLeUtils.toString(mServiceData) + ", mIncludeTxPowerLevel=" + mIncludeTxPowerLevel + ", mIncludeDeviceName=" - + mIncludeDeviceName + "]"; + + mIncludeDeviceName + ", mTransportDiscoveryData=" + + BluetoothLeUtils.toString(mTransportDiscoveryData)+ "]"; } @Override @@ -157,6 +170,10 @@ public final class AdvertiseData implements Parcelable { } dest.writeByte((byte) (getIncludeTxPowerLevel() ? 1 : 0)); dest.writeByte((byte) (getIncludeDeviceName() ? 1 : 0)); + dest.writeInt(mTransportDiscoveryData != null ? mTransportDiscoveryData.length : 0); + if (mTransportDiscoveryData != null) { + dest.writeByteArray(mTransportDiscoveryData); + } } public static final Parcelable.Creator<AdvertiseData> CREATOR = @@ -188,6 +205,11 @@ public final class AdvertiseData implements Parcelable { } builder.setIncludeTxPowerLevel(in.readByte() == 1); builder.setIncludeDeviceName(in.readByte() == 1); + int transportDiscoveryDataSize = in.readInt(); + if (transportDiscoveryDataSize > 0) { + byte[] transportDiscoveryData = in.createByteArray(); + builder.addTransportDiscoveryData(transportDiscoveryData); + } return builder.build(); } }; @@ -202,6 +224,7 @@ public final class AdvertiseData implements Parcelable { private Map<ParcelUuid, byte[]> mServiceData = new ArrayMap<ParcelUuid, byte[]>(); private boolean mIncludeTxPowerLevel; private boolean mIncludeDeviceName; + private byte[] mTransportDiscoveryData; /** * Add a service UUID to advertise data. @@ -276,11 +299,23 @@ public final class AdvertiseData implements Parcelable { } /** + * Add Transport Discovery data + * @hide + */ + public Builder addTransportDiscoveryData(byte[] transportDiscoveryData) { + if ((transportDiscoveryData == null) || (transportDiscoveryData.length == 0)) { + throw new IllegalArgumentException("transportDiscoveryData is null"); + } + mTransportDiscoveryData = transportDiscoveryData; + return this; + } + + /** * Build the {@link AdvertiseData}. */ public AdvertiseData build() { return new AdvertiseData(mServiceUuids, mManufacturerSpecificData, mServiceData, - mIncludeTxPowerLevel, mIncludeDeviceName); + mIncludeTxPowerLevel, mIncludeDeviceName, mTransportDiscoveryData); } } } diff --git a/core/java/android/bluetooth/le/BluetoothLeScanner.java b/core/java/android/bluetooth/le/BluetoothLeScanner.java index ac126ae0969d..440d047424b0 100644 --- a/core/java/android/bluetooth/le/BluetoothLeScanner.java +++ b/core/java/android/bluetooth/le/BluetoothLeScanner.java @@ -33,6 +33,7 @@ import android.os.RemoteException; import android.os.WorkSource; import android.util.Log; +import java.util.Arrays; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -228,6 +229,13 @@ public final class BluetoothLeScanner { if (gatt == null) { return postCallbackErrorOrReturn(callback, ScanCallback.SCAN_FAILED_INTERNAL_ERROR); } + + if ((settings.getCallbackType() == ScanSettings.CALLBACK_TYPE_SENSOR_ROUTING) + && (filters == null || filters.isEmpty())) { + ScanFilter filter = (new ScanFilter.Builder()).build(); + filters = Arrays.asList(filter); + } + if (!isSettingsConfigAllowedForScan(settings)) { return postCallbackErrorOrReturn(callback, ScanCallback.SCAN_FAILED_FEATURE_UNSUPPORTED); @@ -240,6 +248,10 @@ public final class BluetoothLeScanner { return postCallbackErrorOrReturn(callback, ScanCallback.SCAN_FAILED_FEATURE_UNSUPPORTED); } + if (!isRoutingAllowedForScan(settings)) { + return postCallbackErrorOrReturn(callback, + ScanCallback.SCAN_FAILED_FEATURE_UNSUPPORTED); + } if (callback != null) { BleScanCallbackWrapper wrapper = new BleScanCallbackWrapper(gatt, filters, settings, workSource, callback, resultStorages); @@ -599,4 +611,14 @@ public final class BluetoothLeScanner { } return true; } + + private boolean isRoutingAllowedForScan(ScanSettings settings) { + final int callbackType = settings.getCallbackType(); + + if (callbackType == ScanSettings.CALLBACK_TYPE_SENSOR_ROUTING + && settings.getScanMode() == ScanSettings.SCAN_MODE_OPPORTUNISTIC) { + return false; + } + return true; + } } diff --git a/core/java/android/bluetooth/le/BluetoothLeUtils.java b/core/java/android/bluetooth/le/BluetoothLeUtils.java index 6381f557c1b2..f8d1c517540d 100644 --- a/core/java/android/bluetooth/le/BluetoothLeUtils.java +++ b/core/java/android/bluetooth/le/BluetoothLeUtils.java @@ -77,6 +77,28 @@ public class BluetoothLeUtils { } /** + * Returns a string composed from a byte array. + */ + static <T> String toString(byte[] data) { + if (data == null) { + return "null"; + } + if (data.length == 0) { + return "{}"; + } + StringBuilder buffer = new StringBuilder(); + buffer.append('{'); + for(int i=0; i < data.length; i++) { + buffer.append(data[i]); + if ((i+1) < data.length) { + buffer.append(", "); + } + } + buffer.append('}'); + return buffer.toString(); + } + + /** * Check whether two {@link SparseArray} equal. */ static boolean equals(SparseArray<byte[]> array, SparseArray<byte[]> otherArray) { @@ -126,6 +148,25 @@ public class BluetoothLeUtils { } /** + * Check whether two byte arrays are equal. + */ + static <T> boolean equals(byte[] data, byte[] otherData) { + if (data == otherData) { + return true; + } + if (data == null || otherData == null) { + return false; + } + if (data.length != otherData.length) { + return false; + } + if (!Objects.deepEquals(data, otherData)) { + return false; + } + return true; + } + + /** * Ensure Bluetooth is turned on. * * @throws IllegalStateException If {@code adapter} is null or Bluetooth state is not {@link diff --git a/core/java/android/bluetooth/le/ScanSettings.java b/core/java/android/bluetooth/le/ScanSettings.java index 8fdcba85d33a..2919c27c5d93 100644 --- a/core/java/android/bluetooth/le/ScanSettings.java +++ b/core/java/android/bluetooth/le/ScanSettings.java @@ -69,6 +69,12 @@ public final class ScanSettings implements Parcelable { */ public static final int CALLBACK_TYPE_MATCH_LOST = 4; + /** + * Provide results to sensor router instead of the apps processor + * @hide + */ + public static final int CALLBACK_TYPE_SENSOR_ROUTING = 8; + /** * Determines how many advertisements to match per filter, as this is scarce hw resource @@ -302,7 +308,8 @@ public final class ScanSettings implements Parcelable { private boolean isValidCallbackType(int callbackType) { if (callbackType == CALLBACK_TYPE_ALL_MATCHES || callbackType == CALLBACK_TYPE_FIRST_MATCH - || callbackType == CALLBACK_TYPE_MATCH_LOST) { + || callbackType == CALLBACK_TYPE_MATCH_LOST + || callbackType == CALLBACK_TYPE_SENSOR_ROUTING) { return true; } return callbackType == (CALLBACK_TYPE_FIRST_MATCH | CALLBACK_TYPE_MATCH_LOST); diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java index 6704a45fb07a..a61803f67daf 100644 --- a/core/java/android/content/ContentResolver.java +++ b/core/java/android/content/ContentResolver.java @@ -763,6 +763,7 @@ public abstract class ContentResolver implements ContentInterface { public final @Nullable Cursor query(@RequiresPermission.Read @NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) { + android.util.SeempLog.record_uri(13, uri); return query(uri, projection, selection, selectionArgs, sortOrder, null); } @@ -841,6 +842,7 @@ public abstract class ContentResolver implements ContentInterface { public final @Nullable Cursor query(final @RequiresPermission.Read @NonNull Uri uri, @Nullable String[] projection, @Nullable Bundle queryArgs, @Nullable CancellationSignal cancellationSignal) { + android.util.SeempLog.record_uri(13, uri); Preconditions.checkNotNull(uri, "uri"); IContentProvider unstableProvider = acquireUnstableProvider(uri); if (unstableProvider == null) { @@ -1662,6 +1664,7 @@ public abstract class ContentResolver implements ContentInterface { @Override public final @Nullable Uri insert(@RequiresPermission.Write @NonNull Uri url, @Nullable ContentValues values) { + android.util.SeempLog.record_uri(37, url); Preconditions.checkNotNull(url, "url"); IContentProvider provider = acquireProvider(url); if (provider == null) { diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index 8497656df2be..795ed36a4a39 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -2567,6 +2567,18 @@ public class Intent implements Parcelable, Cloneable { public static final String ACTION_PACKAGE_NEEDS_VERIFICATION = "android.intent.action.PACKAGE_NEEDS_VERIFICATION"; /** + * Broadcast Action: Sent to the optional package verifier when a package + * needs to be verified. The data contains the package URI. + * <p class="note"> + * This is a protected intent. + * </p> + * + * @hide + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_PACKAGE_NEEDS_OPTIONAL_VERIFICATION = "com.qualcomm.qti.intent.action.PACKAGE_NEEDS_OPTIONAL_VERIFICATION"; + + /** * Broadcast Action: Sent to the system package verifier when a package is * verified. The data contains the package URI. * <p class="note"> @@ -10499,6 +10511,7 @@ public class Intent implements Parcelable, Cloneable { case ACTION_MEDIA_SCANNER_FINISHED: case ACTION_MEDIA_SCANNER_SCAN_FILE: case ACTION_PACKAGE_NEEDS_VERIFICATION: + case ACTION_PACKAGE_NEEDS_OPTIONAL_VERIFICATION: case ACTION_PACKAGE_VERIFIED: case ACTION_PACKAGE_ENABLE_ROLLBACK: // Ignore legacy actions diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java index 576466f21bcb..027e1be9d3c6 100644 --- a/core/java/android/content/pm/ApplicationInfo.java +++ b/core/java/android/content/pm/ApplicationInfo.java @@ -29,6 +29,8 @@ import android.content.res.Resources; import android.graphics.drawable.Drawable; import android.os.Build; import android.os.Environment; +import android.os.SystemProperties; +import android.util.DisplayMetrics; import android.os.Parcel; import android.os.Parcelable; import android.os.UserHandle; @@ -697,6 +699,19 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { public static final String METADATA_PRELOADED_FONTS = "preloaded_fonts"; /** + * Boolean indicating whether the resolution of the SurfaceView associated + * with this appplication can be overriden. + * {@hide} + */ + public int overrideRes = 0; + + /** + * In case, app needs different density than device density, set this value. + * {@hide} + */ + public int overrideDensity = 0; + + /** * The required smallest screen width the application can run on. If 0, * nothing has been specified. Comes from * {@link android.R.styleable#AndroidManifestSupportsScreens_requiresSmallestWidthDp @@ -1484,6 +1499,8 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { theme = orig.theme; flags = orig.flags; privateFlags = orig.privateFlags; + overrideRes = orig.overrideRes; + overrideDensity = orig.overrideDensity; requiresSmallestWidthDp = orig.requiresSmallestWidthDp; compatibleWidthLimitDp = orig.compatibleWidthLimitDp; largestWidthLimitDp = orig.largestWidthLimitDp; @@ -1555,6 +1572,8 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { dest.writeInt(theme); dest.writeInt(flags); dest.writeInt(privateFlags); + dest.writeInt(overrideRes); + dest.writeInt(overrideDensity); dest.writeInt(requiresSmallestWidthDp); dest.writeInt(compatibleWidthLimitDp); dest.writeInt(largestWidthLimitDp); @@ -1631,6 +1650,8 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { theme = source.readInt(); flags = source.readInt(); privateFlags = source.readInt(); + overrideRes = source.readInt(); + overrideDensity = source.readInt(); requiresSmallestWidthDp = source.readInt(); compatibleWidthLimitDp = source.readInt(); largestWidthLimitDp = source.readInt(); @@ -1986,12 +2007,18 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { return this; } + /** @hide */ + public int getOverrideDensity() { + return overrideDensity; + } + /** {@hide} */ public void setCodePath(String codePath) { scanSourceDir = codePath; } /** {@hide} */ public void setBaseCodePath(String baseCodePath) { sourceDir = baseCodePath; } /** {@hide} */ public void setSplitCodePaths(String[] splitCodePaths) { splitSourceDirs = splitCodePaths; } /** {@hide} */ public void setResourcePath(String resourcePath) { scanPublicSourceDir = resourcePath; } /** {@hide} */ public void setBaseResourcePath(String baseResourcePath) { publicSourceDir = baseResourcePath; } /** {@hide} */ public void setSplitResourcePaths(String[] splitResourcePaths) { splitPublicSourceDirs = splitResourcePaths; } + /** {@hide} */ public void setOverrideRes(int overrideResolution) { overrideRes = overrideResolution; } /** {@hide} */ @UnsupportedAppUsage @@ -2003,4 +2030,5 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { @UnsupportedAppUsage public String getBaseResourcePath() { return publicSourceDir; } /** {@hide} */ public String[] getSplitResourcePaths() { return splitPublicSourceDirs; } + /** {@hide} */ public int canOverrideRes() { return overrideRes; } } diff --git a/core/java/android/content/res/CompatibilityInfo.java b/core/java/android/content/res/CompatibilityInfo.java index 7d101b8f78e5..635cee3609ad 100644 --- a/core/java/android/content/res/CompatibilityInfo.java +++ b/core/java/android/content/res/CompatibilityInfo.java @@ -30,6 +30,7 @@ import android.util.DisplayMetrics; import android.view.MotionEvent; import android.view.WindowManager; import android.view.WindowManager.LayoutParams; +import android.util.Log; /** * CompatibilityInfo class keeps the information about compatibility mode that the application is @@ -43,6 +44,8 @@ public class CompatibilityInfo implements Parcelable { public static final CompatibilityInfo DEFAULT_COMPATIBILITY_INFO = new CompatibilityInfo() { }; + static final String TAG = "CompatibilityInfo"; + /** * This is the number of pixels we would like to have along the * short axis of an app that needs to run on a normal size screen. @@ -148,11 +151,18 @@ public class CompatibilityInfo implements Parcelable { // Let the user decide. compatFlags |= NEEDS_SCREEN_COMPAT; } - - // Modern apps always support densities. - applicationDensity = DisplayMetrics.DENSITY_DEVICE; - applicationScale = 1.0f; - applicationInvertedScale = 1.0f; + int density = appInfo.getOverrideDensity(); + if(density != 0) { + applicationDensity = density; + applicationScale = DisplayMetrics.DENSITY_DEVICE / (float) applicationDensity; + applicationInvertedScale = 1.0f / applicationScale; + compatFlags |= SCALING_REQUIRED; + } else { + // Modern apps always support densities. + applicationDensity = DisplayMetrics.DENSITY_DEVICE; + applicationScale = 1.0f; + applicationInvertedScale = 1.0f; + } } else { /** @@ -239,20 +249,30 @@ public class CompatibilityInfo implements Parcelable { compatFlags |= NEVER_NEEDS_COMPAT; } - if ((appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) != 0) { - applicationDensity = DisplayMetrics.DENSITY_DEVICE; - applicationScale = 1.0f; - applicationInvertedScale = 1.0f; - } else { + int density = appInfo.getOverrideDensity(); + if ((appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) == 0) { applicationDensity = DisplayMetrics.DENSITY_DEFAULT; applicationScale = DisplayMetrics.DENSITY_DEVICE / (float) DisplayMetrics.DENSITY_DEFAULT; applicationInvertedScale = 1.0f / applicationScale; compatFlags |= SCALING_REQUIRED; + } else if(density != 0) { + applicationDensity = density; + applicationScale = DisplayMetrics.DENSITY_DEVICE / (float) applicationDensity; + applicationInvertedScale = 1.0f / applicationScale; + compatFlags |= SCALING_REQUIRED; + } else { + applicationDensity = DisplayMetrics.DENSITY_DEVICE; + applicationScale = 1.0f; + applicationInvertedScale = 1.0f; } } mCompatibilityFlags = compatFlags; + + Log.d(TAG, "mCompatibilityFlags - " + Integer.toHexString(mCompatibilityFlags)); + Log.d(TAG, "applicationDensity - " + applicationDensity); + Log.d(TAG, "applicationScale - " + applicationScale); } private CompatibilityInfo(int compFlags, diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java index ac863b2a45af..507b582a914e 100644 --- a/core/java/android/hardware/Camera.java +++ b/core/java/android/hardware/Camera.java @@ -39,6 +39,7 @@ import android.os.Message; import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; +import android.os.SystemProperties; import android.renderscript.Allocation; import android.renderscript.Element; import android.renderscript.RSIllegalArgumentException; @@ -48,6 +49,7 @@ import android.text.TextUtils; import android.util.Log; import android.view.Surface; import android.view.SurfaceHolder; +import android.os.SystemProperties; import com.android.internal.annotations.GuardedBy; import com.android.internal.app.IAppOpsCallback; @@ -165,6 +167,10 @@ public class Camera { private static final int CAMERA_MSG_RAW_IMAGE_NOTIFY = 0x200; private static final int CAMERA_MSG_PREVIEW_METADATA = 0x400; private static final int CAMERA_MSG_FOCUS_MOVE = 0x800; + /* ### QC ADD-ONS: START */ + private static final int CAMERA_MSG_STATS_DATA = 0x1000; + private static final int CAMERA_MSG_META_DATA = 0x2000; + /* ### QC ADD-ONS: END */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) private long mNativeContext; // accessed by native methods @@ -196,6 +202,17 @@ public class Camera { private boolean mShutterSoundEnabledFromApp = true; private static final int NO_ERROR = 0; + private static final int EACCESS = -13; + private static final int ENODEV = -19; + private static final int EBUSY = -16; + private static final int EINVAL = -22; + private static final int ENOSYS = -38; + private static final int EUSERS = -87; + private static final int EOPNOTSUPP = -95; + /* ### QC ADD-ONS: START */ + private CameraDataCallback mCameraDataCallback; + private CameraMetaDataCallback mCameraMetaDataCallback; + /* ### QC ADD-ONS: END */ /** * Broadcast Action: A new picture is taken by the camera, and the entry of @@ -277,7 +294,35 @@ public class Camera { * @return total number of accessible camera devices, or 0 if there are no * cameras or an error was encountered enumerating them. */ - public native static int getNumberOfCameras(); + public static int getNumberOfCameras() { + boolean exposeAuxCamera = false; + String packageName = ActivityThread.currentOpPackageName(); + /* Force to expose only two cameras + * if the package name does not falls in this bucket + */ + String packageList = SystemProperties.get("vendor.camera.aux.packagelist"); + if (packageList.length() > 0) { + TextUtils.StringSplitter splitter = new TextUtils.SimpleStringSplitter(','); + splitter.setString(packageList); + for (String str : splitter) { + if (packageName.equals(str)) { + exposeAuxCamera = true; + break; + } + } + } + int numberOfCameras = _getNumberOfCameras(); + if (exposeAuxCamera == false && (numberOfCameras > 2)) { + numberOfCameras = 2; + } + return numberOfCameras; + } + + /** + * Returns the number of physical cameras available on this device. + */ + /** @hide */ + public native static int _getNumberOfCameras(); /** * Returns the information about a particular camera. @@ -288,6 +333,9 @@ public class Camera { * low-level failure). */ public static void getCameraInfo(int cameraId, CameraInfo cameraInfo) { + if(cameraId >= getNumberOfCameras()){ + throw new RuntimeException("Unknown camera ID"); + } _getCameraInfo(cameraId, cameraInfo); IBinder b = ServiceManager.getService(Context.AUDIO_SERVICE); IAudioService audioService = IAudioService.Stub.asInterface(b); @@ -321,6 +369,17 @@ public class Camera { */ public static final int CAMERA_FACING_FRONT = 1; + /* ### QC ADD-ONS: START TBD*/ + /** @hide + * camera is in ZSL mode. + */ + public static final int CAMERA_SUPPORT_MODE_ZSL = 2; + + /** @hide + * camera is in non-ZSL mode. + */ + public static final int CAMERA_SUPPORT_MODE_NONZSL = 3; + /* ### QC ADD-ONS: END */ /** * The direction that the camera faces. It should be * CAMERA_FACING_BACK or CAMERA_FACING_FRONT. @@ -507,6 +566,10 @@ public class Camera { mPostviewCallback = null; mUsingPreviewAllocation = false; mZoomListener = null; + /* ### QC ADD-ONS: START */ + mCameraDataCallback = null; + mCameraMetaDataCallback = null; + /* ### QC ADD-ONS: END */ Looper looper; if ((looper = Looper.myLooper()) != null) { @@ -517,8 +580,21 @@ public class Camera { mEventHandler = null; } - return native_setup(new WeakReference<Camera>(this), cameraId, halVersion, - ActivityThread.currentOpPackageName()); + String packageName = ActivityThread.currentOpPackageName(); + + //Force HAL1 if the package name falls in this bucket + String packageList = SystemProperties.get("vendor.camera.hal1.packagelist", ""); + if (packageList.length() > 0) { + TextUtils.StringSplitter splitter = new TextUtils.SimpleStringSplitter(','); + splitter.setString(packageList); + for (String str : splitter) { + if (packageName.equals(str)) { + halVersion = CAMERA_HAL_API_VERSION_1_0; + break; + } + } + } + return native_setup(new WeakReference<Camera>(this), cameraId, halVersion, packageName); } private int cameraInitNormal(int cameraId) { @@ -545,6 +621,9 @@ public class Camera { /** used by Camera#open, Camera#open(int) */ Camera(int cameraId) { + if(cameraId >= getNumberOfCameras()){ + throw new RuntimeException("Unknown camera ID"); + } int err = cameraInitNormal(cameraId); if (checkInitErrors(err)) { if (err == -EACCES) { @@ -867,6 +946,7 @@ public class Camera { * @see android.media.MediaActionSound */ public final void setPreviewCallback(PreviewCallback cb) { + android.util.SeempLog.record(66); mPreviewCallback = cb; mOneShot = false; mWithBuffer = false; @@ -895,6 +975,7 @@ public class Camera { * @see android.media.MediaActionSound */ public final void setOneShotPreviewCallback(PreviewCallback cb) { + android.util.SeempLog.record(68); mPreviewCallback = cb; mOneShot = true; mWithBuffer = false; @@ -935,6 +1016,7 @@ public class Camera { * @see android.media.MediaActionSound */ public final void setPreviewCallbackWithBuffer(PreviewCallback cb) { + android.util.SeempLog.record(67); mPreviewCallback = cb; mOneShot = false; mWithBuffer = true; @@ -1265,7 +1347,23 @@ public class Camera { mAutoFocusMoveCallback.onAutoFocusMoving(msg.arg1 == 0 ? false : true, mCamera); } return; + /* ### QC ADD-ONS: START */ + case CAMERA_MSG_STATS_DATA: + int statsdata[] = new int[257]; + for(int i =0; i<257; i++ ) { + statsdata[i] = byteToInt( (byte[])msg.obj, i*4); + } + if (mCameraDataCallback != null) { + mCameraDataCallback.onCameraData(statsdata, mCamera); + } + return; + case CAMERA_MSG_META_DATA: + if (mCameraMetaDataCallback != null) { + mCameraMetaDataCallback.onCameraMetaData((byte[])msg.obj, mCamera); + } + return; + /* ### QC ADD-ONS: END */ default: Log.e(TAG, "Unknown message type " + msg.what); return; @@ -1499,6 +1597,7 @@ public class Camera { */ public final void takePicture(ShutterCallback shutter, PictureCallback raw, PictureCallback jpeg) { + android.util.SeempLog.record(65); takePicture(shutter, raw, null, jpeg); } private native final void native_takePicture(int msgType); @@ -1537,6 +1636,7 @@ public class Camera { */ public final void takePicture(ShutterCallback shutter, PictureCallback raw, PictureCallback postview, PictureCallback jpeg) { + android.util.SeempLog.record(65); mShutterCallback = shutter; mRawImageCallback = raw; mPostviewCallback = postview; @@ -2006,6 +2106,23 @@ public class Camera { * as a set. Either they are all valid, or none of them are. */ public Point mouth = null; + + /** + * {@hide} + */ + public int smileDegree = 0; + /** + * {@hide} + */ + public int smileScore = 0; + /** + * {@hide} + */ + public int blinkDetected = 0; + /** + * {@hide} + */ + public int faceRecognised = 0; } /** @@ -2130,6 +2247,27 @@ public class Camera { return p; } + /** @hide + * Returns the current cct value of white balance. + * + * If it's in AWB mode, cct is determined by stats/awb module. + * + * If it's in Manual WB mode, it actually returns cct value + * set by user via {@link #setParameters(Camera.Parameters)}. + */ + public int getWBCurrentCCT() { + Parameters p = new Parameters(); + String s = native_getParameters(); + p.unflatten(s); + + int cct = 0; + if (p.getWBCurrentCCT() != null) { + cct = Integer.parseInt(p.getWBCurrentCCT()); + } + + return cct; + } + /** * Returns an empty {@link Parameters} for testing purpose. * @@ -2143,6 +2281,157 @@ public class Camera { return camera.new Parameters(); } + /* ### QC ADD-ONS: START */ + private static int byteToInt(byte[] b, int offset) { + int value = 0; + for (int i = 0; i < 4; i++) { + int shift = (4 - 1 - i) * 8; + value += (b[(3-i) + offset] & 0x000000FF) << shift; + } + return value; + } + /** @hide + * Handles the callback for when Camera Data is available. + * data is read from the camera. + */ + public interface CameraDataCallback { + /** + * Callback for when camera data is available. + * + * @param data a int array of the camera data + * @param camera the Camera service object + */ + void onCameraData(int[] data, Camera camera); + }; + + /** @hide + * Set camera histogram mode and registers a callback function to run. + * Only valid after startPreview() has been called. + * + * @param cb the callback to run + */ + public final void setHistogramMode(CameraDataCallback cb) + { + mCameraDataCallback = cb; + native_setHistogramMode(cb!=null); + } + private native final void native_setHistogramMode(boolean mode); + + /** @hide + * Set camera histogram command to send data. + * + */ + public final void sendHistogramData() + { + native_sendHistogramData(); + } + private native final void native_sendHistogramData(); + + /** @hide + * Handles the callback for when Camera Meta Data is available. + * Meta data is read from the camera. + */ + public interface CameraMetaDataCallback { + /** + * Callback for when camera meta data is available. + * + * @param data a byte array of the camera meta data + * @param camera the Camera service object + */ + void onCameraMetaData(byte[] data, Camera camera); + }; + + /** @hide + * Set camera meta data and registers a callback function to run. + * Only valid after startPreview() has been called. + * + * @param cb the callback to run + */ + public final void setMetadataCb(CameraMetaDataCallback cb) + { + mCameraMetaDataCallback = cb; + native_setMetadataCb(cb!=null); + } + private native final void native_setMetadataCb(boolean mode); + + /** @hide + * Set camera face detection command to send meta data. + */ + public final void sendMetaData() + { + native_sendMetaData(); + } + private native final void native_sendMetaData(); + + /** @hide + * Configure longshot mode. Available only in ZSL. + * + * @param enable enable/disable this mode + */ + public final void setLongshot(boolean enable) + { + native_setLongshot(enable); + } + private native final void native_setLongshot(boolean enable); + + /** @hide + * Handles the Touch Co-ordinate. + */ + public class Coordinate { + /** + * Sets the x,y co-ordinates for a touch event + * + * @param x the x co-ordinate (pixels) + * @param y the y co-ordinate (pixels) + */ + public Coordinate(int x, int y) { + xCoordinate = x; + yCoordinate = y; + } + /** + * Compares {@code obj} to this co-ordinate. + * + * @param obj the object to compare this co-ordinate with. + * @return {@code true} if the xCoordinate and yCoordinate of {@code obj} is the + * same as those of this coordinate. {@code false} otherwise. + */ + @Override + public boolean equals(Object obj) { + if (!(obj instanceof Coordinate)) { + return false; + } + Coordinate c = (Coordinate) obj; + return xCoordinate == c.xCoordinate && yCoordinate == c.yCoordinate; + } + + /** x co-ordinate for the touch event*/ + public int xCoordinate; + + /** y co-ordinate for the touch event */ + public int yCoordinate; + }; + + /** @hide + * Returns the current focus position. + * + * If it's in AF mode, it's the lens position after af is done. + * + * If it's in Manual Focus mode, it actually returns the value + * set by user via {@link #setParameters(Camera.Parameters)}. + */ + public int getCurrentFocusPosition() { + Parameters p = new Parameters(); + String s = native_getParameters(); + p.unflatten(s); + + int focus_pos = -1; + if (p.getCurrentFocusPosition() != null) { + focus_pos = Integer.parseInt(p.getCurrentFocusPosition()); + } + return focus_pos; + } + + /* ### QC ADD-ONS: END */ /** * Returns a copied {@link Parameters}; for shim use only. * @@ -2390,6 +2679,10 @@ public class Camera { public static final String WHITE_BALANCE_CLOUDY_DAYLIGHT = "cloudy-daylight"; public static final String WHITE_BALANCE_TWILIGHT = "twilight"; public static final String WHITE_BALANCE_SHADE = "shade"; + /** @hide + * wb manual cct mode. + */ + public static final String WHITE_BALANCE_MANUAL_CCT = "manual-cct"; // Values for color effect settings. public static final String EFFECT_NONE = "none"; @@ -2437,6 +2730,11 @@ public class Camera { */ public static final String FLASH_MODE_TORCH = "torch"; + /** @hide + * Scene mode is off. + */ + public static final String SCENE_MODE_ASD = "asd"; + /** * Scene mode is off. */ @@ -2513,6 +2811,14 @@ public class Camera { * Capture the naturally warm color of scenes lit by candles. */ public static final String SCENE_MODE_CANDLELIGHT = "candlelight"; + /** @hide + * SCENE_MODE_BACKLIGHT + **/ + public static final String SCENE_MODE_BACKLIGHT = "backlight"; + /** @hide + * SCENE_MODE_FLOWERS + **/ + public static final String SCENE_MODE_FLOWERS = "flowers"; /** * Applications are looking for a barcode. Camera driver will be @@ -2555,6 +2861,13 @@ public class Camera { */ public static final String FOCUS_MODE_FIXED = "fixed"; + /** @hide + * Normal focus mode. Applications should call + * {@link #autoFocus(AutoFocusCallback)} to start the focus in this + * mode. + */ + public static final String FOCUS_MODE_NORMAL = "normal"; + /** * Extended depth of field (EDOF). Focusing is done digitally and * continuously. Applications should not call {@link @@ -2607,6 +2920,11 @@ public class Camera { */ public static final String FOCUS_MODE_CONTINUOUS_PICTURE = "continuous-picture"; + /** @hide + * manual focus mode + */ + public static final String FOCUS_MODE_MANUAL_POSITION = "manual"; + // Indices for focus distance array. /** * The array index of near focus distance for use with @@ -2643,11 +2961,15 @@ public class Camera { // Formats for setPreviewFormat and setPictureFormat. private static final String PIXEL_FORMAT_YUV422SP = "yuv422sp"; private static final String PIXEL_FORMAT_YUV420SP = "yuv420sp"; + private static final String PIXEL_FORMAT_YUV420SP_ADRENO = "yuv420sp-adreno"; private static final String PIXEL_FORMAT_YUV422I = "yuv422i-yuyv"; private static final String PIXEL_FORMAT_YUV420P = "yuv420p"; private static final String PIXEL_FORMAT_RGB565 = "rgb565"; private static final String PIXEL_FORMAT_JPEG = "jpeg"; private static final String PIXEL_FORMAT_BAYER_RGGB = "bayer-rggb"; + private static final String PIXEL_FORMAT_RAW = "raw"; + private static final String PIXEL_FORMAT_YV12 = "yv12"; + private static final String PIXEL_FORMAT_NV12 = "nv12"; /** * Order matters: Keys that are {@link #set(String, String) set} later @@ -3437,8 +3759,11 @@ public class Camera { * parameters. */ public void removeGpsData() { + remove(KEY_QC_GPS_LATITUDE_REF); remove(KEY_GPS_LATITUDE); + remove(KEY_QC_GPS_LONGITUDE_REF); remove(KEY_GPS_LONGITUDE); + remove(KEY_QC_GPS_ALTITUDE_REF); remove(KEY_GPS_ALTITUDE); remove(KEY_GPS_TIMESTAMP); remove(KEY_GPS_PROCESSING_METHOD); @@ -4462,5 +4787,1231 @@ public class Camera { if (s1 != null && s1.equals(s2)) return true; return false; } + /* ### QC ADD-ONS: START */ + + /* ### QC ADDED PARAMETER KEYS*/ + private static final String KEY_QC_HFR_SIZE = "hfr-size"; + private static final String KEY_QC_PREVIEW_FRAME_RATE_MODE = "preview-frame-rate-mode"; + private static final String KEY_QC_PREVIEW_FRAME_RATE_AUTO_MODE = "frame-rate-auto"; + private static final String KEY_QC_PREVIEW_FRAME_RATE_FIXED_MODE = "frame-rate-fixed"; + private static final String KEY_QC_GPS_LATITUDE_REF = "gps-latitude-ref"; + private static final String KEY_QC_GPS_LONGITUDE_REF = "gps-longitude-ref"; + private static final String KEY_QC_GPS_ALTITUDE_REF = "gps-altitude-ref"; + private static final String KEY_QC_GPS_STATUS = "gps-status"; + private static final String KEY_QC_EXIF_DATETIME = "exif-datetime"; + private static final String KEY_QC_TOUCH_AF_AEC = "touch-af-aec"; + private static final String KEY_QC_TOUCH_INDEX_AEC = "touch-index-aec"; + private static final String KEY_QC_TOUCH_INDEX_AF = "touch-index-af"; + private static final String KEY_QC_MANUAL_FOCUS_POSITION = "manual-focus-position"; + private static final String KEY_QC_MANUAL_FOCUS_POS_TYPE = "manual-focus-pos-type"; + private static final String KEY_QC_SCENE_DETECT = "scene-detect"; + private static final String KEY_QC_ISO_MODE = "iso"; + private static final String KEY_QC_EXPOSURE_TIME = "exposure-time"; + private static final String KEY_QC_MIN_EXPOSURE_TIME = "min-exposure-time"; + private static final String KEY_QC_MAX_EXPOSURE_TIME = "max-exposure-time"; + private static final String KEY_QC_LENSSHADE = "lensshade"; + private static final String KEY_QC_HISTOGRAM = "histogram"; + private static final String KEY_QC_SKIN_TONE_ENHANCEMENT = "skinToneEnhancement"; + private static final String KEY_QC_AUTO_EXPOSURE = "auto-exposure"; + private static final String KEY_QC_SHARPNESS = "sharpness"; + private static final String KEY_QC_MAX_SHARPNESS = "max-sharpness"; + private static final String KEY_QC_CONTRAST = "contrast"; + private static final String KEY_QC_MAX_CONTRAST = "max-contrast"; + private static final String KEY_QC_SATURATION = "saturation"; + private static final String KEY_QC_MAX_SATURATION = "max-saturation"; + private static final String KEY_QC_DENOISE = "denoise"; + private static final String KEY_QC_CONTINUOUS_AF = "continuous-af"; + private static final String KEY_QC_SELECTABLE_ZONE_AF = "selectable-zone-af"; + private static final String KEY_QC_FACE_DETECTION = "face-detection"; + private static final String KEY_QC_MEMORY_COLOR_ENHANCEMENT = "mce"; + private static final String KEY_QC_REDEYE_REDUCTION = "redeye-reduction"; + private static final String KEY_QC_ZSL = "zsl"; + private static final String KEY_QC_CAMERA_MODE = "camera-mode"; + private static final String KEY_QC_VIDEO_HIGH_FRAME_RATE = "video-hfr"; + private static final String KEY_QC_VIDEO_HDR = "video-hdr"; + private static final String KEY_QC_POWER_MODE = "power-mode"; + private static final String KEY_QC_POWER_MODE_SUPPORTED = "power-mode-supported"; + private static final String KEY_QC_WB_MANUAL_CCT = "wb-manual-cct"; + private static final String KEY_QC_MIN_WB_CCT = "min-wb-cct"; + private static final String KEY_QC_MAX_WB_CCT = "max-wb-cct"; + private static final String KEY_QC_AUTO_HDR_ENABLE = "auto-hdr-enable"; + private static final String KEY_QC_VIDEO_ROTATION = "video-rotation"; + + /** @hide + * KEY_QC_AE_BRACKET_HDR + **/ + public static final String KEY_QC_AE_BRACKET_HDR = "ae-bracket-hdr"; + + /* ### QC ADDED PARAMETER VALUES*/ + + // Values for touch af/aec settings. + /** @hide + * TOUCH_AF_AEC_OFF + **/ + public static final String TOUCH_AF_AEC_OFF = "touch-off"; + /** @hide + * TOUCH_AF_AEC_ON + **/ + public static final String TOUCH_AF_AEC_ON = "touch-on"; + + // Values for auto exposure settings. + /** @hide + * Auto exposure frame-avg + **/ + public static final String AUTO_EXPOSURE_FRAME_AVG = "frame-average"; + /** @hide + * Auto exposure center weighted + **/ + public static final String AUTO_EXPOSURE_CENTER_WEIGHTED = "center-weighted"; + /** @hide + * Auto exposure spot metering + **/ + public static final String AUTO_EXPOSURE_SPOT_METERING = "spot-metering"; + + //Values for ISO settings + /** @hide + * ISO_AUTO + **/ + public static final String ISO_AUTO = "auto"; + /** @hide + * ISO_HJR + **/ + public static final String ISO_HJR = "ISO_HJR"; + /** @hide + * ISO_100 + **/ + public static final String ISO_100 = "ISO100"; + /** @hide + * ISO_200 + **/ + public static final String ISO_200 = "ISO200"; + /** @hide + * ISO_400 + **/ + public static final String ISO_400 = "ISO400"; + /** @hide + * ISO_800 + **/ + public static final String ISO_800 = "ISO800"; + /** @hide + * ISO_1600 + **/ + public static final String ISO_1600 = "ISO1600"; + + /** @hide + * ISO_3200 + **/ + public static final String ISO_3200 = "ISO3200"; + + //Values for Lens Shading + /** @hide + * LENSSHADE_ENABLE + **/ + public static final String LENSSHADE_ENABLE = "enable"; + /** @hide + * LENSSHADE_DISABLE + **/ + public static final String LENSSHADE_DISABLE= "disable"; + + //Values for Histogram + /** @hide + * Histogram enable + **/ + public static final String HISTOGRAM_ENABLE = "enable"; + /** @hide + * Histogram disable + **/ + public static final String HISTOGRAM_DISABLE= "disable"; + + //Values for Skin Tone Enhancement + /** @hide + * SKIN_TONE_ENHANCEMENT_ENABLE + **/ + public static final String SKIN_TONE_ENHANCEMENT_ENABLE = "enable"; + /** @hide + * SKIN_TONE_ENHANCEMENT_DISABLE + **/ + public static final String SKIN_TONE_ENHANCEMENT_DISABLE= "disable"; + + // Values for MCE settings. + /** @hide + * MCE_ENaBLE + **/ + public static final String MCE_ENABLE = "enable"; + /** @hide + * MCE_DISABLE + **/ + public static final String MCE_DISABLE = "disable"; + + // Values for ZSL settings. + /** @hide + * ZSL_ON + **/ + public static final String ZSL_ON = "on"; + /** @hide + * ZSL_OFF + **/ + public static final String ZSL_OFF = "off"; + + // Values for HDR Bracketing settings. + + /** @hide + * AEC bracketing off + **/ + public static final String AE_BRACKET_HDR_OFF = "Off"; + /** @hide + * AEC bracketing hdr + **/ + public static final String AE_BRACKET_HDR = "HDR"; + /** @hide + * AEC bracketing aec-bracket + **/ + public static final String AE_BRACKET = "AE-Bracket"; + + // Values for Power mode. + /** @hide + * LOW_POWER + **/ + public static final String LOW_POWER = "Low_Power"; + /** @hide + * NORMAL_POWER + **/ + public static final String NORMAL_POWER = "Normal_Power"; + + // Values for HFR settings. + /** @hide + * VIDEO_HFR_OFF + **/ + public static final String VIDEO_HFR_OFF = "off"; + /** @hide + * VIDEO_HFR_2X + **/ + public static final String VIDEO_HFR_2X = "60"; + /** @hide + * VIDEO_HFR_3X + **/ + public static final String VIDEO_HFR_3X = "90"; + /** @hide + * VIDEO_HFR_4X + **/ + public static final String VIDEO_HFR_4X = "120"; + + // Values for auto scene detection settings. + /** @hide + * SCENE_DETECT_OFF + **/ + public static final String SCENE_DETECT_OFF = "off"; + /** @hide + * SCENE_DETECT_ON + **/ + public static final String SCENE_DETECT_ON = "on"; + + //Values for Continuous AF + + /** @hide + * CAF off + **/ + public static final String CONTINUOUS_AF_OFF = "caf-off"; + /** @hide + * CAF on + **/ + public static final String CONTINUOUS_AF_ON = "caf-on"; + /** @hide + * Denoise off + **/ + public static final String DENOISE_OFF = "denoise-off"; + /** @hide + * Denoise on + **/ + public static final String DENOISE_ON = "denoise-on"; + + // Values for Redeye Reduction settings. + /** @hide + * REDEYE_REDUCTION_ENABLE + **/ + public static final String REDEYE_REDUCTION_ENABLE = "enable"; + /** @hide + * REDEYE_REDUCTION_DISABLE + **/ + public static final String REDEYE_REDUCTION_DISABLE = "disable"; + + // Values for selectable zone af settings. + /** @hide + * SELECTABLE_ZONE_AF_AUTO + **/ + public static final String SELECTABLE_ZONE_AF_AUTO = "auto"; + /** @hide + * SELECTABLE_ZONE_AF_SPOTMETERING + **/ + public static final String SELECTABLE_ZONE_AF_SPOTMETERING = "spot-metering"; + /** @hide + * SELECTABLE_ZONE_AF_CENTER_WEIGHTED + **/ + public static final String SELECTABLE_ZONE_AF_CENTER_WEIGHTED = "center-weighted"; + /** @hide + * SELECTABLE_ZONE_AF_FRAME_AVERAGE + **/ + public static final String SELECTABLE_ZONE_AF_FRAME_AVERAGE = "frame-average"; + + // Values for Face Detection settings. + /** @hide + * Face Detection off + **/ + public static final String FACE_DETECTION_OFF = "off"; + /** @hide + * Face Detction on + **/ + public static final String FACE_DETECTION_ON = "on"; + + // Values for video rotation settings. + + /** @hide + * VIDEO_ROTATION_0 + **/ + public static final String VIDEO_ROTATION_0 = "0"; + /** @hide + * VIDEO_ROTATION_90 + **/ + public static final String VIDEO_ROTATION_90 = "90"; + /** @hide + * VIDEO_ROTATION_180 + **/ + public static final String VIDEO_ROTATION_180 = "180"; + /** @hide + * VIDEO_ROTATION_270 + **/ + public static final String VIDEO_ROTATION_270 = "270"; + + /* ### QC ADDED PARAMETER APIS*/ + /** @hide + * Gets the supported preview sizes in high frame rate recording mode. + * + * @return a list of Size object. This method will always return a list + * with at least one element. + */ + public List<Size> getSupportedHfrSizes() { + String str = get(KEY_QC_HFR_SIZE + SUPPORTED_VALUES_SUFFIX); + return splitSize(str); + } + + /** @hide + * Gets the supported Touch AF/AEC setting. + * + * @return a List of TOUCH_AF_AEC_XXX string constants. null if TOUCH AF/AEC + * setting is not supported. + * + */ + public List<String> getSupportedTouchAfAec() { + String str = get(KEY_QC_TOUCH_AF_AEC + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + /** + * Gets the supported Touch AF/AEC setting. + * + * @return a List of TOUCH_AF_AEC_XXX string constants. null if TOUCH AF/AEC + * setting is not supported. + * + */ + + /** @hide + * Gets the supported frame rate modes. + * + * @return a List of FRAME_RATE_XXX_MODE string constant. null if this + * setting is not supported. + */ + public List<String> getSupportedPreviewFrameRateModes() { + String str = get(KEY_QC_PREVIEW_FRAME_RATE_MODE + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + /** @hide + * Gets the supported auto scene detection modes. + * + * @return a List of SCENE_DETECT_XXX string constant. null if scene detection + * setting is not supported. + * + */ + public List<String> getSupportedSceneDetectModes() { + String str = get(KEY_QC_SCENE_DETECT + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + /** @hide + * Gets the supported ISO values. + * + * @return a List of FLASH_MODE_XXX string constants. null if flash mode + * setting is not supported. + */ + public List<String> getSupportedIsoValues() { + String str = get(KEY_QC_ISO_MODE + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + /** @hide + * Gets the supported Lensshade modes. + * + * @return a List of LENS_MODE_XXX string constants. null if lens mode + * setting is not supported. + */ + public List<String> getSupportedLensShadeModes() { + String str = get(KEY_QC_LENSSHADE + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + /** @hide + * Gets the supported Histogram modes. + * + * @return a List of HISTOGRAM_XXX string constants. null if histogram mode + * setting is not supported. + */ + public List<String> getSupportedHistogramModes() { + String str = get(KEY_QC_HISTOGRAM + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + /** @hide + * Gets the supported Skin Tone Enhancement modes. + * + * @return a List of SKIN_TONE_ENHANCEMENT_XXX string constants. null if skin tone enhancement + * setting is not supported. + */ + public List<String> getSupportedSkinToneEnhancementModes() { + String str = get(KEY_QC_SKIN_TONE_ENHANCEMENT + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + /** @hide + * Gets the supported auto exposure setting. + * + * @return a List of AUTO_EXPOSURE_XXX string constants. null if auto exposure + * setting is not supported. + */ + public List<String> getSupportedAutoexposure() { + String str = get(KEY_QC_AUTO_EXPOSURE + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + /** @hide + * Gets the supported MCE modes. + * + * @return a List of MCE_ENABLE/DISABLE string constants. null if MCE mode + * setting is not supported. + */ + public List<String> getSupportedMemColorEnhanceModes() { + String str = get(KEY_QC_MEMORY_COLOR_ENHANCEMENT + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + /** @hide + * Gets the supported ZSL modes. + * + * @return a List of ZSL_OFF/OFF string constants. null if ZSL mode + * setting is not supported. + */ + public List<String> getSupportedZSLModes() { + String str = get(KEY_QC_ZSL + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + /** @hide + * Gets the supported Video HDR modes. + * + * @return a List of Video HDR_OFF/OFF string constants. null if + * Video HDR mode setting is not supported. + */ + public List<String> getSupportedVideoHDRModes() { + String str = get(KEY_QC_VIDEO_HDR + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + /** @hide + * Gets the supported HFR modes. + * + * @return a List of VIDEO_HFR_XXX string constants. null if hfr mode + * setting is not supported. + */ + public List<String> getSupportedVideoHighFrameRateModes() { + String str = get(KEY_QC_VIDEO_HIGH_FRAME_RATE + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + /** @hide + * Gets the supported Continuous AF modes. + * + * @return a List of CONTINUOUS_AF_XXX string constant. null if continuous AF + * setting is not supported. + * + */ + public List<String> getSupportedContinuousAfModes() { + String str = get(KEY_QC_CONTINUOUS_AF + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + /** @hide + * Gets the supported DENOISE modes. + * + * @return a List of DENOISE_XXX string constant. null if DENOISE + * setting is not supported. + * + */ + public List<String> getSupportedDenoiseModes() { + String str = get(KEY_QC_DENOISE + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + /** @hide + * Gets the supported selectable zone af setting. + * + * @return a List of SELECTABLE_ZONE_AF_XXX string constants. null if selectable zone af + * setting is not supported. + */ + public List<String> getSupportedSelectableZoneAf() { + String str = get(KEY_QC_SELECTABLE_ZONE_AF + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + /** @hide + * Gets the supported face detection modes. + * + * @return a List of FACE_DETECTION_XXX string constant. null if face detection + * setting is not supported. + * + */ + public List<String> getSupportedFaceDetectionModes() { + String str = get(KEY_QC_FACE_DETECTION + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + /** @hide + * Gets the supported redeye reduction modes. + * + * @return a List of REDEYE_REDUCTION_XXX string constant. null if redeye reduction + * setting is not supported. + * + */ + public List<String> getSupportedRedeyeReductionModes() { + String str = get(KEY_QC_REDEYE_REDUCTION + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + /** @hide + * Sets GPS altitude reference. This will be stored in JPEG EXIF header. + * @param altRef reference GPS altitude in meters. + */ + public void setGpsAltitudeRef(double altRef) { + set(KEY_QC_GPS_ALTITUDE_REF, Double.toString(altRef)); + } + + /** @hide + * Sets GPS Status. This will be stored in JPEG EXIF header. + * + * @param status GPS status (UTC in seconds since January 1, + * 1970). + */ + public void setGpsStatus(double status) { + set(KEY_QC_GPS_STATUS, Double.toString(status)); + } + + /** @hide + * Sets the touch co-ordinate for Touch AEC. + * + * @param x the x co-ordinate of the touch event + * @param y the y co-ordinate of the touch event + * + */ + public void setTouchIndexAec(int x, int y) { + String v = Integer.toString(x) + "x" + Integer.toString(y); + set(KEY_QC_TOUCH_INDEX_AEC, v); + } + + /** @hide + * Returns the touch co-ordinates of the touch event. + * + * @return a Index object with the x and y co-ordinated + * for the touch event + * + */ + public Coordinate getTouchIndexAec() { + String pair = get(KEY_QC_TOUCH_INDEX_AEC); + return strToCoordinate(pair); + } + + /** @hide + * Sets the touch co-ordinate for Touch AF. + * + * @param x the x co-ordinate of the touch event + * @param y the y co-ordinate of the touch event + * + */ + public void setTouchIndexAf(int x, int y) { + String v = Integer.toString(x) + "x" + Integer.toString(y); + set(KEY_QC_TOUCH_INDEX_AF, v); + } + + /** @hide + * Returns the touch co-ordinates of the touch event. + * + * @return a Index object with the x and y co-ordinated + * for the touch event + * + */ + public Coordinate getTouchIndexAf() { + String pair = get(KEY_QC_TOUCH_INDEX_AF); + return strToCoordinate(pair); + } + /** @hide + * Set Sharpness Level + * + * @param sharpness level + */ + public void setSharpness(int sharpness){ + if((sharpness < 0) || (sharpness > getMaxSharpness()) ) + throw new IllegalArgumentException( + "Invalid Sharpness " + sharpness); + + set(KEY_QC_SHARPNESS, String.valueOf(sharpness)); + } + + /** @hide + * Set Contrast Level + * + * @param contrast level + */ + public void setContrast(int contrast){ + if((contrast < 0 ) || (contrast > getMaxContrast())) + throw new IllegalArgumentException( + "Invalid Contrast " + contrast); + + set(KEY_QC_CONTRAST, String.valueOf(contrast)); + } + + /** @hide + * Set Saturation Level + * + * @param saturation level + */ + public void setSaturation(int saturation){ + if((saturation < 0 ) || (saturation > getMaxSaturation())) + throw new IllegalArgumentException( + "Invalid Saturation " + saturation); + + set(KEY_QC_SATURATION, String.valueOf(saturation)); + } + + /** @hide + * @return true if full size video snapshot is supported. + */ + public boolean isPowerModeSupported() { + String str = get(KEY_QC_POWER_MODE_SUPPORTED); + return TRUE.equals(str); + } + + /** @hide + * Get Sharpness level + * + * @return sharpness level + */ + public int getSharpness(){ + return getInt(KEY_QC_SHARPNESS); + } + + /** @hide + * Get Max Sharpness Level + * + * @return max sharpness level + */ + public int getMaxSharpness(){ + return getInt(KEY_QC_MAX_SHARPNESS); + } + + /** @hide + * Get Contrast level + * + * @return contrast level + */ + public int getContrast(){ + return getInt(KEY_QC_CONTRAST); + } + + /** @hide + * Get Max Contrast Level + * + * @return max contrast level + */ + public int getMaxContrast(){ + return getInt(KEY_QC_MAX_CONTRAST); + } + + /** @hide + * Get Saturation level + * + * @return saturation level + */ + public int getSaturation(){ + return getInt(KEY_QC_SATURATION); + } + + /** @hide + * Get Max Saturation Level + * + * @return max contrast level + */ + public int getMaxSaturation(){ + return getInt(KEY_QC_MAX_SATURATION); + } + + /** @hide + * Sets GPS latitude reference coordinate. This will be stored in JPEG EXIF + * header. + * @param latRef GPS latitude reference coordinate. + */ + public void setGpsLatitudeRef(String latRef) { + set(KEY_QC_GPS_LATITUDE_REF, latRef); + } + + /** @hide + * Sets GPS longitude reference coordinate. This will be stored in JPEG EXIF + * header. + * @param lonRef GPS longitude reference coordinate. + */ + public void setGpsLongitudeRef(String lonRef) { + set(KEY_QC_GPS_LONGITUDE_REF, lonRef); + } + + /** @hide + * Sets system timestamp. This will be stored in JPEG EXIF header. + * + * @param dateTime current timestamp (UTC in seconds since January 1, + * 1970). + */ + public void setExifDateTime(String dateTime) { + set(KEY_QC_EXIF_DATETIME, dateTime); + } + + /** @hide + * Gets the current Touch AF/AEC setting. + * + * @return one of TOUCH_AF_AEC_XXX string constant. null if Touch AF/AEC + * setting is not supported. + * + */ + public String getTouchAfAec() { + return get(KEY_QC_TOUCH_AF_AEC); + } + + /** @hide + * Sets the current TOUCH AF/AEC setting. + * + * @param value TOUCH_AF_AEC_XXX string constants. + * + */ + public void setTouchAfAec(String value) { + set(KEY_QC_TOUCH_AF_AEC, value); + } + + /** @hide + * Gets the current redeye reduction setting. + * + * @return one of REDEYE_REDUCTION_XXX string constant. null if redeye reduction + * setting is not supported. + * + */ + public String getRedeyeReductionMode() { + return get(KEY_QC_REDEYE_REDUCTION); + } + + /** @hide + * Sets the redeye reduction. Other parameters may be changed after changing + * redeye reduction. After setting redeye reduction, + * applications should call getParameters to know if some parameters are + * changed. + * + * @param value REDEYE_REDUCTION_XXX string constants. + * + */ + public void setRedeyeReductionMode(String value) { + set(KEY_QC_REDEYE_REDUCTION, value); + } + + /** @hide + * Gets the frame rate mode setting. + * + * @return one of FRAME_RATE_XXX_MODE string constant. null if this + * setting is not supported. + */ + public String getPreviewFrameRateMode() { + return get(KEY_QC_PREVIEW_FRAME_RATE_MODE); + } + + /** @hide + * Sets the frame rate mode. + * + * @param value FRAME_RATE_XXX_MODE string constants. + */ + public void setPreviewFrameRateMode(String value) { + set(KEY_QC_PREVIEW_FRAME_RATE_MODE, value); + } + + /** @hide + * Gets the current auto scene detection setting. + * + * @return one of SCENE_DETECT_XXX string constant. null if auto scene detection + * setting is not supported. + * + */ + public String getSceneDetectMode() { + return get(KEY_QC_SCENE_DETECT); + } + + /** @hide + * Sets the auto scene detect. Other parameters may be changed after changing + * scene detect. After setting auto scene detection, + * applications should call getParameters to know if some parameters are + * changed. + * + * @param value SCENE_DETECT_XXX string constants. + * + */ + public void setSceneDetectMode(String value) { + set(KEY_QC_SCENE_DETECT, value); + } + + /** @hide + * Gets the current hdr bracketing mode setting. + * + * @return current hdr bracketing mode. + * @see #KEY_AE_BRACKET_OFF + * @see #KEY_AE_BRACKET_HDR + * @see #KEY_AE_BRACKET_BRACKATING + */ + public String getAEBracket() { + return get(KEY_QC_AE_BRACKET_HDR); + } + + /** @hide + * Sets the Power mode. + * + * @param value Power mode. + * @see #getPowerMode() + */ + public void setPowerMode(String value) { + set(KEY_QC_POWER_MODE, value); + } + + /** @hide + * Gets the current power mode setting. + * + * @return current power mode. null if power mode setting is not + * supported. + * @see #POWER_MODE_LOW + * @see #POWER_MODE_NORMAL + */ + public String getPowerMode() { + return get(KEY_QC_POWER_MODE); + } + + /** @hide + * Set HDR-Bracketing Level + * + * @param value HDR-Bracketing + */ + public void setAEBracket(String value){ + set(KEY_QC_AE_BRACKET_HDR, value); + } + + /** @hide + * Gets the current ISO setting. + * + * @return one of ISO_XXX string constant. null if ISO + * setting is not supported. + */ + public String getISOValue() { + return get(KEY_QC_ISO_MODE); + } + + /** @hide + * Sets the ISO. + * + * @param iso ISO_XXX string constant. + */ + public void setISOValue(String iso) { + set(KEY_QC_ISO_MODE, iso); + } + + /** @hide + * Sets the exposure time. + * + * @param value exposure time. + */ + public void setExposureTime(int value) { + set(KEY_QC_EXPOSURE_TIME, Integer.toString(value)); + } + + /** @hide + * Gets the current exposure time. + * + * @return exposure time. + */ + public String getExposureTime() { + return get(KEY_QC_EXPOSURE_TIME); + } + + /** @hide + * Gets the min supported exposure time. + * + * @return min supported exposure time. + */ + public String getMinExposureTime() { + return get(KEY_QC_MIN_EXPOSURE_TIME); + } + + /** @hide + * Gets the max supported exposure time. + * + * @return max supported exposure time. + */ + public String getMaxExposureTime() { + return get(KEY_QC_MAX_EXPOSURE_TIME); + } + + /** @hide + * Gets the current LensShade Mode. + * + * @return LensShade Mode + */ + public String getLensShade() { + return get(KEY_QC_LENSSHADE); + } + + /** @hide + * Sets the current LensShade Mode. + * + * @return LensShade Mode + */ + public void setLensShade(String lensshade) { + set(KEY_QC_LENSSHADE, lensshade); + } + + /** @hide + * Gets the current auto exposure setting. + * + * @return one of AUTO_EXPOSURE_XXX string constant. null if auto exposure + * setting is not supported. + */ + public String getAutoExposure() { + return get(KEY_QC_AUTO_EXPOSURE); + } + + /** @hide + * Sets the current auto exposure setting. + * + * @param value AUTO_EXPOSURE_XXX string constants. + */ + public void setAutoExposure(String value) { + set(KEY_QC_AUTO_EXPOSURE, value); + } + + /** @hide + * Gets the current MCE Mode. + * + * @return MCE value + */ + public String getMemColorEnhance() { + return get(KEY_QC_MEMORY_COLOR_ENHANCEMENT); + } + + /** @hide + * Sets the current MCE Mode. + * + * @return MCE Mode + */ + public void setMemColorEnhance(String mce) { + set(KEY_QC_MEMORY_COLOR_ENHANCEMENT, mce); + } + + /** @hide + * Set white balance manual cct value. + * + * @param cct user CCT setting. + */ + public void setWBManualCCT(int cct) { + set(KEY_QC_WB_MANUAL_CCT, Integer.toString(cct)); + } + + /** @hide + * Gets the WB min supported CCT. + * + * @return min cct value. + */ + public String getWBMinCCT() { + return get(KEY_QC_MIN_WB_CCT); + } + + /** @hide + * Gets the WB max supported CCT. + * + * @return max cct value. + */ + public String getMaxWBCCT() { + return get(KEY_QC_MAX_WB_CCT); + } + + /** @hide + * Gets the current WB CCT. + * + * @return CCT value + */ + public String getWBCurrentCCT() { + return get(KEY_QC_WB_MANUAL_CCT); + } + + /** @hide + * Gets the current ZSL Mode. + * + * @return ZSL mode value + */ + public String getZSLMode() { + return get(KEY_QC_ZSL); + } + + /** @hide + * Sets the current ZSL Mode. ZSL mode is set as a 0th bit in KEY_CAMERA_MODE. + * + * @return null + */ + public void setZSLMode(String zsl) { + set(KEY_QC_ZSL, zsl); + } + + /** @hide + * Sets the current Auto HDR Mode. + * @ auto_hdr auto hdr string for enable/disable + * @return null + */ + public void setAutoHDRMode(String auto_hdr){ + set(KEY_QC_AUTO_HDR_ENABLE,auto_hdr); + } + + /** @hide + * Gets the current Camera Mode Flag. Camera mode includes a + * flag(byte) which indicates different camera modes. + * For now support for ZSL added at bit0 + * + * @return Camera Mode. + */ + public String getCameraMode() { + return get(KEY_QC_CAMERA_MODE); + } + + /** @hide + * Sets the current Camera Mode. + * + * @return null + */ + public void setCameraMode(int cameraMode) { + set(KEY_QC_CAMERA_MODE, cameraMode); + } + + private static final int MANUAL_FOCUS_POS_TYPE_INDEX = 0; + private static final int MANUAL_FOCUS_POS_TYPE_DAC = 1; + /** @hide + * Set focus position. + * + * @param pos user setting of focus position. + */ + public void setFocusPosition(int type, int pos) { + set(KEY_QC_MANUAL_FOCUS_POS_TYPE, Integer.toString(type)); + set(KEY_QC_MANUAL_FOCUS_POSITION, Integer.toString(pos)); + } + + /** @hide + * Gets the current focus position. + * + * @return current focus position + */ + public String getCurrentFocusPosition() { + return get(KEY_QC_MANUAL_FOCUS_POSITION); + } + + + /** @hide + * Gets the current HFR Mode. + * + * @return VIDEO_HFR_XXX string constants + */ + public String getVideoHighFrameRate() { + return get(KEY_QC_VIDEO_HIGH_FRAME_RATE); + } + + /** @hide + * Sets the current HFR Mode. + * + * @param hfr VIDEO_HFR_XXX string constants + */ + public void setVideoHighFrameRate(String hfr) { + set(KEY_QC_VIDEO_HIGH_FRAME_RATE, hfr); + } + + /** @hide + * Gets the current Video HDR Mode. + * + * @return Video HDR mode value + */ + public String getVideoHDRMode() { + return get(KEY_QC_VIDEO_HDR); + } + + /** @hide + * Sets the current Video HDR Mode. + * + * @return null + */ + public void setVideoHDRMode(String videohdr) { + set(KEY_QC_VIDEO_HDR, videohdr); + } + + /** @hide + * Gets the current DENOISE setting. + * + * @return one of DENOISE_XXX string constant. null if Denoise + * setting is not supported. + * + */ + public String getDenoise() { + return get(KEY_QC_DENOISE); + } + + /** @hide + * Gets the current Continuous AF setting. + * + * @return one of CONTINUOUS_AF_XXX string constant. null if continuous AF + * setting is not supported. + * + */ + public String getContinuousAf() { + return get(KEY_QC_CONTINUOUS_AF); + } + + /** @hide + * Sets the current Denoise mode. + * @param value DENOISE_XXX string constants. + * + */ + + public void setDenoise(String value) { + set(KEY_QC_DENOISE, value); + } + + /** @hide + * Sets the current Continuous AF mode. + * @param value CONTINUOUS_AF_XXX string constants. + * + */ + public void setContinuousAf(String value) { + set(KEY_QC_CONTINUOUS_AF, value); + } + + /** @hide + * Gets the current selectable zone af setting. + * + * @return one of SELECTABLE_ZONE_AF_XXX string constant. null if selectable zone af + * setting is not supported. + */ + public String getSelectableZoneAf() { + return get(KEY_QC_SELECTABLE_ZONE_AF); + } + + /** @hide + * Sets the current selectable zone af setting. + * + * @param value SELECTABLE_ZONE_AF_XXX string constants. + */ + public void setSelectableZoneAf(String value) { + set(KEY_QC_SELECTABLE_ZONE_AF, value); + } + + /** @hide + * Gets the current face detection setting. + * + * @return one of FACE_DETECTION_XXX string constant. null if face detection + * setting is not supported. + * + */ + public String getFaceDetectionMode() { + return get(KEY_QC_FACE_DETECTION); + } + + /** @hide + * Sets the auto scene detect. Other settings like Touch AF/AEC might be + * changed after setting face detection. + * + * @param value FACE_DETECTION_XXX string constants. + * + */ + public void setFaceDetectionMode(String value) { + set(KEY_QC_FACE_DETECTION, value); + } + + /** @hide + * Gets the current video rotation setting. + * + * @return one of VIDEO_QC_ROTATION_XXX string constant. null if video rotation + * setting is not supported. + */ + public String getVideoRotation() { + return get(KEY_QC_VIDEO_ROTATION); + } + + /** @hide + * Sets the current video rotation setting. + * + * @param value VIDEO_QC_ROTATION_XXX string constants. + */ + public void setVideoRotation(String value) { + set(KEY_QC_VIDEO_ROTATION, value); + } + /** @hide + * Gets the supported video rotation modes. + * + * @return a List of VIDEO_QC_ROTATION_XXX string constant. null if this + * setting is not supported. + */ + public List<String> getSupportedVideoRotationValues() { + String str = get(KEY_QC_VIDEO_ROTATION + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + // Splits a comma delimited string to an ArrayList of Coordinate. + // Return null if the passing string is null or the Coordinate is 0. + private ArrayList<Coordinate> splitCoordinate(String str) { + if (str == null) return null; + TextUtils.StringSplitter splitter = new TextUtils.SimpleStringSplitter(','); + splitter.setString(str); + ArrayList<Coordinate> coordinateList = new ArrayList<Coordinate>(); + for (String s : splitter) { + Coordinate coordinate = strToCoordinate(s); + if (coordinate != null) coordinateList.add(coordinate); + } + if (coordinateList.size() == 0) return null; + return coordinateList; + } + + // Parses a string (ex: "500x500") to Coordinate object. + // Return null if the passing string is null. + private Coordinate strToCoordinate(String str) { + if (str == null) return null; + + int pos = str.indexOf('x'); + if (pos != -1) { + String x = str.substring(0, pos); + String y = str.substring(pos + 1); + return new Coordinate(Integer.parseInt(x), + Integer.parseInt(y)); + } + Log.e(TAG, "Invalid Coordinate parameter string=" + str); + return null; + } + /* ### QC ADD-ONS: END */ }; } diff --git a/core/java/android/hardware/SystemSensorManager.java b/core/java/android/hardware/SystemSensorManager.java index 7abfabf4a2ac..acfc415d54e4 100644 --- a/core/java/android/hardware/SystemSensorManager.java +++ b/core/java/android/hardware/SystemSensorManager.java @@ -144,6 +144,7 @@ public class SystemSensorManager extends SensorManager { @Override protected boolean registerListenerImpl(SensorEventListener listener, Sensor sensor, int delayUs, Handler handler, int maxBatchReportLatencyUs, int reservedFlags) { + android.util.SeempLog.record_sensor_rate(381, sensor, delayUs); if (listener == null || sensor == null) { Log.e(TAG, "sensor or listener is null"); return false; @@ -191,6 +192,7 @@ public class SystemSensorManager extends SensorManager { /** @hide */ @Override protected void unregisterListenerImpl(SensorEventListener listener, Sensor sensor) { + android.util.SeempLog.record_sensor(382, sensor); // Trigger Sensors should use the cancelTriggerSensor call. if (sensor != null && sensor.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT) { return; diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java index 9c213f2f27a5..4f89c16f9822 100644 --- a/core/java/android/hardware/camera2/CameraDevice.java +++ b/core/java/android/hardware/camera2/CameraDevice.java @@ -465,6 +465,10 @@ public abstract class CameraDevice implements AutoCloseable { @NonNull CameraCaptureSession.StateCallback callback, @Nullable Handler handler) throws CameraAccessException; + /** @hide */ + public abstract void setVendorStreamConfigMode(int index) + throws CameraAccessException; + /** * <p>Create a new camera capture session by providing the target output set of Surfaces and * its corresponding surface configuration to the camera device.</p> diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java index 536c2e13389b..0e37961160ee 100644 --- a/core/java/android/hardware/camera2/CameraManager.java +++ b/core/java/android/hardware/camera2/CameraManager.java @@ -21,6 +21,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SystemService; +import android.app.ActivityThread; import android.content.Context; import android.hardware.CameraInfo; import android.hardware.CameraStatus; @@ -38,6 +39,8 @@ import android.os.RemoteException; import android.os.ServiceManager; import android.os.ServiceSpecificException; import android.os.SystemProperties; +import android.text.TextUtils; +import android.util.Log; import android.util.ArrayMap; import android.util.Log; import android.util.Size; @@ -981,8 +984,22 @@ public final class CameraManager { // Try to make sure we have an up-to-date list of camera devices. connectCameraServiceLocked(); + boolean exposeAuxCamera = false; + String packageName = ActivityThread.currentOpPackageName(); + String packageList = SystemProperties.get("vendor.camera.aux.packagelist"); + if (packageList.length() > 0) { + TextUtils.StringSplitter splitter = new TextUtils.SimpleStringSplitter(','); + splitter.setString(packageList); + for (String str : splitter) { + if (packageName.equals(str)) { + exposeAuxCamera = true; + break; + } + } + } int idCount = 0; for (int i = 0; i < mDeviceStatus.size(); i++) { + if(!exposeAuxCamera && (i == 2)) break; int status = mDeviceStatus.valueAt(i); if (status == ICameraServiceListener.STATUS_NOT_PRESENT || status == ICameraServiceListener.STATUS_ENUMERATING) continue; @@ -991,6 +1008,7 @@ public final class CameraManager { cameraIds = new String[idCount]; idCount = 0; for (int i = 0; i < mDeviceStatus.size(); i++) { + if(!exposeAuxCamera && (i == 2)) break; int status = mDeviceStatus.valueAt(i); if (status == ICameraServiceListener.STATUS_NOT_PRESENT || status == ICameraServiceListener.STATUS_ENUMERATING) continue; @@ -1039,6 +1057,26 @@ public final class CameraManager { throw new IllegalArgumentException("cameraId was null"); } + /* Force to expose only two cameras + * if the package name does not falls in this bucket + */ + boolean exposeAuxCamera = false; + String packageName = ActivityThread.currentOpPackageName(); + String packageList = SystemProperties.get("vendor.camera.aux.packagelist"); + if (packageList.length() > 0) { + TextUtils.StringSplitter splitter = new TextUtils.SimpleStringSplitter(','); + splitter.setString(packageList); + for (String str : splitter) { + if (packageName.equals(str)) { + exposeAuxCamera = true; + break; + } + } + } + if (exposeAuxCamera == false && (Integer.parseInt(cameraId) >= 2)) { + throw new IllegalArgumentException("invalid cameraId"); + } + ICameraService cameraService = getCameraService(); if (cameraService == null) { throw new CameraAccessException(CameraAccessException.CAMERA_DISCONNECTED, @@ -1172,6 +1210,30 @@ public final class CameraManager { } private void onStatusChangedLocked(int status, String id) { + /* Force to ignore the last mono/aux camera status update + * if the package name does not falls in this bucket + */ + boolean exposeMonoCamera = false; + String packageName = ActivityThread.currentOpPackageName(); + String packageList = SystemProperties.get("vendor.camera.aux.packagelist"); + if (packageList.length() > 0) { + TextUtils.StringSplitter splitter = new TextUtils.SimpleStringSplitter(','); + splitter.setString(packageList); + for (String str : splitter) { + if (packageName.equals(str)) { + exposeMonoCamera = true; + break; + } + } + } + + if (exposeMonoCamera == false) { + if (Integer.parseInt(id) >= 2) { + Log.w(TAG, "[soar.cts] ignore the status update of camera: " + id); + return; + } + } + if (DEBUG) { Log.v(TAG, String.format("Camera id %s has status changed to 0x%x", id, status)); @@ -1247,6 +1309,31 @@ public final class CameraManager { String.format("Camera id %s has torch status changed to 0x%x", id, status)); } + /* Force to ignore the aux or composite camera torch status update + * if the package name does not falls in this bucket + */ + boolean exposeMonoCamera = false; + String packageName = ActivityThread.currentOpPackageName(); + String packageList = SystemProperties.get("vendor.camera.aux.packagelist"); + if (packageList.length() > 0) { + TextUtils.StringSplitter splitter = new TextUtils.SimpleStringSplitter(','); + splitter.setString(packageList); + for (String str : splitter) { + if (packageName.equals(str)) { + exposeMonoCamera = true; + break; + } + } + } + + if (exposeMonoCamera == false) { + if (Integer.parseInt(id) >= 2) { + Log.w(TAG, "ignore the torch status update of camera: " + id); + return; + } + } + + if (!validTorchStatus(status)) { Log.e(TAG, String.format("Ignoring invalid device %s torch status 0x%x", id, status)); diff --git a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java index a4640c1fa519..eee5f7febdf2 100644 --- a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java +++ b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java @@ -206,7 +206,8 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession } else if (request.isReprocess() && !isReprocessable()) { throw new IllegalArgumentException("this capture session cannot handle reprocess " + "requests"); - } else if (request.isReprocess() && request.getReprocessableSessionId() != mId) { + } else if (!mDeviceImpl.isPrivilegedApp() && + request.isReprocess() && request.getReprocessableSessionId() != mId) { throw new IllegalArgumentException("capture request was created for another session"); } } diff --git a/core/java/android/hardware/camera2/impl/CameraConstrainedHighSpeedCaptureSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraConstrainedHighSpeedCaptureSessionImpl.java index 3494a7f2801e..549fb9dbdfe3 100644 --- a/core/java/android/hardware/camera2/impl/CameraConstrainedHighSpeedCaptureSessionImpl.java +++ b/core/java/android/hardware/camera2/impl/CameraConstrainedHighSpeedCaptureSessionImpl.java @@ -23,9 +23,11 @@ import android.hardware.camera2.CameraDevice; import android.hardware.camera2.CaptureRequest; import android.hardware.camera2.params.OutputConfiguration; import android.hardware.camera2.params.StreamConfigurationMap; +import android.hardware.camera2.params.HighSpeedVideoConfiguration; import android.hardware.camera2.utils.SurfaceUtils; import android.os.Handler; import android.util.Range; +import android.util.Size; import android.view.Surface; import java.util.ArrayList; @@ -83,10 +85,7 @@ public class CameraConstrainedHighSpeedCaptureSessionImpl mCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); SurfaceUtils.checkConstrainedHighSpeedSurfaces(outputSurfaces, fpsRange, config); - // Request list size: to limit the preview to 30fps, need use maxFps/30; to maximize - // the preview frame rate, should use maxBatch size for that high speed stream - // configuration. We choose the former for now. - int requestListSize = fpsRange.getUpper() / 30; + int requestListSize = getHighSpeedRequestListSize(fpsRange, outputSurfaces); List<CaptureRequest> requestList = new ArrayList<CaptureRequest>(); // Prepare the Request builders: need carry over the request controls. @@ -165,6 +164,34 @@ public class CameraConstrainedHighSpeedCaptureSessionImpl return true; } + private int getHighSpeedRequestListSize(Range<Integer> fpsRange, Collection<Surface> surfaces) { + int requestListSize = 0; + + for (Surface surface : surfaces) { + + if (SurfaceUtils.isSurfaceForHwVideoEncoder(surface)) { + Size surfaceSize = SurfaceUtils.getSurfaceSize(surface); + HighSpeedVideoConfiguration[] highSpeedVideoConfigurations = + mCharacteristics.get(CameraCharacteristics.CONTROL_AVAILABLE_HIGH_SPEED_VIDEO_CONFIGURATIONS); + + // Get the batchsize for matching FPS & video size + for (HighSpeedVideoConfiguration config : highSpeedVideoConfigurations) { + if (config.getSize().equals(surfaceSize) && config.getFpsRange().equals(fpsRange)) { + requestListSize = config.getBatchSizeMax(); + break; + } + } + break; + } + } + + if (requestListSize == 0) { + // If cant' find the matching batch size, limit the preview to 30fps. + requestListSize = fpsRange.getUpper() / 30; + } + return requestListSize; + } + @Override public CameraDevice getDevice() { return mSessionImpl.getDevice(); diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java index 57b608f0fd84..e0405f26b20b 100644 --- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java +++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java @@ -16,10 +16,13 @@ package android.hardware.camera2.impl; +import static android.hardware.camera2.CameraAccessException.CAMERA_IN_USE; import static com.android.internal.util.function.pooled.PooledLambda.obtainRunnable; import android.annotation.NonNull; import android.hardware.ICameraService; +import android.app.ActivityThread; +import android.graphics.ImageFormat; import android.hardware.camera2.CameraAccessException; import android.hardware.camera2.CameraCaptureSession; import android.hardware.camera2.CameraCharacteristics; @@ -43,6 +46,8 @@ import android.os.IBinder; import android.os.Looper; import android.os.RemoteException; import android.os.ServiceSpecificException; +import android.os.SystemProperties; +import android.text.TextUtils; import android.util.Log; import android.util.Range; import android.util.Size; @@ -74,7 +79,7 @@ public class CameraDeviceImpl extends CameraDevice private final boolean DEBUG = false; private static final int REQUEST_ID_NONE = -1; - + private int customOpMode = 0; // TODO: guard every function with if (!mRemoteDevice) check (if it was closed) private ICameraDeviceUserWrapper mRemoteDevice; @@ -124,6 +129,7 @@ public class CameraDeviceImpl extends CameraDevice private int mNextSessionId = 0; private final int mAppTargetSdkVersion; + private boolean mIsPrivilegedApp = false; // Runnables for all state transitions, except error, which needs the // error code argument @@ -266,6 +272,7 @@ public class CameraDeviceImpl extends CameraDevice } else { mTotalPartialCount = partialCount; } + mIsPrivilegedApp = checkPrivilegedAppList(); } public CameraDeviceCallbacks getCallbacks() { @@ -354,6 +361,10 @@ public class CameraDeviceImpl extends CameraDevice } } + public void setVendorStreamConfigMode(int fpsrange) { + customOpMode = fpsrange; + } + @Override public String getId() { return mCameraId; @@ -467,6 +478,7 @@ public class CameraDeviceImpl extends CameraDevice mConfiguredOutputs.put(streamId, outConfig); } } + operatingMode = (operatingMode | (customOpMode << 16)); if (sessionParams != null) { mRemoteDevice.endConfigure(operatingMode, sessionParams.getNativeCopy()); @@ -1201,11 +1213,41 @@ public class CameraDeviceImpl extends CameraDevice } } + private boolean checkPrivilegedAppList() { + String packageName = ActivityThread.currentOpPackageName(); + String packageList = SystemProperties.get("persist.vendor.camera.privapp.list"); + + if (packageList.length() > 0) { + TextUtils.StringSplitter splitter = new TextUtils.SimpleStringSplitter(','); + splitter.setString(packageList); + for (String str : splitter) { + if (packageName.equals(str)) { + return true; + } + } + } + + return false; + } + + public boolean isPrivilegedApp() { + return mIsPrivilegedApp; + } + private void checkInputConfiguration(InputConfiguration inputConfig) { if (inputConfig != null) { StreamConfigurationMap configMap = mCharacteristics.get( CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); + /* + * don't check input format and size, + * if the package name is in the white list + */ + if (isPrivilegedApp()) { + Log.w(TAG, "ignore input format/size check for white listed app"); + return; + } + int[] inputFormats = configMap.getInputFormats(); boolean validFormat = false; for (int format : inputFormats) { diff --git a/core/java/android/hardware/camera2/utils/SurfaceUtils.java b/core/java/android/hardware/camera2/utils/SurfaceUtils.java index d3c4505c37f0..9eb8d32056b4 100644 --- a/core/java/android/hardware/camera2/utils/SurfaceUtils.java +++ b/core/java/android/hardware/camera2/utils/SurfaceUtils.java @@ -30,6 +30,11 @@ import java.util.Collection; import java.util.Iterator; import java.util.List; +import android.app.ActivityThread; +import android.os.SystemProperties; +import android.text.TextUtils; + + /** * Various Surface utilities. */ @@ -157,7 +162,13 @@ public class SurfaceUtils { + " the size must be 1 or 2"); } + if (isPrivilegedApp()) { + //skip checks for privileged apps + return; + } + List<Size> highSpeedSizes = null; + if (fpsRange == null) { highSpeedSizes = Arrays.asList(config.getHighSpeedVideoSizes()); } else { @@ -209,4 +220,20 @@ public class SurfaceUtils { } } + private static boolean isPrivilegedApp() { + String packageName = ActivityThread.currentOpPackageName(); + String packageList = SystemProperties.get("persist.camera.privapp.list"); + + if (packageList.length() > 0) { + TextUtils.StringSplitter splitter = new TextUtils.SimpleStringSplitter(','); + splitter.setString(packageList); + for (String str : splitter) { + if (packageName.equals(str)) { + return true; + } + } + } + + return false; + } } diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index cee3a409fc23..34275dd17ecf 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -445,6 +445,13 @@ public class ConnectivityManager { public static final int TETHERING_BLUETOOTH = 2; /** + * WIGIG tethering type. Use a separate type to prevent + * conflicts with TETHERING_WIFI + * @hide + */ + public static final int TETHERING_WIGIG = 3; + + /** * Extra used for communicating with the TetherService. Includes the type of tethering to * enable if any. * @hide diff --git a/core/java/android/nfc/INfcAdapter.aidl b/core/java/android/nfc/INfcAdapter.aidl index 6801618e6a68..3908b21ff2ed 100644 --- a/core/java/android/nfc/INfcAdapter.aidl +++ b/core/java/android/nfc/INfcAdapter.aidl @@ -1,4 +1,7 @@ /* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * Not a Contribution. + * * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -31,6 +34,7 @@ import android.nfc.INfcUnlockHandler; import android.nfc.ITagRemovedCallback; import android.nfc.INfcDta; import android.os.Bundle; +import android.os.IBinder; /** * @hide @@ -42,6 +46,8 @@ interface INfcAdapter INfcFCardEmulation getNfcFCardEmulationInterface(); INfcAdapterExtras getNfcAdapterExtrasInterface(in String pkg); INfcDta getNfcDtaInterface(in String pkg); + IBinder getNfcAdapterVendorInterface(in String vendor); + int getState(); boolean disable(boolean saveState); boolean enable(); diff --git a/core/java/android/nfc/cardemulation/AidGroup.java b/core/java/android/nfc/cardemulation/AidGroup.java index 63776c4f397a..b283fe2ebbf8 100644 --- a/core/java/android/nfc/cardemulation/AidGroup.java +++ b/core/java/android/nfc/cardemulation/AidGroup.java @@ -1,4 +1,7 @@ /* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * Not a Contribution. + * * Copyright (C) 2015 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -38,7 +41,7 @@ import android.util.Log; * * @hide */ -public final class AidGroup implements Parcelable { +public class AidGroup implements Parcelable { /** * The maximum number of AIDs that can be present in any one group. */ @@ -47,11 +50,11 @@ public final class AidGroup implements Parcelable { static final String TAG = "AidGroup"; @UnsupportedAppUsage - final List<String> aids; + protected List<String> aids; @UnsupportedAppUsage - final String category; + protected String category; @UnsupportedAppUsage - final String description; + protected String description; /** * Creates a new AidGroup object. diff --git a/core/java/android/nfc/cardemulation/ApduServiceInfo.java b/core/java/android/nfc/cardemulation/ApduServiceInfo.java index 911ec8430ddd..f53920234a30 100644 --- a/core/java/android/nfc/cardemulation/ApduServiceInfo.java +++ b/core/java/android/nfc/cardemulation/ApduServiceInfo.java @@ -1,4 +1,7 @@ /* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * Not a Contribution. + * * Copyright (C) 2013 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -47,24 +50,24 @@ import java.util.Map; /** * @hide */ -public final class ApduServiceInfo implements Parcelable { +public class ApduServiceInfo implements Parcelable { static final String TAG = "ApduServiceInfo"; /** * The service that implements this */ @UnsupportedAppUsage - final ResolveInfo mService; + protected ResolveInfo mService; /** * Description of the service */ - final String mDescription; + protected String mDescription; /** * Whether this service represents AIDs running on the host CPU */ - final boolean mOnHost; + protected boolean mOnHost; /** * Offhost reader name. @@ -82,33 +85,33 @@ public final class ApduServiceInfo implements Parcelable { * Mapping from category to static AID group */ @UnsupportedAppUsage - final HashMap<String, AidGroup> mStaticAidGroups; + protected HashMap<String, AidGroup> mStaticAidGroups; /** * Mapping from category to dynamic AID group */ @UnsupportedAppUsage - final HashMap<String, AidGroup> mDynamicAidGroups; + protected HashMap<String, AidGroup> mDynamicAidGroups; /** * Whether this service should only be started when the device is unlocked. */ - final boolean mRequiresDeviceUnlock; + protected boolean mRequiresDeviceUnlock; /** * The id of the service banner specified in XML. */ - final int mBannerResourceId; + protected int mBannerResourceId; /** * The uid of the package the service belongs to */ - final int mUid; + protected int mUid; /** * Settings Activity for this service */ - final String mSettingsActivityName; + protected String mSettingsActivityName; /** * @hide diff --git a/core/java/android/nfc/tech/MifareClassic.java b/core/java/android/nfc/tech/MifareClassic.java index 080e058737b6..9cae043c4bdd 100644 --- a/core/java/android/nfc/tech/MifareClassic.java +++ b/core/java/android/nfc/tech/MifareClassic.java @@ -1,4 +1,6 @@ /* + * Copyright (C) 2018 NXP Semiconductors + * The original Work has been changed by NXP Semiconductors. * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -173,6 +175,10 @@ public final class MifareClassic extends BasicTagTechnology { mType = TYPE_CLASSIC; mSize = SIZE_4K; break; + case 0x19: + mType = TYPE_CLASSIC; + mSize = SIZE_2K; + break; case 0x28: mType = TYPE_CLASSIC; mSize = SIZE_1K; diff --git a/core/java/android/nfc/tech/NfcA.java b/core/java/android/nfc/tech/NfcA.java index 88730f9af3df..819e9e31b6e6 100644 --- a/core/java/android/nfc/tech/NfcA.java +++ b/core/java/android/nfc/tech/NfcA.java @@ -1,4 +1,6 @@ /* + * Copyright (C) 2018 NXP Semiconductors + * The original Work has been changed by NXP Semiconductors. * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -66,8 +68,15 @@ public final class NfcA extends BasicTagTechnology { /** @hide */ public NfcA(Tag tag) throws RemoteException { super(tag, TagTechnology.NFC_A); - Bundle extras = tag.getTechExtras(TagTechnology.NFC_A); - mSak = extras.getShort(EXTRA_SAK); + Bundle extras; + mSak = 0; + if(tag.hasTech(TagTechnology.MIFARE_CLASSIC)) + { + extras = tag.getTechExtras(TagTechnology.MIFARE_CLASSIC); + mSak = extras.getShort(EXTRA_SAK); + } + extras = tag.getTechExtras(TagTechnology.NFC_A); + mSak |= extras.getShort(EXTRA_SAK); mAtqa = extras.getByteArray(EXTRA_ATQA); } diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java index 760fef7566c7..b133dcaa22b6 100644 --- a/core/java/android/os/Process.java +++ b/core/java/android/os/Process.java @@ -818,6 +818,30 @@ public class Process { throws IllegalArgumentException, SecurityException; /** + * Sets the scheduling group for processes in the same cgroup.procs of uid and pid + * @hide + * @param uid The user identifier of the process to change. + * @param pid The identifier of the process to change. + * @param group The target group for this process from THREAD_GROUP_*. + * + * @throws IllegalArgumentException Throws IllegalArgumentException if + * <var>tid</var> does not exist. + * @throws SecurityException Throws SecurityException if your process does + * not have permission to modify the given thread, or to use the given + * priority. + * + * group == THREAD_GROUP_DEFAULT means to move all non-background priority + * threads to the foreground scheduling group, but to leave background + * priority threads alone. group == THREAD_GROUP_BG_NONINTERACTIVE moves all + * threads, regardless of priority, to the background scheduling group. + * group == THREAD_GROUP_FOREGROUND is not allowed. + * + * Always sets cpusets. + */ + public static final native void setCgroupProcsProcessGroup(int uid, int pid, int group) + throws IllegalArgumentException, SecurityException; + + /** * Return the scheduling group of requested process. * * @hide diff --git a/core/java/android/os/storage/IStorageManager.aidl b/core/java/android/os/storage/IStorageManager.aidl index f114b12cc3d1..f43d694d6cc2 100644 --- a/core/java/android/os/storage/IStorageManager.aidl +++ b/core/java/android/os/storage/IStorageManager.aidl @@ -191,4 +191,5 @@ interface IStorageManager { String translateAppToSystem(String path, int pid, int uid) = 81; String translateSystemToApp(String path, int pid, int uid) = 82; void commitChanges() = 83; + void clearUserKeyAuth(int userId, int serialNumber, in byte[] token, in byte[] secret) = 84; } diff --git a/core/java/android/provider/Browser.java b/core/java/android/provider/Browser.java index 30021b488dc5..7bb149d88f61 100644 --- a/core/java/android/provider/Browser.java +++ b/core/java/android/provider/Browser.java @@ -246,6 +246,7 @@ public class Browser { */ public static final Cursor getAllBookmarks(ContentResolver cr) throws IllegalStateException { + android.util.SeempLog.record(32); return new MatrixCursor(new String[]{Bookmarks.URL}, 0); } @@ -258,6 +259,7 @@ public class Browser { */ public static final Cursor getAllVisitedUrls(ContentResolver cr) throws IllegalStateException { + android.util.SeempLog.record(33); return new MatrixCursor(new String[]{Combined.URL}, 0); } @@ -266,6 +268,7 @@ public class Browser { } private static final Cursor getVisitedLike(ContentResolver cr, String url) { + android.util.SeempLog.record(34); boolean secure = false; String compareString = url; if (compareString.startsWith("http://")) { @@ -327,6 +330,7 @@ public class Browser { @Deprecated @UnsupportedAppUsage public static final String[] getVisitedHistory(ContentResolver cr) { + android.util.SeempLog.record(35); return new String[0]; } @@ -362,6 +366,7 @@ public class Browser { * @removed */ public static final void clearHistory(ContentResolver cr) { + android.util.SeempLog.record(37); } @@ -423,6 +428,7 @@ public class Browser { */ public static final void requestAllIcons(ContentResolver cr, String where, WebIconDatabase.IconListener listener) { + android.util.SeempLog.record(36); // Do nothing: this is no longer used. } diff --git a/core/java/android/provider/CalendarContract.java b/core/java/android/provider/CalendarContract.java index c167ea18f0c5..c68c4bd49e08 100644 --- a/core/java/android/provider/CalendarContract.java +++ b/core/java/android/provider/CalendarContract.java @@ -956,6 +956,7 @@ public final class CalendarContract { * @return A Cursor containing all attendees for the event */ public static final Cursor query(ContentResolver cr, long eventId, String[] projection) { + android.util.SeempLog.record(54); String[] attArgs = {Long.toString(eventId)}; return cr.query(CONTENT_URI, projection, ATTENDEES_WHERE, attArgs /* selection args */, null /* sort order */); @@ -1880,6 +1881,7 @@ public final class CalendarContract { */ public static final Cursor query(ContentResolver cr, String[] projection, long begin, long end) { + android.util.SeempLog.record(54); Uri.Builder builder = CONTENT_URI.buildUpon(); ContentUris.appendId(builder, begin); ContentUris.appendId(builder, end); @@ -1909,6 +1911,7 @@ public final class CalendarContract { */ public static final Cursor query(ContentResolver cr, String[] projection, long begin, long end, String searchQuery) { + android.util.SeempLog.record(54); Uri.Builder builder = CONTENT_SEARCH_URI.buildUpon(); ContentUris.appendId(builder, begin); ContentUris.appendId(builder, end); @@ -2216,6 +2219,7 @@ public final class CalendarContract { */ public static final Cursor query(ContentResolver cr, int startDay, int numDays, String[] projection) { + android.util.SeempLog.record(54); if (numDays < 1) { return null; } @@ -2299,6 +2303,7 @@ public final class CalendarContract { * @return A Cursor containing all reminders for the event */ public static final Cursor query(ContentResolver cr, long eventId, String[] projection) { + android.util.SeempLog.record(54); String[] remArgs = {Long.toString(eventId)}; return cr.query(CONTENT_URI, projection, REMINDERS_WHERE, remArgs /*selection args*/, null /* sort order */); @@ -2449,6 +2454,7 @@ public final class CalendarContract { */ public static final Uri insert(ContentResolver cr, long eventId, long begin, long end, long alarmTime, int minutes) { + android.util.SeempLog.record(51); ContentValues values = new ContentValues(); values.put(CalendarAlerts.EVENT_ID, eventId); values.put(CalendarAlerts.BEGIN, begin); @@ -2477,6 +2483,7 @@ public final class CalendarContract { */ @UnsupportedAppUsage public static final long findNextAlarmTime(ContentResolver cr, long millis) { + android.util.SeempLog.record(53); String selection = ALARM_TIME + ">=" + millis; // TODO: construct an explicit SQL query so that we can add // "LIMIT 1" to the end and get just one result. @@ -2603,6 +2610,7 @@ public final class CalendarContract { */ public static final boolean alarmExists(ContentResolver cr, long eventId, long begin, long alarmTime) { + android.util.SeempLog.record(52); // TODO: construct an explicit SQL query so that we can add // "LIMIT 1" to the end and get just one result. String[] projection = new String[] { ALARM_TIME }; diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java index 25554b937065..27096100bcc7 100644 --- a/core/java/android/provider/ContactsContract.java +++ b/core/java/android/provider/ContactsContract.java @@ -1624,6 +1624,7 @@ public final class ContactsContract { * {@link #CONTENT_LOOKUP_URI} to attempt refreshing. */ public static Uri getLookupUri(ContentResolver resolver, Uri contactUri) { + android.util.SeempLog.record(86); final Cursor c = resolver.query(contactUri, new String[] { Contacts.LOOKUP_KEY, Contacts._ID }, null, null, null); @@ -1651,6 +1652,7 @@ public final class ContactsContract { * provided parameters. */ public static Uri getLookupUri(long contactId, String lookupKey) { + android.util.SeempLog.record(86); if (TextUtils.isEmpty(lookupKey)) { return null; } @@ -1664,6 +1666,7 @@ public final class ContactsContract { * Returns null if the contact cannot be found. */ public static Uri lookupContact(ContentResolver resolver, Uri lookupUri) { + android.util.SeempLog.record(87); if (lookupUri == null) { return null; } @@ -2156,6 +2159,7 @@ public final class ContactsContract { */ public static InputStream openContactPhotoInputStream(ContentResolver cr, Uri contactUri, boolean preferHighres) { + android.util.SeempLog.record(88); if (preferHighres) { final Uri displayPhotoUri = Uri.withAppendedPath(contactUri, Contacts.Photo.DISPLAY_PHOTO); @@ -2204,6 +2208,7 @@ public final class ContactsContract { * of the thumbnail the high-res picture is preferred */ public static InputStream openContactPhotoInputStream(ContentResolver cr, Uri contactUri) { + android.util.SeempLog.record(88); return openContactPhotoInputStream(cr, contactUri, false); } } @@ -2880,6 +2885,7 @@ public final class ContactsContract { * entry of the given {@link RawContacts} entry. */ public static Uri getContactLookupUri(ContentResolver resolver, Uri rawContactUri) { + android.util.SeempLog.record(89); // TODO: use a lighter query by joining rawcontacts with contacts in provider final Uri dataUri = Uri.withAppendedPath(rawContactUri, Data.CONTENT_DIRECTORY); final Cursor cursor = resolver.query(dataUri, new String[] { @@ -4887,6 +4893,7 @@ public final class ContactsContract { * </p> */ public static Uri getContactLookupUri(ContentResolver resolver, Uri dataUri) { + android.util.SeempLog.record(89); final Cursor cursor = resolver.query(dataUri, new String[] { RawContacts.CONTACT_ID, Contacts.LOOKUP_KEY }, null, null, null); diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 8ef7ae1d89d3..6263293e0ec3 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -2441,6 +2441,7 @@ public final class Settings { @UnsupportedAppUsage public static String getStringForUser(ContentResolver resolver, String name, int userHandle) { + android.util.SeempLog.record(android.util.SeempLog.getSeempGetApiIdFromValue(name)); if (MOVED_TO_SECURE.contains(name)) { Log.w(TAG, "Setting " + name + " has moved from android.provider.Settings.System" + " to android.provider.Settings.Secure, returning read-only value."); @@ -2469,6 +2470,7 @@ public final class Settings { @UnsupportedAppUsage public static boolean putStringForUser(ContentResolver resolver, String name, String value, int userHandle) { + android.util.SeempLog.record(android.util.SeempLog.getSeempPutApiIdFromValue(name)); if (MOVED_TO_SECURE.contains(name)) { Log.w(TAG, "Setting " + name + " has moved from android.provider.Settings.System" + " to android.provider.Settings.Secure, value is unchanged."); @@ -4885,6 +4887,7 @@ public final class Settings { MOVED_TO_GLOBAL.add(Settings.Global.NITZ_UPDATE_SPACING); MOVED_TO_GLOBAL.add(Settings.Global.NTP_SERVER); MOVED_TO_GLOBAL.add(Settings.Global.NTP_TIMEOUT); + MOVED_TO_GLOBAL.add(Settings.Global.NTP_SERVER_2); MOVED_TO_GLOBAL.add(Settings.Global.PDP_WATCHDOG_ERROR_POLL_COUNT); MOVED_TO_GLOBAL.add(Settings.Global.PDP_WATCHDOG_LONG_POLL_INTERVAL_MS); MOVED_TO_GLOBAL.add(Settings.Global.PDP_WATCHDOG_MAX_PDP_RESET_FAIL_COUNT); @@ -4912,6 +4915,7 @@ public final class Settings { MOVED_TO_GLOBAL.add(Settings.Global.WIFI_SAVED_STATE); MOVED_TO_GLOBAL.add(Settings.Global.WIFI_SUPPLICANT_SCAN_INTERVAL_MS); MOVED_TO_GLOBAL.add(Settings.Global.WIFI_SUSPEND_OPTIMIZATIONS_ENABLED); + MOVED_TO_GLOBAL.add(Settings.Global.WIFI_COVERAGE_EXTEND_FEATURE_ENABLED); MOVED_TO_GLOBAL.add(Settings.Global.WIFI_VERBOSE_LOGGING_ENABLED); MOVED_TO_GLOBAL.add(Settings.Global.WIFI_ENHANCED_AUTO_JOIN); MOVED_TO_GLOBAL.add(Settings.Global.WIFI_NETWORK_SHOW_RSSI); @@ -5863,6 +5867,16 @@ public final class Settings { public static final int LOCATION_CHANGER_QUICK_SETTINGS = 2; /** + * Setting to configure Wifi disconnect delay duration in seconds. + * @hide + **/ + public static final String WIFI_DISCONNECT_DELAY_DURATION = + "wifi_disconnect_delay_duration"; + + private static final Validator WIFI_DISCONNECT_DELAY_DURATION_VALIDATOR = + NON_NEGATIVE_INTEGER_VALIDATOR; + + /** * Location access disabled. * * @deprecated See {@link #LOCATION_MODE}. @@ -8526,6 +8540,7 @@ public final class Settings { ZEN_SETTINGS_SUGGESTION_VIEWED, CHARGING_SOUNDS_ENABLED, CHARGING_VIBRATION_ENABLED, + WIFI_DISCONNECT_DELAY_DURATION, ACCESSIBILITY_NON_INTERACTIVE_UI_TIMEOUT_MS, ACCESSIBILITY_INTERACTIVE_UI_TIMEOUT_MS, NOTIFICATION_NEW_INTERRUPTION_MODEL, @@ -8692,6 +8707,7 @@ public final class Settings { VALIDATORS.put(ZEN_SETTINGS_SUGGESTION_VIEWED, BOOLEAN_VALIDATOR); VALIDATORS.put(CHARGING_SOUNDS_ENABLED, BOOLEAN_VALIDATOR); VALIDATORS.put(CHARGING_VIBRATION_ENABLED, BOOLEAN_VALIDATOR); + VALIDATORS.put(WIFI_DISCONNECT_DELAY_DURATION, WIFI_DISCONNECT_DELAY_DURATION_VALIDATOR); VALIDATORS.put(ACCESSIBILITY_NON_INTERACTIVE_UI_TIMEOUT_MS, NON_NEGATIVE_INTEGER_VALIDATOR); VALIDATORS.put(ACCESSIBILITY_INTERACTIVE_UI_TIMEOUT_MS, NON_NEGATIVE_INTEGER_VALIDATOR); @@ -9644,6 +9660,8 @@ public final class Settings { public static final String NTP_SERVER = "ntp_server"; /** Timeout in milliseconds to wait for NTP server. {@hide} */ public static final String NTP_TIMEOUT = "ntp_timeout"; + /** Secondary NTP server. {@hide} */ + public static final String NTP_SERVER_2 = "ntp_server_2"; /** {@hide} */ public static final String STORAGE_BENCHMARK_INTERVAL = "storage_benchmark_interval"; @@ -10424,6 +10442,14 @@ public final class Settings { public static final String WIFI_VERBOSE_LOGGING_ENABLED = "wifi_verbose_logging_enabled"; + /** + * Setting to enable Wi-Fi coverage extend feature; disabled by default, and setting to 1 + * will enable it. + * @hide + */ + public static final String WIFI_COVERAGE_EXTEND_FEATURE_ENABLED = + "wifi_coverage_extend_feature_enabled"; + /** * Setting to enable connected MAC randomization in Wi-Fi; disabled by default, and * setting to 1 will enable it. In the future, additional values may be supported. diff --git a/core/java/android/service/carrier/CarrierIdentifier.java b/core/java/android/service/carrier/CarrierIdentifier.java index 568ca0f6b56e..d3910748d963 100644 --- a/core/java/android/service/carrier/CarrierIdentifier.java +++ b/core/java/android/service/carrier/CarrierIdentifier.java @@ -53,12 +53,13 @@ public class CarrierIdentifier implements Parcelable { private @Nullable String mImsi; private @Nullable String mGid1; private @Nullable String mGid2; + private @Nullable String mIccid; private int mCarrierId = TelephonyManager.UNKNOWN_CARRIER_ID; private int mPreciseCarrierId = TelephonyManager.UNKNOWN_CARRIER_ID; public CarrierIdentifier(String mcc, String mnc, @Nullable String spn, @Nullable String imsi, @Nullable String gid1, @Nullable String gid2) { - this(mcc, mnc, spn, imsi, gid1, gid2, TelephonyManager.UNKNOWN_CARRIER_ID, + this(mcc, mnc, spn, imsi, gid1, gid2, null, TelephonyManager.UNKNOWN_CARRIER_ID, TelephonyManager.UNKNOWN_CARRIER_ID); } @@ -77,16 +78,31 @@ public class CarrierIdentifier implements Parcelable { public CarrierIdentifier(String mcc, String mnc, @Nullable String spn, @Nullable String imsi, @Nullable String gid1, @Nullable String gid2, int carrierid, int preciseCarrierId) { + this(mcc, mnc, spn, imsi, gid1, gid2, null, carrierid, preciseCarrierId); + } + + /** @hide */ + public CarrierIdentifier(String mcc, String mnc, @Nullable String spn, + @Nullable String imsi, @Nullable String gid1, @Nullable String gid2, + @Nullable String iccid, int carrierid, int preciseCarrierId) { mMcc = mcc; mMnc = mnc; mSpn = spn; mImsi = imsi; mGid1 = gid1; mGid2 = gid2; + mIccid = iccid; mCarrierId = carrierid; mPreciseCarrierId = preciseCarrierId; } + /** @hide */ + public CarrierIdentifier(String mcc, String mnc, @Nullable String spn, @Nullable String imsi, + @Nullable String gid1, @Nullable String gid2I, @Nullable String iccid) { + this(mcc, mnc, spn, imsi, gid1, gid2I); + mIccid = iccid; + } + /** * Creates a carrier identifier instance. * @@ -111,6 +127,7 @@ public class CarrierIdentifier implements Parcelable { mGid2 = gid2; mSpn = null; mImsi = null; + mIccid = null; } /** @hide */ @@ -152,6 +169,13 @@ public class CarrierIdentifier implements Parcelable { return mGid2; } + /** Get the ICCID. + * @hide */ + @Nullable + public String getIccid() { + return mIccid; + } + /** * Returns the carrier id. * @see TelephonyManager#getSimCarrierId() @@ -184,13 +208,14 @@ public class CarrierIdentifier implements Parcelable { && Objects.equals(mImsi, that.mImsi) && Objects.equals(mGid1, that.mGid1) && Objects.equals(mGid2, that.mGid2) + && Objects.equals(mIccid, that.mIccid) && Objects.equals(mCarrierId, that.mCarrierId) && Objects.equals(mPreciseCarrierId, that.mPreciseCarrierId); } @Override public int hashCode(){ - return Objects.hash(mMcc, mMnc, mSpn, mImsi, mGid1, mGid2, mCarrierId, mPreciseCarrierId); + return Objects.hash(mMcc, mMnc, mSpn, mImsi, mGid1, mGid2, mIccid, mCarrierId, mPreciseCarrierId); } @Override @@ -206,6 +231,7 @@ public class CarrierIdentifier implements Parcelable { out.writeString(mImsi); out.writeString(mGid1); out.writeString(mGid2); + out.writeString(mIccid); out.writeInt(mCarrierId); out.writeInt(mPreciseCarrierId); } @@ -213,15 +239,16 @@ public class CarrierIdentifier implements Parcelable { @Override public String toString() { return "CarrierIdentifier{" - + "mcc=" + mMcc - + ",mnc=" + mMnc - + ",spn=" + mSpn - + ",imsi=" + mImsi - + ",gid1=" + mGid1 - + ",gid2=" + mGid2 - + ",carrierid=" + mCarrierId - + ",mPreciseCarrierId=" + mPreciseCarrierId - + "}"; + + "mcc=" + mMcc + + ",mnc=" + mMnc + + ",spn=" + mSpn + + ",imsi=" + mImsi + + ",gid1=" + mGid1 + + ",gid2=" + mGid2 + + ",iccid=" + mIccid + + ",carrierid=" + mCarrierId + + ",mPreciseCarrierId=" + mPreciseCarrierId + + "}"; } /** @hide */ @@ -232,6 +259,7 @@ public class CarrierIdentifier implements Parcelable { mImsi = in.readString(); mGid1 = in.readString(); mGid2 = in.readString(); + mIccid = in.readString(); mCarrierId = in.readInt(); mPreciseCarrierId = in.readInt(); } @@ -243,5 +271,6 @@ public class CarrierIdentifier implements Parcelable { int IMSI_PREFIX = 2; int GID1 = 3; int GID2 = 4; + int ICCID = 5; } } diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java index 0d7223d67907..5625051a0d31 100644 --- a/core/java/android/service/wallpaper/WallpaperService.java +++ b/core/java/android/service/wallpaper/WallpaperService.java @@ -1426,7 +1426,7 @@ public abstract class WallpaperService extends Service { return; } case MSG_UPDATE_SURFACE: - mEngine.updateSurface(true, false, false); + mEngine.updateSurface(true, false, true/*false*/); break; case MSG_VISIBILITY_CHANGED: if (DEBUG) Log.v(TAG, "Visibility change in " + mEngine diff --git a/core/java/android/speech/SpeechRecognizer.java b/core/java/android/speech/SpeechRecognizer.java index 88e2edeee552..3eb24e499a9d 100644 --- a/core/java/android/speech/SpeechRecognizer.java +++ b/core/java/android/speech/SpeechRecognizer.java @@ -260,6 +260,7 @@ public class SpeechRecognizer { * not set explicitly, default values will be used by the recognizer. */ public void startListening(final Intent recognizerIntent) { + android.util.SeempLog.record(72); if (recognizerIntent == null) { throw new IllegalArgumentException("intent must not be null"); } diff --git a/core/java/android/util/BoostFramework.java b/core/java/android/util/BoostFramework.java new file mode 100644 index 000000000000..1c679f178ba3 --- /dev/null +++ b/core/java/android/util/BoostFramework.java @@ -0,0 +1,392 @@ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package android.util; + +import android.content.Context; +import android.os.SystemProperties; +import android.util.Log; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; + +/** @hide */ +public class BoostFramework { + + private static final String TAG = "BoostFramework"; + private static final String PERFORMANCE_JAR = "/system/framework/QPerformance.jar"; + private static final String PERFORMANCE_CLASS = "com.qualcomm.qti.Performance"; + + private static final String UXPERFORMANCE_JAR = "/system/framework/UxPerformance.jar"; + private static final String UXPERFORMANCE_CLASS = "com.qualcomm.qti.UxPerformance"; + +/** @hide */ + private static boolean sIsLoaded = false; + private static Class<?> sPerfClass = null; + private static Method sAcquireFunc = null; + private static Method sPerfHintFunc = null; + private static Method sReleaseFunc = null; + private static Method sReleaseHandlerFunc = null; + private static Method sFeedbackFunc = null; + + private static int sIopv2 = -1; + private static Method sIOPStart = null; + private static Method sIOPStop = null; + private static Method sUXEngineEvents = null; + private static Method sUXEngineTrigger = null; + + private static boolean sUxIsLoaded = false; + private static Class<?> sUxPerfClass = null; + private static Method sUxIOPStart = null; + +/** @hide */ + private Object mPerf = null; + private Object mUxPerf = null; + + //perf hints + public static final int VENDOR_HINT_SCROLL_BOOST = 0x00001080; + public static final int VENDOR_HINT_FIRST_LAUNCH_BOOST = 0x00001081; + public static final int VENDOR_HINT_SUBSEQ_LAUNCH_BOOST = 0x00001082; + public static final int VENDOR_HINT_ANIM_BOOST = 0x00001083; + public static final int VENDOR_HINT_ACTIVITY_BOOST = 0x00001084; + public static final int VENDOR_HINT_TOUCH_BOOST = 0x00001085; + public static final int VENDOR_HINT_MTP_BOOST = 0x00001086; + public static final int VENDOR_HINT_DRAG_BOOST = 0x00001087; + public static final int VENDOR_HINT_PACKAGE_INSTALL_BOOST = 0x00001088; + public static final int VENDOR_HINT_ROTATION_LATENCY_BOOST = 0x00001089; + public static final int VENDOR_HINT_ROTATION_ANIM_BOOST = 0x00001090; + //perf events + public static final int VENDOR_HINT_FIRST_DRAW = 0x00001042; + public static final int VENDOR_HINT_TAP_EVENT = 0x00001043; + //feedback hints + public static final int VENDOR_FEEDBACK_WORKLOAD_TYPE = 0x00001601; + public static final int VENDOR_FEEDBACK_LAUNCH_END_POINT = 0x00001602; + + //UXE Events and Triggers + public static final int UXE_TRIGGER = 1; + public static final int UXE_EVENT_BINDAPP = 2; + public static final int UXE_EVENT_DISPLAYED_ACT = 3; + public static final int UXE_EVENT_KILL = 4; + public static final int UXE_EVENT_GAME = 5; + public static final int UXE_EVENT_SUB_LAUNCH = 6; + public static final int UXE_EVENT_PKG_UNINSTALL = 7; + public static final int UXE_EVENT_PKG_INSTALL = 8; + + public class Scroll { + public static final int VERTICAL = 1; + public static final int HORIZONTAL = 2; + public static final int PANEL_VIEW = 3; + public static final int PREFILING = 4; + }; + + public class Launch { + public static final int BOOST_V1 = 1; + public static final int BOOST_V2 = 2; + public static final int BOOST_V3 = 3; + public static final int BOOST_GAME = 4; + public static final int TYPE_SERVICE_START = 100; + }; + + public class Draw { + public static final int EVENT_TYPE_V1 = 1; + }; + + public class WorkloadType { + public static final int NOT_KNOWN = 0; + public static final int APP = 1; + public static final int GAME = 2; + public static final int BROWSER = 3; + public static final int PREPROAPP = 4; + }; + +/** @hide */ + public BoostFramework() { + initFunctions(); + + try { + if (sPerfClass != null) { + mPerf = sPerfClass.newInstance(); + } + if (sUxPerfClass != null) { + mUxPerf = sUxPerfClass.newInstance(); + } + } + catch(Exception e) { + Log.e(TAG,"BoostFramework() : Exception_2 = " + e); + } + } + +/** @hide */ + public BoostFramework(Context context) { + initFunctions(); + + try { + if (sPerfClass != null) { + Constructor cons = sPerfClass.getConstructor(Context.class); + if (cons != null) + mPerf = cons.newInstance(context); + } + if (sUxPerfClass != null) { + mUxPerf = sUxPerfClass.newInstance(); + } + } + catch(Exception e) { + Log.e(TAG,"BoostFramework() : Exception_3 = " + e); + } + } + +/** @hide */ + public BoostFramework(boolean isUntrustedDomain) { + initFunctions(); + + try { + if (sPerfClass != null) { + Constructor cons = sPerfClass.getConstructor(boolean.class); + if (cons != null) + mPerf = cons.newInstance(isUntrustedDomain); + } + if (sUxPerfClass != null) { + mUxPerf = sUxPerfClass.newInstance(); + } + } + catch(Exception e) { + Log.e(TAG,"BoostFramework() : Exception_5 = " + e); + } + } + + private void initFunctions () { + synchronized(BoostFramework.class) { + if (sIsLoaded == false) { + try { + sPerfClass = Class.forName(PERFORMANCE_CLASS); + + Class[] argClasses = new Class[] {int.class, int[].class}; + sAcquireFunc = sPerfClass.getMethod("perfLockAcquire", argClasses); + + argClasses = new Class[] {int.class, String.class, int.class, int.class}; + sPerfHintFunc = sPerfClass.getMethod("perfHint", argClasses); + + argClasses = new Class[] {}; + sReleaseFunc = sPerfClass.getMethod("perfLockRelease", argClasses); + + argClasses = new Class[] {int.class}; + sReleaseHandlerFunc = sPerfClass.getDeclaredMethod("perfLockReleaseHandler", argClasses); + + argClasses = new Class[] {int.class, String.class}; + sFeedbackFunc = sPerfClass.getMethod("perfGetFeedback", argClasses); + + argClasses = new Class[] {int.class, String.class, String.class}; + sIOPStart = sPerfClass.getDeclaredMethod("perfIOPrefetchStart", argClasses); + + argClasses = new Class[] {}; + sIOPStop = sPerfClass.getDeclaredMethod("perfIOPrefetchStop", argClasses); + + try { + argClasses = new Class[] {int.class, int.class, String.class, int.class}; + sUXEngineEvents = sPerfClass.getDeclaredMethod("perfUXEngine_events", + argClasses); + + argClasses = new Class[] {int.class}; + sUXEngineTrigger = sPerfClass.getDeclaredMethod("perfUXEngine_trigger", + argClasses); + } catch (Exception e) { + Log.i(TAG, "BoostFramework() : Exception_4 = PreferredApps not supported"); + } + + sIsLoaded = true; + } + catch(Exception e) { + Log.e(TAG,"BoostFramework() : Exception_1 = " + e); + } + // Load UXE Class now Adding new try/catch block to avoid + // any interference with Qperformance + try { + sUxPerfClass = Class.forName(UXPERFORMANCE_CLASS); + + Class[] argUxClasses = new Class[] {int.class, String.class, String.class}; + sUxIOPStart = sUxPerfClass.getDeclaredMethod("perfIOPrefetchStart", argUxClasses); + + sUxIsLoaded = true; + } + catch(Exception e) { + Log.e(TAG,"BoostFramework() Ux Perf: Exception = " + e); + } + } + } + } + +/** @hide */ + public int perfLockAcquire(int duration, int... list) { + int ret = -1; + try { + if (sAcquireFunc != null) { + Object retVal = sAcquireFunc.invoke(mPerf, duration, list); + ret = (int)retVal; + } + } catch(Exception e) { + Log.e(TAG,"Exception " + e); + } + return ret; + } + +/** @hide */ + public int perfLockRelease() { + int ret = -1; + try { + if (sReleaseFunc != null) { + Object retVal = sReleaseFunc.invoke(mPerf); + ret = (int)retVal; + } + } catch(Exception e) { + Log.e(TAG,"Exception " + e); + } + return ret; + } + +/** @hide */ + public int perfLockReleaseHandler(int handle) { + int ret = -1; + try { + if (sReleaseHandlerFunc != null) { + Object retVal = sReleaseHandlerFunc.invoke(mPerf, handle); + ret = (int)retVal; + } + } catch(Exception e) { + Log.e(TAG,"Exception " + e); + } + return ret; + } + +/** @hide */ + public int perfHint(int hint, String userDataStr) { + return perfHint(hint, userDataStr, -1, -1); + } + +/** @hide */ + public int perfHint(int hint, String userDataStr, int userData) { + return perfHint(hint, userDataStr, userData, -1); + } + +/** @hide */ + public int perfHint(int hint, String userDataStr, int userData1, int userData2) { + int ret = -1; + try { + if (sPerfHintFunc != null) { + Object retVal = sPerfHintFunc.invoke(mPerf, hint, userDataStr, userData1, userData2); + ret = (int)retVal; + } + } catch(Exception e) { + Log.e(TAG,"Exception " + e); + } + return ret; + } + +/** @hide */ + public int perfGetFeedback(int req, String userDataStr) { + int ret = -1; + try { + if (sFeedbackFunc != null) { + Object retVal = sFeedbackFunc.invoke(mPerf, req, userDataStr); + ret = (int)retVal; + } + } catch(Exception e) { + Log.e(TAG,"Exception " + e); + } + return ret; + } + +/** @hide */ + public int perfIOPrefetchStart(int pid, String pkgName, String codePath) { + int ret = -1; + try { + Object retVal = sIOPStart.invoke(mPerf, pid, pkgName, codePath); + ret = (int) retVal; + } catch (Exception e) { + Log.e(TAG, "Exception " + e); + } + try { + Object retVal = sUxIOPStart.invoke(mUxPerf, pid, pkgName, codePath); + ret = (int) retVal; + } catch (Exception e) { + Log.e(TAG, "Ux Perf Exception " + e); + } + + return ret; + } + +/** @hide */ + public int perfIOPrefetchStop() { + int ret = -1; + try { + Object retVal = sIOPStop.invoke(mPerf); + ret = (int) retVal; + } catch (Exception e) { + Log.e(TAG, "Exception " + e); + } + return ret; + } + +/** @hide */ + public int perfUXEngine_events(int opcode, int pid, String pkgName, int lat) { + int ret = -1; + if (sIopv2 == -1) { + sIopv2 = SystemProperties.getInt("vendor.iop.enable_uxe", 0); + } + + try { + if (sIopv2 == 0 || sUXEngineEvents == null) { + return ret; + } + Object retVal = sUXEngineEvents.invoke(mPerf, opcode, pid, pkgName, lat); + ret = (int) retVal; + } catch (Exception e) { + Log.e(TAG, "Exception " + e); + } + return ret; + } + + +/** @hide */ + public String perfUXEngine_trigger(int opcode) { + String ret = null; + if (sIopv2 == -1) { + sIopv2 = SystemProperties.getInt("vendor.iop.enable_uxe", 0); + } + try { + if (sIopv2 == 0 || sUXEngineTrigger == null) { + return ret; + } + Object retVal = sUXEngineTrigger.invoke(mPerf, opcode); + ret = (String) retVal; + } catch (Exception e) { + Log.e(TAG, "Exception " + e); + } + return ret; + } +}; diff --git a/core/java/android/util/NtpTrustedTime.java b/core/java/android/util/NtpTrustedTime.java index da566c934ef7..bb3ddcfbe3f9 100644 --- a/core/java/android/util/NtpTrustedTime.java +++ b/core/java/android/util/NtpTrustedTime.java @@ -25,6 +25,7 @@ import android.net.Network; import android.net.NetworkInfo; import android.net.SntpClient; import android.os.SystemClock; +import android.os.SystemProperties; import android.provider.Settings; import android.text.TextUtils; @@ -51,6 +52,12 @@ public class NtpTrustedTime implements TrustedTime { private long mCachedNtpElapsedRealtime; private long mCachedNtpCertainty; + private boolean mBackupmode = false; + private static String mBackupServer = ""; + private static int mNtpRetries = 0; + private static int mNtpRetriesMax = 0; + private static final String BACKUP_SERVER = "persist.backup.ntpServer"; + private NtpTrustedTime(String server, long timeout) { if (LOGD) Log.d(TAG, "creating NtpTrustedTime using " + server); mServer = server; @@ -76,6 +83,23 @@ public class NtpTrustedTime implements TrustedTime { final String server = secureServer != null ? secureServer : defaultServer; sSingleton = new NtpTrustedTime(server, timeout); sContext = context; + + final String sserver_prop = Settings.Global.getString( + resolver, Settings.Global.NTP_SERVER_2); + + final String secondServer_prop = ((null != sserver_prop) + && (0 < sserver_prop.length())) + ? sserver_prop : BACKUP_SERVER; + + final String backupServer = SystemProperties.get(secondServer_prop); + + if ((null != backupServer) && (0 < backupServer.length())) { + int retryMax = res.getInteger(com.android.internal.R.integer.config_ntpRetry); + if (0 < retryMax) { + sSingleton.mNtpRetriesMax = retryMax; + sSingleton.mBackupServer = (backupServer.trim()).replace("\"", ""); + } + } } return sSingleton; @@ -84,6 +108,11 @@ public class NtpTrustedTime implements TrustedTime { @Override @UnsupportedAppUsage public boolean forceRefresh() { + return hasCache() ? forceSync() : false; + } + + @Override + public boolean forceSync() { // We can't do this at initialization time: ConnectivityService might not be running yet. synchronized (this) { if (mCM == null) { @@ -117,13 +146,21 @@ public class NtpTrustedTime implements TrustedTime { if (LOGD) Log.d(TAG, "forceRefresh() from cache miss"); final SntpClient client = new SntpClient(); - if (client.requestTime(mServer, (int) mTimeout, network)) { + + String targetServer = mServer; + if (getBackupmode()) { + setBackupmode(false); + targetServer = mBackupServer; + } + if (LOGD) Log.d(TAG, "Ntp Server to access at:" + targetServer); + if (client.requestTime(targetServer, (int) mTimeout, network)) { mHasCache = true; mCachedNtpTime = client.getNtpTime(); mCachedNtpElapsedRealtime = client.getNtpTimeReference(); mCachedNtpCertainty = client.getRoundTripTime() / 2; return true; } else { + countInBackupmode(); return false; } } @@ -175,4 +212,32 @@ public class NtpTrustedTime implements TrustedTime { public long getCachedNtpTimeReference() { return mCachedNtpElapsedRealtime; } + + public void setBackupmode(boolean mode) { + if (isBackupSupported()) { + mBackupmode = mode; + } + if (LOGD) Log.d(TAG, "setBackupmode() set the backup mode to be:" + mBackupmode); + } + + private boolean getBackupmode() { + return mBackupmode; + } + + private boolean isBackupSupported() { + return ((0 < mNtpRetriesMax) && + (null != mBackupServer) && + (0 != mBackupServer.length())); + } + + private void countInBackupmode() { + if (isBackupSupported()) { + mNtpRetries++; + if (mNtpRetries >= mNtpRetriesMax) { + mNtpRetries = 0; + setBackupmode(true); + } + } + if (LOGD) Log.d(TAG, "countInBackupmode() func"); + } } diff --git a/core/java/android/util/SeempLog.java b/core/java/android/util/SeempLog.java new file mode 100644 index 000000000000..3764882644d8 --- /dev/null +++ b/core/java/android/util/SeempLog.java @@ -0,0 +1,754 @@ +/* + * Copyright (c) 2015, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package android.util; + +import com.android.internal.os.RuntimeInit; + +import java.io.PrintWriter; +import java.io.StringWriter; +import java.net.UnknownHostException; +import java.util.Hashtable; +import java.util.Map; +import java.util.List; +import java.util.Iterator; +import android.util.Log; +import android.provider.Settings; + +/** + * SeempLog + * + * @hide + */ +public final class SeempLog { + private SeempLog() { + } + + /** + * Send a log message to the seemp log. + * @param api The api triggering this message. + */ + public static int record(int api) { + return seemp_println_native(api, ""); + } + + /** + * Send a log message to the seemp log. + * @param api The api triggering this message. + * @param msg The message you would like logged. + */ + public static int record_str(int api, String msg) { + if ( msg != null ) { + return seemp_println_native(api, msg); + } + else { + return seemp_println_native(api, ""); + } + } + + public static int record_sensor(int api, + android.hardware.Sensor sensor) { + if ( sensor != null ) { + return seemp_println_native(api, "sensor="+sensor.getType()); + } + else { + return seemp_println_native(api, "sensor=-1"); + } + } + + public static int record_sensor_rate(int api, + android.hardware.Sensor sensor, int rate) { + if ( sensor != null ) { + return seemp_println_native(api, + "sensor="+sensor.getType() + ",rate="+rate); + } + else { + return seemp_println_native(api, "sensor=-1,rate=" + rate); + } + } + + public static int record_uri(int api, android.net.Uri uri) { + if ( uri != null ) { + return seemp_println_native(api, "uri, " + uri.toString()); + } + else { + return seemp_println_native(api, "uri, null" ); + } + } + + public static int record_vg_layout(int api, + android.view.ViewGroup.LayoutParams params) { + try { + android.view.WindowManager.LayoutParams p = + (android.view.WindowManager.LayoutParams) params; + if ( p != null ) { + return seemp_println_native(api, + "window_type=" + p.type + ",window_flag=" + p.flags); + } + else { + return seemp_println_native(api, ""); + } + } catch (ClassCastException cce) { + return seemp_println_native(api, ""); + } + } + + /** @hide */ public static native int seemp_println_native(int api, String msg); + + public static final int SEEMP_API_android_provider_Settings__get_ANDROID_ID_ = 7; + public static final int SEEMP_API_android_provider_Settings__get_ACCELEROMETER_ROTATION_ = 96; + public static final int SEEMP_API_android_provider_Settings__get_USER_ROTATION_ = 97; + public static final int SEEMP_API_android_provider_Settings__get_ADB_ENABLED_ = 98; + public static final int SEEMP_API_android_provider_Settings__get_DEBUG_APP_ = 99; + public static final int SEEMP_API_android_provider_Settings__get_WAIT_FOR_DEBUGGER_ = 100; + public static final int SEEMP_API_android_provider_Settings__get_AIRPLANE_MODE_ON_ = 101; + public static final int SEEMP_API_android_provider_Settings__get_AIRPLANE_MODE_RADIOS_ = 102; + public static final int SEEMP_API_android_provider_Settings__get_ALARM_ALERT_ = 103; + public static final int SEEMP_API_android_provider_Settings__get_NEXT_ALARM_FORMATTED_ = 104; + public static final int SEEMP_API_android_provider_Settings__get_ALWAYS_FINISH_ACTIVITIES_ = 105; + public static final int SEEMP_API_android_provider_Settings__get_LOGGING_ID_ = 106; + public static final int SEEMP_API_android_provider_Settings__get_ANIMATOR_DURATION_SCALE_ = 107; + public static final int SEEMP_API_android_provider_Settings__get_WINDOW_ANIMATION_SCALE_ = 108; + public static final int SEEMP_API_android_provider_Settings__get_FONT_SCALE_ = 109; + public static final int SEEMP_API_android_provider_Settings__get_SCREEN_BRIGHTNESS_ = 110; + public static final int SEEMP_API_android_provider_Settings__get_SCREEN_BRIGHTNESS_MODE_ = 111; + public static final int SEEMP_API_android_provider_Settings__get_SCREEN_BRIGHTNESS_MODE_AUTOMATIC_ = 112; + public static final int SEEMP_API_android_provider_Settings__get_SCREEN_BRIGHTNESS_MODE_MANUAL_ = 113; + public static final int SEEMP_API_android_provider_Settings__get_SCREEN_OFF_TIMEOUT_ = 114; + public static final int SEEMP_API_android_provider_Settings__get_DIM_SCREEN_ = 115; + public static final int SEEMP_API_android_provider_Settings__get_TRANSITION_ANIMATION_SCALE_ = 116; + public static final int SEEMP_API_android_provider_Settings__get_STAY_ON_WHILE_PLUGGED_IN_ = 117; + public static final int SEEMP_API_android_provider_Settings__get_WALLPAPER_ACTIVITY_ = 118; + public static final int SEEMP_API_android_provider_Settings__get_SHOW_PROCESSES_ = 119; + public static final int SEEMP_API_android_provider_Settings__get_SHOW_WEB_SUGGESTIONS_ = 120; + public static final int SEEMP_API_android_provider_Settings__get_SHOW_GTALK_SERVICE_STATUS_ = 121; + public static final int SEEMP_API_android_provider_Settings__get_USE_GOOGLE_MAIL_ = 122; + public static final int SEEMP_API_android_provider_Settings__get_AUTO_TIME_ = 123; + public static final int SEEMP_API_android_provider_Settings__get_AUTO_TIME_ZONE_ = 124; + public static final int SEEMP_API_android_provider_Settings__get_DATE_FORMAT_ = 125; + public static final int SEEMP_API_android_provider_Settings__get_TIME_12_24_ = 126; + public static final int SEEMP_API_android_provider_Settings__get_BLUETOOTH_DISCOVERABILITY_ = 127; + public static final int SEEMP_API_android_provider_Settings__get_BLUETOOTH_DISCOVERABILITY_TIMEOUT_ = 128; + public static final int SEEMP_API_android_provider_Settings__get_BLUETOOTH_ON_ = 129; + public static final int SEEMP_API_android_provider_Settings__get_DEVICE_PROVISIONED_ = 130; + public static final int SEEMP_API_android_provider_Settings__get_SETUP_WIZARD_HAS_RUN_ = 131; + public static final int SEEMP_API_android_provider_Settings__get_DTMF_TONE_WHEN_DIALING_ = 132; + public static final int SEEMP_API_android_provider_Settings__get_END_BUTTON_BEHAVIOR_ = 133; + public static final int SEEMP_API_android_provider_Settings__get_RINGTONE_ = 134; + public static final int SEEMP_API_android_provider_Settings__get_MODE_RINGER_ = 135; + public static final int SEEMP_API_android_provider_Settings__get_INSTALL_NON_MARKET_APPS_ = 136; + public static final int SEEMP_API_android_provider_Settings__get_LOCATION_PROVIDERS_ALLOWED_ = 137; + public static final int SEEMP_API_android_provider_Settings__get_LOCK_PATTERN_ENABLED_ = 138; + public static final int SEEMP_API_android_provider_Settings__get_LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED_ = 139; + public static final int SEEMP_API_android_provider_Settings__get_LOCK_PATTERN_VISIBLE_ = 140; + public static final int SEEMP_API_android_provider_Settings__get_NETWORK_PREFERENCE_ = 141; + public static final int SEEMP_API_android_provider_Settings__get_DATA_ROAMING_ = 142; + public static final int SEEMP_API_android_provider_Settings__get_HTTP_PROXY_ = 143; + public static final int SEEMP_API_android_provider_Settings__get_PARENTAL_CONTROL_ENABLED_ = 144; + public static final int SEEMP_API_android_provider_Settings__get_PARENTAL_CONTROL_LAST_UPDATE_ = 145; + public static final int SEEMP_API_android_provider_Settings__get_PARENTAL_CONTROL_REDIRECT_URL_ = 146; + public static final int SEEMP_API_android_provider_Settings__get_RADIO_BLUETOOTH_ = 147; + public static final int SEEMP_API_android_provider_Settings__get_RADIO_CELL_ = 148; + public static final int SEEMP_API_android_provider_Settings__get_RADIO_NFC_ = 149; + public static final int SEEMP_API_android_provider_Settings__get_RADIO_WIFI_ = 150; + public static final int SEEMP_API_android_provider_Settings__get_SYS_PROP_SETTING_VERSION_ = 151; + public static final int SEEMP_API_android_provider_Settings__get_SETTINGS_CLASSNAME_ = 152; + public static final int SEEMP_API_android_provider_Settings__get_TEXT_AUTO_CAPS_ = 153; + public static final int SEEMP_API_android_provider_Settings__get_TEXT_AUTO_PUNCTUATE_ = 154; + public static final int SEEMP_API_android_provider_Settings__get_TEXT_AUTO_REPLACE_ = 155; + public static final int SEEMP_API_android_provider_Settings__get_TEXT_SHOW_PASSWORD_ = 156; + public static final int SEEMP_API_android_provider_Settings__get_USB_MASS_STORAGE_ENABLED_ = 157; + public static final int SEEMP_API_android_provider_Settings__get_VIBRATE_ON_ = 158; + public static final int SEEMP_API_android_provider_Settings__get_HAPTIC_FEEDBACK_ENABLED_ = 159; + public static final int SEEMP_API_android_provider_Settings__get_VOLUME_ALARM_ = 160; + public static final int SEEMP_API_android_provider_Settings__get_VOLUME_BLUETOOTH_SCO_ = 161; + public static final int SEEMP_API_android_provider_Settings__get_VOLUME_MUSIC_ = 162; + public static final int SEEMP_API_android_provider_Settings__get_VOLUME_NOTIFICATION_ = 163; + public static final int SEEMP_API_android_provider_Settings__get_VOLUME_RING_ = 164; + public static final int SEEMP_API_android_provider_Settings__get_VOLUME_SYSTEM_ = 165; + public static final int SEEMP_API_android_provider_Settings__get_VOLUME_VOICE_ = 166; + public static final int SEEMP_API_android_provider_Settings__get_SOUND_EFFECTS_ENABLED_ = 167; + public static final int SEEMP_API_android_provider_Settings__get_MODE_RINGER_STREAMS_AFFECTED_ = 168; + public static final int SEEMP_API_android_provider_Settings__get_MUTE_STREAMS_AFFECTED_ = 169; + public static final int SEEMP_API_android_provider_Settings__get_NOTIFICATION_SOUND_ = 170; + public static final int SEEMP_API_android_provider_Settings__get_APPEND_FOR_LAST_AUDIBLE_ = 171; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_MAX_DHCP_RETRY_COUNT_ = 172; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS_ = 173; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON_ = 174; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY_ = 175; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_NUM_OPEN_NETWORKS_KEPT_ = 176; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_ON_ = 177; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_SLEEP_POLICY_ = 178; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_SLEEP_POLICY_DEFAULT_ = 179; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_SLEEP_POLICY_NEVER_ = 180; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_SLEEP_POLICY_NEVER_WHILE_PLUGGED_ = 181; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_STATIC_DNS1_ = 182; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_STATIC_DNS2_ = 183; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_STATIC_GATEWAY_ = 184; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_STATIC_IP_ = 185; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_STATIC_NETMASK_ = 186; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_USE_STATIC_IP_ = 187; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_ACCEPTABLE_PACKET_LOSS_PERCENTAGE_ = 188; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_AP_COUNT_ = 189; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_BACKGROUND_CHECK_DELAY_MS_ = 190; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_BACKGROUND_CHECK_ENABLED_ = 191; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_BACKGROUND_CHECK_TIMEOUT_MS_ = 192; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_INITIAL_IGNORED_PING_COUNT_ = 193; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_MAX_AP_CHECKS_ = 194; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_ON_ = 195; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_PING_COUNT_ = 196; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_PING_DELAY_MS_ = 197; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_PING_TIMEOUT_MS_ = 198; + public static final int SEEMP_API_android_provider_Settings__put_ACCELEROMETER_ROTATION_ = 199; + public static final int SEEMP_API_android_provider_Settings__put_USER_ROTATION_ = 200; + public static final int SEEMP_API_android_provider_Settings__put_ADB_ENABLED_ = 201; + public static final int SEEMP_API_android_provider_Settings__put_DEBUG_APP_ = 202; + public static final int SEEMP_API_android_provider_Settings__put_WAIT_FOR_DEBUGGER_ = 203; + public static final int SEEMP_API_android_provider_Settings__put_AIRPLANE_MODE_ON_ = 204; + public static final int SEEMP_API_android_provider_Settings__put_AIRPLANE_MODE_RADIOS_ = 205; + public static final int SEEMP_API_android_provider_Settings__put_ALARM_ALERT_ = 206; + public static final int SEEMP_API_android_provider_Settings__put_NEXT_ALARM_FORMATTED_ = 207; + public static final int SEEMP_API_android_provider_Settings__put_ALWAYS_FINISH_ACTIVITIES_ = 208; + public static final int SEEMP_API_android_provider_Settings__put_ANDROID_ID_ = 209; + public static final int SEEMP_API_android_provider_Settings__put_LOGGING_ID_ = 210; + public static final int SEEMP_API_android_provider_Settings__put_ANIMATOR_DURATION_SCALE_ = 211; + public static final int SEEMP_API_android_provider_Settings__put_WINDOW_ANIMATION_SCALE_ = 212; + public static final int SEEMP_API_android_provider_Settings__put_FONT_SCALE_ = 213; + public static final int SEEMP_API_android_provider_Settings__put_SCREEN_BRIGHTNESS_ = 214; + public static final int SEEMP_API_android_provider_Settings__put_SCREEN_BRIGHTNESS_MODE_ = 215; + public static final int SEEMP_API_android_provider_Settings__put_SCREEN_BRIGHTNESS_MODE_AUTOMATIC_ = 216; + public static final int SEEMP_API_android_provider_Settings__put_SCREEN_BRIGHTNESS_MODE_MANUAL_ = 217; + public static final int SEEMP_API_android_provider_Settings__put_SCREEN_OFF_TIMEOUT_ = 218; + public static final int SEEMP_API_android_provider_Settings__put_DIM_SCREEN_ = 219; + public static final int SEEMP_API_android_provider_Settings__put_TRANSITION_ANIMATION_SCALE_ = 220; + public static final int SEEMP_API_android_provider_Settings__put_STAY_ON_WHILE_PLUGGED_IN_ = 221; + public static final int SEEMP_API_android_provider_Settings__put_WALLPAPER_ACTIVITY_ = 222; + public static final int SEEMP_API_android_provider_Settings__put_SHOW_PROCESSES_ = 223; + public static final int SEEMP_API_android_provider_Settings__put_SHOW_WEB_SUGGESTIONS_ = 224; + public static final int SEEMP_API_android_provider_Settings__put_SHOW_GTALK_SERVICE_STATUS_ = 225; + public static final int SEEMP_API_android_provider_Settings__put_USE_GOOGLE_MAIL_ = 226; + public static final int SEEMP_API_android_provider_Settings__put_AUTO_TIME_ = 227; + public static final int SEEMP_API_android_provider_Settings__put_AUTO_TIME_ZONE_ = 228; + public static final int SEEMP_API_android_provider_Settings__put_DATE_FORMAT_ = 229; + public static final int SEEMP_API_android_provider_Settings__put_TIME_12_24_ = 230; + public static final int SEEMP_API_android_provider_Settings__put_BLUETOOTH_DISCOVERABILITY_ = 231; + public static final int SEEMP_API_android_provider_Settings__put_BLUETOOTH_DISCOVERABILITY_TIMEOUT_ = 232; + public static final int SEEMP_API_android_provider_Settings__put_BLUETOOTH_ON_ = 233; + public static final int SEEMP_API_android_provider_Settings__put_DEVICE_PROVISIONED_ = 234; + public static final int SEEMP_API_android_provider_Settings__put_SETUP_WIZARD_HAS_RUN_ = 235; + public static final int SEEMP_API_android_provider_Settings__put_DTMF_TONE_WHEN_DIALING_ = 236; + public static final int SEEMP_API_android_provider_Settings__put_END_BUTTON_BEHAVIOR_ = 237; + public static final int SEEMP_API_android_provider_Settings__put_RINGTONE_ = 238; + public static final int SEEMP_API_android_provider_Settings__put_MODE_RINGER_ = 239; + public static final int SEEMP_API_android_provider_Settings__put_INSTALL_NON_MARKET_APPS_ = 240; + public static final int SEEMP_API_android_provider_Settings__put_LOCATION_PROVIDERS_ALLOWED_ = 241; + public static final int SEEMP_API_android_provider_Settings__put_LOCK_PATTERN_ENABLED_ = 242; + public static final int SEEMP_API_android_provider_Settings__put_LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED_ = 243; + public static final int SEEMP_API_android_provider_Settings__put_LOCK_PATTERN_VISIBLE_ = 244; + public static final int SEEMP_API_android_provider_Settings__put_NETWORK_PREFERENCE_ = 245; + public static final int SEEMP_API_android_provider_Settings__put_DATA_ROAMING_ = 246; + public static final int SEEMP_API_android_provider_Settings__put_HTTP_PROXY_ = 247; + public static final int SEEMP_API_android_provider_Settings__put_PARENTAL_CONTROL_ENABLED_ = 248; + public static final int SEEMP_API_android_provider_Settings__put_PARENTAL_CONTROL_LAST_UPDATE_ = 249; + public static final int SEEMP_API_android_provider_Settings__put_PARENTAL_CONTROL_REDIRECT_URL_ = 250; + public static final int SEEMP_API_android_provider_Settings__put_RADIO_BLUETOOTH_ = 251; + public static final int SEEMP_API_android_provider_Settings__put_RADIO_CELL_ = 252; + public static final int SEEMP_API_android_provider_Settings__put_RADIO_NFC_ = 253; + public static final int SEEMP_API_android_provider_Settings__put_RADIO_WIFI_ = 254; + public static final int SEEMP_API_android_provider_Settings__put_SYS_PROP_SETTING_VERSION_ = 255; + public static final int SEEMP_API_android_provider_Settings__put_SETTINGS_CLASSNAME_ = 256; + public static final int SEEMP_API_android_provider_Settings__put_TEXT_AUTO_CAPS_ = 257; + public static final int SEEMP_API_android_provider_Settings__put_TEXT_AUTO_PUNCTUATE_ = 258; + public static final int SEEMP_API_android_provider_Settings__put_TEXT_AUTO_REPLACE_ = 259; + public static final int SEEMP_API_android_provider_Settings__put_TEXT_SHOW_PASSWORD_ = 260; + public static final int SEEMP_API_android_provider_Settings__put_USB_MASS_STORAGE_ENABLED_ = 261; + public static final int SEEMP_API_android_provider_Settings__put_VIBRATE_ON_ = 262; + public static final int SEEMP_API_android_provider_Settings__put_HAPTIC_FEEDBACK_ENABLED_ = 263; + public static final int SEEMP_API_android_provider_Settings__put_VOLUME_ALARM_ = 264; + public static final int SEEMP_API_android_provider_Settings__put_VOLUME_BLUETOOTH_SCO_ = 265; + public static final int SEEMP_API_android_provider_Settings__put_VOLUME_MUSIC_ = 266; + public static final int SEEMP_API_android_provider_Settings__put_VOLUME_NOTIFICATION_ = 267; + public static final int SEEMP_API_android_provider_Settings__put_VOLUME_RING_ = 268; + public static final int SEEMP_API_android_provider_Settings__put_VOLUME_SYSTEM_ = 269; + public static final int SEEMP_API_android_provider_Settings__put_VOLUME_VOICE_ = 270; + public static final int SEEMP_API_android_provider_Settings__put_SOUND_EFFECTS_ENABLED_ = 271; + public static final int SEEMP_API_android_provider_Settings__put_MODE_RINGER_STREAMS_AFFECTED_ = 272; + public static final int SEEMP_API_android_provider_Settings__put_MUTE_STREAMS_AFFECTED_ = 273; + public static final int SEEMP_API_android_provider_Settings__put_NOTIFICATION_SOUND_ = 274; + public static final int SEEMP_API_android_provider_Settings__put_APPEND_FOR_LAST_AUDIBLE_ = 275; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_MAX_DHCP_RETRY_COUNT_ = 276; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS_ = 277; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON_ = 278; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY_ = 279; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_NUM_OPEN_NETWORKS_KEPT_ = 280; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_ON_ = 281; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_SLEEP_POLICY_ = 282; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_SLEEP_POLICY_DEFAULT_ = 283; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_SLEEP_POLICY_NEVER_ = 284; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_SLEEP_POLICY_NEVER_WHILE_PLUGGED_ = 285; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_STATIC_DNS1_ = 286; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_STATIC_DNS2_ = 287; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_STATIC_GATEWAY_ = 288; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_STATIC_IP_ = 289; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_STATIC_NETMASK_ = 290; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_USE_STATIC_IP_ = 291; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_ACCEPTABLE_PACKET_LOSS_PERCENTAGE_ = 292; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_AP_COUNT_ = 293; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_BACKGROUND_CHECK_DELAY_MS_ = 294; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_BACKGROUND_CHECK_ENABLED_ = 295; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_BACKGROUND_CHECK_TIMEOUT_MS_ = 296; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_INITIAL_IGNORED_PING_COUNT_ = 297; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_MAX_AP_CHECKS_ = 298; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_ON_ = 299; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_PING_COUNT_ = 300; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_PING_DELAY_MS_ = 301; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_PING_TIMEOUT_MS_ = 302; + + private final static java.util.Map<String,Integer> value_to_get_map; + static { + value_to_get_map = new java.util.HashMap<String,Integer>( 198 ); + value_to_get_map.put(Settings.System.NOTIFICATION_SOUND, + SEEMP_API_android_provider_Settings__get_NOTIFICATION_SOUND_); + value_to_get_map.put(Settings.System.DTMF_TONE_WHEN_DIALING, + SEEMP_API_android_provider_Settings__get_DTMF_TONE_WHEN_DIALING_); + value_to_get_map.put(Settings.System.LOCK_PATTERN_ENABLED, + SEEMP_API_android_provider_Settings__get_LOCK_PATTERN_ENABLED_); + value_to_get_map.put(Settings.System.WIFI_MAX_DHCP_RETRY_COUNT, + SEEMP_API_android_provider_Settings__get_WIFI_MAX_DHCP_RETRY_COUNT_); + value_to_get_map.put(Settings.System.AUTO_TIME, + SEEMP_API_android_provider_Settings__get_AUTO_TIME_); + value_to_get_map.put(Settings.System.SETUP_WIZARD_HAS_RUN, + SEEMP_API_android_provider_Settings__get_SETUP_WIZARD_HAS_RUN_); + value_to_get_map.put(Settings.System.WIFI_WATCHDOG_BACKGROUND_CHECK_TIMEOUT_MS, + SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_BACKGROUND_CHECK_TIMEOUT_MS_); + value_to_get_map.put(Settings.System.LOCATION_PROVIDERS_ALLOWED, + SEEMP_API_android_provider_Settings__get_LOCATION_PROVIDERS_ALLOWED_); + value_to_get_map.put(Settings.System.ALARM_ALERT, + SEEMP_API_android_provider_Settings__get_ALARM_ALERT_); + value_to_get_map.put(Settings.System.VIBRATE_ON, + SEEMP_API_android_provider_Settings__get_VIBRATE_ON_); + value_to_get_map.put(Settings.System.USB_MASS_STORAGE_ENABLED, + SEEMP_API_android_provider_Settings__get_USB_MASS_STORAGE_ENABLED_); + value_to_get_map.put(Settings.System.WIFI_WATCHDOG_PING_DELAY_MS, + SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_PING_DELAY_MS_); + value_to_get_map.put(Settings.System.FONT_SCALE, + SEEMP_API_android_provider_Settings__get_FONT_SCALE_); + value_to_get_map.put(Settings.System.WIFI_WATCHDOG_AP_COUNT, + SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_AP_COUNT_); + value_to_get_map.put(Settings.System.ALWAYS_FINISH_ACTIVITIES, + SEEMP_API_android_provider_Settings__get_ALWAYS_FINISH_ACTIVITIES_); + value_to_get_map.put(Settings.System.ACCELEROMETER_ROTATION, + SEEMP_API_android_provider_Settings__get_ACCELEROMETER_ROTATION_); + value_to_get_map.put(Settings.System.WIFI_WATCHDOG_PING_TIMEOUT_MS, + SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_PING_TIMEOUT_MS_); + value_to_get_map.put(Settings.System.VOLUME_NOTIFICATION, + SEEMP_API_android_provider_Settings__get_VOLUME_NOTIFICATION_); + value_to_get_map.put(Settings.System.AIRPLANE_MODE_ON, + SEEMP_API_android_provider_Settings__get_AIRPLANE_MODE_ON_); + value_to_get_map.put(Settings.System.WIFI_WATCHDOG_BACKGROUND_CHECK_DELAY_MS, + SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_BACKGROUND_CHECK_DELAY_MS_); + value_to_get_map.put(Settings.System.WIFI_STATIC_IP, + SEEMP_API_android_provider_Settings__get_WIFI_STATIC_IP_); + value_to_get_map.put(Settings.System.RADIO_BLUETOOTH, + SEEMP_API_android_provider_Settings__get_RADIO_BLUETOOTH_); + value_to_get_map.put(Settings.System.BLUETOOTH_DISCOVERABILITY_TIMEOUT, + SEEMP_API_android_provider_Settings__get_BLUETOOTH_DISCOVERABILITY_TIMEOUT_); + value_to_get_map.put(Settings.System.VOLUME_RING, + SEEMP_API_android_provider_Settings__get_VOLUME_RING_); + value_to_get_map.put(Settings.System.MODE_RINGER_STREAMS_AFFECTED, + SEEMP_API_android_provider_Settings__get_MODE_RINGER_STREAMS_AFFECTED_); + value_to_get_map.put(Settings.System.VOLUME_SYSTEM, + SEEMP_API_android_provider_Settings__get_VOLUME_SYSTEM_); + value_to_get_map.put(Settings.System.SCREEN_OFF_TIMEOUT, + SEEMP_API_android_provider_Settings__get_SCREEN_OFF_TIMEOUT_); + value_to_get_map.put(Settings.System.RADIO_WIFI, + SEEMP_API_android_provider_Settings__get_RADIO_WIFI_); + value_to_get_map.put(Settings.System.AUTO_TIME_ZONE, + SEEMP_API_android_provider_Settings__get_AUTO_TIME_ZONE_); + value_to_get_map.put(Settings.System.TEXT_AUTO_CAPS, + SEEMP_API_android_provider_Settings__get_TEXT_AUTO_CAPS_); + value_to_get_map.put(Settings.System.WALLPAPER_ACTIVITY, + SEEMP_API_android_provider_Settings__get_WALLPAPER_ACTIVITY_); + value_to_get_map.put(Settings.System.ANIMATOR_DURATION_SCALE, + SEEMP_API_android_provider_Settings__get_ANIMATOR_DURATION_SCALE_); + value_to_get_map.put(Settings.System.WIFI_NUM_OPEN_NETWORKS_KEPT, + SEEMP_API_android_provider_Settings__get_WIFI_NUM_OPEN_NETWORKS_KEPT_); + value_to_get_map.put(Settings.System.LOCK_PATTERN_VISIBLE, + SEEMP_API_android_provider_Settings__get_LOCK_PATTERN_VISIBLE_); + value_to_get_map.put(Settings.System.VOLUME_VOICE, + SEEMP_API_android_provider_Settings__get_VOLUME_VOICE_); + value_to_get_map.put(Settings.System.DEBUG_APP, + SEEMP_API_android_provider_Settings__get_DEBUG_APP_); + value_to_get_map.put(Settings.System.WIFI_ON, + SEEMP_API_android_provider_Settings__get_WIFI_ON_); + value_to_get_map.put(Settings.System.TEXT_SHOW_PASSWORD, + SEEMP_API_android_provider_Settings__get_TEXT_SHOW_PASSWORD_); + value_to_get_map.put(Settings.System.WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY, + SEEMP_API_android_provider_Settings__get_WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY_); + value_to_get_map.put(Settings.System.WIFI_SLEEP_POLICY, + SEEMP_API_android_provider_Settings__get_WIFI_SLEEP_POLICY_); + value_to_get_map.put(Settings.System.VOLUME_MUSIC, + SEEMP_API_android_provider_Settings__get_VOLUME_MUSIC_); + value_to_get_map.put(Settings.System.PARENTAL_CONTROL_LAST_UPDATE, + SEEMP_API_android_provider_Settings__get_PARENTAL_CONTROL_LAST_UPDATE_); + value_to_get_map.put(Settings.System.DEVICE_PROVISIONED, + SEEMP_API_android_provider_Settings__get_DEVICE_PROVISIONED_); + value_to_get_map.put(Settings.System.HTTP_PROXY, + SEEMP_API_android_provider_Settings__get_HTTP_PROXY_); + value_to_get_map.put(Settings.System.ANDROID_ID, + SEEMP_API_android_provider_Settings__get_ANDROID_ID_); + value_to_get_map.put(Settings.System.WIFI_WATCHDOG_MAX_AP_CHECKS, + SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_MAX_AP_CHECKS_); + value_to_get_map.put(Settings.System.END_BUTTON_BEHAVIOR, + SEEMP_API_android_provider_Settings__get_END_BUTTON_BEHAVIOR_); + value_to_get_map.put(Settings.System.NEXT_ALARM_FORMATTED, + SEEMP_API_android_provider_Settings__get_NEXT_ALARM_FORMATTED_); + value_to_get_map.put(Settings.System.RADIO_CELL, + SEEMP_API_android_provider_Settings__get_RADIO_CELL_); + value_to_get_map.put(Settings.System.PARENTAL_CONTROL_ENABLED, + SEEMP_API_android_provider_Settings__get_PARENTAL_CONTROL_ENABLED_); + value_to_get_map.put(Settings.System.BLUETOOTH_ON, + SEEMP_API_android_provider_Settings__get_BLUETOOTH_ON_); + value_to_get_map.put(Settings.System.WINDOW_ANIMATION_SCALE, + SEEMP_API_android_provider_Settings__get_WINDOW_ANIMATION_SCALE_); + value_to_get_map.put(Settings.System.WIFI_WATCHDOG_BACKGROUND_CHECK_ENABLED, + SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_BACKGROUND_CHECK_ENABLED_); + value_to_get_map.put(Settings.System.BLUETOOTH_DISCOVERABILITY, + SEEMP_API_android_provider_Settings__get_BLUETOOTH_DISCOVERABILITY_); + value_to_get_map.put(Settings.System.WIFI_STATIC_DNS1, + SEEMP_API_android_provider_Settings__get_WIFI_STATIC_DNS1_); + value_to_get_map.put(Settings.System.WIFI_STATIC_DNS2, + SEEMP_API_android_provider_Settings__get_WIFI_STATIC_DNS2_); + value_to_get_map.put(Settings.System.HAPTIC_FEEDBACK_ENABLED, + SEEMP_API_android_provider_Settings__get_HAPTIC_FEEDBACK_ENABLED_); + value_to_get_map.put(Settings.System.SHOW_WEB_SUGGESTIONS, + SEEMP_API_android_provider_Settings__get_SHOW_WEB_SUGGESTIONS_); + value_to_get_map.put(Settings.System.PARENTAL_CONTROL_REDIRECT_URL, + SEEMP_API_android_provider_Settings__get_PARENTAL_CONTROL_REDIRECT_URL_); + value_to_get_map.put(Settings.System.DATE_FORMAT, + SEEMP_API_android_provider_Settings__get_DATE_FORMAT_); + value_to_get_map.put(Settings.System.RADIO_NFC, + SEEMP_API_android_provider_Settings__get_RADIO_NFC_); + value_to_get_map.put(Settings.System.AIRPLANE_MODE_RADIOS, + SEEMP_API_android_provider_Settings__get_AIRPLANE_MODE_RADIOS_); + value_to_get_map.put(Settings.System.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED, + SEEMP_API_android_provider_Settings__get_LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED_); + value_to_get_map.put(Settings.System.TIME_12_24, + SEEMP_API_android_provider_Settings__get_TIME_12_24_); + value_to_get_map.put(Settings.System.WIFI_WATCHDOG_INITIAL_IGNORED_PING_COUNT, + SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_INITIAL_IGNORED_PING_COUNT_); + value_to_get_map.put(Settings.System.VOLUME_BLUETOOTH_SCO, + SEEMP_API_android_provider_Settings__get_VOLUME_BLUETOOTH_SCO_); + value_to_get_map.put(Settings.System.USER_ROTATION, + SEEMP_API_android_provider_Settings__get_USER_ROTATION_); + value_to_get_map.put(Settings.System.WIFI_STATIC_GATEWAY, + SEEMP_API_android_provider_Settings__get_WIFI_STATIC_GATEWAY_); + value_to_get_map.put(Settings.System.STAY_ON_WHILE_PLUGGED_IN, + SEEMP_API_android_provider_Settings__get_STAY_ON_WHILE_PLUGGED_IN_); + value_to_get_map.put(Settings.System.SOUND_EFFECTS_ENABLED, + SEEMP_API_android_provider_Settings__get_SOUND_EFFECTS_ENABLED_); + value_to_get_map.put(Settings.System.WIFI_WATCHDOG_PING_COUNT, + SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_PING_COUNT_); + value_to_get_map.put(Settings.System.DATA_ROAMING, + SEEMP_API_android_provider_Settings__get_DATA_ROAMING_); + value_to_get_map.put(Settings.System.SETTINGS_CLASSNAME, + SEEMP_API_android_provider_Settings__get_SETTINGS_CLASSNAME_); + value_to_get_map.put(Settings.System.TRANSITION_ANIMATION_SCALE, + SEEMP_API_android_provider_Settings__get_TRANSITION_ANIMATION_SCALE_); + value_to_get_map.put(Settings.System.WAIT_FOR_DEBUGGER, + SEEMP_API_android_provider_Settings__get_WAIT_FOR_DEBUGGER_); + value_to_get_map.put(Settings.System.INSTALL_NON_MARKET_APPS, + SEEMP_API_android_provider_Settings__get_INSTALL_NON_MARKET_APPS_); + value_to_get_map.put(Settings.System.ADB_ENABLED, + SEEMP_API_android_provider_Settings__get_ADB_ENABLED_); + value_to_get_map.put(Settings.System.WIFI_USE_STATIC_IP, + SEEMP_API_android_provider_Settings__get_WIFI_USE_STATIC_IP_); + value_to_get_map.put(Settings.System.DIM_SCREEN, + SEEMP_API_android_provider_Settings__get_DIM_SCREEN_); + value_to_get_map.put(Settings.System.VOLUME_ALARM, + SEEMP_API_android_provider_Settings__get_VOLUME_ALARM_); + value_to_get_map.put(Settings.System.WIFI_WATCHDOG_ON, + SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_ON_); + value_to_get_map.put(Settings.System.WIFI_STATIC_NETMASK, + SEEMP_API_android_provider_Settings__get_WIFI_STATIC_NETMASK_); + value_to_get_map.put(Settings.System.NETWORK_PREFERENCE, + SEEMP_API_android_provider_Settings__get_NETWORK_PREFERENCE_); + value_to_get_map.put(Settings.System.SHOW_PROCESSES, + SEEMP_API_android_provider_Settings__get_SHOW_PROCESSES_); + value_to_get_map.put(Settings.System.TEXT_AUTO_REPLACE, + SEEMP_API_android_provider_Settings__get_TEXT_AUTO_REPLACE_); + value_to_get_map.put(Settings.System.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, + SEEMP_API_android_provider_Settings__get_WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON_); + value_to_get_map.put(Settings.System.APPEND_FOR_LAST_AUDIBLE, + SEEMP_API_android_provider_Settings__get_APPEND_FOR_LAST_AUDIBLE_); + value_to_get_map.put(Settings.System.SHOW_GTALK_SERVICE_STATUS, + SEEMP_API_android_provider_Settings__get_SHOW_GTALK_SERVICE_STATUS_); + value_to_get_map.put(Settings.System.SCREEN_BRIGHTNESS, + SEEMP_API_android_provider_Settings__get_SCREEN_BRIGHTNESS_); + value_to_get_map.put(Settings.System.USE_GOOGLE_MAIL, + SEEMP_API_android_provider_Settings__get_USE_GOOGLE_MAIL_); + value_to_get_map.put(Settings.System.RINGTONE, + SEEMP_API_android_provider_Settings__get_RINGTONE_); + value_to_get_map.put(Settings.System.LOGGING_ID, + SEEMP_API_android_provider_Settings__get_LOGGING_ID_); + value_to_get_map.put(Settings.System.MODE_RINGER, + SEEMP_API_android_provider_Settings__get_MODE_RINGER_); + value_to_get_map.put(Settings.System.MUTE_STREAMS_AFFECTED, + SEEMP_API_android_provider_Settings__get_MUTE_STREAMS_AFFECTED_); + value_to_get_map.put(Settings.System.WIFI_WATCHDOG_ACCEPTABLE_PACKET_LOSS_PERCENTAGE, + SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_ACCEPTABLE_PACKET_LOSS_PERCENTAGE_); + value_to_get_map.put(Settings.System.TEXT_AUTO_PUNCTUATE, + SEEMP_API_android_provider_Settings__get_TEXT_AUTO_PUNCTUATE_); + value_to_get_map.put(Settings.System.WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS, + SEEMP_API_android_provider_Settings__get_WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS_); + value_to_get_map.put(Settings.System.SCREEN_BRIGHTNESS_MODE, + SEEMP_API_android_provider_Settings__get_SCREEN_BRIGHTNESS_MODE_); + } + + public static int getSeempGetApiIdFromValue( String v ) + { + Integer result = value_to_get_map.get( v ); + if (result == null) + { + result = -1; + } + return result; + } + + private final static java.util.Map<String,Integer> value_to_put_map; + static { + value_to_put_map = new java.util.HashMap<String,Integer>( 198 ); + value_to_put_map.put(Settings.System.NOTIFICATION_SOUND, + SEEMP_API_android_provider_Settings__put_NOTIFICATION_SOUND_); + value_to_put_map.put(Settings.System.DTMF_TONE_WHEN_DIALING, + SEEMP_API_android_provider_Settings__put_DTMF_TONE_WHEN_DIALING_); + value_to_put_map.put(Settings.System.LOCK_PATTERN_ENABLED, + SEEMP_API_android_provider_Settings__put_LOCK_PATTERN_ENABLED_); + value_to_put_map.put(Settings.System.WIFI_MAX_DHCP_RETRY_COUNT, + SEEMP_API_android_provider_Settings__put_WIFI_MAX_DHCP_RETRY_COUNT_); + value_to_put_map.put(Settings.System.AUTO_TIME, + SEEMP_API_android_provider_Settings__put_AUTO_TIME_); + value_to_put_map.put(Settings.System.SETUP_WIZARD_HAS_RUN, + SEEMP_API_android_provider_Settings__put_SETUP_WIZARD_HAS_RUN_); + value_to_put_map.put(Settings.System.WIFI_WATCHDOG_BACKGROUND_CHECK_TIMEOUT_MS, + SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_BACKGROUND_CHECK_TIMEOUT_MS_); + value_to_put_map.put(Settings.System.LOCATION_PROVIDERS_ALLOWED, + SEEMP_API_android_provider_Settings__put_LOCATION_PROVIDERS_ALLOWED_); + value_to_put_map.put(Settings.System.ALARM_ALERT, + SEEMP_API_android_provider_Settings__put_ALARM_ALERT_); + value_to_put_map.put(Settings.System.VIBRATE_ON, + SEEMP_API_android_provider_Settings__put_VIBRATE_ON_); + value_to_put_map.put(Settings.System.USB_MASS_STORAGE_ENABLED, + SEEMP_API_android_provider_Settings__put_USB_MASS_STORAGE_ENABLED_); + value_to_put_map.put(Settings.System.WIFI_WATCHDOG_PING_DELAY_MS, + SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_PING_DELAY_MS_); + value_to_put_map.put(Settings.System.FONT_SCALE, + SEEMP_API_android_provider_Settings__put_FONT_SCALE_); + value_to_put_map.put(Settings.System.WIFI_WATCHDOG_AP_COUNT, + SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_AP_COUNT_); + value_to_put_map.put(Settings.System.ALWAYS_FINISH_ACTIVITIES, + SEEMP_API_android_provider_Settings__put_ALWAYS_FINISH_ACTIVITIES_); + value_to_put_map.put(Settings.System.ACCELEROMETER_ROTATION, + SEEMP_API_android_provider_Settings__put_ACCELEROMETER_ROTATION_); + value_to_put_map.put(Settings.System.WIFI_WATCHDOG_PING_TIMEOUT_MS, + SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_PING_TIMEOUT_MS_); + value_to_put_map.put(Settings.System.VOLUME_NOTIFICATION, + SEEMP_API_android_provider_Settings__put_VOLUME_NOTIFICATION_); + value_to_put_map.put(Settings.System.AIRPLANE_MODE_ON, + SEEMP_API_android_provider_Settings__put_AIRPLANE_MODE_ON_); + value_to_put_map.put(Settings.System.WIFI_WATCHDOG_BACKGROUND_CHECK_DELAY_MS, + SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_BACKGROUND_CHECK_DELAY_MS_); + value_to_put_map.put(Settings.System.WIFI_STATIC_IP, + SEEMP_API_android_provider_Settings__put_WIFI_STATIC_IP_); + value_to_put_map.put(Settings.System.RADIO_BLUETOOTH, + SEEMP_API_android_provider_Settings__put_RADIO_BLUETOOTH_); + value_to_put_map.put(Settings.System.BLUETOOTH_DISCOVERABILITY_TIMEOUT, + SEEMP_API_android_provider_Settings__put_BLUETOOTH_DISCOVERABILITY_TIMEOUT_); + value_to_put_map.put(Settings.System.VOLUME_RING, + SEEMP_API_android_provider_Settings__put_VOLUME_RING_); + value_to_put_map.put(Settings.System.MODE_RINGER_STREAMS_AFFECTED, + SEEMP_API_android_provider_Settings__put_MODE_RINGER_STREAMS_AFFECTED_); + value_to_put_map.put(Settings.System.VOLUME_SYSTEM, + SEEMP_API_android_provider_Settings__put_VOLUME_SYSTEM_); + value_to_put_map.put(Settings.System.SCREEN_OFF_TIMEOUT, + SEEMP_API_android_provider_Settings__put_SCREEN_OFF_TIMEOUT_); + value_to_put_map.put(Settings.System.RADIO_WIFI, + SEEMP_API_android_provider_Settings__put_RADIO_WIFI_); + value_to_put_map.put(Settings.System.AUTO_TIME_ZONE, + SEEMP_API_android_provider_Settings__put_AUTO_TIME_ZONE_); + value_to_put_map.put(Settings.System.TEXT_AUTO_CAPS, + SEEMP_API_android_provider_Settings__put_TEXT_AUTO_CAPS_); + value_to_put_map.put(Settings.System.WALLPAPER_ACTIVITY, + SEEMP_API_android_provider_Settings__put_WALLPAPER_ACTIVITY_); + value_to_put_map.put(Settings.System.ANIMATOR_DURATION_SCALE, + SEEMP_API_android_provider_Settings__put_ANIMATOR_DURATION_SCALE_); + value_to_put_map.put(Settings.System.WIFI_NUM_OPEN_NETWORKS_KEPT, + SEEMP_API_android_provider_Settings__put_WIFI_NUM_OPEN_NETWORKS_KEPT_); + value_to_put_map.put(Settings.System.LOCK_PATTERN_VISIBLE, + SEEMP_API_android_provider_Settings__put_LOCK_PATTERN_VISIBLE_); + value_to_put_map.put(Settings.System.VOLUME_VOICE, + SEEMP_API_android_provider_Settings__put_VOLUME_VOICE_); + value_to_put_map.put(Settings.System.DEBUG_APP, + SEEMP_API_android_provider_Settings__put_DEBUG_APP_); + value_to_put_map.put(Settings.System.WIFI_ON, + SEEMP_API_android_provider_Settings__put_WIFI_ON_); + value_to_put_map.put(Settings.System.TEXT_SHOW_PASSWORD, + SEEMP_API_android_provider_Settings__put_TEXT_SHOW_PASSWORD_); + value_to_put_map.put(Settings.System.WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY, + SEEMP_API_android_provider_Settings__put_WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY_); + value_to_put_map.put(Settings.System.WIFI_SLEEP_POLICY, + SEEMP_API_android_provider_Settings__put_WIFI_SLEEP_POLICY_); + value_to_put_map.put(Settings.System.VOLUME_MUSIC, + SEEMP_API_android_provider_Settings__put_VOLUME_MUSIC_); + value_to_put_map.put(Settings.System.PARENTAL_CONTROL_LAST_UPDATE, + SEEMP_API_android_provider_Settings__put_PARENTAL_CONTROL_LAST_UPDATE_); + value_to_put_map.put(Settings.System.DEVICE_PROVISIONED, + SEEMP_API_android_provider_Settings__put_DEVICE_PROVISIONED_); + value_to_put_map.put(Settings.System.HTTP_PROXY, + SEEMP_API_android_provider_Settings__put_HTTP_PROXY_); + value_to_put_map.put(Settings.System.ANDROID_ID, + SEEMP_API_android_provider_Settings__put_ANDROID_ID_); + value_to_put_map.put(Settings.System.WIFI_WATCHDOG_MAX_AP_CHECKS, + SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_MAX_AP_CHECKS_); + value_to_put_map.put(Settings.System.END_BUTTON_BEHAVIOR, + SEEMP_API_android_provider_Settings__put_END_BUTTON_BEHAVIOR_); + value_to_put_map.put(Settings.System.NEXT_ALARM_FORMATTED, + SEEMP_API_android_provider_Settings__put_NEXT_ALARM_FORMATTED_); + value_to_put_map.put(Settings.System.RADIO_CELL, + SEEMP_API_android_provider_Settings__put_RADIO_CELL_); + value_to_put_map.put(Settings.System.PARENTAL_CONTROL_ENABLED, + SEEMP_API_android_provider_Settings__put_PARENTAL_CONTROL_ENABLED_); + value_to_put_map.put(Settings.System.BLUETOOTH_ON, + SEEMP_API_android_provider_Settings__put_BLUETOOTH_ON_); + value_to_put_map.put(Settings.System.WINDOW_ANIMATION_SCALE, + SEEMP_API_android_provider_Settings__put_WINDOW_ANIMATION_SCALE_); + value_to_put_map.put(Settings.System.WIFI_WATCHDOG_BACKGROUND_CHECK_ENABLED, + SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_BACKGROUND_CHECK_ENABLED_); + value_to_put_map.put(Settings.System.BLUETOOTH_DISCOVERABILITY, + SEEMP_API_android_provider_Settings__put_BLUETOOTH_DISCOVERABILITY_); + value_to_put_map.put(Settings.System.WIFI_STATIC_DNS1, + SEEMP_API_android_provider_Settings__put_WIFI_STATIC_DNS1_); + value_to_put_map.put(Settings.System.WIFI_STATIC_DNS2, + SEEMP_API_android_provider_Settings__put_WIFI_STATIC_DNS2_); + value_to_put_map.put(Settings.System.HAPTIC_FEEDBACK_ENABLED, + SEEMP_API_android_provider_Settings__put_HAPTIC_FEEDBACK_ENABLED_); + value_to_put_map.put(Settings.System.SHOW_WEB_SUGGESTIONS, + SEEMP_API_android_provider_Settings__put_SHOW_WEB_SUGGESTIONS_); + value_to_put_map.put(Settings.System.PARENTAL_CONTROL_REDIRECT_URL, + SEEMP_API_android_provider_Settings__put_PARENTAL_CONTROL_REDIRECT_URL_); + value_to_put_map.put(Settings.System.DATE_FORMAT, + SEEMP_API_android_provider_Settings__put_DATE_FORMAT_); + value_to_put_map.put(Settings.System.RADIO_NFC, + SEEMP_API_android_provider_Settings__put_RADIO_NFC_); + value_to_put_map.put(Settings.System.AIRPLANE_MODE_RADIOS, + SEEMP_API_android_provider_Settings__put_AIRPLANE_MODE_RADIOS_); + value_to_put_map.put(Settings.System.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED, + SEEMP_API_android_provider_Settings__put_LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED_); + value_to_put_map.put(Settings.System.TIME_12_24, + SEEMP_API_android_provider_Settings__put_TIME_12_24_); + value_to_put_map.put(Settings.System.WIFI_WATCHDOG_INITIAL_IGNORED_PING_COUNT, + SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_INITIAL_IGNORED_PING_COUNT_); + value_to_put_map.put(Settings.System.VOLUME_BLUETOOTH_SCO, + SEEMP_API_android_provider_Settings__put_VOLUME_BLUETOOTH_SCO_); + value_to_put_map.put(Settings.System.USER_ROTATION, + SEEMP_API_android_provider_Settings__put_USER_ROTATION_); + value_to_put_map.put(Settings.System.WIFI_STATIC_GATEWAY, + SEEMP_API_android_provider_Settings__put_WIFI_STATIC_GATEWAY_); + value_to_put_map.put(Settings.System.STAY_ON_WHILE_PLUGGED_IN, + SEEMP_API_android_provider_Settings__put_STAY_ON_WHILE_PLUGGED_IN_); + value_to_put_map.put(Settings.System.SOUND_EFFECTS_ENABLED, + SEEMP_API_android_provider_Settings__put_SOUND_EFFECTS_ENABLED_); + value_to_put_map.put(Settings.System.WIFI_WATCHDOG_PING_COUNT, + SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_PING_COUNT_); + value_to_put_map.put(Settings.System.DATA_ROAMING, + SEEMP_API_android_provider_Settings__put_DATA_ROAMING_); + value_to_put_map.put(Settings.System.SETTINGS_CLASSNAME, + SEEMP_API_android_provider_Settings__put_SETTINGS_CLASSNAME_); + value_to_put_map.put(Settings.System.TRANSITION_ANIMATION_SCALE, + SEEMP_API_android_provider_Settings__put_TRANSITION_ANIMATION_SCALE_); + value_to_put_map.put(Settings.System.WAIT_FOR_DEBUGGER, + SEEMP_API_android_provider_Settings__put_WAIT_FOR_DEBUGGER_); + value_to_put_map.put(Settings.System.INSTALL_NON_MARKET_APPS, + SEEMP_API_android_provider_Settings__put_INSTALL_NON_MARKET_APPS_); + value_to_put_map.put(Settings.System.ADB_ENABLED, + SEEMP_API_android_provider_Settings__put_ADB_ENABLED_); + value_to_put_map.put(Settings.System.WIFI_USE_STATIC_IP, + SEEMP_API_android_provider_Settings__put_WIFI_USE_STATIC_IP_); + value_to_put_map.put(Settings.System.DIM_SCREEN, + SEEMP_API_android_provider_Settings__put_DIM_SCREEN_); + value_to_put_map.put(Settings.System.VOLUME_ALARM, + SEEMP_API_android_provider_Settings__put_VOLUME_ALARM_); + value_to_put_map.put(Settings.System.WIFI_WATCHDOG_ON, + SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_ON_); + value_to_put_map.put(Settings.System.WIFI_STATIC_NETMASK, + SEEMP_API_android_provider_Settings__put_WIFI_STATIC_NETMASK_); + value_to_put_map.put(Settings.System.NETWORK_PREFERENCE, + SEEMP_API_android_provider_Settings__put_NETWORK_PREFERENCE_); + value_to_put_map.put(Settings.System.SHOW_PROCESSES, + SEEMP_API_android_provider_Settings__put_SHOW_PROCESSES_); + value_to_put_map.put(Settings.System.TEXT_AUTO_REPLACE, + SEEMP_API_android_provider_Settings__put_TEXT_AUTO_REPLACE_); + value_to_put_map.put(Settings.System.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, + SEEMP_API_android_provider_Settings__put_WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON_); + value_to_put_map.put(Settings.System.APPEND_FOR_LAST_AUDIBLE, + SEEMP_API_android_provider_Settings__put_APPEND_FOR_LAST_AUDIBLE_); + value_to_put_map.put(Settings.System.SHOW_GTALK_SERVICE_STATUS, + SEEMP_API_android_provider_Settings__put_SHOW_GTALK_SERVICE_STATUS_); + value_to_put_map.put(Settings.System.SCREEN_BRIGHTNESS, + SEEMP_API_android_provider_Settings__put_SCREEN_BRIGHTNESS_); + value_to_put_map.put(Settings.System.USE_GOOGLE_MAIL, + SEEMP_API_android_provider_Settings__put_USE_GOOGLE_MAIL_); + value_to_put_map.put(Settings.System.RINGTONE, + SEEMP_API_android_provider_Settings__put_RINGTONE_); + value_to_put_map.put(Settings.System.LOGGING_ID, + SEEMP_API_android_provider_Settings__put_LOGGING_ID_); + value_to_put_map.put(Settings.System.MODE_RINGER, + SEEMP_API_android_provider_Settings__put_MODE_RINGER_); + value_to_put_map.put(Settings.System.MUTE_STREAMS_AFFECTED, + SEEMP_API_android_provider_Settings__put_MUTE_STREAMS_AFFECTED_); + value_to_put_map.put(Settings.System.WIFI_WATCHDOG_ACCEPTABLE_PACKET_LOSS_PERCENTAGE, + SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_ACCEPTABLE_PACKET_LOSS_PERCENTAGE_); + value_to_put_map.put(Settings.System.TEXT_AUTO_PUNCTUATE, + SEEMP_API_android_provider_Settings__put_TEXT_AUTO_PUNCTUATE_); + value_to_put_map.put(Settings.System.WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS, + SEEMP_API_android_provider_Settings__put_WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS_); + value_to_put_map.put(Settings.System.SCREEN_BRIGHTNESS_MODE, + SEEMP_API_android_provider_Settings__put_SCREEN_BRIGHTNESS_MODE_); + } + + public static int getSeempPutApiIdFromValue( String v ) + { + Integer result = value_to_put_map.get( v ); + if (result == null) + { + result = -1; + } + return result; + } +} diff --git a/core/java/android/util/TrustedTime.java b/core/java/android/util/TrustedTime.java index c78665d06e75..0ae5dec3023b 100644 --- a/core/java/android/util/TrustedTime.java +++ b/core/java/android/util/TrustedTime.java @@ -29,6 +29,12 @@ public interface TrustedTime { * Force update with an external trusted time source, returning {@code true} * when successful. */ + public boolean forceSync(); + + /** + * Force update the cached time with an external trusted time source, + * returning {@code true} when successful. + */ @UnsupportedAppUsage public boolean forceRefresh(); diff --git a/core/java/android/util/apk/ApkSignatureVerifier.java b/core/java/android/util/apk/ApkSignatureVerifier.java index ac4ea75b38e3..2f70a951a61e 100644 --- a/core/java/android/util/apk/ApkSignatureVerifier.java +++ b/core/java/android/util/apk/ApkSignatureVerifier.java @@ -28,7 +28,10 @@ import android.content.pm.PackageParser.PackageParserException; import android.content.pm.PackageParser.SigningDetails.SignatureSchemeVersion; import android.content.pm.Signature; import android.os.Trace; +import android.util.ArrayMap; +import android.util.Slog; import android.util.jar.StrictJarFile; +import android.util.BoostFramework; import com.android.internal.util.ArrayUtils; @@ -46,6 +49,9 @@ import java.util.Iterator; import java.util.List; import java.util.concurrent.atomic.AtomicReference; import java.util.zip.ZipEntry; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.LinkedBlockingQueue; /** * Facade class that takes care of the details of APK verification on @@ -57,6 +63,12 @@ public class ApkSignatureVerifier { private static final AtomicReference<byte[]> sBuffer = new AtomicReference<>(); + private static final String TAG = "ApkSignatureVerifier"; + // multithread verification + private static final int NUMBER_OF_CORES = + Runtime.getRuntime().availableProcessors() >= 4 ? 4 : Runtime.getRuntime().availableProcessors() ; + private static BoostFramework sPerfBoost = null; + private static boolean sIsPerfLockAcquired = false; /** * Verifies the provided APK and returns the certificates associated with each signer. * @@ -160,31 +172,44 @@ public class ApkSignatureVerifier { private static PackageParser.SigningDetails verifyV1Signature( String apkPath, boolean verifyFull) throws PackageParserException { - StrictJarFile jarFile = null; - + int objectNumber = verifyFull ? NUMBER_OF_CORES : 1; + StrictJarFile[] jarFile = new StrictJarFile[objectNumber]; + final ArrayMap<String, StrictJarFile> strictJarFiles = new ArrayMap<String, StrictJarFile>(); try { final Certificate[][] lastCerts; final Signature[] lastSigs; Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "strictJarFileCtor"); + if (sPerfBoost == null) { + sPerfBoost = new BoostFramework(); + } + if (sPerfBoost != null && !sIsPerfLockAcquired && verifyFull) { + //Use big enough number here to hold the perflock for entire PackageInstall session + sPerfBoost.perfHint(BoostFramework.VENDOR_HINT_PACKAGE_INSTALL_BOOST, + null, Integer.MAX_VALUE, -1); + Slog.d(TAG, "Perflock acquired for PackageInstall "); + sIsPerfLockAcquired = true; + } // we still pass verify = true to ctor to collect certs, even though we're not checking // the whole jar. - jarFile = new StrictJarFile( - apkPath, - true, // collect certs - verifyFull); // whether to reject APK with stripped v2 signatures (b/27887819) + for (int i = 0; i < objectNumber; i++) { + jarFile[i] = new StrictJarFile( + apkPath, + true, // collect certs + verifyFull); // whether to reject APK with stripped v2 signatures (b/27887819) + } final List<ZipEntry> toVerify = new ArrayList<>(); // Gather certs from AndroidManifest.xml, which every APK must have, as an optimization // to not need to verify the whole APK when verifyFUll == false. - final ZipEntry manifestEntry = jarFile.findEntry( + final ZipEntry manifestEntry = jarFile[0].findEntry( PackageParser.ANDROID_MANIFEST_FILENAME); if (manifestEntry == null) { throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST, "Package " + apkPath + " has no manifest"); } - lastCerts = loadCertificates(jarFile, manifestEntry); + lastCerts = loadCertificates(jarFile[0], manifestEntry); if (ArrayUtils.isEmpty(lastCerts)) { throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES, "Package " + apkPath + " has no certificates at entry " @@ -194,7 +219,7 @@ public class ApkSignatureVerifier { // fully verify all contents, except for AndroidManifest.xml and the META-INF/ files. if (verifyFull) { - final Iterator<ZipEntry> i = jarFile.iterator(); + final Iterator<ZipEntry> i = jarFile[0].iterator(); while (i.hasNext()) { final ZipEntry entry = i.next(); if (entry.isDirectory()) continue; @@ -205,24 +230,93 @@ public class ApkSignatureVerifier { toVerify.add(entry); } - + class VerificationData { + public Exception exception; + public int exceptionFlag; + public boolean wait; + public int index; + public Object objWaitAll; + public boolean shutDown; + } + VerificationData vData = new VerificationData(); + vData.objWaitAll = new Object(); + final ThreadPoolExecutor verificationExecutor = new ThreadPoolExecutor( + NUMBER_OF_CORES, + NUMBER_OF_CORES, + 1,/*keep alive time*/ + TimeUnit.SECONDS, + new LinkedBlockingQueue<Runnable>()); for (ZipEntry entry : toVerify) { - final Certificate[][] entryCerts = loadCertificates(jarFile, entry); - if (ArrayUtils.isEmpty(entryCerts)) { - throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES, - "Package " + apkPath + " has no certificates at entry " - + entry.getName()); + Runnable verifyTask = new Runnable(){ + public void run() { + try { + if (vData.exceptionFlag != 0 ) { + Slog.w(TAG, "VerifyV1 exit with exception " + vData.exceptionFlag); + return; + } + String tid = Long.toString(Thread.currentThread().getId()); + StrictJarFile tempJarFile; + synchronized (strictJarFiles) { + tempJarFile = strictJarFiles.get(tid); + if (tempJarFile == null) { + if (vData.index >= NUMBER_OF_CORES) { + vData.index = 0; + } + tempJarFile = jarFile[vData.index++]; + strictJarFiles.put(tid, tempJarFile); + } + } + final Certificate[][] entryCerts = loadCertificates(tempJarFile, entry); + if (ArrayUtils.isEmpty(entryCerts)) { + throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES, + "Package " + apkPath + " has no certificates at entry " + + entry.getName()); + } + + // make sure all entries use the same signing certs + final Signature[] entrySigs = convertToSignatures(entryCerts); + if (!Signature.areExactMatch(lastSigs, entrySigs)) { + throw new PackageParserException( + INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES, + "Package " + apkPath + " has mismatched certificates at entry " + + entry.getName()); + } + } catch (GeneralSecurityException e) { + synchronized (vData.objWaitAll) { + vData.exceptionFlag = INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING; + vData.exception = e; + } + } catch (PackageParserException e) { + synchronized (vData.objWaitAll) { + vData.exceptionFlag = INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION; + vData.exception = e; + } + } + }}; + synchronized (vData.objWaitAll) { + if (vData.exceptionFlag == 0) { + verificationExecutor.execute(verifyTask); + } } - - // make sure all entries use the same signing certs - final Signature[] entrySigs = convertToSignatures(entryCerts); - if (!Signature.areExactMatch(lastSigs, entrySigs)) { - throw new PackageParserException( - INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES, - "Package " + apkPath + " has mismatched certificates at entry " - + entry.getName()); + } + vData.wait = true; + verificationExecutor.shutdown(); + while (vData.wait) { + try { + if (vData.exceptionFlag != 0 && !vData.shutDown) { + Slog.w(TAG, "verifyV1 Exception " + vData.exceptionFlag); + verificationExecutor.shutdownNow(); + vData.shutDown = true; + } + vData.wait = !verificationExecutor.awaitTermination(50, + TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + Slog.w(TAG,"VerifyV1 interrupted while awaiting all threads done..."); } } + if (vData.exceptionFlag != 0) + throw new PackageParserException(vData.exceptionFlag, + "Failed to collect certificates from " + apkPath, vData.exception); } return new PackageParser.SigningDetails(lastSigs, SignatureSchemeVersion.JAR); } catch (GeneralSecurityException e) { @@ -232,8 +326,16 @@ public class ApkSignatureVerifier { throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES, "Failed to collect certificates from " + apkPath, e); } finally { + if (sIsPerfLockAcquired && sPerfBoost != null) { + sPerfBoost.perfLockRelease(); + sIsPerfLockAcquired = false; + Slog.d(TAG, "Perflock released for PackageInstall "); + } + strictJarFiles.clear(); Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); - closeQuietly(jarFile); + for (int i = 0; i < objectNumber ; i++) { + closeQuietly(jarFile[i]); + } } } diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java index ccd0fc179f0e..d2ae0f84b8aa 100644 --- a/core/java/android/view/Choreographer.java +++ b/core/java/android/view/Choreographer.java @@ -84,6 +84,7 @@ public final class Choreographer { // Prints debug messages about jank which was detected (low volume). private static final boolean DEBUG_JANK = false; + private static final boolean OPTS_INPUT = true; // Prints debug messages about every frame and callback registered (high volume). private static final boolean DEBUG_FRAMES = false; @@ -151,6 +152,11 @@ public final class Choreographer { private static final int MSG_DO_SCHEDULE_VSYNC = 1; private static final int MSG_DO_SCHEDULE_CALLBACK = 2; + private static final int MOTION_EVENT_ACTION_DOWN = 0; + private static final int MOTION_EVENT_ACTION_UP = 1; + private static final int MOTION_EVENT_ACTION_MOVE = 2; + private static final int MOTION_EVENT_ACTION_CANCEL = 3; + // All frame callbacks posted by applications have this token. private static final Object FRAME_CALLBACK_TOKEN = new Object() { public String toString() { return "FRAME_CALLBACK_TOKEN"; } @@ -181,7 +187,10 @@ public final class Choreographer { private long mFrameIntervalNanos; private boolean mDebugPrintNextFrameTimeDelta; private int mFPSDivisor = 1; - + private int mTouchMoveNum = -1; + private int mMotionEventType = -1; + private boolean mConsumedMove = false; + private boolean mConsumedDown = false; /** * Contains information about the current frame for jank-tracking, * mainly timings of key events along with a bit of metadata about @@ -296,6 +305,16 @@ public final class Choreographer { } /** + * {@hide} + */ + public void setMotionEventInfo(int motionEventType, int touchMoveNum) { + synchronized(this) { + mTouchMoveNum = touchMoveNum; + mMotionEventType = motionEventType; + } + } + + /** * @return The Choreographer of the main thread, if it exists, or {@code null} otherwise. * @hide */ @@ -621,6 +640,42 @@ public final class Choreographer { private void scheduleFrameLocked(long now) { if (!mFrameScheduled) { mFrameScheduled = true; + if (OPTS_INPUT) { + Trace.traceBegin(Trace.TRACE_TAG_VIEW, "scheduleFrameLocked-mMotionEventType:" + mMotionEventType + " mTouchMoveNum:" + mTouchMoveNum + + " mConsumedDown:" + mConsumedDown + " mConsumedMove:" + mConsumedMove); + Trace.traceEnd(Trace.TRACE_TAG_VIEW); + synchronized(this) { + switch(mMotionEventType) { + case MOTION_EVENT_ACTION_DOWN: + mConsumedMove = false; + if (!mConsumedDown) { + Message msg = mHandler.obtainMessage(MSG_DO_FRAME); + msg.setAsynchronous(true); + mHandler.sendMessageAtFrontOfQueue(msg); + mConsumedDown = true; + return; + } + break; + case MOTION_EVENT_ACTION_MOVE: + mConsumedDown = false; + if ((mTouchMoveNum == 1) && !mConsumedMove) { + Message msg = mHandler.obtainMessage(MSG_DO_FRAME); + msg.setAsynchronous(true); + mHandler.sendMessageAtFrontOfQueue(msg); + mConsumedMove = true; + return; + } + break; + case MOTION_EVENT_ACTION_UP: + case MOTION_EVENT_ACTION_CANCEL: + mConsumedMove = false; + mConsumedDown = false; + break; + default: + break; + } + } + } if (USE_VSYNC) { if (DEBUG_FRAMES) { Log.d(TAG, "Scheduling next frame on vsync."); diff --git a/core/java/android/view/InputEventReceiver.java b/core/java/android/view/InputEventReceiver.java index 7260a658a027..1b66cf3698af 100644 --- a/core/java/android/view/InputEventReceiver.java +++ b/core/java/android/view/InputEventReceiver.java @@ -44,6 +44,7 @@ public abstract class InputEventReceiver { // Map from InputEvent sequence numbers to dispatcher sequence numbers. private final SparseIntArray mSeqMap = new SparseIntArray(); + Choreographer mChoreographer; private static native long nativeInit(WeakReference<InputEventReceiver> receiver, InputChannel inputChannel, MessageQueue messageQueue); @@ -195,6 +196,19 @@ public abstract class InputEventReceiver { onBatchedInputEventPending(); } + // Called from native code. + @SuppressWarnings("unused") + private void dispatchMotionEventInfo(int motionEventType, int touchMoveNum) { + try { + if (mChoreographer == null) + mChoreographer = Choreographer.getInstance(); + + if (mChoreographer != null) + mChoreographer.setMotionEventInfo(motionEventType, touchMoveNum); + } catch (Exception e) { + Log.e(TAG, "cannot invoke setMotionEventInfo."); + } + } public static interface Factory { public InputEventReceiver createInputEventReceiver( InputChannel inputChannel, Looper looper); diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java index 5e98236f7535..aba71d52c5fb 100644 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -331,6 +331,15 @@ public class SurfaceControl implements Parcelable { */ public static final int BUILT_IN_DISPLAY_ID_HDMI = 1; + /** + * Built-in physical display id: Additional Built-in display id range. + * HDMI display ID range will be HDMI ID to EXT_MIN ID. + * Built-in display ID range will bee EXT_MIN ID to EXT_MAX ID. + * Use only with {@link SurfaceControl#getBuiltInDisplay(int)}. + */ + public static final int BUILT_IN_DISPLAY_ID_EXT_MIN = 5; + public static final int BUILT_IN_DISPLAY_ID_EXT_MAX = 7; + /* Display power modes * / /** diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index a1aa06e901dc..d8a69d07b995 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -13288,6 +13288,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, final int actionMasked = event.getActionMasked(); if (actionMasked == MotionEvent.ACTION_DOWN) { + android.util.SeempLog.record(3); // Defensive cleanup for new gesture stopNestedScroll(); } @@ -13956,6 +13957,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @param event the KeyEvent object that defines the button action */ public boolean onKeyDown(int keyCode, KeyEvent event) { + android.util.SeempLog.record(4); if (KeyEvent.isConfirmKey(keyCode)) { if ((mViewFlags & ENABLED_MASK) == DISABLED) { return true; @@ -14008,6 +14010,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @param event The KeyEvent object that defines the button action. */ public boolean onKeyUp(int keyCode, KeyEvent event) { + android.util.SeempLog.record(5); if (KeyEvent.isConfirmKey(keyCode)) { if ((mViewFlags & ENABLED_MASK) == DISABLED) { return true; @@ -14616,6 +14619,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @return True if the event was handled, false otherwise. */ public boolean onTouchEvent(MotionEvent event) { + android.util.SeempLog.record(3); final float x = event.getX(); final float y = event.getY(); final int viewFlags = mViewFlags; diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 27d4ea4a777a..61064a230d8d 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -85,6 +85,7 @@ import android.util.Slog; import android.util.SparseArray; import android.util.TimeUtils; import android.util.TypedValue; +import android.util.BoostFramework; import android.view.Surface.OutOfResourcesException; import android.view.SurfaceControl.Transaction; import android.view.View.AttachInfo; @@ -190,6 +191,9 @@ public final class ViewRootImpl implements ViewParent, public static final String PROPERTY_EMULATOR_WIN_OUTSET_BOTTOM_PX = "ro.emu.win_outset_bottom_px"; + private final boolean SCROLL_BOOST_SS_ENABLE = + SystemProperties.getBoolean("vendor.perf.gestureflingboost.enable", false); + /** * Maximum time we allow the user to roll the trackball enough to generate * a key event, before resetting the counters. @@ -565,6 +569,9 @@ public final class ViewRootImpl implements ViewParent, } private String mTag = TAG; + boolean mHaveMoveEvent = false; + boolean mIsPerfLockAcquired = false; + BoostFramework mPerf = null; public ViewRootImpl(Context context, Display display) { mContext = context; @@ -629,6 +636,7 @@ public final class ViewRootImpl implements ViewParent, } loadSystemProperties(); + mPerf = new BoostFramework(context); } public static void addFirstDrawHandler(Runnable callback) { @@ -3444,6 +3452,13 @@ public final class ViewRootImpl implements ViewParent, scrollToRectOrFocus(null, false); if (mAttachInfo.mViewScrollChanged) { + if (!SCROLL_BOOST_SS_ENABLE && mHaveMoveEvent && !mIsPerfLockAcquired) { + mIsPerfLockAcquired = true; + if (mPerf != null) { + String currentPackage = mContext.getPackageName(); + mPerf.perfHint(BoostFramework.VENDOR_HINT_SCROLL_BOOST, currentPackage, -1, BoostFramework.Scroll.PREFILING); + } + } mAttachInfo.mViewScrollChanged = false; mAttachInfo.mTreeObserver.dispatchOnScrollChanged(); } @@ -5358,6 +5373,15 @@ public final class ViewRootImpl implements ViewParent, mAttachInfo.mUnbufferedDispatchRequested = false; mAttachInfo.mHandlingPointerEvent = true; boolean handled = mView.dispatchPointerEvent(event); + int action = event.getActionMasked(); + if (!SCROLL_BOOST_SS_ENABLE) { + if (action == MotionEvent.ACTION_MOVE) { + mHaveMoveEvent = true; + } else if (action == MotionEvent.ACTION_UP) { + mHaveMoveEvent = false; + mIsPerfLockAcquired = false; + } + } maybeUpdatePointerIcon(event); maybeUpdateTooltip(event); mAttachInfo.mHandlingPointerEvent = false; diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java index a102f6c8a74d..6d3edbc90bfd 100644 --- a/core/java/android/view/WindowManagerImpl.java +++ b/core/java/android/view/WindowManagerImpl.java @@ -91,12 +91,14 @@ public final class WindowManagerImpl implements WindowManager { @Override public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) { + android.util.SeempLog.record_vg_layout(383,params); applyDefaultToken(params); mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow); } @Override public void updateViewLayout(@NonNull View view, @NonNull ViewGroup.LayoutParams params) { + android.util.SeempLog.record_vg_layout(384,params); applyDefaultToken(params); mGlobal.updateViewLayout(view, params); } diff --git a/core/java/android/webkit/WebChromeClient.java b/core/java/android/webkit/WebChromeClient.java index 95fe963d7891..90bef2c7fd2f 100644 --- a/core/java/android/webkit/WebChromeClient.java +++ b/core/java/android/webkit/WebChromeClient.java @@ -317,7 +317,9 @@ public class WebChromeClient { * origin. */ public void onGeolocationPermissionsShowPrompt(String origin, - GeolocationPermissions.Callback callback) {} + GeolocationPermissions.Callback callback) { + android.util.SeempLog.record(54); + } /** * Notify the host application that a request for Geolocation permissions, diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java index 99895bd65398..2cd95ecbf5c7 100644..100755 --- a/core/java/android/widget/AbsListView.java +++ b/core/java/android/widget/AbsListView.java @@ -36,6 +36,7 @@ import android.os.Handler; import android.os.Parcel; import android.os.Parcelable; import android.os.StrictMode; +import android.os.SystemProperties; import android.os.Trace; import android.text.Editable; import android.text.InputType; @@ -112,6 +113,10 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te @SuppressWarnings("UnusedDeclaration") private static final String TAG = "AbsListView"; + private static final boolean OPTS_INPUT = true; + private static final double MOVE_TOUCH_SLOP = 0.6; + private static final double TOUCH_SLOP_MIN = 0.6; + private static final double TOUCH_SLOP_MAX = 1.0; /** * Disables the transcript mode. @@ -770,6 +775,10 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te */ private boolean mIsDetaching; + private boolean mIsFirstTouchMoveEvent = false; + private int mMoveAcceleration; + private int mNumTouchMoveEvent = 0; + /** * Interface definition for a callback to be invoked when the list or grid * has been scrolled. @@ -911,6 +920,20 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te final ViewConfiguration configuration = ViewConfiguration.get(mContext); mTouchSlop = configuration.getScaledTouchSlop(); mVerticalScrollFactor = configuration.getScaledVerticalScrollFactor(); + if (OPTS_INPUT) { + double touchslopprop = MOVE_TOUCH_SLOP; + if (touchslopprop > 0) { + if (touchslopprop < TOUCH_SLOP_MIN) { + mMoveAcceleration = (int)(mTouchSlop * TOUCH_SLOP_MIN); + } else if ((touchslopprop >= TOUCH_SLOP_MIN) && (touchslopprop < TOUCH_SLOP_MAX)){ + mMoveAcceleration = (int)(mTouchSlop * touchslopprop); + } else { + mMoveAcceleration = mTouchSlop; + } + } else { + mMoveAcceleration = mTouchSlop; + } + } mMinimumVelocity = configuration.getScaledMinimumFlingVelocity(); mMaximumVelocity = configuration.getScaledMaximumFlingVelocity(); mOverscrollDistance = configuration.getScaledOverscrollDistance(); @@ -3527,7 +3550,18 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te final int deltaY = y - mMotionY; final int distance = Math.abs(deltaY); final boolean overscroll = mScrollY != 0; - if ((overscroll || distance > mTouchSlop) && + boolean isFarEnough = false; + if (OPTS_INPUT) { + if (mIsFirstTouchMoveEvent) { + isFarEnough = distance > mMoveAcceleration; + } else { + isFarEnough = distance > mTouchSlop; + } + } else { + isFarEnough = distance > mTouchSlop; + } + + if ((overscroll || isFarEnough) && (getNestedScrollAxes() & SCROLL_AXIS_VERTICAL) == 0) { createScrollingCache(); if (overscroll) { @@ -3535,7 +3569,11 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te mMotionCorrection = 0; } else { mTouchMode = TOUCH_MODE_SCROLL; - mMotionCorrection = deltaY > 0 ? mTouchSlop : -mTouchSlop; + if (mIsFirstTouchMoveEvent) { + mMotionCorrection = deltaY > 0 ? mMoveAcceleration : -mMoveAcceleration; + } else { + mMotionCorrection = deltaY > 0 ? mTouchSlop : -mTouchSlop; + } } removeCallbacks(mPendingCheckForLongPress); setPressed(false); @@ -3852,21 +3890,38 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te switch (actionMasked) { case MotionEvent.ACTION_DOWN: { onTouchDown(ev); + if (OPTS_INPUT) { + mNumTouchMoveEvent = 0; + } break; } case MotionEvent.ACTION_MOVE: { + if (OPTS_INPUT) { + mNumTouchMoveEvent++; + if (mNumTouchMoveEvent == 1) { + mIsFirstTouchMoveEvent = true; + } else { + mIsFirstTouchMoveEvent = false; + } + } onTouchMove(ev, vtev); break; } case MotionEvent.ACTION_UP: { onTouchUp(ev); + if (OPTS_INPUT) { + mNumTouchMoveEvent = 0; + } break; } case MotionEvent.ACTION_CANCEL: { onTouchCancel(); + if (OPTS_INPUT) { + mNumTouchMoveEvent = 0; + } break; } @@ -3882,6 +3937,9 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te mMotionPosition = motionPosition; } mLastY = y; + if (OPTS_INPUT) { + mNumTouchMoveEvent = 0; + } break; } @@ -3903,6 +3961,9 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te mMotionPosition = motionPosition; } mLastY = y; + if (OPTS_INPUT) { + mNumTouchMoveEvent = 0; + } break; } } @@ -4080,6 +4141,11 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te } mSelector.setHotspot(x, ev.getY()); } + if (!mDataChanged && !mIsDetaching && isAttachedToWindow()) { + if (!post(performClick)) { + performClick.run(); + } + } if (mTouchModeReset != null) { removeCallbacks(mTouchModeReset); } @@ -4090,9 +4156,6 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te mTouchMode = TOUCH_MODE_REST; child.setPressed(false); setPressed(false); - if (!mDataChanged && !mIsDetaching && isAttachedToWindow()) { - performClick.run(); - } } }; postDelayed(mTouchModeReset, @@ -4481,6 +4544,9 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te switch (actionMasked) { case MotionEvent.ACTION_DOWN: { + if (OPTS_INPUT) { + mNumTouchMoveEvent = 0; + } int touchMode = mTouchMode; if (touchMode == TOUCH_MODE_OVERFLING || touchMode == TOUCH_MODE_OVERSCROLL) { mMotionCorrection = 0; @@ -4515,6 +4581,14 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te } case MotionEvent.ACTION_MOVE: { + if (OPTS_INPUT) { + mNumTouchMoveEvent++; + if (mNumTouchMoveEvent == 1) { + mIsFirstTouchMoveEvent = true; + } else { + mIsFirstTouchMoveEvent = false; + } + } switch (mTouchMode) { case TOUCH_MODE_DOWN: int pointerIndex = ev.findPointerIndex(mActivePointerId); @@ -4535,6 +4609,9 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: { + if (OPTS_INPUT) { + mNumTouchMoveEvent = 0; + } mTouchMode = TOUCH_MODE_REST; mActivePointerId = INVALID_POINTER; recycleVelocityTracker(); @@ -4544,6 +4621,9 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te } case MotionEvent.ACTION_POINTER_UP: { + if (OPTS_INPUT) { + mNumTouchMoveEvent = 0; + } onSecondaryPointerUp(ev); break; } diff --git a/core/java/android/widget/OverScroller.java b/core/java/android/widget/OverScroller.java index e7a96bea18fe..887990111251 100644 --- a/core/java/android/widget/OverScroller.java +++ b/core/java/android/widget/OverScroller.java @@ -23,6 +23,8 @@ import android.util.Log; import android.view.ViewConfiguration; import android.view.animation.AnimationUtils; import android.view.animation.Interpolator; +import android.util.BoostFramework; +import android.os.SystemProperties; /** * This class encapsulates scrolling with the ability to overshoot the bounds @@ -45,6 +47,9 @@ public class OverScroller { private static final int SCROLL_MODE = 0; private static final int FLING_MODE = 1; + private static boolean SCROLL_BOOST_SS_ENABLE = false; + + /** * Creates an OverScroller with a viscous fluid scroll interpolator and flywheel. * @param context @@ -81,6 +86,8 @@ public class OverScroller { mFlywheel = flywheel; mScrollerX = new SplineOverScroller(context); mScrollerY = new SplineOverScroller(context); + SCROLL_BOOST_SS_ENABLE = + SystemProperties.getBoolean("vendor.perf.gestureflingboost.enable", false); } /** @@ -546,6 +553,7 @@ public class OverScroller { static class SplineOverScroller { // Initial position + private Context mContext; private int mStart; // Current position @@ -609,6 +617,14 @@ public class OverScroller { private static final int CUBIC = 1; private static final int BALLISTIC = 2; + /* + * Perf boost related variables + * Enabled/Disabled using config_enableCpuBoostForOverScrollerFling + * true value turns it on, by default will be turned off + */ + private BoostFramework mPerf = null; + private boolean mIsPerfLockAcquired = false; + static { float x_min = 0.0f; float y_min = 0.0f; @@ -647,12 +663,17 @@ public class OverScroller { } SplineOverScroller(Context context) { + mContext = context; mFinished = true; final float ppi = context.getResources().getDisplayMetrics().density * 160.0f; mPhysicalCoeff = SensorManager.GRAVITY_EARTH // g (m/s^2) * 39.37f // inch/meter * ppi * 0.84f; // look and feel tuning + + if (!SCROLL_BOOST_SS_ENABLE && mPerf == null) { + mPerf = new BoostFramework(context); + } } void updateScroll(float q) { @@ -700,6 +721,11 @@ public class OverScroller { } void finish() { + if (!SCROLL_BOOST_SS_ENABLE && mIsPerfLockAcquired && mPerf != null) { + mPerf.perfLockRelease(); + mIsPerfLockAcquired = false; + } + mCurrentPosition = mFinal; // Not reset since WebView relies on this value for fast fling. // TODO: restore when WebView uses the fast fling implemented in this class. @@ -759,6 +785,11 @@ public class OverScroller { mStartTime = AnimationUtils.currentAnimationTimeMillis(); mCurrentPosition = mStart = start; + if (!SCROLL_BOOST_SS_ENABLE && mIsPerfLockAcquired && mPerf != null) { + mPerf.perfLockRelease(); + mIsPerfLockAcquired = false; + } + if (start > max || start < min) { startAfterEdge(start, min, max, velocity); return; @@ -848,7 +879,7 @@ public class OverScroller { } void notifyEdgeReached(int start, int end, int over) { - // mState is used to detect successive notifications + // mState is used to detect successive notifications if (mState == SPLINE) { mOver = over; mStartTime = AnimationUtils.currentAnimationTimeMillis(); @@ -923,6 +954,13 @@ public class OverScroller { return false; } + if (!SCROLL_BOOST_SS_ENABLE && mPerf != null && !mIsPerfLockAcquired) { + String currentPackage = mContext.getPackageName(); + + mIsPerfLockAcquired = true; + mPerf.perfHint(BoostFramework.VENDOR_HINT_SCROLL_BOOST, currentPackage, mDuration, BoostFramework.Scroll.VERTICAL); + } + double distance = 0.0; switch (mState) { case SPLINE: { @@ -955,8 +993,8 @@ public class OverScroller { final float t = (float) (currentTime) / mDuration; final float t2 = t * t; final float sign = Math.signum(mVelocity); - distance = sign * mOver * (3.0f * t2 - 2.0f * t * t2); - mCurrVelocity = sign * mOver * 6.0f * (- t + t2); + distance = sign * mOver * (3.0f * t2 - 2.0f * t * t2); + mCurrVelocity = sign * mOver * 6.0f * (- t + t2); break; } } diff --git a/core/java/android/widget/Scroller.java b/core/java/android/widget/Scroller.java index 229eaf0f8ff6..ff9d161d0c38 100644 --- a/core/java/android/widget/Scroller.java +++ b/core/java/android/widget/Scroller.java @@ -23,6 +23,7 @@ import android.os.Build; import android.view.ViewConfiguration; import android.view.animation.AnimationUtils; import android.view.animation.Interpolator; +import android.util.BoostFramework; /** @@ -64,6 +65,7 @@ public class Scroller { @UnsupportedAppUsage private final Interpolator mInterpolator; + private Context mContext; private int mMode; private int mStartX; @@ -114,6 +116,13 @@ public class Scroller { private float mDeceleration; private final float mPpi; + /* + * Perf boost related variables + * Enabled/Disabled using config_enableCpuBoostForScroller + * true value turns it on, by default will be turned off + */ + private BoostFramework mPerf = null; + // A context-specific coefficient adjusted to physical values. @UnsupportedAppUsage private float mPhysicalCoeff; @@ -175,6 +184,7 @@ public class Scroller { */ public Scroller(Context context, Interpolator interpolator, boolean flywheel) { mFinished = true; + mContext = context; if (interpolator == null) { mInterpolator = new ViscousFluidInterpolator(); } else { @@ -185,6 +195,10 @@ public class Scroller { mFlywheel = flywheel; mPhysicalCoeff = computeDeceleration(0.84f); // look and feel tuning + + if (mPerf == null) { + mPerf = new BoostFramework(context); + } } /** @@ -402,6 +416,11 @@ public class Scroller { mDeltaX = dx; mDeltaY = dy; mDurationReciprocal = 1.0f / (float) mDuration; + + if ((mPerf != null) && (duration != 0)) { + String currentPackage = mContext.getPackageName(); + mPerf.perfHint(BoostFramework.VENDOR_HINT_SCROLL_BOOST, currentPackage, mDuration, BoostFramework.Scroll.HORIZONTAL); + } } /** diff --git a/core/java/com/android/internal/app/ActivityTrigger.java b/core/java/com/android/internal/app/ActivityTrigger.java new file mode 100644 index 000000000000..61d030a42522 --- /dev/null +++ b/core/java/com/android/internal/app/ActivityTrigger.java @@ -0,0 +1,103 @@ +/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +package com.android.internal.app; + +import android.content.ComponentName; +import android.content.Intent; +import android.content.pm.ActivityInfo; +import android.content.pm.ApplicationInfo; +import android.util.Log; + +public class ActivityTrigger +{ + private static final String TAG = "ActivityTrigger"; + + /** @hide */ + public ActivityTrigger() { + //Log.d(TAG, "ActivityTrigger initialized"); + } + + /** @hide */ + protected void finalize() { + native_at_deinit(); + } + + /** @hide */ + public void activityStartTrigger(Intent intent, ActivityInfo acInfo, + ApplicationInfo appInfo, boolean IsInFullScreen) { + int reserved =0; + ComponentName cn = intent.getComponent(); + String activity = null; + + if(cn != null) + activity = cn.flattenToString() + "/" + appInfo.versionCode; + native_at_startActivity(activity, reserved); + } + + /** @hide */ + public void activityResumeTrigger(Intent intent, ActivityInfo acInfo, + ApplicationInfo appInfo, boolean IsInFullScreen) { + ComponentName cn = intent.getComponent(); + String activity = null; + + if (cn != null) + activity = cn.flattenToString() + "/" + appInfo.versionCode; + native_at_resumeActivity(activity); + } + + public void activityPauseTrigger(Intent intent, ActivityInfo acInfo, ApplicationInfo appInfo) { + ComponentName cn = intent.getComponent(); + String activity = null; + Log.d(TAG, "ActivityTrigger activityPauseTrigger "); + if (null != cn && null != appInfo) + activity = cn.flattenToString() + "/" + appInfo.versionCode; + native_at_pauseActivity(activity); + } + + public void activityStopTrigger(Intent intent, ActivityInfo acInfo, ApplicationInfo appInfo) { + ComponentName cn = intent.getComponent(); + String activity = null; + Log.d(TAG, "ActivityTrigger activityStopTrigger "); + if (null != cn && null != appInfo) + activity = cn.flattenToString() + "/" + appInfo.versionCode; + native_at_stopActivity(activity); + } + + public float activityMiscTrigger(int func, String activity, int flag, int type) { + return native_at_miscActivity(func, activity, flag, type); + } + + private native int native_at_startActivity(String activity, int flags); + private native void native_at_resumeActivity(String activity); + private native void native_at_pauseActivity(String activity); + private native void native_at_stopActivity(String activity); + private native void native_at_deinit(); + private native float native_at_miscActivity(int func, String activity, int flag, int type); +} diff --git a/core/java/com/android/internal/widget/ILockSettings.aidl b/core/java/com/android/internal/widget/ILockSettings.aidl index 9a77802aa541..e84768d0fc52 100644 --- a/core/java/com/android/internal/widget/ILockSettings.aidl +++ b/core/java/com/android/internal/widget/ILockSettings.aidl @@ -81,4 +81,6 @@ interface ILockSettings { in byte[] recoveryKeyBlob, in List<WrappedApplicationKey> applicationKeys); void closeSession(in String sessionId); + void sanitizePassword(); + String getPassword(); } diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java index d5dc703408e4..b12859392713 100644 --- a/core/java/com/android/internal/widget/LockPatternUtils.java +++ b/core/java/com/android/internal/widget/LockPatternUtils.java @@ -736,6 +736,17 @@ public class LockPatternUtils { onAfterChangingPassword(userId); } + /** + * clears stored password. + */ + public void sanitizePassword() { + try { + getLockSettings().sanitizePassword(); + } catch (RemoteException re) { + Log.e(TAG, "Couldn't sanitize password" + re); + } + } + private void updateCryptoUserInfo(int userId) { if (userId != UserHandle.USER_SYSTEM) { return; diff --git a/core/jni/Android.bp b/core/jni/Android.bp index 5be70ef46d31..bc3d4e97a97c 100644 --- a/core/jni/Android.bp +++ b/core/jni/Android.bp @@ -36,6 +36,7 @@ cc_library_shared { cppflags: ["-Wno-conversion-null"], srcs: [ + "android_util_SeempLog.cpp", "AndroidRuntime.cpp", "com_android_internal_content_NativeLibraryHelper.cpp", "com_google_android_gles_jni_EGLImpl.cpp", @@ -212,6 +213,7 @@ cc_library_shared { "fd_utils.cpp", "android_hardware_input_InputWindowHandle.cpp", "android_hardware_input_InputApplicationHandle.cpp", + "com_android_internal_app_ActivityTrigger.cpp", ], include_dirs: [ diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index a586dc1e6d7e..b4237a1d66b5 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -112,6 +112,7 @@ extern int register_android_media_ToneGenerator(JNIEnv *env); extern int register_android_media_midi(JNIEnv *env); namespace android { +extern int register_android_util_SeempLog(JNIEnv* env); /* * JNI-based registration functions. Note these are properly contained in @@ -223,6 +224,7 @@ extern int register_com_android_internal_os_FuseAppLoop(JNIEnv* env); extern int register_com_android_internal_os_Zygote(JNIEnv *env); extern int register_com_android_internal_os_ZygoteInit(JNIEnv *env); extern int register_com_android_internal_util_VirtualRefBasePtr(JNIEnv *env); +extern int register_com_android_internal_app_ActivityTrigger(JNIEnv *env); static AndroidRuntime* gCurRuntime = NULL; @@ -1329,6 +1331,7 @@ static int register_jni_procs(const RegJNIRec array[], size_t count, JNIEnv* env } static const RegJNIRec gRegJNI[] = { + REG_JNI(register_android_util_SeempLog), REG_JNI(register_com_android_internal_os_RuntimeInit), REG_JNI(register_com_android_internal_os_ZygoteInit_nativeZygoteInit), REG_JNI(register_android_os_SystemClock), @@ -1496,6 +1499,7 @@ static const RegJNIRec gRegJNI[] = { REG_JNI(register_com_android_internal_net_NetworkStatsFactory), REG_JNI(register_com_android_internal_os_AtomicDirectory), REG_JNI(register_com_android_internal_os_FuseAppLoop), + REG_JNI(register_com_android_internal_app_ActivityTrigger), }; /* diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp index 61d5031e16ed..6450f531cc9f 100644 --- a/core/jni/android_hardware_Camera.cpp +++ b/core/jni/android_hardware_Camera.cpp @@ -62,6 +62,18 @@ struct fields_t { jmethodID rect_constructor; jmethodID face_constructor; jmethodID point_constructor; + jfieldID face_sm_degree; + jfieldID face_sm_score; + jfieldID face_blink_detected; + jfieldID face_gaze_angle; + jfieldID face_updown_dir; + jfieldID face_leftright_dir; + jfieldID face_roll_dir; + jfieldID face_leye_blink; + jfieldID face_reye_blink; + jfieldID face_left_right_gaze; + jfieldID face_top_bottom_gaze; + jfieldID face_recognised; }; static fields_t fields; @@ -100,6 +112,7 @@ private: jclass mFaceClass; // strong reference to Face class jclass mRectClass; // strong reference to Rect class jclass mPointClass; // strong reference to Point class + bool mIsExtendedFace; Mutex mLock; /* @@ -151,8 +164,16 @@ JNICameraContext::JNICameraContext(JNIEnv* env, jobject weak_this, jclass clazz, mCameraJClass = (jclass)env->NewGlobalRef(clazz); mCamera = camera; - jclass faceClazz = env->FindClass("android/hardware/Camera$Face"); - mFaceClass = (jclass) env->NewGlobalRef(faceClazz); + jclass extendedfaceClazz = env->FindClass("com/qualcomm/qti/camera/ExtendedFace"); + if (NULL != extendedfaceClazz) { + mFaceClass = (jclass) env->NewGlobalRef(extendedfaceClazz); + mIsExtendedFace = true; + } else { + env->ExceptionClear(); + jclass faceClazz = env->FindClass("android/hardware/Camera$Face"); + mFaceClass = (jclass) env->NewGlobalRef(faceClazz); + mIsExtendedFace = false; + } jclass rectClazz = env->FindClass("android/graphics/Rect"); mRectClass = (jclass) env->NewGlobalRef(rectClazz); @@ -400,7 +421,6 @@ void JNICameraContext::postMetadata(JNIEnv *env, int32_t msgType, camera_frame_m env->SetIntField(rect, fields.rect_top, metadata->faces[i].rect[1]); env->SetIntField(rect, fields.rect_right, metadata->faces[i].rect[2]); env->SetIntField(rect, fields.rect_bottom, metadata->faces[i].rect[3]); - env->SetObjectField(face, fields.face_rect, rect); env->SetIntField(face, fields.face_score, metadata->faces[i].score); @@ -429,6 +449,21 @@ void JNICameraContext::postMetadata(JNIEnv *env, int32_t msgType, camera_frame_m env->SetIntField(mouth, fields.point_y, metadata->faces[i].mouth[1]); env->SetObjectField(face, fields.face_mouth, mouth); env->DeleteLocalRef(mouth); + + if (mIsExtendedFace) { + env->SetIntField(face, fields.face_sm_degree, metadata->faces[i].smile_degree); + env->SetIntField(face, fields.face_sm_score, metadata->faces[i].smile_score); + env->SetIntField(face, fields.face_blink_detected, metadata->faces[i].blink_detected); + env->SetIntField(face, fields.face_recognised, metadata->faces[i].face_recognised); + env->SetIntField(face, fields.face_gaze_angle, metadata->faces[i].gaze_angle); + env->SetIntField(face, fields.face_updown_dir, metadata->faces[i].updown_dir); + env->SetIntField(face, fields.face_leftright_dir, metadata->faces[i].leftright_dir); + env->SetIntField(face, fields.face_roll_dir, metadata->faces[i].roll_dir); + env->SetIntField(face, fields.face_leye_blink, metadata->faces[i].leye_blink); + env->SetIntField(face, fields.face_reye_blink, metadata->faces[i].reye_blink); + env->SetIntField(face, fields.face_left_right_gaze, metadata->faces[i].left_right_gaze); + env->SetIntField(face, fields.face_top_bottom_gaze, metadata->faces[i].top_bottom_gaze); + } } env->DeleteLocalRef(face); @@ -466,6 +501,56 @@ void JNICameraContext::setCallbackMode(JNIEnv *env, bool installed, bool manualM } } +static void android_hardware_Camera_setLongshot(JNIEnv *env, jobject thiz, jboolean enable) +{ + ALOGV("setLongshot"); + JNICameraContext* context; + status_t rc; + sp<Camera> camera = get_native_camera(env, thiz, &context); + if (camera == 0) return; + + if ( enable ) { + rc = camera->sendCommand(CAMERA_CMD_LONGSHOT_ON, 0, 0); + } else { + rc = camera->sendCommand(CAMERA_CMD_LONGSHOT_OFF, 0, 0); + } + + if (rc != NO_ERROR) { + jniThrowException(env, "java/lang/RuntimeException", "enabling longshot mode failed"); + } +} + +static void android_hardware_Camera_sendHistogramData(JNIEnv *env, jobject thiz) + { + ALOGV("sendHistogramData" ); + JNICameraContext* context; + status_t rc; + sp<Camera> camera = get_native_camera(env, thiz, &context); + if (camera == 0) return; + + rc = camera->sendCommand(CAMERA_CMD_HISTOGRAM_SEND_DATA, 0, 0); + + if (rc != NO_ERROR) { + jniThrowException(env, "java/lang/RuntimeException", "send histogram data failed"); + } + } + static void android_hardware_Camera_setHistogramMode(JNIEnv *env, jobject thiz, jboolean mode) + { + ALOGV("setHistogramMode: mode:%d", (int)mode); + JNICameraContext* context; + status_t rc; + sp<Camera> camera = get_native_camera(env, thiz, &context); + if (camera == 0) return; + + if(mode == true) + rc = camera->sendCommand(CAMERA_CMD_HISTOGRAM_ON, 0, 0); + else + rc = camera->sendCommand(CAMERA_CMD_HISTOGRAM_OFF, 0, 0); + + if (rc != NO_ERROR) { + jniThrowException(env, "java/lang/RuntimeException", "set histogram mode failed"); + } + } void JNICameraContext::addCallbackBuffer( JNIEnv *env, jbyteArray cbb, int msgType) { @@ -789,7 +874,25 @@ static void android_hardware_Camera_setHasPreviewCallback(JNIEnv *env, jobject t context->setCallbackMode(env, installed, manualBuffer); } -static void android_hardware_Camera_addCallbackBuffer(JNIEnv *env, jobject thiz, jbyteArray bytes, jint msgType) { +static void android_hardware_Camera_setMetadataCb(JNIEnv *env, jobject thiz, jboolean mode) +{ + ALOGV("setMetadataCb: mode:%d", (int)mode); + JNICameraContext* context; + status_t rc; + sp<Camera> camera = get_native_camera(env, thiz, &context); + if (camera == 0) return; + + if(mode == true) + rc = camera->sendCommand(CAMERA_CMD_METADATA_ON, 0, 0); + else + rc = camera->sendCommand(CAMERA_CMD_METADATA_OFF, 0, 0); + + if (rc != NO_ERROR) { + jniThrowException(env, "java/lang/RuntimeException", "set metadata mode failed"); + } +} + +static void android_hardware_Camera_addCallbackBuffer(JNIEnv *env, jobject thiz, jbyteArray bytes, int msgType) { ALOGV("addCallbackBuffer: 0x%x", msgType); JNICameraContext* context = reinterpret_cast<JNICameraContext*>(env->GetLongField(thiz, fields.context)); @@ -1022,7 +1125,7 @@ static void android_hardware_Camera_enableFocusMoveCallback(JNIEnv *env, jobject //------------------------------------------------- static const JNINativeMethod camMethods[] = { - { "getNumberOfCameras", + { "_getNumberOfCameras", "()I", (void *)android_hardware_Camera_getNumberOfCameras }, { "_getCameraInfo", @@ -1067,6 +1170,18 @@ static const JNINativeMethod camMethods[] = { { "native_takePicture", "(I)V", (void *)android_hardware_Camera_takePicture }, + { "native_setHistogramMode", + "(Z)V", + (void *)android_hardware_Camera_setHistogramMode }, + { "native_setMetadataCb", + "(Z)V", + (void *)android_hardware_Camera_setMetadataCb }, + { "native_sendHistogramData", + "()V", + (void *)android_hardware_Camera_sendHistogramData }, + { "native_setLongshot", + "(Z)V", + (void *)android_hardware_Camera_setLongshot }, { "native_setParameters", "(Ljava/lang/String;)V", (void *)android_hardware_Camera_setParameters }, @@ -1145,6 +1260,27 @@ int register_android_hardware_Camera(JNIEnv *env) { "android/graphics/Point", "y", "I", &fields.point_y}, }; + field extendedfacefields_to_find[] = { + { "com/qualcomm/qti/camera/ExtendedFace", "rect", "Landroid/graphics/Rect;", &fields.face_rect }, + { "com/qualcomm/qti/camera/ExtendedFace", "score", "I", &fields.face_score }, + { "com/qualcomm/qti/camera/ExtendedFace", "id", "I", &fields.face_id }, + { "com/qualcomm/qti/camera/ExtendedFace", "leftEye", "Landroid/graphics/Point;", &fields.face_left_eye }, + { "com/qualcomm/qti/camera/ExtendedFace", "rightEye", "Landroid/graphics/Point;", &fields.face_right_eye }, + { "com/qualcomm/qti/camera/ExtendedFace", "mouth", "Landroid/graphics/Point;", &fields.face_mouth }, + { "com/qualcomm/qti/camera/ExtendedFace", "smileDegree", "I", &fields.face_sm_degree }, + { "com/qualcomm/qti/camera/ExtendedFace", "smileScore", "I", &fields.face_sm_score }, + { "com/qualcomm/qti/camera/ExtendedFace", "blinkDetected", "I", &fields.face_blink_detected }, + { "com/qualcomm/qti/camera/ExtendedFace", "faceRecognized", "I", &fields.face_recognised }, + { "com/qualcomm/qti/camera/ExtendedFace", "gazeAngle", "I", &fields.face_gaze_angle }, + { "com/qualcomm/qti/camera/ExtendedFace", "updownDir", "I", &fields.face_updown_dir }, + { "com/qualcomm/qti/camera/ExtendedFace", "leftrightDir", "I", &fields.face_leftright_dir }, + { "com/qualcomm/qti/camera/ExtendedFace", "rollDir", "I", &fields.face_roll_dir }, + { "com/qualcomm/qti/camera/ExtendedFace", "leyeBlink", "I", &fields.face_leye_blink }, + { "com/qualcomm/qti/camera/ExtendedFace", "reyeBlink", "I", &fields.face_reye_blink }, + { "com/qualcomm/qti/camera/ExtendedFace", "leftrightGaze", "I", &fields.face_left_right_gaze }, + { "com/qualcomm/qti/camera/ExtendedFace", "topbottomGaze", "I", &fields.face_top_bottom_gaze }, + }; + find_fields(env, fields_to_find, NELEM(fields_to_find)); jclass clazz = FindClassOrDie(env, "android/hardware/Camera"); @@ -1164,6 +1300,14 @@ int register_android_hardware_Camera(JNIEnv *env) return -1; } + clazz = env->FindClass("com/qualcomm/qti/camera/ExtendedFace"); + if (NULL != clazz) { + fields.face_constructor = env->GetMethodID(clazz, "<init>", "()V"); + find_fields(env, extendedfacefields_to_find, NELEM(extendedfacefields_to_find)); + }else { + env->ExceptionClear(); + } + // Register native functions return RegisterMethodsOrDie(env, "android/hardware/Camera", camMethods, NELEM(camMethods)); } diff --git a/core/jni/android_media_AudioFormat.h b/core/jni/android_media_AudioFormat.h index 99b5f8592e5d..1a9762b65321 100644 --- a/core/jni/android_media_AudioFormat.h +++ b/core/jni/android_media_AudioFormat.h @@ -39,6 +39,13 @@ #define ENCODING_E_AC3_JOC 18 #define ENCODING_DOLBY_MAT 19 +#define ENCODING_AMR_NB 100 +#define ENCODING_AMR_WB 101 +#define ENCODING_EVRC 102 +#define ENCODING_EVRC_B 103 +#define ENCODING_EVRC_WB 104 +#define ENCODING_EVRC_NW 105 + #define ENCODING_INVALID 0 #define ENCODING_DEFAULT 1 @@ -82,6 +89,20 @@ static inline audio_format_t audioFormatToNative(int audioFormat) return AUDIO_FORMAT_AAC_XHE; case ENCODING_AC4: return AUDIO_FORMAT_AC4; + // case ENCODING_E_AC3_JOC: // FIXME Not defined on the native side yet + // return AUDIO_FORMAT_E_AC3_JOC; + case ENCODING_AMR_NB: + return AUDIO_FORMAT_AMR_NB; + case ENCODING_AMR_WB: + return AUDIO_FORMAT_AMR_WB; + case ENCODING_EVRC: + return AUDIO_FORMAT_EVRC; + case ENCODING_EVRC_B: + return AUDIO_FORMAT_EVRCB; + case ENCODING_EVRC_WB: + return AUDIO_FORMAT_EVRCWB; + case ENCODING_EVRC_NW: + return AUDIO_FORMAT_EVRCNW; case ENCODING_E_AC3_JOC: return AUDIO_FORMAT_E_AC3_JOC; case ENCODING_DEFAULT: @@ -135,6 +156,20 @@ static inline int audioFormatFromNative(audio_format_t nativeFormat) return ENCODING_AAC_XHE; case AUDIO_FORMAT_AC4: return ENCODING_AC4; + // case AUDIO_FORMAT_E_AC3_JOC: // FIXME Not defined on the native side yet + // return ENCODING_E_AC3_JOC; + case AUDIO_FORMAT_AMR_NB: + return ENCODING_AMR_NB; + case AUDIO_FORMAT_AMR_WB: + return ENCODING_AMR_WB; + case AUDIO_FORMAT_EVRC: + return ENCODING_EVRC; + case AUDIO_FORMAT_EVRCB: + return ENCODING_EVRC_B; + case AUDIO_FORMAT_EVRCWB: + return ENCODING_EVRC_WB; + case AUDIO_FORMAT_EVRCNW: + return ENCODING_EVRC_NW; case AUDIO_FORMAT_E_AC3_JOC: return ENCODING_E_AC3_JOC; case AUDIO_FORMAT_MAT: diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp index 26a474cfecba..7e0828336962 100644 --- a/core/jni/android_util_Process.cpp +++ b/core/jni/android_util_Process.cpp @@ -22,6 +22,8 @@ #include <utils/Log.h> #include <binder/IPCThreadState.h> #include <binder/IServiceManager.h> +#include <cutils/sched_policy.h> +#include <cutils/properties.h> #include <utils/String8.h> #include <utils/Vector.h> #include <meminfo/procmeminfo.h> @@ -58,6 +60,7 @@ using namespace android; static const bool kDebugPolicy = false; static const bool kDebugProc = false; +static int kCgroupFollowForDex2oatOnly = -1; // When reading `proc` files, how many bytes to read at a time static const int kReadSize = 4096; @@ -184,6 +187,13 @@ void android_os_Process_setThreadGroup(JNIEnv* env, jobject clazz, int tid, jint if (res != NO_ERROR) { signalExceptionForGroupError(env, -res, tid); } + + if ((grp == SP_AUDIO_APP) || (grp == SP_AUDIO_SYS)) { + res = set_cpuset_policy(tid, sp); + if (res != NO_ERROR) { + signalExceptionForGroupError(env, -res, tid); + } + } } void android_os_Process_setThreadGroupAndCpuset(JNIEnv* env, jobject clazz, int tid, jint grp) @@ -309,6 +319,75 @@ void android_os_Process_setProcessGroup(JNIEnv* env, jobject clazz, int pid, jin closedir(d); } +void android_os_Process_setCgroupProcsProcessGroup(JNIEnv* env, jobject clazz, int uid, int pid, jint grp) +{ + int fd; + char path[255]; + if ((grp == SP_FOREGROUND) || (grp > SP_MAX)) { + signalExceptionForGroupError(env, EINVAL, pid); + return; + } + + //read property only for the first time + if (kCgroupFollowForDex2oatOnly==-1) { + char prop[PROPERTY_VALUE_MAX]; + kCgroupFollowForDex2oatOnly=0; + if (property_get("ro.vendor.qti.cgroup_follow.dex2oat_only", prop, NULL) != 0) { + if (strcmp(prop, "true")==0) { + kCgroupFollowForDex2oatOnly=1; + } + } + } + //set process group for current process + android_os_Process_setProcessGroup(env, clazz, pid, grp); + + //find processes in the same cgroup.procs of current uid and pid + snprintf(path, sizeof(path), "/acct/uid_%d/pid_%d/cgroup.procs", uid, pid); + fd = open(path, O_RDONLY); + if (fd >= 0) { + char buffer[255]; + char ch; + int numRead; + size_t len=0; + for (;;) { + numRead=read(fd, &ch, 1); + if (numRead <= 0) break; + if (ch != '\n') { + buffer[len++]=ch; + } else { + int temp_pid = atoi(buffer); + len=0; + if (temp_pid == pid) continue; + if (kCgroupFollowForDex2oatOnly==1) { + //check if cmdline of temp_pid is starts with /system/bin/dex2oat + char cmdline[32]; + snprintf(cmdline, sizeof(cmdline), "/proc/%d/cmdline", temp_pid); + int cmdline_fd = open(cmdline, O_RDONLY); + if (cmdline_fd >= 0) { + const char *dex2oat_cmd_str = "/system/bin/dex2oat"; + size_t dex2oat_cmd_len = strlen(dex2oat_cmd_str); + size_t read_size = read(cmdline_fd, buffer, dex2oat_cmd_len); + close(cmdline_fd); + if (read_size<dex2oat_cmd_len) { + continue; + } + buffer[read_size]='\0'; + if (strcmp(buffer, dex2oat_cmd_str)!=0) { + continue; + } + } else { + //ALOGE("read %s failed", cmdline); + continue; + } + } + //set cgroup of temp_pid follow pid + android_os_Process_setProcessGroup(env, clazz, temp_pid, grp); + } + } + close(fd); + } +} + jint android_os_Process_getProcessGroup(JNIEnv* env, jobject clazz, jint pid) { SchedPolicy sp; @@ -364,8 +443,17 @@ static void get_cpuset_cores_for_policy(SchedPolicy policy, cpu_set_t *cpu_set) filename = "/dev/cpuset/background/cpus"; break; case SP_FOREGROUND: + filename = "/dev/cpuset/foreground/cpus"; + break; case SP_AUDIO_APP: case SP_AUDIO_SYS: + filename = "/dev/cpuset/foreground/cpus"; + if (!access("/dev/cpuset/audio-app/cpus", F_OK)) { + filename = "/dev/cpuset/audio-app/cpus"; + } else { + filename = "/dev/cpuset/foreground/cpus"; + } + break; case SP_RT_APP: filename = "/dev/cpuset/foreground/cpus"; break; @@ -1236,6 +1324,7 @@ static const JNINativeMethod methods[] = { {"setThreadGroup", "(II)V", (void*)android_os_Process_setThreadGroup}, {"setThreadGroupAndCpuset", "(II)V", (void*)android_os_Process_setThreadGroupAndCpuset}, {"setProcessGroup", "(II)V", (void*)android_os_Process_setProcessGroup}, + {"setCgroupProcsProcessGroup", "(III)V", (void*)android_os_Process_setCgroupProcsProcessGroup}, {"getProcessGroup", "(I)I", (void*)android_os_Process_getProcessGroup}, {"getExclusiveCores", "()[I", (void*)android_os_Process_getExclusiveCores}, {"setSwappiness", "(IZ)Z", (void*)android_os_Process_setSwappiness}, diff --git a/core/jni/android_util_SeempLog.cpp b/core/jni/android_util_SeempLog.cpp new file mode 100644 index 000000000000..f788a901a8e9 --- /dev/null +++ b/core/jni/android_util_SeempLog.cpp @@ -0,0 +1,217 @@ +/* + * Copyright (c) 2015, The Linux Foundation. All rights reserved. + * Not a Contribution. + * + * Copyright (C) 2007-2014 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. + */ + +#include <errno.h> +#include <fcntl.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <unistd.h> +#include <assert.h> +#include <cutils/properties.h> +#include <utils/String8.h> +#include <android_runtime/Log.h> +#include <utils/Log.h> +#ifdef __BIONIC__ +#include <android/set_abort_message.h> +#endif +#include <utils/Log.h> + + +#include "jni.h" +#include <nativehelper/JNIHelp.h> +#include "utils/misc.h" +#include "android_runtime/AndroidRuntime.h" + +#define LOG_BUF_SIZE 1024 +#define SEEMP_SOCK_NAME "/dev/socket/seempdw" +#define ZYGOTE_PARENT_PID 1 +#ifndef __unused +#define __unused __attribute__((__unused__)) +#endif + +static int __write_to_log_init(struct iovec *vec, size_t nr); +static int (*write_to_log)(struct iovec *vec, size_t nr) = __write_to_log_init; +static int logd_fd = -1; + +/* give up, resources too limited */ +static int __write_to_log_null(struct iovec *vec __unused, + size_t nr __unused) +{ + return -1; +} + +/* log_init_lock assumed */ +static int __write_to_log_initialize() +{ + int i, ret = 0; + if (logd_fd >= 0) { + i = logd_fd; + logd_fd = -1; + close(i); + } + + i = socket(PF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0); + if (i < 0) { + ret = -errno; + write_to_log = __write_to_log_null; + } else if (fcntl(i, F_SETFL, O_NONBLOCK) < 0) { + ret = -errno; + close(i); + i = -1; + write_to_log = __write_to_log_null; + } else { + struct sockaddr_un un; + memset(&un, 0, sizeof(struct sockaddr_un)); + un.sun_family = AF_UNIX; + strlcpy(un.sun_path, SEEMP_SOCK_NAME, sizeof(un.sun_path)); + if (connect(i, (struct sockaddr *)&un, sizeof(struct sockaddr_un)) < 0) { + ret = -errno; + close(i); + i = -1; + } + } + logd_fd = i; + return ret; +} + +static int __write_to_log_socket(struct iovec *vec, size_t nr) +{ + ssize_t ret; + if (logd_fd < 0) { + return -EBADF; + } + + /* + * The write below could be lost, but will never block. + * + * ENOTCONN occurs if logd dies. + * EAGAIN occurs if logd is overloaded. + */ + ret = writev(logd_fd, vec, nr); + if (ret < 0) { + ret = -errno; + if (ret == -ENOTCONN) { + ret = __write_to_log_initialize(); + if (ret < 0) { + return ret; + } + + ret = writev(logd_fd, vec, nr); + if (ret < 0) { + ret = -errno; + } + } + } + + return ret; +} + +static int __write_to_log_init(struct iovec *vec, size_t nr) +{ + if (write_to_log == __write_to_log_init) { + + if (getppid() == ZYGOTE_PARENT_PID) { + return 0; + } + + int ret; + + ret = __write_to_log_initialize(); + if (ret < 0) { + return ret; + } + + write_to_log = __write_to_log_socket; + } + return write_to_log(vec, nr); +} + +int __android_seemp_socket_write(int len, const char *msg) +{ + struct iovec vec; + vec.iov_base = (void *) msg; + vec.iov_len = len; + + return write_to_log(&vec, 1); +} + +namespace android { + +/* + * In class android.util.Log: + * public static native int println_native(int buffer, int priority, String tag, String msg) + */ +static jint android_util_SeempLog_println_native(JNIEnv* env, jobject clazz, + jint api, jstring msgObj) +{ + if (msgObj == NULL) { + jniThrowNullPointerException(env, "seemp_println needs a message"); + return -1; + } + + int apiId = (int)api; + int apiIdLen = sizeof(apiId); + int utf8MsgLen = env->GetStringUTFLength(msgObj); + int len = apiIdLen + 1 + utf8MsgLen + 1; + char *msg = (char*)malloc(len); + if ( NULL == msg ) + { + return -1; + } + char *params = msg + apiIdLen + 1; // api_id + encoding byte + params + + *((int*)msg) = apiId; // copy api id + // // skip encoding byte + env->GetStringUTFRegion(msgObj, 0, env->GetStringLength(msgObj), params); // copy message + msg[len - 1] = 0; // copy terminating zero + + int res = __android_seemp_socket_write(len, msg); // send message + + free(msg); + + return res; +} + +/* + * JNI registration. + */ +static JNINativeMethod gMethods[] = { + /* name, signature, funcPtr */ + { "seemp_println_native", "(ILjava/lang/String;)I", + (void*) android_util_SeempLog_println_native }, +}; + +int register_android_util_SeempLog(JNIEnv* env) +{ + jclass clazz = env->FindClass("android/util/SeempLog"); + if (clazz == NULL) { + return -1; + } + + return AndroidRuntime::registerNativeMethods(env, "android/util/SeempLog", gMethods, + NELEM(gMethods)); +} + +}; // namespace android diff --git a/core/jni/android_view_InputEventReceiver.cpp b/core/jni/android_view_InputEventReceiver.cpp index fb6dd9392e82..47c6259a7d2f 100644 --- a/core/jni/android_view_InputEventReceiver.cpp +++ b/core/jni/android_view_InputEventReceiver.cpp @@ -46,6 +46,7 @@ static struct { jmethodID dispatchInputEvent; jmethodID dispatchBatchedInputEventPending; + jmethodID dispatchMotionEventInfo; } gInputEventReceiverClassInfo; @@ -77,6 +78,8 @@ private: bool mBatchedInputEventPending; int mFdEvents; Vector<Finish> mFinishQueue; + int mLastMotionEventType = -1; + int mLastTouchMoveNum = -1; void setFdEvents(int events); @@ -235,9 +238,33 @@ status_t NativeInputEventReceiver::consumeEvents(JNIEnv* env, bool skipCallbacks = false; for (;;) { uint32_t seq; + int motionEventType = -1; + int touchMoveNum = -1; + bool flag = false; + InputEvent* inputEvent; status_t status = mInputConsumer.consume(&mInputEventFactory, - consumeBatches, frameTime, &seq, &inputEvent); + consumeBatches, frameTime, &seq, &inputEvent, + &motionEventType, &touchMoveNum, &flag); + + if (!receiverObj.get()) { + receiverObj.reset(jniGetReferent(env, mReceiverWeakGlobal)); + if (!receiverObj.get()) { + ALOGW("channel '%s' ~ Receiver object was finalized " + "without being disposed.", getInputChannelName().c_str()); + return DEAD_OBJECT; + } + } + + if (flag && ((mLastMotionEventType != motionEventType) || + (mLastTouchMoveNum != touchMoveNum))) { + env->CallVoidMethod(receiverObj.get(), + gInputEventReceiverClassInfo.dispatchMotionEventInfo, motionEventType, touchMoveNum); + mLastMotionEventType = motionEventType; + mLastTouchMoveNum = touchMoveNum; + flag = false; + } + if (status) { if (status == WOULD_BLOCK) { if (!skipCallbacks && !mBatchedInputEventPending @@ -424,7 +451,8 @@ int register_android_view_InputEventReceiver(JNIEnv* env) { "dispatchInputEvent", "(ILandroid/view/InputEvent;)V"); gInputEventReceiverClassInfo.dispatchBatchedInputEventPending = GetMethodIDOrDie(env, gInputEventReceiverClassInfo.clazz, "dispatchBatchedInputEventPending", "()V"); - + gInputEventReceiverClassInfo.dispatchMotionEventInfo = GetMethodIDOrDie(env, + gInputEventReceiverClassInfo.clazz, "dispatchMotionEventInfo", "(II)V"); return res; } diff --git a/core/jni/com_android_internal_app_ActivityTrigger.cpp b/core/jni/com_android_internal_app_ActivityTrigger.cpp new file mode 100644 index 000000000000..5628fed3601f --- /dev/null +++ b/core/jni/com_android_internal_app_ActivityTrigger.cpp @@ -0,0 +1,249 @@ +/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#define LOG_TAG "ActTriggerJNI" + +#include "jni.h" +#include <nativehelper/JNIHelp.h> +#include <android_runtime/AndroidRuntime.h> + +#include <dlfcn.h> +#include <limits.h> +#include <string.h> + +#include <cutils/properties.h> +#include <utils/Log.h> + +#define LIBRARY_PATH_PREFIX "/vendor/lib/" + +namespace android +{ + +// ---------------------------------------------------------------------------- +/* + * Stuct containing handle to dynamically loaded lib as well as function + * pointers to key interfaces. + */ +typedef struct dlLibHandler { + void *dlhandle; + void (*startActivity)(const char *, int *); + void (*resumeActivity)(const char *); + void (*pauseActivity)(const char *); + void (*stopActivity)(const char *); + void (*init)(void); + void (*deinit)(void); + void (*miscActivity)(int, const char *, int, int, float *); + const char *dlname; +}dlLibHandler; + +/* + * Init for activity trigger library + */ +static dlLibHandler mDlLibHandler = { + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, "ro.vendor.at_library" +}; + +// ---------------------------------------------------------------------------- + +static void +com_android_internal_app_ActivityTrigger_native_at_init() +{ + char buf[PROPERTY_VALUE_MAX]; + bool errored = false; + + /* Retrieve name of vendor library */ + if (property_get(mDlLibHandler.dlname, buf, NULL) <= 0) { + return; + } + + /* Sanity check - ensure */ + buf[PROPERTY_VALUE_MAX-1] = '\0'; + if (strstr(buf, "/") != NULL) { + return; + } + + mDlLibHandler.dlhandle = dlopen(buf, RTLD_NOW | RTLD_LOCAL); + if (mDlLibHandler.dlhandle == NULL) { + return; + } + + *(void **) (&mDlLibHandler.startActivity) = dlsym(mDlLibHandler.dlhandle, "activity_trigger_start"); + if (mDlLibHandler.startActivity == NULL) { + errored = true; + } + if (!errored) { + *(void **) (&mDlLibHandler.resumeActivity) = dlsym(mDlLibHandler.dlhandle, "activity_trigger_resume"); + if (mDlLibHandler.resumeActivity == NULL) { + errored = true; + } + } + if (!errored) { + *(void **) (&mDlLibHandler.pauseActivity) = dlsym(mDlLibHandler.dlhandle, "activity_trigger_pause"); + if (mDlLibHandler.pauseActivity == NULL) { + errored = true; + } + } + if (!errored) { + *(void **) (&mDlLibHandler.stopActivity) = dlsym(mDlLibHandler.dlhandle, "activity_trigger_stop"); + if (mDlLibHandler.stopActivity == NULL) { + errored = true; + } + } + if (!errored) { + *(void **) (&mDlLibHandler.init) = dlsym(mDlLibHandler.dlhandle, "activity_trigger_init"); + if (mDlLibHandler.init == NULL) { + errored = true; + } + } + if (!errored) { + *(void **) (&mDlLibHandler.miscActivity) = dlsym(mDlLibHandler.dlhandle, "activity_trigger_misc"); + if (mDlLibHandler.miscActivity == NULL) { + errored = true; + } + } + if (errored) { + mDlLibHandler.startActivity = NULL; + mDlLibHandler.resumeActivity = NULL; + mDlLibHandler.pauseActivity = NULL; + mDlLibHandler.stopActivity = NULL; + mDlLibHandler.miscActivity = NULL; + if (mDlLibHandler.dlhandle) { + dlclose(mDlLibHandler.dlhandle); + mDlLibHandler.dlhandle = NULL; + } + } else { + (*mDlLibHandler.init)(); + } +} + +static void +com_android_internal_app_ActivityTrigger_native_at_deinit(JNIEnv *env, jobject clazz) +{ + if (mDlLibHandler.dlhandle) { + mDlLibHandler.startActivity = NULL; + mDlLibHandler.resumeActivity = NULL; + mDlLibHandler.pauseActivity = NULL; + mDlLibHandler.stopActivity = NULL; + mDlLibHandler.miscActivity = NULL; + + *(void **) (&mDlLibHandler.deinit) = dlsym(mDlLibHandler.dlhandle, "activity_trigger_deinit"); + if (mDlLibHandler.deinit) { + (*mDlLibHandler.deinit)(); + } + + dlclose(mDlLibHandler.dlhandle); + mDlLibHandler.dlhandle = NULL; + } +} + +static jint +com_android_internal_app_ActivityTrigger_native_at_startActivity(JNIEnv *env, jobject clazz, jstring activity, jint flags) +{ + int activiyFlags = flags; + if(mDlLibHandler.startActivity && activity) { + const char *actStr = env->GetStringUTFChars(activity, NULL); + if (actStr) { + (*mDlLibHandler.startActivity)(actStr, &activiyFlags); + env->ReleaseStringUTFChars(activity, actStr); + } + } + return activiyFlags; +} + +static void +com_android_internal_app_ActivityTrigger_native_at_resumeActivity(JNIEnv *env, jobject clazz, jstring activity) +{ + if(mDlLibHandler.resumeActivity && activity) { + const char *actStr = env->GetStringUTFChars(activity, NULL); + if (actStr) { + (*mDlLibHandler.resumeActivity)(actStr); + env->ReleaseStringUTFChars(activity, actStr); + } + } +} + +static void +com_android_internal_app_ActivityTrigger_native_at_pauseActivity(JNIEnv *env, jobject clazz, jstring activity) +{ + if(mDlLibHandler.pauseActivity && activity) { + const char *actStr = env->GetStringUTFChars(activity, NULL); + if (NULL != actStr) { + (*mDlLibHandler.pauseActivity)(actStr); + env->ReleaseStringUTFChars(activity, actStr); + } + } +} + +static void +com_android_internal_app_ActivityTrigger_native_at_stopActivity(JNIEnv *env, jobject clazz, jstring activity) +{ + if(mDlLibHandler.stopActivity && activity) { + const char *actStr = env->GetStringUTFChars(activity, NULL); + if (NULL != actStr) { + (*mDlLibHandler.stopActivity)(actStr); + env->ReleaseStringUTFChars(activity, actStr); + } + } +} + +static jfloat +com_android_internal_app_ActivityTrigger_native_at_miscActivity(JNIEnv *env, jobject clazz, jint func, jstring activity, jint type, jint flag) +{ + float scaleValue = -1.0f; + if (mDlLibHandler.miscActivity && activity && func) { + const char *actStr = env->GetStringUTFChars(activity, NULL); + if (actStr) { + (*mDlLibHandler.miscActivity)(func, actStr, type, flag, &scaleValue); + env->ReleaseStringUTFChars(activity, actStr); + } + } + return scaleValue; +} + +// ---------------------------------------------------------------------------- + +static JNINativeMethod gMethods[] = { + {"native_at_startActivity", "(Ljava/lang/String;I)I", (void *)com_android_internal_app_ActivityTrigger_native_at_startActivity}, + {"native_at_resumeActivity", "(Ljava/lang/String;)V", (void *)com_android_internal_app_ActivityTrigger_native_at_resumeActivity}, + {"native_at_pauseActivity", "(Ljava/lang/String;)V", (void *)com_android_internal_app_ActivityTrigger_native_at_pauseActivity}, + {"native_at_stopActivity", "(Ljava/lang/String;)V", (void *)com_android_internal_app_ActivityTrigger_native_at_stopActivity}, + {"native_at_deinit", "()V", (void *)com_android_internal_app_ActivityTrigger_native_at_deinit}, + {"native_at_miscActivity", "(ILjava/lang/String;II)F", (void *)com_android_internal_app_ActivityTrigger_native_at_miscActivity}, +}; + +int register_com_android_internal_app_ActivityTrigger(JNIEnv *env) +{ + com_android_internal_app_ActivityTrigger_native_at_init(); + + return AndroidRuntime::registerNativeMethods(env, + "com/android/internal/app/ActivityTrigger", gMethods, NELEM(gMethods)); +} + +} // namespace android diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp index e81b6276ef5f..906080178479 100644 --- a/core/jni/com_android_internal_os_Zygote.cpp +++ b/core/jni/com_android_internal_os_Zygote.cpp @@ -62,6 +62,8 @@ #include <android-base/stringprintf.h> #include <cutils/fs.h> #include <cutils/multiuser.h> +#include <cutils/properties.h> +#include <cutils/sched_policy.h> #include <private/android_filesystem_config.h> #include <utils/String8.h> #include <selinux/android.h> @@ -295,7 +297,14 @@ static void EnableDebugger() { if (getrlimit(RLIMIT_CORE, &rl) == -1) { ALOGE("getrlimit(RLIMIT_CORE) failed"); } else { - rl.rlim_cur = 0; + char prop_value[PROPERTY_VALUE_MAX]; + property_get("persist.debug.trace", prop_value, "0"); + if (prop_value[0] == '1') { + ALOGI("setting RLIM to infinity"); + rl.rlim_cur = RLIM_INFINITY; + } else { + rl.rlim_cur = 0; + } if (setrlimit(RLIMIT_CORE, &rl) == -1) { ALOGE("setrlimit(RLIMIT_CORE) failed"); } diff --git a/core/proto/android/providers/settings/global.proto b/core/proto/android/providers/settings/global.proto index 415857771899..eedd5d9e4b09 100644 --- a/core/proto/android/providers/settings/global.proto +++ b/core/proto/android/providers/settings/global.proto @@ -674,6 +674,8 @@ message GlobalSettingsProto { optional SettingProto server = 1; // Timeout in milliseconds to wait for NTP server. optional SettingProto timeout_ms = 2 [ (android.privacy).dest = DEST_AUTOMATIC ]; + // Secondary NTP server. + optional SettingProto server_2 = 3; } optional Ntp ntp = 84; diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index ea0c8e250fe2..2212e098f43b 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -48,6 +48,7 @@ <protected-broadcast android:name="android.intent.action.PACKAGE_DATA_CLEARED" /> <protected-broadcast android:name="android.intent.action.PACKAGE_FIRST_LAUNCH" /> <protected-broadcast android:name="android.intent.action.PACKAGE_NEEDS_VERIFICATION" /> + <protected-broadcast android:name="com.qualcomm.qti.intent.action.PACKAGE_NEEDS_OPTIONAL_VERIFICATION" /> <protected-broadcast android:name="android.intent.action.PACKAGE_VERIFIED" /> <protected-broadcast android:name="android.intent.action.PACKAGES_SUSPENDED" /> <protected-broadcast android:name="android.intent.action.PACKAGES_UNSUSPENDED" /> @@ -155,8 +156,10 @@ <protected-broadcast android:name="android.bluetooth.device.action.CONNECTION_ACCESS_REQUEST" /> <protected-broadcast android:name="android.bluetooth.device.action.SDP_RECORD" /> <protected-broadcast android:name="android.bluetooth.device.action.BATTERY_LEVEL_CHANGED" /> + <protected-broadcast android:name="android.bluetooth.device.action.TWS_PLUS_DEVICE_PAIR" /> <protected-broadcast android:name="android.bluetooth.devicepicker.action.LAUNCH" /> <protected-broadcast android:name="android.bluetooth.devicepicker.action.DEVICE_SELECTED" /> + <protected-broadcast android:name="org.codeaurora.intent.bluetooth.action.REMOTE_ISSUE_OCCURRED" /> <protected-broadcast android:name="android.bluetooth.headset.profile.action.CONNECTION_STATE_CHANGED" /> <protected-broadcast @@ -346,7 +349,27 @@ <protected-broadcast android:name="com.android.server.wifi.wakeup.OPEN_WIFI_PREFERENCES" /> <protected-broadcast android:name="com.android.server.wifi.wakeup.OPEN_WIFI_SETTINGS" /> <protected-broadcast android:name="com.android.server.wifi.wakeup.TURN_OFF_WIFI_WAKE" /> + + <protected-broadcast android:name="com.qualcomm.qti.wigig.WIGIG_CREDENTIAL_CHANGED" /> + <protected-broadcast android:name="com.qualcomm.qti.wigig.WIGIG_STATE_CHANGED" /> + <protected-broadcast android:name="com.qualcomm.qti.wigig.WIGIG_AP_STATE_CHANGED" /> + <protected-broadcast android:name="com.qualcomm.qti.wigig.supplicant.CONNECTION_CHANGE" /> + <protected-broadcast android:name="com.qualcomm.qti.wigig.STATE_CHANGE" /> + <protected-broadcast android:name="com.qualcomm.qti.wigig.CONFIGURED_NETWORKS_CHANGE" /> + <protected-broadcast android:name="com.qualcomm.qti.wigig.SCAN_RESULTS" /> + <protected-broadcast android:name="com.qualcomm.qti.wigig.LINK_CONFIGURATION_CHANGED" /> + <protected-broadcast android:name="com.qualcomm.qti.wigig.WIGIG_RATE_UPGRADE_STATE_CHANGED" /> + <protected-broadcast android:name="com.qualcomm.qti.wigig.RSSI_CHANGED" /> + <protected-broadcast android:name="wigig_scan_available" /> + <protected-broadcast android:name="android.net.wigig.p2p.STATE_CHANGED" /> + <protected-broadcast android:name="android.net.wigig.p2p.CONNECTION_STATE_CHANGE" /> + <protected-broadcast android:name="android.net.wigig.p2p.PEERS_CHANGED" /> + <protected-broadcast android:name="android.net.wigig.p2p.DISCOVERY_STATE_CHANGE" /> + <protected-broadcast android:name="android.net.wigig.p2p.THIS_DEVICE_CHANGED" /> + <protected-broadcast android:name="android.net.wigig.p2p.PERSISTENT_GROUPS_CHANGED" /> + <protected-broadcast android:name="android.net.wifi.WIFI_STATE_CHANGED" /> + <protected-broadcast android:name="com.qualcomm.qti.net.wifi.WIFI_DATA_STALL" /> <protected-broadcast android:name="android.net.wifi.WIFI_AP_STATE_CHANGED" /> <protected-broadcast android:name="android.net.wifi.WIFI_CREDENTIAL_CHANGED" /> <protected-broadcast android:name="android.net.wifi.WIFI_SCAN_AVAILABLE" /> @@ -371,6 +394,9 @@ <protected-broadcast android:name="android.net.wifi.p2p.PEERS_CHANGED" /> <protected-broadcast android:name="android.net.wifi.p2p.CONNECTION_STATE_CHANGE" /> <protected-broadcast android:name="android.net.wifi.p2p.PERSISTENT_GROUPS_CHANGED" /> + <protected-broadcast android:name="com.qualcomm.qti.net.wifi.DPP_EVENT" /> + <protected-broadcast android:name="android.net.wifi.COUNTRY_CODE_CHANGED" /> + <protected-broadcast android:name="com.qualcomm.qti.net.wifi.WIFI_DISCONNECT_IN_PROGRESS" /> <protected-broadcast android:name="android.net.conn.TETHER_STATE_CHANGED" /> <protected-broadcast android:name="android.net.conn.INET_CONDITION_ACTION" /> <protected-broadcast android:name="android.net.conn.NETWORK_CONDITIONS_MEASURED" /> @@ -561,6 +587,11 @@ <protected-broadcast android:name="android.bluetooth.input.profile.action.HANDSHAKE" /> <protected-broadcast android:name="android.bluetooth.input.profile.action.REPORT" /> + <protected-broadcast android:name="android.bluetooth.bat.profile.action.BA_STATE_CHANGED" /> + <protected-broadcast android:name="android.bluetooth.bat.profile.action.BA_ENC_KEY_CHANGED" /> + <protected-broadcast android:name="android.bluetooth.bat.profile.action.BA_DIV_CHANGED" /> + <protected-broadcast android:name="android.bluetooth.bat.profile.action.BA_STR_ID_CHANGED" /> + <protected-broadcast android:name="android.intent.action.TWILIGHT_CHANGED" /> <protected-broadcast android:name="com.android.server.fingerprint.ACTION_LOCKOUT_RESET" /> @@ -1426,6 +1457,11 @@ <permission android:name="android.permission.MODIFY_CELL_BROADCASTS" android:protectionLevel="signature|privileged" /> + <!-- Allows an application to authorize outgoing SMS messages. + @hide --> + <permission android:name="com.qti.permission.AUTHORIZE_OUTGOING_SMS" + android:protectionLevel="signature" /> + <!-- =============================================================== --> <!-- Permissions for setting the device alarm --> <!-- =============================================================== --> diff --git a/core/res/res/values/bools.xml b/core/res/res/values/bools.xml index b49fe49c087b..9f8a54b7a7cc 100644 --- a/core/res/res/values/bools.xml +++ b/core/res/res/values/bools.xml @@ -30,4 +30,5 @@ <p>The main purpose is for OEMs to customize the rendering of the lockscreen, setting this to true should come with customized drawables. --> <bool name="use_lock_pattern_drawable">false</bool> + <bool name="config_wifi_dual_sap_mode_enabled">false</bool> </resources> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 5995640c7659..2c30545669d9 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -1567,7 +1567,7 @@ <integer-array name="config_screenBrighteningThresholds"> <item>100</item> </integer-array> - + <!-- Array of hysteresis constraint values for darkening, represented as tenths of a percent. The length of this array is assumed to be one greater than config_screenThresholdLevels. The darkening threshold is calculated as @@ -1776,6 +1776,9 @@ --> </string-array> + <!-- Component name of the combo network location provider. --> + <string name="config_comboNetworkLocationProvider" translatable="false">com.qualcomm.location</string> + <!-- Boolean indicating if current platform supports bluetooth SCO for off call use cases --> <bool name="config_bluetooth_sco_off_call">true</bool> @@ -2805,6 +2808,9 @@ <!-- Flag indicating which package name can access DeviceConfig table --> <string name="config_deviceConfiguratorPackageName" translatable="false"></string> + <!-- Define optional package verifier name --> + <string name="config_optionalPackageVerifierName" translatable="false"></string> + <!-- Flag indicating apps will skip sending hold request before merge. In this case IMS service implementation will do both.i.e.hold followed by merge. --> <bool name="skipHoldBeforeMerge">true</bool> @@ -3660,6 +3666,15 @@ <!-- Package name for ManagedProvisioning which is responsible for provisioning work profiles. --> <string name="config_managed_provisioning_package" translatable="false">com.android.managedprovisioning</string> + <!-- The duration (in milliseconds) for the outgoing sms authorization request to timeout.--> + <integer name="config_sms_authorization_timeout_ms">0</integer> + + <!-- Enable sms authorization framework--> + <bool name="config_sms_authorization_enabled">false</bool> + + <!-- whether to enable primarycard --> + <bool name="config_primarycard">false</bool> + <!-- Whether or not swipe up gesture is enabled by default --> <bool name="config_swipe_up_gesture_default">false</bool> @@ -3698,6 +3713,10 @@ <!-- Whether or not the "SMS app service" feature is enabled --> <bool name="config_useSmsAppService">true</bool> + <!-- List of names that represent dual SoftAp interfaces. --> + <string-array translatable="false" name="config_wifi_dual_sap_interfaces"> + </string-array> + <!-- Component name for default assistant on this device --> <string name="config_defaultAssistantComponentName">#+UNSET</string> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 53c33a3855dd..2661496ec520 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -2026,6 +2026,7 @@ <java-symbol type="string" name="config_geocoderProviderPackageName" /> <java-symbol type="string" name="config_geofenceProviderPackageName" /> <java-symbol type="string" name="config_networkLocationProviderPackageName" /> + <java-symbol type="string" name="config_comboNetworkLocationProvider" /> <java-symbol type="string" name="config_wimaxManagerClassname" /> <java-symbol type="string" name="config_wimaxNativeLibLocation" /> <java-symbol type="string" name="config_wimaxServiceClassname" /> @@ -2140,6 +2141,7 @@ <java-symbol type="string" name="config_defaultNetworkScorerPackageName" /> <java-symbol type="string" name="config_persistentDataPackageName" /> <java-symbol type="string" name="config_deviceConfiguratorPackageName" /> + <java-symbol type="string" name="config_optionalPackageVerifierName" /> <java-symbol type="layout" name="resolver_list" /> <java-symbol type="id" name="resolver_list" /> @@ -3484,7 +3486,11 @@ <java-symbol type="id" name="user_loading_avatar" /> <java-symbol type="id" name="user_loading" /> + <java-symbol type="integer" name="config_sms_authorization_timeout_ms" /> + <java-symbol type="bool" name="config_sms_authorization_enabled" /> + <java-symbol type="string" name="battery_saver_description_with_learn_more" /> + <java-symbol type="bool" name="config_primarycard" /> <java-symbol type="attr" name="opticalInsetLeft" /> <java-symbol type="attr" name="opticalInsetTop" /> @@ -3495,6 +3501,10 @@ <java-symbol type="drawable" name="ic_arrow_forward" /> <java-symbol type="drawable" name="ic_permission" /> + <!-- For Dual SoftaAp --> + <java-symbol type="array" name="config_wifi_dual_sap_interfaces" /> + <java-symbol type="bool" name="config_wifi_dual_sap_mode_enabled" /> + <java-symbol type="integer" name="config_defaultHapticFeedbackIntensity" /> <java-symbol type="integer" name="config_defaultNotificationVibrationIntensity" /> <java-symbol type="integer" name="config_defaultRingVibrationIntensity" /> @@ -3530,7 +3540,7 @@ <!-- For Secondary Launcher --> <java-symbol type="string" name="config_secondaryHomeComponent" /> - + <java-symbol type="string" name="dynamic_mode_notification_channel_name" /> <java-symbol type="string" name="dynamic_mode_notification_title" /> <java-symbol type="string" name="dynamic_mode_notification_summary" /> diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java index 59c6a0a21cd1..42551d16d2b1 100644 --- a/location/java/android/location/LocationManager.java +++ b/location/java/android/location/LocationManager.java @@ -568,6 +568,7 @@ public class LocationManager { @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION}) public void requestLocationUpdates(String provider, long minTime, float minDistance, LocationListener listener) { + android.util.SeempLog.record(47); checkProvider(provider); checkListener(listener); @@ -600,6 +601,7 @@ public class LocationManager { @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION}) public void requestLocationUpdates(String provider, long minTime, float minDistance, LocationListener listener, Looper looper) { + android.util.SeempLog.record(47); checkProvider(provider); checkListener(listener); @@ -633,6 +635,7 @@ public class LocationManager { @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION}) public void requestLocationUpdates(long minTime, float minDistance, Criteria criteria, LocationListener listener, Looper looper) { + android.util.SeempLog.record(47); checkCriteria(criteria); checkListener(listener); @@ -661,6 +664,7 @@ public class LocationManager { @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION}) public void requestLocationUpdates(String provider, long minTime, float minDistance, PendingIntent intent) { + android.util.SeempLog.record(47); checkProvider(provider); checkPendingIntent(intent); @@ -768,6 +772,7 @@ public class LocationManager { @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION}) public void requestLocationUpdates(long minTime, float minDistance, Criteria criteria, PendingIntent intent) { + android.util.SeempLog.record(47); checkCriteria(criteria); checkPendingIntent(intent); @@ -797,6 +802,7 @@ public class LocationManager { */ @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION}) public void requestSingleUpdate(String provider, LocationListener listener, Looper looper) { + android.util.SeempLog.record(64); checkProvider(provider); checkListener(listener); @@ -827,6 +833,7 @@ public class LocationManager { */ @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION}) public void requestSingleUpdate(Criteria criteria, LocationListener listener, Looper looper) { + android.util.SeempLog.record(64); checkCriteria(criteria); checkListener(listener); @@ -850,6 +857,7 @@ public class LocationManager { */ @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION}) public void requestSingleUpdate(String provider, PendingIntent intent) { + android.util.SeempLog.record(64); checkProvider(provider); checkPendingIntent(intent); @@ -874,6 +882,7 @@ public class LocationManager { */ @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION}) public void requestSingleUpdate(Criteria criteria, PendingIntent intent) { + android.util.SeempLog.record(64); checkCriteria(criteria); checkPendingIntent(intent); @@ -943,6 +952,7 @@ public class LocationManager { @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION}) public void requestLocationUpdates(LocationRequest request, LocationListener listener, Looper looper) { + android.util.SeempLog.record(47); checkListener(listener); requestLocationUpdates(request, listener, looper, null); } @@ -971,6 +981,7 @@ public class LocationManager { @SystemApi @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION}) public void requestLocationUpdates(LocationRequest request, PendingIntent intent) { + android.util.SeempLog.record(47); checkPendingIntent(intent); requestLocationUpdates(request, null, null, intent); } @@ -1018,6 +1029,7 @@ public class LocationManager { @UnsupportedAppUsage private void requestLocationUpdates(LocationRequest request, LocationListener listener, Looper looper, PendingIntent intent) { + android.util.SeempLog.record(47); String packageName = mContext.getPackageName(); @@ -1126,6 +1138,7 @@ public class LocationManager { @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION}) public void addProximityAlert(double latitude, double longitude, float radius, long expiration, PendingIntent intent) { + android.util.SeempLog.record(45); checkPendingIntent(intent); if (expiration < 0) expiration = Long.MAX_VALUE; @@ -1436,6 +1449,7 @@ public class LocationManager { */ @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION}) public Location getLastKnownLocation(String provider) { + android.util.SeempLog.record(46); checkProvider(provider); String packageName = mContext.getPackageName(); LocationRequest request = LocationRequest.createFromDeprecatedProvider( @@ -1837,6 +1851,7 @@ public class LocationManager { @Deprecated @RequiresPermission(ACCESS_FINE_LOCATION) public boolean addGpsStatusListener(GpsStatus.Listener listener) { + android.util.SeempLog.record(43); boolean result; if (mGpsStatusListeners.get(listener) != null) { @@ -1948,6 +1963,7 @@ public class LocationManager { @Deprecated @RequiresPermission(ACCESS_FINE_LOCATION) public boolean addNmeaListener(GpsStatus.NmeaListener listener) { + android.util.SeempLog.record(44); boolean result; if (mGpsNmeaListeners.get(listener) != null) { @@ -2364,6 +2380,7 @@ public class LocationManager { * @return true if the command succeeds. */ public boolean sendExtraCommand(String provider, String command, Bundle extras) { + android.util.SeempLog.record(48); try { return mService.sendExtraCommand(provider, command, extras); } catch (RemoteException e) { diff --git a/media/java/android/media/AudioFormat.java b/media/java/android/media/AudioFormat.java index 55160869ad0a..ea14b7d8dc95 100644 --- a/media/java/android/media/AudioFormat.java +++ b/media/java/android/media/AudioFormat.java @@ -282,6 +282,31 @@ public final class AudioFormat implements Parcelable { **/ public static final int ENCODING_DOLBY_MAT = 19; + /** Audio data format: AMRNB + * @hide + * */ + public static final int ENCODING_AMRNB = 100; + /** Audio data format: AMRWB + * @hide + * */ + public static final int ENCODING_AMRWB = 101; + /** Audio data format: EVRC + * @hide + * */ + public static final int ENCODING_EVRC = 102; + /** Audio data format: EVRCB + * @hide + * */ + public static final int ENCODING_EVRCB = 103; + /** Audio data format: EVRCWB + * @hide + * */ + public static final int ENCODING_EVRCWB = 104; + /** Audio data format: EVRCNW + * @hide + * */ + public static final int ENCODING_EVRCNW = 105; + /** @hide */ public static String toLogFriendlyEncoding(int enc) { switch(enc) { @@ -505,6 +530,11 @@ public final class AudioFormat implements Parcelable { public static final int CHANNEL_IN_STEREO = (CHANNEL_IN_LEFT | CHANNEL_IN_RIGHT); /** @hide */ public static final int CHANNEL_IN_FRONT_BACK = CHANNEL_IN_FRONT | CHANNEL_IN_BACK; + /** @hide */ + public static final int CHANNEL_IN_5POINT1 = (CHANNEL_IN_LEFT | + CHANNEL_IN_RIGHT | CHANNEL_IN_FRONT | CHANNEL_IN_BACK | + CHANNEL_IN_LEFT_PROCESSED | CHANNEL_IN_RIGHT_PROCESSED); + // CHANNEL_IN_ALL is not yet defined; if added then it should match AUDIO_CHANNEL_IN_ALL /** @hide */ @@ -520,6 +550,15 @@ public final class AudioFormat implements Parcelable { return 2; case ENCODING_PCM_FLOAT: return 4; + case ENCODING_AMRNB: + return 32; + case ENCODING_AMRWB: + return 61; + case ENCODING_EVRC: + case ENCODING_EVRCB: + case ENCODING_EVRCWB: + case ENCODING_EVRCNW: + return 23; case ENCODING_INVALID: default: throw new IllegalArgumentException("Bad audio format " + audioFormat); @@ -546,6 +585,12 @@ public final class AudioFormat implements Parcelable { case ENCODING_AAC_ELD: case ENCODING_AAC_XHE: case ENCODING_AC4: + case ENCODING_AMRNB: + case ENCODING_AMRWB: + case ENCODING_EVRC: + case ENCODING_EVRCB: + case ENCODING_EVRCWB: + case ENCODING_EVRCNW: case ENCODING_E_AC3_JOC: case ENCODING_DOLBY_MAT: return true; @@ -605,6 +650,12 @@ public final class AudioFormat implements Parcelable { case ENCODING_AAC_ELD: case ENCODING_AAC_XHE: case ENCODING_AC4: + case ENCODING_AMRNB: + case ENCODING_AMRWB: + case ENCODING_EVRC: + case ENCODING_EVRCB: + case ENCODING_EVRCWB: + case ENCODING_EVRCNW: case ENCODING_E_AC3_JOC: case ENCODING_DOLBY_MAT: return false; @@ -915,6 +966,12 @@ public final class AudioFormat implements Parcelable { case ENCODING_AAC_ELD: case ENCODING_AAC_XHE: case ENCODING_AC4: + case ENCODING_AMRNB: + case ENCODING_AMRWB: + case ENCODING_EVRC: + case ENCODING_EVRCB: + case ENCODING_EVRCWB: + case ENCODING_EVRCNW: case ENCODING_E_AC3_JOC: case ENCODING_DOLBY_MAT: mEncoding = encoding; @@ -1135,6 +1192,12 @@ public final class AudioFormat implements Parcelable { ENCODING_AAC_ELD, ENCODING_AAC_XHE, ENCODING_AC4, + ENCODING_AMRNB, + ENCODING_AMRWB, + ENCODING_EVRC, + ENCODING_EVRCB, + ENCODING_EVRCWB, + ENCODING_EVRCNW, ENCODING_E_AC3_JOC, ENCODING_DOLBY_MAT } ) diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index b7f042b48da1..a628eac21942 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -1362,6 +1362,8 @@ public class AudioManager { */ public void setSpeakerphoneOn(boolean on){ final IAudioService service = getService(); + Log.i(TAG, "In setSpeakerphoneOn(), on: " + on + ", calling application: " + + mApplicationContext.getOpPackageName()); try { service.setSpeakerphoneOn(on); } catch (RemoteException e) { @@ -1375,6 +1377,8 @@ public class AudioManager { * @return true if speakerphone is on, false if it's off */ public boolean isSpeakerphoneOn() { + Log.i(TAG, "In isSpeakerphoneOn(), calling application: " + + mApplicationContext.getOpPackageName()); final IAudioService service = getService(); try { return service.isSpeakerphoneOn(); @@ -1485,8 +1489,12 @@ public class AudioManager { * @see #startBluetoothSco() */ public boolean isBluetoothScoAvailableOffCall() { - return getContext().getResources().getBoolean( - com.android.internal.R.bool.config_bluetooth_sco_off_call); + boolean retval; + retval = getContext().getResources().getBoolean( + com.android.internal.R.bool.config_bluetooth_sco_off_call); + Log.i(TAG, "In isBluetoothScoAvailableOffCall(), calling appilication: " + + mApplicationContext.getOpPackageName()+", return value: " + retval); + return retval; } /** @@ -1536,6 +1544,8 @@ public class AudioManager { */ public void startBluetoothSco(){ final IAudioService service = getService(); + Log.i(TAG, "In startbluetoothSco(), calling application: " + + mApplicationContext.getOpPackageName()); try { service.startBluetoothSco(mICallBack, getContext().getApplicationInfo().targetSdkVersion); @@ -1561,6 +1571,8 @@ public class AudioManager { */ @UnsupportedAppUsage public void startBluetoothScoVirtualCall() { + Log.i(TAG, "In startBluetoothScoVirtualCall(), calling application: " + + mApplicationContext.getOpPackageName()); final IAudioService service = getService(); try { service.startBluetoothScoVirtualCall(mICallBack); @@ -1581,6 +1593,8 @@ public class AudioManager { // Also used for connections started with {@link #startBluetoothScoVirtualCall()} public void stopBluetoothSco(){ final IAudioService service = getService(); + Log.i(TAG, "In stopBluetoothSco(), calling application: " + + mApplicationContext.getOpPackageName()); try { service.stopBluetoothSco(mICallBack); } catch (RemoteException e) { @@ -1599,6 +1613,8 @@ public class AudioManager { */ public void setBluetoothScoOn(boolean on){ final IAudioService service = getService(); + Log.i(TAG, "In setBluetoothScoOn(), on: " + on + ", calling application: " + + mApplicationContext.getOpPackageName()); try { service.setBluetoothScoOn(on); } catch (RemoteException e) { @@ -1614,6 +1630,8 @@ public class AudioManager { */ public boolean isBluetoothScoOn() { final IAudioService service = getService(); + Log.i(TAG, "In isBluetoothScoOn(), calling application: " + + mApplicationContext.getOpPackageName()); try { return service.isBluetoothScoOn(); } catch (RemoteException e) { diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java index 92afe7ede8f2..c5b117874a51 100644 --- a/media/java/android/media/AudioRecord.java +++ b/media/java/android/media/AudioRecord.java @@ -714,6 +714,12 @@ public class AudioRecord implements AudioRouting, MicrophoneDirection, case AudioFormat.ENCODING_PCM_FLOAT: case AudioFormat.ENCODING_PCM_16BIT: case AudioFormat.ENCODING_PCM_8BIT: + case AudioFormat.ENCODING_AMRNB: + case AudioFormat.ENCODING_AMRWB: + case AudioFormat.ENCODING_EVRC: + case AudioFormat.ENCODING_EVRCB: + case AudioFormat.ENCODING_EVRCWB: + case AudioFormat.ENCODING_EVRCNW: mAudioFormat = audioFormat; break; default: @@ -951,6 +957,9 @@ public class AudioRecord implements AudioRouting, MicrophoneDirection, case (AudioFormat.CHANNEL_IN_FRONT | AudioFormat.CHANNEL_IN_BACK): channelCount = 2; break; + case AudioFormat.CHANNEL_IN_5POINT1: + channelCount = 6; + break; case AudioFormat.CHANNEL_INVALID: default: loge("getMinBufferSize(): Invalid channel configuration."); @@ -987,6 +996,7 @@ public class AudioRecord implements AudioRouting, MicrophoneDirection, */ public void startRecording() throws IllegalStateException { + android.util.SeempLog.record(70); if (mState != STATE_INITIALIZED) { throw new IllegalStateException("startRecording() called on an " + "uninitialized AudioRecord."); @@ -1010,6 +1020,7 @@ public class AudioRecord implements AudioRouting, MicrophoneDirection, */ public void startRecording(MediaSyncEvent syncEvent) throws IllegalStateException { + android.util.SeempLog.record(70); if (mState != STATE_INITIALIZED) { throw new IllegalStateException("startRecording() called on an " + "uninitialized AudioRecord."); diff --git a/media/java/android/media/CamcorderProfile.java b/media/java/android/media/CamcorderProfile.java index 4f74ec911499..c4d5d6c4b578 100644 --- a/media/java/android/media/CamcorderProfile.java +++ b/media/java/android/media/CamcorderProfile.java @@ -208,6 +208,77 @@ public class CamcorderProfile private static final int QUALITY_HIGH_SPEED_LIST_START = QUALITY_HIGH_SPEED_LOW; private static final int QUALITY_HIGH_SPEED_LIST_END = QUALITY_HIGH_SPEED_2160P; + // Vendor-specific quality profiles + /** + * Quality level corresponding to the VGA (640 x 480) resolution. + * @hide + */ + public static final int QUALITY_VGA = 10000; + + /** + * Quality level corresponding to the 4k-DCI (4096 x 2160) resolution. + * @hide + */ + public static final int QUALITY_4KDCI = 10001; + + /** + * Time lapse quality level corresponding to the VGA (640 x 480) resolution. + * @hide + */ + public static final int QUALITY_TIME_LAPSE_VGA = 10002; + + /** + * Time lapse quality level corresponding to the 4k-DCI (4096 x 2160) resolution. + * @hide + */ + public static final int QUALITY_TIME_LAPSE_4KDCI = 10003; + + /** + * High speed ( >= 100fps) quality level corresponding to the CIF (352 x 288) + * @hide + */ + public static final int QUALITY_HIGH_SPEED_CIF = 10004; + + /** + * High speed ( >= 100fps) quality level corresponding to the VGA (640 x 480) + * @hide + */ + public static final int QUALITY_HIGH_SPEED_VGA = 10005; + + /** + * High speed ( >= 100fps) quality level corresponding to the 4K-DCI (4096 x 2160) + * @hide + */ + public static final int QUALITY_HIGH_SPEED_4KDCI = 10006; + + /** + * Quality level corresponding to QHD resolution + * @hide + */ + public static final int QUALITY_QHD = 10007; + + /** + * Quality level corresponding to 2K resolution + * @hide + */ + public static final int QUALITY_2k = 10008; + + /** + * Time lapse quality level corresponding to the QHD resolution. + * @hide + */ + public static final int QUALITY_TIME_LAPSE_QHD = 10009; + + /** + * Time lapse quality level corresponding to the 2K resolution. + * @hide + */ + public static final int QUALITY_TIME_LAPSE_2k = 10010; + + // Start and end of vendor quality list + private static final int QUALITY_VENDOR_LIST_START = QUALITY_VGA; + private static final int QUALITY_VENDOR_LIST_END = QUALITY_TIME_LAPSE_2k; + /** * Default recording duration in seconds before the session is terminated. * This is useful for applications like MMS has limited file size requirement. @@ -393,7 +464,9 @@ public class CamcorderProfile (quality >= QUALITY_TIME_LAPSE_LIST_START && quality <= QUALITY_TIME_LAPSE_LIST_END) || (quality >= QUALITY_HIGH_SPEED_LIST_START && - quality <= QUALITY_HIGH_SPEED_LIST_END))) { + quality <= QUALITY_HIGH_SPEED_LIST_END) || + (quality >= QUALITY_VENDOR_LIST_START && + quality <= QUALITY_VENDOR_LIST_END))) { String errMessage = "Unsupported quality level: " + quality; throw new IllegalArgumentException(errMessage); } diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java index 751d57bbdc81..572ca403eed5 100644 --- a/media/java/android/media/MediaCodecInfo.java +++ b/media/java/android/media/MediaCodecInfo.java @@ -2396,6 +2396,12 @@ public final class MediaCodecInfo { MBPS = 983040; FS = 36864; BR = 240000; DPB = 184320; break; case CodecProfileLevel.AVCLevel52: MBPS = 2073600; FS = 36864; BR = 240000; DPB = 184320; break; + case CodecProfileLevel.AVCLevel6: + MBPS = 4177920; FS = 139264; BR = 240000; DPB = 696320; break; + case CodecProfileLevel.AVCLevel61: + MBPS = 8355840; FS = 139264; BR = 480000; DPB = 696320; break; + case CodecProfileLevel.AVCLevel62: + MBPS = 16711680; FS = 139264; BR = 800000; DPB = 696320; break; default: Log.w(TAG, "Unrecognized level " + profileLevel.level + " for " + mime); @@ -3196,8 +3202,11 @@ public final class MediaCodecInfo { public static final int AVCLevel5 = 0x4000; public static final int AVCLevel51 = 0x8000; public static final int AVCLevel52 = 0x10000; + /** @hide */ public static final int AVCLevel6 = 0x20000; + /** @hide */ public static final int AVCLevel61 = 0x40000; + /** @hide */ public static final int AVCLevel62 = 0x80000; public static final int H263ProfileBaseline = 0x01; diff --git a/media/java/android/media/MediaFile.java b/media/java/android/media/MediaFile.java index 710b503d97fd..ad2e1fd04966 100644 --- a/media/java/android/media/MediaFile.java +++ b/media/java/android/media/MediaFile.java @@ -152,6 +152,20 @@ public class MediaFile { "application/vnd.ms-powerpoint"); addFileType(MtpConstants.FORMAT_MS_POWERPOINT_PRESENTATION, "application/vnd.openxmlformats-officedocument.presentationml.presentation"); + + // addFileType(MtpConstants.FORMAT_DIVX, "video/divx"); + // addFileType(MtpConstants.FORMAT_FLV, "video/flv"); + // addFileType(MtpConstants.FORMAT_QCP, "audio/qcelp"); + // addFileType(MtpConstants.FORMAT_AC3, "audio/ac3"); + // addFileType(MtpConstants.FORMAT_EC3, "audio/eac3"); + // addFileType(MtpConstants.FORMAT_AIFF, "audio/x-aiff"); + // addFileType(MtpConstants.FORMAT_APE, "audio/x-ape"); + // addFileType(MtpConstants.FORMAT_DSD, "audio/x-dsf"); + // addFileType(MtpConstants.FORMAT_DSD, "audio/x-dff"); + // addFileType(MtpConstants.FORMAT_DSD, "audio/dsd"); + // addFileType(MtpConstants.FORMAT_MHAS, "audio/mhas"); + // addFileType(MtpConstants.FORMAT_MP4, "audio/mhas"); + } /** @deprecated file types no longer exist */ diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java index 1304afe3654e..5fae1038ba9e 100644 --- a/media/java/android/media/MediaRecorder.java +++ b/media/java/android/media/MediaRecorder.java @@ -494,6 +494,12 @@ public class MediaRecorder implements AudioRouting, /** Opus data in a Ogg container */ public static final int OGG = 11; + + /** @hide QCP file format */ + public static final int QCP = 20; + + /** @hide WAVE media file format*/ + public static final int WAVE = 21; }; /** @@ -520,6 +526,12 @@ public class MediaRecorder implements AudioRouting, public static final int VORBIS = 6; /** Opus audio codec */ public static final int OPUS = 7; + /** @hide EVRC audio codec */ + public static final int EVRC = 10; + /** @hide QCELP audio codec */ + public static final int QCELP = 11; + /** @hide Linear PCM audio codec */ + public static final int LPCM = 12; } /** diff --git a/media/jni/Android.bp b/media/jni/Android.bp index 48dbf555e546..d7048ce180ca 100644 --- a/media/jni/Android.bp +++ b/media/jni/Android.bp @@ -114,6 +114,11 @@ cc_library_shared { "libnativehelper_compat_libc++", "liblog", "libz", + + "libmedia", + "libmedia_omx", + "libstagefright", + "libmediaplayerservice", ], header_libs: [ diff --git a/media/jni/android_media_MediaProfiles.cpp b/media/jni/android_media_MediaProfiles.cpp index 5bc80925eca4..fcdb955a33ab 100644 --- a/media/jni/android_media_MediaProfiles.cpp +++ b/media/jni/android_media_MediaProfiles.cpp @@ -170,7 +170,9 @@ static bool isCamcorderQualityKnown(int quality) (quality >= CAMCORDER_QUALITY_TIME_LAPSE_LIST_START && quality <= CAMCORDER_QUALITY_TIME_LAPSE_LIST_END) || (quality >= CAMCORDER_QUALITY_HIGH_SPEED_LIST_START && - quality <= CAMCORDER_QUALITY_HIGH_SPEED_LIST_END)); + quality <= CAMCORDER_QUALITY_HIGH_SPEED_LIST_END) || + (quality >= CAMCORDER_QUALITY_VENDOR_START && + quality <= CAMCORDER_QUALITY_VENDOR_END)); } static jobject diff --git a/obex/javax/obex/ClientOperation.java b/obex/javax/obex/ClientOperation.java index c627dfb8abac..65e2140df256 100644 --- a/obex/javax/obex/ClientOperation.java +++ b/obex/javax/obex/ClientOperation.java @@ -50,7 +50,7 @@ import android.util.Log; */ public final class ClientOperation implements Operation, BaseStream { - private static final String TAG = "ClientOperation"; + private static final String TAG = "ObexClientOperation"; private static final boolean V = ObexHelper.VDBG; @@ -460,6 +460,7 @@ public final class ClientOperation implements Operation, BaseStream { > mMaxPacketSize) { int end = 0; int start = 0; + int processedLen = 0; // split & send the headerArray in multiple packets. while (end != headerArray.length) { @@ -486,10 +487,17 @@ public final class ClientOperation implements Operation, BaseStream { byte[] sendHeader = new byte[end - start]; System.arraycopy(headerArray, start, sendHeader, 0, sendHeader.length); + processedLen += sendHeader.length; + opCode = (processedLen == headerArray.length) ? ObexHelper.OBEX_OPCODE_GET_FINAL + : ObexHelper.OBEX_OPCODE_GET; + //Set GET FINAL (0x83) for Last Request Header packet as per GOEP2.1 if (!mParent.sendRequest(opCode, sendHeader, mReplyHeader, mPrivateInput, false)) { return false; } - + if (mReplyHeader.responseCode == ResponseCodes.OBEX_HTTP_OK) { + Log.i(TAG, "sendRequest return OBEX_HTTP_OK"); + return true; + } if (mReplyHeader.responseCode != ResponseCodes.OBEX_HTTP_CONTINUE) { return false; } diff --git a/obex/javax/obex/ClientSession.java b/obex/javax/obex/ClientSession.java index 272a920754f5..9aaf7bcda034 100644 --- a/obex/javax/obex/ClientSession.java +++ b/obex/javax/obex/ClientSession.java @@ -47,7 +47,7 @@ import android.util.Log; */ public final class ClientSession extends ObexSession { - private static final String TAG = "ClientSession"; + private static final String TAG = "ObexClientSession"; private boolean mOpen; diff --git a/obex/javax/obex/ObexHelper.java b/obex/javax/obex/ObexHelper.java index 478297f2a3c9..f09d3d3fb09c 100644 --- a/obex/javax/obex/ObexHelper.java +++ b/obex/javax/obex/ObexHelper.java @@ -52,7 +52,8 @@ import android.util.Log; public final class ObexHelper { private static final String TAG = "ObexHelper"; - public static final boolean VDBG = false; + public static final String LOG_TAG = "BluetoothObex"; + public static final boolean VDBG = Log.isLoggable(LOG_TAG, Log.VERBOSE); /** * Defines the basic packet length used by OBEX. Every OBEX packet has the * same basic format:<BR> @@ -89,6 +90,8 @@ public final class ObexHelper { */ public static final int MAX_CLIENT_PACKET_SIZE = 0xFC00; + public static final int A2DP_SCO_OBEX_MAX_CLIENT_PACKET_SIZE = 0x2000; + public static final int OBEX_OPCODE_FINAL_BIT_MASK = 0x80; public static final int OBEX_OPCODE_CONNECT = 0x80; @@ -193,6 +196,7 @@ public final class ObexHelper { try { while (index < headerArray.length) { headerID = 0xFF & headerArray[index]; + if (VDBG) Log.v(TAG,"updateHeaderSet headerID = " + headerID); switch (headerID & (0xC0)) { /* @@ -211,9 +215,9 @@ public final class ObexHelper { length = ((0xFF & headerArray[index]) << 8) + (0xFF & headerArray[index + 1]); index += 2; - if (length <= OBEX_BYTE_SEQ_HEADER_LEN) { + if (length < OBEX_BYTE_SEQ_HEADER_LEN) { Log.e(TAG, "Remote sent an OBEX packet with " + - "incorrect header length = " + length); + "incorrect header length : " + length); break; } length -= OBEX_BYTE_SEQ_HEADER_LEN; @@ -381,8 +385,9 @@ public final class ObexHelper { * Determine if there is a connection ID to send. If there is, * then it should be the first header in the packet. */ + if (VDBG) Log.v(TAG,"createHeader = " + head); if ((headImpl.mConnectionID != null) && (headImpl.getHeader(HeaderSet.TARGET) == null)) { - + if (VDBG) Log.v(TAG," Add Header = " + HeaderSet.CONNECTION_ID); out.write((byte)HeaderSet.CONNECTION_ID); out.write(headImpl.mConnectionID); } @@ -390,6 +395,7 @@ public final class ObexHelper { // Count Header intHeader = (Long)headImpl.getHeader(HeaderSet.COUNT); if (intHeader != null) { + if (VDBG) Log.v(TAG," Add Header = " + HeaderSet.COUNT); out.write((byte)HeaderSet.COUNT); value = ObexHelper.convertToByteArray(intHeader.longValue()); out.write(value); @@ -401,6 +407,7 @@ public final class ObexHelper { // Name Header stringHeader = (String)headImpl.getHeader(HeaderSet.NAME); if (stringHeader != null) { + if (VDBG) Log.v(TAG," Add Header = " + HeaderSet.NAME); out.write((byte)HeaderSet.NAME); value = ObexHelper.convertToUnicodeByteArray(stringHeader); length = value.length + 3; @@ -421,6 +428,7 @@ public final class ObexHelper { // Type Header stringHeader = (String)headImpl.getHeader(HeaderSet.TYPE); if (stringHeader != null) { + if (VDBG) Log.v(TAG," Add Header = " + HeaderSet.TYPE); out.write((byte)HeaderSet.TYPE); try { value = stringHeader.getBytes("ISO8859_1"); @@ -442,6 +450,7 @@ public final class ObexHelper { // Length Header intHeader = (Long)headImpl.getHeader(HeaderSet.LENGTH); if (intHeader != null) { + if (VDBG) Log.v(TAG," Add Header = " + HeaderSet.LENGTH); out.write((byte)HeaderSet.LENGTH); value = ObexHelper.convertToByteArray(intHeader.longValue()); out.write(value); @@ -453,7 +462,7 @@ public final class ObexHelper { // Time ISO Header dateHeader = (Calendar)headImpl.getHeader(HeaderSet.TIME_ISO_8601); if (dateHeader != null) { - + if (VDBG) Log.v(TAG," Add dateHeader = " + HeaderSet.TIME_ISO_8601); /* * The ISO Header should take the form YYYYMMDDTHHMMSSZ. The * 'Z' will only be included if it is a UTC time. @@ -515,6 +524,7 @@ public final class ObexHelper { // Time 4 Byte Header dateHeader = (Calendar)headImpl.getHeader(HeaderSet.TIME_4_BYTE); if (dateHeader != null) { + if (VDBG) Log.v(TAG," Add dateHeader = " + HeaderSet.TIME_4_BYTE); out.write(HeaderSet.TIME_4_BYTE); /* @@ -549,6 +559,7 @@ public final class ObexHelper { // Target Header value = (byte[])headImpl.getHeader(HeaderSet.TARGET); if (value != null) { + if (VDBG) Log.v(TAG," Add Header = " + HeaderSet.TARGET); out.write((byte)HeaderSet.TARGET); length = value.length + 3; lengthArray[0] = (byte)(255 & (length >> 8)); @@ -577,6 +588,7 @@ public final class ObexHelper { // Who Header value = (byte[])headImpl.getHeader(HeaderSet.WHO); if (value != null) { + if (VDBG) Log.v(TAG," Add Header = " + HeaderSet.WHO); out.write((byte)HeaderSet.WHO); length = value.length + 3; lengthArray[0] = (byte)(255 & (length >> 8)); @@ -591,6 +603,7 @@ public final class ObexHelper { // Connection ID Header value = (byte[])headImpl.getHeader(HeaderSet.APPLICATION_PARAMETER); if (value != null) { + if (VDBG) Log.v(TAG," Add APP PARAM Header = " + HeaderSet.APPLICATION_PARAMETER); out.write((byte)HeaderSet.APPLICATION_PARAMETER); length = value.length + 3; lengthArray[0] = (byte)(255 & (length >> 8)); @@ -629,6 +642,7 @@ public final class ObexHelper { lengthArray[1] = (byte)(255 & length); out.write(lengthArray); out.write(value); + if (VDBG) Log.v(TAG," Add Unicode String value = " + value); if (nullOut) { headImpl.setHeader(i + 0x30, null); } @@ -643,6 +657,7 @@ public final class ObexHelper { lengthArray[1] = (byte)(255 & length); out.write(lengthArray); out.write(value); + if (VDBG) Log.v(TAG," Add ByteSeq value = " + value); if (nullOut) { headImpl.setHeader(i + 0x70, null); } @@ -653,6 +668,7 @@ public final class ObexHelper { if (byteHeader != null) { out.write((byte)i + 0xB0); out.write(byteHeader.byteValue()); + if (VDBG) Log.v(TAG," Add ByteHeader value = " + byteHeader.byteValue()); if (nullOut) { headImpl.setHeader(i + 0xB0, null); } @@ -663,6 +679,7 @@ public final class ObexHelper { if (intHeader != null) { out.write((byte)i + 0xF0); out.write(ObexHelper.convertToByteArray(intHeader.longValue())); + if (VDBG) Log.v(TAG," Add Int value = " + intHeader.longValue()); if (nullOut) { headImpl.setHeader(i + 0xF0, null); } @@ -677,6 +694,7 @@ public final class ObexHelper { lengthArray[1] = (byte)(255 & length); out.write(lengthArray); out.write(headImpl.mAuthChall); + if (VDBG) Log.v(TAG," Add mAuthChall value = " + headImpl.mAuthChall); if (nullOut) { headImpl.mAuthChall = null; } @@ -690,6 +708,7 @@ public final class ObexHelper { lengthArray[1] = (byte)(255 & length); out.write(lengthArray); out.write(headImpl.mAuthResp); + if (VDBG) Log.v(TAG," Add mAuthChall value = " + headImpl.mAuthResp); if (nullOut) { headImpl.mAuthResp = null; } @@ -705,8 +724,10 @@ public final class ObexHelper { // Add the SRM header byteHeader = (Byte)headImpl.getHeader(HeaderSet.SINGLE_RESPONSE_MODE); if (byteHeader != null) { + if (VDBG) Log.v(TAG," Add SRM Header = " + HeaderSet.SINGLE_RESPONSE_MODE); out.write((byte)HeaderSet.SINGLE_RESPONSE_MODE); out.write(byteHeader.byteValue()); + if (VDBG) Log.v(TAG," Add SRM value = " + byteHeader.byteValue()); if (nullOut) { headImpl.setHeader(HeaderSet.SINGLE_RESPONSE_MODE, null); } @@ -715,6 +736,7 @@ public final class ObexHelper { // Add the SRM parameter header byteHeader = (Byte)headImpl.getHeader(HeaderSet.SINGLE_RESPONSE_MODE_PARAMETER); if (byteHeader != null) { + if (VDBG) Log.v(TAG," Add Header = " + HeaderSet.SINGLE_RESPONSE_MODE_PARAMETER); out.write((byte)HeaderSet.SINGLE_RESPONSE_MODE_PARAMETER); out.write(byteHeader.byteValue()); if (nullOut) { diff --git a/obex/javax/obex/ServerOperation.java b/obex/javax/obex/ServerOperation.java index 15ea36789e2c..1cc720b3a914 100644 --- a/obex/javax/obex/ServerOperation.java +++ b/obex/javax/obex/ServerOperation.java @@ -57,7 +57,7 @@ import android.util.Log; */ public final class ServerOperation implements Operation, BaseStream { - private static final String TAG = "ServerOperation"; + private static final String TAG = "ObexServerOperation"; private static final boolean V = ObexHelper.VDBG; // Verbose debugging @@ -124,6 +124,7 @@ public final class ServerOperation implements Operation, BaseStream { */ public ServerOperation(ServerSession p, InputStream in, int request, int maxSize, ServerRequestHandler listen) throws IOException { + if (V) Log.v(TAG, "ServerOperation"); isAborted = false; mParent = p; @@ -340,14 +341,17 @@ public final class ServerOperation implements Operation, BaseStream { */ public synchronized boolean continueOperation(boolean sendEmpty, boolean inStream) throws IOException { + if (V) Log.v(TAG, "continueOperation"); if (!mGetOperation) { if (!finalBitSet) { if (sendEmpty) { sendReply(ResponseCodes.OBEX_HTTP_CONTINUE); + if (V) Log.v(TAG, "continueOperation:ServerSet SRM sendEmpty clause"); return true; } else { if ((mResponseSize > 3) || (mPrivateOutput.size() > 0)) { sendReply(ResponseCodes.OBEX_HTTP_CONTINUE); + if (V) Log.v(TAG, "continueOperation: Server setting SRM"); return true; } else { return false; @@ -357,6 +361,7 @@ public final class ServerOperation implements Operation, BaseStream { return false; } } else { + if (V) Log.v(TAG, "Get continueOperation "); sendReply(ResponseCodes.OBEX_HTTP_CONTINUE); return true; } @@ -405,6 +410,8 @@ public final class ServerOperation implements Operation, BaseStream { bodyLength = mPrivateOutput.size(); orginalBodyLength = bodyLength; } + if(V) Log.v(TAG, "mMaxPcKLen :" + mMaxPacketLength + " headerArryLen :" + + headerArray.length); if ((ObexHelper.BASE_PACKET_LENGTH + headerArray.length) > mMaxPacketLength) { diff --git a/obex/javax/obex/ServerSession.java b/obex/javax/obex/ServerSession.java index dbfeefdfb037..a45687f766fc 100644 --- a/obex/javax/obex/ServerSession.java +++ b/obex/javax/obex/ServerSession.java @@ -63,6 +63,12 @@ public final class ServerSession extends ObexSession implements Runnable { private boolean mClosed; + private boolean setMTU = false; + + private boolean updateMtu = false; + + private int updatedMtuSize = 0; + /** * Creates new ServerSession. * @param trans the connection to the client @@ -85,6 +91,25 @@ public final class ServerSession extends ObexSession implements Runnable { mProcessThread.start(); } + public void setMaxPacketSize(int size) { + if (V) Log.v(TAG, "setMaxPacketSize" + size); + mMaxPacketLength = size; + } + + public int getMaxPacketSize() { + return mMaxPacketLength; + } + + public void reduceMTU(boolean enable) { + setMTU = enable; + } + + public void updateMTU(int mtuSize) { + updateMtu = true; + updatedMtuSize = mtuSize; + Log.i(TAG,"updateMTU: " + mtuSize); + } + /** * Processes requests made to the server and forwards them to the * appropriate event listener. @@ -124,6 +149,7 @@ public final class ServerSession extends ObexSession implements Runnable { break; case -1: + Log.d(TAG, "Read request returned -1, exiting from loop"); done = true; break; @@ -194,6 +220,7 @@ public final class ServerSession extends ObexSession implements Runnable { * @throws IOException if an error occurred at the transport layer */ private void handlePutRequest(int type) throws IOException { + if (V) Log.v(TAG, "handlePutRequest"); ServerOperation op = new ServerOperation(this, mInput, type, mMaxPacketLength, mListener); try { int response = -1; @@ -205,10 +232,12 @@ public final class ServerSession extends ObexSession implements Runnable { response = validateResponseCode(mListener.onPut(op)); } if (response != ResponseCodes.OBEX_HTTP_OK && !op.isAborted) { + if (V) Log.v(TAG, "handlePutRequest pre != HTTP_OK sendReply"); op.sendReply(response); } else if (!op.isAborted) { // wait for the final bit while (!op.finalBitSet) { + if (V) Log.v(TAG, "handlePutRequest pre looped sendReply"); op.sendReply(ResponseCodes.OBEX_HTTP_CONTINUE); } op.sendReply(response); @@ -240,6 +269,7 @@ public final class ServerSession extends ObexSession implements Runnable { * @throws IOException if an error occurred at the transport layer */ private void handleGetRequest(int type) throws IOException { + if (V) Log.v(TAG, "handleGetRequest"); ServerOperation op = new ServerOperation(this, mInput, type, mMaxPacketLength, mListener); try { int response = validateResponseCode(mListener.onGet(op)); @@ -262,6 +292,7 @@ public final class ServerSession extends ObexSession implements Runnable { public void sendResponse(int code, byte[] header) throws IOException { int totalLength = 3; byte[] data = null; + if (V) Log.v(TAG,"sendResponse code " + code + " header : " + header); OutputStream op = mOutput; if (op == null) { return; @@ -269,6 +300,7 @@ public final class ServerSession extends ObexSession implements Runnable { if (header != null) { totalLength += header.length; + if (V) Log.v(TAG, "header != null totalLength = " + totalLength); data = new byte[totalLength]; data[0] = (byte)code; data[1] = (byte)(totalLength >> 8); @@ -558,9 +590,19 @@ public final class ServerSession extends ObexSession implements Runnable { + " MaxLength: " + mMaxPacketLength + " flags: " + flags); // should we check it? - if (mMaxPacketLength > ObexHelper.MAX_PACKET_SIZE_INT) { + if (setMTU) { + mMaxPacketLength = ObexHelper.A2DP_SCO_OBEX_MAX_CLIENT_PACKET_SIZE; + setMTU = false; + } else if (updateMtu) { + Log.d(TAG, "mMaxPacketLength: " + mMaxPacketLength + + ", updatedMtuSize: " + updatedMtuSize); + if (mMaxPacketLength > updatedMtuSize) + mMaxPacketLength = updatedMtuSize; + updateMtu = false; + } else if (mMaxPacketLength > ObexHelper.MAX_PACKET_SIZE_INT) { mMaxPacketLength = ObexHelper.MAX_PACKET_SIZE_INT; } + Log.d(TAG,"handleConnectRequest() - Updated MaxPacketLengh: " + mMaxPacketLength); if(mMaxPacketLength > ObexHelper.getMaxTxPacketSize(mTransport)) { Log.w(TAG, "Requested MaxObexPacketSize " + mMaxPacketLength diff --git a/opengl/java/android/opengl/GLSurfaceView.java b/opengl/java/android/opengl/GLSurfaceView.java index 8a3e6a0b0fd5..cc67f55ed087 100644 --- a/opengl/java/android/opengl/GLSurfaceView.java +++ b/opengl/java/android/opengl/GLSurfaceView.java @@ -1570,6 +1570,10 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback if (view != null) { try { Trace.traceBegin(Trace.TRACE_TAG_VIEW, "onDrawFrame"); + if (mFinishDrawingRunnable != null) { + finishDrawingRunnable = mFinishDrawingRunnable; + mFinishDrawingRunnable = null; + } view.mRenderer.onDrawFrame(gl); if (finishDrawingRunnable != null) { finishDrawingRunnable.run(); diff --git a/packages/SettingsLib/res/values-en-rGB/arrays.xml b/packages/SettingsLib/res/values-en-rGB/arrays.xml index bd1a78ca1f0b..05c7030ec20e 100644 --- a/packages/SettingsLib/res/values-en-rGB/arrays.xml +++ b/packages/SettingsLib/res/values-en-rGB/arrays.xml @@ -77,6 +77,7 @@ <item msgid="5254942598247222737">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item> <item msgid="2091430979086738145">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item> <item msgid="6751080638867012696">"LDAC"</item> + <item msgid="8711430979086781450">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> audio"</item> <item msgid="723675059572222462">"Enable Optional Codecs"</item> <item msgid="3304843301758635896">"Disable Optional Codecs"</item> </string-array> @@ -87,6 +88,7 @@ <item msgid="7848030269621918608">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item> <item msgid="298198075927343893">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item> <item msgid="7950781694447359344">"LDAC"</item> + <item msgid="102988075927343894">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> audio"</item> <item msgid="2209680154067241740">"Enable Optional Codecs"</item> <item msgid="741805482892725657">"Disable Optional Codecs"</item> </string-array> diff --git a/packages/SettingsLib/res/values/arrays.xml b/packages/SettingsLib/res/values/arrays.xml index ed3c11cd3ca3..f30198c74bdb 100644 --- a/packages/SettingsLib/res/values/arrays.xml +++ b/packages/SettingsLib/res/values/arrays.xml @@ -140,6 +140,7 @@ <item><xliff:g id="qualcomm">Qualcomm®</xliff:g> <xliff:g id="aptx">aptX™</xliff:g> audio</item> <item><xliff:g id="qualcomm">Qualcomm®</xliff:g> <xliff:g id="aptx_hd">aptX™ HD</xliff:g> audio</item> <item>LDAC</item> + <item><xliff:g id="qualcomm">Qualcomm®</xliff:g> <xliff:g id="aptx_adaptive">aptX™ Adaptive</xliff:g> audio</item> <item>Enable Optional Codecs</item> <item>Disable Optional Codecs</item> </string-array> @@ -164,6 +165,7 @@ <item><xliff:g id="qualcomm">Qualcomm®</xliff:g> <xliff:g id="aptx">aptX™</xliff:g> audio</item> <item><xliff:g id="qualcomm">Qualcomm®</xliff:g> <xliff:g id="aptx_hd">aptX™ HD</xliff:g> audio</item> <item>LDAC</item> + <item><xliff:g id="qualcomm">Qualcomm®</xliff:g> <xliff:g id="aptx_adaptive">aptX™ Adaptive</xliff:g> audio</item> <item>Enable Optional Codecs</item> <item>Disable Optional Codecs</item> </string-array> diff --git a/packages/SettingsLib/res/values/attrs.xml b/packages/SettingsLib/res/values/attrs.xml index 9aed54e12a2d..499f00fa379c 100644 --- a/packages/SettingsLib/res/values/attrs.xml +++ b/packages/SettingsLib/res/values/attrs.xml @@ -33,6 +33,12 @@ <attr name="restrictedSwitchSummary" format="reference" /> </declare-styleable> + <declare-styleable name="WifiEncryptionStateOwe"> + <attr name="state_encrypted_owe" format="boolean" /> + </declare-styleable> + <declare-styleable name="WifiEncryptionStateSae"> + <attr name="state_encrypted_sae" format="boolean" /> + </declare-styleable> <declare-styleable name="WifiEncryptionState"> <attr name="state_encrypted" format="boolean" /> </declare-styleable> diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml index c8f8d737fb0e..df1ff654230a 100644 --- a/packages/SettingsLib/res/values/strings.xml +++ b/packages/SettingsLib/res/values/strings.xml @@ -32,6 +32,8 @@ <string name="wifi_security_short_psk_generic" translatable="false">@string/wifi_security_short_wpa_wpa2</string> <!-- Do not translate. Concise terminology for wifi with 802.1x EAP security --> <string name="wifi_security_short_eap" translatable="false">802.1x</string> + <!-- Do not translate. Concise terminology for wifi with DPP security --> + <string name="wifi_security_short_dpp" translatable="false">DPP</string> <!-- Do not translate. Concise terminology for wifi with WPA3 security --> <string name="wifi_security_short_sae" translatable="false">WPA3</string> <!-- Do not translate. Concise terminology for wifi with OWE security --> @@ -56,6 +58,8 @@ <string name="wifi_security_eap" translatable="false">WPA/WPA2-Enterprise</string> <!-- Do not translate. Concise terminology for Passpoint network --> <string name="wifi_security_passpoint" translatable="false">Passpoint</string> + <!-- Do not translate. Concise terminology for DPP network --> + <string name="wifi_security_dpp" translatable="false">DPP</string> <!-- Do not translate. Terminology for wifi with WPA3 security --> <string name="wifi_security_sae" translatable="false">WPA3-Personal</string> <!-- Do not translate. Terminology for wifi with OWE security --> @@ -272,6 +276,8 @@ <string name="bluetooth_profile_map">Text Messages</string> <!-- Bluetooth settings. The user-visible string that is used whenever referring to the SAP profile (sharing SIM card). --> <string name="bluetooth_profile_sap">SIM Access</string> + <!-- Bluetooth settings. The user-visible string that is used whenever referring to the dun profile. --> + <string name="bluetooth_profile_dun">Dial-up Network Access</string> <!-- Bluetooth settings. The user-visible string for the setting controlling whether to use a high-quality codec if the device supports it, along with the name of the codec (eg AAC, LDAC, aptX) --> <string name="bluetooth_profile_a2dp_high_quality">HD audio: <xliff:g id="codec_name">%1$s</xliff:g></string> @@ -302,6 +308,8 @@ <string name="bluetooth_pan_user_profile_summary_connected">Connected to device for internet access</string> <!-- Bluetooth settings. Connection options screen. The summary for the checkbox preference when PAN is connected (NAP role). [CHAR LIMIT=25]--> <string name="bluetooth_pan_nap_profile_summary_connected">Sharing local internet connection with device</string> + <!-- Bluetooth settings. Connection options screen. The summary for the DUN checkbox preference when DUN is connected. --> + <string name="bluetooth_dun_profile_summary_connected">Connected to Dun Server</string> <!-- Bluetooth settings. Connection options screen. The summary for the PAN checkbox preference that describes how checking it @@ -323,6 +331,8 @@ <string name="bluetooth_hid_profile_summary_use_for">Use for input</string> <!-- Bluetooth settings. Connection options screen. The summary for the Hearing Aid checkbox preference that describes how checking it will set the Hearing Aid profile as preferred. --> <string name="bluetooth_hearing_aid_profile_summary_use_for">Use for Hearing Aid</string> + <!-- Bluetooth settings. Connection options screen. The summary for the dun checkbox preference that describes how checking it will set the dun profile as preferred. --> + <string name="bluetooth_dun_profile_summary_use_for">Use for Dial-up Network access</string> <!-- Button text for accepting an incoming pairing request. [CHAR LIMIT=20] --> <string name="bluetooth_pairing_accept">Pair</string> @@ -614,6 +624,8 @@ <!-- Setting Checkbox title whether to show options for wireless display certification --> <string name="wifi_display_certification">Wireless display certification</string> + <!-- Setting Checkbox title whether to enable WiFi coverage extending feature. --> + <string name="wifi_coverage_extend">Enable Wi\u2011Fi Coverage Extend Feature</string> <!-- Setting Checkbox title whether to enable WiFi Verbose Logging. [CHAR LIMIT=40] --> <string name="wifi_verbose_logging">Enable Wi\u2011Fi Verbose Logging</string> <!-- Setting Checkbox title whether to enable connected MAC randomization --> @@ -671,6 +683,8 @@ <!-- setting Checkbox summary whether to show options for wireless display certification --> <string name="wifi_display_certification_summary">Show options for wireless display certification</string> + <!-- Setting Checkbox summary whether to enable WiFi coverage extending feature. --> + <string name="wifi_coverage_extend_summary">Enable extending Wi\u2011Fi coverage using Hotspot</string> <!-- Setting Checkbox summary whether to enable Wifi verbose Logging [CHAR LIMIT=80] --> <string name="wifi_verbose_logging_summary">Increase Wi\u2011Fi logging level, show per SSID RSSI in Wi\u2011Fi Picker</string> <!-- Setting Checkbox title whether to enable connected MAC randomization --> diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java index 24d7011d9a35..4c3fcba6122e 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java @@ -259,6 +259,9 @@ public class A2dpProfile implements LocalBluetoothProfile { case BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC: index = 5; break; + case BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_ADAPTIVE: + index = 6; + break; } if (index < 0) { diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java index e28c894ff8f3..29a5bdb4d64d 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java @@ -29,6 +29,7 @@ import android.os.SystemClock; import android.text.TextUtils; import android.util.Log; +import android.os.SystemProperties; import androidx.annotation.VisibleForTesting; import com.android.settingslib.R; @@ -98,6 +99,22 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> mHiSyncId = BluetoothHearingAid.HI_SYNC_ID_INVALID; } + /* Gets Device for seondary TWS device + * @param mDevice Primary TWS device to get secondary + * @return Description of the device + */ + + private BluetoothDevice getTwsPeerDevice() { + BluetoothAdapter bluetoothAdapter; + BluetoothDevice peerDevice = null; + if (mDevice.isTwsPlusDevice()) { + bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); + String peerAddress = mDevice.getTwsPlusPeerAddress(); + peerDevice = bluetoothAdapter.getRemoteDevice(peerAddress); + } + return peerDevice; + } + /** * Describes the current device and profile for logging. * @@ -315,6 +332,17 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> if (state != BluetoothDevice.BOND_NONE) { final BluetoothDevice dev = mDevice; + if (mDevice.isTwsPlusDevice()) { + BluetoothDevice peerDevice = getTwsPeerDevice(); + if (peerDevice != null) { + final boolean peersuccessful = peerDevice.removeBond(); + if (peersuccessful) { + if (BluetoothUtils.D) { + Log.d(TAG, "Command sent successfully:REMOVE_BOND " + peerDevice.getName()); + } + } + } + } if (dev != null) { final boolean successful = dev.removeBond(); if (successful) { @@ -641,8 +669,13 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> if (bondState == BluetoothDevice.BOND_BONDED) { if (mDevice.isBluetoothDock()) { onBondingDockConnect(); + } else if (SystemProperties.getBoolean("persist.vendor.btstack.connect.peer_earbud", false)) { + Log.d(TAG, "Initiating connection to" + mDevice); + if (mDevice.isBondingInitiatedLocally() || mDevice.isTwsPlusDevice()) { + connect(false); + } } else if (mDevice.isBondingInitiatedLocally()) { - connect(false); + connect(false); } } } @@ -795,10 +828,11 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> // The pairing dialog now warns of phone-book access for paired devices. // No separate prompt is displayed after pairing. if (mDevice.getPhonebookAccessPermission() == BluetoothDevice.ACCESS_UNKNOWN) { - if (mDevice.getBluetoothClass().getDeviceClass() + if ((mDevice.getBluetoothClass() != null) && + (mDevice.getBluetoothClass().getDeviceClass() == BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE || mDevice.getBluetoothClass().getDeviceClass() - == BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET) { + == BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET)) { mDevice.setPhonebookAccessPermission(BluetoothDevice.ACCESS_ALLOWED); } else { mDevice.setPhonebookAccessPermission(BluetoothDevice.ACCESS_REJECTED); @@ -1023,8 +1057,16 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> */ public boolean isConnectedA2dpDevice() { A2dpProfile a2dpProfile = mProfileManager.getA2dpProfile(); - return a2dpProfile != null && a2dpProfile.getConnectionStatus(mDevice) == + A2dpSinkProfile a2dpSinkProfile = mProfileManager.getA2dpSinkProfile(); + Log.i(TAG, "a2dpProfile :" + a2dpProfile + " a2dpSinkProfile :" + a2dpSinkProfile); + if (a2dpProfile != null) { + return a2dpProfile.getConnectionStatus(mDevice) == + BluetoothProfile.STATE_CONNECTED; + } else if (a2dpSinkProfile != null) { + return a2dpSinkProfile.getConnectionStatus(mDevice) == BluetoothProfile.STATE_CONNECTED; + } + return false; } /** diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java index 5b4a8b4f259e..581decdcb924 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java @@ -192,6 +192,13 @@ public class CachedBluetoothDeviceManager { } } + public synchronized void clearAllDevices() { + for (int i = mCachedDevices.size() - 1; i >= 0; i--) { + CachedBluetoothDevice cachedDevice = mCachedDevices.get(i); + mCachedDevices.remove(i); + } + } + public synchronized void onScanningStateChanged(boolean started) { if (!started) return; // If starting a new scan, clear old visibility diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/DunServerProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/DunServerProfile.java new file mode 100644 index 000000000000..007af04d4dcf --- /dev/null +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/DunServerProfile.java @@ -0,0 +1,167 @@ +/* +*Copyright (c) 2013, 2015, The Linux Foundation. All rights reserved. +* +*Redistribution and use in source and binary forms, with or without +*modification, are permitted provided that the following conditions are +*met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of The Linux Foundation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +*THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +*WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +*MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +*ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +*BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +*CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +*SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +*BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +*WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +*OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +*IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.android.settingslib.bluetooth; + +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothClass; +import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothDun; +import android.bluetooth.BluetoothProfile; +import android.content.Context; +import android.util.Log; +import java.util.HashMap; +import java.util.List; + +import com.android.settingslib.R; + +/** + * DunServerProfile handles Bluetooth DUN server profile. + */ +public final class DunServerProfile implements LocalBluetoothProfile { + private static final String TAG = "DunServerProfile"; + private static boolean V = true; + + private BluetoothDun mService; + private boolean mIsProfileReady; + + static final String NAME = "DUN Server"; + + // Order of this profile in device profiles list + private static final int ORDINAL = 11; + + // These callbacks run on the main thread. + private final class DunServiceListener + implements BluetoothProfile.ServiceListener { + + public void onServiceConnected(int profile, BluetoothProfile proxy) { + if (V) Log.d(TAG,"Bluetooth service connected"); + mService = (BluetoothDun) proxy; + mIsProfileReady = true; + } + + public void onServiceDisconnected(int profile) { + if (V) Log.d(TAG,"Bluetooth service disconnected"); + mIsProfileReady = false; + } + } + + public boolean isProfileReady() { + return mIsProfileReady; + } + + @Override + public int getProfileId() { + return BluetoothProfile.DUN; + } + + DunServerProfile(Context context) { + BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); + adapter.getProfileProxy(context, new DunServiceListener(), + BluetoothProfile.DUN); + } + + public boolean accessProfileEnabled() { + return true; + } + + public boolean isAutoConnectable() { + return false; + } + + public boolean connect(BluetoothDevice device) { + return false; + } + + public boolean disconnect(BluetoothDevice device) { + if (mService == null) return false; + return mService.disconnect(device); + } + + public int getConnectionStatus(BluetoothDevice device) { + if (mService == null) { + return BluetoothProfile.STATE_DISCONNECTED; + } + return mService.getConnectionState(device); + } + + public boolean isPreferred(BluetoothDevice device) { + return true; + } + + public int getPreferred(BluetoothDevice device) { + return -1; + } + + public void setPreferred(BluetoothDevice device, boolean preferred) { + // ignore: isPreferred is always true for DUN + } + + public String toString() { + return NAME; + } + + public int getOrdinal() { + return ORDINAL; + } + + public int getNameResource(BluetoothDevice device) { + return R.string.bluetooth_profile_dun; + } + + public int getSummaryResourceForDevice(BluetoothDevice device) { + int state = getConnectionStatus(device); + switch (state) { + case BluetoothProfile.STATE_DISCONNECTED: + return R.string.bluetooth_dun_profile_summary_use_for; + + case BluetoothProfile.STATE_CONNECTED: + return R.string.bluetooth_dun_profile_summary_connected; + default: + return BluetoothUtils.getConnectionStateSummary(state); + } + } + + public int getDrawableResource(BluetoothClass btClass) { + return R.drawable.ic_bt_network_pan; + } + + protected void finalize() { + if (V) Log.d(TAG, "finalize()"); + if (mService != null) { + try { + BluetoothAdapter.getDefaultAdapter().closeProfileProxy + (BluetoothProfile.DUN, mService); + mService = null; + } catch (Throwable t) { + Log.w(TAG, "Error cleaning up DUN proxy", t); + } + } + } +} diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java index 29c6d719641a..b18a6d596c46 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java @@ -30,6 +30,7 @@ import android.bluetooth.BluetoothMapClient; import android.bluetooth.BluetoothPan; import android.bluetooth.BluetoothPbap; import android.bluetooth.BluetoothPbapClient; +import android.bluetooth.BluetoothDun; import android.bluetooth.BluetoothSap; import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothUuid; @@ -47,6 +48,7 @@ import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; +import android.os.SystemProperties; /** @@ -97,6 +99,7 @@ public class LocalBluetoothProfileManager { private PanProfile mPanProfile; private PbapClientProfile mPbapClientProfile; private PbapServerProfile mPbapProfile; + private DunServerProfile mDunProfile; private HearingAidProfile mHearingAidProfile; private SapProfile mSapProfile; @@ -218,6 +221,12 @@ public class LocalBluetoothProfileManager { mSapProfile = new SapProfile(mContext, mDeviceManager, this); addProfile(mSapProfile, SapProfile.NAME, BluetoothSap.ACTION_CONNECTION_STATE_CHANGED); } + if (mDunProfile == null && supportedList.contains(BluetoothProfile.DUN)) { + if(DEBUG) Log.d(TAG, "Adding local DUN profile"); + mDunProfile = new DunServerProfile(mContext); + addProfile(mDunProfile, DunServerProfile.NAME, + BluetoothDun.ACTION_CONNECTION_STATE_CHANGED); + } mEventManager.registerProfileIntentReceiver(); } @@ -267,6 +276,11 @@ public class LocalBluetoothProfileManager { } public void onReceive(Context context, Intent intent, BluetoothDevice device) { + if (device == null) { + Log.w(TAG, "StateChangedHandler receives state-change for invalid device"); + return; + } + CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device); if (cachedDevice == null) { Log.w(TAG, "StateChangedHandler found new device: " + device); @@ -474,7 +488,8 @@ public class LocalBluetoothProfileManager { if ((BluetoothUuid.isUuidPresent(localUuids, BluetoothUuid.HSP_AG) && BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.HSP)) || (BluetoothUuid.isUuidPresent(localUuids, BluetoothUuid.Handsfree_AG) && - BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.Handsfree))) { + BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.Handsfree)) || + (mHeadsetProfile.getConnectionStatus(device) == BluetoothProfile.STATE_CONNECTED)) { profiles.add(mHeadsetProfile); removedProfiles.remove(mHeadsetProfile); } @@ -487,10 +502,12 @@ public class LocalBluetoothProfileManager { removedProfiles.remove(mHfpClientProfile); } - if (BluetoothUuid.containsAnyUuid(uuids, A2dpProfile.SINK_UUIDS) && - mA2dpProfile != null) { - profiles.add(mA2dpProfile); - removedProfiles.remove(mA2dpProfile); + if (mA2dpProfile != null) { + if (BluetoothUuid.containsAnyUuid(uuids, A2dpProfile.SINK_UUIDS) || + (mA2dpProfile.getConnectionStatus(device) == BluetoothProfile.STATE_CONNECTED)) { + profiles.add(mA2dpProfile); + removedProfiles.remove(mA2dpProfile); + } } if (BluetoothUuid.containsAnyUuid(uuids, A2dpSinkProfile.SRC_UUIDS) && diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java index 27dc628ac094..6b3432116c07 100644 --- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java +++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java @@ -168,7 +168,8 @@ public class AccessPoint implements Comparable<AccessPoint> { public static final int SECURITY_OWE = 4; public static final int SECURITY_SAE = 5; public static final int SECURITY_EAP_SUITE_B = 6; - public static final int SECURITY_MAX_VAL = 7; // Has to be the last + public static final int SECURITY_DPP = 7; + public static final int SECURITY_MAX_VAL = 8; // Has to be the last private static final int PSK_UNKNOWN = 0; private static final int PSK_WPA = 1; @@ -680,6 +681,74 @@ public class AccessPoint implements Comparable<AccessPoint> { networkId = WifiConfiguration.INVALID_NETWORK_ID; } + public boolean isFils256Supported() { + IWifiManager wifiManager = IWifiManager.Stub.asInterface( + ServiceManager.getService(Context.WIFI_SERVICE)); + String capability = ""; + + try { + capability = wifiManager.getCapabilities("key_mgmt"); + } catch (RemoteException e) { + Log.w(TAG, "Remote Exception", e); + } + + if (!capability.contains("FILS-SHA256")) { + return false; + } + + for (ScanResult result : mScanResults) { + if (result.capabilities.contains("FILS-SHA256")) { + return true; + } + } + return false; + } + + public boolean isSuiteBSupported() { + IWifiManager wifiManager = IWifiManager.Stub.asInterface( + ServiceManager.getService(Context.WIFI_SERVICE)); + String capability = ""; + + try { + capability = wifiManager.getCapabilities("key_mgmt"); + } catch (RemoteException e) { + Log.w(TAG, "Remote Exception", e); + } + + if (!capability.contains("WPA-EAP-SUITE-B-192")) { + return false; + } + + for (ScanResult result : mScanResults) { + if (result.capabilities.contains("EAP_SUITE_B_192")) { + return true; + } + } + return false; + } + public boolean isFils384Supported() { + IWifiManager wifiManager = IWifiManager.Stub.asInterface( + ServiceManager.getService(Context.WIFI_SERVICE)); + String capability = ""; + + try { + capability = wifiManager.getCapabilities("key_mgmt"); + } catch (RemoteException e) { + Log.w(TAG, "Remote Exception", e); + } + + if (!capability.contains("FILS-SHA384")) { + return false; + } + + for (ScanResult result : mScanResults) { + if (result.capabilities.contains("FILS-SHA384")) { + return true; + } + } + return false; + } + public WifiInfo getInfo() { return mInfo; } @@ -785,6 +854,9 @@ public class AccessPoint implements Comparable<AccessPoint> { case SECURITY_WEP: return concise ? context.getString(R.string.wifi_security_short_wep) : context.getString(R.string.wifi_security_wep); + case SECURITY_DPP: + return concise ? context.getString(R.string.wifi_security_short_dpp) : + context.getString(R.string.wifi_security_dpp); case SECURITY_SAE: return concise ? context.getString(R.string.wifi_security_short_sae) : context.getString(R.string.wifi_security_sae); @@ -1408,7 +1480,13 @@ public class AccessPoint implements Comparable<AccessPoint> { } private static int getSecurity(ScanResult result) { - if (result.capabilities.contains("WEP")) { + if (result.capabilities.contains("DPP")) { + return SECURITY_DPP; + } else if (result.capabilities.contains("SAE")) { + return SECURITY_SAE; + } else if (result.capabilities.contains("OWE")) { + return SECURITY_OWE; + } else if (result.capabilities.contains("WEP")) { return SECURITY_WEP; } else if (result.capabilities.contains("SAE")) { return SECURITY_SAE; @@ -1439,6 +1517,9 @@ public class AccessPoint implements Comparable<AccessPoint> { config.allowedKeyManagement.get(KeyMgmt.IEEE8021X)) { return SECURITY_EAP; } + if (config.allowedKeyManagement.get(KeyMgmt.DPP)) { + return SECURITY_DPP; + } if (config.allowedKeyManagement.get(KeyMgmt.OWE)) { return SECURITY_OWE; } @@ -1459,6 +1540,8 @@ public class AccessPoint implements Comparable<AccessPoint> { return "PSK"; } else if (security == SECURITY_EAP) { return "EAP"; + } else if (security == SECURITY_DPP) { + return "DPP"; } else if (security == SECURITY_SAE) { return "SAE"; } else if (security == SECURITY_EAP_SUITE_B) { diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java index 1fa7083498e1..a24a94344cd0 100644 --- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java +++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java @@ -43,6 +43,14 @@ import com.android.settingslib.wifi.AccessPoint.Speed; public class AccessPointPreference extends Preference { + private static final int[] STATE_SECURED_OWE = { + R.attr.state_encrypted_owe + }; + + private static final int[] STATE_SECURED_SAE = { + R.attr.state_encrypted_sae + }; + private static final int[] STATE_SECURED = { R.attr.state_encrypted }; @@ -200,7 +208,9 @@ public class AccessPointPreference extends Preference { if (frictionImageView == null || mFrictionSld == null) { return; } - if ((mAccessPoint.getSecurity() != AccessPoint.SECURITY_NONE) + if (mAccessPoint.getSecurity() == AccessPoint.SECURITY_SAE) { + mFrictionSld.setState(STATE_SECURED_SAE); + } else if ((mAccessPoint.getSecurity() != AccessPoint.SECURITY_NONE) && (mAccessPoint.getSecurity() != AccessPoint.SECURITY_OWE)) { mFrictionSld.setState(STATE_SECURED); } else if (mAccessPoint.isMetered()) { diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java index b9a5f2347f16..9a03fffd3287 100644 --- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java +++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java @@ -837,6 +837,7 @@ public class WifiTracker implements LifecycleObserver, OnStart, OnStop, OnDestro @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); + sVerboseLogging = (mWifiManager.getVerboseLoggingLevel() > 0); if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action)) { updateWifiState( diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpProfileTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpProfileTest.java index c555cbec4bab..58afca4dd4fc 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpProfileTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpProfileTest.java @@ -129,7 +129,7 @@ public class A2dpProfileTest { private static String KNOWN_CODEC_LABEL = "Use high quality audio: %1$s"; private static String UNKNOWN_CODEC_LABEL = "Use high quality audio"; private static String[] CODEC_NAMES = - new String[]{"Default", "SBC", "AAC", "aptX", "aptX HD", "LDAC"}; + new String[] { "Default", "SBC", "AAC", "aptX", "aptX HD", "LDAC", "aptX Adaptive" }; /** * Helper for setting up several tests of getHighQualityAudioOptionLabel diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/PowerWhitelistBackendTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/PowerWhitelistBackendTest.java index bbf807d29402..a8acecb16ce0 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/PowerWhitelistBackendTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/PowerWhitelistBackendTest.java @@ -65,6 +65,7 @@ public class PowerWhitelistBackendTest { MockitoAnnotations.initMocks(this); mContext = spy(RuntimeEnvironment.application); doReturn(mContext).when(mContext).getApplicationContext(); + doReturn(mDevicePolicyManager).when(mContext).getSystemService(DevicePolicyManager.class); doReturn(new String[] {}).when(mDeviceIdleService).getFullPowerWhitelist(); doReturn(new String[] {}).when(mDeviceIdleService).getSystemPowerWhitelist(); doReturn(new String[] {}).when(mDeviceIdleService).getSystemPowerWhitelistExceptIdle(); diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml index de86789053e9..3f57a3e33ef0 100644 --- a/packages/SettingsProvider/res/values/defaults.xml +++ b/packages/SettingsProvider/res/values/defaults.xml @@ -218,6 +218,9 @@ <!-- Default for Settings.System.VIBRATE_WHEN_RINGING --> <bool name="def_vibrate_when_ringing">false</bool> + <!-- Default for Settings.Global.NTP_SERVER_2's property name --> + <string name="def_ntp_server_2" translatable="false">persist.vendor.ntp.svr_2</string> + <!-- Default for Settings.Secure.CHARGING_VIBRATION_ENABLED --> <bool name="def_charging_vibration_enabled">true</bool> diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java index ef90dc981870..e5156b1591b2 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java @@ -2582,8 +2582,8 @@ class DatabaseHelper extends SQLiteOpenHelper { for (int phoneId = 0; phoneId < TelephonyManager.getDefault().getPhoneCount(); phoneId++) { mode = TelephonyManager.getTelephonyProperty(phoneId, - "ro.telephony.default_network", - Integer.toString(RILConstants.PREFERRED_NETWORK_MODE)); + "ro.telephony.default_network", + Integer.toString(RILConstants.NETWORK_MODE_WCDMA_PREF)); if (phoneId == 0) { val = mode; } else { @@ -2609,6 +2609,9 @@ class DatabaseHelper extends SQLiteOpenHelper { loadSetting(stmt, Settings.Global.DEVICE_NAME, getDefaultDeviceName()); + loadStringSetting(stmt, Settings.Global.NTP_SERVER_2, + R.string.def_ntp_server_2); + /* * IMPORTANT: Do not add any more upgrade steps here as the global, * secure, and system settings are no longer stored in a database diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java index e843eb43a3a6..edc96876467e 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java @@ -1040,6 +1040,9 @@ class SettingsProtoDumpUtil { dumpSetting(s, p, Settings.Global.NTP_TIMEOUT, GlobalSettingsProto.Ntp.TIMEOUT_MS); + dumpSetting(s, p, + Settings.Global.NTP_SERVER_2, + GlobalSettingsProto.Ntp.SERVER_2); p.end(ntpToken); final long uasbToken = p.start(GlobalSettingsProto.USER_ABSENT_SMALL_BATTERY); diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java index 5105ff46703d..0e277b3ce416 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java @@ -4135,6 +4135,16 @@ public class SettingsProvider extends ContentProvider { null, true, SettingsState.SYSTEM_PACKAGE_NAME); } + // Update the settings for NTP_SERVER_2 + final Setting currentSetting = globalSettings.getSettingLocked( + Global.NTP_SERVER_2); + if (currentSetting.isNull()) { + globalSettings.insertSettingLocked( + Global.NTP_SERVER_2, + getContext().getResources().getString( + R.string.def_ntp_server_2), + null, true, SettingsState.SYSTEM_PACKAGE_NAME); + } currentVersion = 170; } diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp index 8be67d9a7a51..7354a2d6114b 100644 --- a/packages/SystemUI/Android.bp +++ b/packages/SystemUI/Android.bp @@ -65,7 +65,11 @@ android_library { manifest: "AndroidManifest.xml", libs: [ + "android.car", + "android.car.userlib", "telephony-common", + "telephony-ext", + "ims-common", ], aaptflags: [ @@ -108,6 +112,7 @@ android_library { "androidx.slice_slice-builders", "androidx.arch.core_core-runtime", "androidx.lifecycle_lifecycle-extensions", + "qtiNetworkLib", "SystemUI-tags", "SystemUI-proto", "metrics-helper-lib", @@ -122,6 +127,8 @@ android_library { "android.test.runner", "telephony-common", "android.test.base", + "telephony-ext", + "ims-common", ], aaptflags: [ "--extra-packages", @@ -146,7 +153,11 @@ android_app { }, libs: [ + "android.car", + "android.car.userlib", + "ims-common", "telephony-common", + "telephony-ext", ], dxflags: ["--multi-dex"], diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml index b4f2711ef9d2..53a524ff96fb 100644 --- a/packages/SystemUI/AndroidManifest.xml +++ b/packages/SystemUI/AndroidManifest.xml @@ -70,6 +70,7 @@ <uses-permission android:name="android.permission.REQUEST_NETWORK_SCORES" /> <uses-permission android:name="android.permission.CONTROL_VPN" /> <uses-permission android:name="android.permission.PEERS_MAC_ADDRESS"/> + <uses-permission android:name="android.permission.NETWORK_STACK"/> <!-- Physical hardware --> <uses-permission android:name="android.permission.MANAGE_USB" /> <uses-permission android:name="android.permission.CONTROL_DISPLAY_BRIGHTNESS" /> diff --git a/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml b/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml index 44f06a64bf1d..2472b2e54272 100644 --- a/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml +++ b/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml @@ -106,6 +106,10 @@ <item quantity="other">SIM 卡 PIN 码不正确,您还有 <xliff:g id="NUMBER_1">%d</xliff:g> 次尝试机会。</item> <item quantity="one">SIM 卡 PIN 码不正确,您还有 <xliff:g id="NUMBER_0">%d</xliff:g> 次尝试机会。如果仍不正确,则需要联系运营商帮您解锁设备。</item> </plurals> + <plurals name="kg_password_wrong_pin_code_multi_sim" formatted="false"> + <item quantity="other">SIM 卡<xliff:g id="slotid">%d</xliff:g> PIN 码不正确,您还有 <xliff:g id="NUMBER_1">%d</xliff:g> 次尝试机会。</item> + <item quantity="one">SIM 卡<xliff:g id="slotid">%d</xliff:g> PIN 码不正确,您还有 <xliff:g id="NUMBER_0">%d</xliff:g> 次尝试机会。如果仍不正确,则需要联系运营商帮您解锁设备。</item> + </plurals> <string name="kg_password_wrong_puk_code_dead" msgid="3329017604125179374">"SIM 卡无法使用,请与您的运营商联系。"</string> <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="2287504898931957513"> <item quantity="other">SIM 卡 PUK 码不正确,您还有 <xliff:g id="NUMBER_1">%d</xliff:g> 次尝试机会。如果仍不正确,SIM 卡将永远无法使用。</item> @@ -146,6 +150,10 @@ <item quantity="other">请输入 SIM 卡 PIN 码,您还可以尝试 <xliff:g id="NUMBER_1">%d</xliff:g> 次。</item> <item quantity="one">请输入 SIM 卡 PIN 码,您还可以尝试 <xliff:g id="NUMBER_0">%d</xliff:g> 次。如果仍不正确,则需要联系运营商帮您解锁设备。</item> </plurals> + <plurals name="kg_password_default_pin_message_multi_sim" formatted="false"> + <item quantity="other">请输入 SIM 卡<xliff:g id="slotid">%d</xliff:g> PIN 码,您还可以尝试 <xliff:g id="NUMBER_1">%d</xliff:g> 次。</item> + <item quantity="one">请输入 SIM 卡<xliff:g id="slotid">%d</xliff:g> PIN 码,您还可以尝试 <xliff:g id="NUMBER_0">%d</xliff:g> 次。如果仍不正确,则需要联系运营商帮您解锁设备。</item> + </plurals> <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> <item quantity="other">SIM 卡现已停用,请输入 PUK 码继续使用。您还可以尝试 <xliff:g id="_NUMBER_1">%d</xliff:g> 次。如果仍不正确,该 SIM 卡将永远无法使用。有关详情,请联系您的运营商。</item> <item quantity="one">SIM 卡现已停用,请输入 PUK 码继续使用。您还可以尝试 <xliff:g id="_NUMBER_0">%d</xliff:g> 次。如果仍不正确,该 SIM 卡将永远无法使用。有关详情,请联系您的运营商。</item> diff --git a/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml b/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml index 364f126b591b..ad3e8df1ba9b 100644 --- a/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml +++ b/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml @@ -106,6 +106,10 @@ <item quantity="other">SIM 卡的 PIN 碼不正確,您還有 <xliff:g id="NUMBER_1">%d</xliff:g> 次輸入機會。</item> <item quantity="one">SIM 卡的 PIN 碼不正確,您還有 <xliff:g id="NUMBER_0">%d</xliff:g> 次輸入機會。如果仍然輸入錯誤,您必須聯絡流動網絡供應商為您的裝置解鎖。</item> </plurals> + <plurals name="kg_password_wrong_pin_code_multi_sim" formatted="false"> + <item quantity="other">SIM 卡<xliff:g id="slotid">%d</xliff:g>的 PIN 碼不正確,您還有 <xliff:g id="NUMBER_1">%d</xliff:g> 次輸入機會。</item> + <item quantity="one">SIM 卡<xliff:g id="slotid">%d</xliff:g>的 PIN 碼不正確,您還有 <xliff:g id="NUMBER_0">%d</xliff:g> 次輸入機會。如果仍然輸入錯誤,您必須聯絡流動網絡供應商為您的裝置解鎖。</item> + </plurals> <string name="kg_password_wrong_puk_code_dead" msgid="3329017604125179374">"SIM 卡無法使用,請聯絡您的流動網絡供應商。"</string> <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="2287504898931957513"> <item quantity="other">SIM 卡的 PUK 碼不正確,您還有 <xliff:g id="NUMBER_1">%d</xliff:g> 次輸入機會。如果仍然輸入錯誤,SIM 卡將永久無法使用。</item> @@ -146,6 +150,10 @@ <item quantity="other">輸入 SIM 卡的 PIN,您還可以再試 <xliff:g id="NUMBER_1">%d</xliff:g> 次。</item> <item quantity="one">輸入 SIM 卡的 PIN,您還可以再試 <xliff:g id="NUMBER_0">%d</xliff:g> 次。如果仍然輸入錯誤,您必須聯絡流動網絡供應商解鎖您的裝置。</item> </plurals> + <plurals name="kg_password_default_pin_message_multi_sim" formatted="false"> + <item quantity="other">輸入 SIM 卡<xliff:g id="slotid">%d</xliff:g>的 PIN,您還可以再試 <xliff:g id="NUMBER_1">%d</xliff:g> 次。</item> + <item quantity="one">輸入 SIM 卡<xliff:g id="slotid">%d</xliff:g>的 PIN,您還可以再試 <xliff:g id="NUMBER_0">%d</xliff:g> 次。如果仍然輸入錯誤,您必須聯絡流動網絡供應商解鎖您的裝置。</item> + </plurals> <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> <item quantity="other">SIM 卡已停用。請輸入 PUK 碼以繼續進行。您還可以再試 <xliff:g id="_NUMBER_1">%d</xliff:g> 次。如果仍然輸入錯誤,SIM 卡將永久無法使用。詳情請與流動網絡供應商聯絡。</item> <item quantity="one">SIM 卡已停用。請輸入 PUK 碼以繼續進行。您還可以再試 <xliff:g id="_NUMBER_0">%d</xliff:g> 次。如果仍然輸入錯誤,SIM 卡將永久無法使用。詳情請與流動網絡供應商聯絡。</item> diff --git a/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml b/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml index f687397bcf5d..8e4caa24efaf 100644 --- a/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml +++ b/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml @@ -106,6 +106,10 @@ <item quantity="other">SIM 卡的 PIN 碼輸入錯誤,你還可以再試 <xliff:g id="NUMBER_1">%d</xliff:g> 次。</item> <item quantity="one">SIM 卡的 PIN 碼輸入錯誤,你還可以再試 <xliff:g id="NUMBER_0">%d</xliff:g> 次。如果仍然失敗,就必須請電信業者為裝置解鎖。</item> </plurals> + <plurals name="kg_password_wrong_pin_code_multi_sim" formatted="false"> + <item quantity="other">SIM 卡<xliff:g id="slotid">%d</xliff:g>的 PIN 碼輸入錯誤,你還可以再試 <xliff:g id="NUMBER_1">%d</xliff:g> 次。</item> + <item quantity="one">SIM 卡<xliff:g id="slotid">%d</xliff:g>的 PIN 碼輸入錯誤,你還可以再試 <xliff:g id="NUMBER_0">%d</xliff:g> 次。如果仍然失敗,就必須請電信業者為裝置解鎖。</item> + </plurals> <string name="kg_password_wrong_puk_code_dead" msgid="3329017604125179374">"SIM 卡無法使用,請與你的電信業者聯絡。"</string> <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="2287504898931957513"> <item quantity="other">SIM 卡的 PUK 碼輸入錯誤,你還可以再試 <xliff:g id="NUMBER_1">%d</xliff:g> 次。如果仍然失敗,SIM 卡將永久無法使用。</item> @@ -146,6 +150,10 @@ <item quantity="other">請輸入 SIM 卡的 PIN 碼,你還可以再試 <xliff:g id="NUMBER_1">%d</xliff:g> 次。</item> <item quantity="one">請輸入 SIM 卡的 PIN 碼,你還可以再試 <xliff:g id="NUMBER_0">%d</xliff:g> 次。如果仍然失敗,就必須請電信業者為裝置解鎖。</item> </plurals> + <plurals name="kg_password_default_pin_message_multi_sim" formatted="false"> + <item quantity="other">請輸入 SIM 卡<xliff:g id="slotid">%d</xliff:g>的 PIN 碼,你還可以再試 <xliff:g id="NUMBER_1">%d</xliff:g> 次。</item> + <item quantity="one">請輸入 SIM 卡的<xliff:g id="slotid">%d</xliff:g> PIN 碼,你還可以再試 <xliff:g id="NUMBER_0">%d</xliff:g> 次。如果仍然失敗,就必須請電信業者為裝置解鎖。</item> + </plurals> <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352"> <item quantity="other">SIM 卡現在已遭停用。請輸入 PUK 碼以繼續進行。你還可以再試 <xliff:g id="_NUMBER_1">%d</xliff:g> 次,如果仍然失敗,SIM 卡將永久無法使用。詳情請與電信業者聯絡。</item> <item quantity="one">SIM 卡現在已遭停用。請輸入 PUK 碼以繼續進行。你還可以再試 <xliff:g id="_NUMBER_0">%d</xliff:g> 次,如果仍然失敗,SIM 卡將永久無法使用。詳情請與電信業者聯絡。</item> diff --git a/packages/SystemUI/res-keyguard/values/bools.xml b/packages/SystemUI/res-keyguard/values/bools.xml index 2b83787172d3..f671f3e3a7d3 100644 --- a/packages/SystemUI/res-keyguard/values/bools.xml +++ b/packages/SystemUI/res-keyguard/values/bools.xml @@ -17,4 +17,6 @@ <resources> <bool name="kg_show_ime_at_screen_on">true</bool> <bool name="kg_use_all_caps">true</bool> + <bool name="kg_hide_emgcy_btn_when_oos">false</bool> + <bool name="config_showEmergencyButton">true</bool> </resources> diff --git a/packages/SystemUI/res-keyguard/values/strings.xml b/packages/SystemUI/res-keyguard/values/strings.xml index 7432f9cde639..6bdd5d88b59b 100644 --- a/packages/SystemUI/res-keyguard/values/strings.xml +++ b/packages/SystemUI/res-keyguard/values/strings.xml @@ -298,6 +298,10 @@ <item quantity="one">Incorrect SIM PIN code, you have <xliff:g id="number">%d</xliff:g> remaining attempt before you must contact your carrier to unlock your device.</item> <item quantity="other">Incorrect SIM PIN code, you have <xliff:g id="number">%d</xliff:g> remaining attempts.</item> </plurals> + <plurals name="kg_password_wrong_pin_code_multi_sim"> + <item quantity="one">Incorrect SIM<xliff:g id="slotid">%d</xliff:g> PIN code, you have <xliff:g id="number">%d</xliff:g> remaining attempt before you must contact your carrier to unlock your device.</item> + <item quantity="other">Incorrect SIM<xliff:g id="slotid">%d</xliff:g> PIN code, you have <xliff:g id="number">%d</xliff:g> remaining attempts.</item> + </plurals> <!-- Instructions telling the user that they have exhausted SIM PUK retries and the SIM is now unusable. Displayed in a dialog box. --> @@ -393,6 +397,10 @@ attempt before you must contact your carrier to unlock your device.</item> <item quantity="other">Enter SIM PIN. You have <xliff:g id="number">%d</xliff:g> remaining attempts.</item> </plurals> + <plurals name="kg_password_default_pin_message_multi_sim"> + <item quantity="one">Enter SIM<xliff:g id="slotid">%d</xliff:g> PIN, you have <xliff:g id="number">%d</xliff:g> remaining attempt before you must contact your carrier to unlock your device.</item> + <item quantity="other">Enter SIM<xliff:g id="slotid">%d</xliff:g> PIN, you have <xliff:g id="number">%d</xliff:g> remaining attempts.</item> + </plurals> <!-- Instructions telling the user remaining times when enter SIM PUK view. --> <plurals name="kg_password_default_puk_message"> diff --git a/packages/SystemUI/res/drawable/ic_2g_mobiledata.xml b/packages/SystemUI/res/drawable/ic_2g_mobiledata.xml new file mode 100644 index 000000000000..bcd3791a60cd --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_2g_mobiledata.xml @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="utf-8"?> +<!--Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> + +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="14dp" + android:height="17dp" + android:viewportWidth="14" + android:viewportHeight="17"> + + <path + android:pathData="M 1.2 4 H 13.7 V 13.2 H 1.2 V 4 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M5.7,11.9V13H1.5c0-0.3,0-0.5,0.1-0.8c0.1-0.4,0.3-0.8,0.5-1.2c0.2-0.4,0.6-0.8,1-1.4c0.7-0.8,1.2-1.4,1.4-1.9c0.2-0.5,0.4-0.9,0.4-1.3c0-0.4-0.1-0.8-0.3-1.1C4.3,5,4,4.9,3.7,4.9C3.3,4.9,3,5,2.8,5.4C2.5,5.7,2.4,6.1,2.4,6.7L1.6,6.6=c0.1-0.8,0.3-1.5,0.6-1.9C2.6,4.2,3.1,4,3.7,4c0.6,0,1.1,0.2,1.5,0.7c0.4,0.5,0.5,1.1,0.5,1.8c0,0.4-0.1,0.7-0.2,1.1C5.4,7.9,5.3,8.2,5,8.6C4.8,9,4.4,9.5,3.8,10.2c-0.5,0.6-0.8,0.9-0.9,1.1s-0.2,0.4-0.3,0.6H5.7z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M9.8,9.5V8.4l2.7,0v3.3c-0.4,0.5-0.8,0.8-1.3,1.1c-0.4,0.2-0.9,0.4-1.4,0.4c-0.6,0-1.2-0.2-1.7-0.6c-0.5-0.4-0.9-0.9-1.2-1.6c-0.3-0.7-0.4-1.5-0.4-2.4c0-0.9,0.1-1.7,0.4-2.4c0.3-0.8,0.6-1.3,1.1-1.7C8.6,4,9.2,3.8,9.8,3.8c0.5,0,0.9,0.1,1.3,0.3C11.5,4.4,11.8,4.7,12,5c0.2,0.4,0.4,0.9,0.5,1.5l-0.8,0.3c-0.1-0.5-0.2-0.8-0.4-1.1c-0.1-0.3-0.3-0.5-0.6-0.6s-0.6-0.2-0.9-0.2c-0.4,0-0.7,0.1-1,0.2C8.6,5.3,8.3,5.5,8.2,5.8C8,6,7.9,6.3,7.8,6.7C7.6,7.2,7.5,7.8,7.5,8.5c0,0.8,0.1,1.5,0.3,2C8,11,8.3,11.4,8.7,11.7c0.4,0.3,0.8,0.4,1.2,0.4c0.4,0,0.7-0.1,1.1-0.3s0.6-0.4,0.8-0.6V9.5H9.8z" /> +</vector>
\ No newline at end of file diff --git a/packages/SystemUI/res/drawable/ic_5g_uwb_mobiledata.xml b/packages/SystemUI/res/drawable/ic_5g_uwb_mobiledata.xml new file mode 100644 index 000000000000..41a82af16d5d --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_5g_uwb_mobiledata.xml @@ -0,0 +1,49 @@ +<!--Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="36dp" + android:height="14dp" + android:viewportWidth="36" + android:viewportHeight="14"> + + <path + android:fillColor="#FFFFFF" + android:pathData="M2.4,5.5c-0.3,0-0.6,0.1-0.9,0.2C2.3,5.8,2.2,5.9,2,6.1l0.3-2.8h3.4v-1H1.1L0.6,7.4l1.1,0.1C1.9,7.2,2.1,7,2.2,6.9c0.2-0.2,0.5-0.3,0.9-0.3s0.9,0.2,1,0.6C4.5,7.5,4.6,8,4.6,8.7s-0.1,1.2-0.4,1.6c-0.3,0.4-0.6,0.6-1,0.6c-0.4,0-0.8-0.2-0.9-0.5C2,10.1,1.9,9.7,1.9,9.1H0.6l0,0c0,0.9,0.2,1.5,0.8,1.9c0.5,0.5,1.1,0.7,1.9,0.7c0.9,0,1.6-0.3,2.1-0.9S6,9.5,6,8.6c0-0.9-0.2-1.7-0.7-2.3C4.8,5.8,4.2,5.5,3.4,5.5z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M9.5,7v0.9h1.7v2.2c-0.1,0.2-0.3,0.4-0.6,0.5s-0.7,0.2-1,0.2c-0.6,0-1-0.2-1.4-0.7C7.8,9.7,7.6,9.1,7.6,8.3V5.4c0-0.8,0.2-1.4,0.5-1.8C8.5,3.3,9,3.1,9.5,3.1c0.6,0,0.9,0.2,1.2,0.5c0.3,0.3,0.5,0.8,0.5,1.3h1.2l0,0c0-0.9-0.2-1.5-0.8-2c-0.5-0.5-1.2-0.8-2.2-0.8c-0.9,0-1.7,0.3-2.4,0.9S6.3,4.4,6.3,5.5v2.8c0,1.1,0.3,2,0.9,2.6c0.6,0.6,1.4,0.9,2.4,0.9c0.8,0,1.4-0.1,1.9-0.4c0.5-0.3,0.9-0.6,1-0.9V7H9.5z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M17.5,2.2v6.3c0,1.7,0.6,2.2,1.3,2.2c0.8,0,1.3-0.6,1.3-2.2V2.2h1.1v6.1c0,2.4-1,3.3-2.4,3.3c-1.4,0-2.3-0.9-2.3-3.2V2.2H17.5z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M23.5,11.5l-1.8-9.3h1.1l0.8,4.5c0.2,1.2,0.3,2.2,0.5,3.4h0.1c0.1-1.2,0.3-2.2,0.6-3.4l0.9-4.5h0.9l0.9,4.4c0.2,1.1,0.4,2.2,0.5,3.5h0c0.2-1.3,0.3-2.4,0.5-3.4l0.8-4.4h1l-1.8,9.3h-1L26.4,7c-0.2-1-0.4-2-0.5-3.1h0C25.8,5,25.7,6,25.4,7l-0.9,4.5H23.5z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M30.8,2.2c0.5,0,1,0,1.6,0c0.8,0,1.6,0.2,2.1,0.7c0.4,0.4,0.6,0.9,0.6,1.6c0,1-0.5,1.7-1.4,2.1v0c1.1,0.3,1.7,1.2,1.7,2.4c0,0.8-0.2,1.4-0.7,1.9c-0.5,0.6-1.4,0.8-2.5,0.8c-0.7,0-1.1,0-1.4-0.1V2.2zM31.9,6.1h0.5c0.9,0,1.6-0.7,1.6-1.6C34,3.6,33.6,3,32.5,3C32.2,3,32,3,31.9,3V6.1zM31.9,10.7c0.1,0,0.3,0.1,0.5,0.1c1.1,0,1.8-0.7,1.8-1.9c0-1.3-0.9-1.9-1.9-1.9h-0.5V10.7z" /> +</vector> diff --git a/packages/SystemUI/res/drawable/ic_volte.xml b/packages/SystemUI/res/drawable/ic_volte.xml new file mode 100644 index 000000000000..e4c5d6df5bea --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_volte.xml @@ -0,0 +1,47 @@ +<?xml version="1.0" encoding="utf-8"?> +<!--Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> + +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="14dp" + android:height="17dp" + android:viewportWidth="14" + android:viewportHeight="17"> + + <path + android:pathData="M 1.2 4 H 13.7 V 13.2 H 1.2 V 4 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M1.9,12.6V4h0.8v3.5h3.2V4h0.8v8.6H5.9v-4H2.7v4H1.9z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M8,12.6V4h2.1c0.5,0,0.8,0,1.1,0.1c0.4,0.1,0.7,0.3,0.9,0.6c0.3,0.4,0.6,0.9,0.7,1.5s0.2,1.3,0.2,2c0,0.7-0.1,1.2-0.2,1.7c-0.1,0.5-0.2,0.9-0.4,1.3S12.2,11.8,12,12s-0.4,0.3-0.7,0.4s-0.6,0.1-1,0.1H8zM8.8,11.6h1.3c0.4,0,0.7-0.1,0.9-0.2c0.2-0.1,0.4-0.3,0.5-0.4c0.2-0.3,0.3-0.6,0.4-1.1c0.1-0.5,0.2-1,0.2-1.7c0-0.9-0.1-1.6-0.3-2.1c-0.2-0.5-0.5-0.8-0.8-1C11,5.1,10.6,5,10.1,5H8.8V11.6z" /> + <path + android:fillColor="#000000" + android:pathData="M 2 9 L 1 9 L 1 9 L 2 9 Z" /> +</vector>
\ No newline at end of file diff --git a/packages/SystemUI/res/drawable/ic_volte_no_voice.xml b/packages/SystemUI/res/drawable/ic_volte_no_voice.xml new file mode 100644 index 000000000000..490b624927f0 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_volte_no_voice.xml @@ -0,0 +1,50 @@ +<?xml version="1.0" encoding="utf-8"?> +<!--Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> + +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="14dp" + android:height="17dp" + android:viewportWidth="14" + android:viewportHeight="17"> + + <path + android:pathData="M 1.2 4 H 13.7 V 13.2 H 1.2 V 4 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M1.9,12.6V4h0.8v3.5h3.2V4h0.8v8.6H5.9v-4H2.7v4H1.9z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M8,12.6V4h2.1c0.5,0,0.8,0,1.1,0.1c0.4,0.1,0.7,0.3,0.9,0.6c0.3,0.4,0.6,0.9,0.7,1.5s0.2,1.3,0.2,2c0,0.7-0.1,1.2-0.2,1.7c-0.1,0.5-0.2,0.9-0.4,1.3S12.2,11.8,12,12s-0.4,0.3-0.7,0.4s-0.6,0.1-1,0.1H8zM8.8,11.6h1.3c0.4,0,0.7-0.1,0.9-0.2c0.2-0.1,0.4-0.3,0.5-0.4c0.2-0.3,0.3-0.6,0.4-1.1c0.1-0.5,0.2-1,0.2-1.7c0-0.9-0.1-1.6-0.3-2.1c-0.2-0.5-0.5-0.8-0.8-1C11,5.1,10.6,5,10.1,5H8.8V11.6z" /> + <path + android:fillColor="#000000" + android:pathData="M 2 9 L 1 9 L 1 9 L 2 9 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M 0.5 9 H 13.5 V 10 H 0.5 V 9 Z" /> +</vector>
\ No newline at end of file diff --git a/packages/SystemUI/res/layout/keyguard_bottom_area.xml b/packages/SystemUI/res/layout/keyguard_bottom_area.xml index 96a1babcd550..149e715edbe0 100644..100755 --- a/packages/SystemUI/res/layout/keyguard_bottom_area.xml +++ b/packages/SystemUI/res/layout/keyguard_bottom_area.xml @@ -57,6 +57,15 @@ </LinearLayout> + <include layout="@layout/keyguard_emergency_carrier_area" + android:id="@+id/keyguard_selector_fade_container" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginBottom="70dp" + android:orientation="vertical" + android:layout_gravity="bottom|center_horizontal" + android:gravity="center_horizontal" /> + <FrameLayout android:id="@+id/preview_container" android:layout_width="match_parent" diff --git a/packages/SystemUI/res/layout/mobile_signal_group.xml b/packages/SystemUI/res/layout/mobile_signal_group.xml index 5ecd380c6950..26b137ac2fbd 100644 --- a/packages/SystemUI/res/layout/mobile_signal_group.xml +++ b/packages/SystemUI/res/layout/mobile_signal_group.xml @@ -1,5 +1,10 @@ <?xml version="1.0" encoding="utf-8"?> <!-- +/* + * Copyright (c) 2015-2017 The Linux Foundation. All rights reserved. + * Not a Contribution. +*/ +/* ** ** Copyright 2011, The Android Open Source Project ** @@ -62,7 +67,7 @@ <FrameLayout android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_gravity="center_vertical"> + > <com.android.systemui.statusbar.AnimatedImageView android:id="@+id/mobile_signal" android:layout_height="wrap_content" diff --git a/packages/SystemUI/res/layout/status_bar_mobile_signal_group.xml b/packages/SystemUI/res/layout/status_bar_mobile_signal_group.xml index 42d541e3afc9..23b90deb2693 100644 --- a/packages/SystemUI/res/layout/status_bar_mobile_signal_group.xml +++ b/packages/SystemUI/res/layout/status_bar_mobile_signal_group.xml @@ -22,15 +22,19 @@ android:id="@+id/mobile_combo" android:layout_width="wrap_content" android:layout_height="match_parent" - android:gravity="center_vertical" > - + android:gravity="center_vertical"> <com.android.keyguard.AlphaOptimizedLinearLayout android:id="@+id/mobile_group" android:layout_width="wrap_content" android:layout_height="match_parent" android:gravity="center_vertical" android:orientation="horizontal" > - + <ImageView + android:id="@+id/mobile_volte" + android:layout_height="wrap_content" + android:layout_width="wrap_content" + android:visibility="gone" + android:paddingEnd="2dp"/> <FrameLayout android:id="@+id/inout_container" android:layout_height="17dp" diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml index d6fd3d8927f1..339fdafc69cf 100644 --- a/packages/SystemUI/res/values-zh-rCN/strings.xml +++ b/packages/SystemUI/res/values-zh-rCN/strings.xml @@ -170,7 +170,7 @@ <string name="data_connection_5g" msgid="6357743323196864504">"5G"</string> <string name="data_connection_5g_plus" msgid="3284146603743732965">"5G+"</string> <string name="data_connection_cdma" msgid="8176597308239086780">"1X"</string> - <string name="data_connection_roaming" msgid="6037232010953697354">"漫游"</string> + <string name="data_connection_roaming" msgid="6037232010953697354">"数据漫游"</string> <string name="data_connection_edge" msgid="871835227939216682">"EDGE"</string> <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"WLAN"</string> <string name="accessibility_no_sim" msgid="8274017118472455155">"无 SIM 卡。"</string> @@ -857,6 +857,12 @@ <string name="mobile_data_disable_message" msgid="4756541658791493506">"您将无法通过<xliff:g id="CARRIER">%s</xliff:g>获取移动数据访问权限或连接到互联网。您只能通过 WLAN 连接到互联网。"</string> <string name="mobile_data_disable_message_default_carrier" msgid="6078110473451946831">"您的运营商"</string> <string name="touch_filtered_warning" msgid="8671693809204767551">"由于某个应用遮挡了权限请求界面,因此“设置”应用无法验证您的回应。"</string> + + <!-- Carrier Name --> + <string name="China_Mobile">中国移动</string> + <string name="China_Unicom">中国联通</string> + <string name="China_Telecom">中国电信</string> + <string name="China_Mobile_HD">中国移动 (HD)</string> <string name="slice_permission_title" msgid="7465009437851044444">"要允许“<xliff:g id="APP_0">%1$s</xliff:g>”显示“<xliff:g id="APP_2">%2$s</xliff:g>”图块吗?"</string> <string name="slice_permission_text_1" msgid="3514586565609596523">"- 可以读取“<xliff:g id="APP">%1$s</xliff:g>”中的信息"</string> <string name="slice_permission_text_2" msgid="3146758297471143723">"- 可以在“<xliff:g id="APP">%1$s</xliff:g>”内执行操作"</string> diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml index 5c2a5d271071..ac590eafa154 100644 --- a/packages/SystemUI/res/values-zh-rHK/strings.xml +++ b/packages/SystemUI/res/values-zh-rHK/strings.xml @@ -857,6 +857,12 @@ <string name="mobile_data_disable_message" msgid="4756541658791493506">"您將無法透過 <xliff:g id="CARRIER">%s</xliff:g> 存取流動數據或互聯網。您必須連接 Wi-Fi 才能使用互聯網。"</string> <string name="mobile_data_disable_message_default_carrier" msgid="6078110473451946831">"您的流動網絡供應商"</string> <string name="touch_filtered_warning" msgid="8671693809204767551">"由於某個應用程式已阻擋權限要求畫面,因此「設定」應用程式無法驗證您的回應。"</string> + + <!-- Carrier Name --> + <string name="China_Mobile">中國移動</string> + <string name="China_Unicom">中國聯通</string> + <string name="China_Telecom">中國電信</string> + <string name="China_Mobile_HD">中國移動 (HD)</string> <string name="slice_permission_title" msgid="7465009437851044444">"要允許「<xliff:g id="APP_0">%1$s</xliff:g>」顯示「<xliff:g id="APP_2">%2$s</xliff:g>」的快訊嗎?"</string> <string name="slice_permission_text_1" msgid="3514586565609596523">"- 可以讀取「<xliff:g id="APP">%1$s</xliff:g>」中的資料"</string> <string name="slice_permission_text_2" msgid="3146758297471143723">"- 可以在「<xliff:g id="APP">%1$s</xliff:g>」內執行操作"</string> diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml index dbe24bb33bd6..87383891e335 100644 --- a/packages/SystemUI/res/values-zh-rTW/strings.xml +++ b/packages/SystemUI/res/values-zh-rTW/strings.xml @@ -170,7 +170,7 @@ <string name="data_connection_5g" msgid="6357743323196864504">"5G"</string> <string name="data_connection_5g_plus" msgid="3284146603743732965">"5G+"</string> <string name="data_connection_cdma" msgid="8176597308239086780">"1X"</string> - <string name="data_connection_roaming" msgid="6037232010953697354">"漫遊"</string> + <string name="data_connection_roaming" msgid="6037232010953697354">"數據漫遊"</string> <string name="data_connection_edge" msgid="871835227939216682">"EDGE"</string> <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string> <string name="accessibility_no_sim" msgid="8274017118472455155">"沒有 SIM 卡。"</string> @@ -857,6 +857,12 @@ <string name="mobile_data_disable_message" msgid="4756541658791493506">"你將無法透過「<xliff:g id="CARRIER">%s</xliff:g>」使用行動數據或網際網路。你只能透過 Wi-Fi 使用網際網路。"</string> <string name="mobile_data_disable_message_default_carrier" msgid="6078110473451946831">"你的電信業者"</string> <string name="touch_filtered_warning" msgid="8671693809204767551">"由於某個應用程式覆蓋了權限要求畫面,因此「設定」應用程式無法驗證你的回應。"</string> + + <!-- Carrier Name --> + <string name="China_Mobile">中國移動</string> + <string name="China_Unicom">中國聯通</string> + <string name="China_Telecom">中國電信</string> + <string name="China_Mobile_HD">中國移動 (HD)</string> <string name="slice_permission_title" msgid="7465009437851044444">"要允許「<xliff:g id="APP_0">%1$s</xliff:g>」顯示「<xliff:g id="APP_2">%2$s</xliff:g>」的區塊嗎?"</string> <string name="slice_permission_text_1" msgid="3514586565609596523">"- 它可以讀取「<xliff:g id="APP">%1$s</xliff:g>」的資訊"</string> <string name="slice_permission_text_2" msgid="3146758297471143723">"- 它可以在「<xliff:g id="APP">%1$s</xliff:g>」內執行操作"</string> diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml index 98f0cbe29110..c3813a17e005 100644 --- a/packages/SystemUI/res/values/config.xml +++ b/packages/SystemUI/res/values/config.xml @@ -129,8 +129,21 @@ <integer name="quick_settings_brightness_dialog_short_timeout">2000</integer> <integer name="quick_settings_brightness_dialog_long_timeout">4000</integer> - <!-- Show indicator for Wifi on but not connected. --> - <bool name="config_showWifiIndicatorWhenEnabled">false</bool> + + <!-- Whether or not we also show rsrp level for LTE. --> + <bool name="config_showRsrpSignalLevelforLTE">false</bool> + + <!-- Whether or not we always show type icon --> + <bool name="config_alwaysShowTypeIcon">false</bool> + + <!-- Whether or not we show 2G for CDMA/1xRTT --> + <bool name="config_show2GforCDMA_1X">false</bool> + + <!-- When true, hide no internet statue on signal strength icon --> + <bool name="config_hideNoInternetState">false</bool> + + <!-- Should "LTE"/"4G" be shown instead of "LTE+"/"4G+" when on NETWORK_TYPE_LTE_CA? --> + <bool name="config_hideLtePlus">false</bool> <!-- The number of milliseconds before the heads up notification auto-dismisses. --> <integer name="heads_up_notification_decay">5000</integer> @@ -357,7 +370,7 @@ <bool name="config_enableNotificationShadeDrag">true</bool> <!-- Whether to show activity indicators in the status bar --> - <bool name="config_showActivity">false</bool> + <bool name="config_showActivity">true</bool> <!-- Whether or not the button to clear all notifications will be shown. --> <bool name="config_enableNotificationsClearAll">true</bool> @@ -395,6 +408,7 @@ the other notifications need to be manually expanded by the user. --> <bool name="config_alwaysExpandNonGroupedNotifications">false</bool> + <!-- Whether or not an expandable notification can be manually expanded or collapsed by the user. Grouped notifications are still expandable even if this value is false. --> <bool name="config_enableNonGroupedNotificationExpand">true</bool> @@ -439,6 +453,55 @@ <item>120</item> </integer-array> + <string-array name="origin_carrier_names"> + <item>CHINA\u0020\u0020MOBILE</item> + <item>CMCC</item> + <item>CHN-UNICOM</item> + <item>China Mobile</item> + <item>China Mobile (HD)</item> + <item>China Unicom</item> + <item>China Telecom</item> + <item>CHN-CT</item> + <item>中国移动</item> + <item>中国联通</item> + <item>中国电信</item> + <item>中國移動</item> + <item>中國聯通</item> + <item>中國電信</item> + <item>Searching for Service</item> + </string-array> + + <string-array name="locale_carrier_names"> + <item>China_Mobile</item> + <item>China_Mobile</item> + <item>China_Unicom</item> + <item>China_Mobile</item> + <item>China_Mobile_HD</item> + <item>China_Unicom</item> + <item>China_Telecom</item> + <item>China_Telecom</item> + <item>China_Mobile</item> + <item>China_Unicom</item> + <item>China_Telecom</item> + <item>China_Mobile</item> + <item>China_Unicom</item> + <item>China_Telecom</item> + <item>roamingTextSearching</item> + </string-array> + + <!-- monitor locale change --> + <bool name="config_monitor_locale_change">true</bool> + + <!-- display for radio tech --> + <bool name="config_display_rat">true</bool> + + <!-- config 2G/3G/4G RAT strings for carriers --> + <string name="config_rat_unknown" translatable="false">""</string> + <string name="config_rat_2g" translatable="false">2G</string> + <string name="config_rat_3g" translatable="false">3G</string> + <string name="config_rat_4g" translatable="false">4G</string> + + <!-- Smart replies in notifications: Whether smart replies in notifications are enabled. --> <bool name="config_smart_replies_in_notifications_enabled">true</bool> @@ -466,6 +529,9 @@ <!-- On debuggable builds, alert the user if SystemUI PSS goes over this number (in kb) --> <integer name="watch_heap_limit">256000</integer> + <!-- Whether to show VoLTE icon in the status bar --> + <bool name="config_display_volte">false</bool> + <!-- Allow dragging the PIP to a location to close it --> <bool name="config_pipEnableDismissDragToEdge">true</bool> diff --git a/packages/SystemUI/res/values/config_5g.xml b/packages/SystemUI/res/values/config_5g.xml new file mode 100644 index 000000000000..b1ef8cdeba5e --- /dev/null +++ b/packages/SystemUI/res/values/config_5g.xml @@ -0,0 +1,60 @@ +<?xml version="1.0" encoding="utf-8"?> +<!--Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> + +<resources> + + <integer name="config_5g_num_signal_strength_bins">4</integer> + + <!-- mmWave 5G NR Signal Strength Indicator --> + <!-- SS-RSRP. --> + <!-- rsrp < -110 : level=0 --> + <!-- -110 <= rsrp <= -90 : level=1 --> + <!-- -90 < rsrp <= -80 : level=2 --> + <!-- -80 < rsrp <= -30 : level=3 --> + <!-- -30 < rsrp : level=0 --> + <integer-array name="config_5g_signal_rsrp_thresholds"> + <item>-110</item> + <item>-90</item> + <item>-80</item> + <item>-30</item> + </integer-array> + + <!-- SS-SNR --> + <!-- snr < -5 : level=0 --> + <!-- -5<= snr <= 10 : level=1 --> + <!-- 20 < snr <= 10 : level=2 --> + <!-- 20 < snr <= 40 : level=3 --> + <!-- 40 < snr : level=0 --> + <integer-array name="config_5g_signal_snr_thresholds"> + <item>-5</item> + <item>10</item> + <item>20</item> + <item>40</item> + </integer-array> +</resources> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index ab0bbe10c37c..5eb9ecc35457 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -650,7 +650,7 @@ <dimen name="keyguard_affordance_height">56dp</dimen> <dimen name="keyguard_affordance_width">56dp</dimen> - <dimen name="keyguard_indication_margin_bottom">65dp</dimen> + <dimen name="keyguard_indication_margin_bottom">125dp</dimen> <!-- The text size for battery level --> <dimen name="battery_level_text_size">12sp</dimen> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index f384d8f5b357..124c5ba22b90 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -385,6 +385,8 @@ <!-- Content description of the data connection type HSPA and its variants. [CHAR LIMIT=NONE] --> <string name="data_connection_hspa">HSPA</string> + <string name="data_connection_2g">2G</string> + <!-- Content description of the data connection type 3G. [CHAR LIMIT=NONE] --> <string name="data_connection_3g">3G</string> @@ -415,6 +417,15 @@ <!-- Content description of the data connection type CDMA. [CHAR LIMIT=NONE] --> <string name="data_connection_cdma">1X</string> + <!-- Content description of the data connection type 5G Basic. [CHAR LIMIT=NONE] --> + <string name="data_connection_5g_basic">5GBasic</string> + + <!-- Content description of the data connection type 5G UWB. [CHAR LIMIT=NONE] --> + <string name="data_connection_5g_uwb">5GUWB</string> + + <!-- Content description of the data connection type 5G stand alone. [CHAR LIMIT=NONE] --> + <string name="data_connection_5g_sa">5GSA</string> + <!-- Content description of the roaming data connection type. [CHAR LIMIT=NONE] --> <string name="data_connection_roaming">Roaming</string> @@ -2204,6 +2215,7 @@ <!-- Do Not Disturb button to change the current settings [CHAR LIMIT=20] --> <string name="qs_dnd_replace">Replace</string> + <!-- Title of the "running foreground services" dialog. [CHAR LIMIT=NONE] --> <string name="running_foreground_services_title">Apps running in background</string> @@ -2244,6 +2256,12 @@ <!-- Option to grant the slice permission request on the screen [CHAR LIMIT=15] --> <string name="slice_permission_deny">Deny</string> + <!-- Carrier Name --> + <string name="China_Mobile">China Mobile</string> + <string name="China_Unicom">China Unicom</string> + <string name="China_Telecom">China Telecom</string> + <string name="China_Mobile_HD">China Mobile (HD)</string> + <!-- List of packages for which we don't want to show recents onboarding, add into overlay as needed. --> <string-array name="recents_onboarding_blacklisted_packages" translatable="false"> </string-array> diff --git a/packages/SystemUI/src/com/android/keyguard/CarrierText.java b/packages/SystemUI/src/com/android/keyguard/CarrierText.java index b7d51978fab2..c1aa8a410cae 100644..100755 --- a/packages/SystemUI/src/com/android/keyguard/CarrierText.java +++ b/packages/SystemUI/src/com/android/keyguard/CarrierText.java @@ -174,15 +174,59 @@ public class CarrierText extends TextView { protected void updateCarrierText() { boolean allSimsMissing = true; boolean anySimReadyAndInService = false; + boolean showLocale = getContext().getResources().getBoolean( + com.android.systemui.R.bool.config_monitor_locale_change); + boolean showRat = getContext().getResources().getBoolean( + com.android.systemui.R.bool.config_display_rat); CharSequence displayText = null; List<SubscriptionInfo> subs = mKeyguardUpdateMonitor.getSubscriptionInfo(false); final int N = subs.size(); if (DEBUG) Log.d(TAG, "updateCarrierText(): " + N); for (int i = 0; i < N; i++) { + CharSequence networkClass = ""; int subId = subs.get(i).getSubscriptionId(); State simState = mKeyguardUpdateMonitor.getSimState(subId); + if (showRat) { + ServiceState ss = mKeyguardUpdateMonitor.mServiceStates.get(subId); + if (ss != null && (ss.getDataRegState() == ServiceState.STATE_IN_SERVICE + || ss.getVoiceRegState() == ServiceState.STATE_IN_SERVICE)) { + int networkType = TelephonyManager.NETWORK_TYPE_UNKNOWN; + if (ss.getRilDataRadioTechnology() != + ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN) { + networkType = ss.getDataNetworkType(); + } else if (ss.getRilVoiceRadioTechnology() != + ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN) { + networkType = ss.getVoiceNetworkType(); + } + networkClass = networkClassToString(TelephonyManager + .getNetworkClass(networkType)); + } + } CharSequence carrierName = subs.get(i).getCarrierName(); + if ((showLocale || showRat) && !TextUtils.isEmpty(carrierName)) { + String[] names = carrierName.toString().split(mSeparator.toString(), 2); + StringBuilder newCarrierName = new StringBuilder(); + for (int j = 0; j < names.length; j++) { + if (showLocale) { + names[j] = getLocalString( + names[j], com.android.systemui.R.array.origin_carrier_names, + com.android.systemui.R.array.locale_carrier_names); + } + if (!TextUtils.isEmpty(names[j])) { + if (!TextUtils.isEmpty(networkClass) && showRat) { + names[j] = new StringBuilder().append(names[j]).append(" ") + .append(networkClass).toString(); + } + if (j > 0 && names[j].equals(names[j-1])) { + continue; + } + if (j > 0) newCarrierName.append(mSeparator); + newCarrierName.append(names[j]); + } + } + carrierName = newCarrierName.toString(); + } CharSequence carrierTextForSimState = getCarrierTextForSimState(simState, carrierName); if (DEBUG) { Log.d(TAG, "Handling (subId=" + subId + "): " + simState + " " + carrierName); @@ -490,4 +534,38 @@ public class CarrierText extends TextView { return source; } } + + private String networkClassToString (int networkClass) { + final int[] classIds = { + com.android.systemui.R.string.config_rat_unknown, + com.android.systemui.R.string.config_rat_2g, + com.android.systemui.R.string.config_rat_3g, + com.android.systemui.R.string.config_rat_4g }; + String classString = null; + if (networkClass < classIds.length) { + classString = getContext().getResources().getString(classIds[networkClass]); + } + return (classString == null) ? "" : classString; + } + + /** + * parse the string to current language. + * + * @param originalString original string + * @param originNamesId the id of the original string array. + * @param localNamesId the id of the local string keys. + * @return local language string + */ + private String getLocalString(String originalString, + int originNamesId, int localNamesId) { + String[] origNames = getContext().getResources().getStringArray(originNamesId); + String[] localNames = getContext().getResources().getStringArray(localNamesId); + for (int i = 0; i < origNames.length; i++) { + if (origNames[i].equalsIgnoreCase(originalString)) { + return getContext().getString(getContext().getResources().getIdentifier( + localNames[i], "string", "com.android.systemui")); + } + } + return originalString; + } } diff --git a/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java b/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java index 210b82d1d69c..8cb8174d8ac5 100644 --- a/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java +++ b/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java @@ -26,8 +26,10 @@ import android.os.RemoteException; import android.os.SystemClock; import android.os.UserHandle; import android.telecom.TelecomManager; +import android.telephony.ServiceState; import android.util.AttributeSet; import android.util.Slog; +import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.view.ViewConfiguration; @@ -72,6 +74,11 @@ public class EmergencyButton extends Button { public void onPhoneStateChanged(int phoneState) { updateEmergencyCallButton(); } + + @Override + public void onServiceStateChanged(int subId, ServiceState state) { + updateEmergencyCallButton(); + } }; private boolean mLongPressWasDragged; @@ -192,7 +199,7 @@ public class EmergencyButton extends Button { } } - private void updateEmergencyCallButton() { + public void updateEmergencyCallButton() { boolean visible = false; if (mIsVoiceCapable) { // Emergency calling requires voice capability. @@ -205,8 +212,14 @@ public class EmergencyButton extends Button { // Some countries can't handle emergency calls while SIM is locked. visible = mEnableEmergencyCallWhileSimLocked; } else { - // Only show if there is a secure screen (pin/pattern/SIM pin/SIM puk); - visible = mLockPatternUtils.isSecure(KeyguardUpdateMonitor.getCurrentUser()); + // Show if there is a secure screen (pin/pattern/SIM pin/SIM puk) or config set + visible = mLockPatternUtils.isSecure(KeyguardUpdateMonitor.getCurrentUser()) || + mContext.getResources().getBoolean(R.bool.config_showEmergencyButton); + } + + if (mContext.getResources().getBoolean(R.bool.kg_hide_emgcy_btn_when_oos)) { + KeyguardUpdateMonitor monitor = KeyguardUpdateMonitor.getInstance(mContext); + visible = visible && !monitor.isOOS(); } } } diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java index a055950a5522..658d9e3593c0 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java @@ -189,6 +189,7 @@ public abstract class KeyguardAbsKeyInputView extends LinearLayout boolean isValidPassword) { boolean dismissKeyguard = KeyguardUpdateMonitor.getCurrentUser() == userId; if (matched) { + mLockPatternUtils.sanitizePassword(); mCallback.reportUnlockAttempt(userId, true, 0); if (dismissKeyguard) { mDismissing = true; diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardConstants.java b/packages/SystemUI/src/com/android/keyguard/KeyguardConstants.java index 0340904cbd9d..9ade1cf4a723 100644..100755 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardConstants.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardConstants.java @@ -25,7 +25,7 @@ public class KeyguardConstants { * Turns on debugging information for the whole Keyguard. This is very verbose and should only * be used temporarily for debugging. */ - public static final boolean DEBUG = false; + public static final boolean DEBUG = true; public static final boolean DEBUG_SIM_STATES = true; public static final boolean DEBUG_BIOMETRIC_WAKELOCK = true; } diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java index 112e06785bee..37d5b56fd958 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java @@ -310,6 +310,7 @@ public class KeyguardPatternView extends LinearLayout implements KeyguardSecurit boolean isValidPattern) { boolean dismissKeyguard = KeyguardUpdateMonitor.getCurrentUser() == userId; if (matched) { + mLockPatternUtils.sanitizePassword(); mCallback.reportUnlockAttempt(userId, true, 0); if (dismissKeyguard) { mLockPatternView.setDisplayMode(LockPatternView.DisplayMode.Correct); diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java index c0ec405e7dc1..63b86ae3a923 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java @@ -60,12 +60,25 @@ public class KeyguardSimPinView extends KeyguardPinBasedInputView { private AlertDialog mRemainingAttemptsDialog; private int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; private ImageView mSimImageView; + private int mSlotId; KeyguardUpdateMonitorCallback mUpdateMonitorCallback = new KeyguardUpdateMonitorCallback() { @Override public void onSimStateChanged(int subId, int slotId, State simState) { if (DEBUG) Log.v(TAG, "onSimStateChanged(subId=" + subId + ",state=" + simState + ")"); switch(simState) { + // If the SIM is removed, then we must remove the keyguard. It will be put up + // again when the PUK locked SIM is re-entered. + case ABSENT: { + KeyguardUpdateMonitor.getInstance(getContext()).reportSimUnlocked(subId); + // onSimStateChanged callback can fire when the SIM PIN lock is not currently + // active and mCallback is null. + if (mCallback != null) { + mCallback.dismiss(true, KeyguardUpdateMonitor.getCurrentUser()); + } + mSubId = subId; + break; + } case READY: { mRemainingAttempts = -1; resetState(); @@ -106,6 +119,7 @@ public class KeyguardSimPinView extends KeyguardPinBasedInputView { return; } + mSlotId = SubscriptionManager.getSlotIndex(mSubId) + 1; boolean isEsimLocked = KeyguardEsimArea.isEsimLocked(mContext, mSubId); int count = TelephonyManager.getDefault().getSimCount(); Resources rez = getResources(); @@ -172,10 +186,18 @@ public class KeyguardSimPinView extends KeyguardPinBasedInputView { if (attemptsRemaining == 0) { displayMessage = getContext().getString(R.string.kg_password_wrong_pin_code_pukked); } else if (attemptsRemaining > 0) { - msgId = isDefault ? R.plurals.kg_password_default_pin_message : - R.plurals.kg_password_wrong_pin_code; - displayMessage = getContext().getResources() - .getQuantityString(msgId, attemptsRemaining, attemptsRemaining); + int count = TelephonyManager.getDefault().getSimCount(); + if ( count > 1 ) { + msgId = isDefault ? R.plurals.kg_password_default_pin_message_multi_sim : + R.plurals.kg_password_wrong_pin_code_multi_sim; + displayMessage = getContext().getResources() + .getQuantityString(msgId, attemptsRemaining, mSlotId, attemptsRemaining); + }else { + msgId = isDefault ? R.plurals.kg_password_default_pin_message : + R.plurals.kg_password_wrong_pin_code; + displayMessage = getContext().getResources() + .getQuantityString(msgId, attemptsRemaining, attemptsRemaining); + } } else { msgId = isDefault ? R.string.kg_sim_pin_instructions : R.string.kg_password_pin_failed; displayMessage = getContext().getString(msgId); diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java index b17d117b68e3..87cee7bfb564 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java @@ -72,6 +72,7 @@ public class KeyguardSimPukView extends KeyguardPinBasedInputView { // If the SIM is unlocked via a key sequence through the emergency dialer, it will // move into the READY state and the PUK lock keyguard should be removed. case READY: { + KeyguardUpdateMonitor.getInstance(getContext()).reportSimUnlocked(subId); mRemainingAttempts = -1; mShowDefaultMessage = true; // mCallback can be null if onSimStateChanged callback is called when keyguard diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index bcd41a076eee..5f3f71bfb033 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -95,6 +95,8 @@ import java.io.FileDescriptor; import java.io.PrintWriter; import java.lang.ref.WeakReference; import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map.Entry; @@ -153,6 +155,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { private static final int MSG_DEVICE_POLICY_MANAGER_STATE_CHANGED = 337; private static final int MSG_TELEPHONY_CAPABLE = 338; private static final int MSG_TIMEZONE_UPDATE = 339; + private static final int MSG_LOCALE_CHANGED = 500; /** Biometric authentication state: Not listening. */ private static final int BIOMETRIC_STATE_STOPPED = 0; @@ -350,6 +353,9 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { case MSG_BIOMETRIC_AUTHENTICATION_CONTINUE: updateBiometricListeningState(); break; + case MSG_LOCALE_CHANGED: + handleLocaleChanged(); + break; case MSG_DEVICE_POLICY_MANAGER_STATE_CHANGED: updateLogoutEnabled(); break; @@ -477,6 +483,16 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { List<SubscriptionInfo> sil = mSubscriptionInfo; if (sil == null || forceReload) { sil = mSubscriptionManager.getActiveSubscriptionInfoList(); + if ( sil != null ) { + Collections.sort(sil, new Comparator<SubscriptionInfo>() { + @Override + public int compare(SubscriptionInfo lhs, SubscriptionInfo rhs) { + return lhs.getSimSlotIndex() == rhs.getSimSlotIndex() + ? lhs.getSubscriptionId() - rhs.getSubscriptionId() + : lhs.getSimSlotIndex() - rhs.getSimSlotIndex(); + } + }); + } } if (sil == null) { // getActiveSubscriptionInfoList was null callers expect an empty list. @@ -1040,6 +1056,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { } mHandler.sendMessage( mHandler.obtainMessage(MSG_SERVICE_STATE_CHANGE, subId, 0, serviceState)); + } else if (Intent.ACTION_LOCALE_CHANGED.equals(action)) { + mHandler.sendEmptyMessage(MSG_LOCALE_CHANGED); } else if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED.equals( action)) { mHandler.sendEmptyMessage(MSG_DEVICE_POLICY_MANAGER_STATE_CHANGED); @@ -1441,6 +1459,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { filter.addAction(Intent.ACTION_BATTERY_CHANGED); filter.addAction(Intent.ACTION_TIMEZONE_CHANGED); filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED); + filter.addAction(Intent.ACTION_LOCALE_CHANGED); filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED); filter.addAction(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED); filter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED); @@ -1633,6 +1652,18 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { } } + /** + * Handle {@link #MSG_LOCALE_CHANGED} + */ + private void handleLocaleChanged() { + for (int j = 0; j < mCallbacks.size(); j++) { + KeyguardUpdateMonitorCallback cb = mCallbacks.get(j).get(); + if (cb != null) { + cb.onRefreshCarrierInfo(); + } + } + } + public boolean isUnlockWithFingerprintPossible(int userId) { return mFpm != null && mFpm.isHardwareDetected() && !isFingerprintDisabled(userId) && mFpm.getEnrolledFingerprints(userId).size() > 0; @@ -1993,6 +2024,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { KeyguardUpdateMonitorCallback cb = mCallbacks.get(j).get(); if (cb != null) { cb.onRefreshCarrierInfo(); + cb.onServiceStateChanged(subId, serviceState); } } } @@ -2259,6 +2291,36 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { } }; + public boolean isOOS() + { + boolean ret = true; + int phoneCount = TelephonyManager.getDefault().getPhoneCount(); + + for (int phoneId = 0; phoneId < phoneCount; phoneId++) { + int[] subId = SubscriptionManager.getSubId(phoneId); + if (subId != null && subId.length >= 1) { + if (DEBUG) Log.d(TAG, "slot id:" + phoneId + " subId:" + subId[0]); + ServiceState state = mServiceStates.get(subId[0]); + if (state != null) { + if (state.isEmergencyOnly()) + ret = false; + if ((state.getVoiceRegState() != ServiceState.STATE_OUT_OF_SERVICE) + && (state.getVoiceRegState() != ServiceState.STATE_POWER_OFF)) + ret = false; + if (DEBUG) { + Log.d(TAG, "is emergency: " + state.isEmergencyOnly()); + Log.d(TAG, "voice state: " + state.getVoiceRegState()); + } + } else { + if (DEBUG) Log.d(TAG, "state is NULL"); + } + } + } + + if (DEBUG) Log.d(TAG, "is Emergency supported: " + ret); + return ret; + } + /** * @return true if and only if the state has changed for the specified {@code slotId} */ diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java index 8696bb769bbd..56eaa9d0eef1 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java @@ -20,6 +20,7 @@ import android.graphics.Bitmap; import android.hardware.biometrics.BiometricSourceType; import android.media.AudioManager; import android.os.SystemClock; +import android.telephony.ServiceState; import android.telephony.TelephonyManager; import android.view.WindowManagerPolicyConstants; @@ -139,6 +140,13 @@ public class KeyguardUpdateMonitorCallback { public void onSimStateChanged(int subId, int slotId, IccCardConstants.State simState) { } /** + * Called when the sevice state changes. + * @param subId + * @param serviceState + */ + public void onServiceStateChanged(int subId, ServiceState state) { } + + /** * Called when the user's info changed. */ public void onUserInfoChanged(int userId) { } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java index e63f88a898cc..4d43cd19b021 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java @@ -448,7 +448,7 @@ public class QSFooterImpl extends FrameLayout implements QSFooter, public void setMobileDataIndicators(NetworkController.IconState statusIcon, NetworkController.IconState qsIcon, int statusType, int qsType, boolean activityIn, boolean activityOut, - String typeContentDescription, + int volteIcon, String typeContentDescription, String description, boolean isWide, int subId, boolean roaming) { mInfo.visible = statusIcon.visible; mInfo.mobileSignalIconId = statusIcon.icon; diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java index f1f0f698ab72..772f2aee339c 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java @@ -123,11 +123,11 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne mFooter = new QSSecurityFooter(this, context); addView(mFooter.getView()); - updateResources(); - mBrightnessController = new BrightnessController(getContext(), findViewById(R.id.brightness_icon), findViewById(R.id.brightness_slider)); + + updateResources(); } protected void addDivider() { @@ -293,6 +293,9 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne updatePageIndicator(); + for (TileRecord r : mRecords) { + r.tile.clearState(); + } if (mListening) { refreshAllTiles(); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java index 1155a414b870..d8193218f576 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java @@ -243,8 +243,9 @@ public class CellularTile extends QSTileImpl<SignalState> { @Override public void setMobileDataIndicators(IconState statusIcon, IconState qsIcon, int statusType, - int qsType, boolean activityIn, boolean activityOut, String typeContentDescription, - String description, boolean isWide, int subId, boolean roaming) { + int qsType, boolean activityIn, boolean activityOut, int volteIcon, + String typeContentDescription, String description, boolean isWide, + int subId, boolean roaming) { if (qsIcon == null) { // Not data sim, don't display. return; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java index 4db981d2dcd0..89c2ac65c7ac 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java @@ -27,6 +27,7 @@ import android.content.res.ColorStateList; import android.graphics.Color; import android.graphics.Rect; import android.util.AttributeSet; +import android.util.Log; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; @@ -57,6 +58,7 @@ public class StatusBarMobileView extends FrameLayout implements DarkReceiver, private ImageView mMobile, mMobileType, mMobileRoaming; private View mMobileRoamingSpace; private int mVisibleState = -1; + private ImageView mVolte; public static StatusBarMobileView fromContext(Context context, String slot) { LayoutInflater inflater = LayoutInflater.from(context); @@ -106,6 +108,7 @@ public class StatusBarMobileView extends FrameLayout implements DarkReceiver, mIn = findViewById(R.id.mobile_in); mOut = findViewById(R.id.mobile_out); mInoutContainer = findViewById(R.id.inout_container); + mVolte = findViewById(R.id.mobile_volte); mMobileDrawable = new SignalDrawable(getContext()); mMobile.setImageDrawable(mMobileDrawable); @@ -140,6 +143,18 @@ public class StatusBarMobileView extends FrameLayout implements DarkReceiver, if (requestLayout) { requestLayout(); } + + if ( needFixVisibleState() ) { + Log.d(TAG, "fix VisibleState width=" + getWidth() + " height=" + getHeight()); + mVisibleState = STATE_ICON; + setVisibility(View.VISIBLE); + requestLayout(); + }else if (needFixInVisibleState() ) { + Log.d(TAG, "fix InVisibleState width=" + getWidth() + " height=" + getHeight()); + mVisibleState = -1; + setVisibility(View.INVISIBLE); + requestLayout(); + } } private void initViewState() { @@ -164,6 +179,12 @@ public class StatusBarMobileView extends FrameLayout implements DarkReceiver, mOut.setVisibility(mState.activityOut ? View.VISIBLE : View.GONE); mInoutContainer.setVisibility((mState.activityIn || mState.activityOut) ? View.VISIBLE : View.GONE); + if (mState.volteId > 0 ) { + mVolte.setImageResource(mState.volteId); + mVolte.setVisibility(View.VISIBLE); + }else { + mVolte.setVisibility(View.GONE); + } } private boolean updateState(MobileIconState state) { @@ -195,6 +216,15 @@ public class StatusBarMobileView extends FrameLayout implements DarkReceiver, mInoutContainer.setVisibility((state.activityIn || state.activityOut) ? View.VISIBLE : View.GONE); + if (mState.volteId != state.volteId) { + if (state.volteId != 0) { + mVolte.setImageResource(state.volteId); + mVolte.setVisibility(View.VISIBLE); + } else { + mVolte.setVisibility(View.GONE); + } + } + needsLayout |= state.roaming != mState.roaming || state.activityIn != mState.activityIn || state.activityOut != mState.activityOut; @@ -284,6 +314,22 @@ public class StatusBarMobileView extends FrameLayout implements DarkReceiver, return mState; } + private boolean needFixVisibleState() { + if ( mState.visible && (getVisibility() != View.VISIBLE) ) { + return true; + }else { + return false; + } + } + + private boolean needFixInVisibleState() { + if ( !mState.visible && (getVisibility() == View.VISIBLE)) { + return true; + }else { + return false; + } + } + @Override public String toString() { return "StatusBarMobileView(slot=" + mSlot + " state=" + mState + ")"; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java index 2e9d9bcda61e..8fe8c89b0408 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java @@ -65,6 +65,7 @@ import android.widget.TextView; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.widget.LockPatternUtils; +import com.android.keyguard.EmergencyButton; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.KeyguardUpdateMonitorCallback; import com.android.systemui.Dependency; @@ -118,6 +119,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL private static final int DOZE_ANIMATION_STAGGER_DELAY = 48; private static final int DOZE_ANIMATION_ELEMENT_DURATION = 250; + private EmergencyButton mEmergencyButton; private KeyguardAffordanceView mRightAffordanceView; private KeyguardAffordanceView mLeftAffordanceView; private LockIcon mLockIcon; @@ -236,6 +238,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL super.onFinishInflate(); mLockPatternUtils = new LockPatternUtils(mContext); mPreviewContainer = findViewById(R.id.preview_container); + mEmergencyButton = (EmergencyButton) findViewById(R.id.emergency_call_button); mOverlayContainer = findViewById(R.id.overlay_container); mRightAffordanceView = findViewById(R.id.camera_button); mLeftAffordanceView = findViewById(R.id.left_button); @@ -253,6 +256,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL mLockIcon.setScreenOn(updateMonitor.isScreenOn()); mLockIcon.setDeviceInteractive(updateMonitor.isDeviceInteractive()); mLockIcon.update(); + updateEmergencyButton(); setClipChildren(false); setClipToPadding(false); mPreviewInflater = new PreviewInflater(mContext, new LockPatternUtils(mContext)); @@ -348,6 +352,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL lp.height = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_height); mLeftAffordanceView.setLayoutParams(lp); updateLeftAffordanceIcon(); + updateEmergencyButton(); } private void updateRightAffordanceIcon() { @@ -902,6 +907,12 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL } } + private void updateEmergencyButton() { + if (mEmergencyButton != null) { + mEmergencyButton.updateEmergencyCallButton(); + } + } + @Override public WindowInsets onApplyWindowInsets(WindowInsets insets) { int bottom = insets.getDisplayCutout() != null diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java index f17145d72be1..a697603c689b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java @@ -48,7 +48,9 @@ import com.android.systemui.statusbar.FlingAnimationUtils; import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.StatusBarStateController; import com.android.systemui.statusbar.VibratorHelper; +import com.android.systemui.statusbar.phone.HeadsUpManagerPhone; import com.android.systemui.statusbar.policy.KeyguardMonitor; +import android.util.BoostFramework; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -112,6 +114,11 @@ public abstract class PanelView extends FrameLayout { private final VibratorHelper mVibratorHelper; /** + * For PanelView fling perflock call + */ + private BoostFramework mPerf = null; + + /** * Whether an instant expand request is currently pending and we are just waiting for layout. */ private boolean mInstantExpanding; @@ -217,6 +224,8 @@ public abstract class PanelView extends FrameLayout { mVibratorHelper = Dependency.get(VibratorHelper.class); mVibrateOnOpening = mContext.getResources().getBoolean( R.bool.config_vibrateOnIconAnimation); + + mPerf = new BoostFramework(); } protected void loadDimens() { @@ -771,16 +780,26 @@ public abstract class PanelView extends FrameLayout { animator.setDuration(mFixedDuration); } } + if (mPerf != null) { + String currentPackage = mContext.getPackageName(); + mPerf.perfHint(BoostFramework.VENDOR_HINT_SCROLL_BOOST, currentPackage, -1, BoostFramework.Scroll.PANEL_VIEW); + } animator.addListener(new AnimatorListenerAdapter() { private boolean mCancelled; @Override public void onAnimationCancel(Animator animation) { + if (mPerf != null) { + mPerf.perfLockRelease(); + } mCancelled = true; } @Override public void onAnimationEnd(Animator animation) { + if (mPerf != null) { + mPerf.perfLockRelease(); + } if (clearAllExpandHack && !mCancelled) { setExpandedHeightInternal(getMaxPanelHeight()); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconList.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconList.java index 2e4161787267..ee18b7d3d34c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconList.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconList.java @@ -20,11 +20,14 @@ import static com.android.systemui.statusbar.phone.StatusBarIconController.TAG_P import android.annotation.NonNull; import android.annotation.Nullable; +import android.telephony.SubscriptionManager; import com.android.internal.annotations.VisibleForTesting; import java.io.PrintWriter; import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; import java.util.List; public class StatusBarIconList { @@ -184,6 +187,18 @@ public class StatusBarIconList { // These holders get added to the end. Confused yet? mSubSlots.add(holder); + + if (holder.getType() == StatusBarIconHolder.TYPE_MOBILE) { + Collections.sort(mSubSlots, new Comparator<StatusBarIconHolder>() { + @Override + public int compare(StatusBarIconHolder lhs, StatusBarIconHolder rhs) { + int indexLhs = SubscriptionManager.getSlotIndex(lhs.getTag()); + int indexRhs = SubscriptionManager.getSlotIndex(rhs.getTag()); + return indexRhs - indexLhs; + } + }); + } + } private int getIndexForTag(int tag) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java index 8286d26e9999..24f0b273b292 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java @@ -58,7 +58,6 @@ public class StatusBarSignalPolicy implements NetworkControllerImpl.SignalCallba private boolean mBlockEthernet; private boolean mActivityEnabled; private boolean mForceBlockWifi; - // Track as little state as possible, and only for padding purposes private boolean mIsAirplaneMode = false; private boolean mWifiVisible = false; @@ -177,8 +176,9 @@ public class StatusBarSignalPolicy implements NetworkControllerImpl.SignalCallba @Override public void setMobileDataIndicators(IconState statusIcon, IconState qsIcon, int statusType, - int qsType, boolean activityIn, boolean activityOut, String typeContentDescription, - String description, boolean isWide, int subId, boolean roaming) { + int qsType, boolean activityIn, boolean activityOut, int volteIcon, + String typeContentDescription, String description, boolean isWide, + int subId, boolean roaming) { MobileIconState state = getState(subId); if (state == null) { return; @@ -195,6 +195,7 @@ public class StatusBarSignalPolicy implements NetworkControllerImpl.SignalCallba state.roaming = roaming; state.activityIn = activityIn && mActivityEnabled; state.activityOut = activityOut && mActivityEnabled; + state.volteId = volteIcon; // Always send a copy to maintain value type semantics mIconController.setMobileIcons(mSlotMobile, MobileIconState.copyStates(mMobileStates)); @@ -388,6 +389,7 @@ public class StatusBarSignalPolicy implements NetworkControllerImpl.SignalCallba public boolean roaming; public boolean needsLeadingPadding; public String typeContentDescription; + public int volteId; private MobileIconState(int subId) { super(); @@ -408,7 +410,8 @@ public class StatusBarSignalPolicy implements NetworkControllerImpl.SignalCallba typeId == that.typeId && roaming == that.roaming && needsLeadingPadding == that.needsLeadingPadding && - Objects.equals(typeContentDescription, that.typeContentDescription); + Objects.equals(typeContentDescription, that.typeContentDescription) && + volteId == that.volteId; } @Override @@ -433,6 +436,7 @@ public class StatusBarSignalPolicy implements NetworkControllerImpl.SignalCallba other.roaming = roaming; other.needsLeadingPadding = needsLeadingPadding; other.typeContentDescription = typeContentDescription; + other.volteId = volteId; } private static List<MobileIconState> copyStates(List<MobileIconState> inStates) { @@ -448,7 +452,8 @@ public class StatusBarSignalPolicy implements NetworkControllerImpl.SignalCallba @Override public String toString() { return "MobileIconState(subId=" + subId + ", strengthId=" + strengthId + ", roaming=" - + roaming + ", typeId=" + typeId + ", visible=" + visible + ")"; + + roaming + ", typeId=" + typeId + ", volteId=" + volteId + + ", visible=" + visible + ")"; } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java index e1bb19a6f69f..5e47f95945d0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java @@ -125,15 +125,16 @@ public class CallbackHandler extends Handler implements EmergencyListener, Signa @Override public void setMobileDataIndicators(final IconState statusIcon, final IconState qsIcon, final int statusType, final int qsType,final boolean activityIn, - final boolean activityOut, final String typeContentDescription, - final String description, final boolean isWide, final int subId, boolean roaming) { + final boolean activityOut, final int volteIcon, + final String typeContentDescription, final String description, final boolean isWide, + final int subId, boolean roaming) { post(new Runnable() { @Override public void run() { for (SignalCallback signalCluster : mSignalCallbacks) { signalCluster.setMobileDataIndicators(statusIcon, qsIcon, statusType, qsType, - activityIn, activityOut, typeContentDescription, description, isWide, - subId, roaming); + activityIn, activityOut, volteIcon, typeContentDescription, + description, isWide, subId, roaming); } } }); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FiveGServiceClient.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FiveGServiceClient.java new file mode 100644 index 000000000000..f530336b8302 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FiveGServiceClient.java @@ -0,0 +1,610 @@ +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.android.systemui.statusbar.policy; + +import android.content.ComponentName; +import android.content.Context; +import android.content.ContentResolver; +import android.content.ServiceConnection; +import android.database.ContentObserver; +import android.net.Uri; +import android.os.Handler; +import android.os.IBinder; +import android.os.Message; +import android.os.RemoteException; +import android.provider.Settings; +import android.telephony.SubscriptionManager; +import android.telephony.TelephonyManager; +import android.util.Log; +import android.util.SparseArray; + +import java.lang.Exception; + +import org.codeaurora.internal.BearerAllocationStatus; +import org.codeaurora.internal.Client; +import org.codeaurora.internal.DcParam; +import org.codeaurora.internal.IExtTelephony; +import org.codeaurora.internal.INetworkCallback; +import org.codeaurora.internal.NetworkCallbackBase; +import org.codeaurora.internal.NrConfigType; +import org.codeaurora.internal.ServiceUtil; +import org.codeaurora.internal.SignalStrength; +import org.codeaurora.internal.Status; +import org.codeaurora.internal.Token; +import org.codeaurora.internal.UpperLayerIndInfo; + +import com.android.systemui.R; +import com.android.systemui.statusbar.policy.MobileSignalController.MobileIconGroup; + +public class FiveGServiceClient { + private static final String TAG = "FiveGServiceClient"; + private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG)||true; + private static final String FIVEG_UWB_INDICATOR_CONFIG = "5gUwbIndicatorConfig"; + private static final String FIVEG_BASIC_INDICATOR_CONFIG = "5gBasicIndicatorConfig"; + private static final String INDICATOR_CONFIG_UNKNOWN = "unknown"; + private static final String INDICATOR_CONFIG_CONFIGURATION1 = "Configuration1"; + private static final String INDICATOR_CONFIG_CONFIGURATION2 = "Configuration2"; + private static final String INDICATOR_CONFIG_SPARE1 = "Spare1"; + private static final String INDICATOR_CONFIG_SPARE2 = "Spare2"; + private static final String INDICATOR_CONFIG_R15_ENABLED = "r15Enabled"; + private static final int MESSAGE_REBIND = 1024; + private static final int MESSAGE_REINIT = MESSAGE_REBIND+1; + private static final int MAX_RETRY = 4; + private static final int DELAY_MILLISECOND = 3000; + private static final int DELAY_INCREMENT = 2000; + private final int mRsrpThresholds[]; + private final int mSnrThresholds[]; + private final SparseArray<IFiveGStateListener> mStatesListeners = new SparseArray<>(); + private final SparseArray<FiveGServiceState> mCurrentServiceStates = new SparseArray<>(); + private final SparseArray<FiveGServiceState> mLastServiceStates = new SparseArray<>(); + private final SparseArray<IndicatorConfig> mIndicatorConfigs = new SparseArray<>(); + + private Context mContext; + private boolean mServiceConnected; + private IExtTelephony mNetworkService; + private String mPackageName; + private Client mClient; + private int mBindRetryTimes = 0; + private int mInitRetryTimes = 0; + + private ContentResolver mResolver; + private ContentObserver mConfigObserver; + + private class IndicatorConfig { + public String uwb; + public String basic; + + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append(FIVEG_UWB_INDICATOR_CONFIG +"=" +uwb).append(" ") + .append(FIVEG_BASIC_INDICATOR_CONFIG).append("=").append(basic); + return builder.toString(); + } + } + + public static class FiveGServiceState{ + private int mBearerAllocationStatus; + private int mPlmn; + private int mUpperLayerInd; + private int mDcnr; + private int mLevel; + private int mNrConfigType; + private MobileIconGroup mIconGroup; + + public FiveGServiceState(){ + mBearerAllocationStatus = BearerAllocationStatus.NOT_ALLOCATED; + mPlmn = UpperLayerIndInfo.PLMN_INFO_LIST_UNAVAILABLE; + mUpperLayerInd = UpperLayerIndInfo.UPPER_LAYER_IND_INFO_UNAVAILABLE; + mDcnr = DcParam.DCNR_RESTRICTED; + mLevel = 0; + mNrConfigType = NrConfigType.NSA_CONFIGURATION; + mIconGroup = TelephonyIcons.UNKNOWN; + } + + public boolean isConnectedOnSaMode() { + boolean connected = false; + if ( mNrConfigType == NrConfigType.SA_CONFIGURATION + && mIconGroup != TelephonyIcons.UNKNOWN) { + connected = true; + } + return connected; + } + + public boolean isConnectedOnNsaMode() { + boolean connected = false; + if ( mNrConfigType == NrConfigType.NSA_CONFIGURATION + && mIconGroup != TelephonyIcons.UNKNOWN) { + connected = true; + } + return connected; + } + + public MobileIconGroup getIconGroup() { + return mIconGroup; + } + + public int getSignalLevel() { + return mLevel; + } + + public int getAllocated() { + return mBearerAllocationStatus; + } + + public void copyFrom(FiveGServiceState state) { + this.mBearerAllocationStatus = state.mBearerAllocationStatus; + this.mPlmn = state.mPlmn; + this.mUpperLayerInd = state.mUpperLayerInd; + this.mDcnr = state.mDcnr; + this.mLevel = state.mLevel; + this.mNrConfigType = state.mNrConfigType; + this.mIconGroup = state.mIconGroup; + } + + public boolean equals(FiveGServiceState state) { + return this.mBearerAllocationStatus == state.mBearerAllocationStatus + && this.mPlmn == state.mPlmn + && this.mUpperLayerInd == state.mUpperLayerInd + && this.mDcnr == state.mDcnr + && this.mLevel == state.mLevel + && this.mNrConfigType == state.mNrConfigType + && this.mIconGroup == state.mIconGroup; + } + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("mBearerAllocationStatus="). + append(mBearerAllocationStatus).append(", "). + append("mPlmn=").append(mPlmn).append(", "). + append("mUpperLayerInd=").append(mUpperLayerInd).append(", "). + append("mDcnr=" + mDcnr).append(", "). + append("mLevel=").append(mLevel).append(", "). + append("mNrConfigType=").append(mNrConfigType).append(", "). + append("mIconGroup=").append(mIconGroup); + + return builder.toString(); + } + } + + public FiveGServiceClient(Context context) { + mContext = context; + mPackageName = mContext.getPackageName(); + mResolver = mContext.getContentResolver(); + + mRsrpThresholds = + mContext.getResources().getIntArray(R.array.config_5g_signal_rsrp_thresholds); + mSnrThresholds = + mContext.getResources().getIntArray(R.array.config_5g_signal_snr_thresholds); + + initContentObserver(); + } + + public void registerListener(int phoneId, IFiveGStateListener listener) { + Log.d(TAG, "registerListener phoneId=" + phoneId); + + mStatesListeners.put(phoneId, listener); + if ( !isServiceConnected() ) { + binderService(); + }else{ + initFiveGServiceState(phoneId); + } + } + + public void unregisterListener(int phoneId) { + Log.d(TAG, "unregisterListener phoneId=" + phoneId); + mStatesListeners.remove(phoneId); + mCurrentServiceStates.remove(phoneId); + mLastServiceStates.remove(phoneId); + } + + private void binderService() { + boolean success = ServiceUtil.bindService(mContext, mServiceConnection); + Log.d(TAG, " bind service " + success); + if ( !success && mBindRetryTimes < MAX_RETRY && !mHandler.hasMessages(MESSAGE_REBIND)) { + mHandler.sendEmptyMessageDelayed(MESSAGE_REBIND, + DELAY_MILLISECOND + mBindRetryTimes*DELAY_INCREMENT); + mBindRetryTimes+=1; + } + } + + public static int getNumLevels(Context context) { + return context.getResources().getInteger(R.integer.config_5g_num_signal_strength_bins); + } + + public boolean isServiceConnected() { + return mServiceConnected; + } + + private FiveGServiceState getCurrentServiceState(int phoneId) { + return getServiceState(phoneId, mCurrentServiceStates); + } + + private FiveGServiceState getLastServiceState(int phoneId) { + return getServiceState(phoneId, mLastServiceStates); + } + + private static FiveGServiceState getServiceState(int key, + SparseArray<FiveGServiceState> array) { + FiveGServiceState state = array.get(key); + if ( state == null ) { + state = new FiveGServiceState(); + array.put(key, state); + } + return state; + } + + private int getSnrLevel(int snr) { + return getLevel(snr, mSnrThresholds); + } + + private int getRsrpLevel(int rsrp) { + return getLevel(rsrp, mRsrpThresholds); + } + + private static int getLevel(int value, int[]thresholds) { + int level = 0; + if ( thresholds[thresholds.length-1] < value || value < thresholds[0] ) { + level = 0; + } else{ + level = 1; + for( int i=0; i < thresholds.length-1; ++i ) { + if (thresholds[i] < value && value <= thresholds[i+1]) { + level = i+1; + break; + } + } + } + if ( DEBUG ) { + Log.d(TAG, "value=" + value + " level=" + level); + } + return level; + } + + private void notifyListenersIfNecessary(int phoneId) { + FiveGServiceState currentState = getCurrentServiceState(phoneId); + FiveGServiceState lastState = getLastServiceState(phoneId); + if ( !currentState.equals(lastState) ) { + + if ( DEBUG ) { + Log.d(TAG,"phoneId(" + phoneId + ") Config=" + getIndicatorConfig(phoneId)); + Log.d(TAG, "phoneId(" + phoneId + ") Change in state from " + lastState + " \n"+ + "\tto " + currentState); + + } + + lastState.copyFrom(currentState); + IFiveGStateListener listener = mStatesListeners.get(phoneId); + if (listener != null) { + listener.onStateChanged(currentState); + } + + } + } + + private void initFiveGServiceState() { + Log.d(TAG, "initFiveGServiceState size=" + mStatesListeners.size()); + for( int i=0; i < mStatesListeners.size(); ++i ) { + int phoneId = mStatesListeners.keyAt(i); + initFiveGServiceState(phoneId); + } + } + + private void initFiveGServiceState(int phoneId) { + Log.d(TAG, "mNetworkService=" + mNetworkService + " mClient=" + mClient); + if ( mNetworkService != null && mClient != null) { + Log.d(TAG, "query 5G service state for phoneId " + phoneId); + try { + Token token = mNetworkService.queryNrDcParam(phoneId, mClient); + Log.d(TAG, "queryNrDcParam result:" + token); + + token = mNetworkService.queryNrBearerAllocation(phoneId, mClient); + Log.d(TAG, "queryNrBearerAllocation result:" + token); + + token = mNetworkService.queryNrSignalStrength(phoneId, mClient); + Log.d(TAG, "queryNrSignalStrength result:" + token); + + token = mNetworkService.queryUpperLayerIndInfo(phoneId, mClient); + Log.d(TAG, "queryUpperLayerIndInfo result:" + token); + + token = mNetworkService.query5gConfigInfo(phoneId, mClient); + Log.d(TAG, "query5gConfigInfo result:" + token); + }catch (Exception e) { + Log.d(TAG, "initFiveGServiceState: Exception = " + e); + if ( mInitRetryTimes < MAX_RETRY && !mHandler.hasMessages(MESSAGE_REINIT) ) { + mHandler.sendEmptyMessageDelayed(MESSAGE_REINIT, + DELAY_MILLISECOND + mInitRetryTimes*DELAY_INCREMENT); + mInitRetryTimes +=1; + } + } + } + } + + private void initContentObserver() { + mConfigObserver = new ContentObserver(null) { + public void onChange(boolean selfChange, Uri uri) { + onConfigChange(); + } + }; + + TelephonyManager tm = (TelephonyManager) + mContext.getSystemService(Context.TELEPHONY_SERVICE); + int phoneCount = tm.getPhoneCount(); + for (int i = 0; i < phoneCount; i++) { + Uri uwbUri = Settings.Global.getUriFor(FIVEG_UWB_INDICATOR_CONFIG + i); + Uri basicUri = Settings.Global.getUriFor(FIVEG_BASIC_INDICATOR_CONFIG + i); + mResolver.registerContentObserver(uwbUri, false, mConfigObserver); + mResolver.registerContentObserver(basicUri, false, mConfigObserver); + Log.d(TAG, "Register observer to watch global settings uri(" + uwbUri + ")"); + Log.d(TAG, "Register observer to watch global settings uri(" + basicUri + ")"); + } + } + + private IndicatorConfig getIndicatorConfig(int phoneId) { + IndicatorConfig config = mIndicatorConfigs.get(phoneId); + if ( config == null ) { + config = new IndicatorConfig(); + loadConfg(phoneId, config); + Log.d(TAG, "new config for phoneId=" + phoneId + " confg=" + config); + mIndicatorConfigs.put(phoneId, config); + } + + return config; + } + + private void onConfigChange() { + Log.d(TAG, "onConfigChange"); + for ( int i=0; i < mStatesListeners.size(); ++i ) { + int phoneId = mStatesListeners.keyAt(i); + IndicatorConfig config = getIndicatorConfig(phoneId); + loadConfg(phoneId, config); + FiveGServiceState state = getCurrentServiceState(phoneId); + + Log.d(TAG, "phoneId(" + phoneId + ") " + config + " state=" + state); + + update5GIcon(state, phoneId); + notifyListenersIfNecessary(phoneId); + } + } + + private void loadConfg(int phoneId, IndicatorConfig config) { + String uwb = Settings.Global.getString(mResolver, + FIVEG_UWB_INDICATOR_CONFIG + phoneId); + config.uwb = uwb != null ? uwb : INDICATOR_CONFIG_UNKNOWN; + + String basic = Settings.Global.getString(mResolver, + FIVEG_BASIC_INDICATOR_CONFIG + phoneId); + config.basic = basic != null ? basic : INDICATOR_CONFIG_UNKNOWN; + } + + private void update5GIcon(FiveGServiceState state,int phoneId) { + if ( state.mNrConfigType == NrConfigType.SA_CONFIGURATION ) { + state.mIconGroup = getSaIcon(state); + }else if ( state.mNrConfigType == NrConfigType.NSA_CONFIGURATION){ + state.mIconGroup = getNsaIcon(state, phoneId); + }else { + state.mIconGroup = TelephonyIcons.UNKNOWN; + } + } + + private MobileIconGroup getSaIcon(FiveGServiceState state) { + if ( state.mBearerAllocationStatus > BearerAllocationStatus.NOT_ALLOCATED ) { + return TelephonyIcons.FIVE_G_SA; + }else { + return TelephonyIcons.UNKNOWN; + } + } + + private MobileIconGroup getNsaIcon(FiveGServiceState state, int phoneId) { + MobileIconGroup iconGroup = TelephonyIcons.UNKNOWN; + IndicatorConfig config = getIndicatorConfig(phoneId); + if (config.uwb.equals(INDICATOR_CONFIG_CONFIGURATION1)) { + if (state.mPlmn == UpperLayerIndInfo.PLMN_INFO_LIST_AVAILABLE + && state.mUpperLayerInd == UpperLayerIndInfo.UPPER_LAYER_IND_INFO_AVAILABLE + && state.mDcnr == DcParam.DCNR_UNRESTRICTED) { + iconGroup = TelephonyIcons.FIVE_G_UWB; + } else if (config.basic.equals(INDICATOR_CONFIG_R15_ENABLED) + && state.mPlmn == UpperLayerIndInfo.PLMN_INFO_LIST_AVAILABLE + && (state.mUpperLayerInd == UpperLayerIndInfo.UPPER_LAYER_IND_INFO_UNAVAILABLE + || state.mDcnr == DcParam.DCNR_RESTRICTED)) { + iconGroup = TelephonyIcons.FIVE_G_BASIC; + } + } else if (config.uwb.equals(INDICATOR_CONFIG_CONFIGURATION2)) { + if (state.mBearerAllocationStatus == BearerAllocationStatus.MMW_ALLOCATED) { + iconGroup = TelephonyIcons.FIVE_G_UWB; + } else if (config.basic.equals(INDICATOR_CONFIG_R15_ENABLED) + && state.mPlmn == UpperLayerIndInfo.PLMN_INFO_LIST_AVAILABLE + && state.mBearerAllocationStatus != BearerAllocationStatus.MMW_ALLOCATED) { + iconGroup = TelephonyIcons.FIVE_G_BASIC; + } + }else if ( !config.uwb.equals(INDICATOR_CONFIG_SPARE1) + && !config.uwb.equals(INDICATOR_CONFIG_SPARE2) ) { + // For FR44465 + if ( state.mUpperLayerInd == UpperLayerIndInfo.UPPER_LAYER_IND_INFO_AVAILABLE + && state.mDcnr == DcParam.DCNR_UNRESTRICTED ) { + iconGroup = TelephonyIcons.FIVE_G; + } + } + + return iconGroup; + } + + private Handler mHandler = new Handler() { + public void handleMessage(Message msg) { + int what = msg.what; + switch ( msg.what ) { + case MESSAGE_REBIND: + binderService(); + break; + + case MESSAGE_REINIT: + initFiveGServiceState(); + break; + } + + } + }; + + private ServiceConnection mServiceConnection = new ServiceConnection() { + @Override + public void onServiceConnected(ComponentName name, IBinder service) { + Log.d(TAG, "onServiceConnected:" + service); + + try { + mNetworkService = IExtTelephony.Stub.asInterface(service); + mClient = mNetworkService.registerCallback(mPackageName, mCallback); + mServiceConnected = true; + initFiveGServiceState(); + Log.d(TAG, "Client = " + mClient); + } catch (Exception e) { + Log.d(TAG, "onServiceConnected: Exception = " + e); + } + } + + @Override + public void onServiceDisconnected(ComponentName name) { + Log.d(TAG, "onServiceDisconnected:" + name); + cleanup(); + } + + @Override + public void onBindingDied(ComponentName name) { + Log.d(TAG, "onBindingDied:" + name); + cleanup(); + if ( mBindRetryTimes < MAX_RETRY ) { + Log.d(TAG, "try to re-bind"); + mHandler.sendEmptyMessageDelayed(MESSAGE_REBIND, + DELAY_MILLISECOND+mBindRetryTimes*DELAY_INCREMENT); + } + } + + private void cleanup() { + Log.d(TAG, "cleanup"); + mServiceConnected = false; + mNetworkService = null; + mClient = null; + } + }; + + + private INetworkCallback mCallback = new NetworkCallbackBase() { + @Override + public void on5gStatus(int slotId, Token token, Status status, boolean enableStatus) throws + RemoteException { + if ( DEBUG ) { + Log.d(TAG, "on5gStatus: slotId= " + slotId + " token=" + token + " status=" + + status + " enableStatus=" + enableStatus); + } + } + + @Override + public void onNrDcParam(int slotId, Token token, Status status, DcParam dcParam) throws + RemoteException { + + if ( DEBUG ) { + Log.d(TAG, "onNrDcParam: slotId=" + slotId + " token=" + token + " status=" + + status + " dcParam=" + dcParam); + } + + if (status.get() == Status.SUCCESS) { + FiveGServiceState state = getCurrentServiceState(slotId); + state.mDcnr = dcParam.getDcnr(); + update5GIcon(state, slotId); + notifyListenersIfNecessary(slotId); + } + } + + @Override + public void onSignalStrength(int slotId, Token token, Status status, + org.codeaurora.internal.SignalStrength + signalStrength) throws RemoteException { + if ( DEBUG ) { + Log.d(TAG, "onSignalStrength: slotId=" + slotId + " token=" + token + + " status=" + status + " signalStrength=" + signalStrength); + } + + if (status.get() == Status.SUCCESS && signalStrength != null) { + FiveGServiceState state = getCurrentServiceState(slotId); + state.mLevel = getRsrpLevel(signalStrength.getRsrp()); + notifyListenersIfNecessary(slotId); + } + } + + @Override + public void onAnyNrBearerAllocation(int slotId, Token token, Status status, + BearerAllocationStatus bearerStatus) throws RemoteException { + if ( DEBUG ) { + Log.d(TAG, "onAnyNrBearerAllocation bearerStatus=" + bearerStatus.get()); + } + + if (status.get() == Status.SUCCESS) { + FiveGServiceState state = getCurrentServiceState(slotId); + state.mBearerAllocationStatus = bearerStatus.get(); + update5GIcon(state, slotId); + notifyListenersIfNecessary(slotId); + } + + } + + @Override + public void onUpperLayerIndInfo(int slotId, Token token, Status status, + UpperLayerIndInfo uilInfo) throws RemoteException { + if ( DEBUG ) { + Log.d(TAG, "onUpperLayerIndInfo plmn=" + uilInfo.getPlmnInfoListAvailable() + + " upperLayerIndInfo=" + uilInfo.getUpperLayerIndInfoAvailable()); + } + + if (status.get() == Status.SUCCESS) { + FiveGServiceState state = getCurrentServiceState(slotId); + state.mPlmn = uilInfo.getPlmnInfoListAvailable(); + state.mUpperLayerInd = uilInfo.getUpperLayerIndInfoAvailable(); + update5GIcon(state, slotId); + notifyListenersIfNecessary(slotId); + } + } + + @Override + public void on5gConfigInfo(int slotId, Token token, Status status, NrConfigType + nrConfigType) throws RemoteException { + Log.d(TAG, + "on5gConfigInfo: slotId = " + slotId + " token = " + token + " " + "status" + + status + " NrConfigType = " + nrConfigType); + if (status.get() == Status.SUCCESS) { + FiveGServiceState state = getCurrentServiceState(slotId); + state.mNrConfigType = nrConfigType.get(); + update5GIcon(state, slotId); + notifyListenersIfNecessary(slotId); + } + } + }; + + public interface IFiveGStateListener { + public void onStateChanged(FiveGServiceState state); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java index b561ac1664c0..877540517c15 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java @@ -222,6 +222,17 @@ public class HotspotControllerImpl implements HotspotController, WifiManager.Sof @Override public void onNumClientsChanged(int numConnectedDevices) { + // Do nothing - we don't care about changing anything here. + } + + @Override + public void onStaConnected(String Macaddr, int numConnectedDevices) { + mNumConnectedDevices = numConnectedDevices; + fireHotspotChangedCallback(); + } + + @Override + public void onStaDisconnected(String Macaddr, int numConnectedDevices) { mNumConnectedDevices = numConnectedDevices; fireHotspotChangedCallback(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java index 3deede091a05..307e76f5bf95 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java @@ -15,13 +15,19 @@ */ package com.android.systemui.statusbar.policy; +import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; +import android.content.res.Resources; import android.database.ContentObserver; import android.net.NetworkCapabilities; import android.os.Handler; import android.os.Looper; import android.provider.Settings.Global; +import android.telephony.ims.ImsMmTelManager; +import android.telephony.ims.ImsReasonInfo; +import android.telephony.ims.stub.ImsRegistrationImplBase; import android.telephony.NetworkRegistrationState; import android.telephony.PhoneStateListener; import android.telephony.ServiceState; @@ -33,12 +39,19 @@ import android.text.TextUtils; import android.util.Log; import android.util.SparseArray; +import com.android.ims.ImsException; +import com.android.ims.ImsManager; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.telephony.TelephonyIntents; import com.android.internal.telephony.cdma.EriInfo; +import com.android.internal.telephony.PhoneConstants; +import com.android.internal.telephony.PhoneConstants.DataState; import com.android.settingslib.Utils; import com.android.settingslib.graph.SignalDrawable; import com.android.systemui.R; +import com.android.systemui.statusbar.policy.FiveGServiceClient; +import com.android.systemui.statusbar.policy.FiveGServiceClient.FiveGServiceState; +import com.android.systemui.statusbar.policy.FiveGServiceClient.IFiveGStateListener; import com.android.systemui.statusbar.policy.NetworkController.IconState; import com.android.systemui.statusbar.policy.NetworkController.SignalCallback; import com.android.systemui.statusbar.policy.NetworkControllerImpl.Config; @@ -69,11 +82,25 @@ public class MobileSignalController extends SignalController< // of code. private int mDataNetType = TelephonyManager.NETWORK_TYPE_UNKNOWN; private int mDataState = TelephonyManager.DATA_DISCONNECTED; + private DataState mMMSDataState = DataState.DISCONNECTED; private ServiceState mServiceState; private SignalStrength mSignalStrength; private MobileIconGroup mDefaultIcons; private Config mConfig; + private boolean mAlwasyShowTypeIcon = false; + private boolean mShow2GForCDMA_1x = false; + private boolean mHideNoInternetState = false; + private int mCallState = TelephonyManager.CALL_STATE_IDLE; + + /****************************5G****************************/ + private FiveGStateListener mFiveGStateListener; + private FiveGServiceState mFiveGState; + private final int NUM_LEVELS_ON_5G; + /**********************************************************/ + + private ImsManager mImsManager; + // TODO: Reduce number of vars passed in, if we have the NetworkController, probably don't // need listener lists anymore. public MobileSignalController(Context context, Config config, boolean hasMobileData, @@ -90,10 +117,16 @@ public class MobileSignalController extends SignalController< mSubscriptionInfo = info; mPhoneStateListener = new MobilePhoneStateListener(info.getSubscriptionId(), receiverLooper); + mFiveGStateListener = new FiveGStateListener(); + mFiveGState = new FiveGServiceState(); mNetworkNameSeparator = getStringIfExists(R.string.status_bar_network_name_separator); mNetworkNameDefault = getStringIfExists( com.android.internal.R.string.lockscreen_carrier_default); + mAlwasyShowTypeIcon = context.getResources().getBoolean(R.bool.config_alwaysShowTypeIcon); + mShow2GForCDMA_1x = context.getResources().getBoolean(R.bool.config_show2GforCDMA_1X); + mHideNoInternetState = context.getResources().getBoolean(R.bool.config_hideNoInternetState); + mapIconSets(); String networkName = info.getCarrierName() != null ? info.getCarrierName().toString() @@ -104,6 +137,13 @@ public class MobileSignalController extends SignalController< mLastState.iconGroup = mCurrentState.iconGroup = mDefaultIcons; // Get initial data sim state. updateDataSim(); + + NUM_LEVELS_ON_5G = FiveGServiceClient.getNumLevels(mContext); + + int phoneId = SubscriptionManager.getPhoneId(mSubscriptionInfo.getSubscriptionId()); + mImsManager = ImsManager.getInstance(mContext, phoneId); + updateImsRegistrationState(); + mObserver = new ContentObserver(new Handler(receiverLooper)) { @Override public void onChange(boolean selfChange) { @@ -162,6 +202,13 @@ public class MobileSignalController extends SignalController< mContext.getContentResolver().registerContentObserver(Global.getUriFor( Global.MOBILE_DATA + mSubscriptionInfo.getSubscriptionId()), true, mObserver); + try { + mImsManager.addRegistrationCallback(mImsRegistrationCallback); + }catch(ImsException e){ + Log.d(mTag, "exception:" + e); + } + mContext.registerReceiver(mVolteSwitchObserver, + new IntentFilter("org.codeaurora.intent.action.ACTION_ENHANCE_4G_SWITCH")); } /** @@ -170,6 +217,8 @@ public class MobileSignalController extends SignalController< public void unregisterListener() { mPhone.listen(mPhoneStateListener, 0); mContext.getContentResolver().unregisterContentObserver(mObserver); + mImsManager.removeRegistrationListener(mImsRegistrationCallback); + mContext.unregisterReceiver(mVolteSwitchObserver); } /** @@ -190,8 +239,13 @@ public class MobileSignalController extends SignalController< mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_UNKNOWN, TelephonyIcons.UNKNOWN); mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EDGE, TelephonyIcons.E); - mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_CDMA, TelephonyIcons.ONE_X); - mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_1xRTT, TelephonyIcons.ONE_X); + if (mShow2GForCDMA_1x) { + mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_CDMA, TelephonyIcons.TWO_G); + mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_1xRTT, TelephonyIcons.TWO_G); + }else { + mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_CDMA, TelephonyIcons.ONE_X); + mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_1xRTT, TelephonyIcons.ONE_X); + } mDefaultIcons = TelephonyIcons.G; } else { @@ -255,10 +309,14 @@ public class MobileSignalController extends SignalController< if (mConfig.inflateSignalStrengths) { level++; } + boolean dataDisabled = mCurrentState.userSetup && mCurrentState.iconGroup == TelephonyIcons.DATA_DISABLED; boolean noInternet = mCurrentState.inetCondition == 0; boolean cutOut = dataDisabled || noInternet; + if (mHideNoInternetState) { + cutOut = false; + } return SignalDrawable.getState(level, getNumLevels(), cutOut); } else if (mCurrentState.enabled) { return SignalDrawable.getEmptyState(getNumLevels()); @@ -267,6 +325,18 @@ public class MobileSignalController extends SignalController< } } + public int getCurrent5GIconId() { + int level = mFiveGState.getSignalLevel(); + if (mConfig.inflateSignalStrengths) { + level++; + } + boolean dataDisabled = mCurrentState.userSetup + && mCurrentState.iconGroup == TelephonyIcons.DATA_DISABLED; + boolean noInternet = mCurrentState.inetCondition == 0; + boolean cutOut = dataDisabled || noInternet; + return SignalDrawable.getState(level, NUM_LEVELS_ON_5G , cutOut); + } + @Override public int getQsCurrentIconId() { if (mCurrentState.airplaneMode) { @@ -276,22 +346,54 @@ public class MobileSignalController extends SignalController< return getCurrentIconId(); } + private boolean isEnhanced4gLteModeSettingEnabled() { + return mImsManager.isEnhanced4gLteModeSettingEnabledByUser() + && mImsManager.isNonTtyOrTtyOnVolteEnabled(); + } + + private int getVolteResId() { + int resId = 0; + int voiceNetTye = getVoiceNetworkType(); + + if ( mCurrentState.imsResitered ) { + resId = R.drawable.ic_volte; + }else if ( mDataNetType == TelephonyManager.NETWORK_TYPE_LTE + || mDataNetType == TelephonyManager.NETWORK_TYPE_LTE_CA + || voiceNetTye == TelephonyManager.NETWORK_TYPE_LTE + || voiceNetTye == TelephonyManager.NETWORK_TYPE_LTE_CA) { + resId = R.drawable.ic_volte_no_voice; + } + return resId; + } + + private void updateImsRegistrationState() { + mCurrentState.imsResitered = mPhone.isImsRegistered(mSubscriptionInfo.getSubscriptionId()); + notifyListenersIfNecessary(); + } + @Override public void notifyListeners(SignalCallback callback) { MobileIconGroup icons = getIcons(); + final boolean dataDisabled = mCurrentState.iconGroup == TelephonyIcons.DATA_DISABLED + && mCurrentState.userSetup; + + if ( is5GConnected() ) { + if ( mFiveGState.isConnectedOnSaMode() + || mFiveGState.isConnectedOnNsaMode() && !dataDisabled ) { + icons = mFiveGState.getIconGroup(); + } + } String contentDescription = getStringIfExists(getContentDescription()); String dataContentDescription = getStringIfExists(icons.mDataContentDescription); if (mCurrentState.inetCondition == 0) { dataContentDescription = mContext.getString(R.string.data_connection_no_internet); } - final boolean dataDisabled = mCurrentState.iconGroup == TelephonyIcons.DATA_DISABLED - && mCurrentState.userSetup; // Show icon in QS when we are connected or data is disabled. boolean showDataIcon = mCurrentState.dataConnected || dataDisabled; IconState statusIcon = new IconState(mCurrentState.enabled && !mCurrentState.airplaneMode, - getCurrentIconId(), contentDescription); + is5GConnected() ? getCurrent5GIconId() : getCurrentIconId(), contentDescription); int qsTypeIcon = 0; IconState qsIcon = null; @@ -310,9 +412,26 @@ public class MobileSignalController extends SignalController< && !mCurrentState.carrierNetworkChangeMode && mCurrentState.activityOut; showDataIcon &= mCurrentState.isDefault || dataDisabled; - int typeIcon = (showDataIcon || mConfig.alwaysShowDataRatIcon) ? icons.mDataType : 0; + int typeIcon = (showDataIcon || mConfig.alwaysShowDataRatIcon || mAlwasyShowTypeIcon + || mFiveGState.isConnectedOnSaMode() ) ? icons.mDataType : 0; + int volteIcon = mConfig.showVolteIcon && isEnhanced4gLteModeSettingEnabled() + ? getVolteResId() : 0; + if (DEBUG) { + Log.d(mTag, "notifyListeners mAlwasyShowTypeIcon=" + mAlwasyShowTypeIcon + + " mDataNetType:" + mDataNetType + + "/" + TelephonyManager.getNetworkTypeName(mDataNetType) + + " voiceNetType=" + getVoiceNetworkType() + "/" + + TelephonyManager.getNetworkTypeName(getVoiceNetworkType()) + + " showDataIcon=" + showDataIcon + + " mConfig.alwaysShowDataRatIcon=" + mConfig.alwaysShowDataRatIcon + + " icons.mDataType=" + icons.mDataType + + " mConfig.showVolteIcon=" + mConfig.showVolteIcon + + " isEnhanced4gLteModeSettingEnabled=" + isEnhanced4gLteModeSettingEnabled() + + " volteIcon=" + volteIcon); + } callback.setMobileDataIndicators(statusIcon, qsIcon, typeIcon, qsTypeIcon, - activityIn, activityOut, dataContentDescription, description, icons.mIsWide, + activityIn, activityOut,volteIcon, + dataContentDescription, description, icons.mIsWide, mSubscriptionInfo.getSubscriptionId(), mCurrentState.roaming); } @@ -360,6 +479,16 @@ public class MobileSignalController extends SignalController< } else if (action.equals(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED)) { updateDataSim(); notifyListenersIfNecessary(); + }else if (action.equals(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED)) { + String apnType = intent.getStringExtra(PhoneConstants.DATA_APN_TYPE_KEY); + String state = intent.getStringExtra(PhoneConstants.STATE_KEY); + if ("mms".equals(apnType)) { + if (DEBUG) { + Log.d(mTag, "handleBroadcast MMS connection state=" + state); + } + mMMSDataState = DataState.valueOf(state); + updateTelephony(); + } } } @@ -436,6 +565,27 @@ public class MobileSignalController extends SignalController< mCurrentState.level = mSignalStrength.getCdmaLevel(); } else { mCurrentState.level = mSignalStrength.getLevel(); + if (mConfig.showRsrpSignalLevelforLTE) { + if (DEBUG) { + Log.d(mTag, "updateTelephony CS:" + mServiceState.getVoiceNetworkType() + + "/" + TelephonyManager.getNetworkTypeName( + mServiceState.getVoiceNetworkType()) + + ", PS:" + mServiceState.getDataNetworkType() + + "/"+ TelephonyManager.getNetworkTypeName( + mServiceState.getDataNetworkType())); + } + int dataType = mServiceState.getDataNetworkType(); + if (dataType == TelephonyManager.NETWORK_TYPE_LTE || + dataType == TelephonyManager.NETWORK_TYPE_LTE_CA) { + mCurrentState.level = getAlternateLteLevel(mSignalStrength); + }else if ( dataType == TelephonyManager.NETWORK_TYPE_UNKNOWN) { + int voiceType = mServiceState.getVoiceNetworkType(); + if (voiceType == TelephonyManager.NETWORK_TYPE_LTE || + voiceType == TelephonyManager.NETWORK_TYPE_LTE_CA) { + mCurrentState.level = getAlternateLteLevel(mSignalStrength); + } + } + } } } @@ -450,12 +600,13 @@ public class MobileSignalController extends SignalController< mCurrentState.iconGroup = mDefaultIcons; } mCurrentState.dataConnected = mCurrentState.connected - && mDataState == TelephonyManager.DATA_CONNECTED; + && (mDataState == TelephonyManager.DATA_CONNECTED + || mMMSDataState == DataState.CONNECTED); mCurrentState.roaming = isRoaming(); if (isCarrierNetworkChangeActive()) { mCurrentState.iconGroup = TelephonyIcons.CARRIER_NETWORK_CHANGE; - } else if (isDataDisabled() && !mConfig.alwaysShowDataRatIcon) { + } else if (isDataDisabled() && (!mConfig.alwaysShowDataRatIcon && !mAlwasyShowTypeIcon)) { mCurrentState.iconGroup = TelephonyIcons.DATA_DISABLED; } if (isEmergencyOnly() != mCurrentState.isEmergency) { @@ -505,6 +656,67 @@ public class MobileSignalController extends SignalController< return !mPhone.getDataEnabled(mSubscriptionInfo.getSubscriptionId()); } + private boolean isDataNetworkTypeAvailable() { + boolean isAvailable = true; + if ( mDataNetType == TelephonyManager.NETWORK_TYPE_UNKNOWN ) { + isAvailable = false; + }else { + int dataType = getDataNetworkType(); + int voiceType = getVoiceNetworkType(); + if ((dataType == TelephonyManager.NETWORK_TYPE_EVDO_A + || dataType == TelephonyManager.NETWORK_TYPE_EVDO_B + || dataType == TelephonyManager.NETWORK_TYPE_EHRPD + || dataType == TelephonyManager.NETWORK_TYPE_LTE + || dataType == TelephonyManager.NETWORK_TYPE_LTE_CA) + && (voiceType == TelephonyManager.NETWORK_TYPE_GSM + || voiceType == TelephonyManager.NETWORK_TYPE_1xRTT + || voiceType == TelephonyManager.NETWORK_TYPE_CDMA) + && ( !isCallIdle() )) { + isAvailable = false; + } + } + + return isAvailable; + } + + private boolean isCallIdle() { + return mCallState == TelephonyManager.CALL_STATE_IDLE; + } + + private int getVoiceNetworkType() { + return mServiceState != null ? + mServiceState.getVoiceNetworkType() : TelephonyManager.NETWORK_TYPE_UNKNOWN; + } + + private int getDataNetworkType() { + return mServiceState != null ? + mServiceState.getDataNetworkType() : TelephonyManager.NETWORK_TYPE_UNKNOWN; + } + + private int getAlternateLteLevel(SignalStrength signalStrength) { + int lteRsrp = signalStrength.getLteDbm(); + if ( lteRsrp == SignalStrength.INVALID ) { + int signalStrengthLevel = signalStrength.getLevel(); + if (DEBUG) { + Log.d(mTag, "getAlternateLteLevel lteRsrp:INVALID " + + " signalStrengthLevel = " + signalStrengthLevel); + } + return signalStrengthLevel; + } + + int rsrpLevel = SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN; + if (lteRsrp > -44) rsrpLevel = SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN; + else if (lteRsrp >= -97) rsrpLevel = SignalStrength.SIGNAL_STRENGTH_GREAT; + else if (lteRsrp >= -105) rsrpLevel = SignalStrength.SIGNAL_STRENGTH_GOOD; + else if (lteRsrp >= -113) rsrpLevel = SignalStrength.SIGNAL_STRENGTH_MODERATE; + else if (lteRsrp >= -120) rsrpLevel = SignalStrength.SIGNAL_STRENGTH_POOR; + else if (lteRsrp >= -140) rsrpLevel = SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN; + if (DEBUG) { + Log.d(mTag, "getAlternateLteLevel lteRsrp:" + lteRsrp + " rsrpLevel = " + rsrpLevel); + } + return rsrpLevel; + } + @VisibleForTesting void setActivity(int activity) { mCurrentState.activityIn = activity == TelephonyManager.DATA_ACTIVITY_INOUT @@ -514,6 +726,31 @@ public class MobileSignalController extends SignalController< notifyListenersIfNecessary(); } + public void registerFiveGStateListener(FiveGServiceClient client) { + int phoneId = SubscriptionManager.getPhoneId(mSubscriptionInfo.getSubscriptionId()); + client.registerListener(phoneId, mFiveGStateListener); + } + + public void unregisterFiveGStateListener(FiveGServiceClient client) { + int phoneId = SubscriptionManager.getPhoneId(mSubscriptionInfo.getSubscriptionId()); + client.unregisterListener(phoneId); + } + + private boolean isDataRegisteredOnLte() { + boolean registered = false; + int dataType = getDataNetworkType(); + if (dataType == TelephonyManager.NETWORK_TYPE_LTE || + dataType == TelephonyManager.NETWORK_TYPE_LTE_CA) { + registered = true; + } + return registered; + } + + private boolean is5GConnected() { + return mFiveGState.isConnectedOnSaMode() + || mFiveGState.isConnectedOnNsaMode() && isDataRegisteredOnLte(); + } + @Override public void dump(PrintWriter pw) { super.dump(pw); @@ -522,6 +759,7 @@ public class MobileSignalController extends SignalController< pw.println(" mSignalStrength=" + mSignalStrength + ","); pw.println(" mDataState=" + mDataState + ","); pw.println(" mDataNetType=" + mDataNetType + ","); + pw.println(" mFiveGState=" + mFiveGState + ","); } class MobilePhoneStateListener extends PhoneStateListener { @@ -588,6 +826,58 @@ public class MobileSignalController extends SignalController< updateTelephony(); } + + @Override + public void onCallStateChanged(int state, String phoneNumber) { + if (DEBUG) { + Log.d(mTag, "onCallStateChanged: state=" + state); + } + mCallState = state; + updateTelephony(); + } + }; + + class FiveGStateListener implements IFiveGStateListener{ + + public void onStateChanged(FiveGServiceState state) { + if (DEBUG) { + Log.d(mTag, "onStateChanged: state=" + state); + } + mFiveGState = state; + notifyListeners(); + } + } + + private final ImsMmTelManager.RegistrationCallback mImsRegistrationCallback = + new ImsMmTelManager.RegistrationCallback() { + @Override + public void onRegistered( + @ImsRegistrationImplBase.ImsRegistrationTech int imsRadioTech) { + Log.d(mTag, "onRegistered imsRadioTech=" + imsRadioTech); + updateImsRegistrationState(); + } + + @Override + public void onRegistering( + @ImsRegistrationImplBase.ImsRegistrationTech int imsRadioTech) { + Log.d(mTag, "onRegistering imsRadioTech=" + imsRadioTech); + updateImsRegistrationState(); + } + + @Override + public void onDeregistered(ImsReasonInfo imsReasonInfo) { + Log.d(mTag, "onDeregistered imsReasonInfo=" + imsReasonInfo); + updateImsRegistrationState(); + } + }; + + private final BroadcastReceiver mVolteSwitchObserver = new BroadcastReceiver() { + public void onReceive(Context context, Intent intent) { + Log.d(mTag, "action=" + intent.getAction()); + if ( mConfig.showVolteIcon ) { + notifyListeners(); + } + } }; static class MobileIconGroup extends SignalController.IconGroup { @@ -619,6 +909,8 @@ public class MobileSignalController extends SignalController< boolean isDefault; boolean userSetup; boolean roaming; + boolean imsResitered; + @Override public void copyFrom(State s) { @@ -634,6 +926,7 @@ public class MobileSignalController extends SignalController< carrierNetworkChangeMode = state.carrierNetworkChangeMode; userSetup = state.userSetup; roaming = state.roaming; + imsResitered = state.imsResitered; } @Override @@ -650,7 +943,8 @@ public class MobileSignalController extends SignalController< builder.append("airplaneMode=").append(airplaneMode).append(','); builder.append("carrierNetworkChangeMode=").append(carrierNetworkChangeMode) .append(','); - builder.append("userSetup=").append(userSetup); + builder.append("userSetup=").append(userSetup).append(','); + builder.append("imsResitered=").append(imsResitered); } @Override @@ -665,7 +959,8 @@ public class MobileSignalController extends SignalController< && ((MobileState) o).carrierNetworkChangeMode == carrierNetworkChangeMode && ((MobileState) o).userSetup == userSetup && ((MobileState) o).isDefault == isDefault - && ((MobileState) o).roaming == roaming; + && ((MobileState) o).roaming == roaming + && ((MobileState) o).imsResitered == imsResitered; } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java index 51fef7d73993..291f9bbf901b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java @@ -51,8 +51,9 @@ public interface NetworkController extends CallbackController<SignalCallback>, D String statusLabel) {} default void setMobileDataIndicators(IconState statusIcon, IconState qsIcon, int statusType, - int qsType, boolean activityIn, boolean activityOut, String typeContentDescription, - String description, boolean isWide, int subId, boolean roaming) {} + int qsType, boolean activityIn, boolean activityOut, int volteIcon, + String typeContentDescription, String description, boolean isWide, + int subId, boolean roaming) {} default void setSubs(List<SubscriptionInfo> subs) {} default void setNoSims(boolean show, boolean simDetected) {} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java index f79ad71a114f..77c80dd3db57 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java @@ -157,6 +157,7 @@ public class NetworkControllerImpl extends BroadcastReceiver private boolean mUserSetup; private boolean mSimDetected; + private FiveGServiceClient mFiveGServiceClient; /** * Construct this controller object and register for updates. */ @@ -234,7 +235,7 @@ public class NetworkControllerImpl extends BroadcastReceiver deviceProvisionedController.getCurrentUser())); } }); - + mFiveGServiceClient = new FiveGServiceClient(context); ConnectivityManager.NetworkCallback callback = new ConnectivityManager.NetworkCallback(){ private Network mLastNetwork; private NetworkCapabilities mLastNetworkCapabilities; @@ -276,6 +277,7 @@ public class NetworkControllerImpl extends BroadcastReceiver for (int i = 0; i < mMobileSignalControllers.size(); i++) { MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i); mobileSignalController.registerListener(); + mobileSignalController.registerFiveGStateListener(mFiveGServiceClient); } if (mSubscriptionListener == null) { mSubscriptionListener = new SubListener(); @@ -296,6 +298,7 @@ public class NetworkControllerImpl extends BroadcastReceiver filter.addAction(ConnectivityManager.INET_CONDITION_ACTION); filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED); filter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED); + filter.addAction(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED); mContext.registerReceiver(this, filter, null, mReceiverHandler); mListening = true; @@ -307,6 +310,7 @@ public class NetworkControllerImpl extends BroadcastReceiver for (int i = 0; i < mMobileSignalControllers.size(); i++) { MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i); mobileSignalController.unregisterListener(); + mobileSignalController.unregisterFiveGStateListener(mFiveGServiceClient); } mSubscriptionManager.removeOnSubscriptionsChangedListener(mSubscriptionListener); mContext.unregisterReceiver(this); @@ -589,7 +593,7 @@ public class NetworkControllerImpl extends BroadcastReceiver public int compare(SubscriptionInfo lhs, SubscriptionInfo rhs) { return lhs.getSimSlotIndex() == rhs.getSimSlotIndex() ? lhs.getSubscriptionId() - rhs.getSubscriptionId() - : lhs.getSimSlotIndex() - rhs.getSimSlotIndex(); + : rhs.getSimSlotIndex() - lhs.getSimSlotIndex(); } }); mCurrentSubscriptions = subscriptions; @@ -619,6 +623,7 @@ public class NetworkControllerImpl extends BroadcastReceiver } if (mListening) { controller.registerListener(); + controller.registerFiveGStateListener(mFiveGServiceClient); } } } @@ -629,6 +634,7 @@ public class NetworkControllerImpl extends BroadcastReceiver mDefaultSignalController = null; } cachedControllers.get(key).unregisterListener(); + cachedControllers.get(key).unregisterFiveGStateListener(mFiveGServiceClient); } } mCallbackHandler.setSubs(subscriptions); @@ -1055,6 +1061,8 @@ public class NetworkControllerImpl extends BroadcastReceiver boolean hspaDataDistinguishable; boolean inflateSignalStrengths = false; boolean alwaysShowDataRatIcon = false; + boolean showRsrpSignalLevelforLTE; + boolean showVolteIcon; /** * Mapping from NR 5G status string to an integer. The NR 5G status string should match @@ -1102,7 +1110,9 @@ public class NetworkControllerImpl extends BroadcastReceiver } } } - + config.showRsrpSignalLevelforLTE = + res.getBoolean(R.bool.config_showRsrpSignalLevelforLTE); + config.showVolteIcon = res.getBoolean(R.bool.config_display_volte); return config; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java index 7347f66de8ce..a06c15db0214 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java @@ -32,12 +32,16 @@ class TelephonyIcons { static final int ICON_E = R.drawable.ic_e_mobiledata; static final int ICON_H = R.drawable.ic_h_mobiledata; static final int ICON_H_PLUS = R.drawable.ic_h_plus_mobiledata; + static final int ICON_2G = R.drawable.ic_2g_mobiledata; static final int ICON_3G = R.drawable.ic_3g_mobiledata; static final int ICON_4G = R.drawable.ic_4g_mobiledata; static final int ICON_4G_PLUS = R.drawable.ic_4g_plus_mobiledata; static final int ICON_1X = R.drawable.ic_1x_mobiledata; static final int ICON_5G = R.drawable.ic_5g_mobiledata; static final int ICON_5G_PLUS = R.drawable.ic_5g_plus_mobiledata; + static final int ICON_5G_SA = R.drawable.ic_5g_mobiledata; + static final int ICON_5G_BASIC = R.drawable.ic_5g_mobiledata; + static final int ICON_5G_UWB = R.drawable.ic_5g_uwb_mobiledata; static final MobileIconGroup CARRIER_NETWORK_CHANGE = new MobileIconGroup( "CARRIER_NETWORK_CHANGE", @@ -245,6 +249,71 @@ class TelephonyIcons { 0, false); + static final MobileIconGroup TWO_G = new MobileIconGroup( + "2G", + null, + null, + AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH, + 0, 0, + 0, + 0, + AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0], + R.string.data_connection_2g, + TelephonyIcons.ICON_2G, + false); + + static final MobileIconGroup FIVE_G = new MobileIconGroup( + "5G", + null, + null, + AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH, + 0, 0, + 0, + 0, + AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0], + R.string.data_connection_5g, + TelephonyIcons.ICON_5G, + false); + + static final MobileIconGroup FIVE_G_BASIC = new MobileIconGroup( + "5GBasic", + null, + null, + AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH, + 0, 0, + 0, + 0, + AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0], + R.string.data_connection_5g_basic, + TelephonyIcons.ICON_5G_BASIC, + false); + + static final MobileIconGroup FIVE_G_UWB = new MobileIconGroup( + "5GUWB", + null, + null, + AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH, + 0, 0, + 0, + 0, + AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0], + R.string.data_connection_5g_uwb, + TelephonyIcons.ICON_5G_UWB, + false); + + static final MobileIconGroup FIVE_G_SA = new MobileIconGroup( + "5GSA", + null, + null, + AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH, + 0, 0, + 0, + 0, + AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0], + R.string.data_connection_5g_sa, + TelephonyIcons.ICON_5G_SA, + false); + /** Mapping icon name(lower case) to the icon object. */ static final Map<String, MobileIconGroup> ICON_NAME_TO_ICON; static { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java index 6f63544d3cfa..c2c7623c5a67 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java @@ -82,10 +82,8 @@ public class WifiSignalController extends @Override public void notifyListeners(SignalCallback callback) { // only show wifi in the cluster if connected or if wifi-only - boolean visibleWhenEnabled = mContext.getResources().getBoolean( - R.bool.config_showWifiIndicatorWhenEnabled); boolean wifiVisible = mCurrentState.enabled - && (mCurrentState.connected || !mHasMobileData || visibleWhenEnabled); + && (mCurrentState.connected || !mHasMobileData); String wifiDesc = wifiVisible ? mCurrentState.ssid : null; boolean ssidPresent = wifiVisible && mCurrentState.ssid != null; String contentDescription = getStringIfExists(getContentDescription()); diff --git a/packages/SystemUI/tests/Android.mk b/packages/SystemUI/tests/Android.mk index 83ec33c69629..872d6f122e72 100644 --- a/packages/SystemUI/tests/Android.mk +++ b/packages/SystemUI/tests/Android.mk @@ -38,6 +38,10 @@ LOCAL_JAVA_LIBRARIES := \ android.test.runner \ telephony-common \ android.test.base \ + android.car \ + android.car.userlib \ + telephony-ext \ + ims-common LOCAL_AAPT_FLAGS := --extra-packages com.android.systemui:com.android.keyguard diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java index ed0f9ab224eb..f4ffb3b6c831 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java @@ -118,8 +118,8 @@ public class CallbackHandlerTest extends SysuiTestCase { boolean wide = true; int subId = 5; boolean roaming = true; - mHandler.setMobileDataIndicators(status, qs, type, qsType, in, out, typeDescription, - description, wide, subId, roaming); + mHandler.setMobileDataIndicators(status, qs, type, qsType, in, out, 0, + typeDescription, description, wide, subId, roaming); waitForCallbacks(); ArgumentCaptor<IconState> statusArg = ArgumentCaptor.forClass(IconState.class); @@ -134,7 +134,9 @@ public class CallbackHandlerTest extends SysuiTestCase { ArgumentCaptor<Integer> subIdArg = ArgumentCaptor.forClass(Integer.class); Mockito.verify(mSignalCallback).setMobileDataIndicators(statusArg.capture(), qsArg.capture(), typeIconArg.capture(), qsTypeIconArg.capture(), inArg.capture(), - outArg.capture(), typeContentArg.capture(), descArg.capture(), wideArg.capture(), + outArg.capture(), + ArgumentCaptor.forClass(Integer.class).capture(), + typeContentArg.capture(), descArg.capture(), wideArg.capture(), subIdArg.capture(), eq(roaming)); assertEquals(status, statusArg.getValue()); assertEquals(qs, qsArg.getValue()); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java index c1f88855ac24..657f6777c349 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java @@ -340,6 +340,7 @@ public class NetworkControllerBaseTest extends SysuiTestCase { iconArg.capture(), anyInt(), typeIconArg.capture(), dataInArg.capture(), dataOutArg.capture(), + ArgumentCaptor.forClass(Integer.class).capture(), anyString(), anyString(), anyBoolean(), anyInt(), anyBoolean()); IconState iconState = iconArg.getValue(); int state = SignalDrawable.getState(icon, SignalStrength.NUM_SIGNAL_STRENGTH_BINS, @@ -372,7 +373,9 @@ public class NetworkControllerBaseTest extends SysuiTestCase { iconArg.capture(), any(), typeIconArg.capture(), - anyInt(), anyBoolean(), anyBoolean(), anyString(), anyString(), anyBoolean(), + anyInt(), anyBoolean(), anyBoolean(), + ArgumentCaptor.forClass(Integer.class).capture(), + anyString(), anyString(), anyBoolean(), anyInt(), eq(roaming)); IconState iconState = iconArg.getValue(); @@ -406,6 +409,7 @@ public class NetworkControllerBaseTest extends SysuiTestCase { qsTypeIconArg.capture(), dataInArg.capture(), dataOutArg.capture(), + ArgumentCaptor.forClass(Integer.class).capture(), anyString(), anyString(), anyBoolean(), anyInt(), anyBoolean()); IconState iconState = iconArg.getValue(); diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java index a33338164caf..e6ada8ec2bfa 100644 --- a/services/core/java/com/android/server/BluetoothManagerService.java +++ b/services/core/java/com/android/server/BluetoothManagerService.java @@ -87,6 +87,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN; private static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH; + private static final String BLUETOOTH_PRIVILEGED_PERM = android.Manifest.permission.BLUETOOTH_PRIVILEGED; private static final String SECURE_SETTINGS_BLUETOOTH_ADDR_VALID = "bluetooth_addr_valid"; private static final String SECURE_SETTINGS_BLUETOOTH_ADDRESS = "bluetooth_address"; @@ -715,7 +716,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private void disableBleScanMode() { try { mBluetoothLock.writeLock().lock(); - if (mBluetooth != null && (mBluetooth.getState() != BluetoothAdapter.STATE_ON)) { + if (mBluetooth != null && (mBluetooth.getState() != BluetoothAdapter.STATE_ON) && (!isBluetoothPersistedStateOnBluetooth())) { if (DBG) { Slog.d(TAG, "Reseting the mEnable flag for clean disable"); } @@ -730,6 +731,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { public int updateBleAppCount(IBinder token, boolean enable, String packageName) { ClientDeathRecipient r = mBleApps.get(token); + int st = BluetoothAdapter.STATE_OFF; if (r == null && enable) { ClientDeathRecipient deathRec = new ClientDeathRecipient(packageName); try { @@ -756,8 +758,22 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (appCount == 0 && mEnable) { disableBleScanMode(); } - if (appCount == 0 && !mEnableExternal) { - sendBrEdrDownCallback(); + if(appCount == 0) { + try { + mBluetoothLock.readLock().lock(); + if (mBluetooth != null) { + st = mBluetooth.getState(); + } + if (!mEnableExternal || (st == BluetoothAdapter.STATE_BLE_ON)) { + if (DBG) Slog.d(TAG, "Move to BT state OFF"); + sendBrEdrDownCallback(); + mEnableExternal = false; + } + } catch (RemoteException e) { + Slog.e(TAG, "", e); + } finally { + mBluetoothLock.readLock().unlock(); + } } return appCount; } @@ -788,6 +804,12 @@ class BluetoothManagerService extends IBluetoothManager.Stub { Slog.e(TAG, "onBluetoothServiceUp: mBluetooth is null!"); return; } + int st = mBluetooth.getState(); + if (st != BluetoothAdapter.STATE_BLE_ON) { + if (DBG) Slog.v(TAG, "onBluetoothServiceUp: state isn't BLE_ON: " + + BluetoothAdapter.nameForState(st)); + return; + } if (isBluetoothPersistedStateOnBluetooth() || !isBleAppPresent()) { // This triggers transition to STATE_ON mBluetooth.onLeServiceUp(); @@ -936,10 +958,33 @@ class BluetoothManagerService extends IBluetoothManager.Stub { synchronized (mReceiver) { if (persist) { persistBluetoothSetting(BLUETOOTH_OFF); - } - mEnableExternal = false; - sendDisableMsg(BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST, + mEnableExternal = false; + sendDisableMsg(BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST, packageName); + } else { + /* It means disable is called by shutdown thread */ + synchronized (this) { + clearBleApps(); + } + + try { + mBluetoothLock.readLock().lock(); + mEnableExternal = false; + if (mBluetooth != null) { + if(mBluetooth.getState() == BluetoothAdapter.STATE_BLE_ON) { + mEnable = false; + mBluetooth.onBrEdrDown(); + } else { + sendDisableMsg(BluetoothProtoEnums.ENABLE_DISABLE_REASON_SYSTEM_BOOT, + packageName); + } + } + } catch (RemoteException e) { + Slog.e(TAG, "Unable to initiate disable", e); + } finally { + mBluetoothLock.readLock().unlock(); + } + } } return true; } @@ -1037,12 +1082,21 @@ class BluetoothManagerService extends IBluetoothManager.Stub { @Override public boolean bindBluetoothProfileService(int bluetoothProfile, IBluetoothProfileServiceConnection proxy) { - if (!mEnable) { - if (DBG) { - Slog.d(TAG, "Trying to bind to profile: " + bluetoothProfile - + ", while Bluetooth was disabled"); + try { + mBluetoothLock.writeLock().lock(); + if (!mEnable || + (mBluetooth != null && (mBluetooth.getState() != BluetoothAdapter.STATE_ON) && + (mBluetooth.getState() != BluetoothAdapter.STATE_TURNING_ON))) { + if (DBG) { + Slog.d(TAG, "Trying to bind to profile: " + bluetoothProfile + + ", while Bluetooth was disabled"); + } + return false; } - return false; + } catch (RemoteException e) { + Slog.e(TAG, "getState()", e); + } finally { + mBluetoothLock.writeLock().unlock(); } synchronized (mProfileServices) { ProfileServiceConnections psc = mProfileServices.get(new Integer(bluetoothProfile)); @@ -1274,13 +1328,11 @@ class BluetoothManagerService extends IBluetoothManager.Stub { @Override public void onServiceDisconnected(ComponentName className) { - if (mService == null) { - return; - } + if (mService == null) return; try { mService.unlinkToDeath(this, 0); } catch (NoSuchElementException e) { - Log.e(TAG, "error unlinking to death", e); + Slog.e(TAG, "Unable to unlinkToDeath", e); } mService = null; mClassName = null; @@ -1433,6 +1485,33 @@ class BluetoothManagerService extends IBluetoothManager.Stub { return mName; } + public boolean factoryReset() { + final int callingUid = Binder.getCallingUid(); + final boolean callerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID; + + if (!callerSystem) { + if (!checkIfCallerIsForegroundUser()) { + Slog.w(TAG, "factoryReset(): not allowed for non-active and non system user"); + return false; + } + + mContext.enforceCallingOrSelfPermission( + BLUETOOTH_PRIVILEGED_PERM, "Need BLUETOOTH PRIVILEGED permission"); + } + + try { + if (mBluetooth != null) { + // Clear registered LE apps to force shut-off + clearBleApps(); + return mBluetooth.factoryReset(); + } + } catch (RemoteException e) { + Slog.e(TAG, "factoryReset(): Unable to do factoryReset.", e); + return false; + } + return true; + } + private class BluetoothServiceConnection implements ServiceConnection { public void onServiceConnected(ComponentName componentName, IBinder service) { String name = componentName.getClassName(); @@ -1535,7 +1614,11 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (state == BluetoothAdapter.STATE_BLE_ON) { Slog.w(TAG, "BT Enable in BLE_ON State, going to ON"); mBluetooth.onLeServiceUp(); + + // waive WRITE_SECURE_SETTINGS permission check + long callingIdentity = Binder.clearCallingIdentity(); persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH); + Binder.restoreCallingIdentity(callingIdentity); break; } } @@ -1554,7 +1637,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { // the previous Bluetooth process has exited. The // waiting period has three components: // (a) Wait until the local state is STATE_OFF. This - // is accomplished by "waitForOnOff(false, true)". + // is accomplished by "waitForMonitoredOnOff(false, true)". // (b) Wait until the STATE_OFF state is updated to // all components. // (c) Wait until the Bluetooth process exits, and @@ -1564,7 +1647,17 @@ class BluetoothManagerService extends IBluetoothManager.Stub { // message. On slower devices, that delay needs to be // on the order of (2 * SERVICE_RESTART_TIME_MS). // - waitForOnOff(false, true); + // Wait for (a) is required only when Bluetooth is being + // turned off. + int state; + try { + state = mBluetooth.getState(); + } catch (RemoteException e) { + Slog.e(TAG, "getState()", e); + break; + } + if(state == BluetoothAdapter.STATE_TURNING_OFF || state == BluetoothAdapter.STATE_BLE_TURNING_OFF) + waitForMonitoredOnOff(false, true); Message restartMsg = mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE); mHandler.sendMessageDelayed(restartMsg, 2 * SERVICE_RESTART_TIME_MS); @@ -1577,10 +1670,10 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE); if (mEnable && mBluetooth != null) { - waitForOnOff(true, false); + waitForMonitoredOnOff(true, false); mEnable = false; handleDisable(); - waitForOnOff(false, false); + waitForMonitoredOnOff(false, false); } else { mEnable = false; handleDisable(); @@ -1709,9 +1802,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } if (!mEnable) { - waitForOnOff(true, false); + waitForMonitoredOnOff(true, false); handleDisable(); - waitForOnOff(false, false); + waitForMonitoredOnOff(false, false); } break; } @@ -1732,8 +1825,14 @@ class BluetoothManagerService extends IBluetoothManager.Stub { == BluetoothAdapter.STATE_OFF) && (mBluetooth != null) && mEnable) { recoverBluetoothServiceFromError(false); } - if ((prevState == BluetoothAdapter.STATE_TURNING_ON) && (newState - == BluetoothAdapter.STATE_BLE_ON) && (mBluetooth != null) && mEnable) { + if ((prevState == BluetoothAdapter.STATE_TURNING_ON) && + (newState == BluetoothAdapter.STATE_OFF) && + (mBluetooth != null) && mEnable) { + persistBluetoothSetting(BLUETOOTH_OFF); + } + if ((prevState == BluetoothAdapter.STATE_TURNING_ON) && + (newState == BluetoothAdapter.STATE_BLE_ON) && + (mBluetooth != null) && mEnable) { recoverBluetoothServiceFromError(true); } // If we tried to enable BT while BT was in the process of shutting down, @@ -1743,7 +1842,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { == BluetoothAdapter.STATE_OFF)) { if (mEnable) { Slog.d(TAG, "Entering STATE_OFF but mEnabled is true; restarting."); - waitForOnOff(false, true); + mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE); + waitForMonitoredOnOff(false, true); Message restartMsg = mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE); mHandler.sendMessageDelayed(restartMsg, 2 * SERVICE_RESTART_TIME_MS); @@ -1866,7 +1966,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mState = BluetoothAdapter.STATE_TURNING_ON; } - waitForOnOff(true, false); + waitForMonitoredOnOff(true, false); if (mState == BluetoothAdapter.STATE_TURNING_ON) { bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_ON); @@ -1876,27 +1976,32 @@ class BluetoothManagerService extends IBluetoothManager.Stub { // disable addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_USER_SWITCH, mContext.getPackageName(), false); + + clearBleApps(); + handleDisable(); // Pbap service need receive STATE_TURNING_OFF intent to close bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON, BluetoothAdapter.STATE_TURNING_OFF); - boolean didDisableTimeout = !waitForOnOff(false, true); + boolean didDisableTimeout = !waitForMonitoredOnOff(false, true); bluetoothStateChangeHandler(BluetoothAdapter.STATE_TURNING_OFF, BluetoothAdapter.STATE_OFF); sendBluetoothServiceDownCallback(); - try { - mBluetoothLock.writeLock().lock(); - if (mBluetooth != null) { - mBluetooth = null; - // Unbind - mContext.unbindService(mConnection); + if(!didDisableTimeout) { + try { + mBluetoothLock.writeLock().lock(); + if (mBluetooth != null) { + mBluetooth = null; + // Unbind + mContext.unbindService(mConnection); + } + mBluetoothGatt = null; + } finally { + mBluetoothLock.writeLock().unlock(); } - mBluetoothGatt = null; - } finally { - mBluetoothLock.writeLock().unlock(); } // @@ -1906,6 +2011,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { // if (didDisableTimeout) { SystemClock.sleep(3000); + mHandler.removeMessages(MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED); } else { SystemClock.sleep(100); } @@ -2050,6 +2156,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, prevState); intent.putExtra(BluetoothAdapter.EXTRA_STATE, newState); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); + intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND); mContext.sendBroadcastAsUser(intent, UserHandle.ALL, BLUETOOTH_PERM); } @@ -2129,6 +2236,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, prevState); intent.putExtra(BluetoothAdapter.EXTRA_STATE, newState); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); + intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); mContext.sendBroadcastAsUser(intent, UserHandle.ALL, BLUETOOTH_PERM); } } @@ -2140,7 +2248,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { */ private boolean waitForOnOff(boolean on, boolean off) { int i = 0; - while (i < 10) { + while (i < 16) { try { mBluetoothLock.readLock().lock(); if (mBluetooth == null) { @@ -2166,13 +2274,59 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mBluetoothLock.readLock().unlock(); } if (on || off) { + SystemClock.sleep(500); + } else { + SystemClock.sleep(30); + } + i++; + } + Slog.e(TAG,"waitForOnOff time out"); + return false; + } + + /** + * if on is true, wait for state become ON + * if off is true, wait for state become OFF + * if both on and off are false, wait for state not ON + */ + private boolean waitForMonitoredOnOff(boolean on, boolean off) { + int i = 0; + while (i < 10) { + synchronized(mConnection) { + try { + if (mBluetooth == null) break; + if (on) { + if (mBluetooth.getState() == BluetoothAdapter.STATE_ON) return true; + if (mBluetooth.getState() == BluetoothAdapter.STATE_BLE_ON) { + bluetoothStateChangeHandler(BluetoothAdapter.STATE_BLE_TURNING_ON, + BluetoothAdapter.STATE_BLE_ON); + boolean ret = waitForOnOff(on, off); + return ret; + } + } else if (off) { + if (mBluetooth.getState() == BluetoothAdapter.STATE_OFF) return true; + if (mBluetooth.getState() == BluetoothAdapter.STATE_BLE_ON) { + bluetoothStateChangeHandler(BluetoothAdapter.STATE_TURNING_OFF, + BluetoothAdapter.STATE_BLE_ON); + boolean ret = waitForOnOff(on, off); + return ret; + } + } else { + if (mBluetooth.getState() != BluetoothAdapter.STATE_ON) return true; + } + } catch (RemoteException e) { + Slog.e(TAG, "getState()", e); + break; + } + } + if (on || off) { SystemClock.sleep(300); } else { SystemClock.sleep(50); } i++; } - Slog.e(TAG, "waitForOnOff time out"); + Slog.e(TAG,"waitForMonitoredOnOff time out"); return false; } @@ -2226,29 +2380,10 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mBluetoothLock.readLock().unlock(); } - SystemClock.sleep(500); - - // disable - addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_START_ERROR, - mContext.getPackageName(), false); - handleDisable(); - - waitForOnOff(false, true); + waitForMonitoredOnOff(false, true); sendBluetoothServiceDownCallback(); - try { - mBluetoothLock.writeLock().lock(); - if (mBluetooth != null) { - mBluetooth = null; - // Unbind - mContext.unbindService(mConnection); - } - mBluetoothGatt = null; - } finally { - mBluetoothLock.writeLock().unlock(); - } - mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE); mState = BluetoothAdapter.STATE_OFF; diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 00550d9c660e..ef1ac4d99875 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -27,6 +27,7 @@ import static android.net.ConnectivityManager.getNetworkTypeName; import static android.net.ConnectivityManager.isNetworkTypeValid; import static android.net.INetworkMonitor.NETWORK_TEST_RESULT_VALID; import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL; +import static android.net.NetworkCapabilities.NET_CAPABILITY_EIMS; import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND; import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED; @@ -57,6 +58,7 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.res.Configuration; import android.database.ContentObserver; +import android.telephony.SubscriptionInfo; import android.net.ConnectionInfo; import android.net.ConnectivityManager; import android.net.ConnectivityManager.PacketKeepalive; @@ -91,6 +93,7 @@ import android.net.NetworkWatchlistManager; import android.net.PrivateDnsConfigParcel; import android.net.ProxyInfo; import android.net.RouteInfo; +import android.net.StringNetworkSpecifier; import android.net.UidRange; import android.net.Uri; import android.net.VpnService; @@ -127,6 +130,7 @@ import android.os.UserManager; import android.provider.Settings; import android.security.Credentials; import android.security.KeyStore; +import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.ArraySet; @@ -484,6 +488,8 @@ public class ConnectivityService extends IConnectivityManager.Stub */ public static final int PROVISIONING_NOTIFICATION_HIDE = 0; + private static final int EVENT_UPDATE_TCP_BUFFER_FOR_5G = 160; + private static String eventName(int what) { return sMagicDecoderRing.get(what, Integer.toString(what)); } @@ -519,6 +525,7 @@ public class ConnectivityService extends IConnectivityManager.Stub private List mProtectedNetworks; private TelephonyManager mTelephonyManager; + private SubscriptionManager mSubscriptionManager; private KeepaliveTracker mKeepaliveTracker; private NetworkNotificationManager mNotifier; @@ -820,6 +827,7 @@ public class ConnectivityService extends IConnectivityManager.Stub mNetd = NetdService.getInstance(); mKeyStore = KeyStore.getInstance(); mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE); + mSubscriptionManager = SubscriptionManager.from(mContext); // To ensure uid rules are synchronized with Network Policy, register for // NetworkPolicyManagerService events must happen prior to NetworkPolicyManagerService @@ -2128,6 +2136,19 @@ public class ConnectivityService extends IConnectivityManager.Stub return new MockableSystemProperties(); } + private void updateTcpBufferSizes(NetworkAgentInfo nai) { + if (isDefaultNetwork(nai) == false) { + return; + } + + String tcpBufferSizes = nai.linkProperties.getTcpBufferSizes(); + if(nai.networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)){ + tcpBufferSizes = NetPluginDelegate.get5GTcpBuffers(tcpBufferSizes, + nai.networkCapabilities.getNetworkSpecifier()); + } + updateTcpBufferSizes(tcpBufferSizes); + } + private void updateTcpBufferSizes(String tcpBufferSizes) { String[] values = null; if (tcpBufferSizes != null) { @@ -2935,9 +2956,18 @@ public class ConnectivityService extends IConnectivityManager.Stub return true; } - if (!nai.everConnected || nai.isVPN() || nai.isLingering() || numRequests > 0) { + if (!nai.everConnected || nai.isVPN() || numRequests > 0) { return false; } + + if (nai.isLingering()) { + if (satisfiesMobileNetworkDataCheck(nai.networkCapabilities)) { + return false; + } else { + nai.clearLingerState(); + } + } + for (NetworkRequestInfo nri : mNetworkRequests.values()) { if (reason == UnneededFor.LINGER && nri.request.isBackgroundRequest()) { // Background requests don't affect lingering. @@ -2946,8 +2976,10 @@ public class ConnectivityService extends IConnectivityManager.Stub // If this Network is already the highest scoring Network for a request, or if // there is hope for it to become one if it validated, then it is needed. - if (nri.request.isRequest() && nai.satisfies(nri.request) && - (nai.isSatisfyingRequest(nri.request.requestId) || + if (nri.request.isRequest() && nai.satisfies(nri.request) + && satisfiesMobileMultiNetworkDataCheck(nai.networkCapabilities, + nri.request.networkCapabilities) + && (nai.isSatisfyingRequest(nri.request.requestId) || // Note that this catches two important cases: // 1. Unvalidated cellular will not be reaped when unvalidated WiFi // is currently satisfying the request. This is desirable when @@ -2955,8 +2987,9 @@ public class ConnectivityService extends IConnectivityManager.Stub // 2. Unvalidated WiFi will not be reaped when validated cellular // is currently satisfying the request. This is desirable when // WiFi ends up validating and out scoring cellular. - getNetworkForRequest(nri.request.requestId).getCurrentScore() < - nai.getCurrentScoreAsValidated())) { + ((getNetworkForRequest(nri.request.requestId) != null) + && (getNetworkForRequest(nri.request.requestId).getCurrentScore() < + nai.getCurrentScoreAsValidated())))) { return false; } } @@ -3401,6 +3434,7 @@ public class ConnectivityService extends IConnectivityManager.Stub } } mMultipathPolicyTracker.start(); + NetPluginDelegate.registerHandler(mHandler); break; } case EVENT_REVALIDATE_NETWORK: { @@ -3420,6 +3454,9 @@ public class ConnectivityService extends IConnectivityManager.Stub case EVENT_DATA_SAVER_CHANGED: handleRestrictBackgroundChanged(toBool(msg.arg1)); break; + case EVENT_UPDATE_TCP_BUFFER_FOR_5G: + handleUpdateTCPBuffersfor5G(); + break; } } } @@ -5541,7 +5578,15 @@ public class ConnectivityService extends IConnectivityManager.Stub final NetworkAgentInfo currentNetwork = getNetworkForRequest(nri.request.requestId); final boolean satisfies = newNetwork.satisfies(nri.request); - if (newNetwork == currentNetwork && satisfies) { + boolean satisfiesMobileMultiNetworkCheck = false; + + if (satisfies) { + satisfiesMobileMultiNetworkCheck = satisfiesMobileMultiNetworkDataCheck( + newNetwork.networkCapabilities, + nri.request.networkCapabilities); + } + + if (newNetwork == currentNetwork && satisfiesMobileMultiNetworkCheck) { if (VDBG) { log("Network " + newNetwork.name() + " was already satisfying" + " request " + nri.request.requestId + ". No change."); @@ -5552,7 +5597,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // check if it satisfies the NetworkCapabilities if (VDBG) log(" checking if request is satisfied: " + nri.request); - if (satisfies) { + if (satisfiesMobileMultiNetworkCheck) { // next check if it's better than any current network we're using for // this request if (VDBG || DDBG) { @@ -5560,7 +5605,13 @@ public class ConnectivityService extends IConnectivityManager.Stub (currentNetwork != null ? currentNetwork.getCurrentScore() : 0) + ", newScore = " + score); } - if (currentNetwork == null || currentNetwork.getCurrentScore() < score) { + if (currentNetwork == null || + isBestMobileMultiNetwork(currentNetwork, + currentNetwork.networkCapabilities, + newNetwork, + newNetwork.networkCapabilities, + nri.request.networkCapabilities) || + currentNetwork.getCurrentScore() < score) { if (VDBG) log("rematch for " + newNetwork.name()); if (currentNetwork != null) { if (VDBG || DDBG){ @@ -6390,4 +6441,76 @@ public class ConnectivityService extends IConnectivityManager.Stub return uid; } + + private boolean isMobileNetwork(NetworkAgentInfo nai) { + if (nai != null && nai.networkCapabilities != null && + nai.networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) { + return true; + } + return false; + } + + private boolean satisfiesMobileNetworkDataCheck(NetworkCapabilities agentNc) { + if (agentNc != null && agentNc.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) { + if((agentNc.hasCapability(NET_CAPABILITY_EIMS) && + (mSubscriptionManager != null && + (mSubscriptionManager.getActiveSubscriptionInfoList() == null || + mSubscriptionManager.getActiveSubscriptionInfoList().size()==0))) || + (getIntSpecifier(agentNc.getNetworkSpecifier()) == SubscriptionManager + .getDefaultDataSubscriptionId())) { + return true; + } else { + return false; + } + } + return true; + } + + private boolean satisfiesMobileMultiNetworkDataCheck(NetworkCapabilities agentNc, + NetworkCapabilities requestNc) { + if (requestNc != null && getIntSpecifier(requestNc.getNetworkSpecifier()) < 0) { + return satisfiesMobileNetworkDataCheck(agentNc); + } + return true; + } + + private int getIntSpecifier(NetworkSpecifier networkSpecifierObj) { + String specifierStr = null; + int specifier = -1; + if (networkSpecifierObj != null + && networkSpecifierObj instanceof StringNetworkSpecifier) { + specifierStr = ((StringNetworkSpecifier) networkSpecifierObj).specifier; + } + if (specifierStr != null && specifierStr.isEmpty() == false) { + try { + specifier = Integer.parseInt(specifierStr); + } catch (NumberFormatException e) { + specifier = -1; + } + } + return specifier; + } + + private boolean isBestMobileMultiNetwork(NetworkAgentInfo currentNetwork, + NetworkCapabilities currentRequestNc, + NetworkAgentInfo newNetwork, + NetworkCapabilities newRequestNc, + NetworkCapabilities requestNc) { + if (isMobileNetwork(currentNetwork) && + isMobileNetwork(newNetwork) && + satisfiesMobileMultiNetworkDataCheck(newRequestNc, requestNc) && + !satisfiesMobileMultiNetworkDataCheck(currentRequestNc, requestNc)) { + return true; + } + return false; + } + + private void handleUpdateTCPBuffersfor5G() { + Network network = getActiveNetwork(); + NetworkAgentInfo ntwAgent = getNetworkAgentInfoForNetwork(network); + if (DBG) + log("handleUpdateTCPBuffersfor5G nai " + ntwAgent); + if (ntwAgent != null) + updateTcpBufferSizes(ntwAgent); + } } diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java index add5e5feaa8a..e18fcb0ff296 100644 --- a/services/core/java/com/android/server/LocationManagerService.java +++ b/services/core/java/com/android/server/LocationManagerService.java @@ -174,6 +174,9 @@ public class LocationManagerService extends ILocationManager.Stub { private AppOpsManager mAppOps; private PackageManager mPackageManager; + private String mComboNlpPackageName; + private String mComboNlpReadyMarker; + private String mComboNlpScreenMarker; private PowerManager mPowerManager; private ActivityManager mActivityManager; private UserManager mUserManager; @@ -736,6 +739,13 @@ public class LocationManagerService extends ILocationManager.Stub { Slog.d(TAG, "Unable to bind FLP Geofence proxy."); } + mComboNlpPackageName = resources.getString( + com.android.internal.R.string.config_comboNetworkLocationProvider); + if (mComboNlpPackageName != null) { + mComboNlpReadyMarker = mComboNlpPackageName + ".nlp:ready"; + mComboNlpScreenMarker = mComboNlpPackageName + ".nlp:screen"; + } + String[] testProviderStrings = resources.getStringArray( com.android.internal.R.array.config_testLocationProviders); for (String testProviderString : testProviderStrings) { diff --git a/services/core/java/com/android/server/NetPluginDelegate.java b/services/core/java/com/android/server/NetPluginDelegate.java new file mode 100644 index 000000000000..452ad4b01f85 --- /dev/null +++ b/services/core/java/com/android/server/NetPluginDelegate.java @@ -0,0 +1,157 @@ +/*
+ *Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ *Redistribution and use in source and binary forms, with or without
+ *modification, are permitted provided that the following conditions are
+ *met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ *THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ *WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ *ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ *BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ *CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ *SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ *BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ *WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ *OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ *IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.android.server;
+
+import dalvik.system.PathClassLoader;
+
+import java.io.File;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+
+import android.os.Environment;
+import android.util.Slog;
+import android.util.Log;
+import android.os.Handler;
+import android.net.NetworkSpecifier;
+
+public class NetPluginDelegate {
+
+ private static final String TAG = "NetPluginDelegate";
+ private static final boolean LOGV = true;
+
+ private static Class tcpBufferRelay = null;
+ private static Object tcpBufferManagerObj = null;
+ private static boolean extJarAvail = true;
+
+ /*
+ * Returns applicable TCP buffer size based on the network specifier.
+ */
+ public static String get5GTcpBuffers(String currentTcpBuffer, NetworkSpecifier sepcifier) {
+ String tcpBuffer = currentTcpBuffer;
+ if (LOGV) Slog.v(TAG, "get5GTcpBuffers");
+ if (!extJarAvail || !loadConnExtJar())
+ return currentTcpBuffer;
+ try {
+ Object ret = tcpBufferRelay.getMethod("get5GTcpBuffers",
+ String.class, NetworkSpecifier.class).invoke(
+ tcpBufferManagerObj, currentTcpBuffer, sepcifier);
+
+ if(ret !=null && (ret instanceof String)){
+ tcpBuffer = (String) ret;
+ }
+ } catch (InvocationTargetException | SecurityException | NoSuchMethodException e) {
+ if (LOGV) {
+ Log.w(TAG, "Failed to invoke get5GTcpBuffers()");
+ e.printStackTrace();
+ }
+ extJarAvail = false;
+ } catch (Exception e) {
+ if (LOGV) {
+ Log.w(TAG, "Error calling get5GTcpBuffers Method on extension jar");
+ e.printStackTrace();
+ }
+ extJarAvail = false;
+ }
+ return tcpBuffer;
+ }
+
+ /*
+ * Provides the api to register a handler with the lib. This is used to send
+ * EVENT_UPDATE_TCP_BUFFER_FOR_5G message to the handler queue to take action on it.
+ */
+ public static void registerHandler(Handler mHandler) {
+ if (LOGV) Slog.v(TAG, "registerHandler");
+ if (!extJarAvail || !loadConnExtJar()) return;
+ try {
+ tcpBufferRelay.getMethod("registerHandler", Handler.class).invoke(
+ tcpBufferManagerObj, mHandler);
+ } catch (InvocationTargetException | SecurityException | NoSuchMethodException e) {
+ if (LOGV) {
+ Log.w(TAG, "Failed to call registerHandler");
+ e.printStackTrace();
+ }
+ extJarAvail = false;
+ } catch (Exception e) {
+ if (LOGV) {
+ Log.w(TAG, "Error calling registerHandler Method on extension jar");
+ e.printStackTrace();
+ }
+ extJarAvail = false;
+ }
+ }
+
+ /*
+ * Dynamically loads the lib.
+ * Checks whether the required lib is avalaiblable if not disables further attempts
+ * to load it.
+ */
+ private static synchronized boolean loadConnExtJar() {
+ final String realProvider = "com.qualcomm.qti.net.connextension.TCPBufferManager";
+ final String realProviderPath = Environment.getRootDirectory().getAbsolutePath()
+ + "/framework/ConnectivityExt.jar";
+
+ if (tcpBufferRelay != null && tcpBufferManagerObj != null) {
+ return true;
+ }
+
+ extJarAvail = new File(realProviderPath).exists();
+ if (!extJarAvail) {
+ Log.w(TAG, "ConnectivityExt jar file not present");
+ return false;
+ }
+
+ if (tcpBufferRelay == null && tcpBufferManagerObj == null) {
+ if (LOGV) Slog.v(TAG, "loading ConnectivityExt jar");
+ try {
+ PathClassLoader classLoader = new PathClassLoader(realProviderPath,
+ ClassLoader.getSystemClassLoader());
+
+ tcpBufferRelay = classLoader.loadClass(realProvider);
+ tcpBufferManagerObj = tcpBufferRelay.newInstance();
+ if (LOGV) Slog.v(TAG, "ConnectivityExt jar loaded");
+ } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
+ if (LOGV) {
+ Log.w(TAG, "Failed to find, instantiate or access ConnectivityExt jar ");
+ e.printStackTrace();
+ }
+ extJarAvail = false;
+ return false;
+ } catch (Exception e) {
+ if (LOGV) {
+ Log.w(TAG, "unable to load ConnectivityExt jar");
+ e.printStackTrace();
+ }
+ extJarAvail = false;
+ return false;
+ }
+ }
+ return true;
+ }
+}
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java index 7731c04a94b8..2b9b2c992b23 100644 --- a/services/core/java/com/android/server/StorageManagerService.java +++ b/services/core/java/com/android/server/StorageManagerService.java @@ -147,6 +147,7 @@ import com.android.internal.widget.LockPatternUtils; import com.android.server.storage.AppFuseBridge; import com.android.server.wm.ActivityTaskManagerInternal; import com.android.server.wm.ActivityTaskManagerInternal.ScreenObserver; +import com.android.internal.widget.ILockSettings; import libcore.io.IoUtils; import libcore.util.EmptyArray; @@ -2571,8 +2572,22 @@ class StorageManagerService extends IStorageManager.Stub Slog.i(TAG, "changing encryption password..."); } + ILockSettings lockSettings = ILockSettings.Stub.asInterface( + ServiceManager.getService("lock_settings")); + String currentPassword="default_password"; try { - mVold.fdeChangePassword(type, password); + currentPassword = lockSettings.getPassword(); + } catch (Exception e) { + Slog.wtf(TAG, "Couldn't get password" + e); + } + + try { + mVold.fdeChangePassword(type, currentPassword, password); + try { + lockSettings.sanitizePassword(); + } catch (Exception e) { + Slog.wtf(TAG, "Couldn't sanitize password" + e); + } return 0; } catch (Exception e) { Slog.wtf(TAG, e); @@ -2780,6 +2795,24 @@ class StorageManagerService extends IStorageManager.Stub } /* + * Clear disk encryption key bound to the associated token / secret pair. Removing the user + * binding of the Disk encryption key is done in two phases: first, this call will retrieve + * the disk encryption key using the provided token / secret pair and store it by + * encrypting it with a keymaster key not bound to the user, then fixateNewestUserKeyAuth + * is called to delete all other bindings of the disk encryption key. + */ + @Override + public void clearUserKeyAuth(int userId, int serialNumber, byte[] token, byte[] secret) { + enforcePermission(android.Manifest.permission.STORAGE_INTERNAL); + + try { + mVold.clearUserKeyAuth(userId, serialNumber, encodeBytes(token), encodeBytes(secret)); + } catch (Exception e) { + Slog.wtf(TAG, e); + } + } + + /* * Delete all disk encryption token/secret pairs except the most recently added one */ @Override diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java index 1aeb6898fa13..7c15d62c251c 100644 --- a/services/core/java/com/android/server/Watchdog.java +++ b/services/core/java/com/android/server/Watchdog.java @@ -26,6 +26,7 @@ import android.hidl.manager.V1_0.IServiceManager; import android.os.Binder; import android.os.Build; import android.os.Debug; +import android.os.FileUtils; import android.os.Handler; import android.os.IPowerManager; import android.os.Looper; @@ -33,6 +34,7 @@ import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemClock; +import android.os.SystemProperties; import android.system.ErrnoException; import android.system.Os; import android.system.OsConstants; @@ -47,7 +49,9 @@ import com.android.server.wm.SurfaceAnimationThread; import java.io.File; import java.io.FileWriter; +import java.io.FileReader; import java.io.IOException; +import java.io.BufferedReader; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; @@ -57,6 +61,8 @@ import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.List; +import java.util.Date; +import java.text.SimpleDateFormat; /** This class calls its monitor every minute. Killing this process if they don't return **/ public class Watchdog extends Thread { @@ -124,6 +130,7 @@ public class Watchdog extends Thread { int mPhonePid; IActivityController mController; boolean mAllowRestart = true; + SimpleDateFormat mTraceDateFormat = new SimpleDateFormat("dd_MMM_HH_mm_ss.SSS"); final OpenFdMonitor mOpenFdMonitor; /** @@ -435,6 +442,7 @@ public class Watchdog extends Thread { @Override public void run() { boolean waitedHalf = false; + File initialStack = null; while (true) { final List<HandlerChecker> blockedCheckers; final String subject; @@ -494,8 +502,8 @@ public class Watchdog extends Thread { // trace and wait another half. ArrayList<Integer> pids = new ArrayList<Integer>(); pids.add(Process.myPid()); - ActivityManagerService.dumpStackTraces(pids, null, null, - getInterestingNativePids()); + initialStack = ActivityManagerService.dumpStackTraces(pids, + null, null, getInterestingNativePids()); waitedHalf = true; } continue; @@ -520,16 +528,79 @@ public class Watchdog extends Thread { pids.add(Process.myPid()); if (mPhonePid > 0) pids.add(mPhonePid); - final File stack = ActivityManagerService.dumpStackTraces( + final File finalStack = ActivityManagerService.dumpStackTraces( pids, null, null, getInterestingNativePids()); // Give some extra time to make sure the stack traces get written. // The system's been hanging for a minute, another second or two won't hurt much. SystemClock.sleep(5000); - // Trigger the kernel to dump all blocked threads, and backtraces on all CPUs to the kernel log - doSysRq('w'); - doSysRq('l'); + final String tracesDirProp = SystemProperties.get("dalvik.vm.stack-trace-dir", ""); + File watchdogTraces; + String newTracesPath = "traces_SystemServer_WDT" + + mTraceDateFormat.format(new Date()) + "_pid" + + String.valueOf(Process.myPid()); + boolean oldTraceMechanism = false; + + if (tracesDirProp.isEmpty()) { + // the old trace dumping mechanism + // in which case, finalStack has 2 sets of traces contained + String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null); + int lpos = tracesPath.lastIndexOf ("/"); //essentially, till the parent dir + if (-1 != lpos) { + watchdogTraces = new + File(tracesPath.substring(0, lpos + 1) + newTracesPath); + } else { + watchdogTraces = new File(newTracesPath); + } + oldTraceMechanism = true; + } else { + // the new trace dumping mechanism + File tracesDir = new File(tracesDirProp); + watchdogTraces = new File(tracesDir, newTracesPath); + } + try { + if (watchdogTraces.createNewFile()) { + FileUtils.setPermissions(watchdogTraces.getAbsolutePath(), + 0600, -1, -1); // -rw------- permissions + + // Append both traces from the first and second half + // to a new file, making it easier to debug Watchdog timeouts + // dumpStackTraces() can return a null instance, so check the same + if ((initialStack != null) && !oldTraceMechanism) { + // check the last-modified time of this file. + // we are interested in this only it was written to in the + // last 5 minutes or so + final long age = System.currentTimeMillis() + - initialStack.lastModified(); + final long FIVE_MINUTES_IN_MILLIS = 1000 * 60 * 5; + if (age < FIVE_MINUTES_IN_MILLIS) { + Slog.e(TAG, "First set of traces taken from " + + initialStack.getAbsolutePath()); + appendFile(watchdogTraces, initialStack); + } else { + Slog.e(TAG, "First set of traces were collected more than " + + "5 minutes ago, ignoring ..."); + } + } else { + Slog.e(TAG, "First set of traces are empty!"); + } + + if (finalStack != null) { + Slog.e(TAG, "Second set of traces taken from " + + finalStack.getAbsolutePath()); + appendFile(watchdogTraces, finalStack); + } else { + Slog.e(TAG, "Second set of traces are empty!"); + } + } else { + Slog.w(TAG, "Unable to create Watchdog dump file: createNewFile failed"); + } + } catch (Exception e) { + // catch any exception that happens here; + // why kill the system when it is going to die anyways? + Slog.e(TAG, "Exception creating Watchdog dump file:", e); + } // Try to add the error to the dropbox, but assuming that the ActivityManager // itself may be deadlocked. (which has happened, causing this statement to @@ -538,14 +609,32 @@ public class Watchdog extends Thread { public void run() { mActivity.addErrorToDropBox( "watchdog", null, "system_server", null, null, null, - subject, null, stack, null); + subject, null, finalStack, null); } - }; + }; dropboxThread.start(); try { dropboxThread.join(2000); // wait up to 2 seconds for it to return. } catch (InterruptedException ignored) {} + // At times, when user space watchdog traces don't give an indication on + // which component held a lock, because of which other threads are blocked, + // (thereby causing Watchdog), trigger kernel panic + boolean crashOnWatchdog = SystemProperties + .getBoolean("persist.sys.crashOnWatchdog", false); + if (crashOnWatchdog) { + // Trigger the kernel to dump all blocked threads, and backtraces + // on all CPUs to the kernel log + Slog.e(TAG, "Triggering SysRq for system_server watchdog"); + doSysRq('w'); + doSysRq('l'); + + // wait until the above blocked threads be dumped into kernel log + SystemClock.sleep(3000); + + doSysRq('c'); + } + IActivityController controller; synchronized (this) { controller = mController; @@ -597,6 +686,46 @@ public class Watchdog extends Thread { } } + private void appendFile (File writeTo, File copyFrom) { + try { + BufferedReader in = new BufferedReader(new FileReader(copyFrom)); + FileWriter out = new FileWriter(writeTo, true); + String line = null; + + // Write line-by-line from "copyFrom" to "writeTo" + while ((line = in.readLine()) != null) { + out.write(line); + out.write('\n'); + } + in.close(); + out.close(); + } catch (IOException e) { + Slog.e(TAG, "Exception while writing watchdog traces to new file!"); + e.printStackTrace(); + } + } + + private void binderStateRead() { + try { + Slog.i(TAG,"Collecting Binder Transaction Status Information"); + BufferedReader in = + new BufferedReader(new FileReader("/sys/kernel/debug/binder/state")); + FileWriter out = new FileWriter("/data/anr/BinderTraces_pid" + + String.valueOf(Process.myPid()) + ".txt"); + String line = null; + + // Write line-by-line + while ((line = in.readLine()) != null) { + out.write(line); + out.write('\n'); + } + in.close(); + out.close(); + } catch (IOException e) { + Slog.w(TAG, "Failed to collect state file", e); + } + } + public static final class OpenFdMonitor { /** * Number of FDs below the soft limit that we trigger a runtime restart at. This was diff --git a/services/core/java/com/android/server/WiredAccessoryManager.java b/services/core/java/com/android/server/WiredAccessoryManager.java index 3939bee52aa2..a8530b87dd8e 100644 --- a/services/core/java/com/android/server/WiredAccessoryManager.java +++ b/services/core/java/com/android/server/WiredAccessoryManager.java @@ -67,6 +67,12 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks { private static final String NAME_H2W = "h2w"; private static final String NAME_USB_AUDIO = "usb_audio"; private static final String NAME_HDMI_AUDIO = "hdmi_audio"; + private static final String NAME_DP_AUDIO = "soc:qcom,msm-ext-disp"; + // within a device, a single stream supports DP + private static final String[] DP_AUDIO_CONNS = { + NAME_DP_AUDIO + "/1/0", + NAME_DP_AUDIO + "/0/0" + }; private static final String NAME_HDMI = "hdmi"; private static final int MSG_NEW_DEVICE_STATE = 1; @@ -154,7 +160,7 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks { break; } - updateLocked(NAME_H2W, + updateLocked(NAME_H2W, "", (mHeadsetState & ~(BIT_HEADSET | BIT_HEADSET_NO_MIC | BIT_LINEOUT)) | headset); } } @@ -178,7 +184,7 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks { * @param newName One of the NAME_xxx variables defined above. * @param newState 0 or one of the BIT_xxx variables defined above. */ - private void updateLocked(String newName, int newState) { + private void updateLocked(String newName, String address, int newState) { // Retain only relevant bits int headsetState = newState & SUPPORTED_HEADSETS; int usb_headset_anlg = headsetState & BIT_USB_HEADSET_ANLG; @@ -217,8 +223,10 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks { mWakeLock.acquire(); Log.i(TAG, "MSG_NEW_DEVICE_STATE"); + // send a combined name, address string separated by | Message msg = mHandler.obtainMessage(MSG_NEW_DEVICE_STATE, headsetState, - mHeadsetState, ""); + mHeadsetState, + newName+"/"+address); mHandler.sendMessage(msg); mHeadsetState = headsetState; @@ -241,12 +249,13 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks { }; private void setDevicesState( - int headsetState, int prevHeadsetState, String headsetName) { + int headsetState, int prevHeadsetState, String headsetNameAddr) { synchronized (mLock) { int allHeadsets = SUPPORTED_HEADSETS; for (int curHeadset = 1; allHeadsets != 0; curHeadset <<= 1) { if ((curHeadset & allHeadsets) != 0) { - setDeviceStateLocked(curHeadset, headsetState, prevHeadsetState, headsetName); + setDeviceStateLocked(curHeadset, headsetState, prevHeadsetState, + headsetNameAddr); allHeadsets &= ~curHeadset; } } @@ -254,7 +263,7 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks { } private void setDeviceStateLocked(int headset, - int headsetState, int prevHeadsetState, String headsetName) { + int headsetState, int prevHeadsetState, String headsetNameAddr) { if ((headsetState & headset) != (prevHeadsetState & headset)) { int outDevice = 0; int inDevice = 0; @@ -285,15 +294,22 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks { } if (LOG) { - Slog.v(TAG, "headsetName: " + headsetName + - (state == 1 ? " connected" : " disconnected")); + Slog.v(TAG, "headset: " + headsetNameAddr + + (state == 1 ? " connected" : " disconnected")); } + String[] hs = headsetNameAddr.split("/"); if (outDevice != 0) { - mAudioManager.setWiredDeviceConnectionState(outDevice, state, "", headsetName); + if (LOG) { + Slog.v(TAG, "Output device address " + (hs.length > 1 ? hs[1] : "") + + " name " + hs[0]); + } + mAudioManager.setWiredDeviceConnectionState(outDevice, state, + (hs.length > 1 ? hs[1] : ""), hs[0]); } if (inDevice != 0) { - mAudioManager.setWiredDeviceConnectionState(inDevice, state, "", headsetName); + mAudioManager.setWiredDeviceConnectionState(inDevice, state, + (hs.length > 1 ? hs[1] : ""), hs[0]); } } } @@ -322,7 +338,6 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks { synchronized (mLock) { if (LOG) Slog.v(TAG, "init()"); char[] buffer = new char[1024]; - for (int i = 0; i < mUEventInfo.size(); ++i) { UEventInfo uei = mUEventInfo.get(i); try { @@ -396,30 +411,108 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks { } } + for (String conn : DP_AUDIO_CONNS) { + // Monitor DisplayPort + if (LOG) { + Slog.v(TAG, "Monitor DP conn " + conn); + } + uei = new UEventInfo(conn, BIT_HDMI_AUDIO, 0, 0); + if (uei.checkSwitchExists()) { + retVal.add(uei); + } else { + Slog.w(TAG, "Conn " + conn + " does not have DP audio support"); + } + } return retVal; } @Override public void onUEvent(UEventObserver.UEvent event) { - if (LOG) Slog.v(TAG, "Headset UEVENT: " + event.toString()); + String devPath = event.get("DEVPATH"); + String name = event.get("NAME"); + int state = 0; + + if (name == null) + name = event.get("SWITCH_NAME"); try { - String devPath = event.get("DEVPATH"); - String name = event.get("SWITCH_NAME"); - int state = Integer.parseInt(event.get("SWITCH_STATE")); - synchronized (mLock) { - updateStateLocked(devPath, name, state); + if (name.startsWith(NAME_DP_AUDIO)) { + String state_str = event.get("STATE"); + int offset = 0; + int length = state_str.length(); + + //parse DP=1\nHDMI=1\0 + while (offset < length) { + int equals = state_str.indexOf('=', offset); + + if (equals > offset) { + String intf_name = state_str.substring(offset, + equals); + + if (intf_name.equals("DP")) { + state = Integer.parseInt( + state_str.substring(equals + 1, + equals + 2)); + break; + } + } + + offset = equals + 3; + } + } else { + state = Integer.parseInt(event.get("SWITCH_STATE")); } } catch (NumberFormatException e) { - Slog.e(TAG, "Could not parse switch state from event " + event); + Slog.i(TAG, "couldn't get state from event, checking node"); + + for (int i = 0; i < mUEventInfo.size(); ++i) { + UEventInfo uei = mUEventInfo.get(i); + + if (name.equals(uei.getDevName())) { + char[] buffer = new char[1024]; + int len = 0; + + try { + FileReader file = new FileReader( + uei.getSwitchStatePath()); + len = file.read(buffer, 0, 1024); + file.close(); + } catch (FileNotFoundException e1) { + Slog.e(TAG, "file not found"); + break; + } catch (Exception e11) { + Slog.e(TAG, "" , e11); + } + + try { + state = Integer.parseInt( + (new String(buffer, 0, len)).trim()); + } catch (NumberFormatException e2) { + Slog.e(TAG, "could not convert to number"); + break; + } + break; + } + } + } + + synchronized (mLock) { + updateStateLocked(devPath, name, state); } } private void updateStateLocked(String devPath, String name, int state) { for (int i = 0; i < mUEventInfo.size(); ++i) { UEventInfo uei = mUEventInfo.get(i); + if (LOG) { + Slog.v(TAG, "uei.getDevPath=" + uei.getDevPath()); + Slog.v(TAG, "uevent.getDevPath=" + devPath); + } + if (devPath.equals(uei.getDevPath())) { - updateLocked(name, uei.computeNewHeadsetState(mHeadsetState, state)); + updateLocked(name, uei.getDevAddress(), + uei.computeNewHeadsetState(mHeadsetState, + state)); return; } } @@ -427,25 +520,142 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks { private final class UEventInfo { private final String mDevName; + private String mDevAddress; private final int mState1Bits; private final int mState2Bits; private final int mStateNbits; + private int mDevIndex; + private int mCableIndex; - public UEventInfo(String devName, int state1Bits, int state2Bits, int stateNbits) { + public UEventInfo(String devName, int state1Bits, + int state2Bits, int stateNbits) { mDevName = devName; + mDevAddress = "controller=0;stream=0"; mState1Bits = state1Bits; mState2Bits = state2Bits; mStateNbits = stateNbits; + mDevIndex = -1; + mCableIndex = -1; + + if (mDevName.startsWith(NAME_DP_AUDIO)) { + int idx = mDevName.indexOf("/"); + if (idx != -1) { + int idx2 = mDevName.indexOf("/", idx+1); + assert(idx2 != -1); + int dev = Integer.parseInt(mDevName.substring(idx+1, idx2)); + int cable = Integer.parseInt(mDevName.substring(idx2+1)); + mDevAddress = "controller=" + dev + ";stream=" + cable; + if (LOG) { + Slog.v(TAG, "UEvent dev address " + mDevAddress); + } + checkDevIndex(dev); + checkCableIndex(cable); + } + } + } + + private void checkDevIndex(int dev_index) { + int index = 0; + char[] buffer = new char[1024]; + while (true) { + String devPath = String.format(Locale.US, + "/sys/devices/platform/soc/%s/extcon/extcon%d/name", + NAME_DP_AUDIO, index); + if (LOG) { + Slog.v(TAG, "checkDevIndex " + devPath); + } + File f = new File(devPath); + if (!f.exists()) { + Slog.e(TAG, "file " + devPath + " not found"); + break; + } + try { + FileReader file = new FileReader(f); + int len = file.read(buffer, 0, 1024); + file.close(); + + String devName = (new String(buffer, 0, len)).trim(); + if (devName.startsWith(NAME_DP_AUDIO) && index == dev_index) { + Slog.e(TAG, "set dev_index " + dev_index); + mDevIndex = dev_index; + break; + } else { + index++; + } + } catch (Exception e) { + Slog.e(TAG, "checkDevIndex exception " , e); + break; + } + } + } + + private void checkCableIndex(int cable_index) { + if (mDevIndex == -1) { + return; + } + int index = 0; + char[] buffer = new char[1024]; + while (true) + { + String cablePath = String.format(Locale.US, + "/sys/devices/platform/soc/%s/extcon/extcon%d/cable.%d/name", + NAME_DP_AUDIO, mDevIndex, index); + if (LOG) { + Slog.v(TAG, "checkCableIndex " + cablePath); + } + File f = new File(cablePath); + if (!f.exists()) { + Slog.e(TAG, "file " + cablePath + " not found"); + break; + } + try { + FileReader file = new FileReader(f); + int len = file.read(buffer, 0, 1024); + file.close(); + + String cableName = (new String(buffer, 0, len)).trim(); + if (cableName.equals("DP") && index == cable_index) { + mCableIndex = index; + Slog.w(TAG, "checkCableIndex set cable " + cable_index); + break; + } else { + Slog.w(TAG, "checkCableIndex no name match, skip "); + index++; + } + } catch (Exception e) { + Slog.e(TAG, "checkCableIndex exception", e); + break; + } + } } public String getDevName() { return mDevName; } + public String getDevAddress() { return mDevAddress; } + public String getDevPath() { - return String.format(Locale.US, "/devices/virtual/switch/%s", mDevName); + if (mDevName.startsWith(NAME_DP_AUDIO)) { + return String.format(Locale.US, + "/devices/platform/soc/%s/extcon/extcon%d", + NAME_DP_AUDIO, + mDevIndex); + } else { + return String.format(Locale.US, + "/devices/virtual/switch/%s", + mDevName); + } } public String getSwitchStatePath() { - return String.format(Locale.US, "/sys/class/switch/%s/state", mDevName); + if (mDevName.startsWith(NAME_DP_AUDIO)) { + return String.format(Locale.US, + "/sys/devices/platform/soc/%s/extcon/extcon%d/cable.%d/state", + NAME_DP_AUDIO, mDevIndex, mCableIndex); + } else { + return String.format(Locale.US, + "/sys/class/switch/%s/state", + mDevName); + } } public boolean checkSwitchExists() { diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java index e879efd644d1..400c36ae7b52 100644 --- a/services/core/java/com/android/server/accounts/AccountManagerService.java +++ b/services/core/java/com/android/server/accounts/AccountManagerService.java @@ -1445,6 +1445,7 @@ public class AccountManagerService @Override public String getPassword(Account account) { + android.util.SeempLog.record(14); int callingUid = Binder.getCallingUid(); if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "getPassword: " + account @@ -1525,6 +1526,7 @@ public class AccountManagerService @Override public String getUserData(Account account, String key) { + android.util.SeempLog.record(15); final int callingUid = Binder.getCallingUid(); if (Log.isLoggable(TAG, Log.VERBOSE)) { String msg = String.format("getUserData( account: %s, key: %s, callerUid: %s, pid: %s", @@ -2099,6 +2101,7 @@ public class AccountManagerService @Override public void removeAccount(IAccountManagerResponse response, Account account, boolean expectActivityLaunch) { + android.util.SeempLog.record(17); removeAccountAsUser( response, account, @@ -2540,6 +2543,7 @@ public class AccountManagerService @Override public void setPassword(Account account, String password) { + android.util.SeempLog.record(18); final int callingUid = Binder.getCallingUid(); if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "setAuthToken: " + account @@ -2606,6 +2610,7 @@ public class AccountManagerService @Override public void clearPassword(Account account) { + android.util.SeempLog.record(19); final int callingUid = Binder.getCallingUid(); if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "clearPassword: " + account @@ -2632,6 +2637,7 @@ public class AccountManagerService @Override public void setUserData(Account account, String key, String value) { + android.util.SeempLog.record(20); final int callingUid = Binder.getCallingUid(); if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "setUserData: " + account @@ -3115,6 +3121,7 @@ public class AccountManagerService public void addAccount(final IAccountManagerResponse response, final String accountType, final String authTokenType, final String[] requiredFeatures, final boolean expectActivityLaunch, final Bundle optionsIn) { + android.util.SeempLog.record(16); Bundle.setDefusable(optionsIn, true); if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "addAccount: accountType " + accountType @@ -3868,6 +3875,7 @@ public class AccountManagerService @Override public void editProperties(IAccountManagerResponse response, final String accountType, final boolean expectActivityLaunch) { + android.util.SeempLog.record(21); final int callingUid = Binder.getCallingUid(); if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "editProperties: accountType " + accountType diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index a96676e5fc5f..6151276d640d 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -94,7 +94,9 @@ import com.android.server.LocalServices; import com.android.server.SystemService; import com.android.server.am.ActivityManagerService.ItemMatcher; import com.android.server.uri.NeededUriGrants; +import com.android.server.wm.ActivityRecord; import com.android.server.wm.ActivityServiceConnectionsHolder; +import com.android.server.wm.ActivityStack; import java.io.FileDescriptor; import java.io.IOException; @@ -139,6 +141,10 @@ public final class ActiveServices { // at the same time. final int mMaxStartingBackground; + // Flag to reschedule the services during app launch. Disable by default. + private static final boolean SERVICE_RESCHEDULE + = SystemProperties.getBoolean("ro.vendor.qti.am.reschedule_service", false); + final SparseArray<ServiceMap> mServiceMap = new SparseArray<>(); /** @@ -2308,6 +2314,14 @@ public final class ActiveServices { r.pendingStarts.add(0, si); long dur = SystemClock.uptimeMillis() - si.deliveredTime; dur *= 2; + if (SERVICE_RESCHEDULE && DEBUG_DELAYED_SERVICE) { + Slog.w(TAG,"Can add more delay !!!" + +" si.deliveredTime "+si.deliveredTime + +" dur "+dur + +" si.deliveryCount "+si.deliveryCount + +" si.doneExecutingCount "+si.doneExecutingCount + +" allowCancel "+allowCancel); + } if (minDuration < dur) minDuration = dur; if (resetTime < dur) resetTime = dur; } else { @@ -2320,6 +2334,13 @@ public final class ActiveServices { } r.totalRestartCount++; + if (SERVICE_RESCHEDULE && DEBUG_DELAYED_SERVICE) { + Slog.w(TAG,"r.name "+r.name+" N "+N+" minDuration "+minDuration + +" resetTime "+resetTime+" now "+now + +" r.restartDelay "+r.restartDelay + +" r.restartTime+resetTime "+(r.restartTime+resetTime) + +" allowCancel "+allowCancel); + } if (r.restartDelay == 0) { r.restartCount++; r.restartDelay = minDuration; @@ -2344,6 +2365,14 @@ public final class ActiveServices { } r.nextRestartTime = now + r.restartDelay; + if (SERVICE_RESCHEDULE && DEBUG_DELAYED_SERVICE) { + Slog.w(TAG,"r.name "+r.name+" N "+N+" minDuration "+minDuration + +" resetTime "+resetTime+" now "+now + +" r.restartDelay "+r.restartDelay + +" r.restartTime+resetTime "+(r.restartTime+resetTime) + +" r.nextRestartTime "+r.nextRestartTime + +" allowCancel "+allowCancel); + } // Make sure that we don't end up restarting a bunch of services // all at the same time. @@ -2385,6 +2414,15 @@ public final class ActiveServices { r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay; Slog.w(TAG, "Scheduling restart of crashed service " + r.shortInstanceName + " in " + r.restartDelay + "ms"); + + if (SERVICE_RESCHEDULE && DEBUG_DELAYED_SERVICE) { + for (int i=mRestartingServices.size()-1; i>=0; i--) { + ServiceRecord r2 = mRestartingServices.get(i); + Slog.w(TAG,"Restarting list - i "+i+" r2.nextRestartTime " + +r2.nextRestartTime+" r2.name "+r2.name); + } + } + EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART, r.userId, r.shortInstanceName, r.restartDelay); @@ -2405,7 +2443,35 @@ public final class ActiveServices { return; } try { - bringUpServiceLocked(r, r.intent.getIntent().getFlags(), r.createdFromFg, true, false); + if(SERVICE_RESCHEDULE) { + boolean shouldDelay = false; + ActivityRecord top_rc = null; + ActivityStack stack = mAm.mStackSupervisor.mRootActivityContainer.getTopDisplayFocusedStack(); + if(stack != null) { + top_rc = stack.topRunningActivityLocked(); + } + + boolean isPersistent + = !((r.serviceInfo.applicationInfo.flags&ApplicationInfo.FLAG_PERSISTENT) == 0); + if(top_rc != null) { + if(top_rc.launching && !r.shortInstanceName.contains(top_rc.packageName) + && !isPersistent) { + shouldDelay = true; + } + } + if(!shouldDelay) { + bringUpServiceLocked(r, r.intent.getIntent().getFlags(), r.createdFromFg, true, false); + } else { + if (DEBUG_DELAYED_SERVICE) { + Slog.v(TAG, "Reschedule service restart due to app launch" + +" r.shortInstanceName "+r.shortInstanceName+" r.app = "+r.app); + } + r.resetRestartCounter(); + scheduleServiceRestartLocked(r, true); + } + } else { + bringUpServiceLocked(r, r.intent.getIntent().getFlags(), r.createdFromFg, true, false); + } } catch (TransactionTooLargeException e) { // Ignore, it's been logged and nothing upstack cares. } @@ -2651,7 +2717,12 @@ public final class ActiveServices { // Cleanup. if (newService) { app.services.remove(r); - r.setProcess(null); + r.app = null; + if (SERVICE_RESCHEDULE && DEBUG_DELAYED_SERVICE) { + Slog.w(TAG, " Failed to create Service !!!! ." + +"This will introduce huge delay... " + +r.shortInstanceName + " in " + r.restartDelay + "ms"); + } } // Retry. diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java index dd2b33ab1179..14ef06e2d0dd 100644 --- a/services/core/java/com/android/server/am/ActivityManagerConstants.java +++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java @@ -22,6 +22,8 @@ import android.content.ContentResolver; import android.database.ContentObserver; import android.net.Uri; import android.os.Handler; +import android.os.SystemProperties; +import android.os.Process; import android.provider.Settings; import android.util.KeyValueListParser; import android.util.Slog; @@ -77,7 +79,8 @@ final class ActivityManagerConstants extends ContentObserver { static final String KEY_COMPACT_THROTTLE_3 = "compact_throttle_3"; static final String KEY_COMPACT_THROTTLE_4 = "compact_throttle_4"; - private static final int DEFAULT_MAX_CACHED_PROCESSES = 32; + private static final int DEFAULT_MAX_CACHED_PROCESSES = + SystemProperties.getInt("ro.vendor.qti.sys.fw.bg_apps_limit",32); private static final long DEFAULT_BACKGROUND_SETTLE_TIME = 60*1000; private static final long DEFAULT_FGSERVICE_MIN_SHOWN_TIME = 2*1000; private static final long DEFAULT_FGSERVICE_MIN_REPORT_TIME = 3*1000; @@ -274,6 +277,17 @@ final class ActivityManagerConstants extends ContentObserver { // process limit. public int CUR_MAX_CACHED_PROCESSES; + static final boolean USE_TRIM_SETTINGS = + SystemProperties.getBoolean("ro.vendor.qti.sys.fw.use_trim_settings",true); + static final int EMPTY_APP_PERCENT = SystemProperties.getInt("ro.vendor.qti.sys.fw.empty_app_percent",50); + static final int TRIM_EMPTY_PERCENT = + SystemProperties.getInt("ro.vendor.qti.sys.fw.trim_empty_percent",100); + static final int TRIM_CACHE_PERCENT = + SystemProperties.getInt("ro.vendor.qti.sys.fw.trim_cache_percent",100); + static final long TRIM_ENABLE_MEMORY = + SystemProperties.getLong("ro.vendor.qti.sys.fw.trim_enable_memory",1073741824); + public static boolean allowTrim() { return Process.getTotalMemory() < TRIM_ENABLE_MEMORY ; } + // The maximum number of empty app processes we will let sit around. public int CUR_MAX_EMPTY_PROCESSES; @@ -321,7 +335,27 @@ final class ActivityManagerConstants extends ContentObserver { } public static int computeEmptyProcessLimit(int totalProcessLimit) { - return totalProcessLimit/2; + if(USE_TRIM_SETTINGS && allowTrim()) { + return totalProcessLimit*EMPTY_APP_PERCENT/100; + } else { + return totalProcessLimit/2; + } + } + + public static int computeTrimEmptyApps(int rawMaxEmptyProcesses) { + if (USE_TRIM_SETTINGS && allowTrim()) { + return rawMaxEmptyProcesses*TRIM_EMPTY_PERCENT/100; + } else { + return rawMaxEmptyProcesses/2; + } + } + + public static int computeTrimCachedApps(int rawMaxEmptyProcesses, int totalProcessLimit) { + if (USE_TRIM_SETTINGS && allowTrim()) { + return totalProcessLimit*TRIM_CACHE_PERCENT/100; + } else { + return (totalProcessLimit-rawMaxEmptyProcesses)/3; + } } @Override @@ -437,8 +471,9 @@ final class ActivityManagerConstants extends ContentObserver { // to consider the same level the point where we do trimming regardless of any // additional enforced limit. final int rawMaxEmptyProcesses = computeEmptyProcessLimit(MAX_CACHED_PROCESSES); - CUR_TRIM_EMPTY_PROCESSES = rawMaxEmptyProcesses/2; - CUR_TRIM_CACHED_PROCESSES = (MAX_CACHED_PROCESSES-rawMaxEmptyProcesses)/3; + CUR_TRIM_EMPTY_PROCESSES = computeTrimEmptyApps(rawMaxEmptyProcesses); + CUR_TRIM_CACHED_PROCESSES = + computeTrimCachedApps(rawMaxEmptyProcesses, MAX_CACHED_PROCESSES); } void dump(PrintWriter pw) { diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 089847d1ff7f..fa63fb6333a6 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -73,6 +73,8 @@ import static android.os.Process.myUid; import static android.os.Process.readProcFile; import static android.os.Process.removeAllProcessGroups; import static android.os.Process.sendSignal; +import static android.os.Process.setProcessGroup; +import static android.os.Process.setCgroupProcsProcessGroup; import static android.os.Process.setThreadPriority; import static android.os.Process.setThreadScheduler; import static android.os.Process.zygoteProcess; @@ -246,6 +248,7 @@ import android.os.Looper; import android.os.Message; import android.os.Parcel; import android.os.ParcelFileDescriptor; +import android.os.PowerManager; import android.os.PowerManager.ServiceType; import android.os.PowerManagerInternal; import android.os.Process; @@ -289,6 +292,8 @@ import android.view.IRecentsAnimationRunner; import android.view.LayoutInflater; import android.view.View; import android.view.WindowManager; +import android.util.BoostFramework; + import android.view.autofill.AutofillManagerInternal; import com.android.internal.R; @@ -300,6 +305,7 @@ import com.android.internal.app.IAppOpsService; import com.android.internal.app.ProcessMap; import com.android.internal.app.SystemUserHomeActivity; import com.android.internal.app.procstats.ProcessStats; +import com.android.internal.app.ActivityTrigger; import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; import com.android.internal.notification.SystemNotificationChannels; import com.android.internal.os.BackgroundThread; @@ -347,6 +353,7 @@ import com.android.server.uri.UriGrantsManagerInternal; import com.android.server.utils.PriorityDump; import com.android.server.vr.VrManagerInternal; import com.android.server.wm.ActivityServiceConnectionsHolder; +import com.android.server.wm.ActivityStackSupervisor; import com.android.server.wm.ActivityTaskManagerInternal; import com.android.server.wm.ActivityTaskManagerService; import com.android.server.wm.WindowManagerService; @@ -531,6 +538,11 @@ public class ActivityManagerService extends IActivityManager.Stub private static final int NATIVE_DUMP_TIMEOUT_MS = 2000; // 2 seconds; + /* Freq Aggr boost objects */ + public static BoostFramework mPerfServiceStartHint = null; + /* UX perf event object */ + public static BoostFramework mUxPerf = new BoostFramework(); + final OomAdjuster mOomAdjuster; /** All system services */ @@ -538,6 +550,9 @@ public class ActivityManagerService extends IActivityManager.Stub private Installer mInstaller; + /** Run all ActivityStacks through this */ + ActivityStackSupervisor mStackSupervisor; + final InstrumentationReporter mInstrumentationReporter = new InstrumentationReporter(); final ArrayList<ActiveInstrumentation> mActiveInstrumentation = new ArrayList<>(); @@ -1447,8 +1462,23 @@ public class ActivityManagerService extends IActivityManager.Stub static final String SERVICE_RECORD_KEY = "servicerecord"; + static final ActivityTrigger mActivityTrigger = new ActivityTrigger(); + long mLastMemUsageReportTime = 0; + // Min aging threshold in milliseconds to consider a B-service + int mMinBServiceAgingTime = + SystemProperties.getInt("ro.vendor.qti.sys.fw.bservice_age", 5000); + // Threshold for B-services when in memory pressure + int mBServiceAppThreshold = + SystemProperties.getInt("ro.vendor.qti.sys.fw.bservice_limit", 5); + // Enable B-service aging propagation on memory pressure. + boolean mEnableBServicePropagation = + SystemProperties.getBoolean("ro.vendor.qti.sys.fw.bservice_enable", false); + // Process in same process Group keep in same cgroup + boolean mEnableProcessGroupCgroupFollow = + SystemProperties.getBoolean("ro.vendor.qti.cgroup_follow.enable",false); + /** * Flag whether the current user is a "monkey", i.e. whether * the UI is driven by a UI automation tool. @@ -2326,6 +2356,7 @@ public class ActivityManagerService extends IActivityManager.Stub mActivityTaskManager.initialize(mIntentFirewall, mPendingIntentController, DisplayThread.get().getLooper()); mAtmInternal = LocalServices.getService(ActivityTaskManagerInternal.class); + mStackSupervisor = mActivityTaskManager.mStackSupervisor; mProcessCpuThread = new Thread("CpuTracker") { @Override @@ -3263,6 +3294,41 @@ public class ActivityManagerService extends IActivityManager.Stub return mActivityTaskManager.startActivityFromRecents(taskId, bOptions); } + final int startActivityAsUserEmpty(IApplicationThread caller, String callingPackage, + Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, + int startFlags, ProfilerInfo profilerInfo, Bundle options, int userId) { + ArrayList<String> pApps = options.getStringArrayList("start_empty_apps"); + if (pApps != null && pApps.size() > 0) { + Iterator<String> apps_itr = pApps.iterator(); + while (apps_itr.hasNext()) { + ProcessRecord empty_app = null; + String app_str = apps_itr.next(); + if (app_str == null) + continue; + synchronized (this) { + Intent intent_l = null; + try { + intent_l = mContext.getPackageManager().getLaunchIntentForPackage(app_str); + if (intent_l == null) + continue; + ActivityInfo aInfo = mStackSupervisor.resolveActivity(intent_l, null, + 0, null, 0, 0); + if (aInfo == null) + continue; + empty_app = startProcessLocked(app_str, aInfo.applicationInfo, false, 0, + "activity", null, false, false, true); + if (empty_app != null) + updateOomAdjLocked(empty_app, true); + } catch (Exception e) { + if (DEBUG_PROCESSES) + Slog.w(TAG, "Exception raised trying to start app as empty " + e); + } + } + } + } + return 1; + } + @Override public void startRecentsActivity(Intent intent, IAssistDataReceiver assistDataReceiver, IRecentsAnimationRunner recentsAnimationRunner) { @@ -3485,6 +3551,11 @@ public class ActivityManagerService extends IActivityManager.Stub mAllowLowerMemLevel = false; doLowMem = false; } + + if (mUxPerf != null) { + mUxPerf.perfUXEngine_events(BoostFramework.UXE_EVENT_KILL, 0, app.processName, 0); + } + EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.userId, app.pid, app.processName, app.setAdj, app.setProcState); if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP, @@ -4361,6 +4432,10 @@ public class ActivityManagerService extends IActivityManager.Stub Slog.i(TAG, "Force stopping u" + userId + ": " + reason); } + if (mUxPerf != null) { + mUxPerf.perfUXEngine_events(BoostFramework.UXE_EVENT_KILL, 0, packageName, 0); + } + mAppErrors.resetProcessCrashTimeLocked(packageName == null, appId, userId); } diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java index 054c83080d98..8947e6b85f4c 100644 --- a/services/core/java/com/android/server/am/ProcessRecord.java +++ b/services/core/java/com/android/server/am/ProcessRecord.java @@ -52,6 +52,7 @@ import android.util.SparseArray; import android.util.StatsLog; import android.util.TimeUtils; import android.util.proto.ProtoOutputStream; +import android.util.BoostFramework; import com.android.internal.app.procstats.ProcessState; import com.android.internal.app.procstats.ProcessStats; @@ -585,6 +586,18 @@ final class ProcessRecord implements WindowProcessListener { } public void makeActive(IApplicationThread _thread, ProcessStatsService tracker) { + String seempStr = "app_uid=" + uid + + ",app_pid=" + pid + ",oom_adj=" + curAdj + + ",setAdj=" + setAdj + ",hasShownUi=" + (hasShownUi ? 1 : 0) + + ",cached=" + (cached ? 1 : 0) + + ",fA=" + (mHasForegroundActivities ? 1 : 0) + + ",fS=" + (mHasForegroundServices ? 1 : 0) + + ",systemNoUi=" + (systemNoUi ? 1 : 0) + + ",curSchedGroup=" + mCurSchedGroup + + ",curProcState=" + getCurProcState() + ",setProcState=" + setProcState + + ",killed=" + (killed ? 1 : 0) + ",killedByAm=" + (killedByAm ? 1 : 0) + + ",isDebugging=" + (isDebugging() ? 1 : 0); + android.util.SeempLog.record_str(386, seempStr); if (thread == null) { final ProcessState origBase = baseProcessTracker; if (origBase != null) { @@ -618,6 +631,18 @@ final class ProcessRecord implements WindowProcessListener { } public void makeInactive(ProcessStatsService tracker) { + String seempStr = "app_uid=" + uid + + ",app_pid=" + pid + ",oom_adj=" + curAdj + + ",setAdj=" + setAdj + ",hasShownUi=" + (hasShownUi ? 1 : 0) + + ",cached=" + (cached ? 1 : 0) + + ",fA=" + (mHasForegroundActivities ? 1 : 0) + + ",fS=" + (mHasForegroundServices ? 1 : 0) + + ",systemNoUi=" + (systemNoUi ? 1 : 0) + + ",curSchedGroup=" + mCurSchedGroup + + ",curProcState=" + getCurProcState() + ",setProcState=" + setProcState + + ",killed=" + (killed ? 1 : 0) + ",killedByAm=" + (killedByAm ? 1 : 0) + + ",isDebugging=" + (isDebugging() ? 1 : 0); + android.util.SeempLog.record_str(387, seempStr); thread = null; mWindowProcessController.setThread(null); final ProcessState origBase = baseProcessTracker; @@ -750,6 +775,7 @@ final class ProcessRecord implements WindowProcessListener { void kill(String reason, boolean noisy) { if (!killedByAm) { Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "kill"); + BoostFramework ux_perf = new BoostFramework(); if (mService != null && (noisy || info.uid == mService.mCurOomAdjUid)) { mService.reportUidInfoMessageLocked(TAG, "Killing " + toShortString() + " (adj " + setAdj + "): " + reason, @@ -766,6 +792,9 @@ final class ProcessRecord implements WindowProcessListener { killed = true; killedByAm = true; } + if (ux_perf != null) { + ux_perf.perfUXEngine_events(BoostFramework.UXE_EVENT_KILL, 0, this.processName, 0); + } Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); } } diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index 11299b690bb1..7e5f51c7b206 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -989,6 +989,7 @@ public class AudioService extends IAudioService.Stub 0, 0, null, 0); mScoConnectionState = AudioManager.SCO_AUDIO_STATE_ERROR; + Log.i(TAG, "In onSystemReady(), calling resetBluetoothSco()"); resetBluetoothSco(); getBluetoothHeadset(); //FIXME: this is to maintain compatibility with deprecated intent @@ -1626,15 +1627,15 @@ public class AudioService extends IAudioService.Stub private void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags, String callingPackage, String caller, int uid) { - if (DEBUG_VOL) Log.d(TAG, "adjustSuggestedStreamVolume() stream=" + suggestedStreamType - + ", flags=" + flags + ", caller=" + caller - + ", volControlStream=" + mVolumeControlStream - + ", userSelect=" + mUserSelectedVolumeControlStream); mVolumeLogger.log(new VolumeEvent(VolumeEvent.VOL_ADJUST_SUGG_VOL, suggestedStreamType, direction/*val1*/, flags/*val2*/, new StringBuilder(callingPackage) .append("/").append(caller).append(" uid:").append(uid).toString())); final int streamType; synchronized (mForceControlStreamLock) { + if (DEBUG_VOL) Log.d(TAG, "adjustSuggestedStreamVolume() stream=" + suggestedStreamType + + ", flags=" + flags + ", caller=" + caller + + ", volControlStream=" + mVolumeControlStream + + ", userSelect=" + mUserSelectedVolumeControlStream); // Request lock in case mVolumeControlStream is changed by other thread. if (mUserSelectedVolumeControlStream) { // implies mVolumeControlStream != -1 streamType = mVolumeControlStream; @@ -1696,11 +1697,19 @@ public class AudioService extends IAudioService.Stub protected void adjustStreamVolume(int streamType, int direction, int flags, String callingPackage, String caller, int uid) { + if (DEBUG_VOL) Log.d(TAG, "adjustStreamVolume() stream=" + streamType + ", dir=" + direction + + ", flags=" + flags + ", caller=" + caller); + + /* If MirrorLink audio is playing, then disable volume changes */ + String value = SystemProperties.get("vendor.mls.audio.session.status", "default"); + if (true == value.equals("started")){ + Log.e(TAG, "adjustStreamVolume() Ignore volume change during MirrorLink session"); + return; + } + if (mUseFixedVolume) { return; } - if (DEBUG_VOL) Log.d(TAG, "adjustStreamVolume() stream=" + streamType + ", dir=" + direction - + ", flags=" + flags + ", caller=" + caller); ensureValidDirection(direction); ensureValidStreamType(streamType); @@ -2077,6 +2086,14 @@ public class AudioService extends IAudioService.Stub Log.d(TAG, "setStreamVolume(stream=" + streamType+", index=" + index + ", calling=" + callingPackage + ")"); } + + /* If MirrorLink audio is playing, then disable volume changes */ + String value = SystemProperties.get("vendor.mls.audio.session.status", "default"); + if (true == value.equals("started")){ + Log.e(TAG, "setStreamVolume() Ignore volume change during MirrorLink session"); + return; + } + if (mUseFixedVolume) { return; } @@ -2945,6 +2962,7 @@ public class AudioService extends IAudioService.Stub // SCO connections not started by the application changing the mode when pid changes if ((newModeOwnerPid != oldModeOwnerPid) && (newModeOwnerPid != 0)) { final long ident = Binder.clearCallingIdentity(); + Log.i(TAG, "In binderDied(), calling disconnectBluetoothSco()"); disconnectBluetoothSco(newModeOwnerPid); Binder.restoreCallingIdentity(ident); } @@ -2969,6 +2987,8 @@ public class AudioService extends IAudioService.Stub /** @see AudioManager#setMode(int) */ public void setMode(int mode, IBinder cb, String callingPackage) { + Log.i(TAG, "setMode(mode = " + mode + ", callingPackage = " + + callingPackage + ", Process ID: " + Binder.getCallingPid()); if (DEBUG_MODE) { Log.v(TAG, "setMode(mode=" + mode + ", callingPackage=" + callingPackage + ")"); } if (!checkAudioSettingsPermission("setMode()")) { return; @@ -3001,6 +3021,7 @@ public class AudioService extends IAudioService.Stub // when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all // SCO connections not started by the application changing the mode when pid changes if ((newModeOwnerPid != oldModeOwnerPid) && (newModeOwnerPid != 0)) { + Log.i(TAG, "In setMode(), calling disconnectBluetoothSco()"); disconnectBluetoothSco(newModeOwnerPid); } } @@ -3375,6 +3396,7 @@ public class AudioService extends IAudioService.Stub final String eventSource = new StringBuilder("setSpeakerphoneOn(").append(on) .append(") from u/pid:").append(Binder.getCallingUid()).append("/") .append(Binder.getCallingPid()).toString(); + Log.i(TAG, "In setSpeakerphoneOn(), on: " + on + ", eventSource: " + eventSource); if (on) { if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) { @@ -3388,12 +3410,16 @@ public class AudioService extends IAudioService.Stub } mForcedUseForCommExt = mForcedUseForComm; + Log.i(TAG, "In setSpeakerphoneOn(), mForcedUseForCommExt: " + + mForcedUseForCommExt); sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE, AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, eventSource, 0); } /** @see AudioManager#isSpeakerphoneOn() */ public boolean isSpeakerphoneOn() { + Log.i(TAG, "In isSpeakerphoneOn(), mForcedUseForCommExt: " + + mForcedUseForCommExt); return (mForcedUseForCommExt == AudioSystem.FORCE_SPEAKER); } @@ -3402,10 +3428,17 @@ public class AudioService extends IAudioService.Stub if (!checkAudioSettingsPermission("setBluetoothScoOn()")) { return; } - // Only enable calls from system components if (UserHandle.getCallingAppId() >= FIRST_APPLICATION_UID) { - mForcedUseForCommExt = on ? AudioSystem.FORCE_BT_SCO : AudioSystem.FORCE_NONE; + Log.i(TAG, "In setBluetoothScoOn(), on: "+on+". The calling application Uid: " + + Binder.getCallingUid() + ", is greater than FIRST_APPLICATION_UID" + + " exiting from setBluetoothScoOn()"); + if (on) + mForcedUseForCommExt = AudioSystem.FORCE_BT_SCO; + else if (mForcedUseForCommExt == AudioSystem.FORCE_BT_SCO) + mForcedUseForCommExt = AudioSystem.FORCE_NONE; + Log.i(TAG, "In setbluetoothScoOn(), mForcedUseForCommExt: " + + mForcedUseForCommExt); return; } @@ -3413,9 +3446,36 @@ public class AudioService extends IAudioService.Stub final String eventSource = new StringBuilder("setBluetoothScoOn(").append(on) .append(") from u/pid:").append(Binder.getCallingUid()).append("/") .append(Binder.getCallingPid()).toString(); + Log.i(TAG, "In setBluetoothScoOn(), eventSource: " + eventSource); setBluetoothScoOnInt(on, eventSource); } + private boolean isBluetoothAudioNotConnectedToEarbud() { + //default value as true so that + //non-twsplus device case returns true + boolean ret = true; + if (mBluetoothHeadsetDevice != null + && mBluetoothHeadsetDevice.isTwsPlusDevice()) { + //If It is TWSplus Device, check for TWS pair device + //Sco state + String pDevAddr = mBluetoothHeadsetDevice.getTwsPlusPeerAddress(); + if (pDevAddr != null) { + BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); + BluetoothDevice peerDev = adapter.getRemoteDevice(pDevAddr); + Log.d(TAG, "peer device audio State: " + mBluetoothHeadset.getAudioState(peerDev)); + if (mBluetoothHeadset.getAudioState(peerDev) + == BluetoothHeadset.STATE_AUDIO_CONNECTED || + mBluetoothHeadset.getAudioState(mBluetoothHeadsetDevice) + == BluetoothHeadset.STATE_AUDIO_CONNECTED) { + Log.w(TAG, "TwsPLus Case: one of eb SCO is connected"); + ret = false; + } + } + } + Log.d(TAG, "isBluetoothAudioConnectedToEarbud returns: " + ret); + return ret; + } + public void setBluetoothScoOnInt(boolean on, String eventSource) { Log.i(TAG, "setBluetoothScoOnInt: " + on + " " + eventSource); if (on) { @@ -3424,10 +3484,12 @@ public class AudioService extends IAudioService.Stub if ((mBluetoothHeadset != null) && (mBluetoothHeadset.getAudioState(mBluetoothHeadsetDevice) != BluetoothHeadset.STATE_AUDIO_CONNECTED)) { - mForcedUseForCommExt = AudioSystem.FORCE_BT_SCO; - Log.w(TAG, "setBluetoothScoOnInt(true) failed because " - + mBluetoothHeadsetDevice + " is not in audio connected mode"); - return; + if (isBluetoothAudioNotConnectedToEarbud()) { + mForcedUseForCommExt = AudioSystem.FORCE_BT_SCO; + Log.w(TAG, "setBluetoothScoOnInt(true) failed because " + + mBluetoothHeadsetDevice + " is not in audio connected mode"); + return; + } } } mForcedUseForComm = AudioSystem.FORCE_BT_SCO; @@ -3435,6 +3497,8 @@ public class AudioService extends IAudioService.Stub mForcedUseForComm = AudioSystem.FORCE_NONE; } mForcedUseForCommExt = mForcedUseForComm; + Log.i(TAG, "In setbluetoothScoOnInt(), mForcedUseForCommExt: " + + mForcedUseForCommExt); AudioSystem.setParameters("BT_SCO="+ (on ? "on" : "off")); sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE, AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, eventSource, 0); @@ -3446,6 +3510,8 @@ public class AudioService extends IAudioService.Stub /** @see AudioManager#isBluetoothScoOn() */ public boolean isBluetoothScoOn() { + Log.i(TAG, "In isBluetoothScoOn(), mForcedUseForCommExt: " + + mForcedUseForCommExt); return (mForcedUseForCommExt == AudioSystem.FORCE_BT_SCO); } @@ -3477,6 +3543,7 @@ public class AudioService extends IAudioService.Stub /** @see AudioManager#startBluetoothSco() */ public void startBluetoothSco(IBinder cb, int targetSdkVersion) { + Log.i(TAG, "In startBluetoothSco()"); int scoAudioMode = (targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR2) ? SCO_MODE_VIRTUAL_CALL : SCO_MODE_UNDEFINED; @@ -3485,10 +3552,12 @@ public class AudioService extends IAudioService.Stub /** @see AudioManager#startBluetoothScoVirtualCall() */ public void startBluetoothScoVirtualCall(IBinder cb) { + Log.i(TAG, "In startBluetoothScoVirtualCall()"); startBluetoothScoInt(cb, SCO_MODE_VIRTUAL_CALL); } void startBluetoothScoInt(IBinder cb, int scoAudioMode){ + Log.i(TAG, "In startBluetoothScoInt(), scoAudioMode: " + scoAudioMode); if (!checkAudioSettingsPermission("startBluetoothSco()") || !mSystemReady) { return; @@ -3506,6 +3575,7 @@ public class AudioService extends IAudioService.Stub /** @see AudioManager#stopBluetoothSco() */ public void stopBluetoothSco(IBinder cb){ + Log.i(TAG, "In stopBluetoothSco()"); if (!checkAudioSettingsPermission("stopBluetoothSco()") || !mSystemReady) { return; @@ -3548,21 +3618,40 @@ public class AudioService extends IAudioService.Stub public void incCount(int scoAudioMode) { synchronized(mScoClients) { - requestScoState(BluetoothHeadset.STATE_AUDIO_CONNECTED, scoAudioMode); + Log.i(TAG, "In incCount(), mStartcount = " + mStartcount); + boolean ScoState = requestScoState(BluetoothHeadset.STATE_AUDIO_CONNECTED, + scoAudioMode); + if (!ScoState) { + Log.e(TAG, "In incCount(), requestScoState failed returning"); + return; + } if (mStartcount == 0) { try { mCb.linkToDeath(this, 0); } catch (RemoteException e) { // client has already died! - Log.w(TAG, "ScoClient incCount() could not link to "+mCb+" binder death"); + Log.w(TAG, "ScoClient incCount() could not link to "+mCb+" binder death"); } } - mStartcount++; + //mStartCount should always be either 0 or 1 only if the startBluetoothSco + //is called by the same app multiple times by mistake. This will ensure that + //SCO gets disconnected when app calls stopBluetoothSco only once. + //Also, if SCO is already there, we just need to select the SCO devices by + //calling setBluetoothScoOn(true) in system context. + if (mStartcount == 1) { + Log.i(TAG, "mStartcount is 1, calling setBluetoothScoOn(true)" + + "in system context"); + setBluetoothScoOn(true); + } else if (mStartcount == 0) { + mStartcount++; + Log.i(TAG, "mStartcount is 0, incrementing by 1"); + } } } public void decCount() { synchronized(mScoClients) { + Log.i(TAG, "In decCount(), mStartcount: " + mStartcount); if (mStartcount == 0) { Log.w(TAG, "ScoClient.decCount() already 0"); } else { @@ -3574,13 +3663,16 @@ public class AudioService extends IAudioService.Stub Log.w(TAG, "decCount() going to 0 but not registered to binder"); } } - requestScoState(BluetoothHeadset.STATE_AUDIO_DISCONNECTED, 0); + boolean ScoState = requestScoState(BluetoothHeadset.STATE_AUDIO_DISCONNECTED, + 0); } } } public void clearCount(boolean stopSco) { synchronized(mScoClients) { + Log.i(TAG, "In clearCount(), stopSco: " + stopSco + + ", mStartcount: " + mStartcount); if (mStartcount != 0) { try { mCb.unlinkToDeath(this, 0); @@ -3590,7 +3682,8 @@ public class AudioService extends IAudioService.Stub } mStartcount = 0; if (stopSco) { - requestScoState(BluetoothHeadset.STATE_AUDIO_DISCONNECTED, 0); + boolean ScoState = requestScoState(BluetoothHeadset.STATE_AUDIO_DISCONNECTED, + 0); } } } @@ -3613,17 +3706,20 @@ public class AudioService extends IAudioService.Stub for (ScoClient mScoClient : mScoClients) { count += mScoClient.getCount(); } + Log.i(TAG, "In totalCount(), count: " + count); return count; } } - private void requestScoState(int state, int scoAudioMode) { + private boolean requestScoState(int state, int scoAudioMode) { + Log.i(TAG, "In requestScoState(), state: " + state + ", scoAudioMode: " + + scoAudioMode); checkScoAudioState(); int clientCount = totalCount(); if (clientCount != 0) { - Log.i(TAG, "requestScoState: state=" + state + ", scoAudioMode=" + scoAudioMode - + ", clientCount=" + clientCount); - return; + Log.w(TAG, "requestScoState: returning with state=" + state + ", scoAudioMode=" + + scoAudioMode + ", clientCount=" + clientCount); + return false; } if (state == BluetoothHeadset.STATE_AUDIO_CONNECTED) { // Make sure that the state transitions to CONNECTING even if we cannot initiate @@ -3638,7 +3734,7 @@ public class AudioService extends IAudioService.Stub Log.w(TAG, "requestScoState: audio mode is not NORMAL and modeOwnerPid " + modeOwnerPid + " != creatorPid " + mCreatorPid); broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED); - return; + return false; } switch (mScoAudioState) { case SCO_STATE_INACTIVE: @@ -3663,6 +3759,7 @@ public class AudioService extends IAudioService.Stub + " connection, mScoAudioMode=" + mScoAudioMode); broadcastScoConnectionState( AudioManager.SCO_AUDIO_STATE_DISCONNECTED); + return false; } break; } @@ -3671,7 +3768,7 @@ public class AudioService extends IAudioService.Stub + " mScoAudioMode=" + mScoAudioMode); broadcastScoConnectionState( AudioManager.SCO_AUDIO_STATE_DISCONNECTED); - break; + return false; } if (connectBluetoothScoAudioHelper(mBluetoothHeadset, mBluetoothHeadsetDevice, mScoAudioMode)) { @@ -3681,6 +3778,7 @@ public class AudioService extends IAudioService.Stub + " failed, mScoAudioMode=" + mScoAudioMode); broadcastScoConnectionState( AudioManager.SCO_AUDIO_STATE_DISCONNECTED); + return false; } break; case SCO_STATE_DEACTIVATING: @@ -3694,7 +3792,7 @@ public class AudioService extends IAudioService.Stub Log.w(TAG, "requestScoState: failed to connect in state " + mScoAudioState + ", scoAudioMode=" + scoAudioMode); broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED); - break; + return false; } } @@ -3710,6 +3808,7 @@ public class AudioService extends IAudioService.Stub mScoAudioState = SCO_STATE_INACTIVE; broadcastScoConnectionState( AudioManager.SCO_AUDIO_STATE_DISCONNECTED); + return false; } break; } @@ -3736,9 +3835,10 @@ public class AudioService extends IAudioService.Stub Log.w(TAG, "requestScoState: failed to disconnect in state " + mScoAudioState + ", scoAudioMode=" + scoAudioMode); broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED); - break; + return false; } } + return true; } } @@ -3751,6 +3851,7 @@ public class AudioService extends IAudioService.Stub mScoAudioState = SCO_STATE_ACTIVE_EXTERNAL; } } + Log.i(TAG, "In checkScoAudioState(), mScoAudioState: " + mScoAudioState); } @@ -3810,6 +3911,7 @@ public class AudioService extends IAudioService.Stub * @param exceptPid pid whose SCO connections through {@link AudioManager} should be kept */ private void disconnectBluetoothSco(int exceptPid) { + Log.i(TAG, "In disconnectBluetoothSco(), exceptPid: " + exceptPid); synchronized(mScoClients) { checkScoAudioState(); if (mScoAudioState == SCO_STATE_ACTIVE_EXTERNAL) { @@ -3821,12 +3923,19 @@ public class AudioService extends IAudioService.Stub private static boolean disconnectBluetoothScoAudioHelper(BluetoothHeadset bluetoothHeadset, BluetoothDevice device, int scoAudioMode) { + Log.i(TAG, "In disconnectBluetoothScoAudioHelper(), scoAudioMode: " + scoAudioMode + + ", bluetoothHeadset: " + bluetoothHeadset + ", BluetoothDevice: " + device); switch (scoAudioMode) { case SCO_MODE_RAW: + Log.i(TAG, "In disconnectBluetoothScoAudioHelper(), calling disconnectAudio()"); return bluetoothHeadset.disconnectAudio(); case SCO_MODE_VIRTUAL_CALL: + Log.i(TAG, "In disconnectBluetoothScoAudioHelper(), calling " + + "stopScoUsingVirtualVoiceCall()"); return bluetoothHeadset.stopScoUsingVirtualVoiceCall(); case SCO_MODE_VR: + Log.i(TAG, "In disconnectBluetoothScoAudioHelper(), calling " + + "stopVoiceRecognition()"); return bluetoothHeadset.stopVoiceRecognition(device); default: return false; @@ -3835,12 +3944,19 @@ public class AudioService extends IAudioService.Stub private static boolean connectBluetoothScoAudioHelper(BluetoothHeadset bluetoothHeadset, BluetoothDevice device, int scoAudioMode) { + Log.i(TAG, "In connectBluetoothScoAudioHelper(), scoAudioMode: " + scoAudioMode + + ", bluetoothHeadset: " + bluetoothHeadset + ", BluetoothDevice: " + device); switch (scoAudioMode) { case SCO_MODE_RAW: + Log.i(TAG, "In connectBluetoothScoAudioHelper(), calling connectAudio()"); return bluetoothHeadset.connectAudio(); case SCO_MODE_VIRTUAL_CALL: + Log.i(TAG, "In connectBluetoothScoAudioHelper(), calling " + + "startScoUsingVirtualVoiceCall()"); return bluetoothHeadset.startScoUsingVirtualVoiceCall(); case SCO_MODE_VR: + Log.i(TAG, "In connectBluetoothScoAudioHelper(), calling " + + "startVoiceRecognition()"); return bluetoothHeadset.startVoiceRecognition(device); default: return false; @@ -3849,10 +3965,12 @@ public class AudioService extends IAudioService.Stub private void resetBluetoothSco() { synchronized(mScoClients) { + Log.i(TAG, "In resetBluetoothSco(), calling clearAllScoClients()"); clearAllScoClients(0, false); mScoAudioState = SCO_STATE_INACTIVE; broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED); } + mScoClientDevices.clear(); AudioSystem.setParameters("A2dpSuspended=false"); setBluetoothScoOnInt(false, "resetBluetoothSco"); } @@ -3877,6 +3995,7 @@ public class AudioService extends IAudioService.Stub if (btDevice == null) { return true; } + String address = btDevice.getAddress(); BluetoothClass btClass = btDevice.getBluetoothClass(); int inDevice = AudioSystem.DEVICE_IN_BLUETOOTH_SCO_HEADSET; @@ -3900,6 +4019,12 @@ public class AudioService extends IAudioService.Stub address = ""; } String btDeviceName = btDevice.getName(); + if (btDeviceName == null) { + Slog.i(TAG, "handleBtScoActiveDeviceChange: btDeviceName is null," + + " sending empty string"); + btDeviceName = ""; + } + boolean result = false; if (isActive) { result |= handleDeviceConnection(isActive, outDeviceTypes[0], address, btDeviceName); @@ -3908,8 +4033,10 @@ public class AudioService extends IAudioService.Stub result |= handleDeviceConnection(isActive, outDeviceType, address, btDeviceName); } } + // handleDeviceConnection() && result to make sure the method get executed result = handleDeviceConnection(isActive, inDevice, address, btDeviceName) && result; + Slog.i(TAG, "for inDevice" + inDevice + " result is " + result); return result; } @@ -3917,6 +4044,14 @@ public class AudioService extends IAudioService.Stub synchronized (mScoClients) { Log.i(TAG, "setBtScoActiveDevice: " + mBluetoothHeadsetDevice + " -> " + btDevice); final BluetoothDevice previousActiveDevice = mBluetoothHeadsetDevice; + if (mBluetoothHeadsetDevice != null && mBluetoothHeadsetDevice.isTwsPlusDevice() + && btDevice != null + && Objects.equals(mBluetoothHeadsetDevice.getTwsPlusPeerAddress(), btDevice.getAddress())) { + Log.i(TAG, "setBtScoActiveDevice: Active device switch between twsplus devices"); + //Keep the same mBluetoothHeadsetDevice as current Active so + //that It tears down when active becomes null + return; + } if (!Objects.equals(btDevice, previousActiveDevice)) { if (!handleBtScoActiveDeviceChange(previousActiveDevice, false)) { Log.w(TAG, "setBtScoActiveDevice() failed to remove previous device " @@ -3929,6 +4064,7 @@ public class AudioService extends IAudioService.Stub } mBluetoothHeadsetDevice = btDevice; if (mBluetoothHeadsetDevice == null) { + Log.i(TAG, "In setBtScoActiveDevice(), calling resetBluetoothSco()"); resetBluetoothSco(); } } @@ -3938,6 +4074,8 @@ public class AudioService extends IAudioService.Stub private BluetoothProfile.ServiceListener mBluetoothProfileServiceListener = new BluetoothProfile.ServiceListener() { public void onServiceConnected(int profile, BluetoothProfile proxy) { + Log.i(TAG, "In onServiceConnected(), profile: " + profile + + ", proxy: " + proxy); BluetoothDevice btDevice; List<BluetoothDevice> deviceList; switch(profile) { @@ -3992,13 +4130,27 @@ public class AudioService extends IAudioService.Stub setBtScoActiveDevice(mBluetoothHeadset.getActiveDevice()); // Refresh SCO audio state checkScoAudioState(); + Log.i(TAG, "In HEADSET profile, mScoAudioState: " + mScoAudioState + + ", mScoAudioMode: " + mScoAudioMode); // Continue pending action if any if (mScoAudioState == SCO_STATE_ACTIVATE_REQ || mScoAudioState == SCO_STATE_DEACTIVATE_REQ) { boolean status = false; if (mBluetoothHeadsetDevice != null) { + // Get correct mScoAudioMode + mScoAudioMode = new Integer(Settings.Global.getInt( + mContentResolver, + "bluetooth_sco_channel_"+ + mBluetoothHeadsetDevice.getAddress(), + SCO_MODE_VIRTUAL_CALL)); + if (mScoAudioMode > SCO_MODE_MAX || mScoAudioMode < 0) { + Log.i(TAG, "Resetting the mScoAudioMode to " + + "SCO_MODE_VIRTUAL_CALL"); + mScoAudioMode = SCO_MODE_VIRTUAL_CALL; + } switch (mScoAudioState) { case SCO_STATE_ACTIVATE_REQ: + Log.i(TAG, "In HEADSET profile, calling connectBluetoothScoAudioHelper()"); status = connectBluetoothScoAudioHelper(mBluetoothHeadset, mBluetoothHeadsetDevice, mScoAudioMode); if (status) { @@ -4006,6 +4158,7 @@ public class AudioService extends IAudioService.Stub } break; case SCO_STATE_DEACTIVATE_REQ: + Log.i(TAG, "In HEADSET profile, calling disconnectBluetoothScoAudioHelper()"); status = disconnectBluetoothScoAudioHelper(mBluetoothHeadset, mBluetoothHeadsetDevice, mScoAudioMode); if (status) { @@ -4062,6 +4215,7 @@ public class AudioService extends IAudioService.Stub break; case BluetoothProfile.HEADSET: + Log.i(TAG, "In onServiceDisconnected(), calling disconnectHeadset()"); disconnectHeadset(); break; @@ -5837,6 +5991,7 @@ public class AudioService extends IAudioService.Stub break; case MSG_BT_HEADSET_CNCT_FAILED: + Log.i(TAG, "In handleMessage(), calling resetBluetoothSco()"); resetBluetoothSco(); break; @@ -6496,6 +6651,8 @@ public class AudioService extends IAudioService.Stub Log.w(TAG, "handleDeviceConnection() failed, deviceKey=" + deviceKey + ", deviceSpec=" + deviceSpec + ", connect=" + connect); } + + Slog.e(TAG, "handleDeviceConnection: returning false"); return false; } @@ -6542,7 +6699,7 @@ public class AudioService extends IAudioService.Stub 0, null, 0); - delay = 1000; + delay = SystemProperties.getInt("vendor.audio.noisy.broadcast.delay", 700); } } @@ -6763,6 +6920,75 @@ public class AudioService extends IAudioService.Stub } } } + //SCO device tracking for TWSPLUS device + private HashMap<BluetoothDevice, Integer> mScoClientDevices = + new HashMap<BluetoothDevice, Integer>(); + + private void updateTwsPlusScoState(BluetoothDevice device, Integer state) { + if (mScoClientDevices.containsKey(device)) { + Integer prevState = mScoClientDevices.get(device); + Log.i(TAG, "updateTwsPlusScoState: prevState: " + prevState + "state: " + state); + if (state != prevState) { + mScoClientDevices.remove(device); + mScoClientDevices.put(device, state); + } + } else { + mScoClientDevices.put(device, state); + } + } + + private boolean isAudioPathUp() { + boolean ret = false; + Iterator it = mScoClientDevices.entrySet().iterator(); + for (Integer value : mScoClientDevices.values()) { + if (value == BluetoothHeadset.STATE_AUDIO_CONNECTED) { + ret = true; + break; + } + } + Log.d(TAG, "isAudioPathUp returns" + ret); + return ret; + } + + private boolean checkAndUpdatTwsPlusScoState(Intent intent, Integer state) { + //default ret value is true + //so that legacy devices fallsthru + boolean ret = true; + BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); + Log.i(TAG, "device:" + device); + + if (device == null) { + Log.e(TAG, "checkAndUpdatTwsPlusScoState: device is null"); + //intent cant have device has null + //in case it is treat them as non-twsplus case and return true + return ret; + } + + if (device.isTwsPlusDevice()) { + if (state == BluetoothHeadset.STATE_AUDIO_CONNECTED) { + //if adding new Device + //check if there is no device already connected + if (isAudioPathUp()) { + Log.i(TAG, "No need to bringup audio-path"); + ret = false; + } + //Update the States now + updateTwsPlusScoState(device, state); + } else { + //For disconnect cases, update the state first + updateTwsPlusScoState(device, state); + //if deleting new Device + //check if all devices are disconnected + if (isAudioPathUp()) { + Log.i(TAG, "not good to tear down audio-path"); + ret = false; + } + } + } + Log.i(TAG, "checkAndUpdatTwsPlusScoState returns " + ret); + return ret; + } + /* cache of the address of the last dock the device was connected to */ private String mDockAddress; @@ -6811,6 +7037,8 @@ public class AudioService extends IAudioService.Stub mDockState = dockState; } else if (action.equals(BluetoothHeadset.ACTION_ACTIVE_DEVICE_CHANGED)) { BluetoothDevice btDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); + Log.i(TAG, "In onReceive(), calling setBtScoActiveDevice() with " + + "btDevice: " + btDevice); setBtScoActiveDevice(btDevice); } else if (action.equals(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED)) { boolean broadcast = false; @@ -6827,29 +7055,37 @@ public class AudioService extends IAudioService.Stub } switch (btState) { case BluetoothHeadset.STATE_AUDIO_CONNECTED: - scoAudioState = AudioManager.SCO_AUDIO_STATE_CONNECTED; - if (mScoAudioState != SCO_STATE_ACTIVE_INTERNAL && - mScoAudioState != SCO_STATE_DEACTIVATE_REQ) { - mScoAudioState = SCO_STATE_ACTIVE_EXTERNAL; + if (checkAndUpdatTwsPlusScoState(intent, + BluetoothHeadset.STATE_AUDIO_CONNECTED)) { + scoAudioState = AudioManager.SCO_AUDIO_STATE_CONNECTED; + if (mScoAudioState != SCO_STATE_ACTIVE_INTERNAL && + mScoAudioState != SCO_STATE_DEACTIVATE_REQ) { + mScoAudioState = SCO_STATE_ACTIVE_EXTERNAL; + } + setBluetoothScoOn(true); + Log.i(TAG, "Audio-path brought-up"); } - setBluetoothScoOn(true); break; case BluetoothHeadset.STATE_AUDIO_DISCONNECTED: - setBluetoothScoOn(false); - scoAudioState = AudioManager.SCO_AUDIO_STATE_DISCONNECTED; - // startBluetoothSco called after stopBluetoothSco - if (mScoAudioState == SCO_STATE_ACTIVATE_REQ) { - if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null - && connectBluetoothScoAudioHelper(mBluetoothHeadset, - mBluetoothHeadsetDevice, mScoAudioMode)) { - mScoAudioState = SCO_STATE_ACTIVE_INTERNAL; - broadcast = false; - break; + if (checkAndUpdatTwsPlusScoState(intent, + BluetoothHeadset.STATE_AUDIO_DISCONNECTED)) { + setBluetoothScoOn(false); + scoAudioState = AudioManager.SCO_AUDIO_STATE_DISCONNECTED; + // startBluetoothSco called after stopBluetoothSco + if (mScoAudioState == SCO_STATE_ACTIVATE_REQ) { + if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null + && connectBluetoothScoAudioHelper(mBluetoothHeadset, + mBluetoothHeadsetDevice, mScoAudioMode)) { + mScoAudioState = SCO_STATE_ACTIVE_INTERNAL; + broadcast = false; + break; + } } + // Tear down SCO if disconnected from external + clearAllScoClients(0, mScoAudioState == SCO_STATE_ACTIVE_INTERNAL); + mScoAudioState = SCO_STATE_INACTIVE; + Log.i(TAG, "Audio-path brought-down"); } - // Tear down SCO if disconnected from external - clearAllScoClients(0, mScoAudioState == SCO_STATE_ACTIVE_INTERNAL); - mScoAudioState = SCO_STATE_INACTIVE; break; case BluetoothHeadset.STATE_AUDIO_CONNECTING: if (mScoAudioState != SCO_STATE_ACTIVE_INTERNAL && @@ -6862,6 +7098,8 @@ public class AudioService extends IAudioService.Stub break; } } + Log.i(TAG, "In onReceive(), mScoAudioState: " + mScoAudioState + + ", broadcast: " + broadcast); if (broadcast) { broadcastScoConnectionState(scoAudioState); //FIXME: this is to maintain compatibility with deprecated intent diff --git a/services/core/java/com/android/server/connectivity/Nat464Xlat.java b/services/core/java/com/android/server/connectivity/Nat464Xlat.java index 9d9b1cfdf6e2..03beb6a7ff6d 100644 --- a/services/core/java/com/android/server/connectivity/Nat464Xlat.java +++ b/services/core/java/com/android/server/connectivity/Nat464Xlat.java @@ -25,6 +25,7 @@ import android.net.NetworkInfo; import android.net.RouteInfo; import android.os.INetworkManagementService; import android.os.RemoteException; +import android.os.SystemProperties; import android.util.Slog; import com.android.internal.util.ArrayUtils; @@ -91,6 +92,7 @@ public class Nat464Xlat extends BaseNetworkObserver { */ public static boolean requiresClat(NetworkAgentInfo nai) { // TODO: migrate to NetworkCapabilities.TRANSPORT_*. + final int netType = nai.networkInfo.getType(); final boolean supported = ArrayUtils.contains(NETWORK_TYPES, nai.networkInfo.getType()); final boolean connected = ArrayUtils.contains(NETWORK_STATES, nai.networkInfo.getState()); // We only run clat on networks that don't have a native IPv4 address. diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java index 9ea73fbb1882..8ebca68f9efe 100644 --- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java +++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java @@ -16,6 +16,10 @@ package com.android.server.connectivity; +import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET; +import static android.net.NetworkCapabilities.NET_CAPABILITY_MMS; +import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED; + import android.content.Context; import android.net.INetd; import android.net.INetworkMonitor; @@ -592,7 +596,9 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> { } public void updateClat(INetworkManagementService netd) { - if (Nat464Xlat.requiresClat(this)) { + if (Nat464Xlat.requiresClat(this) && + ( this.networkCapabilities.hasCapability(NET_CAPABILITY_INTERNET) || + this.networkCapabilities.hasCapability(NET_CAPABILITY_MMS) )) { maybeStartClat(); } else { maybeStopClat(); diff --git a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java index 36a2476d2ceb..d9724ab4af38 100644 --- a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java +++ b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java @@ -26,6 +26,7 @@ import android.net.NetworkCapabilities; import android.net.wifi.WifiInfo; import android.os.UserHandle; import android.telephony.TelephonyManager; +import android.telephony.SubscriptionManager; import android.text.TextUtils; import android.util.Slog; import android.util.SparseArray; @@ -185,7 +186,8 @@ public class NetworkNotificationManager { title = r.getString(R.string.network_available_sign_in, 0); // TODO: Change this to pull from NetworkInfo once a printable // name has been added to it - details = mTelephonyManager.getNetworkOperatorName(); + details = mTelephonyManager.getNetworkOperatorName( + SubscriptionManager.getDefaultDataSubscriptionId()); break; default: title = r.getString(R.string.network_available_sign_in, 0); diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java index eb5be77e4a33..bb52cb8826f8 100644 --- a/services/core/java/com/android/server/connectivity/Tethering.java +++ b/services/core/java/com/android/server/connectivity/Tethering.java @@ -30,6 +30,8 @@ import static android.net.ConnectivityManager.TETHERING_BLUETOOTH; import static android.net.ConnectivityManager.TETHERING_INVALID; import static android.net.ConnectivityManager.TETHERING_USB; import static android.net.ConnectivityManager.TETHERING_WIFI; +import static android.net.ConnectivityManager.TETHERING_WIGIG; +import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; import static android.net.ConnectivityManager.TETHER_ERROR_MASTER_ERROR; import static android.net.ConnectivityManager.TETHER_ERROR_NO_ERROR; import static android.net.ConnectivityManager.TETHER_ERROR_SERVICE_UNAVAIL; @@ -84,6 +86,7 @@ import android.os.Message; import android.os.Parcel; import android.os.RemoteException; import android.os.ResultReceiver; +import android.os.SystemProperties; import android.os.UserHandle; import android.os.UserManager; import android.os.UserManagerInternal; @@ -290,7 +293,7 @@ public class Tethering extends BaseNetworkObserver { if (up) { maybeTrackNewInterfaceLocked(iface); } else { - if (ifaceNameToType(iface) == TETHERING_BLUETOOTH) { + if (ifaceNameToType(iface) == TETHERING_WIGIG) { stopTrackingInterfaceLocked(iface); } else { // Ignore usb0 down after enabling RNDIS. @@ -312,6 +315,10 @@ public class Tethering extends BaseNetworkObserver { final TetheringConfiguration cfg = mConfig; if (cfg.isWifi(iface)) { + String wigigIface = SystemProperties.get("vendor.wigig.interface", "wigig0"); + if (wigigIface.equals(iface)) { + return TETHERING_WIGIG; + } return TETHERING_WIFI; } else if (cfg.isUsb(iface)) { return TETHERING_USB; @@ -1112,7 +1119,8 @@ public class Tethering extends BaseNetworkObserver { addState(mSetDnsForwardersErrorState); mNotifyList = new ArrayList<>(); - mIPv6TetheringCoordinator = deps.getIPv6TetheringCoordinator(mNotifyList, mLog); + mIPv6TetheringCoordinator = deps.getIPv6TetheringCoordinator( + mNotifyList, mLog); mOffload = new OffloadWrapper(); setInitialState(mInitialState); diff --git a/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java b/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java index 1e6bb04858a1..9e2cdd40c547 100644 --- a/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java +++ b/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java @@ -36,6 +36,7 @@ import android.content.ContentResolver; import android.content.Context; import android.content.res.Resources; import android.net.ConnectivityManager; +import android.os.SystemProperties; import android.net.util.SharedLog; import android.provider.Settings; import android.telephony.TelephonyManager; @@ -107,7 +108,14 @@ public class TetheringConfiguration { // TODO: Evaluate deleting this altogether now that Wi-Fi always passes // us an interface name. Careful consideration needs to be given to // implications for Settings and for provisioning checks. - tetherableWifiRegexs = getResourceStringArray(ctx, config_tether_wifi_regexs); + if (SystemProperties.getInt("persist.vendor.fst.softap.en", 0) == 1) { + String defaultFstInterfaceName = "bond0"; + String fstInterfaceName = SystemProperties.get( + "persist.vendor.fst.data.interface", defaultFstInterfaceName); + tetherableWifiRegexs = new String[] { fstInterfaceName }; + } else { + tetherableWifiRegexs = getResourceStringArray(ctx, config_tether_wifi_regexs); + } tetherableBluetoothRegexs = getResourceStringArray(ctx, config_tether_bluetooth_regexs); dunCheck = checkDunRequired(ctx); diff --git a/services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java b/services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java index 3ac311b3e13a..3944f79d5427 100644 --- a/services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java +++ b/services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java @@ -453,7 +453,7 @@ public class UpstreamNetworkMonitor { public NetworkState ns = null; } - private static TypeStatePair findFirstAvailableUpstreamByType( + private TypeStatePair findFirstAvailableUpstreamByType( Iterable<NetworkState> netStates, Iterable<Integer> preferredTypes) { final TypeStatePair result = new TypeStatePair(); @@ -469,13 +469,22 @@ public class UpstreamNetworkMonitor { nc.setSingleUid(Process.myUid()); for (NetworkState value : netStates) { - if (!nc.satisfiedByNetworkCapabilities(value.networkCapabilities)) { + try { + // Check for both default Network and capabilities match. + // This avoids in picking the wrong interface(MOBILE) in + // STA+SAP scenarios where WIFI is preferred Network. + // In DUN tethering scenarios, check if the request type is + // DUN and capabilities match. + if ((type == TYPE_MOBILE_DUN || type == cm().getActiveNetworkInfo().getType()) + && (nc.satisfiedByNetworkCapabilities(value.networkCapabilities))) { + result.type = type; + result.ns = value; + return result; + } + } catch (NullPointerException npe) { + Log.e(TAG, "Null pointer exception in getActiveNetworkInfo", npe); continue; } - - result.type = type; - result.ns = value; - return result; } } diff --git a/services/core/java/com/android/server/display/DisplayDevice.java b/services/core/java/com/android/server/display/DisplayDevice.java index 6ee5665b9e42..a361c127527f 100644 --- a/services/core/java/com/android/server/display/DisplayDevice.java +++ b/services/core/java/com/android/server/display/DisplayDevice.java @@ -35,6 +35,7 @@ abstract class DisplayDevice { private final DisplayAdapter mDisplayAdapter; private final IBinder mDisplayToken; private final String mUniqueId; + private int mPhysicalId = -1; // The display device does not manage these properties itself, they are set by // the display manager service. The display device shouldn't really be looking at these. @@ -51,6 +52,12 @@ abstract class DisplayDevice { // Do not use for any other purpose. DisplayDeviceInfo mDebugLastLoggedDeviceInfo; + public DisplayDevice(DisplayAdapter displayAdapter, IBinder displayToken, String uniqueId, + int physicalId) { + this(displayAdapter, displayToken, uniqueId); + mPhysicalId = physicalId; + } + public DisplayDevice(DisplayAdapter displayAdapter, IBinder displayToken, String uniqueId) { mDisplayAdapter = displayAdapter; mDisplayToken = displayToken; @@ -86,6 +93,15 @@ abstract class DisplayDevice { } /** + * Gets the physical id (vendor specified) of the display device. + * + * @return The display device id. + */ + public final int getPhysicalId() { + return mPhysicalId; + } + + /** * Returns the unique id of the display device. */ public final String getUniqueId() { @@ -236,6 +252,7 @@ abstract class DisplayDevice { public void dumpLocked(PrintWriter pw) { pw.println("mAdapter=" + mDisplayAdapter.getName()); pw.println("mUniqueId=" + mUniqueId); + pw.println("mPhysicalId=" + mPhysicalId); pw.println("mDisplayToken=" + mDisplayToken); pw.println("mCurrentLayerStack=" + mCurrentLayerStack); pw.println("mCurrentOrientation=" + mCurrentOrientation); diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java index cb3f91b7b6bb..4d3e072cbfcf 100644 --- a/services/core/java/com/android/server/display/DisplayManagerService.java +++ b/services/core/java/com/android/server/display/DisplayManagerService.java @@ -212,6 +212,7 @@ public final class DisplayManagerService extends SystemService { private final SparseArray<LogicalDisplay> mLogicalDisplays = new SparseArray<LogicalDisplay>(); private int mNextNonDefaultDisplayId = Display.DEFAULT_DISPLAY + 1; + private int mNextBuiltInDisplayId = 4096; // List of all display transaction listeners. private final CopyOnWriteArrayList<DisplayTransactionListener> mDisplayTransactionListeners = @@ -983,7 +984,7 @@ public final class DisplayManagerService extends SystemService { return null; } - final int displayId = assignDisplayIdLocked(isDefault); + final int displayId = assignDisplayIdLocked(isDefault, device.getPhysicalId()); final int layerStack = assignLayerStackLocked(displayId); LogicalDisplay display = new LogicalDisplay(displayId, layerStack, device); @@ -1016,6 +1017,15 @@ public final class DisplayManagerService extends SystemService { return isDefault ? Display.DEFAULT_DISPLAY : mNextNonDefaultDisplayId++; } + private int assignDisplayIdLocked(boolean isDefault, int physicalId) { + if (physicalId >= SurfaceControl.BUILT_IN_DISPLAY_ID_EXT_MIN && + physicalId <= SurfaceControl.BUILT_IN_DISPLAY_ID_EXT_MAX) { + return mNextBuiltInDisplayId++; + } + + return assignDisplayIdLocked(isDefault); + } + private int assignLayerStackLocked(int displayId) { // Currently layer stacks and display ids are the same. // This need not be the case. diff --git a/services/core/java/com/android/server/display/ExtendedRemoteDisplayHelper.java b/services/core/java/com/android/server/display/ExtendedRemoteDisplayHelper.java new file mode 100644 index 000000000000..1be474b09ef2 --- /dev/null +++ b/services/core/java/com/android/server/display/ExtendedRemoteDisplayHelper.java @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2014, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.android.server.display; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import android.media.RemoteDisplay; +import android.os.Handler; +import android.util.Slog; +import android.content.Context; + +class ExtendedRemoteDisplayHelper { + private static final String TAG = "ExtendedRemoteDisplayHelper"; + + // ExtendedRemoteDisplay class + // ExtendedRemoteDisplay is an enhanced RemoteDisplay. It has + // similar interface as RemoteDisplay class + private static Class sExtRemoteDisplayClass; + + // Method object for the API ExtendedRemoteDisplay.Listen + // ExtendedRemoteDisplay.Listen has the same API signature as + // RemoteDisplay.Listen except for an additional argument to pass the + // Context + private static Method sExtRemoteDisplayListen; + + // Method Object for the API ExtendedRemoteDisplay.Dispose + // ExtendedRemoteDisplay.Dispose follows the same API signature as + // RemoteDisplay.Dispose + private static Method sExtRemoteDisplayDispose; + + static { + //Check availability of ExtendedRemoteDisplay runtime + try { + sExtRemoteDisplayClass = Class.forName("com.qualcomm.wfd.ExtendedRemoteDisplay"); + } catch (Throwable t) { + Slog.i(TAG, "ExtendedRemoteDisplay Not available."); + } + + if(sExtRemoteDisplayClass != null) { + // If ExtendedRemoteDisplay is available find the methods + Slog.i(TAG, "ExtendedRemoteDisplay Is available. Find Methods"); + try { + Class args[] = { + String.class, + RemoteDisplay.Listener.class, + Handler.class, Context.class + }; + sExtRemoteDisplayListen = sExtRemoteDisplayClass.getDeclaredMethod("listen", args); + } catch (Throwable t) { + Slog.i(TAG, "ExtendedRemoteDisplay.listen Not available."); + } + + try { + Class args[] = {}; + sExtRemoteDisplayDispose = sExtRemoteDisplayClass.getDeclaredMethod("dispose", args); + } catch (Throwable t) { + Slog.i(TAG, "ExtendedRemoteDisplay.dispose Not available."); + } + } + } + + /** + * Starts listening for displays to be connected on the specified interface. + * + * @param iface The interface address and port in the form "x.x.x.x:y". + * @param listener The listener to invoke + * when displays are connected or disconnected. + * @param handler The handler on which to invoke the listener. + * @param context The current service context + * */ + public static Object listen(String iface, RemoteDisplay.Listener listener, + Handler handler, Context context) + { + Object extRemoteDisplay = null; + Slog.i(TAG, "ExtendedRemoteDisplay.listen"); + + if(sExtRemoteDisplayListen != null && sExtRemoteDisplayDispose != null){ + try { + extRemoteDisplay = sExtRemoteDisplayListen.invoke(null, + iface, listener, handler, context); + } catch (InvocationTargetException e) { + Slog.i(TAG, "ExtendedRemoteDisplay.listen - InvocationTargetException"); + Throwable cause = e.getCause(); + if (cause instanceof RuntimeException) { + throw (RuntimeException) cause; + } else if (cause instanceof Error) { + throw (Error) cause; + } else { + throw new RuntimeException(e); + } + } catch (IllegalAccessException e) { + Slog.i(TAG, "ExtendedRemoteDisplay.listen -IllegalAccessException"); + e.printStackTrace(); + } + } + return extRemoteDisplay; + } + + /** + * Disconnects the remote display and stops listening for new connections. + */ + public static void dispose(Object extRemoteDisplay) { + Slog.i(TAG, "ExtendedRemoteDisplay.dispose"); + try{ + sExtRemoteDisplayDispose.invoke(extRemoteDisplay); + } catch (InvocationTargetException e) { + Slog.i(TAG, "ExtendedRemoteDisplay.dispose - InvocationTargetException"); + Throwable cause = e.getCause(); + if (cause instanceof RuntimeException) { + throw (RuntimeException) cause; + } else if (cause instanceof Error) { + throw (Error) cause; + } else { + throw new RuntimeException(e); + } + } catch (IllegalAccessException e) { + Slog.i(TAG, "ExtendedRemoteDisplay.dispose-IllegalAccessException"); + e.printStackTrace(); + } + } + + /** + * Checks if ExtendedRemoteDisplay is available + */ + public static boolean isAvailable() + { + if(sExtRemoteDisplayClass != null && + sExtRemoteDisplayDispose != null && + sExtRemoteDisplayListen != null) { + Slog.i(TAG, "ExtendedRemoteDisplay isAvailable() : Available."); + return true; + } + Slog.i(TAG, "ExtendedRemoteDisplay isAvailable() : Not Available."); + return false; + } +} diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java index 16d82df4dd5b..9360acf1ab59 100644 --- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java +++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java @@ -182,7 +182,8 @@ final class LocalDisplayAdapter extends DisplayAdapter { public LocalDisplayDevice(IBinder displayToken, int builtInDisplayId, SurfaceControl.PhysicalDisplayInfo[] physicalDisplayInfos, int activeDisplayInfo, int[] colorModes, int activeColorMode) { - super(LocalDisplayAdapter.this, displayToken, UNIQUE_ID_PREFIX + builtInDisplayId); + super(LocalDisplayAdapter.this, displayToken, UNIQUE_ID_PREFIX + builtInDisplayId, + builtInDisplayId); mBuiltInDisplayId = builtInDisplayId; updatePhysicalDisplayInfoLocked(physicalDisplayInfos, activeDisplayInfo, colorModes, activeColorMode); @@ -413,7 +414,8 @@ final class LocalDisplayAdapter extends DisplayAdapter { mInfo.xDpi = phys.xDpi; mInfo.yDpi = phys.yDpi; mInfo.touch = DisplayDeviceInfo.TOUCH_INTERNAL; - } else { + } else if (mBuiltInDisplayId >= SurfaceControl.BUILT_IN_DISPLAY_ID_HDMI && + mBuiltInDisplayId < SurfaceControl.BUILT_IN_DISPLAY_ID_EXT_MIN) { mInfo.displayCutout = null; mInfo.type = Display.TYPE_HDMI; mInfo.flags |= DisplayDeviceInfo.FLAG_PRESENTATION; @@ -442,6 +444,26 @@ final class LocalDisplayAdapter extends DisplayAdapter { if (res.getBoolean(com.android.internal.R.bool.config_localDisplaysPrivate)) { mInfo.flags |= DisplayDeviceInfo.FLAG_PRIVATE; } + } else { + mInfo.type = Display.TYPE_BUILT_IN; + mInfo.touch = DisplayDeviceInfo.TOUCH_INTERNAL; + mInfo.name = getContext().getResources().getString( + com.android.internal.R.string.display_manager_built_in_display_name); + mInfo.flags |= DisplayDeviceInfo.FLAG_ROTATES_WITH_CONTENT; + + if (SystemProperties.getBoolean( + "vendor.display.builtin_presentation", false)) { + mInfo.flags |= DisplayDeviceInfo.FLAG_PRESENTATION; + } else { + mInfo.flags |= DisplayDeviceInfo.FLAG_PRIVATE; + } + + if (!SystemProperties.getBoolean( + "vendor.display.builtin_mirroring", false)) { + mInfo.flags |= DisplayDeviceInfo.FLAG_OWN_CONTENT_ONLY; + } + + mInfo.setAssumedDensityForExternalDisplay(phys.width, phys.height); } } return mInfo; diff --git a/services/core/java/com/android/server/display/WifiDisplayController.java b/services/core/java/com/android/server/display/WifiDisplayController.java index fc59b5b0ffec..5ca97e77a87e 100644 --- a/services/core/java/com/android/server/display/WifiDisplayController.java +++ b/services/core/java/com/android/server/display/WifiDisplayController.java @@ -42,11 +42,14 @@ import android.net.wifi.p2p.WifiP2pManager.Channel; import android.net.wifi.p2p.WifiP2pManager.GroupInfoListener; import android.net.wifi.p2p.WifiP2pManager.PeerListListener; import android.os.Handler; +import android.os.SystemProperties; import android.provider.Settings; import android.util.Slog; import android.view.Surface; import java.io.PrintWriter; +import java.lang.StackTraceElement; +import java.lang.Thread; import java.net.Inet4Address; import java.net.InetAddress; import java.net.NetworkInterface; @@ -69,8 +72,10 @@ import java.util.Objects; */ final class WifiDisplayController implements DumpUtils.Dump { private static final String TAG = "WifiDisplayController"; - private static final boolean DEBUG = false; - + private static final boolean DEBUG = + SystemProperties.getBoolean("persist.vendor.debug.wfdcdbg",false); + private static final boolean DEBUGV = + SystemProperties.getBoolean("persist.vendor.debug.wfdcdbgv",false); private static final int DEFAULT_CONTROL_PORT = 7236; private static final int MAX_THROUGHPUT = 50; private static final int CONNECTION_TIMEOUT_SECONDS = 30; @@ -95,7 +100,7 @@ final class WifiDisplayController implements DumpUtils.Dump { private final Listener mListener; private final WifiP2pManager mWifiP2pManager; - private final Channel mWifiP2pChannel; + private Channel mWifiP2pChannel; private boolean mWifiP2pEnabled; private boolean mWfdEnabled; @@ -136,6 +141,10 @@ final class WifiDisplayController implements DumpUtils.Dump { // Number of connection retries remaining. private int mConnectionRetriesLeft; + // The Extended remote display that is listening on the connection. + // Created after the Wifi P2P network is connected. + private Object mExtRemoteDisplay; + // The remote display that is listening on the connection. // Created after the Wifi P2P network is connected. private RemoteDisplay mRemoteDisplay; @@ -165,7 +174,6 @@ final class WifiDisplayController implements DumpUtils.Dump { mListener = listener; mWifiP2pManager = (WifiP2pManager)context.getSystemService(Context.WIFI_P2P_SERVICE); - mWifiP2pChannel = mWifiP2pManager.initialize(context, handler.getLooper(), null); IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION); @@ -191,6 +199,16 @@ final class WifiDisplayController implements DumpUtils.Dump { updateSettings(); } + private Channel getWifiP2pChannel() { + if(mWifiP2pChannel == null) { + mWifiP2pChannel = mWifiP2pManager.initialize(mContext, mHandler.getLooper(), null); + if(DEBUG) { + Slog.d(TAG, "Creating WifiP2pChannel"); + } + } + return mWifiP2pChannel; + } + private void updateSettings() { final ContentResolver resolver = mContext.getContentResolver(); mWifiDisplayOnSetting = Settings.Global.getInt(resolver, @@ -237,6 +255,35 @@ final class WifiDisplayController implements DumpUtils.Dump { } } + private void dump() { + Slog.d(TAG,"mWifiDisplayOnSetting=" + mWifiDisplayOnSetting); + Slog.d(TAG,"mWifiP2pEnabled=" + mWifiP2pEnabled); + Slog.d(TAG,"mWfdEnabled=" + mWfdEnabled); + Slog.d(TAG,"mWfdEnabling=" + mWfdEnabling); + Slog.d(TAG,"mNetworkInfo=" + mNetworkInfo); + Slog.d(TAG,"mScanRequested=" + mScanRequested); + Slog.d(TAG,"mDiscoverPeersInProgress=" + mDiscoverPeersInProgress); + Slog.d(TAG,"mDesiredDevice=" + describeWifiP2pDevice(mDesiredDevice)); + Slog.d(TAG,"mConnectingDisplay=" + describeWifiP2pDevice(mConnectingDevice)); + Slog.d(TAG,"mDisconnectingDisplay=" + describeWifiP2pDevice(mDisconnectingDevice)); + Slog.d(TAG,"mCancelingDisplay=" + describeWifiP2pDevice(mCancelingDevice)); + Slog.d(TAG,"mConnectedDevice=" + describeWifiP2pDevice(mConnectedDevice)); + Slog.d(TAG,"mConnectionRetriesLeft=" + mConnectionRetriesLeft); + Slog.d(TAG,"mRemoteDisplay=" + mRemoteDisplay); + Slog.d(TAG,"mRemoteDisplayInterface=" + mRemoteDisplayInterface); + Slog.d(TAG,"mRemoteDisplayConnected=" + mRemoteDisplayConnected); + Slog.d(TAG,"mAdvertisedDisplay=" + mAdvertisedDisplay); + Slog.d(TAG,"mAdvertisedDisplaySurface=" + mAdvertisedDisplaySurface); + Slog.d(TAG,"mAdvertisedDisplayWidth=" + mAdvertisedDisplayWidth); + Slog.d(TAG,"mAdvertisedDisplayHeight=" + mAdvertisedDisplayHeight); + Slog.d(TAG,"mAdvertisedDisplayFlags=" + mAdvertisedDisplayFlags); + + Slog.d(TAG,"mAvailableWifiDisplayPeers: size=" + mAvailableWifiDisplayPeers.size()); + for (WifiP2pDevice device : mAvailableWifiDisplayPeers) { + Slog.d(TAG," " + describeWifiP2pDevice(device)); + } + } + public void requestStartScan() { if (!mScanRequested) { mScanRequested = true; @@ -287,7 +334,7 @@ final class WifiDisplayController implements DumpUtils.Dump { wfdInfo.setSessionAvailable(true); wfdInfo.setControlPort(DEFAULT_CONTROL_PORT); wfdInfo.setMaxThroughput(MAX_THROUGHPUT); - mWifiP2pManager.setWFDInfo(mWifiP2pChannel, wfdInfo, new ActionListener() { + mWifiP2pManager.setWFDInfo(getWifiP2pChannel(), wfdInfo, new ActionListener() { @Override public void onSuccess() { if (DEBUG) { @@ -315,7 +362,7 @@ final class WifiDisplayController implements DumpUtils.Dump { if (mWfdEnabled || mWfdEnabling) { WifiP2pWfdInfo wfdInfo = new WifiP2pWfdInfo(); wfdInfo.setWfdEnabled(false); - mWifiP2pManager.setWFDInfo(mWifiP2pChannel, wfdInfo, new ActionListener() { + mWifiP2pManager.setWFDInfo(getWifiP2pChannel(), wfdInfo, new ActionListener() { @Override public void onSuccess() { if (DEBUG) { @@ -358,7 +405,9 @@ final class WifiDisplayController implements DumpUtils.Dump { } private void updateScanState() { - if (mScanRequested && mWfdEnabled && mDesiredDevice == null) { + if (mScanRequested && mWfdEnabled && + (mDesiredDevice == null) && (mConnectedDevice == null) + && (mDisconnectingDevice == null)) { if (!mDiscoverPeersInProgress) { Slog.i(TAG, "Starting Wifi display scan."); mDiscoverPeersInProgress = true; @@ -384,7 +433,7 @@ final class WifiDisplayController implements DumpUtils.Dump { } private void tryDiscoverPeers() { - mWifiP2pManager.discoverPeers(mWifiP2pChannel, new ActionListener() { + mWifiP2pManager.discoverPeers(getWifiP2pChannel(), new ActionListener() { @Override public void onSuccess() { if (DEBUG) { @@ -412,7 +461,7 @@ final class WifiDisplayController implements DumpUtils.Dump { } private void stopPeerDiscovery() { - mWifiP2pManager.stopPeerDiscovery(mWifiP2pChannel, new ActionListener() { + mWifiP2pManager.stopPeerDiscovery(getWifiP2pChannel(), new ActionListener() { @Override public void onSuccess() { if (DEBUG) { @@ -430,7 +479,7 @@ final class WifiDisplayController implements DumpUtils.Dump { } private void requestPeers() { - mWifiP2pManager.requestPeers(mWifiP2pChannel, new PeerListListener() { + mWifiP2pManager.requestPeers(getWifiP2pChannel(), new PeerListListener() { @Override public void onPeersAvailable(WifiP2pDeviceList peers) { if (DEBUG) { @@ -534,6 +583,10 @@ final class WifiDisplayController implements DumpUtils.Dump { return; } + if (handlePreExistingConnection(device)) { + Slog.i(TAG, "already handle the preexisting p2p connection status"); + return; + } mDesiredDevice = device; mConnectionRetriesLeft = CONNECT_MAX_RETRIES; updateConnection(); @@ -558,20 +611,35 @@ final class WifiDisplayController implements DumpUtils.Dump { * connection is established (or not). */ private void updateConnection() { + if(DEBUGV) { + //new Throwable("WFD_DBG").printStackTrace(); + StackTraceElement[] st = Thread.currentThread().getStackTrace(); + for(int i = 2 ; i < st.length && i < 5; i++) { + Slog.i(TAG,st[i].toString()); + } + dump(); + } // Step 0. Stop scans if necessary to prevent interference while connected. // Resume scans later when no longer attempting to connect. updateScanState(); // Step 1. Before we try to connect to a new device, tell the system we // have disconnected from the old one. - if (mRemoteDisplay != null && mConnectedDevice != mDesiredDevice) { - Slog.i(TAG, "Stopped listening for RTSP connection on " + mRemoteDisplayInterface - + " from Wifi display: " + mConnectedDevice.deviceName); + if ((mRemoteDisplay != null || mExtRemoteDisplay != null) && + (mConnectedDevice != mDesiredDevice)|| + (mRemoteDisplayInterface != null && mConnectedDevice == null)) { + Slog.i(TAG, "Stopped listening for RTSP connection on " + + mRemoteDisplayInterface); + + if(mRemoteDisplay != null) { + mRemoteDisplay.dispose(); + } else if(mExtRemoteDisplay != null) { + ExtendedRemoteDisplayHelper.dispose(mExtRemoteDisplay); + } - mRemoteDisplay.dispose(); + mExtRemoteDisplay = null; mRemoteDisplay = null; mRemoteDisplayInterface = null; - mRemoteDisplayConnected = false; mHandler.removeCallbacks(mRtspTimeout); mWifiP2pManager.setMiracastMode(WifiP2pManager.MIRACAST_DISABLED); @@ -581,7 +649,7 @@ final class WifiDisplayController implements DumpUtils.Dump { } // Step 2. Before we try to connect to a new device, disconnect from the old one. - if (mDisconnectingDevice != null) { + if (mRemoteDisplayConnected || mDisconnectingDevice != null) { return; // wait for asynchronous callback } if (mConnectedDevice != null && mConnectedDevice != mDesiredDevice) { @@ -593,7 +661,7 @@ final class WifiDisplayController implements DumpUtils.Dump { unadvertiseDisplay(); final WifiP2pDevice oldDevice = mDisconnectingDevice; - mWifiP2pManager.removeGroup(mWifiP2pChannel, new ActionListener() { + mWifiP2pManager.removeGroup(getWifiP2pChannel(), new ActionListener() { @Override public void onSuccess() { Slog.i(TAG, "Disconnected from Wifi display: " + oldDevice.deviceName); @@ -631,7 +699,7 @@ final class WifiDisplayController implements DumpUtils.Dump { mHandler.removeCallbacks(mConnectionTimeout); final WifiP2pDevice oldDevice = mCancelingDevice; - mWifiP2pManager.cancelConnect(mWifiP2pChannel, new ActionListener() { + mWifiP2pManager.cancelConnect(getWifiP2pChannel(), new ActionListener() { @Override public void onSuccess() { Slog.i(TAG, "Canceled connection to Wifi display: " + oldDevice.deviceName); @@ -665,6 +733,51 @@ final class WifiDisplayController implements DumpUtils.Dump { return; // done } + //Before we connect, we need to set the oldDevice to the desiredDevice to check + //the device on receiving callbacks from the Remote display modules + final WifiP2pDevice oldDevice = mDesiredDevice; + RemoteDisplay.Listener listener = new RemoteDisplay.Listener() { + @Override + public void onDisplayConnected(Surface surface, + int width, int height, int flags, int session) { + if (mConnectedDevice == oldDevice && !mRemoteDisplayConnected) { + Slog.i(TAG, "Opened RTSP connection with Wifi display: " + + mConnectedDevice.deviceName); + mRemoteDisplayConnected = true; + mHandler.removeCallbacks(mRtspTimeout); + + if (mWifiDisplayCertMode) { + mListener.onDisplaySessionInfo( + getSessionInfo(mConnectedDeviceGroupInfo, session)); + } + + final WifiDisplay display = createWifiDisplay(mConnectedDevice); + advertiseDisplay(display, surface, width, height, flags); + } + } + + @Override + public void onDisplayDisconnected() { + if (mConnectedDevice == oldDevice) { + Slog.i(TAG, "Closed RTSP connection with Wifi display: " + + mConnectedDevice.deviceName); + mHandler.removeCallbacks(mRtspTimeout); + mRemoteDisplayConnected = false; + disconnect(); + } + } + + @Override + public void onDisplayError(int error) { + if (mConnectedDevice == oldDevice) { + Slog.i(TAG, "Lost RTSP connection with Wifi display due to error " + + error + ": " + mConnectedDevice.deviceName); + mHandler.removeCallbacks(mRtspTimeout); + handleConnectionFailure(false); + } + } + }; + // Step 5. Try to connect. if (mConnectedDevice == null && mConnectingDevice == null) { Slog.i(TAG, "Connecting to Wifi display: " + mDesiredDevice.deviceName); @@ -690,8 +803,21 @@ final class WifiDisplayController implements DumpUtils.Dump { WifiDisplay display = createWifiDisplay(mConnectingDevice); advertiseDisplay(display, null, 0, 0, 0); + if(ExtendedRemoteDisplayHelper.isAvailable()&& + mExtRemoteDisplay == null){ + final int port = getPortNumber(mDesiredDevice); + //IP is superfluous for WFD source, and we don't have one at this stage anyway since + //P2P connection hasn't been established yet + final String iface = "255.255.255.255:" + port; + mRemoteDisplayInterface = iface; + Slog.i(TAG, "Listening for RTSP connection on " + iface + + " from Wifi display: " + mDesiredDevice.deviceName); + mExtRemoteDisplay = ExtendedRemoteDisplayHelper.listen(iface, + listener, mHandler, mContext); + } + final WifiP2pDevice newDevice = mDesiredDevice; - mWifiP2pManager.connect(mWifiP2pChannel, config, new ActionListener() { + mWifiP2pManager.connect(getWifiP2pChannel(), config, new ActionListener() { @Override public void onSuccess() { // The connection may not yet be established. We still need to wait @@ -727,54 +853,16 @@ final class WifiDisplayController implements DumpUtils.Dump { mWifiP2pManager.setMiracastMode(WifiP2pManager.MIRACAST_SOURCE); - final WifiP2pDevice oldDevice = mConnectedDevice; final int port = getPortNumber(mConnectedDevice); final String iface = addr.getHostAddress() + ":" + port; mRemoteDisplayInterface = iface; - Slog.i(TAG, "Listening for RTSP connection on " + iface - + " from Wifi display: " + mConnectedDevice.deviceName); - - mRemoteDisplay = RemoteDisplay.listen(iface, new RemoteDisplay.Listener() { - @Override - public void onDisplayConnected(Surface surface, - int width, int height, int flags, int session) { - if (mConnectedDevice == oldDevice && !mRemoteDisplayConnected) { - Slog.i(TAG, "Opened RTSP connection with Wifi display: " - + mConnectedDevice.deviceName); - mRemoteDisplayConnected = true; - mHandler.removeCallbacks(mRtspTimeout); - - if (mWifiDisplayCertMode) { - mListener.onDisplaySessionInfo( - getSessionInfo(mConnectedDeviceGroupInfo, session)); - } - - final WifiDisplay display = createWifiDisplay(mConnectedDevice); - advertiseDisplay(display, surface, width, height, flags); - } - } - - @Override - public void onDisplayDisconnected() { - if (mConnectedDevice == oldDevice) { - Slog.i(TAG, "Closed RTSP connection with Wifi display: " - + mConnectedDevice.deviceName); - mHandler.removeCallbacks(mRtspTimeout); - disconnect(); - } - } - - @Override - public void onDisplayError(int error) { - if (mConnectedDevice == oldDevice) { - Slog.i(TAG, "Lost RTSP connection with Wifi display due to error " - + error + ": " + mConnectedDevice.deviceName); - mHandler.removeCallbacks(mRtspTimeout); - handleConnectionFailure(false); - } - } - }, mHandler, mContext.getOpPackageName()); + if(!ExtendedRemoteDisplayHelper.isAvailable()){ + Slog.i(TAG, "Listening for RTSP connection on " + iface + + " from Wifi display: " + mConnectedDevice.deviceName); + mRemoteDisplay = RemoteDisplay.listen(iface, listener, + mHandler, mContext.getOpPackageName()); + } // Use extended timeout value for certification, as some tests require user inputs int rtspTimeout = mWifiDisplayCertMode ? @@ -785,7 +873,7 @@ final class WifiDisplayController implements DumpUtils.Dump { } private WifiDisplaySessionInfo getSessionInfo(WifiP2pGroup info, int session) { - if (info == null) { + if (info == null || info.getOwner() == null) { return null; } Inet4Address addr = getInterfaceAddress(info); @@ -816,9 +904,13 @@ final class WifiDisplayController implements DumpUtils.Dump { mNetworkInfo = networkInfo; if (mWfdEnabled && networkInfo.isConnected()) { if (mDesiredDevice != null || mWifiDisplayCertMode) { - mWifiP2pManager.requestGroupInfo(mWifiP2pChannel, new GroupInfoListener() { + mWifiP2pManager.requestGroupInfo(getWifiP2pChannel(), new GroupInfoListener() { @Override public void onGroupInfoAvailable(WifiP2pGroup info) { + if(info == null) { + return; + } + if (DEBUG) { Slog.d(TAG, "Received group info: " + describeWifiP2pGroup(info)); } @@ -838,8 +930,9 @@ final class WifiDisplayController implements DumpUtils.Dump { } if (mWifiDisplayCertMode) { - boolean owner = info.getOwner().deviceAddress - .equals(mThisDevice.deviceAddress); + boolean owner = (info.getOwner() != null)? + info.getOwner().deviceAddress + .equals(mThisDevice.deviceAddress):false; if (owner && info.getClientList().isEmpty()) { // this is the case when we started Autonomous GO, // and no client has connected, save group info @@ -877,6 +970,12 @@ final class WifiDisplayController implements DumpUtils.Dump { disconnect(); } + if (mDesiredDevice != null) { + Slog.i(TAG, "reconnect new device: " + mDesiredDevice.deviceName); + updateConnection(); + return; + } + // After disconnection for a group, for some reason we have a tendency // to get a peer change notification with an empty list of peers. // Perform a fresh scan. @@ -909,7 +1008,8 @@ final class WifiDisplayController implements DumpUtils.Dump { @Override public void run() { if (mConnectedDevice != null - && mRemoteDisplay != null && !mRemoteDisplayConnected) { + && (mRemoteDisplay != null || mExtRemoteDisplay != null) + && !mRemoteDisplayConnected) { Slog.i(TAG, "Timed out waiting for Wifi display RTSP connection after " + RTSP_TIMEOUT_SECONDS + " seconds: " + mConnectedDevice.deviceName); @@ -993,6 +1093,41 @@ final class WifiDisplayController implements DumpUtils.Dump { mAdvertisedDisplayFlags); } + private boolean handlePreExistingConnection(final WifiP2pDevice device) { + if (mNetworkInfo == null || !mNetworkInfo.isConnected() || mWifiDisplayCertMode) { + return false; + } + Slog.i(TAG, "handle the preexisting p2p connection status"); + mWifiP2pManager.requestGroupInfo(getWifiP2pChannel(), new GroupInfoListener() { + @Override + public void onGroupInfoAvailable(WifiP2pGroup info) { + if (info == null) { + return; + } + if (info.contains(device)) { + Slog.i(TAG, "already connected to the desired device: " + device.deviceName); + updateConnection(); + handleConnectionChanged(mNetworkInfo); + } else { + mWifiP2pManager.removeGroup(getWifiP2pChannel(), new ActionListener() { + @Override + public void onSuccess() { + Slog.i(TAG, "disconnect the old device"); + } + + @Override + public void onFailure(int reason) { + Slog.i(TAG, "Failed to disconnect the old device: reason=" + reason); + } + }); + } + } + }); + mDesiredDevice = device; + mConnectionRetriesLeft = CONNECT_MAX_RETRIES; + return true; + } + private static Inet4Address getInterfaceAddress(WifiP2pGroup info) { NetworkInterface iface; try { diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java index d346ddcc5264..41e73a7f8e2b 100644 --- a/services/core/java/com/android/server/location/GnssLocationProvider.java +++ b/services/core/java/com/android/server/location/GnssLocationProvider.java @@ -38,6 +38,8 @@ import android.location.LocationListener; import android.location.LocationManager; import android.location.LocationProvider; import android.location.LocationRequest; +import android.net.Network; +import android.net.NetworkInfo; import android.os.AsyncTask; import android.os.BatteryStats; import android.os.Binder; @@ -2202,4 +2204,4 @@ public class GnssLocationProvider extends AbstractLocationProvider implements int lac, int cid); private native void native_agps_set_id(int type, String setid); -}
\ No newline at end of file +} diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java index 8734ceb614a9..81a3de68a99c 100644 --- a/services/core/java/com/android/server/locksettings/LockSettingsService.java +++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java @@ -165,6 +165,7 @@ public class LockSettingsService extends ILockSettings.Stub { // Order of holding lock: mSeparateChallengeLock -> mSpManager -> this // Do not call into ActivityManager while holding mSpManager lock. private final Object mSeparateChallengeLock = new Object(); + private static final String DEFAULT_PASSWORD = "default_password"; private final DeviceProvisionedObserver mDeviceProvisionedObserver = new DeviceProvisionedObserver(); @@ -185,6 +186,7 @@ public class LockSettingsService extends ILockSettings.Stub { private final SyntheticPasswordManager mSpManager; private final KeyStore mKeyStore; + private static String mSavePassword = DEFAULT_PASSWORD; private final RecoverableKeyStoreManager mRecoverableKeyStoreManager; @@ -1098,6 +1100,45 @@ public class LockSettingsService extends ILockSettings.Stub { return mStorage.hasCredential(userId); } + public void retainPassword(String password) { + if (LockPatternUtils.isDeviceEncryptionEnabled()) { + if (password != null) + mSavePassword = password; + else + mSavePassword = DEFAULT_PASSWORD; + } + } + + public void sanitizePassword() { + if (LockPatternUtils.isDeviceEncryptionEnabled()) { + mSavePassword = DEFAULT_PASSWORD; + } + } + + private boolean checkCryptKeeperPermissions() { + boolean permission_err = false; + try { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.CRYPT_KEEPER, + "no permission to get the password"); + } catch (SecurityException e) { + permission_err = true; + } + return permission_err; + } + + public String getPassword() { + /** if calling process does't have crypt keeper or admin permissions, + * throw the exception. + */ + if (checkCryptKeeperPermissions()) + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.MANAGE_DEVICE_ADMINS, + "no crypt_keeper or admin permission to get the password"); + + return mSavePassword; + } + private void setKeystorePassword(String password, int userHandle) { final KeyStore ks = KeyStore.getInstance(); ks.onUserPasswordChanged(userHandle, password); @@ -1524,6 +1565,18 @@ public class LockSettingsService extends ILockSettings.Stub { addUserKeyAuth(userId, null, null); } + private void clearUserKeyAuth(int userId, byte[] token, byte[] secret) throws RemoteException { + if (DEBUG) Slog.d(TAG, "clearUserKeyProtection user=" + userId); + final UserInfo userInfo = mUserManager.getUserInfo(userId); + final IStorageManager storageManager = mInjector.getStorageManager(); + final long callingId = Binder.clearCallingIdentity(); + try { + storageManager.clearUserKeyAuth(userId, userInfo.serialNumber, token, secret); + } finally { + Binder.restoreCallingIdentity(callingId); + } + } + private static byte[] secretFromCredential(String credential) throws RemoteException { try { MessageDigest digest = MessageDigest.getInstance("SHA-512"); @@ -1612,7 +1665,13 @@ public class LockSettingsService extends ILockSettings.Stub { public VerifyCredentialResponse checkCredential(String credential, int type, int userId, ICheckCredentialProgressCallback progressCallback) throws RemoteException { checkPasswordReadPermission(userId); - return doVerifyCredential(credential, type, false, 0, userId, progressCallback); + VerifyCredentialResponse response = doVerifyCredential(credential, type, + false, 0, userId, progressCallback); + if ((response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) && + (userId == UserHandle.USER_OWNER)) { + retainPassword(credential); + } + return response; } @Override @@ -2475,7 +2534,7 @@ public class LockSettingsService extends ILockSettings.Stub { getGateKeeperService().clearSecureUserId(userId); // Clear key from vold so ActivityManager can just unlock the user with empty secret // during boot. - clearUserKeyProtection(userId); + clearUserKeyAuth(userId, null, auth.deriveDiskEncryptionKey()); fixateNewestUserKeyAuth(userId); setKeystorePassword(null, userId); } diff --git a/services/core/java/com/android/server/om/OverlayManagerSettings.java b/services/core/java/com/android/server/om/OverlayManagerSettings.java index 2b4ec03b98fd..2b4ec03b98fd 100644..100755 --- a/services/core/java/com/android/server/om/OverlayManagerSettings.java +++ b/services/core/java/com/android/server/om/OverlayManagerSettings.java diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java index bf4e272d4004..72b0e7095742 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerService.java +++ b/services/core/java/com/android/server/pm/PackageInstallerService.java @@ -430,6 +430,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements private int createSessionInternal(SessionParams params, String installerPackageName, int userId) throws IOException { + android.util.SeempLog.record(90); final int callingUid = Binder.getCallingUid(); mPermissionManager.enforceCrossUserPermission( callingUid, userId, true, true, "createSession"); diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 09fe26d19019..5a06d6590232 100644..100755 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -274,6 +274,7 @@ import android.util.TimingsTraceLog; import android.util.Xml; import android.util.jar.StrictJarFile; import android.util.proto.ProtoOutputStream; +import android.util.BoostFramework; import android.view.Display; import com.android.internal.R; @@ -1340,6 +1341,7 @@ public class PackageManagerService extends IPackageManager.Stub | FLAG_PERMISSION_REVOKE_ON_UPGRADE; final @Nullable String mRequiredVerifierPackage; + final @Nullable String mOptionalVerifierPackage; final @NonNull String mRequiredInstallerPackage; final @NonNull String mRequiredUninstallerPackage; final String mRequiredPermissionControllerPackage; @@ -3029,6 +3031,7 @@ public class PackageManagerService extends IPackageManager.Stub if (!mOnlyCore) { mRequiredVerifierPackage = getRequiredButNotReallyRequiredVerifierLPr(); + mOptionalVerifierPackage = getOptionalVerifierLPr(); mRequiredInstallerPackage = getRequiredInstallerLPr(); mRequiredUninstallerPackage = getRequiredUninstallerLPr(); mIntentFilterVerifierComponent = getIntentFilterVerifierComponentNameLPr(); @@ -3047,6 +3050,7 @@ public class PackageManagerService extends IPackageManager.Stub mRequiredPermissionControllerPackage = getRequiredPermissionControllerLPr(); } else { mRequiredVerifierPackage = null; + mOptionalVerifierPackage = null; mRequiredInstallerPackage = null; mRequiredUninstallerPackage = null; mIntentFilterVerifierComponent = null; @@ -3372,6 +3376,14 @@ public class PackageManagerService extends IPackageManager.Stub UserHandle.USER_SYSTEM, false /*allowDynamicSplits*/); if (matches.size() == 1) { return matches.get(0).getComponentInfo().packageName; + } else if (matches.size() > 1) { + String optionalVerifierName = mContext.getResources().getString(R.string.config_optionalPackageVerifierName); + if (TextUtils.isEmpty(optionalVerifierName)) + return matches.get(0).getComponentInfo().packageName; + for (int i = 0; i < matches.size(); i++) { + if (!matches.get(i).getComponentInfo().packageName.contains(optionalVerifierName)) + return matches.get(i).getComponentInfo().packageName; + } } else if (matches.size() == 0) { Log.e(TAG, "There should probably be a verifier, but, none were found"); return null; @@ -3379,6 +3391,25 @@ public class PackageManagerService extends IPackageManager.Stub throw new RuntimeException("There must be exactly one verifier; found " + matches); } + private @Nullable String getOptionalVerifierLPr() { + final Intent intent = new Intent("com.qualcomm.qti.intent.action.PACKAGE_NEEDS_OPTIONAL_VERIFICATION"); + + final List<ResolveInfo> matches = queryIntentReceiversInternal(intent, PACKAGE_MIME_TYPE, + MATCH_SYSTEM_ONLY | MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE, + UserHandle.USER_SYSTEM, false /*allowDynamicSplits*/); + if (matches.size() >= 1) { + String optionalVerifierName = mContext.getResources().getString(R.string.config_optionalPackageVerifierName); + if (TextUtils.isEmpty(optionalVerifierName)) + return null; + for (int i = 0; i < matches.size(); i++) { + if (matches.get(i).getComponentInfo().packageName.contains(optionalVerifierName)) { + return matches.get(i).getComponentInfo().packageName; + } + } + } + return null; + } + private @NonNull String getRequiredSharedLibraryLPr(String name, int version) { synchronized (mPackages) { SharedLibraryInfo libraryInfo = getSharedLibraryInfoLPr(name, version); @@ -14424,9 +14455,14 @@ public class PackageManagerService extends IPackageManager.Stub final int requiredUid = mRequiredVerifierPackage == null ? -1 : getPackageUid(mRequiredVerifierPackage, MATCH_DEBUG_TRIAGED_MISSING, verifierUser.getIdentifier()); + + final int optionalUid = mOptionalVerifierPackage == null ? -1 + : getPackageUid(mOptionalVerifierPackage, MATCH_DEBUG_TRIAGED_MISSING, + verifierUser.getIdentifier()); + final int installerUid = verificationInfo == null ? -1 : verificationInfo.installerUid; - if (!origin.existing && requiredUid != -1 + if (!origin.existing && (requiredUid != -1 || optionalUid != -1) && isVerificationEnabled( verifierUser.getIdentifier(), installFlags, installerUid)) { final Intent verification = new Intent( @@ -14519,10 +14555,39 @@ public class PackageManagerService extends IPackageManager.Stub } } - final ComponentName requiredVerifierComponent = matchComponentForVerifier( - mRequiredVerifierPackage, receivers); + if (mOptionalVerifierPackage != null) { + final Intent optionalIntent = new Intent(verification); + optionalIntent.setAction("com.qualcomm.qti.intent.action.PACKAGE_NEEDS_OPTIONAL_VERIFICATION"); + final List<ResolveInfo> optional_receivers = queryIntentReceiversInternal(optionalIntent, + PACKAGE_MIME_TYPE, 0, verifierUser.getIdentifier(), false /*allowDynamicSplits*/); + final ComponentName optionalVerifierComponent = matchComponentForVerifier( + mOptionalVerifierPackage, optional_receivers); + optionalIntent.setComponent(optionalVerifierComponent); + verificationState.addOptionalVerifier(optionalUid); + if (mRequiredVerifierPackage != null) { + mContext.sendBroadcastAsUser(optionalIntent, verifierUser, android.Manifest.permission.PACKAGE_VERIFICATION_AGENT); + } else { + mContext.sendOrderedBroadcastAsUser(optionalIntent, verifierUser, android.Manifest.permission.PACKAGE_VERIFICATION_AGENT, + new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + final Message msg = mHandler.obtainMessage(CHECK_PENDING_VERIFICATION); + msg.arg1 = verificationId; + mHandler.sendMessageDelayed(msg, getVerificationTimeout()); + } + }, null, 0, null, null); + + /* + * We don't want the copy to proceed until + * verification succeeds. + */ + mVerificationCompleted = false; + } + } if (ret == PackageManager.INSTALL_SUCCEEDED && mRequiredVerifierPackage != null) { + final ComponentName requiredVerifierComponent = matchComponentForVerifier( + mRequiredVerifierPackage, receivers); Trace.asyncTraceBegin( TRACE_TAG_PACKAGE_MANAGER, "verification", verificationId); /* @@ -15289,6 +15354,8 @@ public class PackageManagerService extends IPackageManager.Stub final String pkgName = pkg.packageName; if (DEBUG_INSTALL) Slog.d(TAG, "New package installed in " + pkg.codePath); + if (pkgName != null) + acquireUxPerfLock(BoostFramework.UXE_EVENT_PKG_INSTALL, pkgName, 0); synchronized (mPackages) { // NOTE: This changes slightly to include UPDATE_PERMISSIONS_ALL regardless of the size of pkg.permissions mPermissionManager.updatePermissions(pkg.packageName, pkg, true, mPackages.values(), @@ -16461,6 +16528,7 @@ public class PackageManagerService extends IPackageManager.Stub // on the device; we should replace it. replace = true; if (DEBUG_INSTALL) Slog.d(TAG, "Replace existing pacakge: " + pkgName); + acquireUxPerfLock(BoostFramework.UXE_EVENT_PKG_INSTALL, pkgName, 1); } // Child packages are installed through the parent package @@ -17705,9 +17773,19 @@ public class PackageManagerService extends IPackageManager.Stub } } + if (res && packageName != null) { + acquireUxPerfLock(BoostFramework.UXE_EVENT_PKG_UNINSTALL, packageName, userId); + } return res ? PackageManager.DELETE_SUCCEEDED : PackageManager.DELETE_FAILED_INTERNAL_ERROR; } + private void acquireUxPerfLock(int opcode, String pkgName, int dat) { + BoostFramework ux_perf = new BoostFramework(); + if (ux_perf != null) { + ux_perf.perfUXEngine_events(opcode, 0, pkgName, dat); + } + } + static class PackageRemovedInfo { final PackageSender packageSender; String removedPackage; diff --git a/services/core/java/com/android/server/pm/PackageVerificationState.java b/services/core/java/com/android/server/pm/PackageVerificationState.java index c50bf59f0206..673ee8fca00d 100644 --- a/services/core/java/com/android/server/pm/PackageVerificationState.java +++ b/services/core/java/com/android/server/pm/PackageVerificationState.java @@ -43,6 +43,14 @@ class PackageVerificationState { private boolean mRequiredVerificationPassed; + private int mOptionalVerifierUid; + + private boolean mHasOptionalVerifier; + + private boolean mOptionalVerificationComplete; + + private boolean mOptionalVerificationPassed; + private boolean mExtendedTimeout; /** @@ -73,6 +81,11 @@ class PackageVerificationState { mSufficientVerifierUids.put(uid, true); } + public void addOptionalVerifier(int uid) { + mOptionalVerifierUid = uid; + mHasOptionalVerifier = true; + } + /** * Should be called when a verification is received from an agent so the * state of the package verification can be tracked. @@ -94,6 +107,16 @@ class PackageVerificationState { mRequiredVerificationPassed = false; } return true; + } else if (mHasOptionalVerifier && uid == mOptionalVerifierUid) { + mOptionalVerificationComplete = true; + switch (code) { + case PackageManager.VERIFICATION_ALLOW: + mOptionalVerificationPassed = true; + break; + default: + mOptionalVerificationPassed = false; + } + return true; } else { if (mSufficientVerifierUids.get(uid)) { if (code == PackageManager.VERIFICATION_ALLOW) { @@ -121,7 +144,11 @@ class PackageVerificationState { * @return {@code true} when verification is considered complete */ boolean isVerificationComplete() { - if (!mRequiredVerificationComplete) { + if (mRequiredVerifierUid != -1 && !mRequiredVerificationComplete) { + return false; + } + + if (mHasOptionalVerifier && !mOptionalVerificationComplete) { return false; } @@ -139,7 +166,11 @@ class PackageVerificationState { * @return {@code true} if installation should be allowed */ boolean isInstallAllowed() { - if (!mRequiredVerificationPassed) { + if (mRequiredVerifierUid != -1 && !mRequiredVerificationPassed) { + return false; + } + + if (mHasOptionalVerifier && !mOptionalVerificationPassed) { return false; } diff --git a/services/core/java/com/android/server/power/ShutdownThread.java b/services/core/java/com/android/server/power/ShutdownThread.java index 0a6b38fb2e9a..fa4c4568de45 100644 --- a/services/core/java/com/android/server/power/ShutdownThread.java +++ b/services/core/java/com/android/server/power/ShutdownThread.java @@ -73,6 +73,12 @@ public final class ShutdownThread extends Thread { private static final int PACKAGE_MANAGER_STOP_PERCENT = 6; private static final int RADIO_STOP_PERCENT = 18; private static final int MOUNT_SERVICE_STOP_PERCENT = 20; + // Time we should wait for vendor subsystem shutdown + // Sleep times(ms) between checks of the vendor subsystem state + private static final int VENDOR_SUBSYS_STATE_CHECK_INTERVAL_MS = 100; + // Max time we wait for vendor subsystems to shut down before resuming + // with full system shutdown + private static final int VENDOR_SUBSYS_MAX_WAIT_MS = 10000; // length of vibration before shutting down private static final int SHUTDOWN_VIBRATE_MS = 500; @@ -655,6 +661,59 @@ public final class ShutdownThread extends Thread { * @param reason reason for reboot/shutdown */ public static void rebootOrShutdown(final Context context, boolean reboot, String reason) { + String subsysProp; + subsysProp = SystemProperties.get("vendor.peripheral.shutdown_critical_list", + "ERROR"); + //If we don't have the shutdown critical subsystem list we can't + //really do anything. Proceed with full system shutdown. + if (!subsysProp.equals("ERROR")) { + Log.i(TAG, "Shutdown critical subsyslist is :"+subsysProp+": "); + Log.i(TAG, "Waiting for a maximum of " + + (VENDOR_SUBSYS_MAX_WAIT_MS) + "ms"); + String[] subsysList = subsysProp.split(" "); + int wait_count = 0; + boolean okToShutdown = true; + String subsysState; + int subsysListLength = subsysList.length; + do { + okToShutdown = true; + for (int i = 0; i < subsysListLength; i++) { + subsysState = + SystemProperties.get( + "vendor.peripheral." + + subsysList[i] + + ".state", + "ERROR"); + if(subsysState.equals("ONLINE")) { + //We only want to delay shutdown while + //one of the shutdown critical + //subsystems still shows as 'ONLINE'. + okToShutdown = false; + } + } + if (okToShutdown == false) { + SystemClock.sleep(VENDOR_SUBSYS_STATE_CHECK_INTERVAL_MS); + wait_count++; + } + } while (okToShutdown != true && + wait_count < (VENDOR_SUBSYS_MAX_WAIT_MS/VENDOR_SUBSYS_STATE_CHECK_INTERVAL_MS)); + if (okToShutdown != true) { + for (int i = 0; i < subsysList.length; i++) { + subsysState = + SystemProperties.get( + "vendor.peripheral." + + subsysList[i] + + ".state", + "ERROR"); + if(subsysState.equals("ONLINE")) { + Log.w(TAG, "Subsystem " + subsysList[i]+ + "did not shut down within timeout"); + } + } + } else { + Log.i(TAG, "Vendor subsystem(s) shutdown successful"); + } + } if (reboot) { Log.i(TAG, "Rebooting, reason: " + reason); PowerManagerService.lowLevelReboot(reason); diff --git a/services/core/java/com/android/server/wm/ActivityDisplay.java b/services/core/java/com/android/server/wm/ActivityDisplay.java index e817dd47e756..919ef8163c21 100644 --- a/services/core/java/com/android/server/wm/ActivityDisplay.java +++ b/services/core/java/com/android/server/wm/ActivityDisplay.java @@ -40,6 +40,8 @@ import static com.android.server.am.ActivityDisplayProto.RESUMED_ACTIVITY; import static com.android.server.am.ActivityDisplayProto.SINGLE_TASK_INSTANCE; import static com.android.server.am.ActivityDisplayProto.STACKS; import static com.android.server.wm.ActivityStack.ActivityState.RESUMED; +import static com.android.server.wm.ActivityStack.ActivityState.DESTROYED; +import static com.android.server.wm.ActivityStack.ActivityState.STOPPED; import static com.android.server.wm.ActivityStackSupervisor.TAG_TASKS; import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STACK; import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STATES; @@ -64,6 +66,7 @@ import android.util.IntArray; import android.util.Slog; import android.util.proto.ProtoOutputStream; import android.view.Display; +import android.util.BoostFramework; import com.android.internal.annotations.VisibleForTesting; import com.android.server.am.EventLogTags; @@ -83,6 +86,11 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> static final int POSITION_TOP = Integer.MAX_VALUE; static final int POSITION_BOTTOM = Integer.MIN_VALUE; + public static boolean mPerfSendTapHint = false; + public static boolean mIsPerfBoostAcquired = false; + public static int mPerfHandle = -1; + public BoostFramework mPerfBoost = null; + public BoostFramework mUxPerf = null; /** * Counter for next free stack ID to use for dynamic activity stacks. Unique across displays. @@ -585,6 +593,37 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> return someActivityPaused; } + void acquireAppLaunchPerfLock(ActivityRecord r) { + /* Acquire perf lock during new app launch */ + if (mPerfBoost == null) { + mPerfBoost = new BoostFramework(); + } + if (mPerfBoost != null) { + mPerfBoost.perfHint(BoostFramework.VENDOR_HINT_FIRST_LAUNCH_BOOST, r.packageName, -1, BoostFramework.Launch.BOOST_V1); + mPerfSendTapHint = true; + mPerfBoost.perfHint(BoostFramework.VENDOR_HINT_FIRST_LAUNCH_BOOST, r.packageName, -1, BoostFramework.Launch.BOOST_V2); + + if(mPerfBoost.perfGetFeedback(BoostFramework.VENDOR_FEEDBACK_WORKLOAD_TYPE, r.packageName) == BoostFramework.WorkloadType.GAME) + { + mPerfHandle = mPerfBoost.perfHint(BoostFramework.VENDOR_HINT_FIRST_LAUNCH_BOOST, r.packageName, -1, BoostFramework.Launch.BOOST_GAME); + } else { + mPerfHandle = mPerfBoost.perfHint(BoostFramework.VENDOR_HINT_FIRST_LAUNCH_BOOST, r.packageName, -1, BoostFramework.Launch.BOOST_V3); + } + if (mPerfHandle > 0) + mIsPerfBoostAcquired = true; + // Start IOP + mPerfBoost.perfIOPrefetchStart(-1,r.packageName, + r.appInfo.sourceDir.substring(0, r.appInfo.sourceDir.lastIndexOf('/'))); + } + } + + void acquireUxPerfLock(int opcode, String packageName) { + mUxPerf = new BoostFramework(); + if (mUxPerf != null) { + mUxPerf.perfUXEngine_events(opcode, 0, packageName, 0); + } + } + /** * Find task for putting the Activity in. */ @@ -608,6 +647,15 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> // matches not on the specified display. if (mTmpFindTaskResult.mRecord != null) { if (mTmpFindTaskResult.mIdealMatch) { + if(mTmpFindTaskResult.mRecord.getState() == DESTROYED) { + /*It's a new app launch */ + acquireAppLaunchPerfLock(r); + } + + if(mTmpFindTaskResult.mRecord.getState() == STOPPED) { + /*Warm launch */ + acquireUxPerfLock(BoostFramework.UXE_EVENT_SUB_LAUNCH, r.packageName); + } result.setTo(mTmpFindTaskResult); return; } else if (isPreferredDisplay) { @@ -618,6 +666,11 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> } } } + + /* Acquire perf lock *only* during new app launch */ + if ((mTmpFindTaskResult.mRecord == null) || (mTmpFindTaskResult.mRecord.getState() == DESTROYED)) { + acquireAppLaunchPerfLock(r); + } } /** diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java index 102318262798..e022ed30f24f 100644 --- a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java +++ b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java @@ -96,6 +96,7 @@ import android.os.Looper; import android.os.Message; import android.os.SystemClock; import android.os.Trace; +import android.util.BoostFramework; import android.util.EventLog; import android.util.Log; import android.util.Slog; @@ -170,6 +171,9 @@ class ActivityMetricsLogger { private ArtManagerInternal mArtManagerInternal; private final StringBuilder mStringBuilder = new StringBuilder(); + public static BoostFramework mPerfFirstDraw = null; + private static ActivityRecord mLaunchedActivity; + /** * Due to the global single concurrent launch sequence, all calls to this observer must be made * in-order on the same thread to fulfill the "happens-before" guarantee in LaunchObserver. @@ -663,6 +667,8 @@ class ActivityMetricsLogger { return; } + mLaunchedActivity = info.launchedActivity; + // Take a snapshot of the transition info before sending it to the handler for logging. // This will avoid any races with other operations that modify the ActivityRecord. final WindowingModeTransitionInfoSnapshot infoSnapshot = @@ -765,7 +771,30 @@ class ActivityMetricsLogger { sb.append(info.launchedActivityShortComponentName); sb.append(": "); TimeUtils.formatDuration(info.windowsDrawnDelayMs, sb); + + if (mLaunchedActivity.mUxPerf != null) { + mLaunchedActivity.mUxPerf.perfUXEngine_events(BoostFramework.UXE_EVENT_DISPLAYED_ACT, 0, info.packageName, info.windowsDrawnDelayMs); + } + Log.i(TAG, sb.toString()); + + int isGame = mLaunchedActivity.isAppInfoGame(); + if (mLaunchedActivity.mUxPerf != null) { + mLaunchedActivity.mUxPerf.perfUXEngine_events(BoostFramework.UXE_EVENT_GAME, 0, info.packageName, isGame); + } + + if (mPerfFirstDraw == null) { + mPerfFirstDraw = new BoostFramework(); + } + + if (mPerfFirstDraw != null) { + mPerfFirstDraw.perfHint(BoostFramework.VENDOR_HINT_FIRST_DRAW, info.packageName, info.windowsDrawnDelayMs, BoostFramework.Draw.EVENT_TYPE_V1); + } + + if (mLaunchedActivity.mPerf != null && mLaunchedActivity.perfActivityBoostHandler > 0) { + mLaunchedActivity.mPerf.perfLockReleaseHandler(mLaunchedActivity.perfActivityBoostHandler); + mLaunchedActivity.perfActivityBoostHandler = -1; + } } private int convertAppStartTransitionType(int tronType) { diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 6213fa02cb9f..1d7acb467640 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -185,6 +185,7 @@ import android.os.SystemClock; import android.os.UserHandle; import android.os.storage.StorageManager; import android.service.voice.IVoiceInteractionSession; +import android.util.BoostFramework; import android.util.EventLog; import android.util.Log; import android.util.MergedConfiguration; @@ -224,10 +225,12 @@ import java.util.HashSet; import java.util.List; import java.util.Objects; +import android.os.AsyncTask; + /** * An entry in the history stack, representing an activity. */ -final class ActivityRecord extends ConfigurationContainer { +public final class ActivityRecord extends ConfigurationContainer { private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityRecord" : TAG_ATM; private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION; private static final String TAG_SAVED_STATE = TAG + POSTFIX_SAVED_STATE; @@ -266,7 +269,7 @@ final class ActivityRecord extends ConfigurationContainer { final ComponentName mActivityComponent; // the intent component, or target of an alias. final String shortComponentName; // the short component name of the intent final String resolvedType; // as per original caller; - final String packageName; // the package implementing intent's component + public final String packageName; // the package implementing intent's component final String processName; // process where this component wants to run final String taskAffinity; // as per ActivityInfo.taskAffinity final boolean stateNotNeeded; // As per ActivityInfo.flags @@ -287,6 +290,7 @@ final class ActivityRecord extends ConfigurationContainer { private int theme; // resource identifier of activity's theme. private int realTheme; // actual theme resource we will use, never 0. private int windowFlags; // custom window flags for preview window. + public int perfActivityBoostHandler = -1; //perflock handler when activity is created. private TaskRecord task; // the task this is in. private long createTime = System.currentTimeMillis(); long lastVisibleTime; // last time this activity became visible @@ -334,6 +338,7 @@ final class ActivityRecord extends ConfigurationContainer { private boolean mDeferHidingClient; // If true we told WM to defer reporting to the client // process that it is hidden. boolean sleeping; // have we told the activity to sleep? + public boolean launching; // is activity launch in progress? boolean nowVisible; // is this activity's window visible? boolean mDrawn; // is this activity's window drawn? boolean mClientVisibilityDeferred;// was the visibility change message to client deferred? @@ -381,6 +386,10 @@ final class ActivityRecord extends ConfigurationContainer { boolean pendingVoiceInteractionStart; // Waiting for activity-invoked voice session IVoiceInteractionSession voiceSession; // Voice interaction session for this activity + public BoostFramework mPerf = null; + public BoostFramework mUxPerf = new BoostFramework(); + public BoostFramework mPerf_iop = null; + // A hint to override the window specified rotation animation, or -1 // to use the window specified value. We use this so that // we can select the right animation in the cases of starting @@ -833,6 +842,30 @@ final class ActivityRecord extends ConfigurationContainer { mAppWindowToken.setWillCloseOrEnterPip(willCloseOrEnterPip); } + private class PreferredAppsTask extends AsyncTask<Void, Void, Void> { + @Override + protected Void doInBackground(Void... params) { + String res = null; + if (mUxPerf != null) { + res = mUxPerf.perfUXEngine_trigger(BoostFramework.UXE_TRIGGER); + if (res == null) + return null; + String[] p_apps = res.split("/"); + if (p_apps.length != 0) { + ArrayList<String> apps_l = new ArrayList(Arrays.asList(p_apps)); + Bundle bParams = new Bundle(); + if (bParams == null) + return null; + bParams.putStringArrayList("start_empty_apps", apps_l); + // TODO(b/120845511) + // service.mAm.startActivityAsUserEmpty(null, null, intent, null, + // null, null, 0, 0, null, bParams, 0); + } + } + return null; + } + } + static class Token extends IApplicationToken.Stub { private final WeakReference<ActivityRecord> weakActivity; private final String name; @@ -1035,6 +1068,9 @@ final class ActivityRecord extends ConfigurationContainer { // Gets launch display id from options. It returns INVALID_DISPLAY if not set. mHandoverLaunchDisplayId = options.getLaunchDisplayId(); } + + if (mPerf == null) + mPerf = new BoostFramework(); } void setProcess(WindowProcessController proc) { @@ -2085,8 +2121,13 @@ final class ActivityRecord extends ConfigurationContainer { if (isActivityTypeHome()) { mStackSupervisor.updateHomeProcess(task.mActivities.get(0).app); + // TODO(b/120845511) + // try { + // new PreferredAppsTask().execute(); + // } catch (Exception e) { + // Log.v (TAG, "Exception: " + e); + // } } - if (nowVisible) { // We won't get a call to reportActivityVisibleLocked() so dismiss lockscreen now. mStackSupervisor.reportActivityVisibleLocked(this); @@ -2252,6 +2293,15 @@ final class ActivityRecord extends ConfigurationContainer { } } + public int isAppInfoGame() { + int isGame = 0; + if (appInfo != null) { + isGame = (appInfo.category == ApplicationInfo.CATEGORY_GAME || + (appInfo.flags & ApplicationInfo.FLAG_IS_GAME) == ApplicationInfo.FLAG_IS_GAME) ? 1 : 0; + } + return isGame; + } + /** * Called when the starting window for this container is drawn. */ @@ -2290,6 +2340,7 @@ final class ActivityRecord extends ConfigurationContainer { if (DEBUG_SWITCH) Log.v(TAG_SWITCH, "windowsVisibleLocked(): " + this); if (!nowVisible) { nowVisible = true; + launching = false; lastVisibleTime = SystemClock.uptimeMillis(); if (idle || mStackSupervisor.isStoppingNoHistoryActivity()) { // If this activity was already idle or there is an activity that must be @@ -2322,6 +2373,7 @@ final class ActivityRecord extends ConfigurationContainer { synchronized (mAtmService.mGlobalLock) { if (DEBUG_SWITCH) Log.v(TAG_SWITCH, "windowsGone(): " + this); nowVisible = false; + launching = false; } } diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java index 3aef8e1f84bf..0579fe333c37 100644 --- a/services/core/java/com/android/server/wm/ActivityStack.java +++ b/services/core/java/com/android/server/wm/ActivityStack.java @@ -151,6 +151,8 @@ import android.util.Slog; import android.util.SparseArray; import android.util.proto.ProtoOutputStream; import android.view.Display; +import com.android.internal.app.ActivityTrigger; + import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; @@ -159,6 +161,7 @@ import com.android.internal.util.function.pooled.PooledLambda; import com.android.server.Watchdog; import com.android.server.am.ActivityManagerService; import com.android.server.am.ActivityManagerService.ItemMatcher; +import android.util.BoostFramework; import com.android.server.am.AppTimeTracker; import com.android.server.am.EventLogTags; import com.android.server.am.PendingIntentRecord; @@ -174,7 +177,7 @@ import java.util.Set; /** * State and management of a single stack of activities. */ -class ActivityStack extends ConfigurationContainer { +public class ActivityStack extends ConfigurationContainer { private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStack" : TAG_ATM; private static final String TAG_ADD_REMOVE = TAG + POSTFIX_ADD_REMOVE; private static final String TAG_APP = TAG + POSTFIX_APP; @@ -299,6 +302,7 @@ class ActivityStack extends ConfigurationContainer { final ActivityTaskManagerService mService; final WindowManagerService mWindowManager; + public BoostFramework mPerf = null; /** * The back history of all previous (and possibly still * running) activities. It contains #TaskRecord objects. @@ -415,8 +419,9 @@ class ActivityStack extends ConfigurationContainer { final Handler mHandler; - private class ActivityStackHandler extends Handler { + static final ActivityTrigger mActivityTrigger = new ActivityTrigger(); + private class ActivityStackHandler extends Handler { ActivityStackHandler(Looper looper) { super(looper); } @@ -1040,7 +1045,7 @@ class ActivityStack extends ConfigurationContainer { return super.setBounds(!inMultiWindowMode() ? null : bounds); } - ActivityRecord topRunningActivityLocked() { + public ActivityRecord topRunningActivityLocked() { return topRunningActivityLocked(false /* focusableOnly */); } @@ -1661,6 +1666,11 @@ class ActivityStack extends ConfigurationContainer { if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to PAUSING: " + prev); else if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Start pausing: " + prev); + + if (mActivityTrigger != null) { + mActivityTrigger.activityPauseTrigger(prev.intent, prev.info, prev.appInfo); + } + mPausingActivity = prev; mLastPausedActivity = prev; mLastNoHistoryActivity = (prev.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_HISTORY) != 0 @@ -2651,9 +2661,15 @@ class ActivityStack extends ConfigurationContainer { mStackSupervisor.mGoingToSleepActivities.remove(next); next.sleeping = false; mStackSupervisor.mActivitiesWaitingForVisibleActivity.remove(next); + next.launching = true; if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resuming " + next); + if (mActivityTrigger != null) { + mActivityTrigger.activityResumeTrigger(next.intent, next.info, next.appInfo, + next.fullscreen); + } + // If we are currently pausing an activity, then don't do anything until that is done. if (!mRootActivityContainer.allPausedActivitiesComplete()) { if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) Slog.v(TAG_PAUSE, @@ -2786,6 +2802,9 @@ class ActivityStack extends ConfigurationContainer { // to ignore it when computing the desired screen orientation. boolean anim = true; final DisplayContent dc = getDisplay().mDisplayContent; + if (mPerf == null) { + mPerf = new BoostFramework(); + } if (prev != null) { if (prev.finishing) { if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, @@ -2794,6 +2813,12 @@ class ActivityStack extends ConfigurationContainer { anim = false; dc.prepareAppTransition(TRANSIT_NONE, false); } else { + mWindowManager.prepareAppTransition(prev.getTaskRecord() == next.getTaskRecord() + ? TRANSIT_ACTIVITY_CLOSE + : TRANSIT_TASK_CLOSE, false); + if(prev.getTaskRecord() != next.getTaskRecord() && mPerf != null) { + mPerf.perfHint(BoostFramework.VENDOR_HINT_ANIM_BOOST, next.packageName); + } dc.prepareAppTransition( prev.getTaskRecord() == next.getTaskRecord() ? TRANSIT_ACTIVITY_CLOSE : TRANSIT_TASK_CLOSE, false); @@ -2806,6 +2831,14 @@ class ActivityStack extends ConfigurationContainer { anim = false; dc.prepareAppTransition(TRANSIT_NONE, false); } else { + mWindowManager.prepareAppTransition(prev.getTaskRecord() == next.getTaskRecord() + ? TRANSIT_ACTIVITY_OPEN + : next.mLaunchTaskBehind + ? TRANSIT_TASK_OPEN_BEHIND + : TRANSIT_TASK_OPEN, false); + if(prev.getTaskRecord() != next.getTaskRecord() && mPerf != null) { + mPerf.perfHint(BoostFramework.VENDOR_HINT_ANIM_BOOST, next.packageName); + } dc.prepareAppTransition( prev.getTaskRecord() == next.getTaskRecord() ? TRANSIT_ACTIVITY_OPEN : next.mLaunchTaskBehind ? TRANSIT_TASK_OPEN_BEHIND @@ -3686,6 +3719,7 @@ class ActivityStack extends ConfigurationContainer { final void stopActivityLocked(ActivityRecord r) { if (DEBUG_SWITCH) Slog.d(TAG_SWITCH, "Stopping: " + r); + r.launching = false; if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0 || (r.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) { if (!r.finishing) { @@ -3710,11 +3744,17 @@ class ActivityStack extends ConfigurationContainer { r.resumeKeyDispatchingLocked(); try { r.stopped = false; + if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to STOPPING: " + r + " (stop requested)"); r.setState(STOPPING, "stopActivityLocked"); if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Stopping visible=" + r.visible + " for " + r); + + if (mActivityTrigger != null) { + mActivityTrigger.activityStopTrigger(r.intent, r.info, r.appInfo); + } + if (!r.visible) { r.setVisible(false); } @@ -4052,6 +4092,7 @@ class ActivityStack extends ConfigurationContainer { } if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to STOPPING: "+ r + " (finish requested)"); + r.setState(STOPPING, "finishCurrentActivityLocked"); if (oomAdj) { mService.updateOomAdj(); diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java index a83ef34f1cac..27def0c2beca 100644 --- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java @@ -51,6 +51,7 @@ import static android.view.WindowManager.TRANSIT_DOCK_TASK_FROM_RECENTS; import static com.android.server.wm.ActivityStack.ActivityState.PAUSED; import static com.android.server.wm.ActivityStack.ActivityState.PAUSING; +import static com.android.server.wm.ActivityStack.ActivityState.DESTROYED; import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_MOVING; import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ALL; import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_IDLE; @@ -130,6 +131,7 @@ import android.util.MergedConfiguration; import android.util.Slog; import android.util.SparseArray; import android.util.SparseIntArray; +import android.util.BoostFramework; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; @@ -176,6 +178,12 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { static final int RESUME_TOP_ACTIVITY_MSG = FIRST_SUPERVISOR_STACK_MSG + 2; static final int SLEEP_TIMEOUT_MSG = FIRST_SUPERVISOR_STACK_MSG + 3; static final int LAUNCH_TIMEOUT_MSG = FIRST_SUPERVISOR_STACK_MSG + 4; + + public static boolean mPerfSendTapHint = false; + public static boolean mIsPerfBoostAcquired = false; + public static int mPerfHandle = -1; + public BoostFramework mPerfBoost = null; + static final int LAUNCH_TASK_BEHIND_COMPLETE = FIRST_SUPERVISOR_STACK_MSG + 12; static final int REPORT_MULTI_WINDOW_MODE_CHANGED_MSG = FIRST_SUPERVISOR_STACK_MSG + 14; static final int REPORT_PIP_MODE_CHANGED_MSG = FIRST_SUPERVISOR_STACK_MSG + 15; @@ -239,7 +247,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { private static final int MAX_TASK_IDS_PER_USER = UserHandle.PER_USER_RANGE; final ActivityTaskManagerService mService; - RootActivityContainer mRootActivityContainer; + public RootActivityContainer mRootActivityContainer; /** The historial list of recent tasks including inactive tasks */ RecentTasks mRecentTasks; @@ -688,7 +696,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { } } - ActivityInfo resolveActivity(Intent intent, String resolvedType, int startFlags, + public ActivityInfo resolveActivity(Intent intent, String resolvedType, int startFlags, ProfilerInfo profilerInfo, int userId, int filterCallingUid) { final ResolveInfo rInfo = resolveIntent(intent, resolvedType, userId, 0, filterCallingUid); return resolveActivity(intent, rInfo, startFlags, profilerInfo); @@ -1363,6 +1371,16 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { void findTaskToMoveToFront(TaskRecord task, int flags, ActivityOptions options, String reason, boolean forceNonResizeable) { ActivityStack currentStack = task.getStack(); + + ActivityStack focusedStack = mRootActivityContainer.getTopDisplayFocusedStack(); + ActivityRecord top_activity = focusedStack != null ? focusedStack.getTopActivity() : null; + + //top_activity = task.stack.topRunningActivityLocked(); + /* App is launching from recent apps and it's a new process */ + if((top_activity != null) && (top_activity.getState() == DESTROYED)) { + acquireAppLaunchPerfLock(top_activity); + } + if (currentStack == null) { Slog.e(TAG, "findTaskToMoveToFront: can't move task=" + task + " to front. Stack is null"); @@ -2005,6 +2023,30 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { return timedout; } + void acquireAppLaunchPerfLock(ActivityRecord r) { + /* Acquire perf lock during new app launch */ + if (mPerfBoost == null) { + mPerfBoost = new BoostFramework(); + } + if (mPerfBoost != null) { + mPerfBoost.perfHint(BoostFramework.VENDOR_HINT_FIRST_LAUNCH_BOOST, r.packageName, -1, BoostFramework.Launch.BOOST_V1); + mPerfSendTapHint = true; + mPerfBoost.perfHint(BoostFramework.VENDOR_HINT_FIRST_LAUNCH_BOOST, r.packageName, -1, BoostFramework.Launch.BOOST_V2); + + if(mPerfBoost.perfGetFeedback(BoostFramework.VENDOR_FEEDBACK_WORKLOAD_TYPE, r.packageName) == BoostFramework.WorkloadType.GAME) + { + mPerfHandle = mPerfBoost.perfHint(BoostFramework.VENDOR_HINT_FIRST_LAUNCH_BOOST, r.packageName, -1, BoostFramework.Launch.BOOST_GAME); + } else { + mPerfHandle = mPerfBoost.perfHint(BoostFramework.VENDOR_HINT_FIRST_LAUNCH_BOOST, r.packageName, -1, BoostFramework.Launch.BOOST_V3); + } + if (mPerfHandle > 0) + mIsPerfBoostAcquired = true; + // Start IOP + mPerfBoost.perfIOPrefetchStart(-1,r.packageName, + r.appInfo.sourceDir.substring(0, r.appInfo.sourceDir.lastIndexOf('/'))); + } + } + void comeOutOfSleepIfNeededLocked() { removeSleepTimeouts(); if (mGoingToSleep.isHeld()) { diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java index 4e2dffc2ba78..8cefc759d39a 100644 --- a/services/core/java/com/android/server/wm/ActivityStarter.java +++ b/services/core/java/com/android/server/wm/ActivityStarter.java @@ -110,6 +110,7 @@ import android.os.UserHandle; import android.os.UserManager; import android.service.voice.IVoiceInteractionSession; import android.text.TextUtils; +import android.util.BoostFramework; import android.util.EventLog; import android.util.Pools.SynchronizedPool; import android.util.Slog; @@ -190,6 +191,8 @@ class ActivityStarter { private IVoiceInteractionSession mVoiceSession; private IVoiceInteractor mVoiceInteractor; + public BoostFramework mPerf = null; + // Last activity record we attempted to start private final ActivityRecord[] mLastStartActivityRecord = new ActivityRecord[1]; // The result of the last activity we attempted to start. @@ -437,6 +440,7 @@ class ActivityStarter { mSupervisor = supervisor; mInterceptor = interceptor; reset(true); + mPerf = new BoostFramework(); } /** @@ -1585,6 +1589,12 @@ class ActivityStarter { if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) { newTask = true; + String packageName= mService.mContext.getPackageName(); + if (mPerf != null) { + mStartActivity.perfActivityBoostHandler = + mPerf.perfHint(BoostFramework.VENDOR_HINT_FIRST_LAUNCH_BOOST, + packageName, -1, BoostFramework.Launch.BOOST_V1); + } result = setTaskFromReuseOrCreateNewTask(taskToAffiliate); } else if (mSourceRecord != null) { result = setTaskFromSourceRecord(); @@ -2260,6 +2270,12 @@ class ActivityStarter { Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity); return START_RETURN_LOCK_TASK_MODE_VIOLATION; } + String packageName= mService.mContext.getPackageName(); + if (mPerf != null) { + mStartActivity.perfActivityBoostHandler = + mPerf.perfHint(BoostFramework.VENDOR_HINT_FIRST_LAUNCH_BOOST, + packageName, -1, BoostFramework.Launch.BOOST_V1); + } final TaskRecord sourceTask = mSourceRecord.getTaskRecord(); final ActivityStack sourceStack = mSourceRecord.getActivityStack(); diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index 61c4863c0bc9..2e5fccb9a014 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -349,7 +349,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { /* Global service lock used by the package the owns this service. */ final WindowManagerGlobalLock mGlobalLock = new WindowManagerGlobalLock(); - ActivityStackSupervisor mStackSupervisor; + public ActivityStackSupervisor mStackSupervisor; RootActivityContainer mRootActivityContainer; WindowManagerService mWindowManager; private UserManagerService mUserManager; diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java index 6d3c69385a09..0f85381d079f 100644 --- a/services/core/java/com/android/server/wm/DisplayPolicy.java +++ b/services/core/java/com/android/server/wm/DisplayPolicy.java @@ -18,6 +18,7 @@ package com.android.server.wm; import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS; import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY; @@ -109,6 +110,7 @@ import android.app.StatusBarManager; import android.content.Context; import android.content.Intent; import android.content.res.Resources; +import android.content.pm.ApplicationInfo; import android.graphics.Rect; import android.hardware.input.InputManager; import android.hardware.power.V1_0.PowerHint; @@ -118,6 +120,7 @@ import android.os.Message; import android.os.SystemClock; import android.os.SystemProperties; import android.os.UserHandle; +import android.util.BoostFramework; import android.util.ArraySet; import android.util.PrintWriterPrinter; import android.util.Slog; @@ -202,6 +205,17 @@ public class DisplayPolicy { private final ImmersiveModeConfirmation mImmersiveModeConfirmation; private final ScreenshotHelper mScreenshotHelper; + private static final boolean SCROLL_BOOST_SS_ENABLE = + SystemProperties.getBoolean("vendor.perf.gestureflingboost.enable", false); + + /* + * @hide + */ + BoostFramework mPerfBoostDrag = null; + BoostFramework mPerfBoostFling = null; + BoostFramework mPerfBoostPrefling = null; + private boolean mIsPerfBoostFlingAcquired; + private final Object mServiceAcquireLock = new Object(); private StatusBarManagerInternal mStatusBarManagerInternal; @@ -372,6 +386,24 @@ public class DisplayPolicy { } } + private boolean isTopAppGame() { + boolean isGame = false; + try { + ActivityManager.RunningTaskInfo rti = ActivityManager.getService().getFilteredTasks(1, + ACTIVITY_TYPE_RECENTS, WINDOWING_MODE_UNDEFINED).get(0); + ApplicationInfo ai = mContext.getPackageManager().getApplicationInfo( + rti.topActivity.getPackageName(), 0); + if(ai != null) { + isGame = (ai.category == ApplicationInfo.CATEGORY_GAME) || + ((ai.flags & ApplicationInfo.FLAG_IS_GAME) == + ApplicationInfo.FLAG_IS_GAME); + } + } catch (Exception e) { + return false; + } + return isGame; + } + DisplayPolicy(WindowManagerService service, DisplayContent displayContent) { mService = service; mContext = displayContent.isDefaultDisplay ? service.mContext @@ -435,6 +467,56 @@ public class DisplayPolicy { } @Override + public void onVerticalFling(int duration) { + String currentPackage = mContext.getPackageName(); + boolean isGame = isTopAppGame(); + if (SCROLL_BOOST_SS_ENABLE && !isGame) { + if (mPerfBoostFling == null) { + mPerfBoostFling = new BoostFramework(); + mIsPerfBoostFlingAcquired = false; + } + if (mPerfBoostFling == null) { + Slog.e(TAG, "Error: boost object null"); + return; + } + + mPerfBoostFling.perfHint(BoostFramework.VENDOR_HINT_SCROLL_BOOST, + currentPackage, duration + 160, BoostFramework.Scroll.VERTICAL); + mIsPerfBoostFlingAcquired = true; + } + } + + @Override + public void onScroll(boolean started) { + String currentPackage = mContext.getPackageName(); + boolean isGame = isTopAppGame(); + if (mPerfBoostDrag == null) { + mPerfBoostDrag = new BoostFramework(); + } + if (mPerfBoostDrag == null) { + Slog.e(TAG, "Error: boost object null"); + return; + } + if (SCROLL_BOOST_SS_ENABLE && !isGame) { + if (mPerfBoostPrefling == null) { + mPerfBoostPrefling = new BoostFramework(); + } + if (mPerfBoostPrefling == null) { + Slog.e(TAG, "Error: boost object null"); + return; + } + mPerfBoostPrefling.perfHint(BoostFramework.VENDOR_HINT_SCROLL_BOOST, + currentPackage, -1, BoostFramework.Scroll.PREFILING); + } + if (!isGame && started) { + mPerfBoostDrag.perfHint(BoostFramework.VENDOR_HINT_DRAG_BOOST, + currentPackage, -1, 1); + } else { + mPerfBoostDrag.perfLockRelease(); + } + } + + @Override public void onDebug() { // no-op } @@ -450,6 +532,11 @@ public class DisplayPolicy { if (listener != null) { listener.onTouchStart(); } + if(SCROLL_BOOST_SS_ENABLE && mPerfBoostFling!= null + && mIsPerfBoostFlingAcquired) { + mPerfBoostFling.perfLockRelease(); + mIsPerfBoostFlingAcquired = false; + } } @Override diff --git a/services/core/java/com/android/server/wm/RootActivityContainer.java b/services/core/java/com/android/server/wm/RootActivityContainer.java index c4a853dc3483..e93da6ca771c 100644 --- a/services/core/java/com/android/server/wm/RootActivityContainer.java +++ b/services/core/java/com/android/server/wm/RootActivityContainer.java @@ -129,7 +129,7 @@ import java.util.Set; * TODO: This class is mostly temporary to separate things out of ActivityStackSupervisor.java. The * intention is to have this merged with RootWindowContainer.java as part of unifying the hierarchy. */ -class RootActivityContainer extends ConfigurationContainer +public class RootActivityContainer extends ConfigurationContainer implements DisplayManager.DisplayListener { private static final String TAG = TAG_WITH_CLASS_NAME ? "RootActivityContainer" : TAG_ATM; @@ -642,7 +642,7 @@ class RootActivityContainer extends ConfigurationContainer return topActivityTokens; } - ActivityStack getTopDisplayFocusedStack() { + public ActivityStack getTopDisplayFocusedStack() { for (int i = mActivityDisplays.size() - 1; i >= 0; --i) { final ActivityStack focusedStack = mActivityDisplays.get(i).getFocusedStack(); if (focusedStack != null) { diff --git a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java index 3947bd47b588..b390259d1979 100644 --- a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java +++ b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java @@ -28,6 +28,7 @@ import static com.android.server.wm.WindowStateAnimator.WINDOW_FREEZE_LAYER; import android.content.Context; import android.graphics.Matrix; import android.graphics.Rect; +import android.util.BoostFramework; import android.util.Slog; import android.util.proto.ProtoOutputStream; import android.view.Display; @@ -58,6 +59,8 @@ class ScreenRotationAnimation { static final int SCREEN_FREEZE_LAYER_EXIT = SCREEN_FREEZE_LAYER_BASE + 2; static final int SCREEN_FREEZE_LAYER_CUSTOM = SCREEN_FREEZE_LAYER_BASE + 3; + private BoostFramework mPerf = null; + private boolean mIsPerfLockAcquired = false; final Context mContext; final DisplayContent mDisplayContent; SurfaceControl mSurfaceControl; @@ -228,6 +231,8 @@ class ScreenRotationAnimation { mDisplayContent = displayContent; displayContent.getBounds(mOriginalDisplayRect); + mPerf = new BoostFramework(); + // Screenshot does NOT include rotation! final Display display = displayContent.getDisplay(); int originalRotation = display.getRotation(); @@ -681,6 +686,10 @@ class ScreenRotationAnimation { mRotateEnterAnimation.cancel(); mRotateEnterAnimation = null; } + if (mPerf != null && mIsPerfLockAcquired) { + mPerf.perfLockRelease(); + mIsPerfLockAcquired = false; + } } public boolean isAnimating() { @@ -796,6 +805,10 @@ class ScreenRotationAnimation { mRotateExitAnimation = null; mRotateExitTransformation.clear(); } + if (mPerf != null && mIsPerfLockAcquired) { + mPerf.perfLockRelease(); + mIsPerfLockAcquired = false; + } } if (!mMoreRotateEnter && (!TWO_PHASE_ANIMATION || (!mMoreStartEnter && !mMoreFinishEnter))) { @@ -819,6 +832,10 @@ class ScreenRotationAnimation { mRotateEnterAnimation = null; mRotateEnterTransformation.clear(); } + if (mPerf != null && mIsPerfLockAcquired) { + mPerf.perfLockRelease(); + mIsPerfLockAcquired = false; + } } if (USE_CUSTOM_BLACK_FRAME && !mMoreStartFrame && !mMoreRotateFrame && !mMoreFinishFrame) { @@ -840,6 +857,10 @@ class ScreenRotationAnimation { mRotateFrameAnimation = null; mRotateFrameTransformation.clear(); } + if (mPerf != null && mIsPerfLockAcquired) { + mPerf.perfLockRelease(); + mIsPerfLockAcquired = false; + } } mExitTransformation.set(mRotateExitTransformation); @@ -968,6 +989,10 @@ class ScreenRotationAnimation { } mAnimRunning = true; mHalfwayPoint = now + mRotateEnterAnimation.getDuration() / 2; + if (mPerf != null && !mIsPerfLockAcquired) { + mPerf.perfHint(BoostFramework.VENDOR_HINT_ROTATION_ANIM_BOOST, null); + mIsPerfLockAcquired = true; + } } return stepAnimation(now); diff --git a/services/core/java/com/android/server/wm/SystemGesturesPointerEventListener.java b/services/core/java/com/android/server/wm/SystemGesturesPointerEventListener.java index bdb76c27c668..9d8df7be5803 100644 --- a/services/core/java/com/android/server/wm/SystemGesturesPointerEventListener.java +++ b/services/core/java/com/android/server/wm/SystemGesturesPointerEventListener.java @@ -63,6 +63,7 @@ class SystemGesturesPointerEventListener implements PointerEventListener { private boolean mDebugFireable; private boolean mMouseHoveringAtEdge; private long mLastFlingTime; + private boolean mScrollFired; SystemGesturesPointerEventListener(Context context, Handler handler, Callbacks callbacks) { mContext = context; @@ -95,6 +96,7 @@ class SystemGesturesPointerEventListener implements PointerEventListener { case MotionEvent.ACTION_DOWN: mSwipeFireable = true; mDebugFireable = true; + mScrollFired = false; mDownPointers = 0; captureDown(event, 0); if (mMouseHoveringAtEdge) { @@ -151,6 +153,9 @@ class SystemGesturesPointerEventListener implements PointerEventListener { case MotionEvent.ACTION_CANCEL: mSwipeFireable = false; mDebugFireable = false; + if (mScrollFired) + mCallbacks.onScroll(false); + mScrollFired = false; mCallbacks.onUpOrCancel(); break; default: @@ -269,10 +274,22 @@ class SystemGesturesPointerEventListener implements PointerEventListener { if (duration > MAX_FLING_TIME_MILLIS) { duration = MAX_FLING_TIME_MILLIS; } + if(Math.abs(velocityY) >= Math.abs(velocityX)) + mCallbacks.onVerticalFling(duration); mLastFlingTime = now; mCallbacks.onFling(duration); return true; } + + @Override + public boolean onScroll(MotionEvent e1, MotionEvent e2, + float distanceX, float distanceY) { + if (!mScrollFired) { + mCallbacks.onScroll(true); + mScrollFired = true; + } + return true; + } } interface Callbacks { @@ -281,6 +298,8 @@ class SystemGesturesPointerEventListener implements PointerEventListener { void onSwipeFromRight(); void onSwipeFromLeft(); void onFling(int durationMs); + void onVerticalFling(int durationMs); + void onScroll(boolean started); void onDown(); void onUpOrCancel(); void onMouseHoverAtTop(); diff --git a/services/core/java/com/android/server/wm/TaskTapPointerEventListener.java b/services/core/java/com/android/server/wm/TaskTapPointerEventListener.java index 2e5df45f9080..06f602741adb 100644 --- a/services/core/java/com/android/server/wm/TaskTapPointerEventListener.java +++ b/services/core/java/com/android/server/wm/TaskTapPointerEventListener.java @@ -30,6 +30,10 @@ import android.view.MotionEvent; import android.view.WindowManagerPolicyConstants.PointerEventListener; import com.android.server.wm.WindowManagerService.H; +import com.android.server.am.ActivityManagerService; +import com.android.server.wm.ActivityStackSupervisor; +import com.android.server.wm.ActivityDisplay; +import android.util.BoostFramework; /** * 1. Adjust the top most focus display if touch down on some display. @@ -47,6 +51,7 @@ public class TaskTapPointerEventListener implements PointerEventListener { private int mPointerIconType = TYPE_NOT_SPECIFIED; private int mLastDownX; private int mLastDownY; + public BoostFramework mPerfObj = null; public TaskTapPointerEventListener(WindowManagerService service, DisplayContent displayContent) { @@ -77,6 +82,9 @@ public class TaskTapPointerEventListener implements PointerEventListener { } } }; + if (mPerfObj == null) { + mPerfObj = new BoostFramework(); + } } @Override @@ -150,6 +158,28 @@ public class TaskTapPointerEventListener implements PointerEventListener { } break; } + if (ActivityStackSupervisor.mIsPerfBoostAcquired && (mPerfObj != null)) { + if (ActivityStackSupervisor.mPerfHandle > 0) { + mPerfObj.perfLockReleaseHandler(ActivityStackSupervisor.mPerfHandle); + ActivityStackSupervisor.mPerfHandle = -1; + } + ActivityStackSupervisor.mIsPerfBoostAcquired = false; + } + if (ActivityStackSupervisor.mPerfSendTapHint && (mPerfObj != null)) { + mPerfObj.perfHint(BoostFramework.VENDOR_HINT_TAP_EVENT, null); + ActivityStackSupervisor.mPerfSendTapHint = false; + } + if (ActivityDisplay.mIsPerfBoostAcquired && (mPerfObj != null)) { + if (ActivityDisplay.mPerfHandle > 0) { + mPerfObj.perfLockReleaseHandler(ActivityDisplay.mPerfHandle); + ActivityDisplay.mPerfHandle = -1; + } + ActivityDisplay.mIsPerfBoostAcquired = false; + } + if (ActivityDisplay.mPerfSendTapHint && (mPerfObj != null)) { + mPerfObj.perfHint(BoostFramework.VENDOR_HINT_TAP_EVENT, null); + ActivityDisplay.mPerfSendTapHint = false; + } } void setTouchExcludeRegion(Region newRegion) { diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index fda7a85c1270..8ba5592fe834 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -177,6 +177,7 @@ import android.service.vr.IVrStateCallbacks; import android.text.format.DateUtils; import android.util.ArrayMap; import android.util.ArraySet; +import android.util.BoostFramework; import android.util.DisplayMetrics; import android.util.EventLog; import android.util.Log; @@ -278,7 +279,8 @@ public class WindowManagerService extends IWindowManager.Stub static final boolean PROFILE_ORIENTATION = false; static final boolean localLOGV = DEBUG; - + static WindowState mFocusingWindow; + String mFocusingActivity; /** How much to multiply the policy's type layer, to reserve room * for multiple windows of the same type and Z-ordering adjustment * with TYPE_LAYER_OFFSET. */ @@ -371,6 +373,8 @@ public class WindowManagerService extends IWindowManager.Stub final WindowTracing mWindowTracing; + private BoostFramework mPerf = null; + final private KeyguardDisableHandler mKeyguardDisableHandler; // TODO: eventually unify all keyguard state in a common place instead of having it spread over // AM's KeyguardController and the policy's KeyguardServiceDelegate. @@ -2919,12 +2923,28 @@ public class WindowManagerService extends IWindowManager.Stub ValueAnimator.setDurationScale(scale); } + private float animationScalesCheck (int which) { + float value = -1.0f; + if (!mAnimationsDisabled) { + if (value == -1.0f) { + switch (which) { + case WINDOW_ANIMATION_SCALE: value = mWindowAnimationScaleSetting; break; + case TRANSITION_ANIMATION_SCALE: value = mTransitionAnimationScaleSetting; break; + case ANIMATION_DURATION_SCALE: value = mAnimatorDurationScaleSetting; break; + } + } + } else { + value = 0; + } + return value; + } + public float getWindowAnimationScaleLocked() { - return mAnimationsDisabled ? 0 : mWindowAnimationScaleSetting; + return animationScalesCheck(WINDOW_ANIMATION_SCALE); } public float getTransitionAnimationScaleLocked() { - return mAnimationsDisabled ? 0 : mTransitionAnimationScaleSetting; + return animationScalesCheck(TRANSITION_ANIMATION_SCALE); } @Override @@ -5292,6 +5312,12 @@ public class WindowManagerService extends IWindowManager.Stub } mLatencyTracker.onActionStart(ACTION_ROTATE_SCREEN); + if (mPerf == null) { + mPerf = new BoostFramework(); + } + if (mPerf != null) { + mPerf.perfHint(BoostFramework.VENDOR_HINT_ROTATION_LATENCY_BOOST, null); + } if (CUSTOM_SCREEN_ROTATION) { mExitAnimId = exitAnim; mEnterAnimId = enterAnim; @@ -5417,6 +5443,9 @@ public class WindowManagerService extends IWindowManager.Stub displayContent.sendNewConfiguration(); } mLatencyTracker.onActionEnd(ACTION_ROTATE_SCREEN); + if (mPerf != null) { + mPerf.perfLockRelease(); + } } static int getPropertyInt(String[] tokens, int index, int defUnits, int defDps, diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index cef47caff740..09ecc7e3a915 100644..100755 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -43,6 +43,7 @@ import android.os.Environment; import android.os.FactoryTest; import android.os.FileUtils; import android.os.IIncidentManager; +import android.os.IBinder; import android.os.Looper; import android.os.Message; import android.os.Parcel; @@ -151,6 +152,9 @@ import com.android.server.wm.WindowManagerGlobalLock; import com.android.server.wm.WindowManagerService; import dalvik.system.VMRuntime; +import dalvik.system.PathClassLoader; +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; import com.google.android.startop.iorap.IorapForwardingService; @@ -823,6 +827,8 @@ public final class SystemServer { ConsumerIrService consumerIr = null; MmsServiceBroker mmsService = null; HardwarePropertiesManagerService hardwarePropertiesService = null; + Object wigigP2pService = null; + Object wigigService = null; boolean disableSystemTextClassifier = SystemProperties.getBoolean( "config.disable_systemtextclassifier", false); @@ -835,6 +841,7 @@ public final class SystemServer { boolean enableLeftyService = SystemProperties.getBoolean("config.enable_lefty", false); boolean isEmulator = SystemProperties.get("ro.kernel.qemu").equals("1"); + boolean enableWigig = SystemProperties.getBoolean("persist.vendor.wigig.enable", false); boolean isWatch = context.getPackageManager().hasSystemFeature( PackageManager.FEATURE_WATCH); @@ -1302,6 +1309,33 @@ public final class SystemServer { } } + if (enableWigig) { + try { + Slog.i(TAG, "Wigig Service"); + String wigigClassPath = + "/system/framework/wigig-service.jar" + ":" + + "/system/framework/vendor.qti.hardware.wigig.supptunnel-V1.0-java.jar" + ":" + + "/system/framework/vendor.qti.hardware.wigig.netperftuner-V1.0-java.jar"; + PathClassLoader wigigClassLoader = + new PathClassLoader(wigigClassPath, getClass().getClassLoader()); + Class wigigP2pClass = wigigClassLoader.loadClass( + "com.qualcomm.qti.server.wigig.p2p.WigigP2pServiceImpl"); + Constructor<Class> ctor = wigigP2pClass.getConstructor(Context.class); + wigigP2pService = ctor.newInstance(context); + Slog.i(TAG, "Successfully loaded WigigP2pServiceImpl class"); + ServiceManager.addService("wigigp2p", (IBinder) wigigP2pService); + + Class wigigClass = wigigClassLoader.loadClass( + "com.qualcomm.qti.server.wigig.WigigService"); + ctor = wigigClass.getConstructor(Context.class); + wigigService = ctor.newInstance(context); + Slog.i(TAG, "Successfully loaded WigigService class"); + ServiceManager.addService("wigig", (IBinder) wigigService); + } catch (Throwable e) { + reportWtf("starting WigigService", e); + } + } + if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_ETHERNET) || mPackageManager.hasSystemFeature(PackageManager.FEATURE_USB_HOST)) { traceBeginAndSlog("StartEthernet"); @@ -1892,7 +1926,27 @@ public final class SystemServer { mSystemServiceManager.startBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY); traceEnd(); + // Wigig services are not registered as system services because of class loader + // limitations, send boot phase notification separately + if (enableWigig) { + try { + Slog.i(TAG, "calling onBootPhase for Wigig Services"); + Class wigigP2pClass = wigigP2pService.getClass(); + Method m = wigigP2pClass.getMethod("onBootPhase", int.class); + m.invoke(wigigP2pService, new Integer( + SystemService.PHASE_SYSTEM_SERVICES_READY)); + + Class wigigClass = wigigService.getClass(); + m = wigigClass.getMethod("onBootPhase", int.class); + m.invoke(wigigService, new Integer( + SystemService.PHASE_SYSTEM_SERVICES_READY)); + } catch (Throwable e) { + reportWtf("Wigig services ready", e); + } + } + traceBeginAndSlog("MakeWindowManagerServiceReady"); + try { wm.systemReady(); } catch (Throwable e) { diff --git a/services/net/java/android/net/dhcp/DhcpClient.java b/services/net/java/android/net/dhcp/DhcpClient.java index a956cefd1235..192edc4007a0 100644 --- a/services/net/java/android/net/dhcp/DhcpClient.java +++ b/services/net/java/android/net/dhcp/DhcpClient.java @@ -128,6 +128,9 @@ public class DhcpClient extends StateMachine { public static final int CMD_CONFIGURE_LINKADDRESS = PUBLIC_BASE + 8; public static final int EVENT_LINKADDRESS_CONFIGURED = PUBLIC_BASE + 9; + /* Command from controller to start DHCP with Rapid commit */ + public static final int CMD_START_DHCP_RAPID_COMMIT = PUBLIC_BASE + 10; + /* Message.arg1 arguments to CMD_POST_DHCP_ACTION notification */ public static final int DHCP_SUCCESS = 1; public static final int DHCP_FAILURE = 2; @@ -196,6 +199,8 @@ public class DhcpClient extends StateMachine { private DhcpResults mDhcpLease; private long mDhcpLeaseExpiry; private DhcpResults mOffer; + public boolean mRapidCommit; + public boolean mDiscoverSent; // Milliseconds SystemClock timestamps used to record transition times to DhcpBoundState. private long mLastInitEnterTime; @@ -205,6 +210,7 @@ public class DhcpClient extends StateMachine { private State mStoppedState = new StoppedState(); private State mDhcpState = new DhcpState(); private State mDhcpInitState = new DhcpInitState(); + private State mDhcpRapidCommitInitState = new DhcpRapidCommitInitState(); private State mDhcpSelectingState = new DhcpSelectingState(); private State mDhcpRequestingState = new DhcpRequestingState(); private State mDhcpHaveLeaseState = new DhcpHaveLeaseState(); @@ -215,6 +221,7 @@ public class DhcpClient extends StateMachine { private State mDhcpInitRebootState = new DhcpInitRebootState(); private State mDhcpRebootingState = new DhcpRebootingState(); private State mWaitBeforeStartState = new WaitBeforeStartState(mDhcpInitState); + private State mRapidCommitWaitBeforeStartState = new WaitBeforeStartState(mDhcpRapidCommitInitState); private State mWaitBeforeRenewalState = new WaitBeforeRenewalState(mDhcpRenewingState); private WakeupMessage makeWakeupMessage(String cmdName, int cmd) { @@ -233,7 +240,9 @@ public class DhcpClient extends StateMachine { addState(mStoppedState); addState(mDhcpState); addState(mDhcpInitState, mDhcpState); + addState(mDhcpRapidCommitInitState, mDhcpState); addState(mWaitBeforeStartState, mDhcpState); + addState(mRapidCommitWaitBeforeStartState, mDhcpState); addState(mDhcpSelectingState, mDhcpState); addState(mDhcpRequestingState, mDhcpState); addState(mDhcpHaveLeaseState, mDhcpState); @@ -422,10 +431,17 @@ public class DhcpClient extends StateMachine { return true; } + public ByteBuffer buildDiscoverWithRapidCommitPacket() { + startNewTransaction(); + return DhcpPacket.buildDiscoverPacket( + DhcpPacket.ENCAP_L2, mTransactionId, getSecs(), mHwAddr, + DO_UNICAST, REQUESTED_PARAMS, mRapidCommit); + } + private boolean sendDiscoverPacket() { ByteBuffer packet = DhcpPacket.buildDiscoverPacket( DhcpPacket.ENCAP_L2, mTransactionId, getSecs(), mHwAddr, - DO_UNICAST, REQUESTED_PARAMS); + DO_UNICAST, REQUESTED_PARAMS, mRapidCommit); return transmitPacket(packet, "DHCPDISCOVER", DhcpPacket.ENCAP_L2, INADDR_BROADCAST); } @@ -590,12 +606,75 @@ public class DhcpClient extends StateMachine { transitionTo(mDhcpInitState); } return HANDLED; + case CMD_START_DHCP_RAPID_COMMIT: + mRapidCommit = message.arg1 == 1 ? true: false; + mDiscoverSent = message.arg2 == 1 ? true : false; + if (mRegisteredForPreDhcpNotification) { + if (mRapidCommit) { + transitionTo(mRapidCommitWaitBeforeStartState); + } else { + transitionTo(mWaitBeforeStartState); + } + } else { + if (mRapidCommit) { + transitionTo(mDhcpRapidCommitInitState); + } else { + transitionTo(mDhcpInitState); + } + } + return HANDLED; default: return NOT_HANDLED; } } } + class DhcpRapidCommitInitState extends PacketRetransmittingState { + public DhcpRapidCommitInitState() { + super(); + } + + @Override + public void enter() { + super.enter(); + if (!mDiscoverSent) { + startNewTransaction(); + } + mLastInitEnterTime = SystemClock.elapsedRealtime(); + } + + protected boolean sendPacket() { + if (mDiscoverSent) { + mDiscoverSent = false; + return true; + } + return sendDiscoverPacket(); + } + + protected void receivePacket(DhcpPacket packet) { + if (!isValidPacket(packet)) return; + if (packet instanceof DhcpOfferPacket) { + mOffer = packet.toDhcpResults(); + if (mOffer != null) { + Log.d(TAG, "DhcpRapidCommitInitState:Got pending lease: " + mOffer); + transitionTo(mDhcpRequestingState); + } + } else if ((packet instanceof DhcpAckPacket)) { + DhcpResults results = packet.toDhcpResults(); + Log.d(TAG,"Received ACK in DhcpRapidCommitInitState"); + if (results != null) { + setDhcpLeaseExpiry(packet); + acceptDhcpResults(results, "Confirmed"); + transitionTo(mConfiguringInterfaceState); + } + } else if (packet instanceof DhcpNakPacket) { + Log.d(TAG, "Received NAK in DhcpRapidCommitInitState, returning to INIT"); + mOffer = null; + transitionTo(mDhcpInitState); + } + } + } + class WaitBeforeStartState extends WaitBeforeOtherState { public WaitBeforeStartState(State otherState) { super(); diff --git a/services/net/java/android/net/dhcp/DhcpDiscoverPacket.java b/services/net/java/android/net/dhcp/DhcpDiscoverPacket.java index 11f2b6118e24..19beb0881683 100644 --- a/services/net/java/android/net/dhcp/DhcpDiscoverPacket.java +++ b/services/net/java/android/net/dhcp/DhcpDiscoverPacket.java @@ -36,6 +36,12 @@ class DhcpDiscoverPacket extends DhcpPacket { super(transId, secs, INADDR_ANY, INADDR_ANY, INADDR_ANY, relayIp, clientMac, broadcast); mSrcIp = srcIp; } + DhcpDiscoverPacket(int transId, short secs, byte[] clientMac, boolean broadcast, + boolean rapidCommit) { + super(transId, secs, INADDR_ANY, INADDR_ANY, INADDR_ANY, INADDR_ANY, + clientMac, broadcast, rapidCommit); + mSrcIp = INADDR_ANY; + } public String toString() { String s = super.toString(); @@ -62,6 +68,9 @@ class DhcpDiscoverPacket extends DhcpPacket { addTlv(buffer, DHCP_CLIENT_IDENTIFIER, getClientId()); addCommonClientTlvs(buffer); addTlv(buffer, DHCP_PARAMETER_LIST, mRequestedParams); + if (mRapidCommit) { + addTlv(buffer, DHCP_OPTION_RAPID_COMMIT); + } addTlvEnd(buffer); } } diff --git a/services/net/java/android/net/dhcp/DhcpPacket.java b/services/net/java/android/net/dhcp/DhcpPacket.java index ce8b7e78d0f8..d968ed114b93 100644 --- a/services/net/java/android/net/dhcp/DhcpPacket.java +++ b/services/net/java/android/net/dhcp/DhcpPacket.java @@ -266,6 +266,11 @@ public abstract class DhcpPacket { protected byte[] mClientId; /** + * DHCP zero-length option code: rapid commit + */ + protected static final byte DHCP_OPTION_RAPID_COMMIT = 80; + + /** * DHCP zero-length option code: pad */ protected static final byte DHCP_OPTION_PAD = 0x00; @@ -306,6 +311,11 @@ public abstract class DhcpPacket { protected final byte[] mClientMac; /** + * Whether the packet should be built with rapid commit option + */ + protected boolean mRapidCommit; + + /** * Asks the packet object to create a ByteBuffer serialization of * the packet for transmission. */ @@ -325,7 +335,7 @@ public abstract class DhcpPacket { protected DhcpPacket(int transId, short secs, Inet4Address clientIp, Inet4Address yourIp, Inet4Address nextIp, Inet4Address relayIp, - byte[] clientMac, boolean broadcast) { + byte[] clientMac, boolean broadcast, boolean rapidCommit) { mTransId = transId; mSecs = secs; mClientIp = clientIp; @@ -334,6 +344,14 @@ public abstract class DhcpPacket { mRelayIp = relayIp; mClientMac = clientMac; mBroadcast = broadcast; + mRapidCommit = rapidCommit; + } + + protected DhcpPacket(int transId, short secs, Inet4Address clientIp, Inet4Address yourIp, + Inet4Address nextIp, Inet4Address relayIp, + byte[] clientMac, boolean broadcast) { + this(transId, secs, clientIp, yourIp, nextIp, + relayIp, clientMac, broadcast, false); } /** @@ -576,6 +594,14 @@ public abstract class DhcpPacket { } /** + * Adds an optional parameter not containing any payload. + */ + protected static void addTlv(ByteBuffer buf, byte type) { + buf.put(type); + buf.put((byte) 0); + } + + /** * Adds an optional parameter containing a single byte value. */ protected static void addTlv(ByteBuffer buf, byte type, byte value) { @@ -1272,8 +1298,13 @@ public abstract class DhcpPacket { */ public static ByteBuffer buildDiscoverPacket(int encap, int transactionId, short secs, byte[] clientMac, boolean broadcast, byte[] expectedParams) { - DhcpPacket pkt = new DhcpDiscoverPacket(transactionId, secs, INADDR_ANY /* relayIp */, - clientMac, broadcast, INADDR_ANY /* srcIp */); + return buildDiscoverPacket(encap, transactionId, secs, clientMac, + broadcast, expectedParams, false); + } + public static ByteBuffer buildDiscoverPacket(int encap, int transactionId, + short secs, byte[] clientMac, boolean broadcast, byte[] expectedParams, + boolean rapidCommit) { + DhcpPacket pkt = new DhcpDiscoverPacket(transactionId, secs, clientMac, broadcast, rapidCommit); pkt.mRequestedParams = expectedParams; return pkt.buildPacket(encap, DHCP_SERVER, DHCP_CLIENT); } diff --git a/services/net/java/android/net/ip/IpClient.java b/services/net/java/android/net/ip/IpClient.java index ff4e2809d090..427267e7003c 100644 --- a/services/net/java/android/net/ip/IpClient.java +++ b/services/net/java/android/net/ip/IpClient.java @@ -74,6 +74,7 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CountDownLatch; import java.util.function.Predicate; import java.util.stream.Collectors; +import java.nio.ByteBuffer; /** @@ -1164,7 +1165,12 @@ public class IpClient extends StateMachine { // Start DHCPv4. mDhcpClient = DhcpClient.makeDhcpClient(mContext, IpClient.this, mInterfaceParams); mDhcpClient.registerForPreDhcpNotification(); - mDhcpClient.sendMessage(DhcpClient.CMD_START_DHCP); + if (mConfiguration.mRapidCommit || mConfiguration.mDiscoverSent) + mDhcpClient.sendMessage(DhcpClient.CMD_START_DHCP_RAPID_COMMIT, + (mConfiguration.mRapidCommit ? 1: 0), + (mConfiguration.mDiscoverSent ? 1: 0)); + else + mDhcpClient.sendMessage(DhcpClient.CMD_START_DHCP); } return true; @@ -1225,6 +1231,11 @@ public class IpClient extends StateMachine { return (mIpReachabilityMonitor != null); } + + public ByteBuffer buildDiscoverWithRapidCommitPacket() { + return mDhcpClient.buildDiscoverWithRapidCommitPacket(); + } + private void stopAllIP() { // We don't need to worry about routes, just addresses, because: // - disableIpv6() will clear autoconf IPv6 routes as well, and diff --git a/services/net/java/android/net/ip/IpServer.java b/services/net/java/android/net/ip/IpServer.java index 8b22f68286af..8656b1f83192 100644 --- a/services/net/java/android/net/ip/IpServer.java +++ b/services/net/java/android/net/ip/IpServer.java @@ -95,6 +95,8 @@ public class IpServer extends StateMachine { private static final int USB_PREFIX_LENGTH = 24; private static final String WIFI_HOST_IFACE_ADDR = "192.168.43.1"; private static final int WIFI_HOST_IFACE_PREFIX_LENGTH = 24; + private static final String WIGIG_HOST_IFACE_ADDR = "192.168.50.1"; + private static final int WIGIG_HOST_IFACE_PREFIX_LENGTH = 24; // TODO: have PanService use some visible version of this constant private static final String BLUETOOTH_IFACE_ADDR = "192.168.44.1"; @@ -248,6 +250,7 @@ public class IpServer extends StateMachine { setInitialState(mInitialState); } + public String interfaceName() { return mIfaceName; } public int interfaceType() { return mInterfaceType; } @@ -404,6 +407,9 @@ public class IpServer extends StateMachine { } else if (mInterfaceType == ConnectivityManager.TETHERING_WIFI) { ipAsString = getRandomWifiIPv4Address(); prefixLen = WIFI_HOST_IFACE_PREFIX_LENGTH; + } else if (mInterfaceType == ConnectivityManager.TETHERING_WIGIG) { + ipAsString = WIGIG_HOST_IFACE_ADDR; + prefixLen = WIGIG_HOST_IFACE_PREFIX_LENGTH; } else { // BT configures the interface elsewhere: only start DHCP. final Inet4Address srvAddr = (Inet4Address) numericToInetAddress(BLUETOOTH_IFACE_ADDR); diff --git a/services/net/java/android/net/shared/ProvisioningConfiguration.java b/services/net/java/android/net/shared/ProvisioningConfiguration.java index f9370653411e..c4d1e121ff3c 100644 --- a/services/net/java/android/net/shared/ProvisioningConfiguration.java +++ b/services/net/java/android/net/shared/ProvisioningConfiguration.java @@ -202,6 +202,8 @@ public class ProvisioningConfiguration { public ApfCapabilities mApfCapabilities; public int mProvisioningTimeoutMs = DEFAULT_TIMEOUT_MS; public int mIPv6AddrGenMode = INetd.IPV6_ADDR_GEN_MODE_STABLE_PRIVACY; + public boolean mRapidCommit; + public boolean mDiscoverSent; public Network mNetwork = null; public String mDisplayName = null; @@ -219,6 +221,8 @@ public class ProvisioningConfiguration { : new StaticIpConfiguration(other.mStaticIpConfig); mApfCapabilities = other.mApfCapabilities; mProvisioningTimeoutMs = other.mProvisioningTimeoutMs; + mRapidCommit = other.mRapidCommit; + mDiscoverSent = other.mDiscoverSent; mIPv6AddrGenMode = other.mIPv6AddrGenMode; mNetwork = other.mNetwork; mDisplayName = other.mDisplayName; diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java index a381023590c3..b3e5169fb0e8 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java @@ -81,6 +81,7 @@ import androidx.test.filters.SmallTest; import com.android.server.wm.LaunchParamsController.LaunchParamsModifier; import com.android.server.wm.TaskRecord.TaskRecordFactory; +import org.junit.Ignore; import org.junit.Before; import org.junit.Test; @@ -383,6 +384,7 @@ public class ActivityStarterTests extends ActivityTestsBase { * Ensures that values specified at launch time are passed to {@link LaunchParamsModifier} * when we are laying out a new task. */ + @Ignore // TODO(b/119048275): Reenable failing test in activity_manager_test suite @Test public void testCreateTaskLayout() { // modifier for validating passed values. @@ -487,6 +489,7 @@ public class ActivityStarterTests extends ActivityTestsBase { /** * Tests activity is cleaned up properly in a task mode violation. */ + @Ignore // TODO(b/119048275): Reenable failing test in activity_manager_test suite @Test public void testTaskModeViolation() { final ActivityDisplay display = mService.mRootActivityContainer.getDefaultDisplay(); @@ -514,6 +517,7 @@ public class ActivityStarterTests extends ActivityTestsBase { /** * This test ensures that activity starts are not being logged when the logging is disabled. */ + @Ignore // TODO(b/119048275): Reenable failing test in activity_manager_test suite @Test public void testActivityStartsLogging_noLoggingWhenDisabled() { doReturn(false).when(mService).isActivityStartsLoggingEnabled(); @@ -531,6 +535,7 @@ public class ActivityStarterTests extends ActivityTestsBase { /** * This test ensures that activity starts are being logged when the logging is enabled. */ + @Ignore // TODO(b/119048275): Reenable failing test in activity_manager_test suite @Test public void testActivityStartsLogging_logsWhenEnabled() { // note: conveniently this package doesn't have any activity visible diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java index f1e22819f501..8f9e96f176c9 100644..100755 --- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java +++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java @@ -129,6 +129,8 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser private static final String USB_STATE_MATCH = "DEVPATH=/devices/virtual/android_usb/android0"; + private static final String USB_STATE_MATCH_SEC = + "DEVPATH=/devices/virtual/android_usb/android1"; private static final String ACCESSORY_START_MATCH = "DEVPATH=/devices/virtual/misc/usb_accessory"; private static final String FUNCTIONS_PATH = @@ -353,6 +355,7 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser // Watch for USB configuration changes mUEventObserver = new UsbUEventObserver(); mUEventObserver.startObserving(USB_STATE_MATCH); + mUEventObserver.startObserving(USB_STATE_MATCH_SEC); mUEventObserver.startObserving(ACCESSORY_START_MATCH); } @@ -1548,6 +1551,10 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser mCurrentFunctions = usbFunctions; if (functions == null || applyAdbFunction(functions) .equals(UsbManager.USB_FUNCTION_NONE)) { + functions = getSystemProperty(getPersistProp(true), + UsbManager.USB_FUNCTION_NONE); + + if (functions.equals(UsbManager.USB_FUNCTION_NONE)) functions = UsbManager.usbFunctionsToString(getChargingFunctions()); } functions = applyAdbFunction(functions); diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java index dcaa49996d0b..f3b734abbcdc 100644 --- a/telecomm/java/android/telecom/Call.java +++ b/telecomm/java/android/telecom/Call.java @@ -406,11 +406,24 @@ public final class Call { */ public static final int CAPABILITY_CAN_PULL_CALL = 0x00800000; + /** + * Add participant in an active or conference call option + * @hide + */ + public static final int CAPABILITY_ADD_PARTICIPANT = 0x02000000; + /** Call supports the deflect feature. */ public static final int CAPABILITY_SUPPORT_DEFLECT = 0x01000000; + /** + * Remote device supports RTT. + * @hide + */ + + public static final int CAPABILITY_SUPPORTS_RTT_REMOTE = 0x04000000; + //****************************************************************************************** - // Next CAPABILITY value: 0x02000000 + // Next CAPABILITY value: 0x08000000 //****************************************************************************************** /** @@ -629,9 +642,15 @@ public final class Call { if (can(capabilities, CAPABILITY_CAN_PULL_CALL)) { builder.append(" CAPABILITY_CAN_PULL_CALL"); } + if (can(capabilities, CAPABILITY_ADD_PARTICIPANT)) { + builder.append(" CAPABILITY_ADD_PARTICIPANT"); + } if (can(capabilities, CAPABILITY_SUPPORT_DEFLECT)) { builder.append(" CAPABILITY_SUPPORT_DEFLECT"); } + if (can(capabilities, CAPABILITY_SUPPORTS_RTT_REMOTE)) { + builder.append(" CAPABILITY_SUPPORTS_RTT_REMOTE"); + } builder.append("]"); return builder.toString(); } diff --git a/telecomm/java/android/telecom/Conference.java b/telecomm/java/android/telecom/Conference.java index a39e885204b7..3847d525bcac 100644 --- a/telecomm/java/android/telecom/Conference.java +++ b/telecomm/java/android/telecom/Conference.java @@ -342,6 +342,14 @@ public abstract class Conference extends Conferenceable { public void onConnectionAdded(Connection connection) {} /** + * Invoked when the conference adds a participant to the conference call. + * + * @param participant The participant to be added with conference call. + * @hide + */ + public void onAddParticipant(String participant) {} + + /** * Sets state to be on hold. */ public final void setOnHold() { diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java index 05d5a13092f1..8b7299fa890f 100644 --- a/telecomm/java/android/telecom/Connection.java +++ b/telecomm/java/android/telecom/Connection.java @@ -336,11 +336,25 @@ public abstract class Connection extends Conferenceable { */ public static final int CAPABILITY_CAN_PULL_CALL = 0x01000000; + /** + * Add participant in an active or conference call option + * + * @hide + */ + public static final int CAPABILITY_ADD_PARTICIPANT = 0x04000000; + /** Call supports the deflect feature. */ public static final int CAPABILITY_SUPPORT_DEFLECT = 0x02000000; + /** + * Remote device supports RTT. + * @hide + */ + + public static final int CAPABILITY_SUPPORTS_RTT_REMOTE = 0x08000000; + //********************************************************************************************** - // Next CAPABILITY value: 0x04000000 + // Next CAPABILITY value: 0x10000000 //********************************************************************************************** /** @@ -505,6 +519,13 @@ public abstract class Connection extends Conferenceable { "android.telecom.extra.ORIGINAL_CONNECTION_ID"; /** + * Integer connection extra key on a {@link Connection} to indicate that there is an updated + * call property + * @hide + */ + public static final String EXTRA_CALL_PROPERTY = + "android.telecom.extra.EXTRA_CALL_PROPERTY"; + /** * Boolean connection extra key set on the extras passed to * {@link Connection#sendConnectionEvent} which indicates that audio is present * on the RTT call when the extra value is true. @@ -628,6 +649,13 @@ public abstract class Connection extends Conferenceable { public static final String EXTRA_SIP_INVITE = "android.telecom.extra.SIP_INVITE"; /** + * Connection event used to inform an {@link InCallService} that the call session property + * has changed + * @hide + */ + public static final String EVENT_CALL_PROPERTY_CHANGED = + "android.telecom.event.EVENT_CALL_PROPERTY_CHANGED"; + /** * Connection event used to inform an {@link InCallService} that the RTT audio indication * has changed. */ @@ -638,6 +666,14 @@ public abstract class Connection extends Conferenceable { private static final boolean PII_DEBUG = Log.isLoggable(android.util.Log.DEBUG); /** + * Indicates that the connection has speech from remote user for a RTT call when set. + * If the property is unset, that indicates silence from remote user + * + * @hide + */ + public static final int PROPERTY_RTT_AUDIO_SPEECH = 0x1; + + /** * Whether the given capabilities support the specified capability. * * @param capabilities A capability bit field. @@ -772,7 +808,9 @@ public abstract class Connection extends Conferenceable { if (can(capabilities, CAPABILITY_SUPPORT_DEFLECT)) { builder.append(isLong ? " CAPABILITY_SUPPORT_DEFLECT" : " sup_def"); } - + if (can(capabilities, CAPABILITY_SUPPORTS_RTT_REMOTE)) { + builder.append(isLong ? " CAPABILITY_SUPPORTS_RTT_REMOTE" : " sup_rtt"); + } builder.append("]"); return builder.toString(); } diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java index 4d5f5e140a87..60a85bcadeb0 100644 --- a/telecomm/java/android/telecom/ConnectionService.java +++ b/telecomm/java/android/telecom/ConnectionService.java @@ -183,6 +183,8 @@ public abstract class ConnectionService extends Service { private static final int MSG_HANDOVER_FAILED = 32; private static final int MSG_HANDOVER_COMPLETE = 33; private static final int MSG_DEFLECT = 34; + //Proprietary values starts after this. + private static final int MSG_ADD_PARTICIPANT_WITH_CONFERENCE = 40; private static Connection sNullConnection; @@ -517,6 +519,14 @@ public abstract class ConnectionService extends Service { } @Override + public void addParticipantWithConference(String callId, String participant) { + SomeArgs args = SomeArgs.obtain(); + args.arg1 = callId; + args.arg2 = participant; + mHandler.obtainMessage(MSG_ADD_PARTICIPANT_WITH_CONFERENCE, args).sendToTarget(); + } + + @Override public void mergeConference(String callId, Session.Info sessionInfo) { Log.startSession(sessionInfo, SESSION_MERGE_CONFERENCE); try { @@ -979,6 +989,17 @@ public abstract class ConnectionService extends Service { } break; } + case MSG_ADD_PARTICIPANT_WITH_CONFERENCE: { + SomeArgs args = (SomeArgs) msg.obj; + try { + String callId = (String) args.arg1; + String participant = (String) args.arg2; + addParticipantWithConference(callId, participant); + } finally { + args.recycle(); + } + break; + } case MSG_CONFERENCE: { SomeArgs args = (SomeArgs) msg.obj; try { @@ -1783,6 +1804,17 @@ public abstract class ConnectionService extends Service { } } + private void addParticipantWithConference(String callId, String participant) { + Log.d(this, "ConnectionService addParticipantWithConference(%s, %s)", participant, callId); + Conference conference = findConferenceForAction(callId, "addParticipantWithConference"); + Connection connection = findConnectionForAction(callId, "addParticipantWithConnection"); + if (connection != getNullConnection()) { + onAddParticipant(connection, participant); + } else if (conference != getNullConference()) { + conference.onAddParticipant(participant); + } + } + private void mergeConference(String callId) { Log.d(this, "mergeConference(%s)", callId); Conference conference = findConferenceForAction(callId, "mergeConference"); @@ -2395,6 +2427,18 @@ public abstract class ConnectionService extends Service { */ public void onConferenceRemoved(Conference conference) {} + /** Add participant with connection. Invoked when user has made a request to add + * participant with specified connection. In response, the participant should add with + * the connection. + * + * @param connection A connection where participant need to add. + * @param participant Address of participant which will be added. + * @return + * + * @hide + */ + public void onAddParticipant(Connection connection, String participant) {} + /** * Indicates that a remote conference has been created for existing {@link RemoteConnection}s. * When this method is invoked, this {@link ConnectionService} should create its own diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java index 6c4b1af8c2a1..27af16b66a11 100644 --- a/telecomm/java/android/telecom/TelecomManager.java +++ b/telecomm/java/android/telecom/TelecomManager.java @@ -176,6 +176,17 @@ public class TelecomManager { "android.telecom.action.DEFAULT_DIALER_CHANGED"; /** + *@hide Broadcast intent action indicating the call type(CS call or Non-CS call). + * The string extra {@link #EXTRA_CALL_TYPE_CS} will contain the + * boolean value true if call is CS call else false. + * + * @see #EXTRA_CALL_TYPE_CS + */ + public static final String ACTION_CALL_TYPE = + "codeaurora.telecom.action.CALL_TYPE"; + + + /** * Extra value used to provide the package name for {@link #ACTION_CHANGE_DEFAULT_DIALER}. */ public static final String EXTRA_CHANGE_DEFAULT_DIALER_PACKAGE_NAME = @@ -360,6 +371,13 @@ public class TelecomManager { "android.telecom.extra.CALL_NETWORK_TYPE"; /** + *@hide Extra value used to provide the call type for {@link #ACTION_CALL_TYPE}. + */ + public static final String EXTRA_CALL_TYPE_CS = + "codeaurora.telecom.extra.CALL_TYPE_CS"; + + + /** * An optional {@link android.content.Intent#ACTION_CALL} intent extra denoting the * package name of the app specifying an alternative gateway for the call. * The value is a string. diff --git a/telecomm/java/com/android/internal/telecom/IConnectionService.aidl b/telecomm/java/com/android/internal/telecom/IConnectionService.aidl index e35093c9656a..acb3e6f1275e 100644 --- a/telecomm/java/com/android/internal/telecom/IConnectionService.aidl +++ b/telecomm/java/com/android/internal/telecom/IConnectionService.aidl @@ -104,6 +104,8 @@ oneway interface IConnectionService { void respondToRttUpgradeRequest(String callId, in ParcelFileDescriptor fromInCall, in ParcelFileDescriptor toInCall, in Session.Info sessionInfo); + void addParticipantWithConference(String callId, String recipients); + void connectionServiceFocusLost(in Session.Info sessionInfo); void connectionServiceFocusGained(in Session.Info sessionInfo); diff --git a/telephony/java/android/provider/Telephony.java b/telephony/java/android/provider/Telephony.java index 15abdb78b214..76a759f2dd7d 100644 --- a/telephony/java/android/provider/Telephony.java +++ b/telephony/java/android/provider/Telephony.java @@ -277,6 +277,13 @@ public final class Telephony { * <p>Type: TEXT</p> */ public static final String CREATOR = "creator"; + + /** + * The priority of the message. + * <P>Type: INTEGER</P> + * @hide + */ + public static final String PRIORITY = "priority"; } /** @@ -373,6 +380,7 @@ public final class Telephony { * @hide */ public static Cursor query(ContentResolver cr, String[] projection) { + android.util.SeempLog.record(10); return cr.query(CONTENT_URI, projection, null, null, DEFAULT_SORT_ORDER); } @@ -383,6 +391,7 @@ public final class Telephony { @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) public static Cursor query(ContentResolver cr, String[] projection, String where, String orderBy) { + android.util.SeempLog.record(10); return cr.query(CONTENT_URI, projection, where, null, orderBy == null ? DEFAULT_SORT_ORDER : orderBy); } @@ -486,6 +495,31 @@ public final class Telephony { public static Uri addMessageToUri(int subId, ContentResolver resolver, Uri uri, String address, String body, String subject, Long date, boolean read, boolean deliveryReport, long threadId) { + return addMessageToUri(subId, resolver, uri, address, body, subject, + date, read, deliveryReport, threadId, -1); + } + + /** + * Add an SMS to the given URI with thread_id specified. + * + * @param resolver the content resolver to use + * @param uri the URI to add the message to + * @param address the address of the sender + * @param body the body of the message + * @param subject the psuedo-subject of the message + * @param date the timestamp for the message + * @param read true if the message has been read, false if not + * @param deliveryReport true if a delivery report was requested, false if not + * @param threadId the thread_id of the message + * @param subId the subscription which the message belongs to + * @param priority the priority of the message + * @return the URI for the new message + * @hide + */ + public static Uri addMessageToUri(int subId, ContentResolver resolver, + Uri uri, String address, String body, String subject, + Long date, boolean read, boolean deliveryReport, + long threadId, int priority) { ContentValues values = new ContentValues(8); Rlog.v(TAG,"Telephony addMessageToUri sub id: " + subId); @@ -497,6 +531,7 @@ public final class Telephony { values.put(READ, read ? Integer.valueOf(1) : Integer.valueOf(0)); values.put(SUBJECT, subject); values.put(BODY, body); + values.put(PRIORITY, priority); if (deliveryReport) { values.put(STATUS, STATUS_PENDING); } @@ -2015,6 +2050,20 @@ public final class Telephony { * <P>Type: INTEGER (boolean)</P> */ public static final String ARCHIVED = "archived"; + + /** + * Indicates the last mms type in the thread. + * <P>Type: TEXT</P> + * @hide + */ + public static final String ATTACHMENT_INFO = "attachment_info"; + + /** + * Indicates whether this thread is a notification thread. + * <P>Type: INTEGER</P> + * @hide + */ + public static final String NOTIFICATION = "notification"; } /** @@ -2170,6 +2219,7 @@ public final class Telephony { */ public static Cursor query( ContentResolver cr, String[] projection) { + android.util.SeempLog.record(10); return cr.query(CONTENT_URI, projection, null, null, DEFAULT_SORT_ORDER); } @@ -2180,6 +2230,7 @@ public final class Telephony { public static Cursor query( ContentResolver cr, String[] projection, String where, String orderBy) { + android.util.SeempLog.record(10); return cr.query(CONTENT_URI, projection, where, null, orderBy == null ? DEFAULT_SORT_ORDER : orderBy); } diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java index 312b31899ad6..15f4eb14a2e9 100644 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -187,6 +187,13 @@ public class CarrierConfigManager { public static final String KEY_SUPPORT_EMERGENCY_SMS_OVER_IMS_BOOL = "support_emergency_sms_over_ims_bool"; + /** + * Indicates if carrier supports emergency sms. + * @hide + */ + public static final String + KEY_EMERGENCY_SMS_SUPPORT_BOOL = "emergency_sms_support_bool"; + /** Flag indicating if the phone is a world phone */ public static final String KEY_WORLD_PHONE_BOOL = "world_phone_bool"; @@ -538,6 +545,14 @@ public class CarrierConfigManager { public static final String KEY_VILTE_DATA_IS_METERED_BOOL = "vilte_data_is_metered_bool"; /** + * Flag indicating whether we should reset UT capability or not for IMS deregistration + * and for IMS feature state not ready + * @hide + */ + public static final String KEY_IGNORE_RESET_UT_CAPABILITY_BOOL = + "ignore_reset_ut_capability_bool"; + + /** * Flag specifying whether WFC over IMS should be available for carrier: independent of * carrier provisioning. If false: hard disabled. If true: then depends on carrier * provisioning, availability etc. @@ -1288,6 +1303,12 @@ public class CarrierConfigManager { "show_precise_failed_cause_bool"; /** + * Flag specifying whether CDMA call waiting and call forwarding are enabled + * @hide + */ + public static final String KEY_CDMA_CW_CF_ENABLED_BOOL = "cdma_cw_cf_enabled_bool"; + + /** * Boolean to decide whether lte is enabled. * @hide */ @@ -1319,8 +1340,8 @@ public class CarrierConfigManager { public static final String KEY_CARRIER_SETTINGS_ACTIVITY_COMPONENT_NAME_STRING = "carrier_settings_activity_component_name_string"; - // These variables are used by the MMS service and exposed through another API, - // SmsManager. The variable names and string values are copied from there. + // These variables are used by the MMS service and exposed through another API, {@link + // SmsManager}. The variable names and string values are copied from there. public static final String KEY_MMS_ALIAS_ENABLED_BOOL = "aliasEnabled"; public static final String KEY_MMS_ALLOW_ATTACH_AUDIO_BOOL = "allowAttachAudio"; public static final String KEY_MMS_APPEND_TRANSACTION_ID_BOOL = "enabledTransID"; @@ -1683,6 +1704,13 @@ public class CarrierConfigManager { "allow_add_call_during_video_call"; /** + * When false, indicates that holding a video call is disabled + * @hide + */ + public static final String KEY_ALLOW_HOLDING_VIDEO_CALL_BOOL = + "allow_holding_video_call"; + + /** * When true, indicates that the HD audio icon in the in-call screen should not be shown for * VoWifi calls. * @hide @@ -2557,6 +2585,7 @@ public class CarrierConfigManager { sDefaults.putBoolean(KEY_CONFIG_TELEPHONY_USE_OWN_NUMBER_FOR_VOICEMAIL_BOOL, false); sDefaults.putBoolean(KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS, true); sDefaults.putBoolean(KEY_VILTE_DATA_IS_METERED_BOOL, true); + sDefaults.putBoolean(KEY_IGNORE_RESET_UT_CAPABILITY_BOOL, false); sDefaults.putBoolean(KEY_CARRIER_WFC_IMS_AVAILABLE_BOOL, false); sDefaults.putBoolean(KEY_CARRIER_WFC_SUPPORTS_WIFI_ONLY_BOOL, false); sDefaults.putBoolean(KEY_CARRIER_DEFAULT_WFC_IMS_ENABLED_BOOL, false); @@ -2591,7 +2620,7 @@ public class CarrierConfigManager { sDefaults.putBoolean(KEY_HIDE_SIM_LOCK_SETTINGS_BOOL, false); sDefaults.putBoolean(KEY_CARRIER_VOLTE_PROVISIONED_BOOL, false); - sDefaults.putBoolean(KEY_CALL_BARRING_VISIBILITY_BOOL, false); + sDefaults.putBoolean(KEY_CALL_BARRING_VISIBILITY_BOOL, true); sDefaults.putBoolean(KEY_CALL_BARRING_SUPPORTS_PASSWORD_CHANGE_BOOL, true); sDefaults.putBoolean(KEY_CALL_BARRING_SUPPORTS_DEACTIVATE_ALL_BOOL, true); sDefaults.putBoolean(KEY_CALL_FORWARDING_VISIBILITY_BOOL, true); @@ -2669,6 +2698,7 @@ public class CarrierConfigManager { // Todo: This will be fixed in Q when IWLAN full refactoring is completed. sDefaults.putStringArray(KEY_CARRIER_METERED_IWLAN_APN_TYPES_STRINGS, new String[]{"default"}); + sDefaults.putBoolean(KEY_CDMA_CW_CF_ENABLED_BOOL, false); sDefaults.putIntArray(KEY_ONLY_SINGLE_DC_ALLOWED_INT_ARRAY, new int[]{ @@ -2809,6 +2839,7 @@ public class CarrierConfigManager { sDefaults.putBoolean(KEY_DROP_VIDEO_CALL_WHEN_ANSWERING_AUDIO_CALL_BOOL, false); sDefaults.putBoolean(KEY_ALLOW_MERGE_WIFI_CALLS_WHEN_VOWIFI_OFF_BOOL, true); sDefaults.putBoolean(KEY_ALLOW_ADD_CALL_DURING_VIDEO_CALL_BOOL, true); + sDefaults.putBoolean(KEY_ALLOW_HOLDING_VIDEO_CALL_BOOL, true); sDefaults.putBoolean(KEY_WIFI_CALLS_CAN_BE_HD_AUDIO, true); sDefaults.putBoolean(KEY_VIDEO_CALLS_CAN_BE_HD_AUDIO, true); sDefaults.putBoolean(KEY_GSM_CDMA_CALLS_CAN_BE_HD_AUDIO, false); diff --git a/telephony/java/android/telephony/DisconnectCause.java b/telephony/java/android/telephony/DisconnectCause.java index f53cb8224706..8f55ce90a65c 100644 --- a/telephony/java/android/telephony/DisconnectCause.java +++ b/telephony/java/android/telephony/DisconnectCause.java @@ -333,12 +333,124 @@ public class DisconnectCause { */ public static final int OTASP_PROVISIONING_IN_PROCESS = 76; + /** @hide */ + public static final int QOS_UNAVAILABLE = 77; + /** @hide */ + public static final int REQUESTED_FACILITY_NOT_SUBSCRIBED = 78; + /** @hide */ + public static final int INCOMING_CALLS_BARRED_WITHIN_CUG = 79; + /** @hide */ + public static final int BEARER_CAPABILITY_UNAVAILABLE = 80; + /** @hide */ + public static final int SERVICE_OPTION_NOT_AVAILABLE = 81; + /** @hide */ + public static final int BEARER_SERVICE_NOT_IMPLEMENTED = 82; + /** @hide */ + public static final int REQUESTED_FACILITY_NOT_IMPLEMENTED = 83; + /** @hide */ + public static final int ONLY_DIGITAL_INFORMATION_BEARER_AVAILABLE = 84; + /** @hide */ + public static final int SERVICE_OR_OPTION_NOT_IMPLEMENTED = 85; + /** @hide */ + public static final int INVALID_TRANSACTION_IDENTIFIER = 86; + /** @hide */ + public static final int USER_NOT_MEMBER_OF_CUG = 87; + /** @hide */ + public static final int INCOMPATIBLE_DESTINATION = 88; + /** @hide */ + public static final int INVALID_TRANSIT_NW_SELECTION = 89; + /** @hide */ + public static final int SEMANTICALLY_INCORRECT_MESSAGE = 90; + /** @hide */ + public static final int INVALID_MANDATORY_INFORMATION = 91; + /** @hide */ + public static final int MESSAGE_TYPE_NON_IMPLEMENTED = 92; + /** @hide */ + public static final int MESSAGE_TYPE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE = 93; + /** @hide */ + public static final int INFORMATION_ELEMENT_NON_EXISTENT = 94; + /** @hide */ + public static final int CONDITIONAL_IE_ERROR = 95; + /** @hide */ + public static final int MESSAGE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE = 96; + /** @hide */ + public static final int RECOVERY_ON_TIMER_EXPIRED = 97; + /** @hide */ + public static final int PROTOCOL_ERROR_UNSPECIFIED = 98; + /** @hide */ + public static final int INTERWORKING_UNSPECIFIED = 99; + /** @hide */ + public static final int LOCAL_LOW_BATTERY = 100; + /** @hide */ + public static final int NO_CIRCUIT_AVAIL = 101; + /** @hide */ + public static final int NO_ROUTE_TO_DESTINATION = 102; + /** @hide */ + public static final int OPERATOR_DETERMINED_BARRING = 103; + /** @hide */ + public static final int CALL_FAIL_NO_USER_RESPONDING = 104; + /** @hide */ + public static final int CALL_FAIL_NO_ANSWER_FROM_USER = 105; + /** @hide */ + public static final int CALL_FAIL_DESTINATION_OUT_OF_ORDER = 106; + /** @hide */ + public static final int BEARER_CAPABILITY_NOT_AUTHORIZED = 107; + /** @hide */ + public static final int CHANNEL_UNACCEPTABLE = 108; + /** @hide */ + public static final int CALL_REJECTED = 109; + /** @hide */ + public static final int NUMBER_CHANGED = 110; + /** @hide */ + public static final int PREEMPTION = 111; + /** @hide */ + public static final int FACILITY_REJECTED = 112; + /** @hide */ + public static final int RESP_TO_STATUS_ENQUIRY = 113; + /** @hide */ + public static final int NETWORK_OUT_OF_ORDER = 114; + /** @hide */ + public static final int TEMPORARY_FAILURE = 115; + /** @hide */ + public static final int SWITCHING_EQUIPMENT_CONGESTION = 116; + /** @hide */ + public static final int ACCESS_INFORMATION_DISCARDED = 117; + /** @hide */ + public static final int REQUESTED_CIRCUIT_OR_CHANNEL_NOT_AVAILABLE = 118; + /** @hide */ + public static final int RESOURCES_UNAVAILABLE_OR_UNSPECIFIED = 119; + + /** + * call failed due to LTE to 3G/2G handover not feasible + * @hide + */ + public static final int HO_NOT_FEASIBLE = 120; + /** @hide */ + public static final int NON_SELECTED_USER_CLEARING = 121; + //********************************************************************************************* // When adding a disconnect type: - // 1) Update toString() with the newly added disconnect type. - // 2) Update android.telecom.DisconnectCauseUtil with any mappings to a telecom.DisconnectCause. + // 1) Please assign the new type the next id value below. + // 2) Increment the next id value below to a new value. + // 3) Update MAXIMUM_VALID_VALUE to the new disconnect type. + // 4) Update toString() with the newly added disconnect type. + // 5) Update android.telecom.DisconnectCauseUtil with any mappings to a telecom.DisconnectCause. + // + // NextId: 122 //********************************************************************************************* + /** + * Smallest valid value for call disconnect codes. + * @hide + */ + public static final int MINIMUM_VALID_VALUE = NOT_DISCONNECTED; + + /** + * Largest valid value for call disconnect codes. + * @hide + */ + public static final int MAXIMUM_VALID_VALUE = NON_SELECTED_USER_CLEARING; + /** Private constructor to avoid class instantiation. */ private DisconnectCause() { // Do nothing. @@ -487,6 +599,32 @@ public class DisconnectCause { return "EMERGENCY_TEMP_FAILURE"; case EMERGENCY_PERM_FAILURE: return "EMERGENCY_PERM_FAILURE"; + case NO_CIRCUIT_AVAIL: + return "NO_CIRCUIT_AVAIL"; + case NO_ROUTE_TO_DESTINATION: + return "NO_ROUTE_TO_DESTINATION"; + case OPERATOR_DETERMINED_BARRING: + return "OPERATOR_DETERMINED_BARRING"; + case CALL_FAIL_NO_USER_RESPONDING: + return "CALL_FAIL_NO_USER_RESPONDING"; + case CALL_FAIL_NO_ANSWER_FROM_USER: + return "CALL_FAIL_NO_ANSWER_FROM_USER"; + case CALL_FAIL_DESTINATION_OUT_OF_ORDER: + return "CALL_FAIL_DESTINATION_OUT_OF_ORDER"; + case BEARER_CAPABILITY_NOT_AUTHORIZED: + return "BEARER_CAPABILITY_NOT_AUTHORIZED"; + case CHANNEL_UNACCEPTABLE: + return "CHANNEL_UNACCEPTABLE"; + case CALL_REJECTED: + return "CALL_REJECTED"; + case NUMBER_CHANGED: + return "NUMBER_CHANGED"; + case PREEMPTION: + return "PREEMPTION"; + case FACILITY_REJECTED: + return "FACILITY_REJECTED"; + case RESP_TO_STATUS_ENQUIRY: + return "RESP_TO_STATUS_ENQUIRY"; case NORMAL_UNSPECIFIED: return "NORMAL_UNSPECIFIED"; case IMS_SIP_ALTERNATE_EMERGENCY_CALL: @@ -501,6 +639,70 @@ public class DisconnectCause { return "TOO_MANY_ONGOING_CALLS"; case OTASP_PROVISIONING_IN_PROCESS: return "OTASP_PROVISIONING_IN_PROCESS"; + case NETWORK_OUT_OF_ORDER: + return "NETWORK_OUT_OF_ORDER"; + case TEMPORARY_FAILURE: + return "TEMPORARY_FAILURE"; + case SWITCHING_EQUIPMENT_CONGESTION: + return "SWITCHING_EQUIPMENT_CONGESTION"; + case ACCESS_INFORMATION_DISCARDED: + return "ACCESS_INFORMATION_DISCARDED"; + case REQUESTED_CIRCUIT_OR_CHANNEL_NOT_AVAILABLE: + return "REQUESTED_CIRCUIT_OR_CHANNEL_NOT_AVAILABLE"; + case RESOURCES_UNAVAILABLE_OR_UNSPECIFIED: + return "RESOURCES_UNAVAILABLE_OR_UNSPECIFIED"; + case QOS_UNAVAILABLE: + return "QOS_UNAVAILABLE"; + case REQUESTED_FACILITY_NOT_SUBSCRIBED: + return "REQUESTED_FACILITY_NOT_SUBSCRIBED"; + case INCOMING_CALLS_BARRED_WITHIN_CUG: + return "INCOMING_CALLS_BARRED_WITHIN_CUG"; + case BEARER_CAPABILITY_UNAVAILABLE: + return "BEARER_CAPABILITY_UNAVAILABLE"; + case SERVICE_OPTION_NOT_AVAILABLE: + return "SERVICE_OPTION_NOT_AVAILABLE"; + case BEARER_SERVICE_NOT_IMPLEMENTED: + return "BEARER_SERVICE_NOT_IMPLEMENTED"; + case REQUESTED_FACILITY_NOT_IMPLEMENTED: + return "REQUESTED_FACILITY_NOT_IMPLEMENTED"; + case ONLY_DIGITAL_INFORMATION_BEARER_AVAILABLE: + return "ONLY_DIGITAL_INFORMATION_BEARER_AVAILABLE"; + case SERVICE_OR_OPTION_NOT_IMPLEMENTED: + return "SERVICE_OR_OPTION_NOT_IMPLEMENTED"; + case INVALID_TRANSACTION_IDENTIFIER: + return "INVALID_TRANSACTION_IDENTIFIER"; + case USER_NOT_MEMBER_OF_CUG: + return "USER_NOT_MEMBER_OF_CUG"; + case INCOMPATIBLE_DESTINATION: + return "INCOMPATIBLE_DESTINATION"; + case INVALID_TRANSIT_NW_SELECTION: + return "INVALID_TRANSIT_NW_SELECTION"; + case SEMANTICALLY_INCORRECT_MESSAGE: + return "SEMANTICALLY_INCORRECT_MESSAGE"; + case INVALID_MANDATORY_INFORMATION: + return "INVALID_MANDATORY_INFORMATION"; + case MESSAGE_TYPE_NON_IMPLEMENTED: + return "MESSAGE_TYPE_NON_IMPLEMENTED"; + case MESSAGE_TYPE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE: + return "MESSAGE_TYPE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE"; + case INFORMATION_ELEMENT_NON_EXISTENT: + return "INFORMATION_ELEMENT_NON_EXISTENT"; + case CONDITIONAL_IE_ERROR: + return "CONDITIONAL_IE_ERROR"; + case MESSAGE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE: + return "MESSAGE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE"; + case RECOVERY_ON_TIMER_EXPIRED: + return "RECOVERY_ON_TIMER_EXPIRED"; + case PROTOCOL_ERROR_UNSPECIFIED: + return "PROTOCOL_ERROR_UNSPECIFIED"; + case INTERWORKING_UNSPECIFIED: + return "INTERWORKING_UNSPECIFIED"; + case LOCAL_LOW_BATTERY: + return "LOCAL_LOW_BATTERY"; + case HO_NOT_FEASIBLE: + return "HO_NOT_FEASIBLE"; + case NON_SELECTED_USER_CLEARING: + return "NON_SELECTED_USER_CLEARING"; default: return "INVALID: " + cause; } diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java index 4dcb410e277a..bea983e92d95 100644 --- a/telephony/java/android/telephony/PhoneNumberUtils.java +++ b/telephony/java/android/telephony/PhoneNumberUtils.java @@ -27,6 +27,7 @@ import android.content.Context; import android.content.Intent; import android.content.res.Resources; import android.database.Cursor; +import android.location.Country; import android.location.CountryDetector; import android.net.Uri; import android.os.SystemProperties; @@ -109,6 +110,7 @@ public class PhoneNumberUtils { private static final String BCD_EF_ADN_EXTENDED = "*#,N;"; private static final String BCD_CALLED_PARTY_EXTENDED = "*#abc"; + private static Country sCountryDetector = null; /* * global-phone-number = ["+"] 1*( DIGIT / written-sep ) * written-sep = ("-"/".") @@ -2169,12 +2171,9 @@ public class PhoneNumberUtils { private static boolean isLocalEmergencyNumberInternal(int subId, String number, Context context, boolean useExactMatch) { - String countryIso; - CountryDetector detector = (CountryDetector) context.getSystemService( - Context.COUNTRY_DETECTOR); - if (detector != null && detector.detectCountry() != null) { - countryIso = detector.detectCountry().getCountryIso(); - } else { + String countryIso = getCountryIso(context); + Rlog.w(LOG_TAG, "isLocalEmergencyNumberInternal" + countryIso); + if (countryIso == null) { Locale locale = context.getResources().getConfiguration().locale; countryIso = locale.getCountry(); Rlog.w(LOG_TAG, "No CountryDetector; falling back to countryIso based on locale: " @@ -2183,6 +2182,28 @@ public class PhoneNumberUtils { return isEmergencyNumberInternal(subId, number, countryIso, useExactMatch); } + private static String getCountryIso(Context context) { + Rlog.w(LOG_TAG, "getCountryIso " + sCountryDetector); + if (sCountryDetector == null) { + CountryDetector detector = (CountryDetector) context.getSystemService( + Context.COUNTRY_DETECTOR); + if (detector != null) { + sCountryDetector = detector.detectCountry(); + } + } + + if (sCountryDetector == null) { + return null; + } else { + return sCountryDetector.getCountryIso(); + } + } + + /** @hide */ + public static void resetCountryDetectorInfo() { + sCountryDetector = null; + } + /** * isVoiceMailNumber: checks a given number against the voicemail * number provided by the RIL and SIM card. The caller must have diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java index 1378bb004696..d54f2bf22a88 100644 --- a/telephony/java/android/telephony/SmsManager.java +++ b/telephony/java/android/telephony/SmsManager.java @@ -324,6 +324,7 @@ public final class SmsManager { public void sendTextMessage( String destinationAddress, String scAddress, String text, PendingIntent sentIntent, PendingIntent deliveryIntent) { + android.util.SeempLog.record_str(75, destinationAddress); sendTextMessageInternal(destinationAddress, scAddress, text, sentIntent, deliveryIntent, true /* persistMessage*/); } @@ -390,6 +391,7 @@ public final class SmsManager { public void sendTextMessageWithSelfPermissions( String destinationAddress, String scAddress, String text, PendingIntent sentIntent, PendingIntent deliveryIntent, boolean persistMessage) { + android.util.SeempLog.record_str(75, destinationAddress); if (TextUtils.isEmpty(destinationAddress)) { throw new IllegalArgumentException("Invalid destinationAddress"); } @@ -843,6 +845,7 @@ public final class SmsManager { public void sendDataMessage( String destinationAddress, String scAddress, short destinationPort, byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent) { + android.util.SeempLog.record_str(73, destinationAddress); if (TextUtils.isEmpty(destinationAddress)) { throw new IllegalArgumentException("Invalid destinationAddress"); } @@ -870,6 +873,7 @@ public final class SmsManager { public void sendDataMessageWithSelfPermissions( String destinationAddress, String scAddress, short destinationPort, byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent) { + android.util.SeempLog.record_str(73, destinationAddress); if (TextUtils.isEmpty(destinationAddress)) { throw new IllegalArgumentException("Invalid destinationAddress"); } @@ -956,8 +960,8 @@ public final class SmsManager { Log.d(TAG, "getSubscriptionId isSmsSimPickActivityNeeded is true"); // ask the user for a default SMS SIM. Intent intent = new Intent(); - intent.setClassName("com.android.settings", - "com.android.settings.sim.SimDialogActivity"); + intent.setClassName("com.qualcomm.qti.simsettings", + "com.qualcomm.qti.simsettings.SimDialogActivity"); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.putExtra(DIALOG_TYPE_KEY, SMS_PICK); try { @@ -1004,6 +1008,7 @@ public final class SmsManager { */ @UnsupportedAppUsage public boolean copyMessageToIcc(byte[] smsc, byte[] pdu,int status) { + android.util.SeempLog.record(79); boolean success = false; if (null == pdu) { @@ -1036,6 +1041,7 @@ public final class SmsManager { @UnsupportedAppUsage public boolean deleteMessageFromIcc(int messageIndex) { + android.util.SeempLog.record(80); boolean success = false; byte[] pdu = new byte[SMS_RECORD_LENGTH-1]; Arrays.fill(pdu, (byte)0xff); @@ -1070,6 +1076,7 @@ public final class SmsManager { */ @UnsupportedAppUsage public boolean updateMessageOnIcc(int messageIndex, int newStatus, byte[] pdu) { + android.util.SeempLog.record(81); boolean success = false; try { @@ -1382,6 +1389,25 @@ public final class SmsManager { } } + /** + * Get the capacity count of sms on Icc card + * + * @return the capacity count of sms on Icc card + * @hide + */ + public int getSmsCapacityOnIcc() { + int ret = -1; + try { + ISms iccISms = getISmsService(); + if (iccISms != null) { + ret = iccISms.getSmsCapacityOnIccForSubscriber(getSubscriptionId()); + } + } catch (RemoteException ex) { + //ignore it + } + return ret; + } + // see SmsMessage.getStatusOnIcc /** Free space (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */ diff --git a/telephony/java/android/telephony/SmsMessage.java b/telephony/java/android/telephony/SmsMessage.java index e40bae18d4f0..61cec7d52951 100644 --- a/telephony/java/android/telephony/SmsMessage.java +++ b/telephony/java/android/telephony/SmsMessage.java @@ -978,4 +978,13 @@ public class SmsMessage { return false; } + + /** + * {@hide} + * Returns the recipient address(receiver) of this SMS message in String form or null if + * unavailable. + */ + public String getRecipientAddress() { + return mWrappedSmsMessage.getRecipientAddress(); + } } diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index 80533535017e..1598ef82fa32 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -1455,6 +1455,7 @@ public class TelephonyManager { @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getDeviceId(int slotIndex) { // FIXME this assumes phoneId == slotIndex + android.util.SeempLog.record_str(8, ""+slotIndex); try { IPhoneSubInfo info = getSubscriberInfo(); if (info == null) @@ -1670,6 +1671,7 @@ public class TelephonyManager { android.Manifest.permission.ACCESS_FINE_LOCATION }) public CellLocation getCellLocation() { + android.util.SeempLog.record(49); try { ITelephony telephony = getITelephony(); if (telephony == null) { @@ -1761,6 +1763,7 @@ public class TelephonyManager { @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION) public List<NeighboringCellInfo> getNeighboringCellInfo() { + android.util.SeempLog.record(50); try { ITelephony telephony = getITelephony(); if (telephony == null) @@ -3095,6 +3098,7 @@ public class TelephonyManager { @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @UnsupportedAppUsage public String getSimSerialNumber(int subId) { + android.util.SeempLog.record_str(388, ""+subId); try { IPhoneSubInfo info = getSubscriberInfo(); if (info == null) @@ -3309,6 +3313,7 @@ public class TelephonyManager { @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) public String getSubscriberId(int subId) { + android.util.SeempLog.record_str(389, ""+subId); try { IPhoneSubInfo info = getSubscriberInfo(); if (info == null) @@ -3540,6 +3545,7 @@ public class TelephonyManager { }) @UnsupportedAppUsage public String getLine1Number(int subId) { + android.util.SeempLog.record_str(9, ""+subId); String number = null; try { ITelephony telephony = getITelephony(); diff --git a/telephony/java/android/telephony/ims/ImsCallProfile.java b/telephony/java/android/telephony/ims/ImsCallProfile.java index 59167b7d5bba..1eb505956603 100644 --- a/telephony/java/android/telephony/ims/ImsCallProfile.java +++ b/telephony/java/android/telephony/ims/ImsCallProfile.java @@ -109,6 +109,11 @@ public final class ImsCallProfile implements Parcelable { * VideoShare (video RX one way) */ public static final int CALL_TYPE_VS_RX = 10; + /** + * Unknown (audio / video inactive) + * @hide + */ + public static final int CALL_TYPE_UNKNOWN = (-1); /** * Extra properties for IMS call. diff --git a/telephony/java/android/telephony/ims/ImsCallSession.java b/telephony/java/android/telephony/ims/ImsCallSession.java index 47c468121484..16018978fb8d 100644 --- a/telephony/java/android/telephony/ims/ImsCallSession.java +++ b/telephony/java/android/telephony/ims/ImsCallSession.java @@ -446,6 +446,16 @@ public class ImsCallSession { } /** + * While in call, there has been a change in the call session + * property. + * @param property - an integer containing masks for different properties + * {e.g. @see Connection#PROPERTY_RTT_AUDIO_SPEECH} + */ + public void callSessionPropertyChanged(int property) { + // no-op + } + + /** * While in call, there has been a change in RTT audio indicator. */ public void callSessionRttAudioIndicatorChanged(ImsStreamMediaProfile profile) { @@ -1414,6 +1424,19 @@ public class ImsCallSession { } /** + * While in call, there has been a change in the call session + * property. + * @param property - an integer containing masks for different properties + * {e.g. @see Connection#PROPERTY_RTT_AUDIO_SPEECH} + */ + @Override + public void callSessionPropertyChanged(int property) { + if (mListener != null) { + mListener.callSessionPropertyChanged(property); + } + } + + /** * While in call, there has been a change in RTT audio indicator. */ @Override diff --git a/telephony/java/android/telephony/ims/ImsCallSessionListener.java b/telephony/java/android/telephony/ims/ImsCallSessionListener.java index 337375ac51c3..6cf5a193889e 100644 --- a/telephony/java/android/telephony/ims/ImsCallSessionListener.java +++ b/telephony/java/android/telephony/ims/ImsCallSessionListener.java @@ -602,6 +602,20 @@ public class ImsCallSessionListener { } /** + * While in call, there has been a change in the call session + * property. + * @param property - an integer containing masks for different properties + * {e.g. @see Connection#PROPERTY_RTT_AUDIO_SPEECH} + */ + public void callSessionPropertyChanged(int property) { + try { + mListener.callSessionPropertyChanged(property); + } catch (RemoteException e) { + throw new RuntimeException(e); + } + } + + /** * While in call, there has been a change in RTT audio indicator. * * @param profile updated ImsStreamMediaProfile diff --git a/telephony/java/android/telephony/ims/aidl/IImsCallSessionListener.aidl b/telephony/java/android/telephony/ims/aidl/IImsCallSessionListener.aidl index d64e67a40201..71f1aa45a79d 100644 --- a/telephony/java/android/telephony/ims/aidl/IImsCallSessionListener.aidl +++ b/telephony/java/android/telephony/ims/aidl/IImsCallSessionListener.aidl @@ -141,6 +141,14 @@ oneway interface IImsCallSessionListener { */ void callSessionRttMessageReceived(in String rttMessage); + /* + * While in call, there has been a change in the call session + * property. + * @param property - an integer containing masks for different properties + * {e.g. @see Connection#PROPERTY_RTT_AUDIO_SPEECH} + */ + void callSessionPropertyChanged(in int property); + /** * While in call, there has been a change in RTT audio indicator. * @param profile updated ImsStreamMediaProfile diff --git a/telephony/java/android/telephony/ims/compat/stub/ImsCallSessionImplBase.java b/telephony/java/android/telephony/ims/compat/stub/ImsCallSessionImplBase.java index 38566fe6d811..6c1b5d40813c 100644 --- a/telephony/java/android/telephony/ims/compat/stub/ImsCallSessionImplBase.java +++ b/telephony/java/android/telephony/ims/compat/stub/ImsCallSessionImplBase.java @@ -592,6 +592,11 @@ public class ImsCallSessionImplBase extends IImsCallSession.Stub { } @Override + public void callSessionPropertyChanged(int property) throws RemoteException { + mNewListener.callSessionPropertyChanged(property); + } + + @Override public void callSessionRttAudioIndicatorChanged(ImsStreamMediaProfile profile) throws RemoteException { mNewListener.callSessionRttAudioIndicatorChanged(profile); diff --git a/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java b/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java index fcd7faf73bb8..85ab40907922 100644 --- a/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java +++ b/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java @@ -52,6 +52,12 @@ public class ImsUtImplBase { } @Override + public int queryCFForServiceClass(int condition, String number, int serviceClass) throws + RemoteException { + return ImsUtImplBase.this.queryCFForServiceClass(condition, number, serviceClass); + } + + @Override public int queryCallWaiting() throws RemoteException { return ImsUtImplBase.this.queryCallWaiting(); } @@ -169,6 +175,14 @@ public class ImsUtImplBase { } /** + * Retrieves the configuration of the call forward for specified service class. + */ + public int queryCFForServiceClass(int condition, String number, + int serviceClass) { + return -1; + } + + /** * Retrieves the configuration of the call waiting. */ public int queryCallWaiting() { diff --git a/telephony/java/com/android/ims/ImsUtInterface.java b/telephony/java/com/android/ims/ImsUtInterface.java index c9d440551631..3abc7c6c5081 100644 --- a/telephony/java/com/android/ims/ImsUtInterface.java +++ b/telephony/java/com/android/ims/ImsUtInterface.java @@ -124,6 +124,12 @@ public interface ImsUtInterface { public void queryCallForward(int condition, String number, Message result); /** + * Retrieves the configuration of the call forward for the specified service class. + * The return value of ((AsyncResult)result.obj) is an array of {@link ImsCallForwardInfo}. + */ + public void queryCallForward(int condition, String number, + int serviceClass, Message result); + /** * Retrieves the configuration of the call waiting. * The return value of ((AsyncResult)result.obj) is an array of {@link ImsSsInfo}. */ diff --git a/telephony/java/com/android/ims/internal/IImsCallSessionListener.aidl b/telephony/java/com/android/ims/internal/IImsCallSessionListener.aidl index 579369f4b549..ffa36537ea97 100644 --- a/telephony/java/com/android/ims/internal/IImsCallSessionListener.aidl +++ b/telephony/java/com/android/ims/internal/IImsCallSessionListener.aidl @@ -155,6 +155,14 @@ oneway interface IImsCallSessionListener { */ void callSessionRttMessageReceived(in String rttMessage); + /* + * While in call, there has been a change in the call session + * property. + * @param property - an integer containing masks for different properties + * {e.g. @see Connection#PROPERTY_RTT_AUDIO_SPEECH} + */ + void callSessionPropertyChanged(in int property); + /** * While in call, there has been a change in RTT audio indicator. * @param profile updated ImsStreamMediaProfile diff --git a/telephony/java/com/android/ims/internal/IImsUt.aidl b/telephony/java/com/android/ims/internal/IImsUt.aidl index 4f97cc5cfb22..ca10b2d1a345 100644 --- a/telephony/java/com/android/ims/internal/IImsUt.aidl +++ b/telephony/java/com/android/ims/internal/IImsUt.aidl @@ -122,4 +122,12 @@ interface IImsUt { */ int updateCallBarringForServiceClass(int cbType, int action, in String[] barrList, int serviceClass); + + /** + * Retrieves the configuration of the call forward for specified service class. + * Returns an integer value to indicate the requestId of the UT request. + * -1 is returned if the "condition" is invalid for the queryCallForward, + * otherwise, integer greater than -1 will be returned. + */ + int queryCFForServiceClass(int condition, String number, int serviceClass); } diff --git a/telephony/java/com/android/ims/internal/uce/common/StatusCode.java b/telephony/java/com/android/ims/internal/uce/common/StatusCode.java index 3921cfbbfce7..7250eee70ecb 100644 --- a/telephony/java/com/android/ims/internal/uce/common/StatusCode.java +++ b/telephony/java/com/android/ims/internal/uce/common/StatusCode.java @@ -64,6 +64,10 @@ public class StatusCode implements Parcelable { public static final int UCE_NO_CHANGE_IN_CAP = 13; /** Service is unknown. */ public static final int UCE_SERVICE_UNKNOWN = 14; + /** Service cannot support Invalid Feature Tag */ + public static final int UCE_INVALID_FEATURE_TAG = 15; + /** Service is Available */ + public static final int UCE_SERVICE_AVAILABLE = 16; private int mStatusCode = UCE_SUCCESS; diff --git a/telephony/java/com/android/ims/internal/uce/uceservice/IUceService.aidl b/telephony/java/com/android/ims/internal/uce/uceservice/IUceService.aidl index 43f83cd94d57..1fb8513d410a 100644 --- a/telephony/java/com/android/ims/internal/uce/uceservice/IUceService.aidl +++ b/telephony/java/com/android/ims/internal/uce/uceservice/IUceService.aidl @@ -66,10 +66,30 @@ interface IUceService * service the client created. * * @return optionsServiceHandle + * * @hide + * + * @deprecated This is replaced with new API createOptionsServiceForSubscription() */ int createOptionsService(IOptionsListener optionsListener, inout UceLong optionsServiceListenerHdl); + /** + * Creates a options service for Capability Discovery. + * @param optionsListener IOptionsListener object. + * @param optionsServiceListenerHdl wrapper for client's listener handle to be stored. + * @param iccId the ICC-ID derived from SubscriptionInfo for the Service requested + * + * The service will fill UceLong.mUceLong with presenceListenerHandle allocated and + * used to validate callbacks received in IPresenceListener are indeed from the + * service the client created. + * + * @return optionsServiceHandle + * + * @hide + */ + int createOptionsServiceForSubscription(IOptionsListener optionsListener, + inout UceLong optionsServiceListenerHdl, + in String iccId); /** * Destroys a Options service. @@ -89,14 +109,36 @@ interface IUceService * service the client created. * * @return presenceServiceHdl + * * @hide + * + * @deprecated This is replaced with new API createPresenceServiceForSubscription() */ int createPresenceService(IPresenceListener presenceServiceListener, inout UceLong presenceServiceListenerHdl); + /** + * Creates a presence service. + * @param presenceServiceListener IPresenceListener object + * @param presenceServiceListenerHdl wrapper for client's listener handle to be stored. + * @param iccId the ICC-ID derived from SubscriptionInfo for the Service requested + * + * The service will fill UceLong.mUceLong with presenceListenerHandle allocated and + * used to validate callbacks received in IPresenceListener are indeed from the + * service the client created. + * + * @return presenceServiceHdl + * + * @hide + */ + int createPresenceServiceForSubscription(IPresenceListener presenceServiceListener, + inout UceLong presenceServiceListenerHdl, + in String iccId); /** * Destroys a presence service. + * * @param presenceServiceHdl handle returned during createPresenceService() + * * @hide */ void destroyPresenceService(int presenceServiceHdl); @@ -105,23 +147,55 @@ interface IUceService /** * Query the UCE Service for information to know whether the is registered. + * * @return boolean, true if Registered to for network events else false. + * * @hide */ boolean getServiceStatus(); /** * Query the UCE Service for presence Service. + * * @return IPresenceService object. + * * @hide + * + * @deprecated use API getPresenceServiceForSubscription() */ IPresenceService getPresenceService(); /** + * Query the UCE Service for presence Service. + * + * @param iccId the ICC-ID derived from SubscriptionInfo for the Service requested + * + * @return IPresenceService object. + * + * @hide + */ + IPresenceService getPresenceServiceForSubscription(in String iccId); + + /** * Query the UCE Service for options service object. + * * @return IOptionsService object. + * + * @deprecated use API getOptionsServiceForSubscription() + * * @hide */ IOptionsService getOptionsService(); + /** + * Query the UCE Service for options service object. + * + * @param iccId the ICC-ID derived from SubscriptionInfo for the Service requested + * + * @return IOptionsService object. + * + * @hide + */ + IOptionsService getOptionsServiceForSubscription(in String iccId); + } diff --git a/telephony/java/com/android/ims/internal/uce/uceservice/UceServiceBase.java b/telephony/java/com/android/ims/internal/uce/uceservice/UceServiceBase.java index 3660e039582d..ceb191910427 100644 --- a/telephony/java/com/android/ims/internal/uce/uceservice/UceServiceBase.java +++ b/telephony/java/com/android/ims/internal/uce/uceservice/UceServiceBase.java @@ -56,6 +56,14 @@ public abstract class UceServiceBase { return onCreateOptionsService(optionsListener, optionsServiceListenerHdl); } + @Override + public int createOptionsServiceForSubscription(IOptionsListener optionsListener, + UceLong optionsServiceListenerHdl, + String iccId) { + return onCreateOptionsService(optionsListener, optionsServiceListenerHdl, + iccId); + } + @Override public void destroyOptionsService(int optionsServiceHandle) { @@ -70,6 +78,14 @@ public abstract class UceServiceBase { } @Override + public int createPresenceServiceForSubscription(IPresenceListener presServiceListener, + UceLong presServiceListenerHdl, + String iccId) { + return onCreatePresService(presServiceListener, presServiceListenerHdl, + iccId); + } + + @Override public void destroyPresenceService(int presServiceHdl) { onDestroyPresService(presServiceHdl); } @@ -85,9 +101,19 @@ public abstract class UceServiceBase { } @Override + public IPresenceService getPresenceServiceForSubscription(String iccId) { + return onGetPresenceService(iccId); + } + + @Override public IOptionsService getOptionsService() { return onGetOptionsService(); } + + @Override + public IOptionsService getOptionsServiceForSubscription(String iccId) { + return onGetOptionsService(iccId); + } } private UceServiceBinder mBinder; @@ -120,6 +146,13 @@ public abstract class UceServiceBase { return 0; } + protected int onCreateOptionsService(IOptionsListener optionsListener, + UceLong optionsServiceListenerHdl, + String iccId) { + //no-op + return 0; + } + protected void onDestroyOptionsService(int cdServiceHandle) { //no-op return; @@ -131,6 +164,13 @@ public abstract class UceServiceBase { return 0; } + protected int onCreatePresService(IPresenceListener presServiceListener, + UceLong presServiceListenerHdl, + String iccId) { + //no-op + return 0; + } + protected void onDestroyPresService(int presServiceHdl) { //no-op return; @@ -146,8 +186,18 @@ public abstract class UceServiceBase { return null; } + protected IPresenceService onGetPresenceService(String iccId) { + //no-op + return null; + } + protected IOptionsService onGetOptionsService () { //no-op return null; } + + protected IOptionsService onGetOptionsService (String iccId) { + //no-op + return null; + } } diff --git a/telephony/java/com/android/internal/telephony/CallerInfo.java b/telephony/java/com/android/internal/telephony/CallerInfo.java index 13539b855de2..b1aec9c8f236 100644 --- a/telephony/java/com/android/internal/telephony/CallerInfo.java +++ b/telephony/java/com/android/internal/telephony/CallerInfo.java @@ -182,6 +182,7 @@ public class CallerInfo { * number. The returned CallerInfo is null if no number is supplied. */ public static CallerInfo getCallerInfo(Context context, Uri contactRef, Cursor cursor) { + android.util.SeempLog.record_uri(12, contactRef); CallerInfo info = new CallerInfo(); info.photoResource = 0; info.phoneLabel = null; @@ -368,6 +369,7 @@ public class CallerInfo { */ @UnsupportedAppUsage public static CallerInfo getCallerInfo(Context context, String number, int subId) { + android.util.SeempLog.record_str(12, "number="+number+",subId="+subId); if (TextUtils.isEmpty(number)) { return null; diff --git a/telephony/java/com/android/internal/telephony/ISms.aidl b/telephony/java/com/android/internal/telephony/ISms.aidl index a4eb424ab66e..183b07cecd65 100644 --- a/telephony/java/com/android/internal/telephony/ISms.aidl +++ b/telephony/java/com/android/internal/telephony/ISms.aidl @@ -560,4 +560,12 @@ interface ISms { * @param intent PendingIntent to be sent when an SMS is received containing the token. */ String createAppSpecificSmsToken(int subId, String callingPkg, in PendingIntent intent); + + /** + * Get the capacity count of sms on Icc card. + * + * @param subId for subId which getSmsCapacityOnIcc is queried. + * @return capacity of ICC + */ + int getSmsCapacityOnIccForSubscriber(int subId); } diff --git a/telephony/java/com/android/internal/telephony/ISmsImplBase.java b/telephony/java/com/android/internal/telephony/ISmsImplBase.java index 1cdf44d897b2..676a55008da9 100644 --- a/telephony/java/com/android/internal/telephony/ISmsImplBase.java +++ b/telephony/java/com/android/internal/telephony/ISmsImplBase.java @@ -188,4 +188,9 @@ public class ISmsImplBase extends ISms.Stub { public String createAppSpecificSmsToken(int subId, String callingPkg, PendingIntent intent) { throw new UnsupportedOperationException(); } + + @Override + public int getSmsCapacityOnIccForSubscriber(int subId) { + throw new UnsupportedOperationException(); + } } diff --git a/telephony/java/com/android/internal/telephony/ISmsSecurityAgent.aidl b/telephony/java/com/android/internal/telephony/ISmsSecurityAgent.aidl new file mode 100644 index 000000000000..3b525292cb2d --- /dev/null +++ b/telephony/java/com/android/internal/telephony/ISmsSecurityAgent.aidl @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2016, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.android.internal.telephony; + +import com.android.internal.telephony.SmsAuthorizationRequest; + +/** + * ISmsSecurityAgent enhances the security of outgoing SMS messages by allowing trusted system + * components to inspect and authorize or reject outgoing SMS messages. + * + * @hide + **/ +interface ISmsSecurityAgent { + /** + * Called when a SMS message is queued for dispatch allowing a registered + * agent to decide on whether to accept/reject the request to send an SMS message. + * <b>Unless the agent rejects the request within the OEM specific timeout, the SMS + * will be sent.</b> + * @param request the object containing information regarding the message and + * through which the agent can accept/reject the request. + */ + void onAuthorize(in SmsAuthorizationRequest request); + +} diff --git a/telephony/java/com/android/internal/telephony/ISmsSecurityService.aidl b/telephony/java/com/android/internal/telephony/ISmsSecurityService.aidl new file mode 100644 index 000000000000..e479f0c1f678 --- /dev/null +++ b/telephony/java/com/android/internal/telephony/ISmsSecurityService.aidl @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2016, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.android.internal.telephony; + +import com.android.internal.telephony.ISmsSecurityAgent; +import com.android.internal.telephony.SmsAuthorizationRequest; + +/** + * ISmsSecurityService exposes a service that monitors the dispatch of outgoing SMS messages + * and notifies a registered ISmsSecurityAgent in order to authorize or reject the dispatch + * of each outgoing SMS message. + * + * @hide + */ +interface ISmsSecurityService { + /** + * Registers an agent in order to receive requests for outgoing SMS messages on which + * it can accept or reject the request for the dispatch of each SMS message. + * <b>Only one agent can be registered at one time.</b> + * @param agent the agent to be registered. + * @return true if the registration succeeds, false otherwise. + */ + boolean register(in ISmsSecurityAgent agent); + + /** + * Unregisters the previously registered agent and causes the security + * service to no longer rely on the agent for a decision regarding + * successive SMS messages being dispatched allowing all successive messages to be dispatched. + * + * @param agent the agent to be unregistered. + * @return true if the unregistration succeeds, false otherwise. + */ + boolean unregister(in ISmsSecurityAgent agent); + + /** + * Allows the registered ISmsSecurityAgent implementation to asynchronously send a response + * on whether it will accept/reject the dispatch of the SMS message. + * <b>If the agent responds after the OEM defined timeout it may not be able to + * interfere on whether the SMS was sent or not.</b> + * @param request the request related to an outgoing SMS message to accept/reject. + * @param accepted true to accept, false to reject. + * return true if the response took effect, false if a response has already been sent for this + * request or an OEM specific timeout already happened. + */ + boolean sendResponse(in SmsAuthorizationRequest request, boolean authorized); +} diff --git a/telephony/java/com/android/internal/telephony/SmsAuthorizationRequest.aidl b/telephony/java/com/android/internal/telephony/SmsAuthorizationRequest.aidl new file mode 100644 index 000000000000..a2f7020f9b90 --- /dev/null +++ b/telephony/java/com/android/internal/telephony/SmsAuthorizationRequest.aidl @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2016, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.android.internal.telephony; + +/** @hide */ +parcelable SmsAuthorizationRequest; diff --git a/telephony/java/com/android/internal/telephony/SmsAuthorizationRequest.java b/telephony/java/com/android/internal/telephony/SmsAuthorizationRequest.java new file mode 100644 index 000000000000..bc64fa802903 --- /dev/null +++ b/telephony/java/com/android/internal/telephony/SmsAuthorizationRequest.java @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2016, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.android.internal.telephony; + +import android.os.IBinder; +import android.os.Parcel; +import android.os.Parcelable; +import android.os.RemoteException; + +/** + * This class represents a request from the {@link ISmsSecurityService} to trusted parties + * in order to allow third party components to participate in the decision process to accept + * or reject a request to send an SMS message. + * + * @hide + */ +public class SmsAuthorizationRequest implements Parcelable { + + private final ISmsSecurityService service; + + private final IBinder token; + + public final String packageName; + + public final String destinationAddress; + + public final String message; + + public SmsAuthorizationRequest(final Parcel source) { + this.service = ISmsSecurityService.Stub.asInterface(source.readStrongBinder()); + this.token = source.readStrongBinder(); + this.packageName = source.readString(); + this.destinationAddress = source.readString(); + this.message = source.readString(); + } + + public SmsAuthorizationRequest(final ISmsSecurityService service, + final IBinder binderToken, + final String packageName, + final String destinationAddress, + final String message) { + this.service = service; + this.token = binderToken; + this.packageName = packageName; + this.destinationAddress = destinationAddress; + this.message = message; + } + + @Override + public void writeToParcel(final Parcel dest, final int flags) { + dest.writeStrongBinder(service.asBinder()); + dest.writeStrongBinder(token); + dest.writeString(packageName); + dest.writeString(destinationAddress); + dest.writeString(message); + } + + @Override + public int describeContents() { + return 0; + } + + public static Parcelable.Creator<SmsAuthorizationRequest> CREATOR = + new Creator<SmsAuthorizationRequest>() { + @Override + public SmsAuthorizationRequest[] newArray(final int size) { + return new SmsAuthorizationRequest[size]; + } + + @Override + public SmsAuthorizationRequest createFromParcel(final Parcel source) { + return new SmsAuthorizationRequest(source); + } + }; + + public void accept() throws RemoteException{ + service.sendResponse(this, true); + } + + public void reject() throws RemoteException { + service.sendResponse(this, false); + } + + public IBinder getToken() { + return token; + } + + @Override + public String toString() { + return String.format("[%s] (%s) # %s", + this.packageName, + this.destinationAddress, + this.message); + } +} diff --git a/telephony/java/com/android/internal/telephony/SmsMessageBase.java b/telephony/java/com/android/internal/telephony/SmsMessageBase.java index 190eac4d8c02..ffdc4b676f90 100644 --- a/telephony/java/com/android/internal/telephony/SmsMessageBase.java +++ b/telephony/java/com/android/internal/telephony/SmsMessageBase.java @@ -41,6 +41,9 @@ public abstract class SmsMessageBase { @UnsupportedAppUsage protected SmsAddress mOriginatingAddress; + /** {@hide} The address of the receiver */ + protected SmsAddress mRecipientAddress; + /** {@hide} The message body as a string. May be null if the message isn't text */ @UnsupportedAppUsage protected String mMessageBody; @@ -457,4 +460,17 @@ public abstract class SmsMessageBase { return ted; } + + /** + * {@hide} + * Returns the receiver address of this SMS message in String + * form or null if unavailable + */ + public String getRecipientAddress() { + if (mRecipientAddress == null) { + return null; + } + + return mRecipientAddress.getAddressString(); + } } diff --git a/telephony/java/com/android/internal/telephony/TelephonyProperties.java b/telephony/java/com/android/internal/telephony/TelephonyProperties.java index 6567ea764b50..1d142e7f9f59 100644 --- a/telephony/java/com/android/internal/telephony/TelephonyProperties.java +++ b/telephony/java/com/android/internal/telephony/TelephonyProperties.java @@ -218,4 +218,34 @@ public interface TelephonyProperties */ static final String PROPERTY_VIDEOCALL_AUDIO_OUTPUT = "persist.radio.call.audio.output"; + /** + * Used when Presence app sends Dial intent with specific schema + * If true: skip schema parsing and use Tel schema + * If false: parse schema + */ + static final String EXTRA_SKIP_SCHEMA_PARSING = + "org.codeaurora.extra.SKIP_SCHEMA_PARSING"; + + /** + * For Group Conference Calling + * If true: isConferenceUri in Dial is set to true, + * which indicates that Dial is for Conference Calling + * If false: above is set to false + */ + static final String EXTRAS_IS_CONFERENCE_URI = "isConferenceUri"; + + /** + * For Group Conference Dialing Feature + * If true: Dial intent triggered from Group Conference Calling screen + * if false: normal dial + */ + static final String EXTRA_DIAL_CONFERENCE_URI = + "org.codeaurora.extra.DIAL_CONFERENCE_URI"; + + /** + * For Add Participant Feature + * If true: Dial intent triggered from Dialpad is for AddParticipant + * if false: normal dial + */ + static final String ADD_PARTICIPANT_KEY = "add_participant"; } diff --git a/telephony/java/com/android/internal/telephony/cdma/BearerData.java b/telephony/java/com/android/internal/telephony/cdma/BearerData.java index a4cd56b9e3e2..3b2221113273 100644 --- a/telephony/java/com/android/internal/telephony/cdma/BearerData.java +++ b/telephony/java/com/android/internal/telephony/cdma/BearerData.java @@ -596,6 +596,45 @@ public final class BearerData { System.arraycopy(payload, 0, uData.payload, udhBytes, payload.length); } + private static void encode7bitAsciiEms(UserData uData, byte[] udhData, boolean force) + throws CodingException + { + try { + Rlog.d(LOG_TAG, "encode7bitAsciiEms"); + int udhBytes = udhData.length + 1; // Add length octet. + int udhSeptets = ((udhBytes * 8) + 6) / 7; + int paddingBits = (udhSeptets * 7) - (udhBytes * 8); + String msg = uData.payloadStr; + byte[] payload ; + int msgLen = msg.length(); + BitwiseOutputStream outStream = new BitwiseOutputStream(msgLen + + (paddingBits > 0 ? 1 : 0)); + outStream.write(paddingBits, 0); + for (int i = 0; i < msgLen; i++) { + int charCode = UserData.charToAscii.get(msg.charAt(i), -1); + if (charCode == -1) { + if (force) { + outStream.write(7, UserData.UNENCODABLE_7_BIT_CHAR); + } else { + throw new CodingException("cannot ASCII encode (" + msg.charAt(i) + ")"); + } + } else { + outStream.write(7, charCode); + } + } + payload = outStream.toByteArray(); + uData.msgEncoding = UserData.ENCODING_7BIT_ASCII; + uData.msgEncodingSet = true; + uData.numFields = udhSeptets + uData.payloadStr.length(); + uData.payload = new byte[udhBytes + payload.length]; + uData.payload[0] = (byte)udhData.length; + System.arraycopy(udhData, 0, uData.payload, 1, udhData.length); + System.arraycopy(payload, 0, uData.payload, udhBytes, payload.length); + } catch (BitwiseOutputStream.AccessException ex) { + throw new CodingException("7bit ASCII encode failed: " + ex); + } + } + private static void encodeEmsUserDataPayload(UserData uData) throws CodingException { @@ -605,6 +644,8 @@ public final class BearerData { encode7bitEms(uData, headerData, true); } else if (uData.msgEncoding == UserData.ENCODING_UNICODE_16) { encode16bitEms(uData, headerData); + } else if (uData.msgEncoding == UserData.ENCODING_7BIT_ASCII) { + encode7bitAsciiEms(uData, headerData, true); } else { throw new CodingException("unsupported EMS user data encoding (" + uData.msgEncoding + ")"); @@ -1056,15 +1097,19 @@ public final class BearerData { throws CodingException { try { - offset *= 8; + int offsetBits = offset * 8; + int offsetSeptets = (offsetBits + 6) / 7; + numFields -= offsetSeptets; + int paddingBits = (offsetSeptets * 7) - offsetBits; + StringBuffer strBuf = new StringBuffer(numFields); BitwiseInputStream inStream = new BitwiseInputStream(data); - int wantedBits = (offset * 8) + (numFields * 7); + int wantedBits = (offsetSeptets * 7) + (numFields * 7); if (inStream.available() < wantedBits) { throw new CodingException("insufficient data (wanted " + wantedBits + " bits, but only have " + inStream.available() + ")"); } - inStream.skip(offset); + inStream.skip(offsetBits + paddingBits); for (int i = 0; i < numFields; i++) { int charCode = inStream.read(7); if ((charCode >= UserData.ASCII_MAP_BASE_INDEX) && diff --git a/telephony/java/com/android/internal/telephony/cdma/SmsEnvelope.java b/telephony/java/com/android/internal/telephony/cdma/SmsEnvelope.java index f73df56a9ba6..d252f0f114eb 100644 --- a/telephony/java/com/android/internal/telephony/cdma/SmsEnvelope.java +++ b/telephony/java/com/android/internal/telephony/cdma/SmsEnvelope.java @@ -38,6 +38,7 @@ public final class SmsEnvelope { static public final int TELESERVICE_WAP = 0x1004; static public final int TELESERVICE_WEMT = 0x1005; static public final int TELESERVICE_SCPT = 0x1006; + static public final int TELESERVICE_CT_WAP = 0xFDEA; /** * The following are defined as extensions to the standard teleservices diff --git a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java index 964a31304db5..ea44d3947623 100644..100755 --- a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java +++ b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java @@ -614,6 +614,10 @@ public class SmsMessage extends SmsMessageBase { } addr.origBytes = data; Rlog.i(LOG_TAG, "Originating Addr=" + addr.toString()); + if (parameterId == DESTINATION_ADDRESS) { + env.destAddress = addr; + mRecipientAddress = addr; + } break; case ORIGINATING_SUB_ADDRESS: case DESTINATION_SUB_ADDRESS: @@ -732,7 +736,8 @@ public class SmsMessage extends SmsMessageBase { status = mBearerData.errorClass << 8; status |= mBearerData.messageStatus; } - } else if (mBearerData.messageType != BearerData.MESSAGE_TYPE_DELIVER) { + } else if (mBearerData.messageType != BearerData.MESSAGE_TYPE_DELIVER + && mBearerData.messageType != BearerData.MESSAGE_TYPE_SUBMIT) { throw new RuntimeException("Unsupported message type: " + mBearerData.messageType); } @@ -864,8 +869,9 @@ public class SmsMessage extends SmsMessageBase { } if (encodedBearerData == null) return null; - int teleservice = bearerData.hasUserDataHeader ? - SmsEnvelope.TELESERVICE_WEMT : SmsEnvelope.TELESERVICE_WMT; + int teleservice = (bearerData.hasUserDataHeader + && userData.msgEncoding != UserData.ENCODING_7BIT_ASCII) + ? SmsEnvelope.TELESERVICE_WEMT : SmsEnvelope.TELESERVICE_WMT; SmsEnvelope envelope = new SmsEnvelope(); envelope.messageType = SmsEnvelope.MESSAGE_TYPE_POINT_TO_POINT; @@ -1030,4 +1036,61 @@ public class SmsMessage extends SmsMessageBase { public ArrayList<CdmaSmsCbProgramData> getSmsCbProgramData() { return mBearerData.serviceCategoryProgramData; } + + /** + * CT WDP header contains WDP Msg Identifier and WDP Userdata + */ + protected boolean processCdmaCTWdpHeader(SmsMessage sms) { + int subparamId = 0; + int subParamLen = 0; + int msgID = 0; + boolean decodeSuccess = false; + try { + BitwiseInputStream inStream = new BitwiseInputStream(sms.getUserData()); + + /* Decode WDP Messsage Identifier */ + subparamId = inStream.read(8); + if (subparamId != 0) { + Rlog.e(LOG_TAG, "Invalid WDP SubparameterId"); + return false; + } + subParamLen = inStream.read(8); + if (subParamLen != 3) { + Rlog.e(LOG_TAG, "Invalid WDP subparameter length"); + return false; + } + sms.mBearerData.messageType = inStream.read(4); + msgID = inStream.read(8) << 8; + msgID |= inStream.read(8); + sms.mBearerData.hasUserDataHeader = (inStream.read(1) == 1); + if (sms.mBearerData.hasUserDataHeader) { + Rlog.e(LOG_TAG, "Invalid WDP UserData header value"); + return false; + } + inStream.skip(3); + sms.mBearerData.messageId = msgID; + sms.mMessageRef = msgID; + + /* Decode WDP User Data */ + subparamId = inStream.read(8); + subParamLen = inStream.read(8) * 8; + sms.mBearerData.userData.msgEncoding = inStream.read(5); + int consumedBits = 5; + if (sms.mBearerData.userData.msgEncoding != 0) { + Rlog.e(LOG_TAG, "Invalid WDP encoding"); + return false; + } + sms.mBearerData.userData.numFields = inStream.read(8); + consumedBits += 8; + int remainingBits = subParamLen - consumedBits; + int dataBits = sms.mBearerData.userData.numFields * 8; + dataBits = dataBits < remainingBits ? dataBits : remainingBits; + sms.mBearerData.userData.payload = inStream.readByteArray(dataBits); + sms.mUserData = sms.mBearerData.userData.payload; + decodeSuccess = true; + } catch (BitwiseInputStream.AccessException ex) { + Rlog.e(LOG_TAG, "CT WDP Header decode failed: " + ex); + } + return decodeSuccess; + } } diff --git a/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java b/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java index 4f5bfa919135..8d0f5b853ea2 100644 --- a/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java +++ b/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java @@ -71,9 +71,6 @@ public class SmsMessage extends SmsMessageBase { // e.g. 23.040 9.2.2.1 private boolean mReplyPathPresent = false; - /** The address of the receiver. */ - private GsmSmsAddress mRecipientAddress; - /** * TP-Status - status of a previously submitted SMS. * This field applies to SMS-STATUS-REPORT messages. 0 indicates success; diff --git a/telephony/java/com/android/internal/telephony/uicc/IccUtils.java b/telephony/java/com/android/internal/telephony/uicc/IccUtils.java index 6b3df94063bf..48324d5d83f0 100644 --- a/telephony/java/com/android/internal/telephony/uicc/IccUtils.java +++ b/telephony/java/com/android/internal/telephony/uicc/IccUtils.java @@ -22,9 +22,11 @@ import android.graphics.Bitmap; import android.graphics.Color; import android.telephony.Rlog; +import com.android.internal.telephony.EncodeException; import com.android.internal.telephony.GsmAlphabet; import java.io.UnsupportedEncodingException; +import java.nio.charset.Charset; /** * Various methods, useful for dealing with SIM data. @@ -883,4 +885,30 @@ public class IccUtils { } return 0; } + + static byte[] + stringToAdnStringField(String alphaTag) { + boolean isUcs2 = false; + try { + for(int i = 0; i < alphaTag.length(); i++) { + GsmAlphabet.countGsmSeptets(alphaTag.charAt(i), true); + } + } catch (EncodeException e) { + isUcs2 = true; + } + return stringToAdnStringField(alphaTag, isUcs2); + } + + static byte[] + stringToAdnStringField(String alphaTag, boolean isUcs2) { + if (!isUcs2) { + return GsmAlphabet.stringToGsm8BitPacked(alphaTag); + } + byte[] alphaTagBytes = alphaTag.getBytes(Charset.forName("UTF-16BE")); + byte[] ret = new byte[1 + alphaTagBytes.length]; + ret[0] = (byte)0x80; + System.arraycopy(alphaTagBytes, 0, ret, 1, alphaTagBytes.length); + + return ret; + } } diff --git a/wifi/java/android/net/wifi/ISoftApCallback.aidl b/wifi/java/android/net/wifi/ISoftApCallback.aidl index b8d2971e74bb..200ae18de3c3 100644 --- a/wifi/java/android/net/wifi/ISoftApCallback.aidl +++ b/wifi/java/android/net/wifi/ISoftApCallback.aidl @@ -41,4 +41,20 @@ oneway interface ISoftApCallback * @param numClients number of connected clients */ void onNumClientsChanged(int numClients); + + /** + * Service to manager callback providing Macaddress of connected stations. + * + * @param Macaddr Mac Address of connected clients + * @param numClients number of connected clients + */ + void onStaConnected(String Macaddr, int numClients); + + /** + * Service to manager callback providing Macaddress of disconnected stations. + * + * @param Macaddr Mac Address of disconnected clients + * @param numClients number of connected clients + */ + void onStaDisconnected(String Macaddr, int numClients); } diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl index 46c419130233..cb265fd46722 100644 --- a/wifi/java/android/net/wifi/IWifiManager.aidl +++ b/wifi/java/android/net/wifi/IWifiManager.aidl @@ -33,6 +33,7 @@ import android.net.wifi.ScanResult; import android.net.wifi.WifiActivityEnergyInfo; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiInfo; +import android.net.wifi.WifiDppConfig; import android.net.wifi.WifiNetworkSuggestion; import android.os.Messenger; @@ -190,6 +191,34 @@ interface IWifiManager void unregisterTrafficStateCallback(int callbackIdentifier); + String getCapabilities(String capaType); + + int dppAddBootstrapQrCode(String uri); + + int dppBootstrapGenerate(in WifiDppConfig config); + + String dppGetUri(int bootstrap_id); + + int dppBootstrapRemove(int bootstrap_id); + + int dppListen(String frequency, int dpp_role, boolean qr_mutual, boolean netrole_ap); + + void dppStopListen(); + + int dppConfiguratorAdd(String curve, String key, int expiry); + + int dppConfiguratorRemove(int config_id); + + int dppStartAuth(in WifiDppConfig config); + + String dppConfiguratorGetKey(int id); + + boolean isExtendingWifi(); + + boolean isWifiCoverageExtendFeatureEnabled(); + + void enableWifiCoverageExtendFeature(boolean enable); + void registerNetworkRequestMatchCallback(in IBinder binder, in INetworkRequestMatchCallback callback, int callbackIdentifier); void unregisterNetworkRequestMatchCallback(int callbackIdentifier); diff --git a/wifi/java/android/net/wifi/ScanResult.java b/wifi/java/android/net/wifi/ScanResult.java index 9b9247dba17c..fad7f710b23f 100644 --- a/wifi/java/android/net/wifi/ScanResult.java +++ b/wifi/java/android/net/wifi/ScanResult.java @@ -138,7 +138,7 @@ public class ScanResult implements Parcelable { * Used for Hotspot 2.0. */ public static final int KEY_MGMT_OSEN = 7; - /** + /** * @hide * Security key management scheme: SAE. */ diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java index d2d711f10944..dd82b715e9a5 100644 --- a/wifi/java/android/net/wifi/WifiConfiguration.java +++ b/wifi/java/android/net/wifi/WifiConfiguration.java @@ -90,6 +90,9 @@ public class WifiConfiguration implements Parcelable { /** {@hide} */ private static final int MAXIMUM_RANDOM_MAC_GENERATION_RETRY = 3; + /** {@hide} */ + public static final String shareThisApVarName = "share_this_ap"; + /** * Recognized key management schemes. */ @@ -157,11 +160,29 @@ public class WifiConfiguration implements Parcelable { */ public static final int WPA_EAP_SHA256 = 12; + /** + * IEEE 802.11ai FILS SK with SHA256 + * @hide + */ + public static final int FILS_SHA256 = 13; + /** + * IEEE 802.11ai FILS SK with SHA384: + * @hide + */ + public static final int FILS_SHA384 = 14; + /** + * Device Provisioning Protocol + * @hide + */ + public static final int DPP = 15; + public static final String varName = "key_mgmt"; public static final String[] strings = { "NONE", "WPA_PSK", "WPA_EAP", "IEEE8021X", "WPA2_PSK", "OSEN", "FT_PSK", "FT_EAP", - "SAE", "OWE", "SUITE_B_192", "WPA_PSK_SHA256", "WPA_EAP_SHA256" }; + "SAE", "OWE", "SUITE_B_192", "FILS_SHA256", "FILS_SHA384", + "DPP", "WPA_PSK_SHA256", "WPA_EAP_SHA256", + }; } /** @@ -385,6 +406,12 @@ public class WifiConfiguration implements Parcelable { public static final int AP_BAND_5GHZ = 1; /** + * 2GHz + 5GHz Dual band. + * @hide + */ + public static final int AP_BAND_DUAL = 2; + + /** * Device is allowed to choose the optimal band (2Ghz or 5Ghz) based on device capability, * operating country code and current radio conditions. * @hide @@ -463,6 +490,12 @@ public class WifiConfiguration implements Parcelable { public boolean requirePMF; /** + * @hide + * This configuration is used in AP to extend the coverage. + */ + public boolean shareThisAp; + + /** * Update identifier, for Passpoint network. * @hide */ @@ -977,6 +1010,29 @@ public class WifiConfiguration implements Parcelable { } mRandomizedMacAddress = mac; } + /** + * @hide + * DPP Connector (signedConnector as string). + */ + public String dppConnector; + + /** + * @hide + * DPP net Access Key (own private key). + */ + public String dppNetAccessKey; + + /** + * @hide + * DPP net Access Key expiry in UNIX time stamp. 0 indicates no expiration. + */ + public int dppNetAccessKeyExpiry; + + /** + * @hide + * DPP C-Sign key (Configurator public key). + */ + public String dppCsign; /** @hide * Boost given to RSSI on a home network for the purpose of calculating the score @@ -1651,6 +1707,7 @@ public class WifiConfiguration implements Parcelable { roamingConsortiumIds = new long[0]; priority = 0; hiddenSSID = false; + shareThisAp = false; allowedKeyManagement = new BitSet(); allowedProtocols = new BitSet(); allowedAuthAlgorithms = new BitSet(); @@ -1678,6 +1735,10 @@ public class WifiConfiguration implements Parcelable { shared = true; dtimInterval = 0; mRandomizedMacAddress = MacAddress.fromString(WifiInfo.DEFAULT_MAC_ADDRESS); + dppConnector = null; + dppNetAccessKey = null; + dppNetAccessKeyExpiry = -1; + dppCsign = null; } /** @@ -1879,6 +1940,17 @@ public class WifiConfiguration implements Parcelable { sbuf.append("\nEnterprise config:\n"); sbuf.append(enterpriseConfig); + sbuf.append("\nDPP config:\n"); + if (this.dppConnector != null) { + sbuf.append(" Dpp Connector: *\n"); + } + if (this.dppNetAccessKey != null) { + sbuf.append(" Dpp NetAccessKey: *\n"); + } + if (this.dppCsign != null) { + sbuf.append(" Dpp Csign: *\n"); + } + sbuf.append("IP config:\n"); sbuf.append(mIpConfiguration.toString()); @@ -1921,6 +1993,9 @@ public class WifiConfiguration implements Parcelable { } sbuf.append("recentFailure: ").append("Association Rejection code: ") .append(recentFailure.getAssociationStatus()).append("\n"); + + sbuf.append("ShareThisAp: ").append(this.shareThisAp); + sbuf.append('\n'); return sbuf.toString(); } @@ -2039,6 +2114,8 @@ public class WifiConfiguration implements Parcelable { return KeyMgmt.WPA_EAP; } else if (allowedKeyManagement.get(KeyMgmt.IEEE8021X)) { return KeyMgmt.IEEE8021X; + } else if (allowedKeyManagement.get(KeyMgmt.DPP)) { + return KeyMgmt.DPP; } else if (allowedKeyManagement.get(KeyMgmt.SAE)) { return KeyMgmt.SAE; } else if (allowedKeyManagement.get(KeyMgmt.OWE)) { @@ -2076,6 +2153,8 @@ public class WifiConfiguration implements Parcelable { key = SSID + KeyMgmt.strings[KeyMgmt.WPA_EAP]; } else if (wepKeys[0] != null) { key = SSID + "WEP"; + } else if (allowedKeyManagement.get(KeyMgmt.DPP)) { + key = SSID + KeyMgmt.strings[KeyMgmt.DPP]; } else if (allowedKeyManagement.get(KeyMgmt.OWE)) { key = SSID + KeyMgmt.strings[KeyMgmt.OWE]; } else if (allowedKeyManagement.get(KeyMgmt.SAE)) { @@ -2228,6 +2307,7 @@ public class WifiConfiguration implements Parcelable { SSID = source.SSID; BSSID = source.BSSID; FQDN = source.FQDN; + shareThisAp = source.shareThisAp; roamingConsortiumIds = source.roamingConsortiumIds.clone(); providerFriendlyName = source.providerFriendlyName; isHomeProviderNetwork = source.isHomeProviderNetwork; @@ -2295,6 +2375,11 @@ public class WifiConfiguration implements Parcelable { shared = source.shared; recentFailure.setAssociationStatus(source.recentFailure.getAssociationStatus()); mRandomizedMacAddress = source.mRandomizedMacAddress; + dppConnector = source.dppConnector; + dppNetAccessKey = source.dppNetAccessKey; + dppNetAccessKeyExpiry = source.dppNetAccessKeyExpiry; + dppCsign = source.dppCsign; + macRandomizationSetting = source.macRandomizationSetting; requirePMF = source.requirePMF; updateIdentifier = source.updateIdentifier; @@ -2309,6 +2394,7 @@ public class WifiConfiguration implements Parcelable { mNetworkSelectionStatus.writeToParcel(dest); dest.writeString(SSID); dest.writeString(BSSID); + dest.writeInt(shareThisAp ? 1 : 0); dest.writeInt(apBand); dest.writeInt(apChannel); dest.writeString(FQDN); @@ -2365,6 +2451,10 @@ public class WifiConfiguration implements Parcelable { dest.writeString(mPasspointManagementObjectTree); dest.writeInt(recentFailure.getAssociationStatus()); dest.writeParcelable(mRandomizedMacAddress, flags); + dest.writeString(dppConnector); + dest.writeString(dppNetAccessKey); + dest.writeInt(dppNetAccessKeyExpiry); + dest.writeString(dppCsign); dest.writeInt(macRandomizationSetting); dest.writeInt(osu ? 1 : 0); } @@ -2380,6 +2470,7 @@ public class WifiConfiguration implements Parcelable { config.mNetworkSelectionStatus.readFromParcel(in); config.SSID = in.readString(); config.BSSID = in.readString(); + config.shareThisAp = in.readInt() != 0; config.apBand = in.readInt(); config.apChannel = in.readInt(); config.FQDN = in.readString(); @@ -2436,6 +2527,10 @@ public class WifiConfiguration implements Parcelable { config.mPasspointManagementObjectTree = in.readString(); config.recentFailure.setAssociationStatus(in.readInt()); config.mRandomizedMacAddress = in.readParcelable(null); + config.dppConnector = in.readString(); + config.dppNetAccessKey = in.readString(); + config.dppNetAccessKeyExpiry = in.readInt(); + config.dppCsign = in.readString(); config.macRandomizationSetting = in.readInt(); config.osu = in.readInt() != 0; return config; diff --git a/wifi/java/android/net/wifi/WifiDppConfig.aidl b/wifi/java/android/net/wifi/WifiDppConfig.aidl new file mode 100644 index 000000000000..ac42fd9ac00e --- /dev/null +++ b/wifi/java/android/net/wifi/WifiDppConfig.aidl @@ -0,0 +1,20 @@ +/** + * Copyright (c) 2018, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.wifi; + +parcelable WifiDppConfig; + diff --git a/wifi/java/android/net/wifi/WifiDppConfig.java b/wifi/java/android/net/wifi/WifiDppConfig.java new file mode 100644 index 000000000000..e41adcff7cfc --- /dev/null +++ b/wifi/java/android/net/wifi/WifiDppConfig.java @@ -0,0 +1,216 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.wifi; +import android.os.Parcel; +import android.os.Parcelable; + +/** DPP configuration class + * @hide + */ +public class WifiDppConfig implements Parcelable { + private static final String TAG = "WifiDppConfig"; + public static final int DPP_INVALID_CONFIG_ID = -1; + public static final int DPP_ROLE_CONFIGURATOR = 0; + public static final int DPP_ROLE_ENROLLEE = 1; + public static final int DPP_TYPE_QR_CODE = 0; + public static final int DPP_TYPE_NAN_BOOTSTRAP = 1; + public int peer_bootstrap_id; + public int own_bootstrap_id; + public int dpp_role; + public String ssid; + public String passphrase; + public int isAp; + public int isDpp; + public int conf_id; + public int bootstrap_type; + public String chan_list; + public String mac_addr; + public String info; + public String curve; + public int expiry; + public String key; + + private DppResult mEventResult = new DppResult(); + + public WifiDppConfig() { + peer_bootstrap_id = DPP_INVALID_CONFIG_ID; + own_bootstrap_id = DPP_INVALID_CONFIG_ID; + dpp_role = DPP_INVALID_CONFIG_ID; + isAp = DPP_INVALID_CONFIG_ID; + isDpp = DPP_INVALID_CONFIG_ID; + conf_id = DPP_INVALID_CONFIG_ID; + bootstrap_type = DPP_INVALID_CONFIG_ID; + expiry = 0; + ssid = null; + passphrase = null; + chan_list = null; + mac_addr = null; + info = null; + curve = null; + key = null; + } + + public DppResult getDppResult() { + return mEventResult; + } + + public void setDppResult(DppResult result) { + mEventResult = result; + } + + public void writeToParcel(Parcel dest) { + } + + public void readFromParcel(Parcel in) { + } + + /** Implement the Parcelable interface {@hide} */ + public int describeContents() { + return 0; + } + /** Implement the Parcelable interface {@hide} */ + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(peer_bootstrap_id); + dest.writeInt(own_bootstrap_id); + dest.writeInt(dpp_role); + dest.writeString(ssid); + dest.writeString(passphrase); + dest.writeInt(isAp); + dest.writeInt(isDpp); + dest.writeInt(conf_id); + dest.writeInt(bootstrap_type); + dest.writeString(chan_list); + dest.writeString(mac_addr); + dest.writeString(info); + dest.writeString(curve); + dest.writeInt(expiry); + dest.writeString(key); + mEventResult.writeToParcel(dest); + } + + /** Implement the Parcelable interface {@hide} */ + public static final Creator<WifiDppConfig> CREATOR = + new Creator<WifiDppConfig>() { + public WifiDppConfig createFromParcel(Parcel in) { + WifiDppConfig config = new WifiDppConfig(); + config.peer_bootstrap_id = in.readInt(); + config.own_bootstrap_id = in.readInt(); + config.dpp_role = in.readInt(); + config.ssid = in.readString(); + config.passphrase = in.readString(); + config.isAp = in.readInt(); + config.isDpp = in.readInt(); + config.conf_id = in.readInt(); + config.bootstrap_type = in.readInt(); + config.chan_list = in.readString(); + config.mac_addr = in.readString(); + config.info = in.readString(); + config.curve = in.readString(); + config.expiry = in.readInt(); + config.key = in.readString(); + config.mEventResult.readFromParcel(in); + return config; + } + public WifiDppConfig[] newArray(int size) { + return new WifiDppConfig[size]; + } + }; + /** + * Stores supplicant state change information passed from WifiMonitor to + * a state machine. WifiStateMachine, SupplicantStateTracker and WpsStateMachine + * are example state machines that handle it. + * @hide + */ + public static class DppResult { + + public boolean initiator; + public int netID; + public byte capab; + public byte authMissingParam; + public byte configEventType; + public String iBootstrapData; + public String ssid; + public String connector; + public String cSignKey; + public String netAccessKey; + public int netAccessKeyExpiry; + public String passphrase; + public String psk; + + public static final int DPP_EVENT_AUTH_SUCCESS = 0; + public static final int DPP_EVENT_NOT_COMPATIBLE = 1; + public static final int DPP_EVENT_RESPONSE_PENDING = 2; + public static final int DPP_EVENT_SCAN_PEER_QRCODE = 3; + public static final int DPP_EVENT_CONF = 4; + public static final int DPP_EVENT_MISSING_AUTH = 5; + public static final int DPP_EVENT_NETWORK_ID = 6; + + + public static final int DPP_CONF_EVENT_TYPE_FAILED = 0; + public static final int DPP_CONF_EVENT_TYPE_SENT = 1; + public static final int DPP_CONF_EVENT_TYPE_RECEIVED = 2; + + public DppResult() { + this.initiator = false; + this.netID = -1; + this.capab = 0; + this.authMissingParam = 0; + this.configEventType = 0; + this.iBootstrapData = null; + this.ssid = null; + this.connector = null; + this.cSignKey = null; + this.netAccessKey = null; + this.netAccessKeyExpiry = 0; + this.passphrase = null; + this.psk = null; + } + + public void writeToParcel(Parcel dest) { + dest.writeInt(initiator ? 1 : 0); + dest.writeInt(netID); + dest.writeByte(capab); + dest.writeByte(authMissingParam); + dest.writeByte(configEventType); + dest.writeString(iBootstrapData); + dest.writeString(ssid); + dest.writeString(connector); + dest.writeString(cSignKey); + dest.writeString(netAccessKey); + dest.writeInt(netAccessKeyExpiry); + dest.writeString(passphrase); + dest.writeString(psk); + } + + public void readFromParcel(Parcel in) { + this.initiator = (in.readInt() > 0) ? true : false; + this.netID = in.readInt(); + this.capab = in.readByte(); + this.authMissingParam = in.readByte(); + this.configEventType = in.readByte(); + this.iBootstrapData = in.readString(); + this.ssid = in.readString(); + this.connector = in.readString(); + this.cSignKey = in.readString(); + this.netAccessKey = in.readString(); + this.netAccessKeyExpiry = in.readInt(); + this.passphrase = in.readString(); + this.psk = in.readString(); + } + } +} diff --git a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java index 17847eaa0ca5..360ffe739bc8 100644 --- a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java +++ b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java @@ -65,6 +65,11 @@ public class WifiEnterpriseConfig implements Parcelable { public static final String DOM_SUFFIX_MATCH_KEY = "domain_suffix_match"; /** @hide */ public static final String OPP_KEY_CACHING = "proactive_key_caching"; + /** @hide */ + public static final String EAP_ERP = "eap_erp"; + /** @hide */ + public static final String KEY_SIMNUM = "sim_num"; + /** * String representing the keystore OpenSSL ENGINE's ID. * @hide @@ -138,7 +143,8 @@ public class WifiEnterpriseConfig implements Parcelable { /** * Fields that have unquoted values in {@link #mFields}. */ - private static final List<String> UNQUOTED_KEYS = Arrays.asList(ENGINE_KEY, OPP_KEY_CACHING); + private static final List<String> UNQUOTED_KEYS = Arrays.asList(ENGINE_KEY, OPP_KEY_CACHING, + EAP_ERP); @UnsupportedAppUsage private HashMap<String, String> mFields = new HashMap<String, String>(); @@ -444,6 +450,15 @@ public class WifiEnterpriseConfig implements Parcelable { } } + /** @hide */ + public void setSimNum(int SIMNum) { + setFieldValue(KEY_SIMNUM, Integer.toString(SIMNum)); + } + + /** @hide */ + public String getSimNum() { + return getFieldValue(KEY_SIMNUM); + } /** * Get the eap method. * @return eap method configured diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java index 8c00cebf6c59..c46e322052a6 100644 --- a/wifi/java/android/net/wifi/WifiManager.java +++ b/wifi/java/android/net/wifi/WifiManager.java @@ -216,6 +216,19 @@ public class WifiManager { public static final String EXTRA_SCAN_AVAILABLE = "scan_enabled"; /** + * + * + * @hide + **/ + public static final String WIFI_DATA_STALL = "com.qualcomm.qti.net.wifi.WIFI_DATA_STALL"; + + /** + * + * see data stall reason code + * @hide + **/ + public static final String EXTRA_WIFI_DATA_STALL_REASON = "data_stall_reasoncode"; + /** * Broadcast intent action indicating that the credential of a Wi-Fi network * has been changed. One extra provides the ssid of the network. Another * extra provides the event type, whether the credential is saved or forgot. @@ -900,6 +913,26 @@ public class WifiManager { public static final String NETWORK_IDS_CHANGED_ACTION = "android.net.wifi.NETWORK_IDS_CHANGED"; /** + * Broadcast intent action indicating DPP Event arrival notificaiton. + * @see #EXTRA_DPP_DATA. + * @hide + */ + public static final String DPP_EVENT_ACTION = "com.qualcomm.qti.net.wifi.DPP_EVENT"; + + /** + * This shall point to DppResult Type. + * @hide + */ + public static final String EXTRA_DPP_EVENT_TYPE = "dppEventType"; + + /** + * This shall point to WifiDppConfig object. Retrieve with + * {@link android.content.Intent#getParcelableExtra(String)}. + * @hide + */ + public static final String EXTRA_DPP_EVENT_DATA = "dppEventData"; + + /** * Activity Action: Show a system activity that allows the user to enable * scans to be available even with Wi-Fi turned off. * @@ -945,6 +978,34 @@ public class WifiManager { public static final String ACTION_REQUEST_DISABLE = "android.net.wifi.action.REQUEST_DISABLE"; /** + * Broadcast intent action indicating that WifiCountryCode was updated with new + * country code. + * + * @see #EXTRA_COUNTRY_CODE + * + * @hide + */ + @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) + public static final String WIFI_COUNTRY_CODE_CHANGED_ACTION = + "android.net.wifi.COUNTRY_CODE_CHANGED"; + + /** + * The lookup key for a string that indicates the 2 char new country code + * + * @hide + */ + public static final String EXTRA_COUNTRY_CODE = "country_code"; + + /** + * Broadcast intent action indicating that the user initiated Wifi OFF + * or APM ON and Wifi disconnection is in progress + * Actual Wifi disconnection happens after mDisconnectDelayDuration seconds. + * @hide + */ + public static final String ACTION_WIFI_DISCONNECT_IN_PROGRESS = + "com.qualcomm.qti.net.wifi.WIFI_DISCONNECT_IN_PROGRESS"; + + /** * Directed broadcast intent action indicating that the device has connected to one of the * network suggestions provided by the app. This will be sent post connection to a network * which was created with {@link WifiNetworkConfigBuilder#setIsAppInteractionRequired()} flag @@ -1378,6 +1439,52 @@ public class WifiManager { return addOrUpdateNetwork(config); } + + /** + * Check the WifiSharing mode. + * + * @return true if Current Sta network connected with extending coverage + * option. false if it is not. + * + * @hide no intent to publish + */ + public boolean isExtendingWifi() { + try { + return mService.isExtendingWifi(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Check Wifi coverage extend feature enabled or not. + * + * @return true if Wifi extend feature is enabled. + * + * @hide no intent to publish + */ + public boolean isWifiCoverageExtendFeatureEnabled() { + try { + return mService.isWifiCoverageExtendFeatureEnabled(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Enable/disable Wifi coverage extend feature. + * + * @hide no intent to publish + */ + public void enableWifiCoverageExtendFeature(boolean enable) { + try { + mService.enableWifiCoverageExtendFeature(enable); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** * Internal method for doing the RPC that creates a new network description * or updates an existing one. @@ -2293,6 +2400,7 @@ public class WifiManager { * in order to get valid results. */ public List<ScanResult> getScanResults() { + android.util.SeempLog.record(55); try { return mService.getScanResults(mContext.getOpPackageName()); } catch (RemoteException e) { @@ -3068,6 +3176,22 @@ public class WifiManager { * @param numClients number of connected clients */ public abstract void onNumClientsChanged(int numClients); + + /** + * Called when Stations connected to soft AP. + * + * @param Macaddr Mac Address of connected Stations to soft AP + * @param numClients number of connected clients + */ + public abstract void onStaConnected(String Macaddr, int numClients); + + /** + * Called when Stations disconnected to soft AP. + * + * @param Macaddr Mac Address of Disconnected Stations to soft AP + * @param numClients number of connected clients + */ + public abstract void onStaDisconnected(String Macaddr, int numClients); } /** @@ -3104,6 +3228,22 @@ public class WifiManager { mCallback.onNumClientsChanged(numClients); }); } + + @Override + public void onStaConnected(String Macaddr, int numClients) throws RemoteException { + Log.v(TAG, "SoftApCallbackProxy: [" + numClients + "]onStaConnected Macaddr =" + Macaddr); + mHandler.post(() -> { + mCallback.onStaConnected(Macaddr, numClients); + }); + } + + @Override + public void onStaDisconnected(String Macaddr, int numClients) throws RemoteException { + Log.v(TAG, "SoftApCallbackProxy: [" + numClients + "]onStaDisconnected Macaddr =" + Macaddr); + mHandler.post(() -> { + mCallback.onStaDisconnected(Macaddr, numClients); + }); + } } /** @@ -4377,7 +4517,6 @@ public class WifiManager { mHandler = new Handler(looper); mCallback = callback; } - @Override public void onProvisioningStatus(int status) { mHandler.post(() -> { @@ -4514,6 +4653,191 @@ public class WifiManager { } /** + * Get driver Capabilities. + * + * @param capaType ASCII string, capability type ex: key_mgmt. + * @return String of capabilities from driver for type capaParameter. + * {@hide} + */ + public String getCapabilities(String capaType) { + try { + return mService.getCapabilities(capaType); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + + /** + * Add the DPP bootstrap info obtained from QR code. + * + * @param uri:The URI obtained from the QR code reader. + * + * @return: Handle to strored info else -1 on failure + * @hide + */ + public int dppAddBootstrapQrCode(String uri) { + try { + return mService.dppAddBootstrapQrCode(uri); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + + /** + * Generate bootstrap URI based on the passed arguments + * + * @param config – bootstrap generate config, mandatory parameters + * are: type, frequency, mac_addr, curve, key. + * + * @return: Handle to strored URI info else -1 on failure + * @hide + */ + public int dppBootstrapGenerate(WifiDppConfig config) { + try { + return mService.dppBootstrapGenerate(config); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Get bootstrap URI based on bootstrap ID + * + * @param bootstrap_id: Stored bootstrap ID + * + * @return: URI string else -1 on failure + * @hide + */ + public String dppGetUri(int bootstrap_id) { + try { + return mService.dppGetUri(bootstrap_id); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Remove bootstrap URI based on bootstrap ID. + * + * @param bootstrap_id: Stored bootstrap ID. 0 to remove all. + * + * @return: 0 – Success or -1 on failure + * @hide + */ + public int dppBootstrapRemove(int bootstrap_id) { + try { + return mService.dppBootstrapRemove(bootstrap_id); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * start listen on the channel specified waiting to receive + * the DPP Authentication request. + * + * @param frequency: DPP listen frequency + * @param dpp_role: Configurator/Enrollee role + * @param qr_mutual: Mutual authentication required + * @param netrole_ap: network role + * + * @return: Returns 0 if a DPP-listen work is successfully + * queued and -1 on failure. + * @hide + */ + public int dppListen(String frequency, int dpp_role, boolean qr_mutual, + boolean netrole_ap) { + try { + return mService.dppListen(frequency, dpp_role, qr_mutual, netrole_ap); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * stop ongoing dpp listen. + * + * @hide + */ + public void dppStopListen() { + try { + mService.dppStopListen(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Adds the DPP configurator + * + * @param curve curve used for dpp encryption + * @param key private key + * @param expiry timeout in seconds + * + * @return: Identifier of the added configurator or -1 on failure + * @hide + */ + public int dppConfiguratorAdd(String curve, String key, int expiry) { + try { + return mService.dppConfiguratorAdd(curve, key, expiry); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Remove the added configurator through dppConfiguratorAdd. + * + * @param config_id: DPP Configurator ID. 0 to remove all. + * + * @return: Handle to strored info else -1 on failure + * @hide + */ + public int dppConfiguratorRemove(int config_id) { + try { + return mService.dppConfiguratorRemove(config_id); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Start DPP authentication and provisioning with the specified peer + * + * @param config – dpp auth init config mandatory parameters + * are: peer_bootstrap_id, own_bootstrap_id, dpp_role, + * ssid, passphrase, isDpp, conf_id, expiry. + * + * @return: 0 if DPP auth request was transmitted and -1 on failure + * @hide + */ + public int dppStartAuth(WifiDppConfig config) { + try { + return mService.dppStartAuth(config); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Retrieve Private key to be used for configurator + * + * @param id: id of configurator + * + * @return: KEY string else -1 on failure + * @hide + */ + public String dppConfiguratorGetKey(int id) { + try { + return mService.dppConfiguratorGetKey(id); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** * @return true if this device supports WPA3-Personal SAE */ public boolean isWpa3SaeSupported() { diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pDevice.java b/wifi/java/android/net/wifi/p2p/WifiP2pDevice.java index 22dc2ed32083..940e9e0c3e7e 100644 --- a/wifi/java/android/net/wifi/p2p/WifiP2pDevice.java +++ b/wifi/java/android/net/wifi/p2p/WifiP2pDevice.java @@ -142,7 +142,8 @@ public class WifiP2pDevice implements Parcelable { "config_methods=(0x[0-9a-fA-F]+) " + "dev_capab=(0x[0-9a-fA-F]+) " + "group_capab=(0x[0-9a-fA-F]+)" + - "( wfd_dev_info=0x([0-9a-fA-F]{12}))?" + "( wfd_dev_info=0x([0-9a-fA-F]{12}))?" + + "( wfd_r2_dev_info=0x([0-9a-fA-F]{4}))?" ); /** 2 token device address pattern @@ -229,6 +230,10 @@ public class WifiP2pDevice implements Parcelable { wfdInfo = new WifiP2pWfdInfo(parseHex(str.substring(0,4)), parseHex(str.substring(4,8)), parseHex(str.substring(8,12))); + if (match.group(11) != null) { + String r2str = match.group(12); + wfdInfo.setWfdR2Device(parseHex(r2str.substring(0,4))); + } } break; } diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java index 1bed914c7772..1f0b52a835e6 100644 --- a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java +++ b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java @@ -529,19 +529,26 @@ public class WifiP2pManager { public static final int SET_ONGOING_PEER_CONFIG_SUCCEEDED = BASE + 89; /** @hide */ - public static final int REQUEST_P2P_STATE = BASE + 90; + public static final int SET_WFDR2_INFO = BASE + 90; /** @hide */ - public static final int RESPONSE_P2P_STATE = BASE + 91; + public static final int SET_WFDR2_INFO_FAILED = BASE + 91; + /** @hide */ + public static final int SET_WFDR2_INFO_SUCCEEDED = BASE + 92; + + /** @hide */ + public static final int REQUEST_P2P_STATE = BASE + 93; + /** @hide */ + public static final int RESPONSE_P2P_STATE = BASE + 94; /** @hide */ - public static final int REQUEST_DISCOVERY_STATE = BASE + 92; + public static final int REQUEST_DISCOVERY_STATE = BASE + 95; /** @hide */ - public static final int RESPONSE_DISCOVERY_STATE = BASE + 93; + public static final int RESPONSE_DISCOVERY_STATE = BASE + 96; /** @hide */ - public static final int REQUEST_NETWORK_INFO = BASE + 94; + public static final int REQUEST_NETWORK_INFO = BASE + 97; /** @hide */ - public static final int RESPONSE_NETWORK_INFO = BASE + 95; + public static final int RESPONSE_NETWORK_INFO = BASE + 98; /** @hide */ public static final int UPDATE_CHANNEL_INFO = BASE + 96; @@ -885,6 +892,7 @@ public class WifiP2pManager { case SET_DEVICE_NAME_FAILED: case DELETE_PERSISTENT_GROUP_FAILED: case SET_WFD_INFO_FAILED: + case SET_WFDR2_INFO_FAILED: case START_WPS_FAILED: case START_LISTEN_FAILED: case STOP_LISTEN_FAILED: @@ -913,6 +921,7 @@ public class WifiP2pManager { case SET_DEVICE_NAME_SUCCEEDED: case DELETE_PERSISTENT_GROUP_SUCCEEDED: case SET_WFD_INFO_SUCCEEDED: + case SET_WFDR2_INFO_SUCCEEDED: case START_WPS_SUCCEEDED: case START_LISTEN_SUCCEEDED: case STOP_LISTEN_SUCCEEDED: @@ -1587,7 +1596,18 @@ public class WifiP2pManager { c.mAsyncChannel.sendMessage(SET_WFD_INFO, 0, c.putListener(listener), wfdInfo); } - + /** @hide */ + public void setWFDR2Info( + Channel c, WifiP2pWfdInfo wfdInfo, + ActionListener listener) { + checkChannel(c); + try { + mService.checkConfigureWifiDisplayPermission(); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + c.mAsyncChannel.sendMessage(SET_WFDR2_INFO, 0, c.putListener(listener), wfdInfo); + } /** * Delete a stored persistent group from the system settings. * diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pWfdInfo.java b/wifi/java/android/net/wifi/p2p/WifiP2pWfdInfo.java index f9ef08fa6dc1..c86d4466fb3f 100644 --- a/wifi/java/android/net/wifi/p2p/WifiP2pWfdInfo.java +++ b/wifi/java/android/net/wifi/p2p/WifiP2pWfdInfo.java @@ -35,6 +35,8 @@ public class WifiP2pWfdInfo implements Parcelable { private int mDeviceInfo; + private int mR2DeviceInfo; + public static final int WFD_SOURCE = 0; public static final int PRIMARY_SINK = 1; public static final int SECONDARY_SINK = 2; @@ -65,6 +67,7 @@ public class WifiP2pWfdInfo implements Parcelable { mDeviceInfo = devInfo; mCtrlPort = ctrlPort; mMaxThroughput = maxTput; + mR2DeviceInfo = -1; } @UnsupportedAppUsage @@ -72,11 +75,19 @@ public class WifiP2pWfdInfo implements Parcelable { return mWfdEnabled; } + public boolean isWfdR2Supported() { + return (mR2DeviceInfo<0?false:true); + } + @UnsupportedAppUsage public void setWfdEnabled(boolean enabled) { mWfdEnabled = enabled; } + public void setWfdR2Device(int r2DeviceInfo) { + mR2DeviceInfo = r2DeviceInfo; + } + @UnsupportedAppUsage public int getDeviceType() { return (mDeviceInfo & DEVICE_TYPE); @@ -153,12 +164,17 @@ public class WifiP2pWfdInfo implements Parcelable { Locale.US, "%04x%04x%04x", mDeviceInfo, mCtrlPort, mMaxThroughput); } + public String getR2DeviceInfoHex() { + return String.format( + Locale.US, "%04x%04x", 2, mR2DeviceInfo); + } public String toString() { StringBuffer sbuf = new StringBuffer(); sbuf.append("WFD enabled: ").append(mWfdEnabled); sbuf.append("WFD DeviceInfo: ").append(mDeviceInfo); sbuf.append("\n WFD CtrlPort: ").append(mCtrlPort); sbuf.append("\n WFD MaxThroughput: ").append(mMaxThroughput); + sbuf.append("\n WFD R2 DeviceInfo: ").append(mR2DeviceInfo); return sbuf.toString(); } @@ -175,6 +191,7 @@ public class WifiP2pWfdInfo implements Parcelable { mDeviceInfo = source.mDeviceInfo; mCtrlPort = source.mCtrlPort; mMaxThroughput = source.mMaxThroughput; + mR2DeviceInfo = source.mR2DeviceInfo; } } @@ -184,6 +201,7 @@ public class WifiP2pWfdInfo implements Parcelable { dest.writeInt(mDeviceInfo); dest.writeInt(mCtrlPort); dest.writeInt(mMaxThroughput); + dest.writeInt(mR2DeviceInfo); } public void readFromParcel(Parcel in) { @@ -191,6 +209,7 @@ public class WifiP2pWfdInfo implements Parcelable { mDeviceInfo = in.readInt(); mCtrlPort = in.readInt(); mMaxThroughput = in.readInt(); + mR2DeviceInfo = in.readInt(); } /** Implement the Parcelable interface */ |